summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2023-11-07 02:42:08 +0300
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2023-11-07 02:42:08 +0300
commitcdd5b5a9761fd66d17586e4f4ba6588c70e640ea (patch)
treeaba8409818be01f6af8683bf76594c790942d0bc /drivers
parent5c15c60e7be615f05a45cd905093a54b11f461bc (diff)
parent28d3fe32354701decc3e76d89712569c269b5e4f (diff)
downloadlinux-cdd5b5a9761fd66d17586e4f4ba6588c70e640ea.tar.xz
Merge branch 'next' into for-linus
Prepare input updates for 6.7 merge window.
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.h86
-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/accel/ivpu/ivpu_drv.h1
-rw-r--r--drivers/accel/ivpu/ivpu_gem.c8
-rw-r--r--drivers/accel/ivpu/ivpu_hw_mtl.c20
-rw-r--r--drivers/accel/qaic/qaic_control.c65
-rw-r--r--drivers/accel/qaic/qaic_data.c1
-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/acpi_ffh.c2
-rw-r--r--drivers/acpi/acpi_lpss.c10
-rw-r--r--drivers/acpi/acpi_pad.c1
-rw-r--r--drivers/acpi/acpi_platform.c31
-rw-r--r--drivers/acpi/apei/bert.c2
-rw-r--r--drivers/acpi/apei/ghes.c4
-rw-r--r--drivers/acpi/arm64/Makefile2
-rw-r--r--drivers/acpi/arm64/agdi.c2
-rw-r--r--drivers/acpi/arm64/apmt.c12
-rw-r--r--drivers/acpi/arm64/init.c13
-rw-r--r--drivers/acpi/arm64/init.h6
-rw-r--r--drivers/acpi/arm64/iort.c4
-rw-r--r--drivers/acpi/bus.c91
-rw-r--r--drivers/acpi/button.c164
-rw-r--r--drivers/acpi/device_sysfs.c2
-rw-r--r--drivers/acpi/ec.c41
-rw-r--r--drivers/acpi/internal.h4
-rw-r--r--drivers/acpi/nfit/nfit.h2
-rw-r--r--drivers/acpi/osl.c2
-rw-r--r--drivers/acpi/processor_core.c29
-rw-r--r--drivers/acpi/processor_idle.c4
-rw-r--r--drivers/acpi/resource.c48
-rw-r--r--drivers/acpi/riscv/Makefile2
-rw-r--r--drivers/acpi/riscv/rhct.c83
-rw-r--r--drivers/acpi/scan.c106
-rw-r--r--drivers/acpi/sleep.c2
-rw-r--r--drivers/acpi/tables.c10
-rw-r--r--drivers/acpi/thermal.c287
-rw-r--r--drivers/acpi/tiny-power-button.c49
-rw-r--r--drivers/acpi/video_detect.c45
-rw-r--r--drivers/acpi/x86/s2idle.c66
-rw-r--r--drivers/acpi/x86/utils.c26
-rw-r--r--drivers/android/binder.c16
-rw-r--r--drivers/android/binder_alloc.c6
-rw-r--r--drivers/android/binder_alloc.h1
-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.c394
-rw-r--r--drivers/ata/libata.h2
-rw-r--r--drivers/ata/pata_arasan_cf.c3
-rw-r--r--drivers/ata/pata_ixp4xx_cf.c2
-rw-r--r--drivers/ata/pata_ns87415.c2
-rw-r--r--drivers/ata/pata_octeon_cf.c33
-rw-r--r--drivers/ata/pata_of_platform.c2
-rw-r--r--drivers/ata/pata_parport/aten.c105
-rw-r--r--drivers/ata/pata_parport/bpck.c468
-rw-r--r--drivers/ata/pata_parport/bpck6.c70
-rw-r--r--drivers/ata/pata_parport/comm.c240
-rw-r--r--drivers/ata/pata_parport/dstr.c287
-rw-r--r--drivers/ata/pata_parport/epat.c323
-rw-r--r--drivers/ata/pata_parport/epia.c445
-rw-r--r--drivers/ata/pata_parport/fit2.c134
-rw-r--r--drivers/ata/pata_parport/fit3.c209
-rw-r--r--drivers/ata/pata_parport/friq.c294
-rw-r--r--drivers/ata/pata_parport/frpw.c324
-rw-r--r--drivers/ata/pata_parport/kbic.c317
-rw-r--r--drivers/ata/pata_parport/ktti.c87
-rw-r--r--drivers/ata/pata_parport/on20.c151
-rw-r--r--drivers/ata/pata_parport/on26.c416
-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.c4
-rw-r--r--drivers/auxdisplay/lcd2s.c2
-rw-r--r--drivers/base/cpu.c85
-rw-r--r--drivers/base/dd.c6
-rw-r--r--drivers/base/devres.c6
-rw-r--r--drivers/base/isa.c7
-rw-r--r--drivers/base/node.c15
-rw-r--r--drivers/base/power/domain.c15
-rw-r--r--drivers/base/power/power.h1
-rw-r--r--drivers/base/power/wakeirq.c61
-rw-r--r--drivers/base/power/wakeup.c5
-rw-r--r--drivers/base/property.c12
-rw-r--r--drivers/base/regmap/Makefile2
-rw-r--r--drivers/base/regmap/internal.h15
-rw-r--r--drivers/base/regmap/regcache-maple.c140
-rw-r--r--drivers/base/regmap/regcache-rbtree.c4
-rw-r--r--drivers/base/regmap/regcache.c15
-rw-r--r--drivers/base/regmap/regmap-debugfs.c11
-rw-r--r--drivers/base/regmap/regmap-i2c.c8
-rw-r--r--drivers/base/regmap/regmap-irq.c275
-rw-r--r--drivers/base/regmap/regmap-kunit.c456
-rw-r--r--drivers/base/regmap/regmap-mmio.c2
-rw-r--r--drivers/base/regmap/regmap-raw-ram.c133
-rw-r--r--drivers/base/regmap/regmap-spi-avmm.c2
-rw-r--r--drivers/base/regmap/regmap.c34
-rw-r--r--drivers/block/amiflop.c20
-rw-r--r--drivers/block/aoe/aoeblk.c8
-rw-r--r--drivers/block/aoe/aoechr.c30
-rw-r--r--drivers/block/ataflop.c43
-rw-r--r--drivers/block/brd.c91
-rw-r--r--drivers/block/drbd/drbd_bitmap.c4
-rw-r--r--drivers/block/drbd/drbd_main.c26
-rw-r--r--drivers/block/drbd/drbd_nl.c24
-rw-r--r--drivers/block/drbd/drbd_receiver.c1
-rw-r--r--drivers/block/floppy.c74
-rw-r--r--drivers/block/loop.c66
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c4
-rw-r--r--drivers/block/nbd.c15
-rw-r--r--drivers/block/null_blk/zoned.c16
-rw-r--r--drivers/block/pktcdvd.c560
-rw-r--r--drivers/block/rbd.c156
-rw-r--r--drivers/block/rnbd/Makefile6
-rw-r--r--drivers/block/rnbd/rnbd-clt-sysfs.c24
-rw-r--r--drivers/block/rnbd/rnbd-clt.c8
-rw-r--r--drivers/block/rnbd/rnbd-common.c23
-rw-r--r--drivers/block/rnbd/rnbd-proto.h31
-rw-r--r--drivers/block/rnbd/rnbd-srv-sysfs.c28
-rw-r--r--drivers/block/rnbd/rnbd-srv.c67
-rw-r--r--drivers/block/rnbd/rnbd-srv.h4
-rw-r--r--drivers/block/sunvdc.c2
-rw-r--r--drivers/block/swim.c26
-rw-r--r--drivers/block/swim3.c33
-rw-r--r--drivers/block/ublk_drv.c509
-rw-r--r--drivers/block/virtio_blk.c34
-rw-r--r--drivers/block/xen-blkback/xenbus.c4
-rw-r--r--drivers/block/xen-blkfront.c2
-rw-r--r--drivers/block/z2ram.c8
-rw-r--r--drivers/block/zram/zram_drv.c57
-rw-r--r--drivers/bluetooth/btqca.c2
-rw-r--r--drivers/bluetooth/btrtl.c18
-rw-r--r--drivers/bluetooth/btusb.c6
-rw-r--r--drivers/bluetooth/hci_bcm.c3
-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/intel-ixp4xx-eb.c2
-rw-r--r--drivers/bus/ti-sysc.c6
-rw-r--r--drivers/cdrom/cdrom.c42
-rw-r--r--drivers/cdrom/gdrom.c14
-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/random.c4
-rw-r--r--drivers/char/tpm/st33zp24/i2c.c2
-rw-r--r--drivers/char/tpm/tpm-chip.c76
-rw-r--r--drivers/char/tpm/tpm_crb.c49
-rw-r--r--drivers/char/tpm/tpm_i2c_atmel.c2
-rw-r--r--drivers/char/tpm/tpm_i2c_infineon.c2
-rw-r--r--drivers/char/tpm/tpm_i2c_nuvoton.c2
-rw-r--r--drivers/char/tpm/tpm_tis.c43
-rw-r--r--drivers/char/tpm/tpm_tis_core.c112
-rw-r--r--drivers/char/tpm/tpm_tis_core.h4
-rw-r--r--drivers/char/tpm/tpm_tis_i2c.c61
-rw-r--r--drivers/char/tpm/tpm_tis_i2c_cr50.c2
-rw-r--r--drivers/char/tpm/tpm_tis_spi_main.c8
-rw-r--r--drivers/char/tpm/tpm_vtpm_proxy.c30
-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/Kconfig4
-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-devres.c13
-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-rk808.c34
-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-imx1.c1
-rw-r--r--drivers/clk/imx/clk-imx27.c1
-rw-r--r--drivers/clk/imx/clk-imx31.c1
-rw-r--r--drivers/clk/imx/clk-imx35.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.c55
-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.c51
-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/Kconfig9
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/arm_arch_timer.c54
-rw-r--r--drivers/clocksource/hyperv_timer.c96
-rw-r--r--drivers/clocksource/ingenic-timer.c10
-rw-r--r--drivers/clocksource/timer-cadence-ttc.c19
-rw-r--r--drivers/clocksource/timer-imx-gpt.c25
-rw-r--r--drivers/clocksource/timer-loongson1-pwm.c236
-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/Kconfig5
-rw-r--r--drivers/cpufreq/Kconfig.x8617
-rw-r--r--drivers/cpufreq/amd-pstate.c141
-rw-r--r--drivers/cpufreq/armada-8k-cpufreq.c16
-rw-r--r--drivers/cpufreq/cpufreq-dt-platdev.c5
-rw-r--r--drivers/cpufreq/cpufreq.c3
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c30
-rw-r--r--drivers/cpufreq/intel_pstate.c60
-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.c60
-rw-r--r--drivers/cpufreq/sparc-us3-cpufreq.c60
-rw-r--r--drivers/cpufreq/tegra194-cpufreq.c6
-rw-r--r--drivers/cpufreq/ti-cpufreq.c1
-rw-r--r--drivers/cpuidle/cpuidle-psci-domain.c39
-rw-r--r--drivers/cpuidle/cpuidle.c8
-rw-r--r--drivers/cpuidle/dt_idle_genpd.c24
-rw-r--r--drivers/cpuidle/dt_idle_genpd.h7
-rw-r--r--drivers/cpuidle/poll_state.c4
-rw-r--r--drivers/crypto/Kconfig12
-rw-r--r--drivers/crypto/Makefile1
-rw-r--r--drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c2
-rw-r--r--drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c2
-rw-r--r--drivers/crypto/allwinner/sun4i-ss/sun4i-ss-hash.c2
-rw-r--r--drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h2
-rw-r--r--drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c2
-rw-r--r--drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c2
-rw-r--r--drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c2
-rw-r--r--drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c2
-rw-r--r--drivers/crypto/allwinner/sun8i-ce/sun8i-ce-trng.c2
-rw-r--r--drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c2
-rw-r--r--drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c2
-rw-r--r--drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c2
-rw-r--r--drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c2
-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.c53
-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.c14
-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/Kconfig15
-rw-r--r--drivers/cxl/acpi.c213
-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.c384
-rw-r--r--drivers/cxl/core/memdev.c522
-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.h245
-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/devfreq/exynos-bus.c1
-rw-r--r--drivers/devfreq/mtk-cci-devfreq.c3
-rw-r--r--drivers/dma-buf/dma-fence-unwrap.c26
-rw-r--r--drivers/dma-buf/dma-fence.c7
-rw-r--r--drivers/dma-buf/dma-resv.c15
-rw-r--r--drivers/dma-buf/sw_sync.c20
-rw-r--r--drivers/dma/Kconfig3
-rw-r--r--drivers/dma/dma-axi-dmac.c1
-rw-r--r--drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c1
-rw-r--r--drivers/dma/dw-edma/Makefile8
-rw-r--r--drivers/dma/dw-edma/dw-edma-core.c86
-rw-r--r--drivers/dma/dw-edma/dw-edma-core.h58
-rw-r--r--drivers/dma/dw-edma/dw-edma-pcie.c4
-rw-r--r--drivers/dma/dw-edma/dw-edma-v0-core.c85
-rw-r--r--drivers/dma/dw-edma/dw-edma-v0-core.h14
-rw-r--r--drivers/dma/dw-edma/dw-hdma-v0-core.c296
-rw-r--r--drivers/dma/dw-edma/dw-hdma-v0-core.h17
-rw-r--r--drivers/dma/dw-edma/dw-hdma-v0-debugfs.c170
-rw-r--r--drivers/dma/dw-edma/dw-hdma-v0-debugfs.h22
-rw-r--r--drivers/dma/dw-edma/dw-hdma-v0-regs.h129
-rw-r--r--drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c4
-rw-r--r--drivers/dma/idxd/device.c4
-rw-r--r--drivers/dma/ioat/dma.c12
-rw-r--r--drivers/dma/mcf-edma.c13
-rw-r--r--drivers/dma/owl-dma.c2
-rw-r--r--drivers/dma/pl330.c18
-rw-r--r--drivers/dma/plx_dma.c1
-rw-r--r--drivers/dma/qcom/Kconfig1
-rw-r--r--drivers/dma/qcom/bam_dma.c18
-rw-r--r--drivers/dma/qcom/hidma.c1
-rw-r--r--drivers/dma/sprd-dma.c1
-rw-r--r--drivers/dma/ste_dma40.c338
-rw-r--r--drivers/dma/ste_dma40.h110
-rw-r--r--drivers/dma/ste_dma40_ll.c3
-rw-r--r--drivers/dma/ti/k3-psil-j721s2.c11
-rw-r--r--drivers/dma/ti/k3-udma.c25
-rw-r--r--drivers/dma/xilinx/xdma.c6
-rw-r--r--drivers/edac/Kconfig11
-rw-r--r--drivers/edac/Makefile1
-rw-r--r--drivers/edac/amd64_edac.c398
-rw-r--r--drivers/edac/amd64_edac.h2
-rw-r--r--drivers/edac/mce_amd.c3
-rw-r--r--drivers/edac/npcm_edac.c543
-rw-r--r--drivers/edac/thunderx_edac.c2
-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/mailbox.c4
-rw-r--r--drivers/firmware/arm_scmi/powercap.c173
-rw-r--r--drivers/firmware/arm_scmi/raw_mode.c5
-rw-r--r--drivers/firmware/arm_scmi/smc.c51
-rw-r--r--drivers/firmware/cirrus/cs_dsp.c8
-rw-r--r--drivers/firmware/dmi-sysfs.c4
-rw-r--r--drivers/firmware/efi/Kconfig14
-rw-r--r--drivers/firmware/efi/Makefile1
-rw-r--r--drivers/firmware/efi/efi.c27
-rw-r--r--drivers/firmware/efi/esrt.c6
-rw-r--r--drivers/firmware/efi/libstub/Makefile2
-rw-r--r--drivers/firmware/efi/libstub/bitmap.c41
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c6
-rw-r--r--drivers/firmware/efi/libstub/efistub.h6
-rw-r--r--drivers/firmware/efi/libstub/find.c43
-rw-r--r--drivers/firmware/efi/libstub/unaccepted_memory.c222
-rw-r--r--drivers/firmware/efi/libstub/x86-stub.c75
-rw-r--r--drivers/firmware/efi/unaccepted_memory.c147
-rw-r--r--drivers/firmware/efi/vars.c12
-rw-r--r--drivers/firmware/iscsi_ibft_find.c26
-rw-r--r--drivers/firmware/smccc/soc_id.c5
-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-104-dio-48e.c37
-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-mvebu.c26
-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-sim.c16
-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-tps68470.c6
-rw-r--r--drivers/gpio/gpio-ts4900.c2
-rw-r--r--drivers/gpio/gpio-twl4030.c64
-rw-r--r--drivers/gpio/gpio-ws16c48.c2
-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-sysfs.c7
-rw-r--r--drivers/gpio/gpiolib.c60
-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.h85
-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.c175
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c19
-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.c68
-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.c381
-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.c91
-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.c93
-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.c381
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h143
-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.c31
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c53
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c48
-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.c201
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c257
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h73
-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_ring_mux.c5
-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.c11
-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.c62
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h35
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c266
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h28
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c39
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c67
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c415
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h184
-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/atom.c2
-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.c282
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c318
-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.c4195
-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.c847
-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_v2_3.c13
-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.c25
-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.c509
-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.c6
-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.c87
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_crat.h8
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_debug.c1117
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_debug.h129
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c2
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device.c536
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c1037
-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.c137
-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.h321
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process.c292
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c133
-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.c226
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_topology.h14
-rw-r--r--drivers/gpu/drm/amd/amdkfd/soc15_int.h1
-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.c479
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h11
-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_crtc.c12
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c352
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c60
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c117
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h11
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c3
-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.c47
-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.c114
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c573
-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.h54
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c317
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h16
-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_abm.h29
-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.c17
-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.c15
-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_cm_common.c19
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h1
-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.c162
-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.c107
-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.c41
-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_dpp.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c2
-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.c72
-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.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c40
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn301/Makefile3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.c185
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.h36
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c38
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c34
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c33
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c11
-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.c52
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c64
-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.c22
-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_hubp.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c90
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c9
-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.c53
-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.c224
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c58
-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/dcn20/display_mode_vba_20.c16
-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.c645
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h6
-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.c592
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.h4
-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.h4
-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.h2
-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.h2
-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_irq_handler.c37
-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.h22
-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.c10
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h4
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c67
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h35
-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.c54
-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.c149
-rw-r--r--drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h2
-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/legacy-dpm/legacy_dpm.c2
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c48
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c4
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c16
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.c12
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c27
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c10
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.c36
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c4
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c4
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c4
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c4
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h4
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/inc/power_state.h1
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c48
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h2
-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.h18
-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/arcturus_ppt.c2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c12
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c131
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c9
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c3
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c109
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c552
-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.c410
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c533
-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.c122
-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.c9
-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.c2
-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.c201
-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.c11
-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.c56
-rw-r--r--drivers/gpu/drm/bridge/ti-tfp410.c2
-rw-r--r--drivers/gpu/drm/display/drm_dp_helper.c2
-rw-r--r--drivers/gpu/drm/display/drm_dp_mst_topology.c111
-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.c12
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c13
-rw-r--r--drivers/gpu/drm/drm_client.c21
-rw-r--r--drivers/gpu/drm/drm_client_modeset.c6
-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.c67
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c402
-rw-r--r--drivers/gpu/drm/drm_fbdev_dma.c17
-rw-r--r--drivers/gpu/drm/drm_fbdev_generic.c15
-rw-r--r--drivers/gpu/drm/drm_file.c132
-rw-r--r--drivers/gpu/drm/drm_gem.c68
-rw-r--r--drivers/gpu/drm/drm_gem_framebuffer_helper.c9
-rw-r--r--drivers/gpu/drm/drm_gem_shmem_helper.c6
-rw-r--r--drivers/gpu/drm/drm_gem_vram_helper.c6
-rw-r--r--drivers/gpu/drm/drm_managed.c6
-rw-r--r--drivers/gpu/drm/drm_mipi_dsi.c2
-rw-r--r--drivers/gpu/drm/drm_probe_helper.c68
-rw-r--r--drivers/gpu/drm/drm_syncobj.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.c13
-rw-r--r--drivers/gpu/drm/gma500/Kconfig1
-rw-r--r--drivers/gpu/drm/gma500/fbdev.c14
-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.c4
-rw-r--r--drivers/gpu/drm/i915/Kconfig1
-rw-r--r--drivers/gpu/drm/i915/Kconfig.debug1
-rw-r--r--drivers/gpu/drm/i915/Makefile18
-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.c3047
-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.c1183
-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.c930
-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.h7
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power_map.c76
-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.h4
-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.c18
-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.c55
-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.c23
-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.c273
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr_regs.h209
-rw-r--r--drivers/gpu/drm/i915/display/intel_sdvo.c110
-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.c66
-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.c114
-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.c10
-rw-r--r--drivers/gpu/drm/i915/gt/gen6_ppgtt.c10
-rw-r--r--drivers/gpu/drm/i915/gt/gen8_engine_cs.c178
-rw-r--r--drivers/gpu/drm/i915/gt/gen8_engine_cs.h21
-rw-r--r--drivers/gpu/drm/i915/gt/gen8_ppgtt.c87
-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_gpu_commands.h2
-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.h35
-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.c49
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gtt.h36
-rw-r--r--drivers/gpu/drm/i915/gt/intel_lrc.c21
-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.c54
-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.c227
-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.c99
-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.c148
-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.c203
-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.c450
-rw-r--r--drivers/gpu/drm/i915/i915_perf.c105
-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.c13
-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.c43
-rw-r--r--drivers/gpu/drm/i915/selftests/mock_gtt.c8
-rw-r--r--drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c2
-rw-r--r--drivers/gpu/drm/imx/lcdc/imx-lcdc.c4
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c2
-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.c5
-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_gpu_state.h2
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_hfi.c33
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c29
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c8
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h158
-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_core_perf.h13
-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.c84
-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.c5
-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.c47
-rw-r--r--drivers/gpu/drm/msm/msm_fence.c6
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c15
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c23
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c6
-rw-r--r--drivers/gpu/drm/msm/msm_mdss.c29
-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.c25
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.c1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c13
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_debugfs.c19
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c20
-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/engine/disp/dp.c48
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c27
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c13
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c2
-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/i2c/base.c11
-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.c15
-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-jdi-lt070me05000.c36
-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.c586
-rw-r--r--drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c43
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c161
-rw-r--r--drivers/gpu/drm/panel/panel-sitronix-st7703.c102
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_devfreq.c2
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.h2
-rw-r--r--drivers/gpu/drm/qxl/qxl_dumb.c5
-rw-r--r--drivers/gpu/drm/qxl/qxl_gem.c25
-rw-r--r--drivers/gpu/drm/qxl/qxl_ioctl.c6
-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_atombios.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_atpx_handler.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_combios.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_cs.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_fbdev.c13
-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.c5
-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/inno_hdmi.c2
-rw-r--r--drivers/gpu/drm/rockchip/rk3066_hdmi.c2
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c2
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c25
-rw-r--r--drivers/gpu/drm/scheduler/sched_entity.c96
-rw-r--r--drivers/gpu/drm/scheduler/sched_fence.c44
-rw-r--r--drivers/gpu/drm/scheduler/sched_main.c40
-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_hdmi_i2c.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.c12
-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_bo.c30
-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_resource.c5
-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/drm/vmwgfx/vmwgfx_bo.c6
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_bo.h8
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h12
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c35
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c6
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h16
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c3
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_shader.c3
-rw-r--r--drivers/gpu/ipu-v3/ipu-prv.h1
-rw-r--r--drivers/greybus/connection.c4
-rw-r--r--drivers/greybus/svc.c2
-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_desc.c30
-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-hyperv.c10
-rw-r--r--drivers/hid/hid-ids.h15
-rw-r--r--drivers/hid/hid-input.c7
-rw-r--r--drivers/hid/hid-logitech-hidpp.c8
-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/hv/connection.c13
-rw-r--r--drivers/hv/hv_balloon.c2
-rw-r--r--drivers/hv/hv_common.c10
-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.c156
-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/k10temp.c17
-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.c83
-rw-r--r--drivers/hwmon/nct6775-i2c.c4
-rw-r--r--drivers/hwmon/nct6775-platform.c41
-rw-r--r--drivers/hwmon/nct6775.h3
-rw-r--r--drivers/hwmon/nct7802.c4
-rw-r--r--drivers/hwmon/nct7904.c2
-rw-r--r--drivers/hwmon/occ/p8_i2c.c2
-rw-r--r--drivers/hwmon/oxp-sensors.c204
-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.c18
-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.c26
-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.c36
-rw-r--r--drivers/hwtracing/coresight/coresight-trbe.h38
-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.c17
-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.c105
-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-hisi.c8
-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.c11
-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.c12
-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.c50
-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.c9
-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.c26
-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.c117
-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.c28
-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.c59
-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.c24
-rw-r--r--drivers/iio/adc/ad7291.c2
-rw-r--r--drivers/iio/adc/ad799x.c2
-rw-r--r--drivers/iio/adc/ina2xx-adc.c11
-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.c25
-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/common/cros_ec_sensors/cros_ec_sensors_core.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/frequency/admv1013.c5
-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_core.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-core.c5
-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.c1042
-rw-r--r--drivers/iio/light/rohm-bu27034.c25
-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.c5
-rw-r--r--drivers/infiniband/core/umem.c3
-rw-r--r--drivers/infiniband/hw/bnxt_re/bnxt_re.h5
-rw-r--r--drivers/infiniband/hw/bnxt_re/ib_verbs.c304
-rw-r--r--drivers/infiniband/hw/bnxt_re/ib_verbs.h19
-rw-r--r--drivers/infiniband/hw/bnxt_re/main.c196
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_fp.c124
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_fp.h3
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_rcfw.c667
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_rcfw.h52
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_res.c178
-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/chip.c1
-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/ctrl.c31
-rw-r--r--drivers/infiniband/hw/irdma/defs.h46
-rw-r--r--drivers/infiniband/hw/irdma/hw.c3
-rw-r--r--drivers/infiniband/hw/irdma/main.h2
-rw-r--r--drivers/infiniband/hw/irdma/puda.c6
-rw-r--r--drivers/infiniband/hw/irdma/type.h2
-rw-r--r--drivers/infiniband/hw/irdma/uk.c15
-rw-r--r--drivers/infiniband/hw/irdma/utils.c8
-rw-r--r--drivers/infiniband/hw/irdma/verbs.c41
-rw-r--r--drivers/infiniband/hw/mana/qp.c5
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c18
-rw-r--r--drivers/infiniband/hw/mlx5/ib_rep.c103
-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/mthca/mthca_qp.c2
-rw-r--r--drivers/infiniband/hw/qib/qib_user_pages.c2
-rw-r--r--drivers/infiniband/hw/usnic/usnic_uiom.c2
-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.c23
-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.c47
-rw-r--r--drivers/infiniband/sw/rxe/rxe_verbs.h21
-rw-r--r--drivers/infiniband/sw/siw/siw_mem.c2
-rw-r--r--drivers/infiniband/sw/siw/siw_qp_tx.c16
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-clt.c1
-rw-r--r--drivers/input/evdev.c2
-rw-r--r--drivers/input/input-leds.c2
-rw-r--r--drivers/input/joystick/walkera0701.c13
-rw-r--r--drivers/input/keyboard/adp5520-keys.c6
-rw-r--r--drivers/input/keyboard/cros_ec_keyb.c16
-rw-r--r--drivers/input/keyboard/ep93xx_keypad.c6
-rw-r--r--drivers/input/keyboard/iqs62x-keys.c6
-rw-r--r--drivers/input/keyboard/matrix_keypad.c6
-rw-r--r--drivers/input/keyboard/omap-keypad.c6
-rw-r--r--drivers/input/keyboard/omap4-keypad.c6
-rw-r--r--drivers/input/keyboard/samsung-keypad.c6
-rw-r--r--drivers/input/keyboard/sh_keysc.c6
-rw-r--r--drivers/input/keyboard/spear-keyboard.c6
-rw-r--r--drivers/input/keyboard/stmpe-keypad.c6
-rw-r--r--drivers/input/keyboard/tegra-kbc.c7
-rw-r--r--drivers/input/misc/88pm80x_onkey.c5
-rw-r--r--drivers/input/misc/Kconfig2
-rw-r--r--drivers/input/misc/axp20x-pek.c11
-rw-r--r--drivers/input/misc/da9052_onkey.c6
-rw-r--r--drivers/input/misc/da9055_onkey.c6
-rw-r--r--drivers/input/misc/ideapad_slidebar.c6
-rw-r--r--drivers/input/misc/iqs269a.c10
-rw-r--r--drivers/input/misc/kxtj9.c29
-rw-r--r--drivers/input/misc/m68kspkr.c6
-rw-r--r--drivers/input/misc/max8997_haptic.c6
-rw-r--r--drivers/input/misc/mc13783-pwrbutton.c6
-rw-r--r--drivers/input/misc/palmas-pwrbutton.c6
-rw-r--r--drivers/input/misc/pcap_keys.c6
-rw-r--r--drivers/input/misc/pcf50633-input.c6
-rw-r--r--drivers/input/misc/pcspkr.c6
-rw-r--r--drivers/input/misc/pm8941-pwrkey.c6
-rw-r--r--drivers/input/misc/soc_button_array.c6
-rw-r--r--drivers/input/misc/sparcspkr.c12
-rw-r--r--drivers/input/misc/wistron_btns.c6
-rw-r--r--drivers/input/misc/wm831x-on.c6
-rw-r--r--drivers/input/mouse/cyapa.c14
-rw-r--r--drivers/input/mouse/navpoint.c6
-rw-r--r--drivers/input/rmi4/rmi_bus.c2
-rw-r--r--drivers/input/rmi4/rmi_f34.c2
-rw-r--r--drivers/input/serio/altera_ps2.c6
-rw-r--r--drivers/input/serio/ams_delta_serio.c6
-rw-r--r--drivers/input/serio/apbps2.c6
-rw-r--r--drivers/input/serio/arc_ps2.c6
-rw-r--r--drivers/input/serio/ct82c710.c6
-rw-r--r--drivers/input/serio/i8042-sparcio.h6
-rw-r--r--drivers/input/serio/i8042.c6
-rw-r--r--drivers/input/serio/ioc3kbd.c6
-rw-r--r--drivers/input/serio/maceps2.c6
-rw-r--r--drivers/input/serio/olpc_apsp.c6
-rw-r--r--drivers/input/serio/ps2-gpio.c5
-rw-r--r--drivers/input/serio/q40kbd.c6
-rw-r--r--drivers/input/serio/rpckbd.c6
-rw-r--r--drivers/input/serio/sun4i-ps2.c6
-rw-r--r--drivers/input/serio/xilinx_ps2.c6
-rw-r--r--drivers/input/touchscreen/ad7877.c12
-rw-r--r--drivers/input/touchscreen/ad7879-i2c.c7
-rw-r--r--drivers/input/touchscreen/ad7879-spi.c7
-rw-r--r--drivers/input/touchscreen/ad7879.c10
-rw-r--r--drivers/input/touchscreen/ad7879.h3
-rw-r--r--drivers/input/touchscreen/ads7846.c130
-rw-r--r--drivers/input/touchscreen/cyttsp5.c19
-rw-r--r--drivers/input/touchscreen/da9052_tsi.c6
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c10
-rw-r--r--drivers/input/touchscreen/elants_i2c.c15
-rw-r--r--drivers/input/touchscreen/exc3000.c12
-rw-r--r--drivers/input/touchscreen/hideep.c15
-rw-r--r--drivers/input/touchscreen/hycon-hy46xx.c10
-rw-r--r--drivers/input/touchscreen/ili210x.c15
-rw-r--r--drivers/input/touchscreen/ilitek_ts_i2c.c12
-rw-r--r--drivers/input/touchscreen/iqs5xx.c10
-rw-r--r--drivers/input/touchscreen/mainstone-wm97xx.c6
-rw-r--r--drivers/input/touchscreen/mc13783_ts.c6
-rw-r--r--drivers/input/touchscreen/melfas_mip4.c13
-rw-r--r--drivers/input/touchscreen/pcap_ts.c6
-rw-r--r--drivers/input/touchscreen/raydium_i2c_ts.c16
-rw-r--r--drivers/input/touchscreen/rohm_bu21023.c12
-rw-r--r--drivers/input/touchscreen/s6sy761.c10
-rw-r--r--drivers/input/touchscreen/stmfts.c10
-rw-r--r--drivers/input/touchscreen/stmpe-ts.c6
-rw-r--r--drivers/input/touchscreen/sun4i-ts.c8
-rw-r--r--drivers/input/touchscreen/ti_am335x_tsc.c5
-rw-r--r--drivers/input/touchscreen/tsc2004.c7
-rw-r--r--drivers/input/touchscreen/tsc2005.c7
-rw-r--r--drivers/input/touchscreen/tsc200x-core.c18
-rw-r--r--drivers/input/touchscreen/tsc200x-core.h1
-rw-r--r--drivers/input/touchscreen/wdt87xx_i2c.c16
-rw-r--r--drivers/input/touchscreen/wm831x-ts.c6
-rw-r--r--drivers/input/touchscreen/wm97xx-core.c6
-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/bcm-voter.c5
-rw-r--r--drivers/interconnect/qcom/icc-rpm.c112
-rw-r--r--drivers/interconnect/qcom/icc-rpm.h22
-rw-r--r--drivers/interconnect/qcom/icc-rpmh.h2
-rw-r--r--drivers/interconnect/qcom/msm8996.c35
-rw-r--r--drivers/interconnect/qcom/sa8775p.c1
-rw-r--r--drivers/interconnect/qcom/sdm660.c17
-rw-r--r--drivers/interconnect/qcom/sm8450.c9
-rw-r--r--drivers/interconnect/qcom/sm8550.c17
-rw-r--r--drivers/iommu/Kconfig1
-rw-r--r--drivers/iommu/amd/amd_iommu.h91
-rw-r--r--drivers/iommu/amd/amd_iommu_types.h96
-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.c109
-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.c61
-rw-r--r--drivers/iommu/fsl_pamu_domain.c113
-rw-r--r--drivers/iommu/intel/iommu.c29
-rw-r--r--drivers/iommu/intel/irq_remapping.c8
-rw-r--r--drivers/iommu/iommu-sva.c5
-rw-r--r--drivers/iommu/iommu.c695
-rw-r--r--drivers/iommu/iommufd/device.c14
-rw-r--r--drivers/iommu/iommufd/io_pagetable.c14
-rw-r--r--drivers/iommu/iommufd/iommufd_private.h15
-rw-r--r--drivers/iommu/iommufd/main.c78
-rw-r--r--drivers/iommu/iommufd/pages.c6
-rw-r--r--drivers/iommu/iova.c8
-rw-r--r--drivers/iommu/virtio-iommu.c57
-rw-r--r--drivers/irqchip/irq-bcm6345-l1.c14
-rw-r--r--drivers/irqchip/irq-clps711x.c7
-rw-r--r--drivers/irqchip/irq-ftintc010.c4
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c80
-rw-r--r--drivers/irqchip/irq-gic-v3.c107
-rw-r--r--drivers/irqchip/irq-jcore-aic.c7
-rw-r--r--drivers/irqchip/irq-loongson-eiointc.c135
-rw-r--r--drivers/irqchip/irq-loongson-liointc.c13
-rw-r--r--drivers/irqchip/irq-loongson-pch-pic.c10
-rw-r--r--drivers/irqchip/irq-mmp.c127
-rw-r--r--drivers/irqchip/irq-mxs.c1
-rw-r--r--drivers/irqchip/irq-riscv-intc.c70
-rw-r--r--drivers/irqchip/irq-stm32-exti.c13
-rw-r--r--drivers/isdn/Kconfig1
-rw-r--r--drivers/isdn/hardware/mISDN/Kconfig12
-rw-r--r--drivers/isdn/hardware/mISDN/hfcpci.c10
-rw-r--r--drivers/isdn/mISDN/dsp.h2
-rw-r--r--drivers/isdn/mISDN/dsp_cmx.c2
-rw-r--r--drivers/isdn/mISDN/dsp_core.c2
-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.c386
-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/bcache.h12
-rw-r--r--drivers/md/bcache/btree.c48
-rw-r--r--drivers/md/bcache/btree.h5
-rw-r--r--drivers/md/bcache/request.c4
-rw-r--r--drivers/md/bcache/stats.h1
-rw-r--r--drivers/md/bcache/super.c136
-rw-r--r--drivers/md/bcache/sysfs.c31
-rw-r--r--drivers/md/bcache/sysfs.h2
-rw-r--r--drivers/md/bcache/writeback.c10
-rw-r--r--drivers/md/dm-bufio.c24
-rw-r--r--drivers/md/dm-cache-policy-smq.c28
-rw-r--r--drivers/md/dm-cache-target.c12
-rw-r--r--drivers/md/dm-clone-target.c10
-rw-r--r--drivers/md/dm-core.h10
-rw-r--r--drivers/md/dm-crypt.c69
-rw-r--r--drivers/md/dm-era-target.c6
-rw-r--r--drivers/md/dm-flakey.c210
-rw-r--r--drivers/md/dm-init.c4
-rw-r--r--drivers/md/dm-integrity.c90
-rw-r--r--drivers/md/dm-ioctl.c108
-rw-r--r--drivers/md/dm-raid.c24
-rw-r--r--drivers/md/dm-snap.c18
-rw-r--r--drivers/md/dm-table.c37
-rw-r--r--drivers/md/dm-thin-metadata.c58
-rw-r--r--drivers/md/dm-thin.c50
-rw-r--r--drivers/md/dm-verity-fec.c2
-rw-r--r--drivers/md/dm-verity-loadpin.c3
-rw-r--r--drivers/md/dm-verity-target.c6
-rw-r--r--drivers/md/dm-zone.c15
-rw-r--r--drivers/md/dm-zoned-metadata.c6
-rw-r--r--drivers/md/dm.c149
-rw-r--r--drivers/md/dm.h5
-rw-r--r--drivers/md/md-autodetect.c3
-rw-r--r--drivers/md/md-bitmap.c93
-rw-r--r--drivers/md/md-bitmap.h8
-rw-r--r--drivers/md/md-cluster.c17
-rw-r--r--drivers/md/md-multipath.c4
-rw-r--r--drivers/md/md.c274
-rw-r--r--drivers/md/md.h35
-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.c74
-rw-r--r--drivers/md/raid1.c43
-rw-r--r--drivers/md/raid1.h2
-rw-r--r--drivers/md/raid10.c205
-rw-r--r--drivers/md/raid10.h2
-rw-r--r--drivers/md/raid5-cache.c24
-rw-r--r--drivers/md/raid5-ppl.c4
-rw-r--r--drivers/md/raid5.c72
-rw-r--r--drivers/md/raid5.h4
-rw-r--r--drivers/media/cec/i2c/Kconfig1
-rw-r--r--drivers/media/cec/i2c/ch7322.c2
-rw-r--r--drivers/media/cec/usb/pulse8/pulse8-cec.c7
-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.c6
-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/cx23885/cx23885-dvb.c12
-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_core.c6
-rw-r--r--drivers/media/platform/amphion/vpu_malone.c12
-rw-r--r--drivers/media/platform/amphion/vpu_mbox.c9
-rw-r--r--drivers/media/platform/amphion/vpu_v4l2.c7
-rw-r--r--drivers/media/platform/amphion/vpu_v4l2.h2
-rw-r--r--drivers/media/platform/chips-media/coda-common.c2
-rw-r--r--drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c834
-rw-r--r--drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c4
-rw-r--r--drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_parse.c17
-rw-r--r--drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c4
-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.c10
-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.c133
-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/imx-jpeg/mxc-jpeg-hw.h1
-rw-r--r--drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c135
-rw-r--r--drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h5
-rw-r--r--drivers/media/platform/nxp/imx7-media-csi.c97
-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.h54
-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.c21
-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.c81
-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/media/v4l2-core/videobuf-dma-sg.c2
-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.c61
-rw-r--r--drivers/memory/tegra/mc.h1
-rw-r--r--drivers/memory/tegra/tegra186-emc.c133
-rw-r--r--drivers/memory/tegra/tegra194.c1
-rw-r--r--drivers/memory/tegra/tegra234.c574
-rw-r--r--drivers/memory/ti-emif-sram-pm.S2
-rw-r--r--drivers/memstick/host/r592.c4
-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/Kconfig70
-rw-r--r--drivers/mfd/Makefile8
-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.c6
-rw-r--r--drivers/mfd/axp20x.c219
-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-core.c (renamed from drivers/mfd/rk808.c)352
-rw-r--r--drivers/mfd/rk8xx-i2c.c185
-rw-r--r--drivers/mfd/rk8xx-spi.c124
-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-core.c462
-rw-r--r--drivers/mfd/tps6594-i2c.c244
-rw-r--r--drivers/mfd/tps6594-spi.c129
-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/cardreader/rts5227.c2
-rw-r--r--drivers/misc/cardreader/rts5228.c18
-rw-r--r--drivers/misc/cardreader/rts5249.c3
-rw-r--r--drivers/misc/cardreader/rts5260.c18
-rw-r--r--drivers/misc/cardreader/rts5261.c18
-rw-r--r--drivers/misc/cardreader/rtsx_pcr.c5
-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/bugs.c5
-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/sgi-gru/grufault.c4
-rw-r--r--drivers/misc/smpro-errmon.c1
-rw-r--r--drivers/misc/sram.c9
-rw-r--r--drivers/misc/tps6594-esm.c149
-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/core/block.c54
-rw-r--r--drivers/mmc/core/card.h30
-rw-r--r--drivers/mmc/core/quirks.h27
-rw-r--r--drivers/mmc/core/sd.c2
-rw-r--r--drivers/mmc/host/Kconfig2
-rw-r--r--drivers/mmc/host/cqhci.h3
-rw-r--r--drivers/mmc/host/dw_mmc-bluefield.c2
-rw-r--r--drivers/mmc/host/dw_mmc-k3.c2
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.c5
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.h2
-rw-r--r--drivers/mmc/host/dw_mmc-starfive.c2
-rw-r--r--drivers/mmc/host/meson-mx-sdhc-mmc.c8
-rw-r--r--drivers/mmc/host/mmci.c208
-rw-r--r--drivers/mmc/host/mmci.h25
-rw-r--r--drivers/mmc/host/mmci_stm32_sdmmc.c179
-rw-r--r--drivers/mmc/host/moxart-mmc.c8
-rw-r--r--drivers/mmc/host/mtk-sd.c48
-rw-r--r--drivers/mmc/host/omap.c46
-rw-r--r--drivers/mmc/host/sdhci-msm.c223
-rw-r--r--drivers/mmc/host/sdhci-pci-core.c1
-rw-r--r--drivers/mmc/host/sdhci-pci-gli.c406
-rw-r--r--drivers/mmc/host/sdhci-pci.h2
-rw-r--r--drivers/mmc/host/sdhci.c4
-rw-r--r--drivers/mmc/host/sdhci.h7
-rw-r--r--drivers/mmc/host/sdhci_f_sdh30.c69
-rw-r--r--drivers/mmc/host/sunplus-mmc.c26
-rw-r--r--drivers/mmc/host/wbsd.c2
-rw-r--r--drivers/most/configfs.c8
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c3
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c3
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0020.c3
-rw-r--r--drivers/mtd/chips/cfi_probe.c3
-rw-r--r--drivers/mtd/chips/cfi_util.c3
-rw-r--r--drivers/mtd/chips/gen_probe.c2
-rw-r--r--drivers/mtd/chips/jedec_probe.c3
-rw-r--r--drivers/mtd/chips/map_ram.c3
-rw-r--r--drivers/mtd/chips/map_rom.c3
-rw-r--r--drivers/mtd/devices/block2mtd.c64
-rw-r--r--drivers/mtd/devices/st_spi_fsm.c28
-rw-r--r--drivers/mtd/maps/pismo.c2
-rw-r--r--drivers/mtd/mtd_blkdevs.c8
-rw-r--r--drivers/mtd/mtdblock.c2
-rw-r--r--drivers/mtd/mtdcore.c21
-rw-r--r--drivers/mtd/mtdpart.c1
-rw-r--r--drivers/mtd/nand/raw/Makefile1
-rw-r--r--drivers/mtd/nand/raw/arasan-nand-controller.c15
-rw-r--r--drivers/mtd/nand/raw/fsl_upm.c2
-rw-r--r--drivers/mtd/nand/raw/internals.h1
-rw-r--r--drivers/mtd/nand/raw/meson_nand.c137
-rw-r--r--drivers/mtd/nand/raw/nand_ids.c5
-rw-r--r--drivers/mtd/nand/raw/nand_macronix.c167
-rw-r--r--drivers/mtd/nand/raw/nand_sandisk.c26
-rw-r--r--drivers/mtd/nand/raw/omap_elm.c24
-rw-r--r--drivers/mtd/nand/raw/rockchip-nand-controller.c45
-rw-r--r--drivers/mtd/nand/spi/gigadevice.c10
-rw-r--r--drivers/mtd/nand/spi/macronix.c20
-rw-r--r--drivers/mtd/nand/spi/toshiba.c4
-rw-r--r--drivers/mtd/nand/spi/winbond.c4
-rw-r--r--drivers/mtd/sm_ftl.c2
-rw-r--r--drivers/mtd/spi-nor/spansion.c4
-rw-r--r--drivers/mtd/ubi/block.c9
-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/Kconfig1
-rw-r--r--drivers/net/arcnet/arcnet.c8
-rw-r--r--drivers/net/bonding/bond_alb.c6
-rw-r--r--drivers/net/bonding/bond_main.c26
-rw-r--r--drivers/net/bonding/bonding_priv.h4
-rw-r--r--drivers/net/can/Kconfig3
-rw-r--r--drivers/net/can/at91_can.c6
-rw-r--r--drivers/net/can/bxcan.c17
-rw-r--r--drivers/net/can/c_can/c_can_platform.c6
-rw-r--r--drivers/net/can/cc770/cc770_isa.c6
-rw-r--r--drivers/net/can/cc770/cc770_platform.c6
-rw-r--r--drivers/net/can/ctucanfd/ctucanfd_platform.c6
-rw-r--r--drivers/net/can/dev/length.c15
-rw-r--r--drivers/net/can/dev/rx-offload.c2
-rw-r--r--drivers/net/can/flexcan/flexcan-core.c6
-rw-r--r--drivers/net/can/grcan.c6
-rw-r--r--drivers/net/can/ifi_canfd/ifi_canfd.c6
-rw-r--r--drivers/net/can/janz-ican3.c6
-rw-r--r--drivers/net/can/kvaser_pciefd.c955
-rw-r--r--drivers/net/can/m_can/m_can.c4
-rw-r--r--drivers/net/can/m_can/m_can_platform.c6
-rw-r--r--drivers/net/can/mscan/mpc5xxx_can.c6
-rw-r--r--drivers/net/can/rcar/rcar_can.c5
-rw-r--r--drivers/net/can/rcar/rcar_canfd.c6
-rw-r--r--drivers/net/can/sja1000/sja1000.c40
-rw-r--r--drivers/net/can/sja1000/sja1000.h1
-rw-r--r--drivers/net/can/sja1000/sja1000_isa.c6
-rw-r--r--drivers/net/can/sja1000/sja1000_platform.c11
-rw-r--r--drivers/net/can/softing/softing_main.c5
-rw-r--r--drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c10
-rw-r--r--drivers/net/can/spi/mcp251xfd/mcp251xfd.h1
-rw-r--r--drivers/net/can/sun4i_can.c6
-rw-r--r--drivers/net/can/ti_hecc.c8
-rw-r--r--drivers/net/can/usb/Kconfig12
-rw-r--r--drivers/net/can/usb/Makefile1
-rw-r--r--drivers/net/can/usb/esd_usb.c352
-rw-r--r--drivers/net/can/usb/f81604.c1201
-rw-r--r--drivers/net/can/usb/gs_usb.c132
-rw-r--r--drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c2
-rw-r--r--drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c13
-rw-r--r--drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c6
-rw-r--r--drivers/net/can/vxcan.c7
-rw-r--r--drivers/net/can/xilinx_can.c25
-rw-r--r--drivers/net/dsa/b53/b53_serdes.c3
-rw-r--r--drivers/net/dsa/bcm_sf2.c8
-rw-r--r--drivers/net/dsa/hirschmann/hellcreek.c14
-rw-r--r--drivers/net/dsa/lan9303-core.c1
-rw-r--r--drivers/net/dsa/lan9303_i2c.c2
-rw-r--r--drivers/net/dsa/microchip/ksz8795.c36
-rw-r--r--drivers/net/dsa/microchip/ksz8863_smi.c13
-rw-r--r--drivers/net/dsa/microchip/ksz9477.c116
-rw-r--r--drivers/net/dsa/microchip/ksz9477_i2c.c4
-rw-r--r--drivers/net/dsa/microchip/ksz_common.c94
-rw-r--r--drivers/net/dsa/microchip/ksz_common.h83
-rw-r--r--drivers/net/dsa/microchip/ksz_spi.c2
-rw-r--r--drivers/net/dsa/microchip/lan937x_main.c8
-rw-r--r--drivers/net/dsa/mt7530.c7
-rw-r--r--drivers/net/dsa/mt7530.h2
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c193
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.h15
-rw-r--r--drivers/net/dsa/mv88e6xxx/global2.c5
-rw-r--r--drivers/net/dsa/mv88e6xxx/port.c29
-rw-r--r--drivers/net/dsa/mv88e6xxx/port.h15
-rw-r--r--drivers/net/dsa/mv88e6xxx/serdes.c47
-rw-r--r--drivers/net/dsa/mv88e6xxx/serdes.h4
-rw-r--r--drivers/net/dsa/ocelot/felix.c24
-rw-r--r--drivers/net/dsa/ocelot/felix.h1
-rw-r--r--drivers/net/dsa/ocelot/felix_vsc9959.c87
-rw-r--r--drivers/net/dsa/ocelot/seville_vsc9953.c20
-rw-r--r--drivers/net/dsa/qca/ar9331.c20
-rw-r--r--drivers/net/dsa/qca/qca8k-8xxx.c25
-rw-r--r--drivers/net/dsa/qca/qca8k-common.c25
-rw-r--r--drivers/net/dsa/qca/qca8k-leds.c201
-rw-r--r--drivers/net/dsa/sja1105/sja1105.h2
-rw-r--r--drivers/net/dsa/sja1105/sja1105_main.c28
-rw-r--r--drivers/net/dsa/sja1105/sja1105_mdio.c11
-rw-r--r--drivers/net/dsa/sja1105/sja1105_ptp.c48
-rw-r--r--drivers/net/dsa/sja1105/sja1105_tas.c7
-rw-r--r--drivers/net/dsa/vitesse-vsc73xx-core.c6
-rw-r--r--drivers/net/dsa/xrs700x/xrs700x_i2c.c2
-rw-r--r--drivers/net/ethernet/8390/8390.h2
-rw-r--r--drivers/net/ethernet/8390/apne.c7
-rw-r--r--drivers/net/ethernet/8390/axnet_cs.c6
-rw-r--r--drivers/net/ethernet/8390/hydra.c6
-rw-r--r--drivers/net/ethernet/8390/lib8390.c5
-rw-r--r--drivers/net/ethernet/8390/mac8390.c6
-rw-r--r--drivers/net/ethernet/8390/mcf8390.c4
-rw-r--r--drivers/net/ethernet/8390/ne.c4
-rw-r--r--drivers/net/ethernet/8390/ne2k-pci.c1
-rw-r--r--drivers/net/ethernet/8390/pcnet_cs.c5
-rw-r--r--drivers/net/ethernet/8390/smc-ultra.c4
-rw-r--r--drivers/net/ethernet/8390/stnic.c5
-rw-r--r--drivers/net/ethernet/8390/wd.c4
-rw-r--r--drivers/net/ethernet/8390/zorro8390.c7
-rw-r--r--drivers/net/ethernet/altera/Kconfig4
-rw-r--r--drivers/net/ethernet/altera/altera_tse_main.c65
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_admin_defs.h6
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_com.c3
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_netdev.c136
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_netdev.h4
-rw-r--r--drivers/net/ethernet/amd/pds_core/core.c4
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c13
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_macsec.c40
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_ring.c6
-rw-r--r--drivers/net/ethernet/arc/emac.h2
-rw-r--r--drivers/net/ethernet/arc/emac_arc.c6
-rw-r--r--drivers/net/ethernet/arc/emac_main.c4
-rw-r--r--drivers/net/ethernet/arc/emac_rockchip.c5
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_main.c7
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_main.c7
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl1.c7
-rw-r--r--drivers/net/ethernet/broadcom/b44.c8
-rw-r--r--drivers/net/ethernet/broadcom/bgmac.c6
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.c1
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c21
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c32
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c17
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c95
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c1
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c14
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h2
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c14
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmmii.c4
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c7
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad_debugfs.c5
-rw-r--r--drivers/net/ethernet/cadence/macb.h13
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c56
-rw-r--r--drivers/net/ethernet/cavium/Kconfig5
-rw-r--r--drivers/net/ethernet/cavium/liquidio/Makefile8
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c8
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c7
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn66xx_device.c1
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn68xx_device.c1
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_core.c16
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_ethtool.c1
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_main.c18
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_vf_main.c15
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_device.c24
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_droq.c4
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c5
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_nic.c3
-rw-r--r--drivers/net/ethernet/cavium/liquidio/request_manager.c14
-rw-r--r--drivers/net/ethernet/cavium/liquidio/response_manager.c3
-rw-r--r--drivers/net/ethernet/cavium/thunder/thunder_bgx.c3
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/sge.c5
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h5
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c2
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c2
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h3
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c2
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c118
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c2
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c35
-rw-r--r--drivers/net/ethernet/engleder/tsnep_selftests.c12
-rw-r--r--drivers/net/ethernet/engleder/tsnep_tc.c4
-rw-r--r--drivers/net/ethernet/freescale/Kconfig2
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c4
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c33
-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/freescale/enetc/enetc.c12
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.h1
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_pf.c133
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_qos.c113
-rw-r--r--drivers/net/ethernet/freescale/fec.h17
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c220
-rw-r--r--drivers/net/ethernet/freescale/fman/fman_dtsec.c7
-rw-r--r--drivers/net/ethernet/freescale/fman/fman_memac.c18
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mii-fec.c2
-rw-r--r--drivers/net/ethernet/fungible/funeth/funeth_rx.c5
-rw-r--r--drivers/net/ethernet/fungible/funeth/funeth_tx.c3
-rw-r--r--drivers/net/ethernet/google/gve/gve.h1
-rw-r--r--drivers/net/ethernet/google/gve/gve_ethtool.c5
-rw-r--r--drivers/net/ethernet/google/gve/gve_main.c16
-rw-r--r--drivers/net/ethernet/google/gve/gve_tx.c2
-rw-r--r--drivers/net/ethernet/google/gve/gve_tx_dqo.c4
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hnae3.h10
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c22
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h2
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c3
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.h3
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c39
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_enet.c16
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c7
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c51
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c32
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c76
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h11
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c36
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h5
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c14
-rw-r--r--drivers/net/ethernet/i825xx/82596.c5
-rw-r--r--drivers/net/ethernet/i825xx/lasi_82596.c5
-rw-r--r--drivers/net/ethernet/i825xx/lib82596.c5
-rw-r--r--drivers/net/ethernet/i825xx/sun3_82586.c1
-rw-r--r--drivers/net/ethernet/i825xx/sun3_82586.h1
-rw-r--r--drivers/net/ethernet/ibm/ibmveth.c2
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.c121
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_debugfs.c2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c11
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_nvm.c16
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_xsk.c2
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf.h16
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_alloc.h3
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_common.c45
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_ethtool.c54
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_fdir.c88
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_fdir.h2
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_main.c326
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_osdep.h9
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_prototype.h5
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_txrx.c43
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_txrx.h4
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_virtchnl.c5
-rw-r--r--drivers/net/ethernet/intel/ice/Makefile1
-rw-r--r--drivers/net/ethernet/intel/ice/ice.h51
-rw-r--r--drivers/net/ethernet/intel/ice/ice_adminq_cmd.h2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_arfs.c5
-rw-r--r--drivers/net/ethernet/intel/ice/ice_base.c55
-rw-r--r--drivers/net/ethernet/intel/ice/ice_common.c10
-rw-r--r--drivers/net/ethernet/intel/ice/ice_controlq.c12
-rw-r--r--drivers/net/ethernet/intel/ice/ice_controlq.h1
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ddp.h9
-rw-r--r--drivers/net/ethernet/intel/ice/ice_devlink.c10
-rw-r--r--drivers/net/ethernet/intel/ice/ice_eswitch.c90
-rw-r--r--drivers/net/ethernet/intel/ice/ice_eswitch.h14
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ethtool.c324
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ethtool.h105
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c26
-rw-r--r--drivers/net/ethernet/intel/ice/ice_flow.c23
-rw-r--r--drivers/net/ethernet/intel/ice/ice_idc.c54
-rw-r--r--drivers/net/ethernet/intel/ice/ice_irq.c378
-rw-r--r--drivers/net/ethernet/intel/ice/ice_irq.h25
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lag.c12
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lag.h54
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lib.c359
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lib.h5
-rw-r--r--drivers/net/ethernet/intel/ice/ice_main.c413
-rw-r--r--drivers/net/ethernet/intel/ice/ice_protocol_type.h197
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp.c64
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp.h16
-rw-r--r--drivers/net/ethernet/intel/ice/ice_repr.c17
-rw-r--r--drivers/net/ethernet/intel/ice/ice_repr.h5
-rw-r--r--drivers/net/ethernet/intel/ice/ice_sched.c11
-rw-r--r--drivers/net/ethernet/intel/ice/ice_sriov.c60
-rw-r--r--drivers/net/ethernet/intel/ice/ice_switch.c251
-rw-r--r--drivers/net/ethernet/intel/ice/ice_switch.h13
-rw-r--r--drivers/net/ethernet/intel/ice/ice_tc_lib.c56
-rw-r--r--drivers/net/ethernet/intel/ice/ice_tc_lib.h2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_vf_lib.c69
-rw-r--r--drivers/net/ethernet/intel/ice/ice_vf_lib.h8
-rw-r--r--drivers/net/ethernet/intel/ice/ice_virtchnl.c9
-rw-r--r--drivers/net/ethernet/intel/ice/ice_vlan_mode.c2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_xsk.c5
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c7
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ptp.c24
-rw-r--r--drivers/net/ethernet/intel/igc/igc.h56
-rw-r--r--drivers/net/ethernet/intel/igc/igc_defines.h2
-rw-r--r--drivers/net/ethernet/intel/igc/igc_ethtool.c2
-rw-r--r--drivers/net/ethernet/intel/igc/igc_main.c303
-rw-r--r--drivers/net/ethernet/intel/igc/igc_ptp.c167
-rw-r--r--drivers/net/ethernet/intel/igc/igc_tsn.c68
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c2
-rw-r--r--drivers/net/ethernet/korina.c3
-rw-r--r--drivers/net/ethernet/litex/litex_liteeth.c19
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c182
-rw-r--r--drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c14
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c3
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c2
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_main.c9
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_rx.c2
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/Kconfig1
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/cgx.c33
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/cgx.h2
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/common.h9
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h3
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/mbox.h11
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/ptp.c19
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rpm.c32
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rpm.h5
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu.c8
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu.h32
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c22
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c5
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c74
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c306
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c66
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h8
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h3
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c18
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/Makefile2
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c224
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c215
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h93
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c29
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c8
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c143
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h13
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c58
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c43
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h4
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c19
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/qos.c1363
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/qos.h69
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/qos_sq.c296
-rw-r--r--drivers/net/ethernet/marvell/prestera/prestera_flower.c6
-rw-r--r--drivers/net/ethernet/marvell/prestera/prestera_main.c11
-rw-r--r--drivers/net/ethernet/marvell/prestera/prestera_pci.c3
-rw-r--r--drivers/net/ethernet/marvell/prestera/prestera_router.c14
-rw-r--r--drivers/net/ethernet/mediatek/mtk_eth_soc.c29
-rw-r--r--drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c2
-rw-r--r--drivers/net/ethernet/mediatek/mtk_wed.c12
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c65
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/Makefile3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/debugfs.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/dev.c22
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/devlink.c87
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c106
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en.h17
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c44
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/qos.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c14
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c31
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.h5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c18
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c26
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c18
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_fs.c12
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c53
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rep.c157
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rep.h7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rx.c48
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_stats.c25
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tc.c237
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c25
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c69
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h12
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_debugfs.c89
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c21
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c37
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.c206
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.h80
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c454
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/events.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c35
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.c108
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fw.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c168
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/health.c25
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c141
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h11
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c36
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c129
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h37
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/events.h40
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h34
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/main.c215
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h42
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c11
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c16
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/rdma.c24
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c15
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c14
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sriov.c53
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c20
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/thermal.c34
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/vport.c16
-rw-r--r--drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/i2c.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/minimal.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/pci.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/reg.h9
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.c22
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.h8
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c45
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c19
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c832
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h12
-rw-r--r--drivers/net/ethernet/microchip/Kconfig2
-rw-r--r--drivers/net/ethernet/microchip/enc28j60.c28
-rw-r--r--drivers/net/ethernet/microchip/lan743x_main.c43
-rw-r--r--drivers/net/ethernet/microchip/lan966x/Kconfig11
-rw-r--r--drivers/net/ethernet/microchip/lan966x/Makefile1
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_dcb.c365
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_main.c3
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_main.h60
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c7
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_port.c149
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_regs.h147
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_tc.c10
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c61
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c264
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c23
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c82
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_main.c1
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c8
-rw-r--r--drivers/net/ethernet/microchip/vcap/vcap_ag_api.h67
-rw-r--r--drivers/net/ethernet/microchip/vcap/vcap_api.c8
-rw-r--r--drivers/net/ethernet/microsoft/mana/hw_channel.c2
-rw-r--r--drivers/net/ethernet/microsoft/mana/mana_en.c61
-rw-r--r--drivers/net/ethernet/mscc/ocelot.c2
-rw-r--r--drivers/net/ethernet/mscc/ocelot_fdma.c3
-rw-r--r--drivers/net/ethernet/mscc/ocelot_flower.c10
-rw-r--r--drivers/net/ethernet/mscc/ocelot_mm.c14
-rw-r--r--drivers/net/ethernet/mscc/ocelot_ptp.c66
-rw-r--r--drivers/net/ethernet/myricom/myri10ge/myri10ge.c1
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_devlink.c10
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_common.c11
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c32
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h7
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c54
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/Kconfig2
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c6
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_ethtool.c10
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_lif.c33
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_lif.h1
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_dev_api.h16
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_fcoe.c19
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_fcoe.h17
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_hw.c26
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_iscsi.c19
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_iscsi.h8
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_l2.c19
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_l2.h24
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_main.c6
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_main.c10
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-mac.c7
-rw-r--r--drivers/net/ethernet/realtek/r8169_main.c86
-rw-r--r--drivers/net/ethernet/renesas/rswitch.c38
-rw-r--r--drivers/net/ethernet/renesas/rswitch.h7
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h2
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c4
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c5
-rw-r--r--drivers/net/ethernet/sfc/Kconfig1
-rw-r--r--drivers/net/ethernet/sfc/Makefile3
-rw-r--r--drivers/net/ethernet/sfc/ef10.c13
-rw-r--r--drivers/net/ethernet/sfc/ef100_netdev.c85
-rw-r--r--drivers/net/ethernet/sfc/ef100_nic.c2
-rw-r--r--drivers/net/ethernet/sfc/efx.c9
-rw-r--r--drivers/net/ethernet/sfc/efx_devlink.c83
-rw-r--r--drivers/net/ethernet/sfc/falcon/selftest.c58
-rw-r--r--drivers/net/ethernet/sfc/mae.c141
-rw-r--r--drivers/net/ethernet/sfc/mae.h9
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h3
-rw-r--r--drivers/net/ethernet/sfc/selftest.c58
-rw-r--r--drivers/net/ethernet/sfc/siena/selftest.c58
-rw-r--r--drivers/net/ethernet/sfc/siena/tx_common.c1
-rw-r--r--drivers/net/ethernet/sfc/tc.c409
-rw-r--r--drivers/net/ethernet/sfc/tc.h51
-rw-r--r--drivers/net/ethernet/sfc/tc_bindings.c13
-rw-r--r--drivers/net/ethernet/sfc/tc_bindings.h14
-rw-r--r--drivers/net/ethernet/sfc/tc_counters.c58
-rw-r--r--drivers/net/ethernet/sfc/tc_counters.h3
-rw-r--r--drivers/net/ethernet/sfc/tc_encap_actions.c747
-rw-r--r--drivers/net/ethernet/sfc/tc_encap_actions.h114
-rw-r--r--drivers/net/ethernet/sfc/tx_common.c1
-rw-r--r--drivers/net/ethernet/socionext/netsec.c11
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Kconfig3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Makefile2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c257
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h29
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c16
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c9
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c9
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c297
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c108
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c9
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c19
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c20
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c15
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c168
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h16
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c7
-rw-r--r--drivers/net/ethernet/sun/cassini.c8
-rw-r--r--drivers/net/ethernet/sun/sunvnet_common.c1
-rw-r--r--drivers/net/ethernet/ti/am65-cpsw-qos.c11
-rw-r--r--drivers/net/ethernet/ti/cpsw_ale.c24
-rw-r--r--drivers/net/ethernet/wangxun/Kconfig10
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_hw.c273
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_hw.h3
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_lib.c737
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_lib.h1
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_type.h220
-rw-r--r--drivers/net/ethernet/wangxun/ngbe/ngbe_main.c20
-rw-r--r--drivers/net/ethernet/wangxun/ngbe/ngbe_type.h1
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/Makefile1
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c28
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c35
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_main.c98
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c673
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h10
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_type.h90
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac_main.c12
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_main.c16
-rw-r--r--drivers/net/gtp.c2
-rw-r--r--drivers/net/hyperv/hyperv_net.h5
-rw-r--r--drivers/net/hyperv/netvsc_drv.c10
-rw-r--r--drivers/net/hyperv/rndis_filter.c29
-rw-r--r--drivers/net/ieee802154/ca8210.c4
-rw-r--r--drivers/net/ipa/ipa_table.c20
-rw-r--r--drivers/net/ipvlan/ipvlan_core.c12
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c3
-rw-r--r--drivers/net/macsec.c28
-rw-r--r--drivers/net/macvlan.c1
-rw-r--r--drivers/net/mctp/mctp-i2c.c2
-rw-r--r--drivers/net/mdio/Kconfig11
-rw-r--r--drivers/net/mdio/Makefile1
-rw-r--r--drivers/net/mdio/mdio-bitbang.c4
-rw-r--r--drivers/net/mdio/mdio-mux-mmioreg.c7
-rw-r--r--drivers/net/mdio/mdio-regmap.c93
-rw-r--r--drivers/net/netdevsim/dev.c9
-rw-r--r--drivers/net/ntb_netdev.c2
-rw-r--r--drivers/net/pcs/Kconfig6
-rw-r--r--drivers/net/pcs/Makefile1
-rw-r--r--drivers/net/pcs/pcs-altera-tse.c160
-rw-r--r--drivers/net/pcs/pcs-lynx.c123
-rw-r--r--drivers/net/pcs/pcs-mtk-lynxi.c39
-rw-r--r--drivers/net/pcs/pcs-rzn1-miic.c10
-rw-r--r--drivers/net/pcs/pcs-xpcs.c265
-rw-r--r--drivers/net/pcs/pcs-xpcs.h3
-rw-r--r--drivers/net/phy/Kconfig17
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/at803x.c91
-rw-r--r--drivers/net/phy/bcm-phy-lib.c264
-rw-r--r--drivers/net/phy/bcm-phy-lib.h10
-rw-r--r--drivers/net/phy/broadcom.c190
-rw-r--r--drivers/net/phy/dp83869.c13
-rw-r--r--drivers/net/phy/dp83td510.c23
-rw-r--r--drivers/net/phy/marvell10g.c7
-rw-r--r--drivers/net/phy/mediatek-ge-soc.c1116
-rw-r--r--drivers/net/phy/mediatek-ge.c3
-rw-r--r--drivers/net/phy/micrel.c331
-rw-r--r--drivers/net/phy/microchip_t1s.c274
-rw-r--r--drivers/net/phy/mscc/mscc.h1
-rw-r--r--drivers/net/phy/mscc/mscc_main.c51
-rw-r--r--drivers/net/phy/phy-c45.c9
-rw-r--r--drivers/net/phy/phy.c22
-rw-r--r--drivers/net/phy/phy_device.c55
-rw-r--r--drivers/net/phy/phylink.c209
-rw-r--r--drivers/net/phy/realtek.c34
-rw-r--r--drivers/net/phy/sfp-bus.c30
-rw-r--r--drivers/net/phy/sfp.c345
-rw-r--r--drivers/net/phy/sfp.h1
-rw-r--r--drivers/net/ppp/Kconfig34
-rw-r--r--drivers/net/ppp/pppoe.c2
-rw-r--r--drivers/net/ppp/pptp.c31
-rw-r--r--drivers/net/tap.c3
-rw-r--r--drivers/net/team/team.c13
-rw-r--r--drivers/net/tun.c4
-rw-r--r--drivers/net/usb/Kconfig10
-rw-r--r--drivers/net/usb/cdc_ether.c27
-rw-r--r--drivers/net/usb/ipheth.c186
-rw-r--r--drivers/net/usb/lan78xx.c7
-rw-r--r--drivers/net/usb/qmi_wwan.c2
-rw-r--r--drivers/net/usb/r8152.c1
-rw-r--r--drivers/net/usb/usbnet.c6
-rw-r--r--drivers/net/usb/zaurus.c21
-rw-r--r--drivers/net/veth.c34
-rw-r--r--drivers/net/virtio_net.c667
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c4
-rw-r--r--drivers/net/vrf.c12
-rw-r--r--drivers/net/vxlan/vxlan_core.c186
-rw-r--r--drivers/net/vxlan/vxlan_vnifilter.c11
-rw-r--r--drivers/net/wireguard/allowedips.c8
-rw-r--r--drivers/net/wireguard/device.c1
-rw-r--r--drivers/net/wireguard/netlink.c14
-rw-r--r--drivers/net/wireguard/queueing.c1
-rw-r--r--drivers/net/wireguard/queueing.h25
-rw-r--r--drivers/net/wireguard/receive.c2
-rw-r--r--drivers/net/wireguard/selftest/allowedips.c16
-rw-r--r--drivers/net/wireguard/send.c2
-rw-r--r--drivers/net/wireguard/timers.c10
-rw-r--r--drivers/net/wireless/ath/ath10k/ahb.c20
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c12
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h3
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c4
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h6
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c13
-rw-r--r--drivers/net/wireless/ath/ath10k/qmi.c3
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c8
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c34
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h2
-rw-r--r--drivers/net/wireless/ath/ath11k/ahb.c9
-rw-r--r--drivers/net/wireless/ath/ath11k/ce.c4
-rw-r--r--drivers/net/wireless/ath/ath11k/core.c89
-rw-r--r--drivers/net/wireless/ath/ath11k/core.h16
-rw-r--r--drivers/net/wireless/ath/ath11k/debug.c2
-rw-r--r--drivers/net/wireless/ath/ath11k/debug.h49
-rw-r--r--drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c114
-rw-r--r--drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h43
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_rx.c8
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_tx.c12
-rw-r--r--drivers/net/wireless/ath/ath11k/hal.c10
-rw-r--r--drivers/net/wireless/ath/ath11k/hal_rx.c24
-rw-r--r--drivers/net/wireless/ath/ath11k/htc.c42
-rw-r--r--drivers/net/wireless/ath/ath11k/hw.c5
-rw-r--r--drivers/net/wireless/ath/ath11k/hw.h1
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.c539
-rw-r--r--drivers/net/wireless/ath/ath11k/mhi.c6
-rw-r--r--drivers/net/wireless/ath/ath11k/pci.c25
-rw-r--r--drivers/net/wireless/ath/ath11k/pcic.c7
-rw-r--r--drivers/net/wireless/ath/ath11k/peer.c4
-rw-r--r--drivers/net/wireless/ath/ath11k/qmi.c76
-rw-r--r--drivers/net/wireless/ath/ath11k/reg.c4
-rw-r--r--drivers/net/wireless/ath/ath11k/testmode.c387
-rw-r--r--drivers/net/wireless/ath/ath11k/testmode.h6
-rw-r--r--drivers/net/wireless/ath/ath11k/testmode_i.h18
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.c628
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.h70
-rw-r--r--drivers/net/wireless/ath/ath11k/wow.c3
-rw-r--r--drivers/net/wireless/ath/ath12k/core.c2
-rw-r--r--drivers/net/wireless/ath/ath12k/core.h1
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_rx.c27
-rw-r--r--drivers/net/wireless/ath/ath12k/hal.c16
-rw-r--r--drivers/net/wireless/ath/ath12k/hal.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/hw.c6
-rw-r--r--drivers/net/wireless/ath/ath12k/hw.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.c51
-rw-r--r--drivers/net/wireless/ath/ath12k/pci.c14
-rw-r--r--drivers/net/wireless/ath/ath12k/qmi.c9
-rw-r--r--drivers/net/wireless/ath/ath12k/qmi.h1
-rw-r--r--drivers/net/wireless/ath/ath12k/wmi.c106
-rw-r--r--drivers/net/wireless/ath/ath12k/wmi.h10
-rw-r--r--drivers/net/wireless/ath/ath6kl/Makefile5
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_hw.c27
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_hst.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c11
-rw-r--r--drivers/net/wireless/ath/ath9k/wmi.c4
-rw-r--r--drivers/net/wireless/ath/wil6210/fw.h4
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.h2
-rw-r--r--drivers/net/wireless/atmel/Kconfig2
-rw-r--r--drivers/net/wireless/atmel/atmel_cs.c13
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c5
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c6
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h7
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h7
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h8
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c4
-rw-r--r--drivers/net/wireless/cisco/airo.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/Kconfig1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/Makefile1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/1000.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/2000.c18
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/22000.c837
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/5000.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/6000.c18
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/7000.c22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/8000.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/9000.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/ax210.c301
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/bz.c183
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/sc.c166
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/rs.c43
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/acpi.c121
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/acpi.h41
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/binding.h14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/commands.h23
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/config.h15
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/context.h13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/d3.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/location.h16
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h65
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/mac.h24
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h46
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/offload.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/phy.h10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/power.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/rs.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/rx.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/scan.h41
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/tx.h13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.c72
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.h18
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/debugfs.c35
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dump.c15
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/file.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/pnvm.c234
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/pnvm.h27
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/runtime.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/uefi.c272
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/uefi.h47
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-config.h71
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h32
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-context-info.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c56
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.c75
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-fh.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-io.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c155
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-prph.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.h108
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mei/main.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/binding.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/constants.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c420
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c202
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c48
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c23
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c93
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/link.c37
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c122
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c200
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c99
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c26
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c177
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c28
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h107
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/nvm.c63
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/offloading.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c16
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c15
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/power.c56
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c77
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.c11
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rx.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c46
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c163
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sf.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c90
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h20
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c150
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/utils.c26
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c273
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/drv.c517
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/internal.h12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/rx.c31
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c73
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/queue/tx.c22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/queue/tx.h8
-rw-r--r--drivers/net/wireless/intersil/hostap/Kconfig2
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_ioctl.c2
-rw-r--r--drivers/net/wireless/intersil/orinoco/orinoco_cs.c13
-rw-r--r--drivers/net/wireless/intersil/orinoco/spectrum_cs.c13
-rw-r--r--drivers/net/wireless/intersil/p54/p54spi.c1
-rw-r--r--drivers/net/wireless/legacy/ray_cs.c33
-rw-r--r--drivers/net/wireless/legacy/rayctl.h2
-rw-r--r--drivers/net/wireless/legacy/wl3501_cs.c16
-rw-r--r--drivers/net/wireless/marvell/mwifiex/11n.h4
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfg80211.c12
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.c8
-rw-r--r--drivers/net/wireless/marvell/mwifiex/scan.c6
-rw-r--r--drivers/net/wireless/marvell/mwifiex/wmm.h15
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c6
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/dma.c4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mcu.c8
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/pci.c8
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/debugfs.c2
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/trace.h2
-rw-r--r--drivers/net/wireless/microchip/wilc1000/hif.c8
-rw-r--r--drivers/net/wireless/microchip/wilc1000/hif.h2
-rw-r--r--drivers/net/wireless/microchip/wilc1000/wlan_cfg.h2
-rw-r--r--drivers/net/wireless/microchip/wilc1000/wlan_if.h2
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00link.c2
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/Kconfig3
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/Makefile2
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h84
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c3
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c25
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c28
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c2090
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c37
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c5
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c567
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h52
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.c20
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.h1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/core.c10
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/core.h2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/pci.c7
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c40
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c41
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c56
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h6
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c42
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c40
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c16
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c42
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c42
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c42
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c14
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c60
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h9
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/usb.c42
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/wifi.h29
-rw-r--r--drivers/net/wireless/realtek/rtw88/Kconfig11
-rw-r--r--drivers/net/wireless/realtek/rtw88/Makefile3
-rw-r--r--drivers/net/wireless/realtek/rtw88/debug.c59
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.c68
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.h13
-rw-r--r--drivers/net/wireless/realtek/rtw88/mac.c6
-rw-r--r--drivers/net/wireless/realtek/rtw88/mac80211.c13
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.c15
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.h1
-rw-r--r--drivers/net/wireless/realtek/rtw88/pci.c5
-rw-r--r--drivers/net/wireless/realtek/rtw88/ps.c3
-rw-r--r--drivers/net/wireless/realtek/rtw88/reg.h2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723d.c15
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723d.h6
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723ds.c41
-rw-r--r--drivers/net/wireless/realtek/rtw88/sdio.c24
-rw-r--r--drivers/net/wireless/realtek/rtw88/tx.c94
-rw-r--r--drivers/net/wireless/realtek/rtw88/tx.h124
-rw-r--r--drivers/net/wireless/realtek/rtw88/usb.c17
-rw-r--r--drivers/net/wireless/realtek/rtw89/Kconfig14
-rw-r--r--drivers/net/wireless/realtek/rtw89/Makefile12
-rw-r--r--drivers/net/wireless/realtek/rtw89/acpi.c52
-rw-r--r--drivers/net/wireless/realtek/rtw89/acpi.h21
-rw-r--r--drivers/net/wireless/realtek/rtw89/coex.c9
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.c261
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.h217
-rw-r--r--drivers/net/wireless/realtek/rtw89/debug.c65
-rw-r--r--drivers/net/wireless/realtek/rtw89/efuse.c21
-rw-r--r--drivers/net/wireless/realtek/rtw89/efuse.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.c175
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.h281
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.c162
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.h5
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac80211.c16
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.c25
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.c344
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.h12
-rw-r--r--drivers/net/wireless/realtek/rtw89/reg.h134
-rw-r--r--drivers/net/wireless/realtek/rtw89/regd.c324
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b.c2442
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b.h76
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c3621
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.h28
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b_table.c252
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b_table.h2
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851be.c86
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852a.c15
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c36
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b.c8
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c8
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b_table.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b_table.h2
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c.c8
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c11
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_table.c27992
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_table.h2
-rw-r--r--drivers/net/wireless/realtek/rtw89/ser.c48
-rw-r--r--drivers/net/wireless/realtek/rtw89/txrx.h176
-rw-r--r--drivers/net/wireless/realtek/rtw89/wow.c2
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_sdio.c9
-rw-r--r--drivers/net/wireless/virtual/mac80211_hwsim.c23
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_imem.c17
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_imem.h15
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_mux.h4
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_pcie.c4
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_port.c17
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_trace.c8
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_wwan.c23
-rw-r--r--drivers/net/wwan/t7xx/t7xx_hif_cldma.c13
-rw-r--r--drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c5
-rw-r--r--drivers/net/xen-netback/netback.c21
-rw-r--r--drivers/nfc/fdp/i2c.c2
-rw-r--r--drivers/nfc/microread/i2c.c2
-rw-r--r--drivers/nfc/nfcmrvl/i2c.c2
-rw-r--r--drivers/nfc/nxp-nci/i2c.c4
-rw-r--r--drivers/nfc/pn533/i2c.c2
-rw-r--r--drivers/nfc/pn544/i2c.c2
-rw-r--r--drivers/nfc/s3fwrn5/i2c.c2
-rw-r--r--drivers/nfc/st-nci/i2c.c2
-rw-r--r--drivers/nfc/st21nfca/i2c.c2
-rw-r--r--drivers/ntb/hw/amd/ntb_hw_amd.c11
-rw-r--r--drivers/ntb/hw/epf/ntb_hw_epf.c12
-rw-r--r--drivers/ntb/hw/idt/ntb_hw_idt.c24
-rw-r--r--drivers/ntb/hw/intel/ntb_hw_gen1.c9
-rw-r--r--drivers/ntb/ntb_transport.c2
-rw-r--r--drivers/ntb/test/ntb_tool.c2
-rw-r--r--drivers/nubus/nubus.c13
-rw-r--r--drivers/nubus/proc.c33
-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/auth.c6
-rw-r--r--drivers/nvme/host/constants.c2
-rw-r--r--drivers/nvme/host/core.c873
-rw-r--r--drivers/nvme/host/fabrics.c241
-rw-r--r--drivers/nvme/host/fabrics.h21
-rw-r--r--drivers/nvme/host/fault_inject.c2
-rw-r--r--drivers/nvme/host/fc.c45
-rw-r--r--drivers/nvme/host/ioctl.c142
-rw-r--r--drivers/nvme/host/multipath.c16
-rw-r--r--drivers/nvme/host/nvme.h20
-rw-r--r--drivers/nvme/host/pci.c40
-rw-r--r--drivers/nvme/host/pr.c315
-rw-r--r--drivers/nvme/host/rdma.c84
-rw-r--r--drivers/nvme/host/sysfs.c668
-rw-r--r--drivers/nvme/host/tcp.c144
-rw-r--r--drivers/nvme/host/zns.c9
-rw-r--r--drivers/nvme/target/fabrics-cmd-auth.c13
-rw-r--r--drivers/nvme/target/fcloop.c5
-rw-r--r--drivers/nvme/target/io-cmd-bdev.c4
-rw-r--r--drivers/nvme/target/loop.c2
-rw-r--r--drivers/nvme/target/nvmet.h4
-rw-r--r--drivers/nvme/target/passthru.c4
-rw-r--r--drivers/nvme/target/tcp.c46
-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/Kconfig2
-rw-r--r--drivers/of/dynamic.c31
-rw-r--r--drivers/of/kexec.c3
-rw-r--r--drivers/of/of_reserved_mem.c60
-rw-r--r--drivers/of/platform.c9
-rw-r--r--drivers/of/unittest.c36
-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.c38
-rw-r--r--drivers/parport/Kconfig3
-rw-r--r--drivers/parport/parport_gsc.c28
-rw-r--r--drivers/parport/parport_gsc.h7
-rw-r--r--drivers/parport/procfs.c185
-rw-r--r--drivers/parport/share.c2
-rw-r--r--drivers/pci/Kconfig1
-rw-r--r--drivers/pci/bus.c4
-rw-r--r--drivers/pci/controller/Kconfig1
-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.c2
-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.c15
-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.c9
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c21
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c12
-rw-r--r--drivers/pci/of.c19
-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/Kconfig21
-rw-r--r--drivers/perf/Makefile2
-rw-r--r--drivers/perf/apple_m1_cpu_pmu.c30
-rw-r--r--drivers/perf/arm-cci.c4
-rw-r--r--drivers/perf/arm-cmn.c172
-rw-r--r--drivers/perf/arm_cspmu/Kconfig3
-rw-r--r--drivers/perf/arm_cspmu/arm_cspmu.c89
-rw-r--r--drivers/perf/arm_cspmu/arm_cspmu.h5
-rw-r--r--drivers/perf/arm_dmc620_pmu.c22
-rw-r--r--drivers/perf/arm_pmu.c7
-rw-r--r--drivers/perf/arm_pmuv3.c12
-rw-r--r--drivers/perf/cxl_pmu.c990
-rw-r--r--drivers/perf/fsl_imx9_ddr_perf.c711
-rw-r--r--drivers/perf/hisilicon/Makefile2
-rw-r--r--drivers/perf/hisilicon/hisi_pcie_pmu.c2
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_pa_pmu.c127
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_pmu.c4
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_pmu.h14
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_uc_pmu.c578
-rw-r--r--drivers/perf/qcom_l2_pmu.c2
-rw-r--r--drivers/perf/riscv_pmu.c3
-rw-r--r--drivers/perf/riscv_pmu_sbi.c23
-rw-r--r--drivers/phy/Kconfig1
-rw-r--r--drivers/phy/amlogic/phy-meson-g12a-usb2.c15
-rw-r--r--drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c15
-rw-r--r--drivers/phy/broadcom/phy-brcm-usb-init.c34
-rw-r--r--drivers/phy/broadcom/phy-brcm-usb-init.h8
-rw-r--r--drivers/phy/cadence/phy-cadence-salvo.c95
-rw-r--r--drivers/phy/cadence/phy-cadence-sierra.c1
-rw-r--r--drivers/phy/cadence/phy-cadence-torrent.c721
-rw-r--r--drivers/phy/freescale/phy-fsl-imx8m-pcie.c4
-rw-r--r--drivers/phy/freescale/phy-fsl-imx8mq-usb.c218
-rw-r--r--drivers/phy/hisilicon/Kconfig2
-rw-r--r--drivers/phy/hisilicon/phy-hisi-inno-usb2.c64
-rw-r--r--drivers/phy/mediatek/phy-mtk-dp.c2
-rw-r--r--drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c2
-rw-r--r--drivers/phy/mediatek/phy-mtk-tphy.c356
-rw-r--r--drivers/phy/microchip/sparx5_serdes.c426
-rw-r--r--drivers/phy/microchip/sparx5_serdes.h1
-rw-r--r--drivers/phy/microchip/sparx5_serdes_regs.h106
-rw-r--r--drivers/phy/phy-core.c14
-rw-r--r--drivers/phy/qualcomm/Kconfig12
-rw-r--r--drivers/phy/qualcomm/Makefile3
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-combo.c263
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-usb.c182
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qusb2.c3
-rw-r--r--drivers/phy/qualcomm/phy-qcom-sgmii-eth.c451
-rw-r--r--drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c78
-rw-r--r--drivers/phy/samsung/Kconfig2
-rw-r--r--drivers/phy/tegra/xusb.c4
-rw-r--r--drivers/phy/ti/phy-am654-serdes.c1
-rw-r--r--drivers/phy/ti/phy-gmii-sel.c34
-rw-r--r--drivers/phy/ti/phy-j721e-wiz.c1
-rw-r--r--drivers/pinctrl/Kconfig3
-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.c83
-rw-r--r--drivers/pinctrl/pinctrl-amd.h2
-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-rk805.c189
-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.c22
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.h44
-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.c328
-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/renesas/pinctrl-rza2.c17
-rw-r--r--drivers/pinctrl/renesas/pinctrl-rzg2l.c43
-rw-r--r--drivers/pinctrl/renesas/pinctrl-rzv2m.c41
-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_i2c.c2
-rw-r--r--drivers/platform/chrome/cros_ec_lpc.c15
-rw-r--r--drivers/platform/chrome/cros_ec_spi.c8
-rw-r--r--drivers/platform/chrome/cros_ec_typec.c2
-rw-r--r--drivers/platform/chrome/cros_hps_i2c.c2
-rw-r--r--drivers/platform/chrome/cros_typec_switch.c11
-rw-r--r--drivers/platform/mellanox/mlxbf-bootctl.c144
-rw-r--r--drivers/platform/mellanox/mlxbf-tmfifo.c1
-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/Makefile2
-rw-r--r--drivers/platform/x86/amd/pmc-quirks.c172
-rw-r--r--drivers/platform/x86/amd/pmc.c153
-rw-r--r--drivers/platform/x86/amd/pmc.h44
-rw-r--r--drivers/platform/x86/amd/pmf/Kconfig11
-rw-r--r--drivers/platform/x86/amd/pmf/acpi.c23
-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/core.c12
-rw-r--r--drivers/platform/x86/amd/pmf/pmf.h16
-rw-r--r--drivers/platform/x86/amd/pmf/sps.c130
-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/asus-wmi.c14
-rw-r--r--drivers/platform/x86/dell/dell-rbtn.c13
-rw-r--r--drivers/platform/x86/dell/dell-wmi-ddv.c7
-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/huawei-wmi.c2
-rw-r--r--drivers/platform/x86/ideapad-laptop.c5
-rw-r--r--drivers/platform/x86/intel/hid.c27
-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.c5
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c2
-rw-r--r--drivers/platform/x86/intel/tpmi.c10
-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-ymc.c32
-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/mlx-platform.c23
-rw-r--r--drivers/platform/x86/msi-ec.c18
-rw-r--r--drivers/platform/x86/msi-laptop.c8
-rw-r--r--drivers/platform/x86/serial-multi-instantiate.c35
-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.c69
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c149
-rw-r--r--drivers/platform/x86/toshiba_acpi.c2
-rw-r--r--drivers/platform/x86/touchscreen_dmi.c23
-rw-r--r--drivers/platform/x86/wmi.c132
-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/Kconfig19
-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/Kconfig18
-rw-r--r--drivers/powercap/Makefile1
-rw-r--r--drivers/powercap/arm_scmi_powercap.c16
-rw-r--r--drivers/powercap/intel_rapl_common.c885
-rw-r--r--drivers/powercap/intel_rapl_msr.c80
-rw-r--r--drivers/powercap/intel_rapl_tpmi.c324
-rw-r--r--drivers/ptp/Kconfig2
-rw-r--r--drivers/ptp/ptp_chardev.c5
-rw-r--r--drivers/ptp/ptp_clock.c4
-rw-r--r--drivers/ptp/ptp_clockmatrix.c36
-rw-r--r--drivers/ptp/ptp_clockmatrix.h2
-rw-r--r--drivers/ptp/ptp_idt82p33.c18
-rw-r--r--drivers/ptp/ptp_idt82p33.h4
-rw-r--r--drivers/ptp/ptp_ocp.c7
-rw-r--r--drivers/ptp/ptp_sysfs.c15
-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-atmel.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-pxa.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/ras/debugfs.c2
-rw-r--r--drivers/regulator/88pg86x.c2
-rw-r--r--drivers/regulator/Kconfig45
-rw-r--r--drivers/regulator/Makefile4
-rw-r--r--drivers/regulator/act8865-regulator.c2
-rw-r--r--drivers/regulator/ad5398.c2
-rw-r--r--drivers/regulator/axp20x-regulator.c290
-rw-r--r--drivers/regulator/core.c30
-rw-r--r--drivers/regulator/da9063-regulator.c9
-rw-r--r--drivers/regulator/da9121-regulator.c2
-rw-r--r--drivers/regulator/da9210-regulator.c2
-rw-r--r--drivers/regulator/da9211-regulator.c2
-rw-r--r--drivers/regulator/fan53555.c2
-rw-r--r--drivers/regulator/fan53880.c2
-rw-r--r--drivers/regulator/helpers.c23
-rw-r--r--drivers/regulator/isl6271a-regulator.c2
-rw-r--r--drivers/regulator/isl9305.c2
-rw-r--r--drivers/regulator/lp3971.c2
-rw-r--r--drivers/regulator/lp3972.c2
-rw-r--r--drivers/regulator/lp872x.c2
-rw-r--r--drivers/regulator/lp8755.c2
-rw-r--r--drivers/regulator/ltc3589.c4
-rw-r--r--drivers/regulator/ltc3676.c4
-rw-r--r--drivers/regulator/max1586.c2
-rw-r--r--drivers/regulator/max20086-regulator.c2
-rw-r--r--drivers/regulator/max20411-regulator.c2
-rw-r--r--drivers/regulator/max77541-regulator.c153
-rw-r--r--drivers/regulator/max77826-regulator.c2
-rw-r--r--drivers/regulator/max8649.c2
-rw-r--r--drivers/regulator/max8660.c2
-rw-r--r--drivers/regulator/max8893.c2
-rw-r--r--drivers/regulator/max8952.c2
-rw-r--r--drivers/regulator/max8973-regulator.c2
-rw-r--r--drivers/regulator/mcp16502.c2
-rw-r--r--drivers/regulator/mp5416.c2
-rw-r--r--drivers/regulator/mp8859.c2
-rw-r--r--drivers/regulator/mp886x.c2
-rw-r--r--drivers/regulator/mpq7920.c2
-rw-r--r--drivers/regulator/mt6311-regulator.c2
-rw-r--r--drivers/regulator/mt6358-regulator.c221
-rw-r--r--drivers/regulator/pca9450-regulator.c2
-rw-r--r--drivers/regulator/pf8x00-regulator.c2
-rw-r--r--drivers/regulator/pfuze100-regulator.c2
-rw-r--r--drivers/regulator/pv88060-regulator.c2
-rw-r--r--drivers/regulator/pv88080-regulator.c2
-rw-r--r--drivers/regulator/pv88090-regulator.c2
-rw-r--r--drivers/regulator/qcom-rpmh-regulator.c2
-rw-r--r--drivers/regulator/raa215300.c190
-rw-r--r--drivers/regulator/rk808-regulator.c399
-rw-r--r--drivers/regulator/rpi-panel-attiny-regulator.c2
-rw-r--r--drivers/regulator/rt4801-regulator.c2
-rw-r--r--drivers/regulator/rt5190a-regulator.c2
-rw-r--r--drivers/regulator/rt5739.c2
-rw-r--r--drivers/regulator/rt5759-regulator.c2
-rw-r--r--drivers/regulator/rt6160-regulator.c2
-rw-r--r--drivers/regulator/rt6190-regulator.c2
-rw-r--r--drivers/regulator/rt6245-regulator.c2
-rw-r--r--drivers/regulator/rtmv20-regulator.c2
-rw-r--r--drivers/regulator/rtq2134-regulator.c2
-rw-r--r--drivers/regulator/rtq6752-regulator.c2
-rw-r--r--drivers/regulator/slg51000-regulator.c2
-rw-r--r--drivers/regulator/stm32-pwr.c2
-rw-r--r--drivers/regulator/sy8106a-regulator.c2
-rw-r--r--drivers/regulator/sy8824x.c2
-rw-r--r--drivers/regulator/sy8827n.c2
-rw-r--r--drivers/regulator/tps51632-regulator.c2
-rw-r--r--drivers/regulator/tps62360-regulator.c2
-rw-r--r--drivers/regulator/tps6286x-regulator.c2
-rw-r--r--drivers/regulator/tps6287x-regulator.c189
-rw-r--r--drivers/regulator/tps65023-regulator.c2
-rw-r--r--drivers/regulator/tps65132-regulator.c2
-rw-r--r--drivers/regulator/tps65219-regulator.c6
-rw-r--r--drivers/regulator/tps6594-regulator.c615
-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/Kconfig29
-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.c142
-rw-r--r--drivers/s390/block/dasd_3990_erp.c4
-rw-r--r--drivers/s390/block/dasd_diag.c2
-rw-r--r--drivers/s390/block/dasd_eckd.c4
-rw-r--r--drivers/s390/block/dasd_fba.c2
-rw-r--r--drivers/s390/block/dasd_genhd.c5
-rw-r--r--drivers/s390/block/dasd_int.h3
-rw-r--r--drivers/s390/block/dasd_ioctl.c3
-rw-r--r--drivers/s390/block/dcssblk.c16
-rw-r--r--drivers/s390/char/Kconfig2
-rw-r--r--drivers/s390/char/con3215.c2
-rw-r--r--drivers/s390/char/monwriter.c2
-rw-r--r--drivers/s390/char/uvdevice.c231
-rw-r--r--drivers/s390/char/zcore.c41
-rw-r--r--drivers/s390/cio/ccwgroup.c2
-rw-r--r--drivers/s390/cio/device.c2
-rw-r--r--drivers/s390/cio/device_fsm.c4
-rw-r--r--drivers/s390/cio/vfio_ccw_cp.c4
-rw-r--r--drivers/s390/cio/vfio_ccw_drv.c2
-rw-r--r--drivers/s390/cio/vfio_ccw_private.h2
-rw-r--r--drivers/s390/crypto/ap_bus.c4
-rw-r--r--drivers/s390/crypto/ap_bus.h27
-rw-r--r--drivers/s390/crypto/ap_queue.c7
-rw-r--r--drivers/s390/crypto/pkey_api.c509
-rw-r--r--drivers/s390/crypto/vfio_ap_ops.c138
-rw-r--r--drivers/s390/crypto/vfio_ap_private.h3
-rw-r--r--drivers/s390/crypto/zcrypt_api.c113
-rw-r--r--drivers/s390/crypto/zcrypt_api.h3
-rw-r--r--drivers/s390/crypto/zcrypt_ccamisc.c2
-rw-r--r--drivers/s390/crypto/zcrypt_ccamisc.h4
-rw-r--r--drivers/s390/crypto/zcrypt_ep11misc.c2
-rw-r--r--drivers/s390/crypto/zcrypt_ep11misc.h4
-rw-r--r--drivers/s390/crypto/zcrypt_msgtype50.c10
-rw-r--r--drivers/s390/crypto/zcrypt_msgtype6.c51
-rw-r--r--drivers/s390/net/ctcm_dbug.c2
-rw-r--r--drivers/s390/net/ctcm_main.c6
-rw-r--r--drivers/s390/net/ctcm_main.h1
-rw-r--r--drivers/s390/net/ctcm_mpc.c28
-rw-r--r--drivers/s390/net/ctcm_sysfs.c46
-rw-r--r--drivers/s390/net/ism_drv.c141
-rw-r--r--drivers/s390/net/lcs.c13
-rw-r--r--drivers/s390/net/lcs.h2
-rw-r--r--drivers/s390/net/netiucv.c2
-rw-r--r--drivers/s390/net/qeth_core.h1
-rw-r--r--drivers/s390/net/qeth_core_main.c2
-rw-r--r--drivers/s390/net/qeth_l2_main.c9
-rw-r--r--drivers/s390/net/qeth_l3_main.c8
-rw-r--r--drivers/s390/net/qeth_l3_sys.c2
-rw-r--r--drivers/s390/scsi/zfcp_fc.c6
-rw-r--r--drivers/sbus/char/oradax.c21
-rw-r--r--drivers/scsi/3w-9xxx.c2
-rw-r--r--drivers/scsi/3w-xxxx.c4
-rw-r--r--drivers/scsi/53c700.c2
-rw-r--r--drivers/scsi/Kconfig25
-rw-r--r--drivers/scsi/NCR5380.c2
-rw-r--r--drivers/scsi/aacraid/aachba.c2
-rw-r--r--drivers/scsi/aacraid/aacraid.h2
-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/bnx2i/bnx2i_init.c2
-rw-r--r--drivers/scsi/ch.c3
-rw-r--r--drivers/scsi/fcoe/fcoe_transport.c2
-rw-r--r--drivers/scsi/fnic/fnic.h2
-rw-r--r--drivers/scsi/fnic/fnic_debugfs.c8
-rw-r--r--drivers/scsi/fnic/fnic_scsi.c6
-rw-r--r--drivers/scsi/fnic/fnic_trace.c2
-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/hptiop.c4
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c6
-rw-r--r--drivers/scsi/isci/scu_task_context.h2
-rw-r--r--drivers/scsi/iscsi_tcp.c26
-rw-r--r--drivers/scsi/iscsi_tcp.h2
-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.c61
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h30
-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.c88
-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/megaraid/megaraid_sas_base.c12
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fp.c6
-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/ncr53c8xx.c2
-rw-r--r--drivers/scsi/pcmcia/Kconfig6
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c33
-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.c21
-rw-r--r--drivers/scsi/qedi/qedi_main.c25
-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.h27
-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.c271
-rw-r--r--drivers/scsi/qla2xxx/qla_inline.h5
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c41
-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/raid_class.c47
-rw-r--r--drivers/scsi/scsi.c162
-rw-r--r--drivers/scsi/scsi_bsg.c4
-rw-r--r--drivers/scsi/scsi_common.c46
-rw-r--r--drivers/scsi/scsi_debug.c8
-rw-r--r--drivers/scsi/scsi_error.c48
-rw-r--r--drivers/scsi/scsi_ioctl.c38
-rw-r--r--drivers/scsi/scsi_lib.c137
-rw-r--r--drivers/scsi/scsi_priv.h6
-rw-r--r--drivers/scsi/scsi_proc.c30
-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.c237
-rw-r--r--drivers/scsi/sd_zbc.c12
-rw-r--r--drivers/scsi/sg.c19
-rw-r--r--drivers/scsi/smartpqi/Kconfig2
-rw-r--r--drivers/scsi/smartpqi/smartpqi.h10
-rw-r--r--drivers/scsi/smartpqi/smartpqi_init.c293
-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.c4
-rw-r--r--drivers/scsi/sr.c24
-rw-r--r--drivers/scsi/st.c2
-rw-r--r--drivers/scsi/storvsc_drv.c10
-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/aspeed/aspeed-socinfo.c1
-rw-r--r--drivers/soc/aspeed/aspeed-uart-routing.c2
-rw-r--r--drivers/soc/fsl/dpio/dpio-driver.c8
-rw-r--r--drivers/soc/fsl/qe/Kconfig1
-rw-r--r--drivers/soc/imx/imx8mp-blk-ctrl.c2
-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.c95
-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.c13
-rw-r--r--drivers/soundwire/bus.c38
-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.c498
-rw-r--r--drivers/soundwire/stream.c161
-rw-r--r--drivers/spi/Kconfig7
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/spi-atmel.c18
-rw-r--r--drivers/spi/spi-bcm-qspi.c10
-rw-r--r--drivers/spi/spi-bcm63xx-hsspi.c2
-rw-r--r--drivers/spi/spi-bcm63xx.c2
-rw-r--r--drivers/spi/spi-bcmbca-hsspi.c2
-rw-r--r--drivers/spi/spi-cadence-quadspi.c19
-rw-r--r--drivers/spi/spi-cadence.c20
-rw-r--r--drivers/spi/spi-dw-core.c14
-rw-r--r--drivers/spi/spi-dw-dma.c76
-rw-r--r--drivers/spi/spi-dw-mmio.c22
-rw-r--r--drivers/spi/spi-dw.h1
-rw-r--r--drivers/spi/spi-fsl-lpspi.c8
-rw-r--r--drivers/spi/spi-geni-qcom.c111
-rw-r--r--drivers/spi/spi-hisi-kunpeng.c2
-rw-r--r--drivers/spi/spi-imx.c63
-rw-r--r--drivers/spi/spi-mt65xx.c33
-rw-r--r--drivers/spi/spi-pl022.c4
-rw-r--r--drivers/spi/spi-qcom-qspi.c264
-rw-r--r--drivers/spi/spi-rzv2m-csi.c667
-rw-r--r--drivers/spi/spi-s3c64xx.c199
-rw-r--r--drivers/spi/spi-sc18is602.c2
-rw-r--r--drivers/spi/spi-sn-f-ospi.c17
-rw-r--r--drivers/spi/spi-stm32.c270
-rw-r--r--drivers/spi/spi-sun6i.c133
-rw-r--r--drivers/spi/spi-xcomm.c2
-rw-r--r--drivers/spi/spidev.c5
-rw-r--r--drivers/staging/axis-fifo/axis-fifo.c3
-rw-r--r--drivers/staging/fbtft/fb_ili9341.c2
-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/ks7010/ks_wlan_net.c6
-rw-r--r--drivers/staging/media/atomisp/Kconfig1
-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/rtl8712/rtl871x_xmit.c43
-rw-r--r--drivers/staging/rtl8712/xmit_linux.c6
-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.c19
-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.c286
-rw-r--r--drivers/target/target_core_pr.c79
-rw-r--r--drivers/target/target_core_pscsi.c9
-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/target/target_core_user.c4
-rw-r--r--drivers/tee/optee/smc_abi.c3
-rw-r--r--drivers/thermal/Kconfig8
-rw-r--r--drivers/thermal/amlogic_thermal.c3
-rw-r--r--drivers/thermal/armada_thermal.c32
-rw-r--r--drivers/thermal/imx8mm_thermal.c3
-rw-r--r--drivers/thermal/imx_sc_thermal.c3
-rw-r--r--drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c218
-rw-r--r--drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h57
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c27
-rw-r--r--drivers/thermal/k3_bandgap.c3
-rw-r--r--drivers/thermal/mediatek/auxadc_thermal.c14
-rw-r--r--drivers/thermal/mediatek/lvts_thermal.c4
-rw-r--r--drivers/thermal/qcom/qcom-spmi-adc-tm5.c4
-rw-r--r--drivers/thermal/qcom/qcom-spmi-temp-alarm.c38
-rw-r--r--drivers/thermal/qcom/tsens-v0_1.c126
-rw-r--r--drivers/thermal/qcom/tsens-v1.c22
-rw-r--r--drivers/thermal/qcom/tsens.c26
-rw-r--r--drivers/thermal/qcom/tsens.h6
-rw-r--r--drivers/thermal/qoriq_thermal.c52
-rw-r--r--drivers/thermal/rcar_gen3_thermal.c141
-rw-r--r--drivers/thermal/st/st_thermal.c4
-rw-r--r--drivers/thermal/st/st_thermal.h2
-rw-r--r--drivers/thermal/st/st_thermal_memmap.c6
-rw-r--r--drivers/thermal/sun8i_thermal.c59
-rw-r--r--drivers/thermal/tegra/tegra30-tsensor.c3
-rw-r--r--drivers/thermal/thermal-generic-adc.c4
-rw-r--r--drivers/thermal/thermal_core.c4
-rw-r--r--drivers/thermal/thermal_core.h2
-rw-r--r--drivers/thermal/thermal_hwmon.c5
-rw-r--r--drivers/thermal/thermal_of.c27
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-thermal-common.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.c331
-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.c715
-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/Kconfig3
-rw-r--r--drivers/tty/n_gsm.c7
-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.c94
-rw-r--r--drivers/tty/serial/8250/8250_dwlib.c6
-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.c165
-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/Kconfig27
-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.c61
-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.c12
-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.h47
-rw-r--r--drivers/tty/serial/serial_base_bus.c247
-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/sh-sci.c2
-rw-r--r--drivers/tty/serial/sifive.c2
-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/ucc_uart.c2
-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.c37
-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.c298
-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.h28
-rw-r--r--drivers/ufs/core/ufshcd.c509
-rw-r--r--drivers/ufs/core/ufshpb.c6
-rw-r--r--drivers/ufs/core/ufshpb.h2
-rw-r--r--drivers/ufs/host/Kconfig3
-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.c104
-rw-r--r--drivers/ufs/host/ufs-qcom.h32
-rw-r--r--drivers/ufs/host/ufs-renesas.c2
-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.c19
-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.c12
-rw-r--r--drivers/usb/core/buffer.c8
-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/core/quirks.c4
-rw-r--r--drivers/usb/dwc2/params.c21
-rw-r--r--drivers/usb/dwc2/platform.c22
-rw-r--r--drivers/usb/dwc3/core.c37
-rw-r--r--drivers/usb/dwc3/core.h5
-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-pci.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.c22
-rw-r--r--drivers/usb/fotg210/fotg210-core.c6
-rw-r--r--drivers/usb/gadget/composite.c4
-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/legacy/raw_gadget.c10
-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.c34
-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.c14
-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.c13
-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.c13
-rw-r--r--drivers/usb/host/xhci-pci.c28
-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.c162
-rw-r--r--drivers/usb/host/xhci-tegra.c20
-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/ehset.c8
-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.c10
-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-simple.c73
-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/storage/alauda.c12
-rw-r--r--drivers/usb/typec/Kconfig13
-rw-r--r--drivers/usb/typec/Makefile1
-rw-r--r--drivers/usb/typec/altmodes/displayport.c18
-rw-r--r--drivers/usb/typec/anx7411.c2
-rw-r--r--drivers/usb/typec/class.c19
-rw-r--r--drivers/usb/typec/hd3ss3220.c4
-rw-r--r--drivers/usb/typec/mux.c61
-rw-r--r--drivers/usb/typec/mux/Kconfig11
-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.c540
-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.c34
-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/core/mlx5_vdpa.h2
-rw-r--r--drivers/vdpa/mlx5/core/mr.c97
-rw-r--r--drivers/vdpa/mlx5/net/mlx5_vnet.c167
-rw-r--r--drivers/vdpa/mlx5/net/mlx5_vnet.h15
-rw-r--r--drivers/vdpa/pds/Makefile9
-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.c286
-rw-r--r--drivers/vdpa/pds/debugfs.h17
-rw-r--r--drivers/vdpa/pds/vdpa_dev.c843
-rw-r--r--drivers/vdpa/pds/vdpa_dev.h50
-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.c9
-rw-r--r--drivers/vdpa/vdpa_user/vduse_dev.c16
-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/vfio/vfio_iommu_type1.c9
-rw-r--r--drivers/vhost/net.c8
-rw-r--r--drivers/vhost/scsi.c290
-rw-r--r--drivers/vhost/vdpa.c2
-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.c18
-rw-r--r--drivers/video/console/vgacon.c74
-rw-r--r--drivers/video/fbdev/Kconfig24
-rw-r--r--drivers/video/fbdev/amifb.c2
-rw-r--r--drivers/video/fbdev/arcfb.c12
-rw-r--r--drivers/video/fbdev/atmel_lcdfb.c2
-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.c5
-rw-r--r--drivers/video/fbdev/broadsheetfb.c18
-rw-r--r--drivers/video/fbdev/bw2.c3
-rw-r--r--drivers/video/fbdev/cg14.c3
-rw-r--r--drivers/video/fbdev/cg3.c3
-rw-r--r--drivers/video/fbdev/cg6.c3
-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.c8
-rw-r--r--drivers/video/fbdev/core/fbmem.c113
-rw-r--r--drivers/video/fbdev/core/sysimgblt.c2
-rw-r--r--drivers/video/fbdev/ep93xx-fb.c4
-rw-r--r--drivers/video/fbdev/ffb.c3
-rw-r--r--drivers/video/fbdev/goldfishfb.c4
-rw-r--r--drivers/video/fbdev/grvga.c3
-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/imxfb.c48
-rw-r--r--drivers/video/fbdev/kyro/STG4000InitDevice.c10
-rw-r--r--drivers/video/fbdev/kyro/fbdev.c2
-rw-r--r--drivers/video/fbdev/leo.c3
-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/mb862xx/mb862xxfb_accel.c4
-rw-r--r--drivers/video/fbdev/mb862xx/mb862xxfbdrv.c6
-rw-r--r--drivers/video/fbdev/metronomefb.c18
-rw-r--r--drivers/video/fbdev/mmp/hw/mmp_ctrl.c4
-rw-r--r--drivers/video/fbdev/omap/lcd_mipid.c16
-rw-r--r--drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c2
-rw-r--r--drivers/video/fbdev/p9100.c3
-rw-r--r--drivers/video/fbdev/platinumfb.c4
-rw-r--r--drivers/video/fbdev/ps3fb.c4
-rw-r--r--drivers/video/fbdev/pvr2fb.c5
-rw-r--r--drivers/video/fbdev/sbuslib.c2
-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.c7
-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/sunxvr1000.c3
-rw-r--r--drivers/video/fbdev/sunxvr2500.c2
-rw-r--r--drivers/video/fbdev/sunxvr500.c2
-rw-r--r--drivers/video/fbdev/tcx.c3
-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/fbdev/xilinxfb.c5
-rw-r--r--drivers/video/sticore.c (renamed from drivers/video/console/sticore.c)284
-rw-r--r--drivers/virt/acrn/ioreq.c4
-rw-r--r--drivers/virt/coco/sev-guest/Kconfig1
-rw-r--r--drivers/virtio/virtio_mem.c168
-rw-r--r--drivers/virtio/virtio_mmio.c5
-rw-r--r--drivers/virtio/virtio_pci_common.c2
-rw-r--r--drivers/virtio/virtio_pci_common.h7
-rw-r--r--drivers/virtio/virtio_pci_legacy.c1
-rw-r--r--drivers/virtio/virtio_pci_modern_dev.c33
-rw-r--r--drivers/virtio/virtio_vdpa.c6
-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
-rw-r--r--drivers/watchdog/Kconfig18
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/ep93xx_wdt.c5
-rw-r--r--drivers/watchdog/ibmasr.c3
-rw-r--r--drivers/watchdog/loongson1_wdt.c13
-rw-r--r--drivers/watchdog/m54xx_wdt.c4
-rw-r--r--drivers/watchdog/max63xx_wdt.c5
-rw-r--r--drivers/watchdog/moxart_wdt.c4
-rw-r--r--drivers/watchdog/octeon-wdt-nmi.S5
-rw-r--r--drivers/watchdog/orion_wdt.c4
-rw-r--r--drivers/watchdog/rtd119x_wdt.c2
-rw-r--r--drivers/watchdog/sbc_fitpc2_wdt.c4
-rw-r--r--drivers/watchdog/sp5100_tco.c4
-rw-r--r--drivers/watchdog/ts4800_wdt.c4
-rw-r--r--drivers/watchdog/ts72xx_wdt.c4
-rw-r--r--drivers/watchdog/xilinx_wwdt.c201
-rw-r--r--drivers/watchdog/ziirave_wdt.c2
-rw-r--r--drivers/xen/events/events_base.c16
-rw-r--r--drivers/xen/evtchn.c35
-rw-r--r--drivers/xen/grant-dma-ops.c2
-rw-r--r--drivers/xen/grant-table.c40
-rw-r--r--drivers/xen/privcmd.c2
-rw-r--r--drivers/xen/pvcalls-back.c4
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c3
5934 files changed, 279110 insertions, 86367 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..2f027d5a8206 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);
@@ -3991,6 +3980,15 @@ static inline void hl_debugfs_fini(void)
{
}
+static inline int hl_debugfs_device_init(struct hl_device *hdev)
+{
+ return 0;
+}
+
+static inline void hl_debugfs_device_fini(struct hl_device *hdev)
+{
+}
+
static inline void hl_debugfs_add_device(struct hl_device *hdev)
{
}
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/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h
index d3013fbd13b3..399dc5dcefd7 100644
--- a/drivers/accel/ivpu/ivpu_drv.h
+++ b/drivers/accel/ivpu/ivpu_drv.h
@@ -75,6 +75,7 @@ struct ivpu_wa_table {
bool punit_disabled;
bool clear_runtime_mem;
bool d3hot_after_power_off;
+ bool interrupt_clear_with_0;
};
struct ivpu_hw_info;
diff --git a/drivers/accel/ivpu/ivpu_gem.c b/drivers/accel/ivpu/ivpu_gem.c
index 52b339aefadc..9967fcfa27ec 100644
--- a/drivers/accel/ivpu/ivpu_gem.c
+++ b/drivers/accel/ivpu/ivpu_gem.c
@@ -173,6 +173,9 @@ static void internal_free_pages_locked(struct ivpu_bo *bo)
{
unsigned int i, npages = bo->base.size >> PAGE_SHIFT;
+ if (ivpu_bo_cache_mode(bo) != DRM_IVPU_BO_CACHED)
+ set_pages_array_wb(bo->pages, bo->base.size >> PAGE_SHIFT);
+
for (i = 0; i < npages; i++)
put_page(bo->pages[i]);
@@ -587,6 +590,11 @@ ivpu_bo_alloc_internal(struct ivpu_device *vdev, u64 vpu_addr, u64 size, u32 fla
if (ivpu_bo_cache_mode(bo) != DRM_IVPU_BO_CACHED)
drm_clflush_pages(bo->pages, bo->base.size >> PAGE_SHIFT);
+ if (bo->flags & DRM_IVPU_BO_WC)
+ set_pages_array_wc(bo->pages, bo->base.size >> PAGE_SHIFT);
+ else if (bo->flags & DRM_IVPU_BO_UNCACHED)
+ set_pages_array_uc(bo->pages, bo->base.size >> PAGE_SHIFT);
+
prot = ivpu_bo_pgprot(bo, PAGE_KERNEL);
bo->kvaddr = vmap(bo->pages, bo->base.size >> PAGE_SHIFT, VM_MAP, prot);
if (!bo->kvaddr) {
diff --git a/drivers/accel/ivpu/ivpu_hw_mtl.c b/drivers/accel/ivpu/ivpu_hw_mtl.c
index fef35422c6f0..2a5dd3a5dc46 100644
--- a/drivers/accel/ivpu/ivpu_hw_mtl.c
+++ b/drivers/accel/ivpu/ivpu_hw_mtl.c
@@ -101,6 +101,9 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev)
vdev->wa.punit_disabled = ivpu_is_fpga(vdev);
vdev->wa.clear_runtime_mem = false;
vdev->wa.d3hot_after_power_off = true;
+
+ if (ivpu_device_id(vdev) == PCI_DEVICE_ID_MTL && ivpu_revision(vdev) < 4)
+ vdev->wa.interrupt_clear_with_0 = true;
}
static void ivpu_hw_timeouts_init(struct ivpu_device *vdev)
@@ -885,7 +888,7 @@ static void ivpu_hw_mtl_irq_disable(struct ivpu_device *vdev)
REGB_WR32(MTL_BUTTRESS_GLOBAL_INT_MASK, 0x1);
REGB_WR32(MTL_BUTTRESS_LOCAL_INT_MASK, BUTTRESS_IRQ_DISABLE_MASK);
REGV_WR64(MTL_VPU_HOST_SS_ICB_ENABLE_0, 0x0ull);
- REGB_WR32(MTL_VPU_HOST_SS_FW_SOC_IRQ_EN, 0x0);
+ REGV_WR32(MTL_VPU_HOST_SS_FW_SOC_IRQ_EN, 0x0);
}
static void ivpu_hw_mtl_irq_wdt_nce_handler(struct ivpu_device *vdev)
@@ -973,12 +976,15 @@ static u32 ivpu_hw_mtl_irqb_handler(struct ivpu_device *vdev, int irq)
schedule_recovery = true;
}
- /*
- * Clear local interrupt status by writing 0 to all bits.
- * This must be done after interrupts are cleared at the source.
- * Writing 1 triggers an interrupt, so we can't perform read update write.
- */
- REGB_WR32(MTL_BUTTRESS_INTERRUPT_STAT, 0x0);
+ /* This must be done after interrupts are cleared at the source. */
+ if (IVPU_WA(interrupt_clear_with_0))
+ /*
+ * Writing 1 triggers an interrupt, so we can't perform read update write.
+ * Clear local interrupt status by writing 0 to all bits.
+ */
+ REGB_WR32(MTL_BUTTRESS_INTERRUPT_STAT, 0x0);
+ else
+ REGB_WR32(MTL_BUTTRESS_INTERRUPT_STAT, status);
/* Re-enable global interrupt */
REGB_WR32(MTL_BUTTRESS_GLOBAL_INT_MASK, 0x0);
diff --git a/drivers/accel/qaic/qaic_control.c b/drivers/accel/qaic/qaic_control.c
index 5c57f7b4494e..388abd40024b 100644
--- a/drivers/accel/qaic/qaic_control.c
+++ b/drivers/accel/qaic/qaic_control.c
@@ -14,6 +14,7 @@
#include <linux/mm.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
+#include <linux/overflow.h>
#include <linux/pci.h>
#include <linux/scatterlist.h>
#include <linux/types.h>
@@ -366,7 +367,7 @@ static int encode_passthrough(struct qaic_device *qdev, void *trans, struct wrap
if (in_trans->hdr.len % 8 != 0)
return -EINVAL;
- if (msg_hdr_len + in_trans->hdr.len > QAIC_MANAGE_EXT_MSG_LENGTH)
+ if (size_add(msg_hdr_len, in_trans->hdr.len) > QAIC_MANAGE_EXT_MSG_LENGTH)
return -ENOSPC;
trans_wrapper = add_wrapper(wrappers,
@@ -391,18 +392,31 @@ static int find_and_map_user_pages(struct qaic_device *qdev,
struct qaic_manage_trans_dma_xfer *in_trans,
struct ioctl_resources *resources, struct dma_xfer *xfer)
{
+ u64 xfer_start_addr, remaining, end, total;
unsigned long need_pages;
struct page **page_list;
unsigned long nr_pages;
struct sg_table *sgt;
- u64 xfer_start_addr;
int ret;
int i;
- xfer_start_addr = in_trans->addr + resources->xferred_dma_size;
+ if (check_add_overflow(in_trans->addr, resources->xferred_dma_size, &xfer_start_addr))
+ return -EINVAL;
- need_pages = DIV_ROUND_UP(in_trans->size + offset_in_page(xfer_start_addr) -
- resources->xferred_dma_size, PAGE_SIZE);
+ if (in_trans->size < resources->xferred_dma_size)
+ return -EINVAL;
+ remaining = in_trans->size - resources->xferred_dma_size;
+ if (remaining == 0)
+ return 0;
+
+ if (check_add_overflow(xfer_start_addr, remaining, &end))
+ return -EINVAL;
+
+ total = remaining + offset_in_page(xfer_start_addr);
+ if (total >= SIZE_MAX)
+ return -EINVAL;
+
+ need_pages = DIV_ROUND_UP(total, PAGE_SIZE);
nr_pages = need_pages;
@@ -418,9 +432,12 @@ static int find_and_map_user_pages(struct qaic_device *qdev,
}
ret = get_user_pages_fast(xfer_start_addr, nr_pages, 0, page_list);
- if (ret < 0 || ret != nr_pages) {
- ret = -EFAULT;
+ if (ret < 0)
goto free_page_list;
+ if (ret != nr_pages) {
+ nr_pages = ret;
+ ret = -EFAULT;
+ goto put_pages;
}
sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
@@ -431,7 +448,7 @@ static int find_and_map_user_pages(struct qaic_device *qdev,
ret = sg_alloc_table_from_pages(sgt, page_list, nr_pages,
offset_in_page(xfer_start_addr),
- in_trans->size - resources->xferred_dma_size, GFP_KERNEL);
+ remaining, GFP_KERNEL);
if (ret) {
ret = -ENOMEM;
goto free_sgt;
@@ -557,17 +574,11 @@ static int encode_dma(struct qaic_device *qdev, void *trans, struct wrapper_list
msg = &wrapper->msg;
msg_hdr_len = le32_to_cpu(msg->hdr.len);
- if (msg_hdr_len > (UINT_MAX - QAIC_MANAGE_EXT_MSG_LENGTH))
- return -EINVAL;
-
/* There should be enough space to hold at least one ASP entry. */
- if (msg_hdr_len + sizeof(*out_trans) + sizeof(struct wire_addr_size_pair) >
+ if (size_add(msg_hdr_len, sizeof(*out_trans) + sizeof(struct wire_addr_size_pair)) >
QAIC_MANAGE_EXT_MSG_LENGTH)
return -ENOMEM;
- if (in_trans->addr + in_trans->size < in_trans->addr || !in_trans->size)
- return -EINVAL;
-
xfer = kmalloc(sizeof(*xfer), GFP_KERNEL);
if (!xfer)
return -ENOMEM;
@@ -634,7 +645,7 @@ static int encode_activate(struct qaic_device *qdev, void *trans, struct wrapper
msg = &wrapper->msg;
msg_hdr_len = le32_to_cpu(msg->hdr.len);
- if (msg_hdr_len + sizeof(*out_trans) > QAIC_MANAGE_MAX_MSG_LENGTH)
+ if (size_add(msg_hdr_len, sizeof(*out_trans)) > QAIC_MANAGE_MAX_MSG_LENGTH)
return -ENOSPC;
if (!in_trans->queue_size)
@@ -718,7 +729,7 @@ static int encode_status(struct qaic_device *qdev, void *trans, struct wrapper_l
msg = &wrapper->msg;
msg_hdr_len = le32_to_cpu(msg->hdr.len);
- if (msg_hdr_len + in_trans->hdr.len > QAIC_MANAGE_MAX_MSG_LENGTH)
+ if (size_add(msg_hdr_len, in_trans->hdr.len) > QAIC_MANAGE_MAX_MSG_LENGTH)
return -ENOSPC;
trans_wrapper = add_wrapper(wrappers, sizeof(*trans_wrapper));
@@ -748,7 +759,8 @@ static int encode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
int ret;
int i;
- if (!user_msg->count) {
+ if (!user_msg->count ||
+ user_msg->len < sizeof(*trans_hdr)) {
ret = -EINVAL;
goto out;
}
@@ -765,12 +777,13 @@ static int encode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
}
for (i = 0; i < user_msg->count; ++i) {
- if (user_len >= user_msg->len) {
+ if (user_len > user_msg->len - sizeof(*trans_hdr)) {
ret = -EINVAL;
break;
}
trans_hdr = (struct qaic_manage_trans_hdr *)(user_msg->data + user_len);
- if (user_len + trans_hdr->len > user_msg->len) {
+ if (trans_hdr->len < sizeof(trans_hdr) ||
+ size_add(user_len, trans_hdr->len) > user_msg->len) {
ret = -EINVAL;
break;
}
@@ -953,15 +966,23 @@ static int decode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
int ret;
int i;
- if (msg_hdr_len > QAIC_MANAGE_MAX_MSG_LENGTH)
+ if (msg_hdr_len < sizeof(*trans_hdr) ||
+ msg_hdr_len > QAIC_MANAGE_MAX_MSG_LENGTH)
return -EINVAL;
user_msg->len = 0;
user_msg->count = le32_to_cpu(msg->hdr.count);
for (i = 0; i < user_msg->count; ++i) {
+ u32 hdr_len;
+
+ if (msg_len > msg_hdr_len - sizeof(*trans_hdr))
+ return -EINVAL;
+
trans_hdr = (struct wire_trans_hdr *)(msg->data + msg_len);
- if (msg_len + le32_to_cpu(trans_hdr->len) > msg_hdr_len)
+ hdr_len = le32_to_cpu(trans_hdr->len);
+ if (hdr_len < sizeof(*trans_hdr) ||
+ size_add(msg_len, hdr_len) > msg_hdr_len)
return -EINVAL;
switch (le32_to_cpu(trans_hdr->type)) {
diff --git a/drivers/accel/qaic/qaic_data.c b/drivers/accel/qaic/qaic_data.c
index e9a1cb779b30..6b6d981a71be 100644
--- a/drivers/accel/qaic/qaic_data.c
+++ b/drivers/accel/qaic/qaic_data.c
@@ -1021,6 +1021,7 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
bo->dbc = dbc;
srcu_read_unlock(&dbc->ch_lock, rcu_id);
drm_gem_object_put(obj);
+ kfree(slice_ent);
srcu_read_unlock(&qdev->dev_lock, qdev_rcu_id);
srcu_read_unlock(&usr->qddev_lock, usr_rcu_id);
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/acpi_ffh.c b/drivers/acpi/acpi_ffh.c
index 19aff808bbb8..8d5126963dc7 100644
--- a/drivers/acpi/acpi_ffh.c
+++ b/drivers/acpi/acpi_ffh.c
@@ -9,8 +9,6 @@
#include <linux/idr.h>
#include <linux/io.h>
-#include <linux/arm-smccc.h>
-
static struct acpi_ffh_info ffh_ctx;
int __weak acpi_ffh_address_space_arch_setup(void *handler_ctxt,
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index 77186f084d3a..539e700de4d2 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -201,11 +201,19 @@ static void byt_i2c_setup(struct lpss_private_data *pdata)
writel(0, pdata->mmio_base + LPSS_I2C_ENABLE);
}
-/* BSW PWM used for backlight control by the i915 driver */
+/*
+ * BSW PWM1 is used for backlight control by the i915 driver
+ * BSW PWM2 is used for backlight control for fixed (etched into the glass)
+ * touch controls on some models. These touch-controls have specialized
+ * drivers which know they need the "pwm_soc_lpss_2" con-id.
+ */
static struct pwm_lookup bsw_pwm_lookup[] = {
PWM_LOOKUP_WITH_MODULE("80862288:00", 0, "0000:00:02.0",
"pwm_soc_backlight", 0, PWM_POLARITY_NORMAL,
"pwm-lpss-platform"),
+ PWM_LOOKUP_WITH_MODULE("80862289:00", 0, NULL,
+ "pwm_soc_lpss_2", 0, PWM_POLARITY_NORMAL,
+ "pwm-lpss-platform"),
};
static void bsw_pwm_setup(struct lpss_private_data *pdata)
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index 02f1a1b1143c..7a453c5ff303 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -66,6 +66,7 @@ static void power_saving_mwait_init(void)
case X86_VENDOR_AMD:
case X86_VENDOR_INTEL:
case X86_VENDOR_ZHAOXIN:
+ case X86_VENDOR_CENTAUR:
/*
* AMD Fam10h TSC will tick in all
* C/P/S0/S1 states when this bit is set.
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c
index fe00a5783f53..48d15dd785f6 100644
--- a/drivers/acpi/acpi_platform.c
+++ b/drivers/acpi/acpi_platform.c
@@ -9,6 +9,7 @@
*/
#include <linux/acpi.h>
+#include <linux/bits.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/kernel.h>
@@ -19,13 +20,16 @@
#include "internal.h"
+/* Exclude devices that have no _CRS resources provided */
+#define ACPI_ALLOW_WO_RESOURCES BIT(0)
+
static const struct acpi_device_id forbidden_id_list[] = {
{"ACPI0009", 0}, /* IOxAPIC */
{"ACPI000A", 0}, /* IOAPIC */
{"PNP0000", 0}, /* PIC */
{"PNP0100", 0}, /* Timer */
{"PNP0200", 0}, /* AT DMA Controller */
- {"SMB0001", 0}, /* ACPI SMBUS virtual device */
+ {ACPI_SMBUS_MS_HID, ACPI_ALLOW_WO_RESOURCES}, /* ACPI SMBUS virtual device */
{ }
};
@@ -83,6 +87,15 @@ static void acpi_platform_fill_resource(struct acpi_device *adev,
dest->parent = pci_find_resource(to_pci_dev(parent), dest);
}
+static unsigned int acpi_platform_resource_count(struct acpi_resource *ares, void *data)
+{
+ bool *has_resources = data;
+
+ *has_resources = true;
+
+ return AE_CTRL_TERMINATE;
+}
+
/**
* acpi_create_platform_device - Create platform device for ACPI device node
* @adev: ACPI device node to create a platform device for.
@@ -100,6 +113,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
struct acpi_device *parent = acpi_dev_parent(adev);
struct platform_device *pdev = NULL;
struct platform_device_info pdevinfo;
+ const struct acpi_device_id *match;
struct resource_entry *rentry;
struct list_head resource_list;
struct resource *resources = NULL;
@@ -109,8 +123,19 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
if (adev->physical_node_count)
return NULL;
- if (!acpi_match_device_ids(adev, forbidden_id_list))
- return ERR_PTR(-EINVAL);
+ match = acpi_match_acpi_device(forbidden_id_list, adev);
+ if (match) {
+ if (match->driver_data & ACPI_ALLOW_WO_RESOURCES) {
+ bool has_resources = false;
+
+ acpi_walk_resources(adev->handle, METHOD_NAME__CRS,
+ acpi_platform_resource_count, &has_resources);
+ if (has_resources)
+ return ERR_PTR(-EINVAL);
+ } else {
+ return ERR_PTR(-EINVAL);
+ }
+ }
INIT_LIST_HEAD(&resource_list);
count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
diff --git a/drivers/acpi/apei/bert.c b/drivers/acpi/apei/bert.c
index 7514e38d5640..5427e49e646b 100644
--- a/drivers/acpi/apei/bert.c
+++ b/drivers/acpi/apei/bert.c
@@ -34,7 +34,7 @@
#define ACPI_BERT_PRINT_MAX_RECORDS 5
#define ACPI_BERT_PRINT_MAX_LEN 1024
-static int bert_disable;
+static int bert_disable __initdata;
/*
* Print "all" the error records in the BERT table, but avoid huge spam to
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 34ad071a64e9..ef59d6ea16da 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -152,7 +152,6 @@ struct ghes_vendor_record_entry {
};
static struct gen_pool *ghes_estatus_pool;
-static unsigned long ghes_estatus_pool_size_request;
static struct ghes_estatus_cache __rcu *ghes_estatus_caches[GHES_ESTATUS_CACHES_SIZE];
static atomic_t ghes_estatus_cache_alloced;
@@ -191,7 +190,6 @@ int ghes_estatus_pool_init(unsigned int num_ghes)
len = GHES_ESTATUS_CACHE_AVG_SIZE * GHES_ESTATUS_CACHE_ALLOCED_MAX;
len += (num_ghes * GHES_ESOURCE_PREALLOC_MAX_SIZE);
- ghes_estatus_pool_size_request = PAGE_ALIGN(len);
addr = (unsigned long)vmalloc(PAGE_ALIGN(len));
if (!addr)
goto err_pool_alloc;
@@ -1544,6 +1542,8 @@ struct list_head *ghes_get_devices(void)
pr_warn_once("Force-loading ghes_edac on an unsupported platform. You're on your own!\n");
}
+ } else if (list_empty(&ghes_devs)) {
+ return NULL;
}
return &ghes_devs;
diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
index e21a9e84e394..f81fe24894b2 100644
--- a/drivers/acpi/arm64/Makefile
+++ b/drivers/acpi/arm64/Makefile
@@ -3,4 +3,4 @@ obj-$(CONFIG_ACPI_AGDI) += agdi.o
obj-$(CONFIG_ACPI_IORT) += iort.o
obj-$(CONFIG_ACPI_GTDT) += gtdt.o
obj-$(CONFIG_ACPI_APMT) += apmt.o
-obj-y += dma.o
+obj-y += dma.o init.o
diff --git a/drivers/acpi/arm64/agdi.c b/drivers/acpi/arm64/agdi.c
index f605302395c3..8b3c7d42b41b 100644
--- a/drivers/acpi/arm64/agdi.c
+++ b/drivers/acpi/arm64/agdi.c
@@ -9,11 +9,11 @@
#define pr_fmt(fmt) "ACPI: AGDI: " fmt
#include <linux/acpi.h>
-#include <linux/acpi_agdi.h>
#include <linux/arm_sdei.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
+#include "init.h"
struct agdi_data {
int sdei_event;
diff --git a/drivers/acpi/arm64/apmt.c b/drivers/acpi/arm64/apmt.c
index 8cab69fa5d59..bb010f6164e5 100644
--- a/drivers/acpi/arm64/apmt.c
+++ b/drivers/acpi/arm64/apmt.c
@@ -10,10 +10,10 @@
#define pr_fmt(fmt) "ACPI: APMT: " fmt
#include <linux/acpi.h>
-#include <linux/acpi_apmt.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
+#include "init.h"
#define DEV_NAME "arm-cs-arch-pmu"
@@ -35,11 +35,13 @@ static int __init apmt_init_resources(struct resource *res,
num_res++;
- res[num_res].start = node->base_address1;
- res[num_res].end = node->base_address1 + SZ_4K - 1;
- res[num_res].flags = IORESOURCE_MEM;
+ if (node->flags & ACPI_APMT_FLAGS_DUAL_PAGE) {
+ res[num_res].start = node->base_address1;
+ res[num_res].end = node->base_address1 + SZ_4K - 1;
+ res[num_res].flags = IORESOURCE_MEM;
- num_res++;
+ num_res++;
+ }
if (node->ovflw_irq != 0) {
trigger = (node->ovflw_irq_flags & ACPI_APMT_OVFLW_IRQ_FLAGS_MODE);
diff --git a/drivers/acpi/arm64/init.c b/drivers/acpi/arm64/init.c
new file mode 100644
index 000000000000..d3ce53dda122
--- /dev/null
+++ b/drivers/acpi/arm64/init.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/acpi.h>
+#include "init.h"
+
+void __init acpi_arm_init(void)
+{
+ if (IS_ENABLED(CONFIG_ACPI_AGDI))
+ acpi_agdi_init();
+ if (IS_ENABLED(CONFIG_ACPI_APMT))
+ acpi_apmt_init();
+ if (IS_ENABLED(CONFIG_ACPI_IORT))
+ acpi_iort_init();
+}
diff --git a/drivers/acpi/arm64/init.h b/drivers/acpi/arm64/init.h
new file mode 100644
index 000000000000..a1715a2a34e9
--- /dev/null
+++ b/drivers/acpi/arm64/init.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#include <linux/init.h>
+
+void __init acpi_agdi_init(void);
+void __init acpi_apmt_init(void);
+void __init acpi_iort_init(void);
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 38fb84974f35..56d887323ae5 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dma-map-ops.h>
+#include "init.h"
#define IORT_TYPE_MASK(type) (1 << (type))
#define IORT_MSI_TYPE (1 << ACPI_IORT_NODE_ITS_GROUP)
@@ -1006,9 +1007,6 @@ static void iort_node_get_rmr_info(struct acpi_iort_node *node,
for (i = 0; i < node->mapping_count; i++, map++) {
struct acpi_iort_node *parent;
- if (!map->id_count)
- continue;
-
parent = ACPI_ADD_PTR(struct acpi_iort_node, iort_table,
map->output_reference);
if (parent != iommu)
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index d161ff707de4..2fc2b43a4ed3 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -26,9 +26,6 @@
#include <asm/mpspec.h>
#include <linux/dmi.h>
#endif
-#include <linux/acpi_agdi.h>
-#include <linux/acpi_apmt.h>
-#include <linux/acpi_iort.h>
#include <linux/acpi_viot.h>
#include <linux/pci.h>
#include <acpi/apei.h>
@@ -530,65 +527,30 @@ static void acpi_notify_device(acpi_handle handle, u32 event, void *data)
acpi_drv->ops.notify(device, event);
}
-static void acpi_notify_device_fixed(void *data)
-{
- struct acpi_device *device = data;
-
- /* Fixed hardware devices have no handles */
- acpi_notify_device(NULL, ACPI_FIXED_HARDWARE_EVENT, device);
-}
-
-static u32 acpi_device_fixed_event(void *data)
-{
- acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_notify_device_fixed, data);
- return ACPI_INTERRUPT_HANDLED;
-}
-
static int acpi_device_install_notify_handler(struct acpi_device *device,
struct acpi_driver *acpi_drv)
{
- acpi_status status;
-
- if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) {
- status =
- acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
- acpi_device_fixed_event,
- device);
- } else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON) {
- status =
- acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
- acpi_device_fixed_event,
- device);
- } else {
- u32 type = acpi_drv->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS ?
+ u32 type = acpi_drv->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS ?
ACPI_ALL_NOTIFY : ACPI_DEVICE_NOTIFY;
+ acpi_status status;
- status = acpi_install_notify_handler(device->handle, type,
- acpi_notify_device,
- device);
- }
-
+ status = acpi_install_notify_handler(device->handle, type,
+ acpi_notify_device, device);
if (ACPI_FAILURE(status))
return -EINVAL;
+
return 0;
}
static void acpi_device_remove_notify_handler(struct acpi_device *device,
struct acpi_driver *acpi_drv)
{
- if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) {
- acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
- acpi_device_fixed_event);
- } else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON) {
- acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
- acpi_device_fixed_event);
- } else {
- u32 type = acpi_drv->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS ?
+ u32 type = acpi_drv->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS ?
ACPI_ALL_NOTIFY : ACPI_DEVICE_NOTIFY;
- acpi_remove_notify_handler(device->handle, type,
- acpi_notify_device);
- }
+ acpi_remove_notify_handler(device->handle, type,
+ acpi_notify_device);
+
acpi_os_wait_events_complete();
}
@@ -720,7 +682,7 @@ bool acpi_device_is_first_physical_node(struct acpi_device *adev,
* resources available from it but they will be matched normally using functions
* provided by their bus types (and analogously for their modalias).
*/
-struct acpi_device *acpi_companion_match(const struct device *dev)
+const struct acpi_device *acpi_companion_match(const struct device *dev)
{
struct acpi_device *adev;
@@ -744,7 +706,7 @@ struct acpi_device *acpi_companion_match(const struct device *dev)
* identifiers and a _DSD object with the "compatible" property, use that
* property to match against the given list of identifiers.
*/
-static bool acpi_of_match_device(struct acpi_device *adev,
+static bool acpi_of_match_device(const struct acpi_device *adev,
const struct of_device_id *of_match_table,
const struct of_device_id **of_id)
{
@@ -846,7 +808,7 @@ static bool __acpi_match_device_cls(const struct acpi_device_id *id,
return true;
}
-static bool __acpi_match_device(struct acpi_device *device,
+static bool __acpi_match_device(const struct acpi_device *device,
const struct acpi_device_id *acpi_ids,
const struct of_device_id *of_ids,
const struct acpi_device_id **acpi_id,
@@ -889,6 +851,26 @@ out_acpi_match:
}
/**
+ * acpi_match_acpi_device - Match an ACPI device against a given list of ACPI IDs
+ * @ids: Array of struct acpi_device_id objects to match against.
+ * @adev: The ACPI device pointer to match.
+ *
+ * Match the ACPI device @adev against a given list of ACPI IDs @ids.
+ *
+ * Return:
+ * a pointer to the first matching ACPI ID on success or %NULL on failure.
+ */
+const struct acpi_device_id *acpi_match_acpi_device(const struct acpi_device_id *ids,
+ const struct acpi_device *adev)
+{
+ const struct acpi_device_id *id = NULL;
+
+ __acpi_match_device(adev, ids, NULL, &id, NULL);
+ return id;
+}
+EXPORT_SYMBOL_GPL(acpi_match_acpi_device);
+
+/**
* acpi_match_device - Match a struct device against a given list of ACPI IDs
* @ids: Array of struct acpi_device_id object to match against.
* @dev: The device structure to match.
@@ -902,10 +884,7 @@ out_acpi_match:
const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
const struct device *dev)
{
- const struct acpi_device_id *id = NULL;
-
- __acpi_match_device(acpi_companion_match(dev), ids, NULL, &id, NULL);
- return id;
+ return acpi_match_acpi_device(ids, acpi_companion_match(dev));
}
EXPORT_SYMBOL_GPL(acpi_match_device);
@@ -1408,7 +1387,7 @@ static int __init acpi_init(void)
acpi_init_ffh();
pci_mmcfg_late_init();
- acpi_iort_init();
+ acpi_arm_init();
acpi_viot_early_init();
acpi_hest_init();
acpi_ghes_init();
@@ -1420,8 +1399,6 @@ static int __init acpi_init(void)
acpi_debugger_init();
acpi_setup_sb_notify_handler();
acpi_viot_init();
- acpi_agdi_init();
- acpi_apmt_init();
return 0;
}
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 475e1eddfa3b..1e76a64cce0a 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -78,6 +78,15 @@ static const struct dmi_system_id dmi_lid_quirks[] = {
.driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_DISABLED,
},
{
+ /* Nextbook Ares 8A tablet, _LID device always reports lid closed */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "CherryTrail"),
+ DMI_MATCH(DMI_BIOS_VERSION, "M882"),
+ },
+ .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_DISABLED,
+ },
+ {
/*
* Lenovo Yoga 9 14ITL5, initial notification of the LID device
* never happens.
@@ -126,7 +135,6 @@ static const struct dmi_system_id dmi_lid_quirks[] = {
static int acpi_button_add(struct acpi_device *device);
static void acpi_button_remove(struct acpi_device *device);
-static void acpi_button_notify(struct acpi_device *device, u32 event);
#ifdef CONFIG_PM_SLEEP
static int acpi_button_suspend(struct device *dev);
@@ -144,7 +152,6 @@ static struct acpi_driver acpi_button_driver = {
.ops = {
.add = acpi_button_add,
.remove = acpi_button_remove,
- .notify = acpi_button_notify,
},
.drv.pm = &acpi_button_pm,
};
@@ -400,45 +407,65 @@ static void acpi_lid_initialize_state(struct acpi_device *device)
button->lid_state_initialized = true;
}
-static void acpi_button_notify(struct acpi_device *device, u32 event)
+static void acpi_lid_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_button *button = acpi_driver_data(device);
+ struct acpi_device *device = data;
+ struct acpi_button *button;
+
+ if (event != ACPI_BUTTON_NOTIFY_STATUS) {
+ acpi_handle_debug(device->handle, "Unsupported event [0x%x]\n",
+ event);
+ return;
+ }
+
+ button = acpi_driver_data(device);
+ if (!button->lid_state_initialized)
+ return;
+
+ acpi_lid_update_state(device, true);
+}
+
+static void acpi_button_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct acpi_device *device = data;
+ struct acpi_button *button;
struct input_dev *input;
+ int keycode;
- switch (event) {
- case ACPI_FIXED_HARDWARE_EVENT:
- event = ACPI_BUTTON_NOTIFY_STATUS;
- fallthrough;
- case ACPI_BUTTON_NOTIFY_STATUS:
- input = button->input;
- if (button->type == ACPI_BUTTON_TYPE_LID) {
- if (button->lid_state_initialized)
- acpi_lid_update_state(device, true);
- } else {
- int keycode;
-
- acpi_pm_wakeup_event(&device->dev);
- if (button->suspended)
- break;
-
- keycode = test_bit(KEY_SLEEP, input->keybit) ?
- KEY_SLEEP : KEY_POWER;
- input_report_key(input, keycode, 1);
- input_sync(input);
- input_report_key(input, keycode, 0);
- input_sync(input);
-
- acpi_bus_generate_netlink_event(
- device->pnp.device_class,
- dev_name(&device->dev),
- event, ++button->pushed);
- }
- break;
- default:
+ if (event != ACPI_BUTTON_NOTIFY_STATUS) {
acpi_handle_debug(device->handle, "Unsupported event [0x%x]\n",
event);
- break;
+ return;
}
+
+ acpi_pm_wakeup_event(&device->dev);
+
+ button = acpi_driver_data(device);
+ if (button->suspended)
+ return;
+
+ input = button->input;
+ keycode = test_bit(KEY_SLEEP, input->keybit) ? KEY_SLEEP : KEY_POWER;
+
+ input_report_key(input, keycode, 1);
+ input_sync(input);
+ input_report_key(input, keycode, 0);
+ input_sync(input);
+
+ acpi_bus_generate_netlink_event(device->pnp.device_class,
+ dev_name(&device->dev),
+ event, ++button->pushed);
+}
+
+static void acpi_button_notify_run(void *data)
+{
+ acpi_button_notify(NULL, ACPI_BUTTON_NOTIFY_STATUS, data);
+}
+
+static u32 acpi_button_event(void *data)
+{
+ acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_button_notify_run, data);
+ return ACPI_INTERRUPT_HANDLED;
}
#ifdef CONFIG_PM_SLEEP
@@ -480,11 +507,13 @@ static int acpi_lid_input_open(struct input_dev *input)
static int acpi_button_add(struct acpi_device *device)
{
+ acpi_notify_handler handler;
struct acpi_button *button;
struct input_dev *input;
const char *hid = acpi_device_hid(device);
+ acpi_status status;
char *name, *class;
- int error;
+ int error = 0;
if (!strcmp(hid, ACPI_BUTTON_HID_LID) &&
lid_init_state == ACPI_BUTTON_LID_INIT_DISABLED)
@@ -508,17 +537,20 @@ static int acpi_button_add(struct acpi_device *device)
if (!strcmp(hid, ACPI_BUTTON_HID_POWER) ||
!strcmp(hid, ACPI_BUTTON_HID_POWERF)) {
button->type = ACPI_BUTTON_TYPE_POWER;
+ handler = acpi_button_notify;
strcpy(name, ACPI_BUTTON_DEVICE_NAME_POWER);
sprintf(class, "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
} else if (!strcmp(hid, ACPI_BUTTON_HID_SLEEP) ||
!strcmp(hid, ACPI_BUTTON_HID_SLEEPF)) {
button->type = ACPI_BUTTON_TYPE_SLEEP;
+ handler = acpi_button_notify;
strcpy(name, ACPI_BUTTON_DEVICE_NAME_SLEEP);
sprintf(class, "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
} else if (!strcmp(hid, ACPI_BUTTON_HID_LID)) {
button->type = ACPI_BUTTON_TYPE_LID;
+ handler = acpi_lid_notify;
strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
sprintf(class, "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
@@ -526,12 +558,15 @@ static int acpi_button_add(struct acpi_device *device)
} else {
pr_info("Unsupported hid [%s]\n", hid);
error = -ENODEV;
- goto err_free_input;
}
- error = acpi_button_add_fs(device);
- if (error)
- goto err_free_input;
+ if (!error)
+ error = acpi_button_add_fs(device);
+
+ if (error) {
+ input_free_device(input);
+ goto err_free_button;
+ }
snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid);
@@ -559,6 +594,29 @@ static int acpi_button_add(struct acpi_device *device)
error = input_register_device(input);
if (error)
goto err_remove_fs;
+
+ switch (device->device_type) {
+ case ACPI_BUS_TYPE_POWER_BUTTON:
+ status = acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+ acpi_button_event,
+ device);
+ break;
+ case ACPI_BUS_TYPE_SLEEP_BUTTON:
+ status = acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
+ acpi_button_event,
+ device);
+ break;
+ default:
+ status = acpi_install_notify_handler(device->handle,
+ ACPI_DEVICE_NOTIFY, handler,
+ device);
+ break;
+ }
+ if (ACPI_FAILURE(status)) {
+ error = -ENODEV;
+ goto err_input_unregister;
+ }
+
if (button->type == ACPI_BUTTON_TYPE_LID) {
/*
* This assumes there's only one lid device, or if there are
@@ -571,11 +629,11 @@ static int acpi_button_add(struct acpi_device *device)
pr_info("%s [%s]\n", name, acpi_device_bid(device));
return 0;
- err_remove_fs:
+err_input_unregister:
+ input_unregister_device(input);
+err_remove_fs:
acpi_button_remove_fs(device);
- err_free_input:
- input_free_device(input);
- err_free_button:
+err_free_button:
kfree(button);
return error;
}
@@ -584,6 +642,24 @@ static void acpi_button_remove(struct acpi_device *device)
{
struct acpi_button *button = acpi_driver_data(device);
+ switch (device->device_type) {
+ case ACPI_BUS_TYPE_POWER_BUTTON:
+ acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+ acpi_button_event);
+ break;
+ case ACPI_BUS_TYPE_SLEEP_BUTTON:
+ acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
+ acpi_button_event);
+ break;
+ default:
+ acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
+ button->type == ACPI_BUTTON_TYPE_LID ?
+ acpi_lid_notify :
+ acpi_button_notify);
+ break;
+ }
+ acpi_os_wait_events_complete();
+
acpi_button_remove_fs(device);
input_unregister_device(button->input);
kfree(button);
diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c
index 0fbfbaa8d8e3..b9bbf0746199 100644
--- a/drivers/acpi/device_sysfs.c
+++ b/drivers/acpi/device_sysfs.c
@@ -283,7 +283,7 @@ int acpi_device_uevent_modalias(const struct device *dev, struct kobj_uevent_env
}
EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);
-static int __acpi_device_modalias(struct acpi_device *adev, char *buf, int size)
+static int __acpi_device_modalias(const struct acpi_device *adev, char *buf, int size)
{
int len, count;
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 928899ab9502..660834a49c1f 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -662,21 +662,6 @@ static void advance_transaction(struct acpi_ec *ec, bool interrupt)
ec_dbg_stm("%s (%d)", interrupt ? "IRQ" : "TASK", smp_processor_id());
- /*
- * Clear GPE_STS upfront to allow subsequent hardware GPE_STS 0->1
- * changes to always trigger a GPE interrupt.
- *
- * GPE STS is a W1C register, which means:
- *
- * 1. Software can clear it without worrying about clearing the other
- * GPEs' STS bits when the hardware sets them in parallel.
- *
- * 2. As long as software can ensure only clearing it when it is set,
- * hardware won't set it in parallel.
- */
- if (ec->gpe >= 0 && acpi_ec_gpe_status_set(ec))
- acpi_clear_gpe(NULL, ec->gpe);
-
status = acpi_ec_read_status(ec);
/*
@@ -1282,12 +1267,34 @@ static void acpi_ec_event_handler(struct work_struct *work)
spin_unlock_irq(&ec->lock);
}
+static void clear_gpe_and_advance_transaction(struct acpi_ec *ec, bool interrupt)
+{
+ /*
+ * Clear GPE_STS upfront to allow subsequent hardware GPE_STS 0->1
+ * changes to always trigger a GPE interrupt.
+ *
+ * GPE STS is a W1C register, which means:
+ *
+ * 1. Software can clear it without worrying about clearing the other
+ * GPEs' STS bits when the hardware sets them in parallel.
+ *
+ * 2. As long as software can ensure only clearing it when it is set,
+ * hardware won't set it in parallel.
+ */
+ if (ec->gpe >= 0 && acpi_ec_gpe_status_set(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);
- advance_transaction(ec, true);
+
+ clear_gpe_and_advance_transaction(ec, true);
+
spin_unlock_irqrestore(&ec->lock, flags);
}
@@ -2082,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/internal.h b/drivers/acpi/internal.h
index 06ad497067ac..f4148dc50b9c 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -11,6 +11,8 @@
#include <linux/idr.h>
+extern struct acpi_device *acpi_root;
+
int early_acpi_osi_init(void);
int acpi_osi_init(void);
acpi_status acpi_os_initialize1(void);
@@ -119,7 +121,7 @@ int acpi_bus_register_early_device(int type);
/* --------------------------------------------------------------------------
Device Matching and Notification
-------------------------------------------------------------------------- */
-struct acpi_device *acpi_companion_match(const struct device *dev);
+const struct acpi_device *acpi_companion_match(const struct device *dev);
int __acpi_device_uevent_modalias(const struct acpi_device *adev,
struct kobj_uevent_env *env);
diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h
index 6023ad61831a..573bc0de2990 100644
--- a/drivers/acpi/nfit/nfit.h
+++ b/drivers/acpi/nfit/nfit.h
@@ -347,4 +347,6 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev);
bool intel_fwa_supported(struct nvdimm_bus *nvdimm_bus);
extern struct device_attribute dev_attr_firmware_activate_noidle;
+void nfit_intel_shutdown_status(struct nfit_mem *nfit_mem);
+
#endif /* __NFIT_H__ */
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/processor_idle.c b/drivers/acpi/processor_idle.c
index 9718d07cc2a2..dc615ef6550a 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -597,10 +597,6 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
io_idle(cx->address);
} else
return -ENODEV;
-
-#if defined(CONFIG_X86) && defined(CONFIG_HOTPLUG_CPU)
- cond_wakeup_cpu0();
-#endif
}
/* Never reached */
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 0800a9d77558..32cfa3f4efd3 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -470,24 +470,6 @@ static const struct dmi_system_id asus_laptop[] = {
{ }
};
-static const struct dmi_system_id lenovo_laptop[] = {
- {
- .ident = "LENOVO IdeaPad Flex 5 14ALC7",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "82R9"),
- },
- },
- {
- .ident = "LENOVO IdeaPad Flex 5 16ALC7",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "82RA"),
- },
- },
- { }
-};
-
static const struct dmi_system_id tongfang_gm_rg[] = {
{
.ident = "TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD",
@@ -516,6 +498,21 @@ static const struct dmi_system_id maingear_laptop[] = {
{ }
};
+static const struct dmi_system_id pcspecialist_laptop[] = {
+ {
+ .ident = "PCSpecialist Elimina Pro 16 M",
+ /*
+ * Some models have product-name "Elimina Pro 16 M",
+ * others "GM6BGEQ". Match on board-name to match both.
+ */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "PCSpecialist"),
+ DMI_MATCH(DMI_BOARD_NAME, "GM6BGEQ"),
+ },
+ },
+ { }
+};
+
static const struct dmi_system_id lg_laptop[] = {
{
.ident = "LG Electronics 17U70P",
@@ -539,10 +536,9 @@ struct irq_override_cmp {
static const struct irq_override_cmp override_table[] = {
{ medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
{ asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
- { lenovo_laptop, 6, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, true },
- { lenovo_laptop, 10, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, true },
{ tongfang_gm_rg, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
{ maingear_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
+ { pcspecialist_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
{ lg_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
};
@@ -564,6 +560,18 @@ static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity,
#ifdef CONFIG_X86
/*
+ * Always use the MADT override info, except for the i8042 PS/2 ctrl
+ * IRQs (1 and 12). For these the DSDT IRQ settings should sometimes
+ * be used otherwise PS/2 keyboards / mice will not work.
+ */
+ if (gsi != 1 && gsi != 12)
+ return true;
+
+ /* If the override comes from an INT_SRC_OVR MADT entry, honor it. */
+ if (acpi_int_src_ovr[gsi])
+ return true;
+
+ /*
* IRQ override isn't needed on modern AMD Zen systems and
* this override breaks active low IRQs on AMD Ryzen 6000 and
* newer systems. Skip it.
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/scan.c b/drivers/acpi/scan.c
index 0c6f06abe3f4..87e385542576 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -23,8 +23,7 @@
#include <linux/dma-direct.h>
#include "internal.h"
-
-extern struct acpi_device *acpi_root;
+#include "sleep.h"
#define ACPI_BUS_CLASS "system_bus"
#define ACPI_BUS_HID "LNXSYBUS"
@@ -930,26 +929,29 @@ static int acpi_bus_extract_wakeup_device_power_package(struct acpi_device *dev)
return err;
}
+/* Do not use a button for S5 wakeup */
+#define ACPI_AVOID_WAKE_FROM_S5 BIT(0)
+
static bool acpi_wakeup_gpe_init(struct acpi_device *device)
{
static const struct acpi_device_id button_device_ids[] = {
- {"PNP0C0C", 0}, /* Power button */
- {"PNP0C0D", 0}, /* Lid */
- {"PNP0C0E", 0}, /* Sleep button */
+ {"PNP0C0C", 0}, /* Power button */
+ {"PNP0C0D", ACPI_AVOID_WAKE_FROM_S5}, /* Lid */
+ {"PNP0C0E", ACPI_AVOID_WAKE_FROM_S5}, /* Sleep button */
{"", 0},
};
struct acpi_device_wakeup *wakeup = &device->wakeup;
+ const struct acpi_device_id *match;
acpi_status status;
wakeup->flags.notifier_present = 0;
/* Power button, Lid switch always enable wakeup */
- if (!acpi_match_device_ids(device, button_device_ids)) {
- if (!acpi_match_device_ids(device, &button_device_ids[1])) {
- /* Do not use Lid/sleep button for S5 wakeup */
- if (wakeup->sleep_state == ACPI_STATE_S5)
- wakeup->sleep_state = ACPI_STATE_S4;
- }
+ match = acpi_match_acpi_device(button_device_ids, device);
+ if (match) {
+ if ((match->driver_data & ACPI_AVOID_WAKE_FROM_S5) &&
+ wakeup->sleep_state == ACPI_STATE_S5)
+ wakeup->sleep_state = ACPI_STATE_S4;
acpi_mark_gpe_for_wake(wakeup->gpe_device, wakeup->gpe_number);
device_set_wakeup_capable(&device->dev, true);
return true;
@@ -1712,6 +1714,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
{"BSG1160", },
{"BSG2150", },
{"CSC3551", },
+ {"CSC3556", },
{"INT33FE", },
{"INT3515", },
/* Non-conforming _HID for Cirrus Logic already released */
@@ -2029,8 +2032,6 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
return count;
}
-static bool acpi_bus_scan_second_pass;
-
static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep,
struct acpi_device **adev_p)
{
@@ -2050,10 +2051,8 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep,
return AE_OK;
/* Bail out if there are dependencies. */
- if (acpi_scan_check_dep(handle, check_dep) > 0) {
- acpi_bus_scan_second_pass = true;
+ if (acpi_scan_check_dep(handle, check_dep) > 0)
return AE_CTRL_DEPTH;
- }
fallthrough;
case ACPI_TYPE_ANY: /* for ACPI_ROOT_OBJECT */
@@ -2301,6 +2300,12 @@ static bool acpi_scan_clear_dep_queue(struct acpi_device *adev)
return true;
}
+static void acpi_scan_delete_dep_data(struct acpi_dep_data *dep)
+{
+ list_del(&dep->node);
+ kfree(dep);
+}
+
static int acpi_scan_clear_dep(struct acpi_dep_data *dep, void *data)
{
struct acpi_device *adev = acpi_get_acpi_dev(dep->consumer);
@@ -2311,8 +2316,10 @@ static int acpi_scan_clear_dep(struct acpi_dep_data *dep, void *data)
acpi_dev_put(adev);
}
- list_del(&dep->node);
- kfree(dep);
+ if (dep->free_when_met)
+ acpi_scan_delete_dep_data(dep);
+ else
+ dep->met = true;
return 0;
}
@@ -2406,6 +2413,55 @@ struct acpi_device *acpi_dev_get_next_consumer_dev(struct acpi_device *supplier,
}
EXPORT_SYMBOL_GPL(acpi_dev_get_next_consumer_dev);
+static void acpi_scan_postponed_branch(acpi_handle handle)
+{
+ struct acpi_device *adev = NULL;
+
+ if (ACPI_FAILURE(acpi_bus_check_add(handle, false, &adev)))
+ return;
+
+ acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
+ acpi_bus_check_add_2, NULL, NULL, (void **)&adev);
+ acpi_bus_attach(adev, NULL);
+}
+
+static void acpi_scan_postponed(void)
+{
+ struct acpi_dep_data *dep, *tmp;
+
+ mutex_lock(&acpi_dep_list_lock);
+
+ list_for_each_entry_safe(dep, tmp, &acpi_dep_list, node) {
+ acpi_handle handle = dep->consumer;
+
+ /*
+ * In case there are multiple acpi_dep_list entries with the
+ * same consumer, skip the current entry if the consumer device
+ * object corresponding to it is present already.
+ */
+ if (!acpi_fetch_acpi_dev(handle)) {
+ /*
+ * Even though the lock is released here, tmp is
+ * guaranteed to be valid, because none of the list
+ * entries following dep is marked as "free when met"
+ * and so they cannot be deleted.
+ */
+ mutex_unlock(&acpi_dep_list_lock);
+
+ acpi_scan_postponed_branch(handle);
+
+ mutex_lock(&acpi_dep_list_lock);
+ }
+
+ if (dep->met)
+ acpi_scan_delete_dep_data(dep);
+ else
+ dep->free_when_met = true;
+ }
+
+ mutex_unlock(&acpi_dep_list_lock);
+}
+
/**
* acpi_bus_scan - Add ACPI device node objects in a given namespace scope.
* @handle: Root of the namespace scope to scan.
@@ -2424,8 +2480,6 @@ int acpi_bus_scan(acpi_handle handle)
{
struct acpi_device *device = NULL;
- acpi_bus_scan_second_pass = false;
-
/* Pass 1: Avoid enumerating devices with missing dependencies. */
if (ACPI_SUCCESS(acpi_bus_check_add(handle, true, &device)))
@@ -2438,19 +2492,9 @@ int acpi_bus_scan(acpi_handle handle)
acpi_bus_attach(device, (void *)true);
- if (!acpi_bus_scan_second_pass)
- return 0;
-
/* Pass 2: Enumerate all of the remaining devices. */
- device = NULL;
-
- if (ACPI_SUCCESS(acpi_bus_check_add(handle, false, &device)))
- acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
- acpi_bus_check_add_2, NULL, NULL,
- (void **)&device);
-
- acpi_bus_attach(device, NULL);
+ acpi_scan_postponed();
return 0;
}
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index f32570f72b90..808484d11209 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -848,7 +848,7 @@ void __weak acpi_s2idle_setup(void)
s2idle_set_ops(&acpi_s2idle_ops);
}
-static void acpi_sleep_suspend_setup(void)
+static void __init acpi_sleep_suspend_setup(void)
{
bool suspend_ops_needed = false;
int i;
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/acpi/thermal.c b/drivers/acpi/thermal.c
index 4720a3649a61..f9f6ebb08fdb 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -40,12 +40,35 @@
#define ACPI_THERMAL_NOTIFY_HOT 0xF1
#define ACPI_THERMAL_MODE_ACTIVE 0x00
-#define ACPI_THERMAL_MAX_ACTIVE 10
-#define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
+#define ACPI_THERMAL_MAX_ACTIVE 10
+#define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
-MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
-MODULE_LICENSE("GPL");
+#define ACPI_TRIPS_CRITICAL BIT(0)
+#define ACPI_TRIPS_HOT BIT(1)
+#define ACPI_TRIPS_PASSIVE BIT(2)
+#define ACPI_TRIPS_ACTIVE BIT(3)
+#define ACPI_TRIPS_DEVICES BIT(4)
+
+#define ACPI_TRIPS_THRESHOLDS (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE)
+
+#define ACPI_TRIPS_INIT (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT | \
+ ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE | \
+ ACPI_TRIPS_DEVICES)
+
+/*
+ * This exception is thrown out in two cases:
+ * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid
+ * when re-evaluating the AML code.
+ * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change.
+ * We need to re-bind the cooling devices of a thermal zone when this occurs.
+ */
+#define ACPI_THERMAL_TRIPS_EXCEPTION(flags, tz, str) \
+do { \
+ if (flags != ACPI_TRIPS_INIT) \
+ acpi_handle_info(tz->device->handle, \
+ "ACPI thermal trip point %s changed\n" \
+ "Please report to linux-acpi@vger.kernel.org\n", str); \
+} while (0)
static int act;
module_param(act, int, 0644);
@@ -73,75 +96,30 @@ MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
static struct workqueue_struct *acpi_thermal_pm_queue;
-static int acpi_thermal_add(struct acpi_device *device);
-static void acpi_thermal_remove(struct acpi_device *device);
-static void acpi_thermal_notify(struct acpi_device *device, u32 event);
-
-static const struct acpi_device_id thermal_device_ids[] = {
- {ACPI_THERMAL_HID, 0},
- {"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
-
-#ifdef CONFIG_PM_SLEEP
-static int acpi_thermal_suspend(struct device *dev);
-static int acpi_thermal_resume(struct device *dev);
-#else
-#define acpi_thermal_suspend NULL
-#define acpi_thermal_resume NULL
-#endif
-static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, acpi_thermal_suspend, acpi_thermal_resume);
-
-static struct acpi_driver acpi_thermal_driver = {
- .name = "thermal",
- .class = ACPI_THERMAL_CLASS,
- .ids = thermal_device_ids,
- .ops = {
- .add = acpi_thermal_add,
- .remove = acpi_thermal_remove,
- .notify = acpi_thermal_notify,
- },
- .drv.pm = &acpi_thermal_pm,
-};
-
-struct acpi_thermal_state {
- u8 critical:1;
- u8 hot:1;
- u8 passive:1;
- u8 active:1;
- u8 reserved:4;
- int active_index;
-};
-
-struct acpi_thermal_state_flags {
- u8 valid:1;
- u8 enabled:1;
- u8 reserved:6;
-};
-
struct acpi_thermal_critical {
- struct acpi_thermal_state_flags flags;
unsigned long temperature;
+ bool valid;
};
struct acpi_thermal_hot {
- struct acpi_thermal_state_flags flags;
unsigned long temperature;
+ bool valid;
};
struct acpi_thermal_passive {
- struct acpi_thermal_state_flags flags;
+ struct acpi_handle_list devices;
unsigned long temperature;
unsigned long tc1;
unsigned long tc2;
unsigned long tsp;
- struct acpi_handle_list devices;
+ bool valid;
};
struct acpi_thermal_active {
- struct acpi_thermal_state_flags flags;
- unsigned long temperature;
struct acpi_handle_list devices;
+ unsigned long temperature;
+ bool valid;
+ bool enabled;
};
struct acpi_thermal_trips {
@@ -151,12 +129,6 @@ struct acpi_thermal_trips {
struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE];
};
-struct acpi_thermal_flags {
- u8 cooling_mode:1; /* _SCP */
- u8 devices:1; /* _TZD */
- u8 reserved:6;
-};
-
struct acpi_thermal {
struct acpi_device *device;
acpi_bus_id name;
@@ -164,8 +136,6 @@ struct acpi_thermal {
unsigned long last_temperature;
unsigned long polling_frequency;
volatile u8 zombie;
- struct acpi_thermal_flags flags;
- struct acpi_thermal_state state;
struct acpi_thermal_trips trips;
struct acpi_handle_list devices;
struct thermal_zone_device *thermal_zone;
@@ -220,52 +190,12 @@ static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
return 0;
}
-static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
-{
- if (!tz)
- return -EINVAL;
-
- if (ACPI_FAILURE(acpi_execute_simple_method(tz->device->handle,
- "_SCP", mode)))
- return -ENODEV;
-
- return 0;
-}
-
-#define ACPI_TRIPS_CRITICAL 0x01
-#define ACPI_TRIPS_HOT 0x02
-#define ACPI_TRIPS_PASSIVE 0x04
-#define ACPI_TRIPS_ACTIVE 0x08
-#define ACPI_TRIPS_DEVICES 0x10
-
-#define ACPI_TRIPS_REFRESH_THRESHOLDS (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE)
-#define ACPI_TRIPS_REFRESH_DEVICES ACPI_TRIPS_DEVICES
-
-#define ACPI_TRIPS_INIT (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT | \
- ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE | \
- ACPI_TRIPS_DEVICES)
-
-/*
- * This exception is thrown out in two cases:
- * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid
- * when re-evaluating the AML code.
- * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change.
- * We need to re-bind the cooling devices of a thermal zone when this occurs.
- */
-#define ACPI_THERMAL_TRIPS_EXCEPTION(flags, tz, str) \
-do { \
- if (flags != ACPI_TRIPS_INIT) \
- acpi_handle_info(tz->device->handle, \
- "ACPI thermal trip point %s changed\n" \
- "Please report to linux-acpi@vger.kernel.org\n", str); \
-} while (0)
-
static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
{
acpi_status status;
unsigned long long tmp;
struct acpi_handle_list devices;
- int valid = 0;
+ bool valid = false;
int i;
/* Critical Shutdown */
@@ -279,21 +209,21 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
* ... so lets discard those as invalid.
*/
if (ACPI_FAILURE(status)) {
- tz->trips.critical.flags.valid = 0;
+ tz->trips.critical.valid = false;
acpi_handle_debug(tz->device->handle,
"No critical threshold\n");
} else if (tmp <= 2732) {
pr_info(FW_BUG "Invalid critical threshold (%llu)\n", tmp);
- tz->trips.critical.flags.valid = 0;
+ tz->trips.critical.valid = false;
} else {
- tz->trips.critical.flags.valid = 1;
+ tz->trips.critical.valid = true;
acpi_handle_debug(tz->device->handle,
"Found critical threshold [%lu]\n",
tz->trips.critical.temperature);
}
- if (tz->trips.critical.flags.valid) {
+ if (tz->trips.critical.valid) {
if (crt == -1) {
- tz->trips.critical.flags.valid = 0;
+ tz->trips.critical.valid = false;
} else if (crt > 0) {
unsigned long crt_k = celsius_to_deci_kelvin(crt);
@@ -312,12 +242,12 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
if (flag & ACPI_TRIPS_HOT) {
status = acpi_evaluate_integer(tz->device->handle, "_HOT", NULL, &tmp);
if (ACPI_FAILURE(status)) {
- tz->trips.hot.flags.valid = 0;
+ tz->trips.hot.valid = false;
acpi_handle_debug(tz->device->handle,
"No hot threshold\n");
} else {
tz->trips.hot.temperature = tmp;
- tz->trips.hot.flags.valid = 1;
+ tz->trips.hot.valid = true;
acpi_handle_debug(tz->device->handle,
"Found hot threshold [%lu]\n",
tz->trips.hot.temperature);
@@ -325,9 +255,9 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
}
/* Passive (optional) */
- if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.flags.valid) ||
+ if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.valid) ||
flag == ACPI_TRIPS_INIT) {
- valid = tz->trips.passive.flags.valid;
+ valid = tz->trips.passive.valid;
if (psv == -1) {
status = AE_SUPPORT;
} else if (psv > 0) {
@@ -339,44 +269,44 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
}
if (ACPI_FAILURE(status)) {
- tz->trips.passive.flags.valid = 0;
+ tz->trips.passive.valid = false;
} else {
tz->trips.passive.temperature = tmp;
- tz->trips.passive.flags.valid = 1;
+ tz->trips.passive.valid = true;
if (flag == ACPI_TRIPS_INIT) {
status = acpi_evaluate_integer(tz->device->handle,
"_TC1", NULL, &tmp);
if (ACPI_FAILURE(status))
- tz->trips.passive.flags.valid = 0;
+ tz->trips.passive.valid = false;
else
tz->trips.passive.tc1 = tmp;
status = acpi_evaluate_integer(tz->device->handle,
"_TC2", NULL, &tmp);
if (ACPI_FAILURE(status))
- tz->trips.passive.flags.valid = 0;
+ tz->trips.passive.valid = false;
else
tz->trips.passive.tc2 = tmp;
status = acpi_evaluate_integer(tz->device->handle,
"_TSP", NULL, &tmp);
if (ACPI_FAILURE(status))
- tz->trips.passive.flags.valid = 0;
+ tz->trips.passive.valid = false;
else
tz->trips.passive.tsp = tmp;
}
}
}
- if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.flags.valid) {
+ if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.valid) {
memset(&devices, 0, sizeof(struct acpi_handle_list));
status = acpi_evaluate_reference(tz->device->handle, "_PSL",
NULL, &devices);
if (ACPI_FAILURE(status)) {
acpi_handle_info(tz->device->handle,
"Invalid passive threshold\n");
- tz->trips.passive.flags.valid = 0;
+ tz->trips.passive.valid = false;
} else {
- tz->trips.passive.flags.valid = 1;
+ tz->trips.passive.valid = true;
}
if (memcmp(&tz->trips.passive.devices, &devices,
@@ -387,24 +317,24 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
}
}
if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
- if (valid != tz->trips.passive.flags.valid)
+ if (valid != tz->trips.passive.valid)
ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state");
}
/* Active (optional) */
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
- valid = tz->trips.active[i].flags.valid;
+ valid = tz->trips.active[i].valid;
if (act == -1)
break; /* disable all active trip points */
if (flag == ACPI_TRIPS_INIT || ((flag & ACPI_TRIPS_ACTIVE) &&
- tz->trips.active[i].flags.valid)) {
+ tz->trips.active[i].valid)) {
status = acpi_evaluate_integer(tz->device->handle,
name, NULL, &tmp);
if (ACPI_FAILURE(status)) {
- tz->trips.active[i].flags.valid = 0;
+ tz->trips.active[i].valid = false;
if (i == 0)
break;
@@ -426,21 +356,21 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
break;
} else {
tz->trips.active[i].temperature = tmp;
- tz->trips.active[i].flags.valid = 1;
+ tz->trips.active[i].valid = true;
}
}
name[2] = 'L';
- if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].flags.valid) {
+ if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].valid) {
memset(&devices, 0, sizeof(struct acpi_handle_list));
status = acpi_evaluate_reference(tz->device->handle,
name, NULL, &devices);
if (ACPI_FAILURE(status)) {
acpi_handle_info(tz->device->handle,
"Invalid active%d threshold\n", i);
- tz->trips.active[i].flags.valid = 0;
+ tz->trips.active[i].valid = false;
} else {
- tz->trips.active[i].flags.valid = 1;
+ tz->trips.active[i].valid = true;
}
if (memcmp(&tz->trips.active[i].devices, &devices,
@@ -451,10 +381,10 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
}
}
if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES))
- if (valid != tz->trips.active[i].flags.valid)
+ if (valid != tz->trips.active[i].valid)
ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state");
- if (!tz->trips.active[i].flags.valid)
+ if (!tz->trips.active[i].valid)
break;
}
@@ -474,17 +404,18 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
{
- int i, valid, ret = acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
+ int i, ret = acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
+ bool valid;
if (ret)
return ret;
- valid = tz->trips.critical.flags.valid |
- tz->trips.hot.flags.valid |
- tz->trips.passive.flags.valid;
+ valid = tz->trips.critical.valid |
+ tz->trips.hot.valid |
+ tz->trips.passive.valid;
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
- valid |= tz->trips.active[i].flags.valid;
+ valid = valid || tz->trips.active[i].valid;
if (!valid) {
pr_warn(FW_BUG "No valid trip found\n");
@@ -521,7 +452,7 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal,
if (!tz || trip < 0)
return -EINVAL;
- if (tz->trips.critical.flags.valid) {
+ if (tz->trips.critical.valid) {
if (!trip) {
*type = THERMAL_TRIP_CRITICAL;
return 0;
@@ -529,7 +460,7 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal,
trip--;
}
- if (tz->trips.hot.flags.valid) {
+ if (tz->trips.hot.valid) {
if (!trip) {
*type = THERMAL_TRIP_HOT;
return 0;
@@ -537,7 +468,7 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal,
trip--;
}
- if (tz->trips.passive.flags.valid) {
+ if (tz->trips.passive.valid) {
if (!trip) {
*type = THERMAL_TRIP_PASSIVE;
return 0;
@@ -545,7 +476,7 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal,
trip--;
}
- for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].flags.valid; i++) {
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].valid; i++) {
if (!trip) {
*type = THERMAL_TRIP_ACTIVE;
return 0;
@@ -565,7 +496,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
if (!tz || trip < 0)
return -EINVAL;
- if (tz->trips.critical.flags.valid) {
+ if (tz->trips.critical.valid) {
if (!trip) {
*temp = deci_kelvin_to_millicelsius_with_offset(
tz->trips.critical.temperature,
@@ -575,7 +506,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
trip--;
}
- if (tz->trips.hot.flags.valid) {
+ if (tz->trips.hot.valid) {
if (!trip) {
*temp = deci_kelvin_to_millicelsius_with_offset(
tz->trips.hot.temperature,
@@ -585,7 +516,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
trip--;
}
- if (tz->trips.passive.flags.valid) {
+ if (tz->trips.passive.valid) {
if (!trip) {
*temp = deci_kelvin_to_millicelsius_with_offset(
tz->trips.passive.temperature,
@@ -596,7 +527,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
}
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
- tz->trips.active[i].flags.valid; i++) {
+ tz->trips.active[i].valid; i++) {
if (!trip) {
*temp = deci_kelvin_to_millicelsius_with_offset(
tz->trips.active[i].temperature,
@@ -614,7 +545,7 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
{
struct acpi_thermal *tz = thermal_zone_device_priv(thermal);
- if (tz->trips.critical.flags.valid) {
+ if (tz->trips.critical.valid) {
*temperature = deci_kelvin_to_millicelsius_with_offset(
tz->trips.critical.temperature,
tz->kelvin_offset);
@@ -700,13 +631,13 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
int trip = -1;
int result = 0;
- if (tz->trips.critical.flags.valid)
+ if (tz->trips.critical.valid)
trip++;
- if (tz->trips.hot.flags.valid)
+ if (tz->trips.hot.valid)
trip++;
- if (tz->trips.passive.flags.valid) {
+ if (tz->trips.passive.valid) {
trip++;
for (i = 0; i < tz->trips.passive.devices.count; i++) {
handle = tz->trips.passive.devices.handles[i];
@@ -731,7 +662,7 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
}
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
- if (!tz->trips.active[i].flags.valid)
+ if (!tz->trips.active[i].valid)
break;
trip++;
@@ -819,19 +750,19 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
acpi_status status;
int i;
- if (tz->trips.critical.flags.valid)
+ if (tz->trips.critical.valid)
trips++;
- if (tz->trips.hot.flags.valid)
+ if (tz->trips.hot.valid)
trips++;
- if (tz->trips.passive.flags.valid)
+ if (tz->trips.passive.valid)
trips++;
- for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].flags.valid;
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].valid;
i++, trips++);
- if (tz->trips.passive.flags.valid)
+ if (tz->trips.passive.valid)
tz->thermal_zone = thermal_zone_device_register("acpitz", trips, 0, tz,
&acpi_thermal_zone_ops, NULL,
tz->trips.passive.tsp * 100,
@@ -906,13 +837,13 @@ static void acpi_thermal_notify(struct acpi_device *device, u32 event)
acpi_queue_thermal_check(tz);
break;
case ACPI_THERMAL_NOTIFY_THRESHOLDS:
- acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS);
+ acpi_thermal_trips_update(tz, ACPI_TRIPS_THRESHOLDS);
acpi_queue_thermal_check(tz);
acpi_bus_generate_netlink_event(device->pnp.device_class,
dev_name(&device->dev), event, 0);
break;
case ACPI_THERMAL_NOTIFY_DEVICES:
- acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
+ acpi_thermal_trips_update(tz, ACPI_TRIPS_DEVICES);
acpi_queue_thermal_check(tz);
acpi_bus_generate_netlink_event(device->pnp.device_class,
dev_name(&device->dev), event, 0);
@@ -976,9 +907,8 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz)
return result;
/* Set the cooling mode [_SCP] to active cooling (default) */
- result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
- if (!result)
- tz->flags.cooling_mode = 1;
+ acpi_execute_simple_method(tz->device->handle, "_SCP",
+ ACPI_THERMAL_MODE_ACTIVE);
/* Get default polling frequency [_TZP] (optional) */
if (tzp)
@@ -1001,7 +931,7 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz)
*/
static void acpi_thermal_guess_offset(struct acpi_thermal *tz)
{
- if (tz->trips.critical.flags.valid &&
+ if (tz->trips.critical.valid &&
(tz->trips.critical.temperature % 5) == 1)
tz->kelvin_offset = 273100;
else
@@ -1110,27 +1040,48 @@ static int acpi_thermal_resume(struct device *dev)
return -EINVAL;
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
- if (!tz->trips.active[i].flags.valid)
+ if (!tz->trips.active[i].valid)
break;
- tz->trips.active[i].flags.enabled = 1;
+ tz->trips.active[i].enabled = true;
for (j = 0; j < tz->trips.active[i].devices.count; j++) {
result = acpi_bus_update_power(
tz->trips.active[i].devices.handles[j],
&power_state);
if (result || (power_state != ACPI_STATE_D0)) {
- tz->trips.active[i].flags.enabled = 0;
+ tz->trips.active[i].enabled = false;
break;
}
}
- tz->state.active |= tz->trips.active[i].flags.enabled;
}
acpi_queue_thermal_check(tz);
return AE_OK;
}
+#else
+#define acpi_thermal_suspend NULL
+#define acpi_thermal_resume NULL
#endif
+static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, acpi_thermal_suspend, acpi_thermal_resume);
+
+static const struct acpi_device_id thermal_device_ids[] = {
+ {ACPI_THERMAL_HID, 0},
+ {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
+
+static struct acpi_driver acpi_thermal_driver = {
+ .name = "thermal",
+ .class = ACPI_THERMAL_CLASS,
+ .ids = thermal_device_ids,
+ .ops = {
+ .add = acpi_thermal_add,
+ .remove = acpi_thermal_remove,
+ .notify = acpi_thermal_notify,
+ },
+ .drv.pm = &acpi_thermal_pm,
+};
static int thermal_act(const struct dmi_system_id *d) {
if (act == 0) {
@@ -1236,3 +1187,7 @@ static void __exit acpi_thermal_exit(void)
module_init(acpi_thermal_init);
module_exit(acpi_thermal_exit);
+
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/acpi/tiny-power-button.c b/drivers/acpi/tiny-power-button.c
index 598f548b21f3..6353be6fec69 100644
--- a/drivers/acpi/tiny-power-button.c
+++ b/drivers/acpi/tiny-power-button.c
@@ -19,18 +19,52 @@ static const struct acpi_device_id tiny_power_button_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, tiny_power_button_device_ids);
-static int acpi_noop_add(struct acpi_device *device)
+static void acpi_tiny_power_button_notify(acpi_handle handle, u32 event, void *data)
{
- return 0;
+ kill_cad_pid(power_signal, 1);
}
-static void acpi_noop_remove(struct acpi_device *device)
+static void acpi_tiny_power_button_notify_run(void *not_used)
{
+ acpi_tiny_power_button_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, NULL);
}
-static void acpi_tiny_power_button_notify(struct acpi_device *device, u32 event)
+static u32 acpi_tiny_power_button_event(void *not_used)
{
- kill_cad_pid(power_signal, 1);
+ acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_tiny_power_button_notify_run, NULL);
+ return ACPI_INTERRUPT_HANDLED;
+}
+
+static int acpi_tiny_power_button_add(struct acpi_device *device)
+{
+ acpi_status status;
+
+ if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) {
+ status = acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+ acpi_tiny_power_button_event,
+ NULL);
+ } else {
+ status = acpi_install_notify_handler(device->handle,
+ ACPI_DEVICE_NOTIFY,
+ acpi_tiny_power_button_notify,
+ NULL);
+ }
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ return 0;
+}
+
+static void acpi_tiny_power_button_remove(struct acpi_device *device)
+{
+ if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) {
+ acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+ acpi_tiny_power_button_event);
+ } else {
+ acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
+ acpi_tiny_power_button_notify);
+ }
+ acpi_os_wait_events_complete();
}
static struct acpi_driver acpi_tiny_power_button_driver = {
@@ -38,9 +72,8 @@ static struct acpi_driver acpi_tiny_power_button_driver = {
.class = "tiny-power-button",
.ids = tiny_power_button_device_ids,
.ops = {
- .add = acpi_noop_add,
- .remove = acpi_noop_remove,
- .notify = acpi_tiny_power_button_notify,
+ .add = acpi_tiny_power_button_add,
+ .remove = acpi_tiny_power_button_remove,
},
};
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index bcc25d457581..18cc08c858cf 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -471,6 +471,22 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
},
},
{
+ .callback = video_detect_force_native,
+ /* Lenovo ThinkPad X131e (3371 AMD version) */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "3371"),
+ },
+ },
+ {
+ .callback = video_detect_force_native,
+ /* Apple iMac11,3 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "iMac11,3"),
+ },
+ },
+ {
/* https://bugzilla.redhat.com/show_bug.cgi?id=1217249 */
.callback = video_detect_force_native,
/* Apple MacBook Pro 12,1 */
@@ -514,6 +530,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
},
{
.callback = video_detect_force_native,
+ /* Dell Studio 1569 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1569"),
+ },
+ },
+ {
+ .callback = video_detect_force_native,
/* Acer Aspire 3830TG */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -828,6 +852,27 @@ enum acpi_backlight_type __acpi_video_get_backlight_type(bool native, bool *auto
if (native_available)
return acpi_backlight_native;
+ /*
+ * The vendor specific BIOS interfaces are only necessary for
+ * laptops from before ~2008.
+ *
+ * For laptops from ~2008 till ~2023 this point is never reached
+ * because on those (video_caps & ACPI_VIDEO_BACKLIGHT) above is true.
+ *
+ * Laptops from after ~2023 no longer support ACPI_VIDEO_BACKLIGHT,
+ * if this point is reached on those, this likely means that
+ * the GPU kms driver which sets native_available has not loaded yet.
+ *
+ * Returning acpi_backlight_vendor in this case is known to sometimes
+ * cause a non working vendor specific /sys/class/backlight device to
+ * get registered.
+ *
+ * Return acpi_backlight_none on laptops with ACPI tables written
+ * for Windows 8 (laptops from after ~2012) to avoid this problem.
+ */
+ if (acpi_osi_is_win8())
+ return acpi_backlight_none;
+
/* No ACPI video/native (old hw), use vendor specific fw methods. */
return acpi_backlight_vendor;
}
diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
index e499c60c4579..ce62e61a9605 100644
--- a/drivers/acpi/x86/s2idle.c
+++ b/drivers/acpi/x86/s2idle.c
@@ -59,6 +59,7 @@ static int lps0_dsm_func_mask;
static guid_t lps0_dsm_guid_microsoft;
static int lps0_dsm_func_mask_microsoft;
+static int lps0_dsm_state;
/* Device constraint entry structure */
struct lpi_device_info {
@@ -320,6 +321,44 @@ static void lpi_check_constraints(void)
}
}
+static bool acpi_s2idle_vendor_amd(void)
+{
+ return boot_cpu_data.x86_vendor == X86_VENDOR_AMD;
+}
+
+static const char *acpi_sleep_dsm_state_to_str(unsigned int state)
+{
+ if (lps0_dsm_func_mask_microsoft || !acpi_s2idle_vendor_amd()) {
+ switch (state) {
+ case ACPI_LPS0_SCREEN_OFF:
+ return "screen off";
+ case ACPI_LPS0_SCREEN_ON:
+ return "screen on";
+ case ACPI_LPS0_ENTRY:
+ return "lps0 entry";
+ case ACPI_LPS0_EXIT:
+ return "lps0 exit";
+ case ACPI_LPS0_MS_ENTRY:
+ return "lps0 ms entry";
+ case ACPI_LPS0_MS_EXIT:
+ return "lps0 ms exit";
+ }
+ } else {
+ switch (state) {
+ case ACPI_LPS0_SCREEN_ON_AMD:
+ return "screen on";
+ case ACPI_LPS0_SCREEN_OFF_AMD:
+ return "screen off";
+ case ACPI_LPS0_ENTRY_AMD:
+ return "lps0 entry";
+ case ACPI_LPS0_EXIT_AMD:
+ return "lps0 exit";
+ }
+ }
+
+ return "unknown";
+}
+
static void acpi_sleep_run_lps0_dsm(unsigned int func, unsigned int func_mask, guid_t dsm_guid)
{
union acpi_object *out_obj;
@@ -331,14 +370,15 @@ static void acpi_sleep_run_lps0_dsm(unsigned int func, unsigned int func_mask, g
rev_id, func, NULL);
ACPI_FREE(out_obj);
- acpi_handle_debug(lps0_device_handle, "_DSM function %u evaluation %s\n",
- func, out_obj ? "successful" : "failed");
+ lps0_dsm_state = func;
+ if (pm_debug_messages_on) {
+ acpi_handle_info(lps0_device_handle,
+ "%s transitioned to state %s\n",
+ out_obj ? "Successfully" : "Failed to",
+ acpi_sleep_dsm_state_to_str(lps0_dsm_state));
+ }
}
-static bool acpi_s2idle_vendor_amd(void)
-{
- return boot_cpu_data.x86_vendor == X86_VENDOR_AMD;
-}
static int validate_dsm(acpi_handle handle, const char *uuid, int rev, guid_t *dsm_guid)
{
@@ -485,11 +525,11 @@ int acpi_s2idle_prepare_late(void)
ACPI_LPS0_ENTRY,
lps0_dsm_func_mask, lps0_dsm_guid);
if (lps0_dsm_func_mask_microsoft > 0) {
- acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
/* modern standby entry */
acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
}
list_for_each_entry(handler, &lps0_s2idle_devops_head, list_node) {
@@ -524,11 +564,6 @@ void acpi_s2idle_restore_early(void)
if (handler->restore)
handler->restore();
- /* Modern standby exit */
- if (lps0_dsm_func_mask_microsoft > 0)
- acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-
/* LPS0 exit */
if (lps0_dsm_func_mask > 0)
acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
@@ -539,6 +574,11 @@ void acpi_s2idle_restore_early(void)
acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
+ /* Modern standby exit */
+ if (lps0_dsm_func_mask_microsoft > 0)
+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
+
/* Screen on */
if (lps0_dsm_func_mask_microsoft > 0)
acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c
index 9c2d6f35f88a..c2b925f8cd4e 100644
--- a/drivers/acpi/x86/utils.c
+++ b/drivers/acpi/x86/utils.c
@@ -259,10 +259,11 @@ bool force_storage_d3(void)
* drivers/platform/x86/x86-android-tablets.c kernel module.
*/
#define ACPI_QUIRK_SKIP_I2C_CLIENTS BIT(0)
-#define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(1)
-#define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY BIT(2)
-#define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY BIT(3)
-#define ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS BIT(4)
+#define ACPI_QUIRK_UART1_SKIP BIT(1)
+#define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(2)
+#define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY BIT(3)
+#define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY BIT(4)
+#define ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS BIT(5)
static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
/*
@@ -319,6 +320,7 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
},
.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
+ ACPI_QUIRK_UART1_SKIP |
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
},
@@ -365,7 +367,7 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
},
{
- /* Nextbook Ares 8 */
+ /* Nextbook Ares 8 (BYT version)*/
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
DMI_MATCH(DMI_PRODUCT_NAME, "M890BAP"),
@@ -375,6 +377,16 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
},
{
+ /* 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 *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
+ ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
+ },
+ {
/* Whitelabel (sold as various brands) TM800A550L */
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
@@ -392,6 +404,7 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
static const struct acpi_device_id i2c_acpi_known_good_ids[] = {
{ "10EC5640", 0 }, /* RealTek ALC5640 audio codec */
+ { "10EC5651", 0 }, /* RealTek ALC5651 audio codec */
{ "INT33F4", 0 }, /* X-Powers AXP288 PMIC */
{ "INT33FD", 0 }, /* Intel Crystal Cove PMIC */
{ "INT34D3", 0 }, /* Intel Whiskey Cove PMIC */
@@ -438,6 +451,9 @@ int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *s
if (dmi_id)
quirks = (unsigned long)dmi_id->driver_data;
+ if ((quirks & ACPI_QUIRK_UART1_SKIP) && uid == 1)
+ *skip = true;
+
if (quirks & ACPI_QUIRK_UART1_TTY_UART2_SKIP) {
if (uid == 1)
return -ENODEV; /* Create tty cdev instead of serdev */
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 8fb7672021ee..d720f93d8b19 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) {
@@ -6610,6 +6617,7 @@ err_init_binder_device_failed:
err_alloc_device_names_failed:
debugfs_remove_recursive(binder_debugfs_dir_entry_root);
+ binder_alloc_shrinker_exit();
return ret;
}
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index 662a2a2e2e84..e3db8297095a 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -1087,6 +1087,12 @@ int binder_alloc_shrinker_init(void)
return ret;
}
+void binder_alloc_shrinker_exit(void)
+{
+ unregister_shrinker(&binder_shrinker);
+ list_lru_destroy(&binder_alloc_lru);
+}
+
/**
* check_buffer() - verify that buffer/offset is safe to access
* @alloc: binder_alloc for this proc
diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h
index 138d1d5af9ce..dc1e2b01dd64 100644
--- a/drivers/android/binder_alloc.h
+++ b/drivers/android/binder_alloc.h
@@ -129,6 +129,7 @@ extern struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc,
int pid);
extern void binder_alloc_init(struct binder_alloc *alloc);
extern int binder_alloc_shrinker_init(void);
+extern void binder_alloc_shrinker_exit(void);
extern void binder_alloc_vma_close(struct binder_alloc *alloc);
extern struct binder_buffer *
binder_alloc_prepare_to_free(struct binder_alloc *alloc,
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..04db0f2c683a 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..c6ece32de8e3 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;
@@ -1102,7 +1100,14 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev)
}
} else {
sdev->sector_size = ata_id_logical_sector_size(dev->id);
+ /*
+ * Stop the drive on suspend but do not issue START STOP UNIT
+ * on resume as this is not necessary and may fail: the device
+ * will be woken up by ata_port_pm_resume() with a port reset
+ * and device revalidation.
+ */
sdev->manage_start_stop = 1;
+ sdev->no_start_on_resume = 1;
}
/*
@@ -1122,7 +1127,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 +1388,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 +1567,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 +1618,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 +1643,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 +2222,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 +2347,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 +2440,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 +2471,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 +2496,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 +3411,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 +3438,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 +3449,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 +3486,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 +3778,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 +3804,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 +3820,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 +3915,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 +4000,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 +4035,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_arasan_cf.c b/drivers/ata/pata_arasan_cf.c
index 6ab294322e79..314eaa167954 100644
--- a/drivers/ata/pata_arasan_cf.c
+++ b/drivers/ata/pata_arasan_cf.c
@@ -529,7 +529,8 @@ static void data_xfer(struct work_struct *work)
/* dma_request_channel may sleep, so calling from process context */
acdev->dma_chan = dma_request_chan(acdev->host->dev, "data");
if (IS_ERR(acdev->dma_chan)) {
- dev_err(acdev->host->dev, "Unable to get dma_chan\n");
+ dev_err_probe(acdev->host->dev, PTR_ERR(acdev->dma_chan),
+ "Unable to get dma_chan\n");
acdev->dma_chan = NULL;
goto chan_request_fail;
}
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_ns87415.c b/drivers/ata/pata_ns87415.c
index d60e1f69d7b0..c697219a61a2 100644
--- a/drivers/ata/pata_ns87415.c
+++ b/drivers/ata/pata_ns87415.c
@@ -260,7 +260,7 @@ static u8 ns87560_check_status(struct ata_port *ap)
* LOCKING:
* Inherited from caller.
*/
-void ns87560_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+static void ns87560_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c
index b1ce9f1761af..2884acfc4863 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;
@@ -816,8 +815,8 @@ static int octeon_cf_probe(struct platform_device *pdev)
irq_handler_t irq_handler = NULL;
void __iomem *base;
struct octeon_cf_port *cf_port;
- int rv = -ENOMEM;
u32 bus_width;
+ int rv;
node = pdev->dev.of_node;
if (node == 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);
@@ -900,12 +893,12 @@ static int octeon_cf_probe(struct platform_device *pdev)
cs0 = devm_ioremap(&pdev->dev, res_cs0->start,
resource_size(res_cs0));
if (!cs0)
- return rv;
+ return -ENOMEM;
/* allocate host */
host = ata_host_alloc(&pdev->dev, 1);
if (!host)
- return rv;
+ return -ENOMEM;
ap = host->ports[0];
ap->private_data = cf_port;
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..620ce6c8da5c 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 = {
@@ -136,4 +139,6 @@ static struct pi_protocol aten = {
};
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("ATEN EH-100 parallel port IDE adapter protocol driver");
module_pata_parport_driver(aten);
diff --git a/drivers/ata/pata_parport/bpck.c b/drivers/ata/pata_parport/bpck.c
index 1c5035a09554..bba1eda65f36 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 = {
@@ -436,4 +502,6 @@ static struct pi_protocol bpck = {
};
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("MicroSolutions BACKPACK parallel port IDE adapter protocol driver");
module_pata_parport_driver(bpck);
diff --git a/drivers/ata/pata_parport/bpck6.c b/drivers/ata/pata_parport/bpck6.c
index 76febd07a9bb..62c2b53325e1 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 = {
@@ -456,5 +459,6 @@ static struct pi_protocol bpck6 = {
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Micro Solutions Inc.");
-MODULE_DESCRIPTION("BACKPACK Protocol module, compatible with PARIDE");
+MODULE_DESCRIPTION("Micro Solutions BACKPACK parallel port IDE adapter "
+ "(version 6 drives) protocol driver");
module_pata_parport_driver(bpck6);
diff --git a/drivers/ata/pata_parport/comm.c b/drivers/ata/pata_parport/comm.c
index 4c2f9ad60ad8..4839becbbd56 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 = {
@@ -195,4 +201,6 @@ static struct pi_protocol comm = {
};
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("DataStor Commuter parallel port IDE adapter protocol driver");
module_pata_parport_driver(comm);
diff --git a/drivers/ata/pata_parport/dstr.c b/drivers/ata/pata_parport/dstr.c
index 2524684be206..88930bb1f07e 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 = {
@@ -207,4 +230,6 @@ static struct pi_protocol dstr = {
};
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("DataStor EP2000 parallel port IDE adapter protocol driver");
module_pata_parport_driver(dstr);
diff --git a/drivers/ata/pata_parport/epat.c b/drivers/ata/pata_parport/epat.c
index b146999368ae..3cb54fcbf0d0 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);
}
@@ -322,5 +358,8 @@ static void __exit epat_exit(void)
}
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Shuttle Technologies EPAT parallel port IDE adapter "
+ "protocol driver");
module_init(epat_init)
module_exit(epat_exit)
diff --git a/drivers/ata/pata_parport/epia.c b/drivers/ata/pata_parport/epia.c
index f6db2f79fe99..7aaba474c671 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 = {
@@ -288,4 +306,7 @@ static struct pi_protocol epia = {
};
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Shuttle Technologies EPIA parallel port IDE adapter "
+ "protocol driver");
module_pata_parport_driver(epia);
diff --git a/drivers/ata/pata_parport/fit2.c b/drivers/ata/pata_parport/fit2.c
index fd3b2ce426a5..de79cf91ad5f 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);
}
@@ -135,4 +132,7 @@ static struct pi_protocol fit2 = {
};
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Fidelity International Technology parallel port IDE adapter"
+ "(older models) protocol driver");
module_pata_parport_driver(fit2);
diff --git a/drivers/ata/pata_parport/fit3.c b/drivers/ata/pata_parport/fit3.c
index 75df656ac472..bad7aa920cdc 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 = {
@@ -191,4 +193,7 @@ static struct pi_protocol fit3 = {
};
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Fidelity International Technology parallel port IDE adapter"
+ "(newer models) protocol driver");
module_pata_parport_driver(fit3);
diff --git a/drivers/ata/pata_parport/friq.c b/drivers/ata/pata_parport/friq.c
index 1647264cd9a8..7abe2ff40685 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)
@@ -251,4 +259,6 @@ static struct pi_protocol friq = {
};
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Freecom IQ parallel port IDE adapter protocol driver");
module_pata_parport_driver(friq);
diff --git a/drivers/ata/pata_parport/frpw.c b/drivers/ata/pata_parport/frpw.c
index 3ec0abf16fa6..7fa9b9857321 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 = {
@@ -279,4 +293,6 @@ static struct pi_protocol frpw = {
};
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Freecom Power parallel port IDE adapter protocol driver");
module_pata_parport_driver(frpw);
diff --git a/drivers/ata/pata_parport/kbic.c b/drivers/ata/pata_parport/kbic.c
index 8213e62f8f00..fca322627b82 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)
@@ -291,5 +301,8 @@ static void __exit kbic_exit(void)
}
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("KingByte Information Systems KBIC-951A and KBIC-971A "
+ "parallel port IDE adapter protocol driver");
module_init(kbic_init)
module_exit(kbic_exit)
diff --git a/drivers/ata/pata_parport/ktti.c b/drivers/ata/pata_parport/ktti.c
index 4890b1f12348..c078d1934862 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 = {
@@ -111,4 +106,6 @@ static struct pi_protocol ktti = {
};
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("KT Technology parallel port IDE adapter protocol driver");
module_pata_parport_driver(ktti);
diff --git a/drivers/ata/pata_parport/on20.c b/drivers/ata/pata_parport/on20.c
index 276ace12d490..7c70e5b13a2a 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 = {
@@ -127,4 +142,6 @@ static struct pi_protocol on20 = {
};
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Onspec 90c20 parallel port IDE adapter protocol driver");
module_pata_parport_driver(on20);
diff --git a/drivers/ata/pata_parport/on26.c b/drivers/ata/pata_parport/on26.c
index dc47a54b121f..c88e5d6f203e 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 = {
@@ -290,4 +310,6 @@ static struct pi_protocol on26 = {
};
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Onspec 90c26 parallel port IDE adapter protocol driver");
module_pata_parport_driver(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 02425991c159..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;
@@ -820,7 +820,7 @@ static const struct of_device_id ht16k33_of_match[] = {
MODULE_DEVICE_TABLE(of, ht16k33_of_match);
static struct i2c_driver ht16k33_driver = {
- .probe_new = ht16k33_probe,
+ .probe = ht16k33_probe,
.remove = ht16k33_remove,
.driver = {
.name = DRIVER_NAME,
diff --git a/drivers/auxdisplay/lcd2s.c b/drivers/auxdisplay/lcd2s.c
index 135831a16514..6422be0dfe20 100644
--- a/drivers/auxdisplay/lcd2s.c
+++ b/drivers/auxdisplay/lcd2s.c
@@ -365,7 +365,7 @@ static struct i2c_driver lcd2s_i2c_driver = {
.name = "lcd2s",
.of_match_table = lcd2s_of_table,
},
- .probe_new = lcd2s_i2c_probe,
+ .probe = lcd2s_i2c_probe,
.remove = lcd2s_i2c_remove,
.id_table = lcd2s_i2c_id,
};
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index c1815b9dae68..fe6690ecf563 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -509,73 +509,30 @@ static void __init cpu_dev_register_generic(void)
}
#ifdef CONFIG_GENERIC_CPU_VULNERABILITIES
-
-ssize_t __weak cpu_show_meltdown(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_spectre_v1(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_spectre_v2(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_spec_store_bypass(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_l1tf(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_mds(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_tsx_async_abort(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_itlb_multihit(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_srbds(struct device *dev,
+static ssize_t cpu_show_not_affected(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sysfs_emit(buf, "Not affected\n");
}
-ssize_t __weak cpu_show_mmio_stale_data(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sysfs_emit(buf, "Not affected\n");
-}
-
-ssize_t __weak cpu_show_retbleed(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sysfs_emit(buf, "Not affected\n");
-}
+#define CPU_SHOW_VULN_FALLBACK(func) \
+ ssize_t cpu_show_##func(struct device *, \
+ struct device_attribute *, char *) \
+ __attribute__((weak, alias("cpu_show_not_affected")))
+
+CPU_SHOW_VULN_FALLBACK(meltdown);
+CPU_SHOW_VULN_FALLBACK(spectre_v1);
+CPU_SHOW_VULN_FALLBACK(spectre_v2);
+CPU_SHOW_VULN_FALLBACK(spec_store_bypass);
+CPU_SHOW_VULN_FALLBACK(l1tf);
+CPU_SHOW_VULN_FALLBACK(mds);
+CPU_SHOW_VULN_FALLBACK(tsx_async_abort);
+CPU_SHOW_VULN_FALLBACK(itlb_multihit);
+CPU_SHOW_VULN_FALLBACK(srbds);
+CPU_SHOW_VULN_FALLBACK(mmio_stale_data);
+CPU_SHOW_VULN_FALLBACK(retbleed);
+CPU_SHOW_VULN_FALLBACK(spec_rstack_overflow);
+CPU_SHOW_VULN_FALLBACK(gds);
static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
@@ -588,6 +545,8 @@ static DEVICE_ATTR(itlb_multihit, 0444, cpu_show_itlb_multihit, NULL);
static DEVICE_ATTR(srbds, 0444, cpu_show_srbds, NULL);
static DEVICE_ATTR(mmio_stale_data, 0444, cpu_show_mmio_stale_data, NULL);
static DEVICE_ATTR(retbleed, 0444, cpu_show_retbleed, NULL);
+static DEVICE_ATTR(spec_rstack_overflow, 0444, cpu_show_spec_rstack_overflow, NULL);
+static DEVICE_ATTR(gather_data_sampling, 0444, cpu_show_gds, NULL);
static struct attribute *cpu_root_vulnerabilities_attrs[] = {
&dev_attr_meltdown.attr,
@@ -601,6 +560,8 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
&dev_attr_srbds.attr,
&dev_attr_mmio_stale_data.attr,
&dev_attr_retbleed.attr,
+ &dev_attr_spec_rstack_overflow.attr,
+ &dev_attr_gather_data_sampling.attr,
NULL
};
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 9c09ca5c4ab6..878aa7646b37 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -751,14 +751,12 @@ static int really_probe_debug(struct device *dev, struct device_driver *drv)
*
* Should somehow figure out how to use a semaphore, not an atomic variable...
*/
-int driver_probe_done(void)
+bool __init driver_probe_done(void)
{
int local_probe_count = atomic_read(&probe_count);
pr_debug("%s: probe_count = %d\n", __func__, local_probe_count);
- if (local_probe_count)
- return -EBUSY;
- return 0;
+ return !local_probe_count;
}
/**
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index 5c998cfac335..3df0025d12aa 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -29,10 +29,10 @@ struct devres {
* Some archs want to perform DMA into kmalloc caches
* and need a guaranteed alignment larger than
* the alignment of a 64-bit integer.
- * Thus we use ARCH_KMALLOC_MINALIGN here and get exactly the same
- * buffer alignment as if it was allocated by plain kmalloc().
+ * Thus we use ARCH_DMA_MINALIGN for data[] which will force the same
+ * alignment for struct devres when allocated by kmalloc().
*/
- u8 __aligned(ARCH_KMALLOC_MINALIGN) data[];
+ u8 __aligned(ARCH_DMA_MINALIGN) data[];
};
struct devres_group {
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 b46db17124f3..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);
@@ -449,6 +449,9 @@ static ssize_t node_read_meminfo(struct device *dev,
"Node %d FileHugePages: %8lu kB\n"
"Node %d FilePmdMapped: %8lu kB\n"
#endif
+#ifdef CONFIG_UNACCEPTED_MEMORY
+ "Node %d Unaccepted: %8lu kB\n"
+#endif
,
nid, K(node_page_state(pgdat, NR_FILE_DIRTY)),
nid, K(node_page_state(pgdat, NR_WRITEBACK)),
@@ -478,6 +481,10 @@ static ssize_t node_read_meminfo(struct device *dev,
nid, K(node_page_state(pgdat, NR_FILE_THPS)),
nid, K(node_page_state(pgdat, NR_FILE_PMDMAPPED))
#endif
+#ifdef CONFIG_UNACCEPTED_MEMORY
+ ,
+ nid, K(sum_zone_node_page_state(nid, NR_UNACCEPTED))
+#endif
);
len += hugetlb_report_node_meminfo(buf, len, nid);
return len;
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 32084e38b73d..5cb2023581d4 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1632,9 +1632,6 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
dev_dbg(dev, "%s()\n", __func__);
- if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
- return -EINVAL;
-
gpd_data = genpd_alloc_dev_data(dev, gd);
if (IS_ERR(gpd_data))
return PTR_ERR(gpd_data);
@@ -1676,6 +1673,9 @@ int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev)
{
int ret;
+ if (!genpd || !dev)
+ return -EINVAL;
+
mutex_lock(&gpd_list_lock);
ret = genpd_add_device(genpd, dev, dev);
mutex_unlock(&gpd_list_lock);
@@ -2523,6 +2523,9 @@ int of_genpd_add_device(struct of_phandle_args *genpdspec, struct device *dev)
struct generic_pm_domain *genpd;
int ret;
+ if (!dev)
+ return -EINVAL;
+
mutex_lock(&gpd_list_lock);
genpd = genpd_get_from_provider(genpdspec);
@@ -2939,10 +2942,10 @@ static int genpd_parse_state(struct genpd_power_state *genpd_state,
err = of_property_read_u32(state_node, "min-residency-us", &residency);
if (!err)
- genpd_state->residency_ns = 1000 * residency;
+ genpd_state->residency_ns = 1000LL * residency;
- genpd_state->power_on_latency_ns = 1000 * exit_latency;
- genpd_state->power_off_latency_ns = 1000 * entry_latency;
+ genpd_state->power_on_latency_ns = 1000LL * exit_latency;
+ genpd_state->power_off_latency_ns = 1000LL * entry_latency;
genpd_state->fwnode = &state_node->fwnode;
return 0;
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 0eb7f02b3ad5..922ed457db19 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -29,6 +29,7 @@ extern u64 pm_runtime_active_time(struct device *dev);
#define WAKE_IRQ_DEDICATED_MASK (WAKE_IRQ_DEDICATED_ALLOCATED | \
WAKE_IRQ_DEDICATED_MANAGED | \
WAKE_IRQ_DEDICATED_REVERSE)
+#define WAKE_IRQ_DEDICATED_ENABLED BIT(3)
struct wake_irq {
struct device *dev;
diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c
index d487a6bac630..42171f766dcb 100644
--- a/drivers/base/power/wakeirq.c
+++ b/drivers/base/power/wakeirq.c
@@ -194,7 +194,6 @@ err_free:
return err;
}
-
/**
* dev_pm_set_dedicated_wake_irq - Request a dedicated wake-up interrupt
* @dev: Device entry
@@ -206,11 +205,6 @@ err_free:
* Sets up a threaded interrupt handler for a device that has
* a dedicated wake-up interrupt in addition to the device IO
* interrupt.
- *
- * The interrupt starts disabled, and needs to be managed for
- * the device by the bus code or the device driver using
- * dev_pm_enable_wake_irq*() and dev_pm_disable_wake_irq*()
- * functions.
*/
int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
{
@@ -232,11 +226,6 @@ EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq);
* the status of WAKE_IRQ_DEDICATED_REVERSE to tell rpm_suspend()
* to enable dedicated wake-up interrupt after running the runtime suspend
* callback for @dev.
- *
- * The interrupt starts disabled, and needs to be managed for
- * the device by the bus code or the device driver using
- * dev_pm_enable_wake_irq*() and dev_pm_disable_wake_irq*()
- * functions.
*/
int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq)
{
@@ -245,44 +234,6 @@ int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq)
EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq_reverse);
/**
- * dev_pm_enable_wake_irq - Enable device wake-up interrupt
- * @dev: Device
- *
- * Optionally called from the bus code or the device driver for
- * runtime_resume() to override the PM runtime core managed wake-up
- * interrupt handling to enable the wake-up interrupt.
- *
- * Note that for runtime_suspend()) the wake-up interrupts
- * should be unconditionally enabled unlike for suspend()
- * that is conditional.
- */
-void dev_pm_enable_wake_irq(struct device *dev)
-{
- struct wake_irq *wirq = dev->power.wakeirq;
-
- if (wirq && (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED))
- enable_irq(wirq->irq);
-}
-EXPORT_SYMBOL_GPL(dev_pm_enable_wake_irq);
-
-/**
- * dev_pm_disable_wake_irq - Disable device wake-up interrupt
- * @dev: Device
- *
- * Optionally called from the bus code or the device driver for
- * runtime_suspend() to override the PM runtime core managed wake-up
- * interrupt handling to disable the wake-up interrupt.
- */
-void dev_pm_disable_wake_irq(struct device *dev)
-{
- struct wake_irq *wirq = dev->power.wakeirq;
-
- if (wirq && (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED))
- disable_irq_nosync(wirq->irq);
-}
-EXPORT_SYMBOL_GPL(dev_pm_disable_wake_irq);
-
-/**
* dev_pm_enable_wake_irq_check - Checks and enables wake-up interrupt
* @dev: Device
* @can_change_status: Can change wake-up interrupt status
@@ -314,8 +265,10 @@ void dev_pm_enable_wake_irq_check(struct device *dev,
return;
enable:
- if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE))
+ if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE)) {
enable_irq(wirq->irq);
+ wirq->status |= WAKE_IRQ_DEDICATED_ENABLED;
+ }
}
/**
@@ -336,8 +289,10 @@ void dev_pm_disable_wake_irq_check(struct device *dev, bool cond_disable)
if (cond_disable && (wirq->status & WAKE_IRQ_DEDICATED_REVERSE))
return;
- if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED)
+ if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED) {
+ wirq->status &= ~WAKE_IRQ_DEDICATED_ENABLED;
disable_irq_nosync(wirq->irq);
+ }
}
/**
@@ -376,7 +331,7 @@ void dev_pm_arm_wake_irq(struct wake_irq *wirq)
if (device_may_wakeup(wirq->dev)) {
if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED &&
- !pm_runtime_status_suspended(wirq->dev))
+ !(wirq->status & WAKE_IRQ_DEDICATED_ENABLED))
enable_irq(wirq->irq);
enable_irq_wake(wirq->irq);
@@ -399,7 +354,7 @@ void dev_pm_disarm_wake_irq(struct wake_irq *wirq)
disable_irq_wake(wirq->irq);
if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED &&
- !pm_runtime_status_suspended(wirq->dev))
+ !(wirq->status & WAKE_IRQ_DEDICATED_ENABLED))
disable_irq_nosync(wirq->irq);
}
}
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 7cc0c0cf8eaa..a917219feea6 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -19,11 +19,6 @@
#include "power.h"
-#ifndef CONFIG_SUSPEND
-suspend_state_t pm_suspend_target_state;
-#define pm_suspend_target_state (PM_SUSPEND_ON)
-#endif
-
#define list_for_each_entry_rcu_locked(pos, head, member) \
list_for_each_entry_rcu(pos, head, member, \
srcu_read_lock_held(&wakeup_srcu))
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/base/regmap/Makefile b/drivers/base/regmap/Makefile
index f6c6cb017200..5fdd0845b45e 100644
--- a/drivers/base/regmap/Makefile
+++ b/drivers/base/regmap/Makefile
@@ -8,7 +8,7 @@ obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o
obj-$(CONFIG_REGMAP_KUNIT) += regmap-kunit.o
obj-$(CONFIG_REGMAP_AC97) += regmap-ac97.o
obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
-obj-$(CONFIG_REGMAP_RAM) += regmap-ram.o
+obj-$(CONFIG_REGMAP_RAM) += regmap-ram.o regmap-raw-ram.o
obj-$(CONFIG_REGMAP_SLIMBUS) += regmap-slimbus.o
obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o
obj-$(CONFIG_REGMAP_SPMI) += regmap-spmi.o
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 9bd0dfd1e259..9a9ea514c2d8 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -125,6 +125,9 @@ struct regmap {
int reg_stride;
int reg_stride_order;
+ /* If set, will always write field to HW. */
+ bool force_write_field;
+
/* regcache specific members */
const struct regcache_ops *cache_ops;
enum regcache_type cache_type;
@@ -257,6 +260,8 @@ int regcache_sync_block(struct regmap *map, void *block,
unsigned long *cache_present,
unsigned int block_base, unsigned int start,
unsigned int end);
+bool regcache_reg_needs_sync(struct regmap *map, unsigned int reg,
+ unsigned int val);
static inline const void *regcache_get_val_addr(struct regmap *map,
const void *base,
@@ -267,7 +272,7 @@ static inline const void *regcache_get_val_addr(struct regmap *map,
unsigned int regcache_get_val(struct regmap *map, const void *base,
unsigned int idx);
-bool regcache_set_val(struct regmap *map, void *base, unsigned int idx,
+void regcache_set_val(struct regmap *map, void *base, unsigned int idx,
unsigned int val);
int regcache_lookup_reg(struct regmap *map, unsigned int reg);
int regcache_sync_val(struct regmap *map, unsigned int reg, unsigned int val);
@@ -312,6 +317,7 @@ struct regmap_ram_data {
unsigned int *vals; /* Allocatd by caller */
bool *read;
bool *written;
+ enum regmap_endian reg_endian;
};
/*
@@ -326,5 +332,12 @@ struct regmap *__regmap_init_ram(const struct regmap_config *config,
#define regmap_init_ram(config, data) \
__regmap_lockdep_wrapper(__regmap_init_ram, #config, config, data)
+struct regmap *__regmap_init_raw_ram(const struct regmap_config *config,
+ struct regmap_ram_data *data,
+ struct lock_class_key *lock_key,
+ const char *lock_name);
+
+#define regmap_init_raw_ram(config, data) \
+ __regmap_lockdep_wrapper(__regmap_init_raw_ram, #config, config, data)
#endif
diff --git a/drivers/base/regmap/regcache-maple.c b/drivers/base/regmap/regcache-maple.c
index c2e3a0f6c218..283c2e02a298 100644
--- a/drivers/base/regmap/regcache-maple.c
+++ b/drivers/base/regmap/regcache-maple.c
@@ -186,6 +186,55 @@ out_unlocked:
return ret;
}
+static int regcache_maple_sync_block(struct regmap *map, unsigned long *entry,
+ struct ma_state *mas,
+ unsigned int min, unsigned int max)
+{
+ void *buf;
+ unsigned long r;
+ size_t val_bytes = map->format.val_bytes;
+ int ret = 0;
+
+ mas_pause(mas);
+ rcu_read_unlock();
+
+ /*
+ * Use a raw write if writing more than one register to a
+ * device that supports raw writes to reduce transaction
+ * overheads.
+ */
+ if (max - min > 1 && regmap_can_raw_write(map)) {
+ buf = kmalloc(val_bytes * (max - min), map->alloc_flags);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* Render the data for a raw write */
+ for (r = min; r < max; r++) {
+ regcache_set_val(map, buf, r - min,
+ entry[r - mas->index]);
+ }
+
+ ret = _regmap_raw_write(map, min, buf, (max - min) * val_bytes,
+ false);
+
+ kfree(buf);
+ } else {
+ for (r = min; r < max; r++) {
+ ret = _regmap_write(map, r,
+ entry[r - mas->index]);
+ if (ret != 0)
+ goto out;
+ }
+ }
+
+out:
+ rcu_read_lock();
+
+ return ret;
+}
+
static int regcache_maple_sync(struct regmap *map, unsigned int min,
unsigned int max)
{
@@ -194,8 +243,9 @@ static int regcache_maple_sync(struct regmap *map, unsigned int min,
MA_STATE(mas, mt, min, max);
unsigned long lmin = min;
unsigned long lmax = max;
- unsigned int r;
+ unsigned int r, v, sync_start;
int ret;
+ bool sync_needed = false;
map->cache_bypass = true;
@@ -203,18 +253,38 @@ static int regcache_maple_sync(struct regmap *map, unsigned int min,
mas_for_each(&mas, entry, max) {
for (r = max(mas.index, lmin); r <= min(mas.last, lmax); r++) {
- mas_pause(&mas);
- rcu_read_unlock();
- ret = regcache_sync_val(map, r, entry[r - mas.index]);
+ v = entry[r - mas.index];
+
+ if (regcache_reg_needs_sync(map, r, v)) {
+ if (!sync_needed) {
+ sync_start = r;
+ sync_needed = true;
+ }
+ continue;
+ }
+
+ if (!sync_needed)
+ continue;
+
+ ret = regcache_maple_sync_block(map, entry, &mas,
+ sync_start, r);
+ if (ret != 0)
+ goto out;
+ sync_needed = false;
+ }
+
+ if (sync_needed) {
+ ret = regcache_maple_sync_block(map, entry, &mas,
+ sync_start, r);
if (ret != 0)
goto out;
- rcu_read_lock();
+ sync_needed = false;
}
}
+out:
rcu_read_unlock();
-out:
map->cache_bypass = false;
return ret;
@@ -242,11 +312,41 @@ static int regcache_maple_exit(struct regmap *map)
return 0;
}
+static int regcache_maple_insert_block(struct regmap *map, int first,
+ int last)
+{
+ struct maple_tree *mt = map->cache;
+ MA_STATE(mas, mt, first, last);
+ unsigned long *entry;
+ int i, ret;
+
+ entry = kcalloc(last - first + 1, sizeof(unsigned long), GFP_KERNEL);
+ if (!entry)
+ return -ENOMEM;
+
+ for (i = 0; i < last - first + 1; i++)
+ entry[i] = map->reg_defaults[first + i].def;
+
+ mas_lock(&mas);
+
+ mas_set_range(&mas, map->reg_defaults[first].reg,
+ map->reg_defaults[last].reg);
+ ret = mas_store_gfp(&mas, entry, GFP_KERNEL);
+
+ mas_unlock(&mas);
+
+ if (ret)
+ kfree(entry);
+
+ return ret;
+}
+
static int regcache_maple_init(struct regmap *map)
{
struct maple_tree *mt;
int i;
int ret;
+ int range_start;
mt = kmalloc(sizeof(*mt), GFP_KERNEL);
if (!mt)
@@ -255,14 +355,30 @@ static int regcache_maple_init(struct regmap *map)
mt_init(mt);
- for (i = 0; i < map->num_reg_defaults; i++) {
- ret = regcache_maple_write(map,
- map->reg_defaults[i].reg,
- map->reg_defaults[i].def);
- if (ret)
- goto err;
+ if (!map->num_reg_defaults)
+ return 0;
+
+ range_start = 0;
+
+ /* Scan for ranges of contiguous registers */
+ for (i = 1; i < map->num_reg_defaults; i++) {
+ if (map->reg_defaults[i].reg !=
+ map->reg_defaults[i - 1].reg + 1) {
+ ret = regcache_maple_insert_block(map, range_start,
+ i - 1);
+ if (ret != 0)
+ goto err;
+
+ range_start = i;
+ }
}
+ /* Add the last block */
+ ret = regcache_maple_insert_block(map, range_start,
+ map->num_reg_defaults - 1);
+ if (ret != 0)
+ goto err;
+
return 0;
err:
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
index fabf87058d80..584bcc55f56e 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -471,6 +471,8 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
unsigned int start, end;
int ret;
+ map->async = true;
+
rbtree_ctx = map->cache;
for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) {
rbnode = rb_entry(node, struct regcache_rbtree_node, node);
@@ -499,6 +501,8 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
return ret;
}
+ map->async = false;
+
return regmap_async_complete(map);
}
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 97c681fcf9f6..7d3e47436056 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -279,8 +279,8 @@ int regcache_write(struct regmap *map,
return 0;
}
-static bool regcache_reg_needs_sync(struct regmap *map, unsigned int reg,
- unsigned int val)
+bool regcache_reg_needs_sync(struct regmap *map, unsigned int reg,
+ unsigned int val)
{
int ret;
@@ -368,8 +368,6 @@ int regcache_sync(struct regmap *map)
if (!map->cache_dirty)
goto out;
- map->async = true;
-
/* Apply any patch first */
map->cache_bypass = true;
for (i = 0; i < map->patch_regs; i++) {
@@ -392,7 +390,6 @@ int regcache_sync(struct regmap *map)
out:
/* Restore the bypass state */
- map->async = false;
map->cache_bypass = bypass;
map->no_sync_defaults = false;
map->unlock(map->lock_arg);
@@ -561,17 +558,14 @@ void regcache_cache_bypass(struct regmap *map, bool enable)
}
EXPORT_SYMBOL_GPL(regcache_cache_bypass);
-bool regcache_set_val(struct regmap *map, void *base, unsigned int idx,
+void regcache_set_val(struct regmap *map, void *base, unsigned int idx,
unsigned int val)
{
- if (regcache_get_val(map, base, idx) == val)
- return true;
-
/* Use device native format if possible */
if (map->format.format_val) {
map->format.format_val(base + (map->cache_word_size * idx),
val, 0);
- return false;
+ return;
}
switch (map->cache_word_size) {
@@ -604,7 +598,6 @@ bool regcache_set_val(struct regmap *map, void *base, unsigned int idx,
default:
BUG();
}
- return false;
}
unsigned int regcache_get_val(struct regmap *map, const void *base,
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index c491fabe3617..f36027591e1a 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -636,6 +636,17 @@ void regmap_debugfs_init(struct regmap *map)
&regmap_cache_bypass_fops);
}
+ /*
+ * This could interfere with driver operation. Therefore, don't provide
+ * any real compile time configuration option for this feature. One will
+ * have to modify the source code directly in order to use it.
+ */
+#undef REGMAP_ALLOW_FORCE_WRITE_FIELD_DEBUGFS
+#ifdef REGMAP_ALLOW_FORCE_WRITE_FIELD_DEBUGFS
+ debugfs_create_bool("force_write_field", 0600, map->debugfs,
+ &map->force_write_field);
+#endif
+
next = rb_first(&map->range_tree);
while (next) {
range_node = rb_entry(next, struct regmap_range_node, node);
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
index 980e5ce6a3a3..3ec611dc0c09 100644
--- a/drivers/base/regmap/regmap-i2c.c
+++ b/drivers/base/regmap/regmap-i2c.c
@@ -242,8 +242,8 @@ static int regmap_i2c_smbus_i2c_read(void *context, const void *reg,
static const struct regmap_bus regmap_i2c_smbus_i2c_block = {
.write = regmap_i2c_smbus_i2c_write,
.read = regmap_i2c_smbus_i2c_read,
- .max_raw_read = I2C_SMBUS_BLOCK_MAX,
- .max_raw_write = I2C_SMBUS_BLOCK_MAX,
+ .max_raw_read = I2C_SMBUS_BLOCK_MAX - 1,
+ .max_raw_write = I2C_SMBUS_BLOCK_MAX - 1,
};
static int regmap_i2c_smbus_i2c_write_reg16(void *context, const void *data,
@@ -299,8 +299,8 @@ static int regmap_i2c_smbus_i2c_read_reg16(void *context, const void *reg,
static const struct regmap_bus regmap_i2c_smbus_i2c_block_reg16 = {
.write = regmap_i2c_smbus_i2c_write_reg16,
.read = regmap_i2c_smbus_i2c_read_reg16,
- .max_raw_read = I2C_SMBUS_BLOCK_MAX,
- .max_raw_write = I2C_SMBUS_BLOCK_MAX,
+ .max_raw_read = I2C_SMBUS_BLOCK_MAX - 2,
+ .max_raw_write = I2C_SMBUS_BLOCK_MAX - 2,
};
static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index b99bb2369fff..45fd13ef13fc 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -30,9 +30,6 @@ struct regmap_irq_chip_data {
int irq;
int wake_count;
- unsigned int mask_base;
- unsigned int unmask_base;
-
void *status_reg_buf;
unsigned int *main_status_buf;
unsigned int *status_buf;
@@ -41,7 +38,6 @@ struct regmap_irq_chip_data {
unsigned int *wake_buf;
unsigned int *type_buf;
unsigned int *type_buf_def;
- unsigned int **virt_buf;
unsigned int **config_buf;
unsigned int irq_reg_stride;
@@ -114,25 +110,22 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
* suppress pointless writes.
*/
for (i = 0; i < d->chip->num_regs; i++) {
- if (d->mask_base) {
- if (d->chip->handle_mask_sync)
- d->chip->handle_mask_sync(d->map, i,
- d->mask_buf_def[i],
- d->mask_buf[i],
- d->chip->irq_drv_data);
- else {
- reg = d->get_irq_reg(d, d->mask_base, i);
- ret = regmap_update_bits(d->map, reg,
- d->mask_buf_def[i],
- d->mask_buf[i]);
- if (ret)
- dev_err(d->map->dev, "Failed to sync masks in %x\n",
- reg);
- }
+ if (d->chip->handle_mask_sync)
+ d->chip->handle_mask_sync(i, d->mask_buf_def[i],
+ d->mask_buf[i],
+ d->chip->irq_drv_data);
+
+ if (d->chip->mask_base && !d->chip->handle_mask_sync) {
+ reg = d->get_irq_reg(d, d->chip->mask_base, i);
+ ret = regmap_update_bits(d->map, reg,
+ d->mask_buf_def[i],
+ d->mask_buf[i]);
+ if (ret)
+ dev_err(d->map->dev, "Failed to sync masks in %x\n", reg);
}
- if (d->unmask_base) {
- reg = d->get_irq_reg(d, d->unmask_base, i);
+ if (d->chip->unmask_base && !d->chip->handle_mask_sync) {
+ reg = d->get_irq_reg(d, d->chip->unmask_base, i);
ret = regmap_update_bits(d->map, reg,
d->mask_buf_def[i], ~d->mask_buf[i]);
if (ret)
@@ -183,34 +176,6 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
}
}
- /* Don't update the type bits if we're using mask bits for irq type. */
- if (!d->chip->type_in_mask) {
- for (i = 0; i < d->chip->num_type_reg; i++) {
- if (!d->type_buf_def[i])
- continue;
- reg = d->get_irq_reg(d, d->chip->type_base, i);
- ret = regmap_update_bits(d->map, reg,
- d->type_buf_def[i], d->type_buf[i]);
- if (ret != 0)
- dev_err(d->map->dev, "Failed to sync type in %x\n",
- reg);
- }
- }
-
- if (d->chip->num_virt_regs) {
- for (i = 0; i < d->chip->num_virt_regs; i++) {
- for (j = 0; j < d->chip->num_regs; j++) {
- reg = d->get_irq_reg(d, d->chip->virt_reg_base[i],
- j);
- ret = regmap_write(map, reg, d->virt_buf[i][j]);
- if (ret != 0)
- dev_err(d->map->dev,
- "Failed to write virt 0x%x: %d\n",
- reg, ret);
- }
- }
- }
-
for (i = 0; i < d->chip->num_config_bases; i++) {
for (j = 0; j < d->chip->num_config_regs; j++) {
reg = d->get_irq_reg(d, d->chip->config_base[i], j);
@@ -289,41 +254,9 @@ static int regmap_irq_set_type(struct irq_data *data, unsigned int type)
reg = t->type_reg_offset / map->reg_stride;
- if (t->type_reg_mask)
- d->type_buf[reg] &= ~t->type_reg_mask;
- else
- d->type_buf[reg] &= ~(t->type_falling_val |
- t->type_rising_val |
- t->type_level_low_val |
- t->type_level_high_val);
- switch (type) {
- case IRQ_TYPE_EDGE_FALLING:
- d->type_buf[reg] |= t->type_falling_val;
- break;
-
- case IRQ_TYPE_EDGE_RISING:
- d->type_buf[reg] |= t->type_rising_val;
- break;
-
- case IRQ_TYPE_EDGE_BOTH:
- d->type_buf[reg] |= (t->type_falling_val |
- t->type_rising_val);
- break;
-
- case IRQ_TYPE_LEVEL_HIGH:
- d->type_buf[reg] |= t->type_level_high_val;
- break;
-
- case IRQ_TYPE_LEVEL_LOW:
- d->type_buf[reg] |= t->type_level_low_val;
- break;
- default:
- return -EINVAL;
- }
-
- if (d->chip->set_type_virt) {
- ret = d->chip->set_type_virt(d->virt_buf, type, data->hwirq,
- reg);
+ if (d->chip->type_in_mask) {
+ ret = regmap_irq_set_type_config_simple(&d->type_buf, type,
+ irq_data, reg, d->chip->irq_drv_data);
if (ret)
return ret;
}
@@ -390,15 +323,8 @@ static inline int read_sub_irq_data(struct regmap_irq_chip_data *data,
unsigned int offset = subreg->offset[i];
unsigned int index = offset / map->reg_stride;
- if (chip->not_fixed_stride)
- ret = regmap_read(map,
- chip->status_base + offset,
- &data->status_buf[b]);
- else
- ret = regmap_read(map,
- chip->status_base + offset,
- &data->status_buf[index]);
-
+ ret = regmap_read(map, chip->status_base + offset,
+ &data->status_buf[index]);
if (ret)
break;
}
@@ -453,17 +379,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
* sake of simplicity. and add bulk reads only if needed
*/
for (i = 0; i < chip->num_main_regs; i++) {
- /*
- * For not_fixed_stride, don't use ->get_irq_reg().
- * It would produce an incorrect result.
- */
- if (data->chip->not_fixed_stride)
- reg = chip->main_status +
- i * map->reg_stride * data->irq_reg_stride;
- else
- reg = data->get_irq_reg(data,
- chip->main_status, i);
-
+ reg = data->get_irq_reg(data, chip->main_status, i);
ret = regmap_read(map, reg, &data->main_status_buf[i]);
if (ret) {
dev_err(map->dev,
@@ -586,12 +502,12 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
}
exit:
- if (chip->runtime_pm)
- pm_runtime_put(map->dev);
-
if (chip->handle_post_irq)
chip->handle_post_irq(chip->irq_drv_data);
+ if (chip->runtime_pm)
+ pm_runtime_put(map->dev);
+
if (handled)
return IRQ_HANDLED;
else
@@ -629,20 +545,8 @@ static const struct irq_domain_ops regmap_domain_ops = {
unsigned int regmap_irq_get_irq_reg_linear(struct regmap_irq_chip_data *data,
unsigned int base, int index)
{
- const struct regmap_irq_chip *chip = data->chip;
struct regmap *map = data->map;
- /*
- * FIXME: This is for backward compatibility and should be removed
- * when not_fixed_stride is dropped (it's only used by qcom-pm8008).
- */
- if (chip->not_fixed_stride && chip->sub_reg_offsets) {
- struct regmap_irq_sub_irq_map *subreg;
-
- subreg = &chip->sub_reg_offsets[0];
- return base + subreg->offset[0];
- }
-
return base + index * map->reg_stride * data->irq_reg_stride;
}
EXPORT_SYMBOL_GPL(regmap_irq_get_irq_reg_linear);
@@ -730,8 +634,6 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
struct regmap_irq_chip_data *d;
int i;
int ret = -ENOMEM;
- int num_type_reg;
- int num_regs;
u32 reg;
if (chip->num_regs <= 0)
@@ -740,6 +642,9 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
if (chip->clear_on_unmask && (chip->ack_base || chip->use_ack))
return -EINVAL;
+ if (chip->mask_base && chip->unmask_base && !chip->mask_unmask_non_inverted)
+ return -EINVAL;
+
for (i = 0; i < chip->num_irqs; i++) {
if (chip->irqs[i].reg_offset % map->reg_stride)
return -EINVAL;
@@ -748,20 +653,6 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
return -EINVAL;
}
- if (chip->not_fixed_stride) {
- dev_warn(map->dev, "not_fixed_stride is deprecated; use ->get_irq_reg() instead");
-
- for (i = 0; i < chip->num_regs; i++)
- if (chip->sub_reg_offsets[i].num_regs != 1)
- return -EINVAL;
- }
-
- if (chip->num_type_reg)
- dev_warn(map->dev, "type registers are deprecated; use config registers instead");
-
- if (chip->num_virt_regs || chip->virt_reg_base || chip->set_type_virt)
- dev_warn(map->dev, "virtual registers are deprecated; use config registers instead");
-
if (irq_base) {
irq_base = irq_alloc_descs(irq_base, 0, chip->num_irqs, 0);
if (irq_base < 0) {
@@ -806,43 +697,17 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
goto err_alloc;
}
- /*
- * Use num_config_regs if defined, otherwise fall back to num_type_reg
- * to maintain backward compatibility.
- */
- num_type_reg = chip->num_config_regs ? chip->num_config_regs
- : chip->num_type_reg;
- num_regs = chip->type_in_mask ? chip->num_regs : num_type_reg;
- if (num_regs) {
- d->type_buf_def = kcalloc(num_regs,
+ if (chip->type_in_mask) {
+ d->type_buf_def = kcalloc(chip->num_regs,
sizeof(*d->type_buf_def), GFP_KERNEL);
if (!d->type_buf_def)
goto err_alloc;
- d->type_buf = kcalloc(num_regs, sizeof(*d->type_buf),
- GFP_KERNEL);
+ d->type_buf = kcalloc(chip->num_regs, sizeof(*d->type_buf), GFP_KERNEL);
if (!d->type_buf)
goto err_alloc;
}
- if (chip->num_virt_regs) {
- /*
- * Create virt_buf[chip->num_extra_config_regs][chip->num_regs]
- */
- d->virt_buf = kcalloc(chip->num_virt_regs, sizeof(*d->virt_buf),
- GFP_KERNEL);
- if (!d->virt_buf)
- goto err_alloc;
-
- for (i = 0; i < chip->num_virt_regs; i++) {
- d->virt_buf[i] = kcalloc(chip->num_regs,
- sizeof(**d->virt_buf),
- GFP_KERNEL);
- if (!d->virt_buf[i])
- goto err_alloc;
- }
- }
-
if (chip->num_config_bases && chip->num_config_regs) {
/*
* Create config_buf[num_config_bases][num_config_regs]
@@ -852,7 +717,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
if (!d->config_buf)
goto err_alloc;
- for (i = 0; i < chip->num_config_regs; i++) {
+ for (i = 0; i < chip->num_config_bases; i++) {
d->config_buf[i] = kcalloc(chip->num_config_regs,
sizeof(**d->config_buf),
GFP_KERNEL);
@@ -868,28 +733,6 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
d->chip = chip;
d->irq_base = irq_base;
- if (chip->mask_base && chip->unmask_base &&
- !chip->mask_unmask_non_inverted) {
- /*
- * Chips that specify both mask_base and unmask_base used to
- * get inverted mask behavior by default, with no way to ask
- * for the normal, non-inverted behavior. This "inverted by
- * default" behavior is deprecated, but we have to support it
- * until existing drivers have been fixed.
- *
- * Existing drivers should be updated by swapping mask_base
- * and unmask_base and setting mask_unmask_non_inverted=true.
- * New drivers should always set the flag.
- */
- dev_warn(map->dev, "mask_base and unmask_base are inverted, please fix it");
-
- d->mask_base = chip->unmask_base;
- d->unmask_base = chip->mask_base;
- } else {
- d->mask_base = chip->mask_base;
- d->unmask_base = chip->unmask_base;
- }
-
if (chip->irq_reg_stride)
d->irq_reg_stride = chip->irq_reg_stride;
else
@@ -918,29 +761,28 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
for (i = 0; i < chip->num_regs; i++) {
d->mask_buf[i] = d->mask_buf_def[i];
- if (d->mask_base) {
- if (chip->handle_mask_sync) {
- ret = chip->handle_mask_sync(d->map, i,
- d->mask_buf_def[i],
- d->mask_buf[i],
- chip->irq_drv_data);
- if (ret)
- goto err_alloc;
- } else {
- reg = d->get_irq_reg(d, d->mask_base, i);
- ret = regmap_update_bits(d->map, reg,
- d->mask_buf_def[i],
- d->mask_buf[i]);
- if (ret) {
- dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
- reg, ret);
- goto err_alloc;
- }
+ if (chip->handle_mask_sync) {
+ ret = chip->handle_mask_sync(i, d->mask_buf_def[i],
+ d->mask_buf[i],
+ chip->irq_drv_data);
+ if (ret)
+ goto err_alloc;
+ }
+
+ if (chip->mask_base && !chip->handle_mask_sync) {
+ reg = d->get_irq_reg(d, chip->mask_base, i);
+ ret = regmap_update_bits(d->map, reg,
+ d->mask_buf_def[i],
+ d->mask_buf[i]);
+ if (ret) {
+ dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
+ reg, ret);
+ goto err_alloc;
}
}
- if (d->unmask_base) {
- reg = d->get_irq_reg(d, d->unmask_base, i);
+ if (chip->unmask_base && !chip->handle_mask_sync) {
+ reg = d->get_irq_reg(d, chip->unmask_base, i);
ret = regmap_update_bits(d->map, reg,
d->mask_buf_def[i], ~d->mask_buf[i]);
if (ret) {
@@ -1014,20 +856,6 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
}
}
- if (chip->num_type_reg && !chip->type_in_mask) {
- for (i = 0; i < chip->num_type_reg; ++i) {
- reg = d->get_irq_reg(d, d->chip->type_base, i);
-
- ret = regmap_read(map, reg, &d->type_buf_def[i]);
-
- if (ret) {
- dev_err(map->dev, "Failed to get type defaults at 0x%x: %d\n",
- reg, ret);
- goto err_alloc;
- }
- }
- }
-
if (irq_base)
d->domain = irq_domain_create_legacy(fwnode, chip->num_irqs,
irq_base, 0,
@@ -1064,11 +892,6 @@ err_alloc:
kfree(d->mask_buf);
kfree(d->status_buf);
kfree(d->status_reg_buf);
- if (d->virt_buf) {
- for (i = 0; i < chip->num_virt_regs; i++)
- kfree(d->virt_buf[i]);
- kfree(d->virt_buf);
- }
if (d->config_buf) {
for (i = 0; i < chip->num_config_bases; i++)
kfree(d->config_buf[i]);
diff --git a/drivers/base/regmap/regmap-kunit.c b/drivers/base/regmap/regmap-kunit.c
index f76d41688134..9ff3018a46aa 100644
--- a/drivers/base/regmap/regmap-kunit.c
+++ b/drivers/base/regmap/regmap-kunit.c
@@ -58,6 +58,9 @@ static struct regmap *gen_regmap(struct regmap_config *config,
int i;
struct reg_default *defaults;
+ config->disable_locking = config->cache_type == REGCACHE_RBTREE ||
+ config->cache_type == REGCACHE_MAPLE;
+
buf = kmalloc(size, GFP_KERNEL);
if (!buf)
return ERR_PTR(-ENOMEM);
@@ -92,6 +95,11 @@ static struct regmap *gen_regmap(struct regmap_config *config,
return ret;
}
+static bool reg_5_false(struct device *context, unsigned int reg)
+{
+ return reg != 5;
+}
+
static void basic_read_write(struct kunit *test)
{
struct regcache_types *t = (struct regcache_types *)test->param_value;
@@ -191,6 +199,81 @@ static void bulk_read(struct kunit *test)
regmap_exit(map);
}
+static void write_readonly(struct kunit *test)
+{
+ struct regcache_types *t = (struct regcache_types *)test->param_value;
+ struct regmap *map;
+ struct regmap_config config;
+ struct regmap_ram_data *data;
+ unsigned int val;
+ int i;
+
+ config = test_regmap_config;
+ config.cache_type = t->type;
+ config.num_reg_defaults = BLOCK_TEST_SIZE;
+ config.writeable_reg = reg_5_false;
+
+ map = gen_regmap(&config, &data);
+ KUNIT_ASSERT_FALSE(test, IS_ERR(map));
+ if (IS_ERR(map))
+ return;
+
+ get_random_bytes(&val, sizeof(val));
+
+ for (i = 0; i < BLOCK_TEST_SIZE; i++)
+ data->written[i] = false;
+
+ /* Change the value of all registers, readonly should fail */
+ for (i = 0; i < BLOCK_TEST_SIZE; i++)
+ KUNIT_EXPECT_EQ(test, i != 5, regmap_write(map, i, val) == 0);
+
+ /* Did that match what we see on the device? */
+ for (i = 0; i < BLOCK_TEST_SIZE; i++)
+ KUNIT_EXPECT_EQ(test, i != 5, data->written[i]);
+
+ regmap_exit(map);
+}
+
+static void read_writeonly(struct kunit *test)
+{
+ struct regcache_types *t = (struct regcache_types *)test->param_value;
+ struct regmap *map;
+ struct regmap_config config;
+ struct regmap_ram_data *data;
+ unsigned int val;
+ int i;
+
+ config = test_regmap_config;
+ config.cache_type = t->type;
+ config.readable_reg = reg_5_false;
+
+ map = gen_regmap(&config, &data);
+ KUNIT_ASSERT_FALSE(test, IS_ERR(map));
+ if (IS_ERR(map))
+ return;
+
+ for (i = 0; i < BLOCK_TEST_SIZE; i++)
+ data->read[i] = false;
+
+ /*
+ * Try to read all the registers, the writeonly one should
+ * fail if we aren't using the flat cache.
+ */
+ for (i = 0; i < BLOCK_TEST_SIZE; i++) {
+ if (t->type != REGCACHE_FLAT) {
+ KUNIT_EXPECT_EQ(test, i != 5,
+ regmap_read(map, i, &val) == 0);
+ } else {
+ KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &val));
+ }
+ }
+
+ /* Did we trigger a hardware access? */
+ KUNIT_EXPECT_FALSE(test, data->read[5]);
+
+ regmap_exit(map);
+}
+
static void reg_defaults(struct kunit *test)
{
struct regcache_types *t = (struct regcache_types *)test->param_value;
@@ -609,6 +692,47 @@ static void cache_sync_defaults(struct kunit *test)
regmap_exit(map);
}
+static void cache_sync_readonly(struct kunit *test)
+{
+ struct regcache_types *t = (struct regcache_types *)test->param_value;
+ struct regmap *map;
+ struct regmap_config config;
+ struct regmap_ram_data *data;
+ unsigned int val;
+ int i;
+
+ config = test_regmap_config;
+ config.cache_type = t->type;
+ config.writeable_reg = reg_5_false;
+
+ map = gen_regmap(&config, &data);
+ KUNIT_ASSERT_FALSE(test, IS_ERR(map));
+ if (IS_ERR(map))
+ return;
+
+ /* Read all registers to fill the cache */
+ for (i = 0; i < BLOCK_TEST_SIZE; i++)
+ KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &val));
+
+ /* Change the value of all registers, readonly should fail */
+ get_random_bytes(&val, sizeof(val));
+ regcache_cache_only(map, true);
+ for (i = 0; i < BLOCK_TEST_SIZE; i++)
+ KUNIT_EXPECT_EQ(test, i != 5, regmap_write(map, i, val) == 0);
+ regcache_cache_only(map, false);
+
+ /* Resync */
+ for (i = 0; i < BLOCK_TEST_SIZE; i++)
+ data->written[i] = false;
+ KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
+
+ /* Did that match what we see on the device? */
+ for (i = 0; i < BLOCK_TEST_SIZE; i++)
+ KUNIT_EXPECT_EQ(test, i != 5, data->written[i]);
+
+ regmap_exit(map);
+}
+
static void cache_sync_patch(struct kunit *test)
{
struct regcache_types *t = (struct regcache_types *)test->param_value;
@@ -712,10 +836,335 @@ static void cache_drop(struct kunit *test)
regmap_exit(map);
}
+struct raw_test_types {
+ const char *name;
+
+ enum regcache_type cache_type;
+ enum regmap_endian val_endian;
+};
+
+static void raw_to_desc(const struct raw_test_types *t, char *desc)
+{
+ strcpy(desc, t->name);
+}
+
+static const struct raw_test_types raw_types_list[] = {
+ { "none-little", REGCACHE_NONE, REGMAP_ENDIAN_LITTLE },
+ { "none-big", REGCACHE_NONE, REGMAP_ENDIAN_BIG },
+ { "flat-little", REGCACHE_FLAT, REGMAP_ENDIAN_LITTLE },
+ { "flat-big", REGCACHE_FLAT, REGMAP_ENDIAN_BIG },
+ { "rbtree-little", REGCACHE_RBTREE, REGMAP_ENDIAN_LITTLE },
+ { "rbtree-big", REGCACHE_RBTREE, REGMAP_ENDIAN_BIG },
+ { "maple-little", REGCACHE_MAPLE, REGMAP_ENDIAN_LITTLE },
+ { "maple-big", REGCACHE_MAPLE, REGMAP_ENDIAN_BIG },
+};
+
+KUNIT_ARRAY_PARAM(raw_test_types, raw_types_list, raw_to_desc);
+
+static const struct raw_test_types raw_cache_types_list[] = {
+ { "flat-little", REGCACHE_FLAT, REGMAP_ENDIAN_LITTLE },
+ { "flat-big", REGCACHE_FLAT, REGMAP_ENDIAN_BIG },
+ { "rbtree-little", REGCACHE_RBTREE, REGMAP_ENDIAN_LITTLE },
+ { "rbtree-big", REGCACHE_RBTREE, REGMAP_ENDIAN_BIG },
+ { "maple-little", REGCACHE_MAPLE, REGMAP_ENDIAN_LITTLE },
+ { "maple-big", REGCACHE_MAPLE, REGMAP_ENDIAN_BIG },
+};
+
+KUNIT_ARRAY_PARAM(raw_test_cache_types, raw_cache_types_list, raw_to_desc);
+
+static const struct regmap_config raw_regmap_config = {
+ .max_register = BLOCK_TEST_SIZE,
+
+ .reg_format_endian = REGMAP_ENDIAN_LITTLE,
+ .reg_bits = 16,
+ .val_bits = 16,
+};
+
+static struct regmap *gen_raw_regmap(struct regmap_config *config,
+ struct raw_test_types *test_type,
+ struct regmap_ram_data **data)
+{
+ u16 *buf;
+ struct regmap *ret;
+ size_t size = (config->max_register + 1) * config->reg_bits / 8;
+ int i;
+ struct reg_default *defaults;
+
+ config->cache_type = test_type->cache_type;
+ config->val_format_endian = test_type->val_endian;
+ config->disable_locking = config->cache_type == REGCACHE_RBTREE ||
+ config->cache_type == REGCACHE_MAPLE;
+
+ buf = kmalloc(size, GFP_KERNEL);
+ if (!buf)
+ return ERR_PTR(-ENOMEM);
+
+ get_random_bytes(buf, size);
+
+ *data = kzalloc(sizeof(**data), GFP_KERNEL);
+ if (!(*data))
+ return ERR_PTR(-ENOMEM);
+ (*data)->vals = (void *)buf;
+
+ config->num_reg_defaults = config->max_register + 1;
+ defaults = kcalloc(config->num_reg_defaults,
+ sizeof(struct reg_default),
+ GFP_KERNEL);
+ if (!defaults)
+ return ERR_PTR(-ENOMEM);
+ config->reg_defaults = defaults;
+
+ for (i = 0; i < config->num_reg_defaults; i++) {
+ defaults[i].reg = i;
+ switch (test_type->val_endian) {
+ case REGMAP_ENDIAN_LITTLE:
+ defaults[i].def = le16_to_cpu(buf[i]);
+ break;
+ case REGMAP_ENDIAN_BIG:
+ defaults[i].def = be16_to_cpu(buf[i]);
+ break;
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+ }
+
+ /*
+ * We use the defaults in the tests but they don't make sense
+ * to the core if there's no cache.
+ */
+ if (config->cache_type == REGCACHE_NONE)
+ config->num_reg_defaults = 0;
+
+ ret = regmap_init_raw_ram(config, *data);
+ if (IS_ERR(ret)) {
+ kfree(buf);
+ kfree(*data);
+ }
+
+ return ret;
+}
+
+static void raw_read_defaults_single(struct kunit *test)
+{
+ struct raw_test_types *t = (struct raw_test_types *)test->param_value;
+ struct regmap *map;
+ struct regmap_config config;
+ struct regmap_ram_data *data;
+ unsigned int rval;
+ int i;
+
+ config = raw_regmap_config;
+
+ map = gen_raw_regmap(&config, t, &data);
+ KUNIT_ASSERT_FALSE(test, IS_ERR(map));
+ if (IS_ERR(map))
+ return;
+
+ /* Check that we can read the defaults via the API */
+ for (i = 0; i < config.max_register + 1; i++) {
+ KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval));
+ KUNIT_EXPECT_EQ(test, config.reg_defaults[i].def, rval);
+ }
+
+ regmap_exit(map);
+}
+
+static void raw_read_defaults(struct kunit *test)
+{
+ struct raw_test_types *t = (struct raw_test_types *)test->param_value;
+ struct regmap *map;
+ struct regmap_config config;
+ struct regmap_ram_data *data;
+ u16 *rval;
+ u16 def;
+ size_t val_len;
+ int i;
+
+ config = raw_regmap_config;
+
+ map = gen_raw_regmap(&config, t, &data);
+ KUNIT_ASSERT_FALSE(test, IS_ERR(map));
+ if (IS_ERR(map))
+ return;
+
+ val_len = sizeof(*rval) * (config.max_register + 1);
+ rval = kmalloc(val_len, GFP_KERNEL);
+ KUNIT_ASSERT_TRUE(test, rval != NULL);
+ if (!rval)
+ return;
+
+ /* Check that we can read the defaults via the API */
+ KUNIT_EXPECT_EQ(test, 0, regmap_raw_read(map, 0, rval, val_len));
+ for (i = 0; i < config.max_register + 1; i++) {
+ def = config.reg_defaults[i].def;
+ if (config.val_format_endian == REGMAP_ENDIAN_BIG) {
+ KUNIT_EXPECT_EQ(test, def, be16_to_cpu(rval[i]));
+ } else {
+ KUNIT_EXPECT_EQ(test, def, le16_to_cpu(rval[i]));
+ }
+ }
+
+ kfree(rval);
+ regmap_exit(map);
+}
+
+static void raw_write_read_single(struct kunit *test)
+{
+ struct raw_test_types *t = (struct raw_test_types *)test->param_value;
+ struct regmap *map;
+ struct regmap_config config;
+ struct regmap_ram_data *data;
+ u16 val;
+ unsigned int rval;
+
+ config = raw_regmap_config;
+
+ map = gen_raw_regmap(&config, t, &data);
+ KUNIT_ASSERT_FALSE(test, IS_ERR(map));
+ if (IS_ERR(map))
+ return;
+
+ get_random_bytes(&val, sizeof(val));
+
+ /* If we write a value to a register we can read it back */
+ KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 0, val));
+ KUNIT_EXPECT_EQ(test, 0, regmap_read(map, 0, &rval));
+ KUNIT_EXPECT_EQ(test, val, rval);
+
+ regmap_exit(map);
+}
+
+static void raw_write(struct kunit *test)
+{
+ struct raw_test_types *t = (struct raw_test_types *)test->param_value;
+ struct regmap *map;
+ struct regmap_config config;
+ struct regmap_ram_data *data;
+ u16 *hw_buf;
+ u16 val[2];
+ unsigned int rval;
+ int i;
+
+ config = raw_regmap_config;
+
+ map = gen_raw_regmap(&config, t, &data);
+ KUNIT_ASSERT_FALSE(test, IS_ERR(map));
+ if (IS_ERR(map))
+ return;
+
+ hw_buf = (u16 *)data->vals;
+
+ get_random_bytes(&val, sizeof(val));
+
+ /* Do a raw write */
+ KUNIT_EXPECT_EQ(test, 0, regmap_raw_write(map, 2, val, sizeof(val)));
+
+ /* We should read back the new values, and defaults for the rest */
+ for (i = 0; i < config.max_register + 1; i++) {
+ KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval));
+
+ switch (i) {
+ case 2:
+ case 3:
+ if (config.val_format_endian == REGMAP_ENDIAN_BIG) {
+ KUNIT_EXPECT_EQ(test, rval,
+ be16_to_cpu(val[i % 2]));
+ } else {
+ KUNIT_EXPECT_EQ(test, rval,
+ le16_to_cpu(val[i % 2]));
+ }
+ break;
+ default:
+ KUNIT_EXPECT_EQ(test, config.reg_defaults[i].def, rval);
+ break;
+ }
+ }
+
+ /* The values should appear in the "hardware" */
+ KUNIT_EXPECT_MEMEQ(test, &hw_buf[2], val, sizeof(val));
+
+ regmap_exit(map);
+}
+
+static void raw_sync(struct kunit *test)
+{
+ struct raw_test_types *t = (struct raw_test_types *)test->param_value;
+ struct regmap *map;
+ struct regmap_config config;
+ struct regmap_ram_data *data;
+ u16 val[2];
+ u16 *hw_buf;
+ unsigned int rval;
+ int i;
+
+ config = raw_regmap_config;
+
+ map = gen_raw_regmap(&config, t, &data);
+ KUNIT_ASSERT_FALSE(test, IS_ERR(map));
+ if (IS_ERR(map))
+ return;
+
+ hw_buf = (u16 *)data->vals;
+
+ get_random_bytes(&val, sizeof(val));
+
+ /* Do a regular write and a raw write in cache only mode */
+ regcache_cache_only(map, true);
+ KUNIT_EXPECT_EQ(test, 0, regmap_raw_write(map, 2, val, sizeof(val)));
+ if (config.val_format_endian == REGMAP_ENDIAN_BIG)
+ KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 6,
+ be16_to_cpu(val[0])));
+ else
+ KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 6,
+ le16_to_cpu(val[0])));
+
+ /* We should read back the new values, and defaults for the rest */
+ for (i = 0; i < config.max_register + 1; i++) {
+ KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval));
+
+ switch (i) {
+ case 2:
+ case 3:
+ case 6:
+ if (config.val_format_endian == REGMAP_ENDIAN_BIG) {
+ KUNIT_EXPECT_EQ(test, rval,
+ be16_to_cpu(val[i % 2]));
+ } else {
+ KUNIT_EXPECT_EQ(test, rval,
+ le16_to_cpu(val[i % 2]));
+ }
+ break;
+ default:
+ KUNIT_EXPECT_EQ(test, config.reg_defaults[i].def, rval);
+ break;
+ }
+ }
+
+ /* The values should not appear in the "hardware" */
+ KUNIT_EXPECT_MEMNEQ(test, &hw_buf[2], val, sizeof(val));
+ KUNIT_EXPECT_MEMNEQ(test, &hw_buf[6], val, sizeof(u16));
+
+ for (i = 0; i < config.max_register + 1; i++)
+ data->written[i] = false;
+
+ /* Do the sync */
+ regcache_cache_only(map, false);
+ regcache_mark_dirty(map);
+ KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
+
+ /* The values should now appear in the "hardware" */
+ KUNIT_EXPECT_MEMEQ(test, &hw_buf[2], val, sizeof(val));
+ KUNIT_EXPECT_MEMEQ(test, &hw_buf[6], val, sizeof(u16));
+
+ regmap_exit(map);
+}
+
static struct kunit_case regmap_test_cases[] = {
KUNIT_CASE_PARAM(basic_read_write, regcache_types_gen_params),
KUNIT_CASE_PARAM(bulk_write, regcache_types_gen_params),
KUNIT_CASE_PARAM(bulk_read, regcache_types_gen_params),
+ KUNIT_CASE_PARAM(write_readonly, regcache_types_gen_params),
+ KUNIT_CASE_PARAM(read_writeonly, regcache_types_gen_params),
KUNIT_CASE_PARAM(reg_defaults, regcache_types_gen_params),
KUNIT_CASE_PARAM(reg_defaults_read_dev, regcache_types_gen_params),
KUNIT_CASE_PARAM(register_patch, regcache_types_gen_params),
@@ -725,8 +1174,15 @@ static struct kunit_case regmap_test_cases[] = {
KUNIT_CASE_PARAM(cache_bypass, real_cache_types_gen_params),
KUNIT_CASE_PARAM(cache_sync, real_cache_types_gen_params),
KUNIT_CASE_PARAM(cache_sync_defaults, real_cache_types_gen_params),
+ KUNIT_CASE_PARAM(cache_sync_readonly, real_cache_types_gen_params),
KUNIT_CASE_PARAM(cache_sync_patch, real_cache_types_gen_params),
KUNIT_CASE_PARAM(cache_drop, sparse_cache_types_gen_params),
+
+ KUNIT_CASE_PARAM(raw_read_defaults_single, raw_test_types_gen_params),
+ KUNIT_CASE_PARAM(raw_read_defaults, raw_test_types_gen_params),
+ KUNIT_CASE_PARAM(raw_write_read_single, raw_test_types_gen_params),
+ KUNIT_CASE_PARAM(raw_write, raw_test_types_gen_params),
+ KUNIT_CASE_PARAM(raw_sync, raw_test_cache_types_gen_params),
{}
};
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c
index 3ccdd86a97e7..8132b5c101c4 100644
--- a/drivers/base/regmap/regmap-mmio.c
+++ b/drivers/base/regmap/regmap-mmio.c
@@ -448,7 +448,7 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
if (min_stride < 0)
return ERR_PTR(min_stride);
- if (config->reg_stride < min_stride)
+ if (config->reg_stride && config->reg_stride < min_stride)
return ERR_PTR(-EINVAL);
if (config->use_relaxed_mmio && config->io_port)
diff --git a/drivers/base/regmap/regmap-raw-ram.c b/drivers/base/regmap/regmap-raw-ram.c
new file mode 100644
index 000000000000..c9b800885f3b
--- /dev/null
+++ b/drivers/base/regmap/regmap-raw-ram.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Register map access API - Memory region with raw access
+//
+// This is intended for testing only
+//
+// Copyright (c) 2023, Arm Ltd
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/swab.h>
+
+#include "internal.h"
+
+static unsigned int decode_reg(enum regmap_endian endian, const void *reg)
+{
+ const u16 *r = reg;
+
+ if (endian == REGMAP_ENDIAN_BIG)
+ return be16_to_cpu(*r);
+ else
+ return le16_to_cpu(*r);
+}
+
+static int regmap_raw_ram_gather_write(void *context,
+ const void *reg, size_t reg_len,
+ const void *val, size_t val_len)
+{
+ struct regmap_ram_data *data = context;
+ unsigned int r;
+ u16 *our_buf = (u16 *)data->vals;
+ int i;
+
+ if (reg_len != 2)
+ return -EINVAL;
+ if (val_len % 2)
+ return -EINVAL;
+
+ r = decode_reg(data->reg_endian, reg);
+ memcpy(&our_buf[r], val, val_len);
+
+ for (i = 0; i < val_len / 2; i++)
+ data->written[r + i] = true;
+
+ return 0;
+}
+
+static int regmap_raw_ram_write(void *context, const void *data, size_t count)
+{
+ return regmap_raw_ram_gather_write(context, data, 2,
+ data + 2, count - 2);
+}
+
+static int regmap_raw_ram_read(void *context,
+ const void *reg, size_t reg_len,
+ void *val, size_t val_len)
+{
+ struct regmap_ram_data *data = context;
+ unsigned int r;
+ u16 *our_buf = (u16 *)data->vals;
+ int i;
+
+ if (reg_len != 2)
+ return -EINVAL;
+ if (val_len % 2)
+ return -EINVAL;
+
+ r = decode_reg(data->reg_endian, reg);
+ memcpy(val, &our_buf[r], val_len);
+
+ for (i = 0; i < val_len / 2; i++)
+ data->read[r + i] = true;
+
+ return 0;
+}
+
+static void regmap_raw_ram_free_context(void *context)
+{
+ struct regmap_ram_data *data = context;
+
+ kfree(data->vals);
+ kfree(data->read);
+ kfree(data->written);
+ kfree(data);
+}
+
+static const struct regmap_bus regmap_raw_ram = {
+ .fast_io = true,
+ .write = regmap_raw_ram_write,
+ .gather_write = regmap_raw_ram_gather_write,
+ .read = regmap_raw_ram_read,
+ .free_context = regmap_raw_ram_free_context,
+};
+
+struct regmap *__regmap_init_raw_ram(const struct regmap_config *config,
+ struct regmap_ram_data *data,
+ struct lock_class_key *lock_key,
+ const char *lock_name)
+{
+ struct regmap *map;
+
+ if (config->reg_bits != 16)
+ return ERR_PTR(-EINVAL);
+
+ if (!config->max_register) {
+ pr_crit("No max_register specified for RAM regmap\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ data->read = kcalloc(sizeof(bool), config->max_register + 1,
+ GFP_KERNEL);
+ if (!data->read)
+ return ERR_PTR(-ENOMEM);
+
+ data->written = kcalloc(sizeof(bool), config->max_register + 1,
+ GFP_KERNEL);
+ if (!data->written)
+ return ERR_PTR(-ENOMEM);
+
+ data->reg_endian = config->reg_format_endian;
+
+ map = __regmap_init(NULL, &regmap_raw_ram, data, config,
+ lock_key, lock_name);
+
+ return map;
+}
+EXPORT_SYMBOL_GPL(__regmap_init_raw_ram);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/base/regmap/regmap-spi-avmm.c b/drivers/base/regmap/regmap-spi-avmm.c
index 6af692844c19..4c2b94b3e30b 100644
--- a/drivers/base/regmap/regmap-spi-avmm.c
+++ b/drivers/base/regmap/regmap-spi-avmm.c
@@ -660,7 +660,7 @@ static const struct regmap_bus regmap_spi_avmm_bus = {
.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
.max_raw_read = SPI_AVMM_VAL_SIZE * MAX_READ_CNT,
- .max_raw_write = SPI_AVMM_REG_SIZE + SPI_AVMM_VAL_SIZE * MAX_WRITE_CNT,
+ .max_raw_write = SPI_AVMM_VAL_SIZE * MAX_WRITE_CNT,
.free_context = spi_avmm_bridge_ctx_free,
};
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index fa2d3fba6ac9..1bfd1727b4da 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -2082,8 +2082,6 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
size_t val_count = val_len / val_bytes;
size_t chunk_count, chunk_bytes;
size_t chunk_regs = val_count;
- size_t max_data = map->max_raw_write - map->format.reg_bytes -
- map->format.pad_bytes;
int ret, i;
if (!val_count)
@@ -2091,8 +2089,8 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
if (map->use_single_write)
chunk_regs = 1;
- else if (map->max_raw_write && val_len > max_data)
- chunk_regs = max_data / val_bytes;
+ else if (map->max_raw_write && val_len > map->max_raw_write)
+ chunk_regs = map->max_raw_write / val_bytes;
chunk_count = val_count / chunk_regs;
chunk_bytes = chunk_regs * val_bytes;
@@ -2983,6 +2981,11 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
size_t chunk_count, chunk_bytes;
size_t chunk_regs = val_count;
+ if (!map->cache_bypass && map->cache_only) {
+ ret = -EBUSY;
+ goto out;
+ }
+
if (!map->read) {
ret = -ENOTSUPP;
goto out;
@@ -3078,18 +3081,19 @@ int regmap_noinc_read(struct regmap *map, unsigned int reg,
goto out_unlock;
}
+ /*
+ * We have not defined the FIFO semantics for cache, as the
+ * cache is just one value deep. Should we return the last
+ * written value? Just avoid this by always reading the FIFO
+ * even when using cache. Cache only will not work.
+ */
+ if (!map->cache_bypass && map->cache_only) {
+ ret = -EBUSY;
+ goto out_unlock;
+ }
+
/* Use the accelerated operation if we can */
if (map->bus->reg_noinc_read) {
- /*
- * We have not defined the FIFO semantics for cache, as the
- * cache is just one value deep. Should we return the last
- * written value? Just avoid this by always reading the FIFO
- * even when using cache. Cache only will not work.
- */
- if (map->cache_only) {
- ret = -EBUSY;
- goto out_unlock;
- }
ret = regmap_noinc_readwrite(map, reg, val, val_len, false);
goto out_unlock;
}
@@ -3273,7 +3277,7 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
tmp = orig & ~mask;
tmp |= val & mask;
- if (force_write || (tmp != orig)) {
+ if (force_write || (tmp != orig) || map->force_write_field) {
ret = _regmap_write(map, reg, tmp);
if (ret == 0 && change)
*change = true;
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 4c8b2ba579ee..e460c9799d9f 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1532,7 +1532,7 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}
-static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
+static int fd_locked_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long param)
{
struct amiga_floppy_struct *p = bdev->bd_disk->private_data;
@@ -1607,7 +1607,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
return 0;
}
-static int fd_ioctl(struct block_device *bdev, fmode_t mode,
+static int fd_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long param)
{
int ret;
@@ -1654,10 +1654,10 @@ static void fd_probe(int dev)
* /dev/PS0 etc), and disallows simultaneous access to the same
* drive with different device numbers.
*/
-static int floppy_open(struct block_device *bdev, fmode_t mode)
+static int floppy_open(struct gendisk *disk, blk_mode_t mode)
{
- int drive = MINOR(bdev->bd_dev) & 3;
- int system = (MINOR(bdev->bd_dev) & 4) >> 2;
+ int drive = disk->first_minor & 3;
+ int system = (disk->first_minor & 4) >> 2;
int old_dev;
unsigned long flags;
@@ -1673,10 +1673,9 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
mutex_unlock(&amiflop_mutex);
return -ENXIO;
}
-
- if (mode & (FMODE_READ|FMODE_WRITE)) {
- bdev_check_media_change(bdev);
- if (mode & FMODE_WRITE) {
+ if (mode & (BLK_OPEN_READ | BLK_OPEN_WRITE)) {
+ disk_check_media_change(disk);
+ if (mode & BLK_OPEN_WRITE) {
int wrprot;
get_fdc(drive);
@@ -1691,7 +1690,6 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
}
}
}
-
local_irq_save(flags);
fd_ref[drive]++;
fd_device[drive] = system;
@@ -1709,7 +1707,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
return 0;
}
-static void floppy_release(struct gendisk *disk, fmode_t mode)
+static void floppy_release(struct gendisk *disk)
{
struct amiga_floppy_struct *p = disk->private_data;
int drive = p - unit;
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index 128722cf6c3c..cf6883756155 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -204,9 +204,9 @@ aoedisk_rm_debugfs(struct aoedev *d)
}
static int
-aoeblk_open(struct block_device *bdev, fmode_t mode)
+aoeblk_open(struct gendisk *disk, blk_mode_t mode)
{
- struct aoedev *d = bdev->bd_disk->private_data;
+ struct aoedev *d = disk->private_data;
ulong flags;
if (!virt_addr_valid(d)) {
@@ -232,7 +232,7 @@ aoeblk_open(struct block_device *bdev, fmode_t mode)
}
static void
-aoeblk_release(struct gendisk *disk, fmode_t mode)
+aoeblk_release(struct gendisk *disk)
{
struct aoedev *d = disk->private_data;
ulong flags;
@@ -285,7 +285,7 @@ aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
}
static int
-aoeblk_ioctl(struct block_device *bdev, fmode_t mode, uint cmd, ulong arg)
+aoeblk_ioctl(struct block_device *bdev, blk_mode_t mode, uint cmd, ulong arg)
{
struct aoedev *d;
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 4c666f72203f..a42c4bcc85ba 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -49,7 +49,7 @@ static int emsgs_head_idx, emsgs_tail_idx;
static struct completion emsgs_comp;
static spinlock_t emsgs_lock;
static int nblocked_emsgs_readers;
-static struct class *aoe_class;
+
static struct aoe_chardev chardevs[] = {
{ MINOR_ERR, "err" },
{ MINOR_DISCOVER, "discover" },
@@ -58,6 +58,16 @@ static struct aoe_chardev chardevs[] = {
{ MINOR_FLUSH, "flush" },
};
+static char *aoe_devnode(const struct device *dev, umode_t *mode)
+{
+ return kasprintf(GFP_KERNEL, "etherd/%s", dev_name(dev));
+}
+
+static const struct class aoe_class = {
+ .name = "aoe",
+ .devnode = aoe_devnode,
+};
+
static int
discover(void)
{
@@ -273,11 +283,6 @@ static const struct file_operations aoe_fops = {
.llseek = noop_llseek,
};
-static char *aoe_devnode(const struct device *dev, umode_t *mode)
-{
- return kasprintf(GFP_KERNEL, "etherd/%s", dev_name(dev));
-}
-
int __init
aoechr_init(void)
{
@@ -290,15 +295,14 @@ aoechr_init(void)
}
init_completion(&emsgs_comp);
spin_lock_init(&emsgs_lock);
- aoe_class = class_create("aoe");
- if (IS_ERR(aoe_class)) {
+ n = class_register(&aoe_class);
+ if (n) {
unregister_chrdev(AOE_MAJOR, "aoechr");
- return PTR_ERR(aoe_class);
+ return n;
}
- aoe_class->devnode = aoe_devnode;
for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
- device_create(aoe_class, NULL,
+ device_create(&aoe_class, NULL,
MKDEV(AOE_MAJOR, chardevs[i].minor), NULL,
chardevs[i].name);
@@ -311,8 +315,8 @@ aoechr_exit(void)
int i;
for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
- device_destroy(aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor));
- class_destroy(aoe_class);
+ device_destroy(&aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor));
+ class_unregister(&aoe_class);
unregister_chrdev(AOE_MAJOR, "aoechr");
}
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 9deb4df6bdb8..cd738cab725f 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -442,13 +442,13 @@ static void fd_times_out(struct timer_list *unused);
static void finish_fdc( void );
static void finish_fdc_done( int dummy );
static void setup_req_params( int drive );
-static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
- cmd, unsigned long param);
+static int fd_locked_ioctl(struct block_device *bdev, blk_mode_t mode,
+ unsigned int cmd, unsigned long param);
static void fd_probe( int drive );
static int fd_test_drive_present( int drive );
static void config_types( void );
-static int floppy_open(struct block_device *bdev, fmode_t mode);
-static void floppy_release(struct gendisk *disk, fmode_t mode);
+static int floppy_open(struct gendisk *disk, blk_mode_t mode);
+static void floppy_release(struct gendisk *disk);
/************************* End of Prototypes **************************/
@@ -1581,7 +1581,7 @@ out:
return BLK_STS_OK;
}
-static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
+static int fd_locked_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long param)
{
struct gendisk *disk = bdev->bd_disk;
@@ -1760,15 +1760,15 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
/* invalidate the buffer track to force a reread */
BufferDrive = -1;
set_bit(drive, &fake_change);
- if (bdev_check_media_change(bdev))
- floppy_revalidate(bdev->bd_disk);
+ if (disk_check_media_change(disk))
+ floppy_revalidate(disk);
return 0;
default:
return -EINVAL;
}
}
-static int fd_ioctl(struct block_device *bdev, fmode_t mode,
+static int fd_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long arg)
{
int ret;
@@ -1915,32 +1915,31 @@ static void __init config_types( void )
* drive with different device numbers.
*/
-static int floppy_open(struct block_device *bdev, fmode_t mode)
+static int floppy_open(struct gendisk *disk, blk_mode_t mode)
{
- struct atari_floppy_struct *p = bdev->bd_disk->private_data;
- int type = MINOR(bdev->bd_dev) >> 2;
+ struct atari_floppy_struct *p = disk->private_data;
+ int type = disk->first_minor >> 2;
DPRINT(("fd_open: type=%d\n",type));
if (p->ref && p->type != type)
return -EBUSY;
- if (p->ref == -1 || (p->ref && mode & FMODE_EXCL))
+ if (p->ref == -1 || (p->ref && mode & BLK_OPEN_EXCL))
return -EBUSY;
-
- if (mode & FMODE_EXCL)
+ if (mode & BLK_OPEN_EXCL)
p->ref = -1;
else
p->ref++;
p->type = type;
- if (mode & FMODE_NDELAY)
+ if (mode & BLK_OPEN_NDELAY)
return 0;
- if (mode & (FMODE_READ|FMODE_WRITE)) {
- if (bdev_check_media_change(bdev))
- floppy_revalidate(bdev->bd_disk);
- if (mode & FMODE_WRITE) {
+ if (mode & (BLK_OPEN_READ | BLK_OPEN_WRITE)) {
+ if (disk_check_media_change(disk))
+ floppy_revalidate(disk);
+ if (mode & BLK_OPEN_WRITE) {
if (p->wpstat) {
if (p->ref < 0)
p->ref = 0;
@@ -1953,18 +1952,18 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
return 0;
}
-static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode)
+static int floppy_unlocked_open(struct gendisk *disk, blk_mode_t mode)
{
int ret;
mutex_lock(&ataflop_mutex);
- ret = floppy_open(bdev, mode);
+ ret = floppy_open(disk, mode);
mutex_unlock(&ataflop_mutex);
return ret;
}
-static void floppy_release(struct gendisk *disk, fmode_t mode)
+static void floppy_release(struct gendisk *disk)
{
struct atari_floppy_struct *p = disk->private_data;
mutex_lock(&ataflop_mutex);
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index bcad9b926b0c..970bd6ff38c4 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -19,7 +19,7 @@
#include <linux/highmem.h>
#include <linux/mutex.h>
#include <linux/pagemap.h>
-#include <linux/radix-tree.h>
+#include <linux/xarray.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/backing-dev.h>
@@ -28,7 +28,7 @@
#include <linux/uaccess.h>
/*
- * Each block ramdisk device has a radix_tree brd_pages of pages that stores
+ * Each block ramdisk device has a xarray brd_pages of pages that stores
* the pages containing the block device's contents. A brd page's ->index is
* its offset in PAGE_SIZE units. This is similar to, but in no way connected
* with, the kernel's pagecache or buffer cache (which sit above our block
@@ -40,11 +40,9 @@ struct brd_device {
struct list_head brd_list;
/*
- * Backing store of pages and lock to protect it. This is the contents
- * of the block device.
+ * Backing store of pages. This is the contents of the block device.
*/
- spinlock_t brd_lock;
- struct radix_tree_root brd_pages;
+ struct xarray brd_pages;
u64 brd_nr_pages;
};
@@ -56,21 +54,8 @@ static struct page *brd_lookup_page(struct brd_device *brd, sector_t sector)
pgoff_t idx;
struct page *page;
- /*
- * The page lifetime is protected by the fact that we have opened the
- * device node -- brd pages will never be deleted under us, so we
- * don't need any further locking or refcounting.
- *
- * This is strictly true for the radix-tree nodes as well (ie. we
- * don't actually need the rcu_read_lock()), however that is not a
- * documented feature of the radix-tree API so it is better to be
- * safe here (we don't have total exclusion from radix tree updates
- * here, only deletes).
- */
- rcu_read_lock();
idx = sector >> PAGE_SECTORS_SHIFT; /* sector to page index */
- page = radix_tree_lookup(&brd->brd_pages, idx);
- rcu_read_unlock();
+ page = xa_load(&brd->brd_pages, idx);
BUG_ON(page && page->index != idx);
@@ -83,7 +68,7 @@ static struct page *brd_lookup_page(struct brd_device *brd, sector_t sector)
static int brd_insert_page(struct brd_device *brd, sector_t sector, gfp_t gfp)
{
pgoff_t idx;
- struct page *page;
+ struct page *page, *cur;
int ret = 0;
page = brd_lookup_page(brd, sector);
@@ -94,71 +79,42 @@ static int brd_insert_page(struct brd_device *brd, sector_t sector, gfp_t gfp)
if (!page)
return -ENOMEM;
- if (radix_tree_maybe_preload(gfp)) {
- __free_page(page);
- return -ENOMEM;
- }
+ xa_lock(&brd->brd_pages);
- spin_lock(&brd->brd_lock);
idx = sector >> PAGE_SECTORS_SHIFT;
page->index = idx;
- if (radix_tree_insert(&brd->brd_pages, idx, page)) {
+
+ cur = __xa_cmpxchg(&brd->brd_pages, idx, NULL, page, gfp);
+
+ if (unlikely(cur)) {
__free_page(page);
- page = radix_tree_lookup(&brd->brd_pages, idx);
- if (!page)
- ret = -ENOMEM;
- else if (page->index != idx)
+ ret = xa_err(cur);
+ if (!ret && (cur->index != idx))
ret = -EIO;
} else {
brd->brd_nr_pages++;
}
- spin_unlock(&brd->brd_lock);
- radix_tree_preload_end();
+ xa_unlock(&brd->brd_pages);
+
return ret;
}
/*
- * Free all backing store pages and radix tree. This must only be called when
+ * Free all backing store pages and xarray. This must only be called when
* there are no other users of the device.
*/
-#define FREE_BATCH 16
static void brd_free_pages(struct brd_device *brd)
{
- unsigned long pos = 0;
- struct page *pages[FREE_BATCH];
- int nr_pages;
-
- do {
- int i;
-
- nr_pages = radix_tree_gang_lookup(&brd->brd_pages,
- (void **)pages, pos, FREE_BATCH);
-
- for (i = 0; i < nr_pages; i++) {
- void *ret;
-
- BUG_ON(pages[i]->index < pos);
- pos = pages[i]->index;
- ret = radix_tree_delete(&brd->brd_pages, pos);
- BUG_ON(!ret || ret != pages[i]);
- __free_page(pages[i]);
- }
-
- pos++;
+ struct page *page;
+ pgoff_t idx;
- /*
- * It takes 3.4 seconds to remove 80GiB ramdisk.
- * So, we need cond_resched to avoid stalling the CPU.
- */
+ xa_for_each(&brd->brd_pages, idx, page) {
+ __free_page(page);
cond_resched();
+ }
- /*
- * This assumes radix_tree_gang_lookup always returns as
- * many pages as possible. If the radix-tree code changes,
- * so will this have to.
- */
- } while (nr_pages == FREE_BATCH);
+ xa_destroy(&brd->brd_pages);
}
/*
@@ -372,8 +328,7 @@ static int brd_alloc(int i)
brd->brd_number = i;
list_add_tail(&brd->brd_list, &brd_devices);
- spin_lock_init(&brd->brd_lock);
- INIT_RADIX_TREE(&brd->brd_pages, GFP_ATOMIC);
+ xa_init(&brd->brd_pages);
snprintf(buf, DISK_NAME_LEN, "ram%d", i);
if (!IS_ERR_OR_NULL(brd_debugfs_dir))
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index 6ac8c54b44c7..85ca000a0564 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -1043,9 +1043,7 @@ static void bm_page_io_async(struct drbd_bm_aio_ctx *ctx, int page_nr) __must_ho
bio = bio_alloc_bioset(device->ldev->md_bdev, 1, op, GFP_NOIO,
&drbd_md_io_bio_set);
bio->bi_iter.bi_sector = on_disk_sector;
- /* bio_add_page of a single page to an empty bio will always succeed,
- * according to api. Do we want to assert that? */
- bio_add_page(bio, page, len, 0);
+ __bio_add_page(bio, page, len, 0);
bio->bi_private = ctx;
bio->bi_end_io = drbd_bm_endio;
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 83987e7a5ef2..79ab532aabaf 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -37,7 +37,6 @@
#include <linux/notifier.h>
#include <linux/kthread.h>
#include <linux/workqueue.h>
-#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
#include <linux/vmalloc.h>
#include <linux/sched/signal.h>
@@ -50,8 +49,8 @@
#include "drbd_debugfs.h"
static DEFINE_MUTEX(drbd_main_mutex);
-static int drbd_open(struct block_device *bdev, fmode_t mode);
-static void drbd_release(struct gendisk *gd, fmode_t mode);
+static int drbd_open(struct gendisk *disk, blk_mode_t mode);
+static void drbd_release(struct gendisk *gd);
static void md_sync_timer_fn(struct timer_list *t);
static int w_bitmap_io(struct drbd_work *w, int unused);
@@ -1540,6 +1539,8 @@ static int _drbd_send_page(struct drbd_peer_device *peer_device, struct page *pa
int offset, size_t size, unsigned msg_flags)
{
struct socket *socket = peer_device->connection->data.socket;
+ struct msghdr msg = { .msg_flags = msg_flags, };
+ struct bio_vec bvec;
int len = size;
int err = -EIO;
@@ -1549,15 +1550,17 @@ static int _drbd_send_page(struct drbd_peer_device *peer_device, struct page *pa
* put_page(); and would cause either a VM_BUG directly, or
* __page_cache_release a page that would actually still be referenced
* by someone, leading to some obscure delayed Oops somewhere else. */
- if (drbd_disable_sendpage || !sendpage_ok(page))
- return _drbd_no_send_page(peer_device, page, offset, size, msg_flags);
+ if (!drbd_disable_sendpage && sendpage_ok(page))
+ msg.msg_flags |= MSG_NOSIGNAL | MSG_SPLICE_PAGES;
- msg_flags |= MSG_NOSIGNAL;
drbd_update_congested(peer_device->connection);
do {
int sent;
- sent = socket->ops->sendpage(socket, page, offset, len, msg_flags);
+ bvec_set_page(&bvec, page, offset, len);
+ iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, len);
+
+ sent = sock_sendmsg(socket, &msg);
if (sent <= 0) {
if (sent == -EAGAIN) {
if (we_should_drop_the_connection(peer_device->connection, socket))
@@ -1883,9 +1886,9 @@ int drbd_send_all(struct drbd_connection *connection, struct socket *sock, void
return 0;
}
-static int drbd_open(struct block_device *bdev, fmode_t mode)
+static int drbd_open(struct gendisk *disk, blk_mode_t mode)
{
- struct drbd_device *device = bdev->bd_disk->private_data;
+ struct drbd_device *device = disk->private_data;
unsigned long flags;
int rv = 0;
@@ -1895,7 +1898,7 @@ static int drbd_open(struct block_device *bdev, fmode_t mode)
* and no race with updating open_cnt */
if (device->state.role != R_PRIMARY) {
- if (mode & FMODE_WRITE)
+ if (mode & BLK_OPEN_WRITE)
rv = -EROFS;
else if (!drbd_allow_oos)
rv = -EMEDIUMTYPE;
@@ -1909,9 +1912,10 @@ static int drbd_open(struct block_device *bdev, fmode_t mode)
return rv;
}
-static void drbd_release(struct gendisk *gd, fmode_t mode)
+static void drbd_release(struct gendisk *gd)
{
struct drbd_device *device = gd->private_data;
+
mutex_lock(&drbd_main_mutex);
device->open_cnt--;
mutex_unlock(&drbd_main_mutex);
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 1a5d3d72d91d..cddae6f4b00f 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1640,8 +1640,8 @@ static struct block_device *open_backing_dev(struct drbd_device *device,
struct block_device *bdev;
int err = 0;
- bdev = blkdev_get_by_path(bdev_path,
- FMODE_READ | FMODE_WRITE | FMODE_EXCL, claim_ptr);
+ bdev = blkdev_get_by_path(bdev_path, BLK_OPEN_READ | BLK_OPEN_WRITE,
+ claim_ptr, NULL);
if (IS_ERR(bdev)) {
drbd_err(device, "open(\"%s\") failed with %ld\n",
bdev_path, PTR_ERR(bdev));
@@ -1653,7 +1653,7 @@ static struct block_device *open_backing_dev(struct drbd_device *device,
err = bd_link_disk_holder(bdev, device->vdisk);
if (err) {
- blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+ blkdev_put(bdev, claim_ptr);
drbd_err(device, "bd_link_disk_holder(\"%s\", ...) failed with %d\n",
bdev_path, err);
bdev = ERR_PTR(err);
@@ -1695,13 +1695,13 @@ static int open_backing_devices(struct drbd_device *device,
}
static void close_backing_dev(struct drbd_device *device, struct block_device *bdev,
- bool do_bd_unlink)
+ void *claim_ptr, bool do_bd_unlink)
{
if (!bdev)
return;
if (do_bd_unlink)
bd_unlink_disk_holder(bdev, device->vdisk);
- blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+ blkdev_put(bdev, claim_ptr);
}
void drbd_backing_dev_free(struct drbd_device *device, struct drbd_backing_dev *ldev)
@@ -1709,8 +1709,11 @@ void drbd_backing_dev_free(struct drbd_device *device, struct drbd_backing_dev *
if (ldev == NULL)
return;
- close_backing_dev(device, ldev->md_bdev, ldev->md_bdev != ldev->backing_bdev);
- close_backing_dev(device, ldev->backing_bdev, true);
+ close_backing_dev(device, ldev->md_bdev,
+ ldev->md.meta_dev_idx < 0 ?
+ (void *)device : (void *)drbd_m_holder,
+ ldev->md_bdev != ldev->backing_bdev);
+ close_backing_dev(device, ldev->backing_bdev, device, true);
kfree(ldev->disk_conf);
kfree(ldev);
@@ -2126,8 +2129,11 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
fail:
conn_reconfig_done(connection);
if (nbc) {
- close_backing_dev(device, nbc->md_bdev, nbc->md_bdev != nbc->backing_bdev);
- close_backing_dev(device, nbc->backing_bdev, true);
+ close_backing_dev(device, nbc->md_bdev,
+ nbc->disk_conf->meta_dev_idx < 0 ?
+ (void *)device : (void *)drbd_m_holder,
+ nbc->md_bdev != nbc->backing_bdev);
+ close_backing_dev(device, nbc->backing_bdev, device, true);
kfree(nbc);
}
kfree(new_disk_conf);
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 8c2bc47de473..0c9f54197768 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -27,7 +27,6 @@
#include <uapi/linux/sched/types.h>
#include <linux/sched/signal.h>
#include <linux/pkt_sched.h>
-#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
#include <linux/vmalloc.h>
#include <linux/random.h>
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index cec2c20f5e59..2db9b186b977 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -402,7 +402,7 @@ static struct floppy_drive_struct drive_state[N_DRIVE];
static struct floppy_write_errors write_errors[N_DRIVE];
static struct timer_list motor_off_timer[N_DRIVE];
static struct blk_mq_tag_set tag_sets[N_DRIVE];
-static struct block_device *opened_bdev[N_DRIVE];
+static struct gendisk *opened_disk[N_DRIVE];
static DEFINE_MUTEX(open_lock);
static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
@@ -3210,13 +3210,13 @@ static int floppy_raw_cmd_ioctl(int type, int drive, int cmd,
#endif
-static int invalidate_drive(struct block_device *bdev)
+static int invalidate_drive(struct gendisk *disk)
{
/* invalidate the buffer track to force a reread */
- set_bit((long)bdev->bd_disk->private_data, &fake_change);
+ set_bit((long)disk->private_data, &fake_change);
process_fd_request();
- if (bdev_check_media_change(bdev))
- floppy_revalidate(bdev->bd_disk);
+ if (disk_check_media_change(disk))
+ floppy_revalidate(disk);
return 0;
}
@@ -3251,10 +3251,11 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g,
floppy_type[type].size + 1;
process_fd_request();
for (cnt = 0; cnt < N_DRIVE; cnt++) {
- struct block_device *bdev = opened_bdev[cnt];
- if (!bdev || ITYPE(drive_state[cnt].fd_device) != type)
+ struct gendisk *disk = opened_disk[cnt];
+
+ if (!disk || ITYPE(drive_state[cnt].fd_device) != type)
continue;
- __invalidate_device(bdev, true);
+ __invalidate_device(disk->part0, true);
}
mutex_unlock(&open_lock);
} else {
@@ -3287,7 +3288,7 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g,
drive_state[current_drive].maxtrack ||
((user_params[drive].sect ^ oldStretch) &
(FD_SWAPSIDES | FD_SECTBASEMASK)))
- invalidate_drive(bdev);
+ invalidate_drive(bdev->bd_disk);
else
process_fd_request();
}
@@ -3393,8 +3394,8 @@ static bool valid_floppy_drive_params(const short autodetect[FD_AUTODETECT_SIZE]
return true;
}
-static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
- unsigned long param)
+static int fd_locked_ioctl(struct block_device *bdev, blk_mode_t mode,
+ unsigned int cmd, unsigned long param)
{
int drive = (long)bdev->bd_disk->private_data;
int type = ITYPE(drive_state[drive].fd_device);
@@ -3427,7 +3428,8 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
return ret;
/* permission checks */
- if (((cmd & 0x40) && !(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL))) ||
+ if (((cmd & 0x40) &&
+ !(mode & (BLK_OPEN_WRITE | BLK_OPEN_WRITE_IOCTL))) ||
((cmd & 0x80) && !capable(CAP_SYS_ADMIN)))
return -EPERM;
@@ -3464,7 +3466,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
current_type[drive] = NULL;
floppy_sizes[drive] = MAX_DISK_SIZE << 1;
drive_state[drive].keep_data = 0;
- return invalidate_drive(bdev);
+ return invalidate_drive(bdev->bd_disk);
case FDSETPRM:
case FDDEFPRM:
return set_geometry(cmd, &inparam.g, drive, type, bdev);
@@ -3503,7 +3505,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
case FDFLUSH:
if (lock_fdc(drive))
return -EINTR;
- return invalidate_drive(bdev);
+ return invalidate_drive(bdev->bd_disk);
case FDSETEMSGTRESH:
drive_params[drive].max_errors.reporting = (unsigned short)(param & 0x0f);
return 0;
@@ -3565,7 +3567,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
return 0;
}
-static int fd_ioctl(struct block_device *bdev, fmode_t mode,
+static int fd_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long param)
{
int ret;
@@ -3653,8 +3655,8 @@ struct compat_floppy_write_errors {
#define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state)
#define FDWERRORGET32 _IOR(2, 0x17, struct compat_floppy_write_errors)
-static int compat_set_geometry(struct block_device *bdev, fmode_t mode, unsigned int cmd,
- struct compat_floppy_struct __user *arg)
+static int compat_set_geometry(struct block_device *bdev, blk_mode_t mode,
+ unsigned int cmd, struct compat_floppy_struct __user *arg)
{
struct floppy_struct v;
int drive, type;
@@ -3663,7 +3665,7 @@ static int compat_set_geometry(struct block_device *bdev, fmode_t mode, unsigned
BUILD_BUG_ON(offsetof(struct floppy_struct, name) !=
offsetof(struct compat_floppy_struct, name));
- if (!(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL)))
+ if (!(mode & (BLK_OPEN_WRITE | BLK_OPEN_WRITE_IOCTL)))
return -EPERM;
memset(&v, 0, sizeof(struct floppy_struct));
@@ -3860,8 +3862,8 @@ static int compat_werrorget(int drive,
return 0;
}
-static int fd_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
- unsigned long param)
+static int fd_compat_ioctl(struct block_device *bdev, blk_mode_t mode,
+ unsigned int cmd, unsigned long param)
{
int drive = (long)bdev->bd_disk->private_data;
switch (cmd) {
@@ -3962,7 +3964,7 @@ static void __init config_types(void)
pr_cont("\n");
}
-static void floppy_release(struct gendisk *disk, fmode_t mode)
+static void floppy_release(struct gendisk *disk)
{
int drive = (long)disk->private_data;
@@ -3973,7 +3975,7 @@ static void floppy_release(struct gendisk *disk, fmode_t mode)
drive_state[drive].fd_ref = 0;
}
if (!drive_state[drive].fd_ref)
- opened_bdev[drive] = NULL;
+ opened_disk[drive] = NULL;
mutex_unlock(&open_lock);
mutex_unlock(&floppy_mutex);
}
@@ -3983,9 +3985,9 @@ static void floppy_release(struct gendisk *disk, fmode_t mode)
* /dev/PS0 etc), and disallows simultaneous access to the same
* drive with different device numbers.
*/
-static int floppy_open(struct block_device *bdev, fmode_t mode)
+static int floppy_open(struct gendisk *disk, blk_mode_t mode)
{
- int drive = (long)bdev->bd_disk->private_data;
+ int drive = (long)disk->private_data;
int old_dev, new_dev;
int try;
int res = -EBUSY;
@@ -3994,7 +3996,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
mutex_lock(&floppy_mutex);
mutex_lock(&open_lock);
old_dev = drive_state[drive].fd_device;
- if (opened_bdev[drive] && opened_bdev[drive] != bdev)
+ if (opened_disk[drive] && opened_disk[drive] != disk)
goto out2;
if (!drive_state[drive].fd_ref && (drive_params[drive].flags & FD_BROKEN_DCL)) {
@@ -4004,7 +4006,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
drive_state[drive].fd_ref++;
- opened_bdev[drive] = bdev;
+ opened_disk[drive] = disk;
res = -ENXIO;
@@ -4038,7 +4040,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
}
}
- new_dev = MINOR(bdev->bd_dev);
+ new_dev = disk->first_minor;
drive_state[drive].fd_device = new_dev;
set_capacity(disks[drive][ITYPE(new_dev)], floppy_sizes[new_dev]);
if (old_dev != -1 && old_dev != new_dev) {
@@ -4048,21 +4050,20 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
if (fdc_state[FDC(drive)].rawcmd == 1)
fdc_state[FDC(drive)].rawcmd = 2;
-
- if (!(mode & FMODE_NDELAY)) {
- if (mode & (FMODE_READ|FMODE_WRITE)) {
+ if (!(mode & BLK_OPEN_NDELAY)) {
+ if (mode & (BLK_OPEN_READ | BLK_OPEN_WRITE)) {
drive_state[drive].last_checked = 0;
clear_bit(FD_OPEN_SHOULD_FAIL_BIT,
&drive_state[drive].flags);
- if (bdev_check_media_change(bdev))
- floppy_revalidate(bdev->bd_disk);
+ if (disk_check_media_change(disk))
+ floppy_revalidate(disk);
if (test_bit(FD_DISK_CHANGED_BIT, &drive_state[drive].flags))
goto out;
if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &drive_state[drive].flags))
goto out;
}
res = -EROFS;
- if ((mode & FMODE_WRITE) &&
+ if ((mode & BLK_OPEN_WRITE) &&
!test_bit(FD_DISK_WRITABLE_BIT, &drive_state[drive].flags))
goto out;
}
@@ -4073,7 +4074,7 @@ out:
drive_state[drive].fd_ref--;
if (!drive_state[drive].fd_ref)
- opened_bdev[drive] = NULL;
+ opened_disk[drive] = NULL;
out2:
mutex_unlock(&open_lock);
mutex_unlock(&floppy_mutex);
@@ -4147,7 +4148,7 @@ static int __floppy_read_block_0(struct block_device *bdev, int drive)
cbdata.drive = drive;
bio_init(&bio, bdev, &bio_vec, 1, REQ_OP_READ);
- bio_add_page(&bio, page, block_size(bdev), 0);
+ __bio_add_page(&bio, page, block_size(bdev), 0);
bio.bi_iter.bi_sector = 0;
bio.bi_flags |= (1 << BIO_QUIET);
@@ -4203,7 +4204,8 @@ static int floppy_revalidate(struct gendisk *disk)
drive_state[drive].generation++;
if (drive_no_geom(drive)) {
/* auto-sensing */
- res = __floppy_read_block_0(opened_bdev[drive], drive);
+ res = __floppy_read_block_0(opened_disk[drive]->part0,
+ drive);
} else {
if (cf)
poll_drive(false, FD_RAW_NEED_DISK);
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index bc31bb7072a2..637c5bda2387 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -990,7 +990,7 @@ loop_set_status_from_info(struct loop_device *lo,
return 0;
}
-static int loop_configure(struct loop_device *lo, fmode_t mode,
+static int loop_configure(struct loop_device *lo, blk_mode_t mode,
struct block_device *bdev,
const struct loop_config *config)
{
@@ -1014,8 +1014,8 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
* If we don't hold exclusive handle for the device, upgrade to it
* here to avoid changing device under exclusive owner.
*/
- if (!(mode & FMODE_EXCL)) {
- error = bd_prepare_to_claim(bdev, loop_configure);
+ if (!(mode & BLK_OPEN_EXCL)) {
+ error = bd_prepare_to_claim(bdev, loop_configure, NULL);
if (error)
goto out_putf;
}
@@ -1050,7 +1050,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
if (error)
goto out_unlock;
- if (!(file->f_mode & FMODE_WRITE) || !(mode & FMODE_WRITE) ||
+ if (!(file->f_mode & FMODE_WRITE) || !(mode & BLK_OPEN_WRITE) ||
!file->f_op->write_iter)
lo->lo_flags |= LO_FLAGS_READ_ONLY;
@@ -1116,7 +1116,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
if (partscan)
loop_reread_partitions(lo);
- if (!(mode & FMODE_EXCL))
+ if (!(mode & BLK_OPEN_EXCL))
bd_abort_claiming(bdev, loop_configure);
return 0;
@@ -1124,7 +1124,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
out_unlock:
loop_global_unlock(lo, is_loop);
out_bdev:
- if (!(mode & FMODE_EXCL))
+ if (!(mode & BLK_OPEN_EXCL))
bd_abort_claiming(bdev, loop_configure);
out_putf:
fput(file);
@@ -1528,7 +1528,7 @@ static int lo_simple_ioctl(struct loop_device *lo, unsigned int cmd,
return err;
}
-static int lo_ioctl(struct block_device *bdev, fmode_t mode,
+static int lo_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long arg)
{
struct loop_device *lo = bdev->bd_disk->private_data;
@@ -1563,24 +1563,22 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
return loop_clr_fd(lo);
case LOOP_SET_STATUS:
err = -EPERM;
- if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) {
+ if ((mode & BLK_OPEN_WRITE) || capable(CAP_SYS_ADMIN))
err = loop_set_status_old(lo, argp);
- }
break;
case LOOP_GET_STATUS:
return loop_get_status_old(lo, argp);
case LOOP_SET_STATUS64:
err = -EPERM;
- if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) {
+ if ((mode & BLK_OPEN_WRITE) || capable(CAP_SYS_ADMIN))
err = loop_set_status64(lo, argp);
- }
break;
case LOOP_GET_STATUS64:
return loop_get_status64(lo, argp);
case LOOP_SET_CAPACITY:
case LOOP_SET_DIRECT_IO:
case LOOP_SET_BLOCK_SIZE:
- if (!(mode & FMODE_WRITE) && !capable(CAP_SYS_ADMIN))
+ if (!(mode & BLK_OPEN_WRITE) && !capable(CAP_SYS_ADMIN))
return -EPERM;
fallthrough;
default:
@@ -1691,7 +1689,7 @@ loop_get_status_compat(struct loop_device *lo,
return err;
}
-static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode,
+static int lo_compat_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long arg)
{
struct loop_device *lo = bdev->bd_disk->private_data;
@@ -1727,7 +1725,7 @@ static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode,
}
#endif
-static void lo_release(struct gendisk *disk, fmode_t mode)
+static void lo_release(struct gendisk *disk)
{
struct loop_device *lo = disk->private_data;
@@ -1777,14 +1775,43 @@ static const struct block_device_operations lo_fops = {
/*
* If max_loop is specified, create that many devices upfront.
* This also becomes a hard limit. If max_loop is not specified,
+ * the default isn't a hard limit (as before commit 85c50197716c
+ * changed the default value from 0 for max_loop=0 reasons), just
* create CONFIG_BLK_DEV_LOOP_MIN_COUNT loop devices at module
* init time. Loop devices can be requested on-demand with the
* /dev/loop-control interface, or be instantiated by accessing
* a 'dead' device node.
*/
static int max_loop = CONFIG_BLK_DEV_LOOP_MIN_COUNT;
-module_param(max_loop, int, 0444);
+
+#ifdef CONFIG_BLOCK_LEGACY_AUTOLOAD
+static bool max_loop_specified;
+
+static int max_loop_param_set_int(const char *val,
+ const struct kernel_param *kp)
+{
+ int ret;
+
+ ret = param_set_int(val, kp);
+ if (ret < 0)
+ return ret;
+
+ max_loop_specified = true;
+ return 0;
+}
+
+static const struct kernel_param_ops max_loop_param_ops = {
+ .set = max_loop_param_set_int,
+ .get = param_get_int,
+};
+
+module_param_cb(max_loop, &max_loop_param_ops, &max_loop, 0444);
MODULE_PARM_DESC(max_loop, "Maximum number of loop devices");
+#else
+module_param(max_loop, int, 0444);
+MODULE_PARM_DESC(max_loop, "Initial number of loop devices");
+#endif
+
module_param(max_part, int, 0444);
MODULE_PARM_DESC(max_part, "Maximum number of partitions per loop device");
@@ -2095,14 +2122,18 @@ static void loop_remove(struct loop_device *lo)
put_disk(lo->lo_disk);
}
+#ifdef CONFIG_BLOCK_LEGACY_AUTOLOAD
static void loop_probe(dev_t dev)
{
int idx = MINOR(dev) >> part_shift;
- if (max_loop && idx >= max_loop)
+ if (max_loop_specified && max_loop && idx >= max_loop)
return;
loop_add(idx);
}
+#else
+#define loop_probe NULL
+#endif /* !CONFIG_BLOCK_LEGACY_AUTOLOAD */
static int loop_control_remove(int idx)
{
@@ -2283,6 +2314,9 @@ module_exit(loop_exit);
static int __init max_loop_setup(char *str)
{
max_loop = simple_strtol(str, NULL, 0);
+#ifdef CONFIG_BLOCK_LEGACY_AUTOLOAD
+ max_loop_specified = true;
+#endif
return 1;
}
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 815d77ba6381..b200950e8fb5 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -3041,7 +3041,7 @@ static int rssd_disk_name_format(char *prefix,
* structure pointer.
*/
static int mtip_block_ioctl(struct block_device *dev,
- fmode_t mode,
+ blk_mode_t mode,
unsigned cmd,
unsigned long arg)
{
@@ -3079,7 +3079,7 @@ static int mtip_block_ioctl(struct block_device *dev,
* structure pointer.
*/
static int mtip_block_compat_ioctl(struct block_device *dev,
- fmode_t mode,
+ blk_mode_t mode,
unsigned cmd,
unsigned long arg)
{
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 65ecde3e2a5b..8576d696c7a2 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -1502,7 +1502,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
return -ENOTTY;
}
-static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
+static int nbd_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long arg)
{
struct nbd_device *nbd = bdev->bd_disk->private_data;
@@ -1553,13 +1553,13 @@ static struct nbd_config *nbd_alloc_config(void)
return config;
}
-static int nbd_open(struct block_device *bdev, fmode_t mode)
+static int nbd_open(struct gendisk *disk, blk_mode_t mode)
{
struct nbd_device *nbd;
int ret = 0;
mutex_lock(&nbd_index_mutex);
- nbd = bdev->bd_disk->private_data;
+ nbd = disk->private_data;
if (!nbd) {
ret = -ENXIO;
goto out;
@@ -1587,17 +1587,17 @@ static int nbd_open(struct block_device *bdev, fmode_t mode)
refcount_inc(&nbd->refs);
mutex_unlock(&nbd->config_lock);
if (max_part)
- set_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state);
+ set_bit(GD_NEED_PART_SCAN, &disk->state);
} else if (nbd_disconnected(nbd->config)) {
if (max_part)
- set_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state);
+ set_bit(GD_NEED_PART_SCAN, &disk->state);
}
out:
mutex_unlock(&nbd_index_mutex);
return ret;
}
-static void nbd_release(struct gendisk *disk, fmode_t mode)
+static void nbd_release(struct gendisk *disk)
{
struct nbd_device *nbd = disk->private_data;
@@ -1776,7 +1776,8 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
if (err == -ENOSPC)
err = -EEXIST;
} else {
- err = idr_alloc(&nbd_index_idr, nbd, 0, 0, GFP_KERNEL);
+ err = idr_alloc(&nbd_index_idr, nbd, 0,
+ (MINORMASK >> part_shift) + 1, GFP_KERNEL);
if (err >= 0)
index = err;
}
diff --git a/drivers/block/null_blk/zoned.c b/drivers/block/null_blk/zoned.c
index 635ce0648133..55c5b48bc276 100644
--- a/drivers/block/null_blk/zoned.c
+++ b/drivers/block/null_blk/zoned.c
@@ -162,21 +162,15 @@ int null_register_zoned_dev(struct nullb *nullb)
disk_set_zoned(nullb->disk, BLK_ZONED_HM);
blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, q);
blk_queue_required_elevator_features(q, ELEVATOR_F_ZBD_SEQ_WRITE);
-
- if (queue_is_mq(q)) {
- int ret = blk_revalidate_disk_zones(nullb->disk, NULL);
-
- if (ret)
- return ret;
- } else {
- blk_queue_chunk_sectors(q, dev->zone_size_sects);
- nullb->disk->nr_zones = bdev_nr_zones(nullb->disk->part0);
- }
-
+ blk_queue_chunk_sectors(q, dev->zone_size_sects);
+ nullb->disk->nr_zones = bdev_nr_zones(nullb->disk->part0);
blk_queue_max_zone_append_sectors(q, dev->zone_size_sects);
disk_set_max_open_zones(nullb->disk, dev->zone_max_open);
disk_set_max_active_zones(nullb->disk, dev->zone_max_active);
+ if (queue_is_mq(q))
+ return blk_revalidate_disk_zones(nullb->disk, NULL);
+
return 0;
}
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index d5d7884cedd4..a1428538bda5 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -46,47 +46,34 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/pktcdvd.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
+#include <linux/backing-dev.h>
#include <linux/compat.h>
-#include <linux/kthread.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
#include <linux/errno.h>
-#include <linux/spinlock.h>
#include <linux/file.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/miscdevice.h>
#include <linux/freezer.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/nospec.h>
+#include <linux/pktcdvd.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/slab.h>
-#include <linux/backing-dev.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+
+#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_ioctl.h>
-#include <scsi/scsi.h>
-#include <linux/debugfs.h>
-#include <linux/device.h>
-#include <linux/nospec.h>
-#include <linux/uaccess.h>
-#define DRIVER_NAME "pktcdvd"
+#include <asm/unaligned.h>
-#define pkt_err(pd, fmt, ...) \
- pr_err("%s: " fmt, pd->name, ##__VA_ARGS__)
-#define pkt_notice(pd, fmt, ...) \
- pr_notice("%s: " fmt, pd->name, ##__VA_ARGS__)
-#define pkt_info(pd, fmt, ...) \
- pr_info("%s: " fmt, pd->name, ##__VA_ARGS__)
-
-#define pkt_dbg(level, pd, fmt, ...) \
-do { \
- if (level == 2 && PACKET_DEBUG >= 2) \
- pr_notice("%s: %s():" fmt, \
- pd->name, __func__, ##__VA_ARGS__); \
- else if (level == 1 && PACKET_DEBUG >= 1) \
- pr_notice("%s: " fmt, pd->name, ##__VA_ARGS__); \
-} while (0)
+#define DRIVER_NAME "pktcdvd"
#define MAX_SPEED 0xffff
@@ -107,7 +94,6 @@ static struct dentry *pkt_debugfs_root = NULL; /* /sys/kernel/debug/pktcdvd */
/* forward declaration */
static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev);
static int pkt_remove_dev(dev_t pkt_dev);
-static int pkt_seq_show(struct seq_file *m, void *p);
static sector_t get_zone(sector_t sector, struct pktcdvd_device *pd)
{
@@ -253,15 +239,16 @@ static ssize_t congestion_off_store(struct device *dev,
const char *buf, size_t len)
{
struct pktcdvd_device *pd = dev_get_drvdata(dev);
- int val;
+ int val, ret;
- if (sscanf(buf, "%d", &val) == 1) {
- spin_lock(&pd->lock);
- pd->write_congestion_off = val;
- init_write_congestion_marks(&pd->write_congestion_off,
- &pd->write_congestion_on);
- spin_unlock(&pd->lock);
- }
+ ret = kstrtoint(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ spin_lock(&pd->lock);
+ pd->write_congestion_off = val;
+ init_write_congestion_marks(&pd->write_congestion_off, &pd->write_congestion_on);
+ spin_unlock(&pd->lock);
return len;
}
static DEVICE_ATTR_RW(congestion_off);
@@ -283,15 +270,16 @@ static ssize_t congestion_on_store(struct device *dev,
const char *buf, size_t len)
{
struct pktcdvd_device *pd = dev_get_drvdata(dev);
- int val;
+ int val, ret;
- if (sscanf(buf, "%d", &val) == 1) {
- spin_lock(&pd->lock);
- pd->write_congestion_on = val;
- init_write_congestion_marks(&pd->write_congestion_off,
- &pd->write_congestion_on);
- spin_unlock(&pd->lock);
- }
+ ret = kstrtoint(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ spin_lock(&pd->lock);
+ pd->write_congestion_on = val;
+ init_write_congestion_marks(&pd->write_congestion_off, &pd->write_congestion_on);
+ spin_unlock(&pd->lock);
return len;
}
static DEVICE_ATTR_RW(congestion_on);
@@ -319,7 +307,7 @@ static void pkt_sysfs_dev_new(struct pktcdvd_device *pd)
if (class_is_registered(&class_pktcdvd)) {
pd->dev = device_create_with_groups(&class_pktcdvd, NULL,
MKDEV(0, 0), pd, pkt_groups,
- "%s", pd->name);
+ "%s", pd->disk->disk_name);
if (IS_ERR(pd->dev))
pd->dev = NULL;
}
@@ -349,8 +337,8 @@ static ssize_t device_map_show(const struct class *c, const struct class_attribu
struct pktcdvd_device *pd = pkt_devs[idx];
if (!pd)
continue;
- n += sprintf(data+n, "%s %u:%u %u:%u\n",
- pd->name,
+ n += sysfs_emit_at(data, n, "%s %u:%u %u:%u\n",
+ pd->disk->disk_name,
MAJOR(pd->pkt_dev), MINOR(pd->pkt_dev),
MAJOR(pd->bdev->bd_dev),
MINOR(pd->bdev->bd_dev));
@@ -428,34 +416,92 @@ static void pkt_sysfs_cleanup(void)
*******************************************************************/
-static int pkt_debugfs_seq_show(struct seq_file *m, void *p)
+static void pkt_count_states(struct pktcdvd_device *pd, int *states)
{
- return pkt_seq_show(m, p);
+ struct packet_data *pkt;
+ int i;
+
+ for (i = 0; i < PACKET_NUM_STATES; i++)
+ states[i] = 0;
+
+ spin_lock(&pd->cdrw.active_list_lock);
+ list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) {
+ states[pkt->state]++;
+ }
+ spin_unlock(&pd->cdrw.active_list_lock);
}
-static int pkt_debugfs_fops_open(struct inode *inode, struct file *file)
+static int pkt_seq_show(struct seq_file *m, void *p)
{
- return single_open(file, pkt_debugfs_seq_show, inode->i_private);
-}
+ struct pktcdvd_device *pd = m->private;
+ char *msg;
+ int states[PACKET_NUM_STATES];
-static const struct file_operations debug_fops = {
- .open = pkt_debugfs_fops_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+ seq_printf(m, "Writer %s mapped to %pg:\n", pd->disk->disk_name, pd->bdev);
+
+ seq_printf(m, "\nSettings:\n");
+ seq_printf(m, "\tpacket size:\t\t%dkB\n", pd->settings.size / 2);
+
+ if (pd->settings.write_type == 0)
+ msg = "Packet";
+ else
+ msg = "Unknown";
+ seq_printf(m, "\twrite type:\t\t%s\n", msg);
+
+ seq_printf(m, "\tpacket type:\t\t%s\n", pd->settings.fp ? "Fixed" : "Variable");
+ seq_printf(m, "\tlink loss:\t\t%d\n", pd->settings.link_loss);
+
+ seq_printf(m, "\ttrack mode:\t\t%d\n", pd->settings.track_mode);
+
+ if (pd->settings.block_mode == PACKET_BLOCK_MODE1)
+ msg = "Mode 1";
+ else if (pd->settings.block_mode == PACKET_BLOCK_MODE2)
+ msg = "Mode 2";
+ else
+ msg = "Unknown";
+ seq_printf(m, "\tblock mode:\t\t%s\n", msg);
+
+ seq_printf(m, "\nStatistics:\n");
+ seq_printf(m, "\tpackets started:\t%lu\n", pd->stats.pkt_started);
+ seq_printf(m, "\tpackets ended:\t\t%lu\n", pd->stats.pkt_ended);
+ seq_printf(m, "\twritten:\t\t%lukB\n", pd->stats.secs_w >> 1);
+ seq_printf(m, "\tread gather:\t\t%lukB\n", pd->stats.secs_rg >> 1);
+ seq_printf(m, "\tread:\t\t\t%lukB\n", pd->stats.secs_r >> 1);
+
+ seq_printf(m, "\nMisc:\n");
+ seq_printf(m, "\treference count:\t%d\n", pd->refcnt);
+ seq_printf(m, "\tflags:\t\t\t0x%lx\n", pd->flags);
+ seq_printf(m, "\tread speed:\t\t%ukB/s\n", pd->read_speed);
+ seq_printf(m, "\twrite speed:\t\t%ukB/s\n", pd->write_speed);
+ seq_printf(m, "\tstart offset:\t\t%lu\n", pd->offset);
+ seq_printf(m, "\tmode page offset:\t%u\n", pd->mode_offset);
+
+ seq_printf(m, "\nQueue state:\n");
+ seq_printf(m, "\tbios queued:\t\t%d\n", pd->bio_queue_size);
+ seq_printf(m, "\tbios pending:\t\t%d\n", atomic_read(&pd->cdrw.pending_bios));
+ seq_printf(m, "\tcurrent sector:\t\t0x%llx\n", pd->current_sector);
+
+ pkt_count_states(pd, states);
+ seq_printf(m, "\tstate:\t\t\ti:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n",
+ states[0], states[1], states[2], states[3], states[4], states[5]);
+
+ seq_printf(m, "\twrite congestion marks:\toff=%d on=%d\n",
+ pd->write_congestion_off,
+ pd->write_congestion_on);
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(pkt_seq);
static void pkt_debugfs_dev_new(struct pktcdvd_device *pd)
{
if (!pkt_debugfs_root)
return;
- pd->dfs_d_root = debugfs_create_dir(pd->name, pkt_debugfs_root);
+ pd->dfs_d_root = debugfs_create_dir(pd->disk->disk_name, pkt_debugfs_root);
if (!pd->dfs_d_root)
return;
- pd->dfs_f_info = debugfs_create_file("info", 0444,
- pd->dfs_d_root, pd, &debug_fops);
+ pd->dfs_f_info = debugfs_create_file("info", 0444, pd->dfs_d_root,
+ pd, &pkt_seq_fops);
}
static void pkt_debugfs_dev_remove(struct pktcdvd_device *pd)
@@ -484,9 +530,11 @@ static void pkt_debugfs_cleanup(void)
static void pkt_bio_finished(struct pktcdvd_device *pd)
{
+ struct device *ddev = disk_to_dev(pd->disk);
+
BUG_ON(atomic_read(&pd->cdrw.pending_bios) <= 0);
if (atomic_dec_and_test(&pd->cdrw.pending_bios)) {
- pkt_dbg(2, pd, "queue empty\n");
+ dev_dbg(ddev, "queue empty\n");
atomic_set(&pd->iosched.attention, 1);
wake_up(&pd->wqueue);
}
@@ -717,15 +765,16 @@ static const char *sense_key_string(__u8 index)
static void pkt_dump_sense(struct pktcdvd_device *pd,
struct packet_command *cgc)
{
+ struct device *ddev = disk_to_dev(pd->disk);
struct scsi_sense_hdr *sshdr = cgc->sshdr;
if (sshdr)
- pkt_err(pd, "%*ph - sense %02x.%02x.%02x (%s)\n",
+ dev_err(ddev, "%*ph - sense %02x.%02x.%02x (%s)\n",
CDROM_PACKET_SIZE, cgc->cmd,
sshdr->sense_key, sshdr->asc, sshdr->ascq,
sense_key_string(sshdr->sense_key));
else
- pkt_err(pd, "%*ph - no sense\n", CDROM_PACKET_SIZE, cgc->cmd);
+ dev_err(ddev, "%*ph - no sense\n", CDROM_PACKET_SIZE, cgc->cmd);
}
/*
@@ -762,10 +811,8 @@ static noinline_for_stack int pkt_set_speed(struct pktcdvd_device *pd,
init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
cgc.sshdr = &sshdr;
cgc.cmd[0] = GPCMD_SET_SPEED;
- cgc.cmd[2] = (read_speed >> 8) & 0xff;
- cgc.cmd[3] = read_speed & 0xff;
- cgc.cmd[4] = (write_speed >> 8) & 0xff;
- cgc.cmd[5] = write_speed & 0xff;
+ put_unaligned_be16(read_speed, &cgc.cmd[2]);
+ put_unaligned_be16(write_speed, &cgc.cmd[4]);
ret = pkt_generic_packet(pd, &cgc);
if (ret)
@@ -809,6 +856,7 @@ static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio)
*/
static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
{
+ struct device *ddev = disk_to_dev(pd->disk);
if (atomic_read(&pd->iosched.attention) == 0)
return;
@@ -836,7 +884,7 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
need_write_seek = 0;
if (need_write_seek && reads_queued) {
if (atomic_read(&pd->cdrw.pending_bios) > 0) {
- pkt_dbg(2, pd, "write, waiting\n");
+ dev_dbg(ddev, "write, waiting\n");
break;
}
pkt_flush_cache(pd);
@@ -845,7 +893,7 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
} else {
if (!reads_queued && writes_queued) {
if (atomic_read(&pd->cdrw.pending_bios) > 0) {
- pkt_dbg(2, pd, "read, waiting\n");
+ dev_dbg(ddev, "read, waiting\n");
break;
}
pd->iosched.writing = 1;
@@ -892,25 +940,27 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
*/
static int pkt_set_segment_merging(struct pktcdvd_device *pd, struct request_queue *q)
{
- if ((pd->settings.size << 9) / CD_FRAMESIZE
- <= queue_max_segments(q)) {
+ struct device *ddev = disk_to_dev(pd->disk);
+
+ if ((pd->settings.size << 9) / CD_FRAMESIZE <= queue_max_segments(q)) {
/*
* The cdrom device can handle one segment/frame
*/
clear_bit(PACKET_MERGE_SEGS, &pd->flags);
return 0;
- } else if ((pd->settings.size << 9) / PAGE_SIZE
- <= queue_max_segments(q)) {
+ }
+
+ if ((pd->settings.size << 9) / PAGE_SIZE <= queue_max_segments(q)) {
/*
* We can handle this case at the expense of some extra memory
* copies during write operations
*/
set_bit(PACKET_MERGE_SEGS, &pd->flags);
return 0;
- } else {
- pkt_err(pd, "cdrom max_phys_segments too small\n");
- return -EIO;
}
+
+ dev_err(ddev, "cdrom max_phys_segments too small\n");
+ return -EIO;
}
static void pkt_end_io_read(struct bio *bio)
@@ -919,9 +969,8 @@ static void pkt_end_io_read(struct bio *bio)
struct pktcdvd_device *pd = pkt->pd;
BUG_ON(!pd);
- pkt_dbg(2, pd, "bio=%p sec0=%llx sec=%llx err=%d\n",
- bio, (unsigned long long)pkt->sector,
- (unsigned long long)bio->bi_iter.bi_sector, bio->bi_status);
+ dev_dbg(disk_to_dev(pd->disk), "bio=%p sec0=%llx sec=%llx err=%d\n",
+ bio, pkt->sector, bio->bi_iter.bi_sector, bio->bi_status);
if (bio->bi_status)
atomic_inc(&pkt->io_errors);
@@ -939,7 +988,7 @@ static void pkt_end_io_packet_write(struct bio *bio)
struct pktcdvd_device *pd = pkt->pd;
BUG_ON(!pd);
- pkt_dbg(2, pd, "id=%d, err=%d\n", pkt->id, bio->bi_status);
+ dev_dbg(disk_to_dev(pd->disk), "id=%d, err=%d\n", pkt->id, bio->bi_status);
pd->stats.pkt_ended++;
@@ -955,6 +1004,7 @@ static void pkt_end_io_packet_write(struct bio *bio)
*/
static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
{
+ struct device *ddev = disk_to_dev(pd->disk);
int frames_read = 0;
struct bio *bio;
int f;
@@ -983,8 +1033,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
spin_unlock(&pkt->lock);
if (pkt->cache_valid) {
- pkt_dbg(2, pd, "zone %llx cached\n",
- (unsigned long long)pkt->sector);
+ dev_dbg(ddev, "zone %llx cached\n", pkt->sector);
goto out_account;
}
@@ -1005,8 +1054,8 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
p = (f * CD_FRAMESIZE) / PAGE_SIZE;
offset = (f * CD_FRAMESIZE) % PAGE_SIZE;
- pkt_dbg(2, pd, "Adding frame %d, page:%p offs:%d\n",
- f, pkt->pages[p], offset);
+ dev_dbg(ddev, "Adding frame %d, page:%p offs:%d\n", f,
+ pkt->pages[p], offset);
if (!bio_add_page(bio, pkt->pages[p], CD_FRAMESIZE, offset))
BUG();
@@ -1016,8 +1065,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
}
out_account:
- pkt_dbg(2, pd, "need %d frames for zone %llx\n",
- frames_read, (unsigned long long)pkt->sector);
+ dev_dbg(ddev, "need %d frames for zone %llx\n", frames_read, pkt->sector);
pd->stats.pkt_started++;
pd->stats.secs_rg += frames_read * (CD_FRAMESIZE >> 9);
}
@@ -1051,17 +1099,17 @@ static void pkt_put_packet_data(struct pktcdvd_device *pd, struct packet_data *p
}
}
-static inline void pkt_set_state(struct packet_data *pkt, enum packet_data_state state)
+static inline void pkt_set_state(struct device *ddev, struct packet_data *pkt,
+ enum packet_data_state state)
{
-#if PACKET_DEBUG > 1
static const char *state_name[] = {
"IDLE", "WAITING", "READ_WAIT", "WRITE_WAIT", "RECOVERY", "FINISHED"
};
enum packet_data_state old_state = pkt->state;
- pkt_dbg(2, pd, "pkt %2d : s=%6llx %s -> %s\n",
- pkt->id, (unsigned long long)pkt->sector,
- state_name[old_state], state_name[state]);
-#endif
+
+ dev_dbg(ddev, "pkt %2d : s=%6llx %s -> %s\n",
+ pkt->id, pkt->sector, state_name[old_state], state_name[state]);
+
pkt->state = state;
}
@@ -1071,6 +1119,7 @@ static inline void pkt_set_state(struct packet_data *pkt, enum packet_data_state
*/
static int pkt_handle_queue(struct pktcdvd_device *pd)
{
+ struct device *ddev = disk_to_dev(pd->disk);
struct packet_data *pkt, *p;
struct bio *bio = NULL;
sector_t zone = 0; /* Suppress gcc warning */
@@ -1080,7 +1129,7 @@ static int pkt_handle_queue(struct pktcdvd_device *pd)
atomic_set(&pd->scan_queue, 0);
if (list_empty(&pd->cdrw.pkt_free_list)) {
- pkt_dbg(2, pd, "no pkt\n");
+ dev_dbg(ddev, "no pkt\n");
return 0;
}
@@ -1117,7 +1166,7 @@ try_next_bio:
}
spin_unlock(&pd->lock);
if (!bio) {
- pkt_dbg(2, pd, "no bio\n");
+ dev_dbg(ddev, "no bio\n");
return 0;
}
@@ -1133,12 +1182,13 @@ try_next_bio:
* to this packet.
*/
spin_lock(&pd->lock);
- pkt_dbg(2, pd, "looking for zone %llx\n", (unsigned long long)zone);
+ dev_dbg(ddev, "looking for zone %llx\n", zone);
while ((node = pkt_rbtree_find(pd, zone)) != NULL) {
+ sector_t tmp = get_zone(node->bio->bi_iter.bi_sector, pd);
+
bio = node->bio;
- pkt_dbg(2, pd, "found zone=%llx\n", (unsigned long long)
- get_zone(bio->bi_iter.bi_sector, pd));
- if (get_zone(bio->bi_iter.bi_sector, pd) != zone)
+ dev_dbg(ddev, "found zone=%llx\n", tmp);
+ if (tmp != zone)
break;
pkt_rbtree_erase(pd, node);
spin_lock(&pkt->lock);
@@ -1157,7 +1207,7 @@ try_next_bio:
spin_unlock(&pd->lock);
pkt->sleep_time = max(PACKET_WAIT_TIME, 1);
- pkt_set_state(pkt, PACKET_WAITING_STATE);
+ pkt_set_state(ddev, pkt, PACKET_WAITING_STATE);
atomic_set(&pkt->run_sm, 1);
spin_lock(&pd->cdrw.active_list_lock);
@@ -1209,6 +1259,7 @@ static void bio_list_copy_data(struct bio *dst, struct bio *src)
*/
static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
{
+ struct device *ddev = disk_to_dev(pd->disk);
int f;
bio_init(pkt->w_bio, pd->bdev, pkt->w_bio->bi_inline_vecs, pkt->frames,
@@ -1225,7 +1276,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
if (!bio_add_page(pkt->w_bio, page, CD_FRAMESIZE, offset))
BUG();
}
- pkt_dbg(2, pd, "vcnt=%d\n", pkt->w_bio->bi_vcnt);
+ dev_dbg(ddev, "vcnt=%d\n", pkt->w_bio->bi_vcnt);
/*
* Fill-in bvec with data from orig_bios.
@@ -1233,11 +1284,10 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
spin_lock(&pkt->lock);
bio_list_copy_data(pkt->w_bio, pkt->orig_bios.head);
- pkt_set_state(pkt, PACKET_WRITE_WAIT_STATE);
+ pkt_set_state(ddev, pkt, PACKET_WRITE_WAIT_STATE);
spin_unlock(&pkt->lock);
- pkt_dbg(2, pd, "Writing %d frames for zone %llx\n",
- pkt->write_size, (unsigned long long)pkt->sector);
+ dev_dbg(ddev, "Writing %d frames for zone %llx\n", pkt->write_size, pkt->sector);
if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames))
pkt->cache_valid = 1;
@@ -1265,7 +1315,9 @@ static void pkt_finish_packet(struct packet_data *pkt, blk_status_t status)
static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data *pkt)
{
- pkt_dbg(2, pd, "pkt %d\n", pkt->id);
+ struct device *ddev = disk_to_dev(pd->disk);
+
+ dev_dbg(ddev, "pkt %d\n", pkt->id);
for (;;) {
switch (pkt->state) {
@@ -1275,7 +1327,7 @@ static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data
pkt->sleep_time = 0;
pkt_gather_data(pd, pkt);
- pkt_set_state(pkt, PACKET_READ_WAIT_STATE);
+ pkt_set_state(ddev, pkt, PACKET_READ_WAIT_STATE);
break;
case PACKET_READ_WAIT_STATE:
@@ -1283,7 +1335,7 @@ static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data
return;
if (atomic_read(&pkt->io_errors) > 0) {
- pkt_set_state(pkt, PACKET_RECOVERY_STATE);
+ pkt_set_state(ddev, pkt, PACKET_RECOVERY_STATE);
} else {
pkt_start_write(pd, pkt);
}
@@ -1294,15 +1346,15 @@ static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data
return;
if (!pkt->w_bio->bi_status) {
- pkt_set_state(pkt, PACKET_FINISHED_STATE);
+ pkt_set_state(ddev, pkt, PACKET_FINISHED_STATE);
} else {
- pkt_set_state(pkt, PACKET_RECOVERY_STATE);
+ pkt_set_state(ddev, pkt, PACKET_RECOVERY_STATE);
}
break;
case PACKET_RECOVERY_STATE:
- pkt_dbg(2, pd, "No recovery possible\n");
- pkt_set_state(pkt, PACKET_FINISHED_STATE);
+ dev_dbg(ddev, "No recovery possible\n");
+ pkt_set_state(ddev, pkt, PACKET_FINISHED_STATE);
break;
case PACKET_FINISHED_STATE:
@@ -1318,6 +1370,7 @@ static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data
static void pkt_handle_packets(struct pktcdvd_device *pd)
{
+ struct device *ddev = disk_to_dev(pd->disk);
struct packet_data *pkt, *next;
/*
@@ -1338,28 +1391,13 @@ static void pkt_handle_packets(struct pktcdvd_device *pd)
if (pkt->state == PACKET_FINISHED_STATE) {
list_del(&pkt->list);
pkt_put_packet_data(pd, pkt);
- pkt_set_state(pkt, PACKET_IDLE_STATE);
+ pkt_set_state(ddev, pkt, PACKET_IDLE_STATE);
atomic_set(&pd->scan_queue, 1);
}
}
spin_unlock(&pd->cdrw.active_list_lock);
}
-static void pkt_count_states(struct pktcdvd_device *pd, int *states)
-{
- struct packet_data *pkt;
- int i;
-
- for (i = 0; i < PACKET_NUM_STATES; i++)
- states[i] = 0;
-
- spin_lock(&pd->cdrw.active_list_lock);
- list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) {
- states[pkt->state]++;
- }
- spin_unlock(&pd->cdrw.active_list_lock);
-}
-
/*
* kcdrwd is woken up when writes have been queued for one of our
* registered devices
@@ -1367,7 +1405,9 @@ static void pkt_count_states(struct pktcdvd_device *pd, int *states)
static int kcdrwd(void *foobar)
{
struct pktcdvd_device *pd = foobar;
+ struct device *ddev = disk_to_dev(pd->disk);
struct packet_data *pkt;
+ int states[PACKET_NUM_STATES];
long min_sleep_time, residue;
set_user_nice(current, MIN_NICE);
@@ -1398,13 +1438,9 @@ static int kcdrwd(void *foobar)
goto work_to_do;
/* Otherwise, go to sleep */
- if (PACKET_DEBUG > 1) {
- int states[PACKET_NUM_STATES];
- pkt_count_states(pd, states);
- pkt_dbg(2, pd, "i:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n",
- states[0], states[1], states[2],
- states[3], states[4], states[5]);
- }
+ pkt_count_states(pd, states);
+ dev_dbg(ddev, "i:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n",
+ states[0], states[1], states[2], states[3], states[4], states[5]);
min_sleep_time = MAX_SCHEDULE_TIMEOUT;
list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) {
@@ -1412,9 +1448,9 @@ static int kcdrwd(void *foobar)
min_sleep_time = pkt->sleep_time;
}
- pkt_dbg(2, pd, "sleeping\n");
+ dev_dbg(ddev, "sleeping\n");
residue = schedule_timeout(min_sleep_time);
- pkt_dbg(2, pd, "wake up\n");
+ dev_dbg(ddev, "wake up\n");
/* make swsusp happy with our thread */
try_to_freeze();
@@ -1462,7 +1498,7 @@ work_to_do:
static void pkt_print_settings(struct pktcdvd_device *pd)
{
- pkt_info(pd, "%s packets, %u blocks, Mode-%c disc\n",
+ dev_info(disk_to_dev(pd->disk), "%s packets, %u blocks, Mode-%c disc\n",
pd->settings.fp ? "Fixed" : "Variable",
pd->settings.size >> 2,
pd->settings.block_mode == 8 ? '1' : '2');
@@ -1474,8 +1510,7 @@ static int pkt_mode_sense(struct pktcdvd_device *pd, struct packet_command *cgc,
cgc->cmd[0] = GPCMD_MODE_SENSE_10;
cgc->cmd[2] = page_code | (page_control << 6);
- cgc->cmd[7] = cgc->buflen >> 8;
- cgc->cmd[8] = cgc->buflen & 0xff;
+ put_unaligned_be16(cgc->buflen, &cgc->cmd[7]);
cgc->data_direction = CGC_DATA_READ;
return pkt_generic_packet(pd, cgc);
}
@@ -1486,8 +1521,7 @@ static int pkt_mode_select(struct pktcdvd_device *pd, struct packet_command *cgc
memset(cgc->buffer, 0, 2);
cgc->cmd[0] = GPCMD_MODE_SELECT_10;
cgc->cmd[1] = 0x10; /* PF */
- cgc->cmd[7] = cgc->buflen >> 8;
- cgc->cmd[8] = cgc->buflen & 0xff;
+ put_unaligned_be16(cgc->buflen, &cgc->cmd[7]);
cgc->data_direction = CGC_DATA_WRITE;
return pkt_generic_packet(pd, cgc);
}
@@ -1528,8 +1562,7 @@ static int pkt_get_track_info(struct pktcdvd_device *pd, __u16 track, __u8 type,
init_cdrom_command(&cgc, ti, 8, CGC_DATA_READ);
cgc.cmd[0] = GPCMD_READ_TRACK_RZONE_INFO;
cgc.cmd[1] = type & 3;
- cgc.cmd[4] = (track & 0xff00) >> 8;
- cgc.cmd[5] = track & 0xff;
+ put_unaligned_be16(track, &cgc.cmd[4]);
cgc.cmd[8] = 8;
cgc.quiet = 1;
@@ -1590,6 +1623,7 @@ static noinline_for_stack int pkt_get_last_written(struct pktcdvd_device *pd,
*/
static noinline_for_stack int pkt_set_write_settings(struct pktcdvd_device *pd)
{
+ struct device *ddev = disk_to_dev(pd->disk);
struct packet_command cgc;
struct scsi_sense_hdr sshdr;
write_param_page *wp;
@@ -1609,8 +1643,8 @@ static noinline_for_stack int pkt_set_write_settings(struct pktcdvd_device *pd)
return ret;
}
- size = 2 + ((buffer[0] << 8) | (buffer[1] & 0xff));
- pd->mode_offset = (buffer[6] << 8) | (buffer[7] & 0xff);
+ size = 2 + get_unaligned_be16(&buffer[0]);
+ pd->mode_offset = get_unaligned_be16(&buffer[6]);
if (size > sizeof(buffer))
size = sizeof(buffer);
@@ -1656,7 +1690,7 @@ static noinline_for_stack int pkt_set_write_settings(struct pktcdvd_device *pd)
/*
* paranoia
*/
- pkt_err(pd, "write mode wrong %d\n", wp->data_block_type);
+ dev_err(ddev, "write mode wrong %d\n", wp->data_block_type);
return 1;
}
wp->packet_size = cpu_to_be32(pd->settings.size >> 2);
@@ -1677,6 +1711,8 @@ static noinline_for_stack int pkt_set_write_settings(struct pktcdvd_device *pd)
*/
static int pkt_writable_track(struct pktcdvd_device *pd, track_information *ti)
{
+ struct device *ddev = disk_to_dev(pd->disk);
+
switch (pd->mmc3_profile) {
case 0x1a: /* DVD+RW */
case 0x12: /* DVD-RAM */
@@ -1701,7 +1737,7 @@ static int pkt_writable_track(struct pktcdvd_device *pd, track_information *ti)
if (ti->rt == 1 && ti->blank == 0)
return 1;
- pkt_err(pd, "bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet);
+ dev_err(ddev, "bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet);
return 0;
}
@@ -1710,6 +1746,8 @@ static int pkt_writable_track(struct pktcdvd_device *pd, track_information *ti)
*/
static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di)
{
+ struct device *ddev = disk_to_dev(pd->disk);
+
switch (pd->mmc3_profile) {
case 0x0a: /* CD-RW */
case 0xffff: /* MMC3 not supported */
@@ -1719,8 +1757,7 @@ static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di)
case 0x12: /* DVD-RAM */
return 1;
default:
- pkt_dbg(2, pd, "Wrong disc profile (%x)\n",
- pd->mmc3_profile);
+ dev_dbg(ddev, "Wrong disc profile (%x)\n", pd->mmc3_profile);
return 0;
}
@@ -1729,22 +1766,22 @@ static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di)
* but i'm not sure, should we leave this to user apps? probably.
*/
if (di->disc_type == 0xff) {
- pkt_notice(pd, "unknown disc - no track?\n");
+ dev_notice(ddev, "unknown disc - no track?\n");
return 0;
}
if (di->disc_type != 0x20 && di->disc_type != 0) {
- pkt_err(pd, "wrong disc type (%x)\n", di->disc_type);
+ dev_err(ddev, "wrong disc type (%x)\n", di->disc_type);
return 0;
}
if (di->erasable == 0) {
- pkt_notice(pd, "disc not erasable\n");
+ dev_err(ddev, "disc not erasable\n");
return 0;
}
if (di->border_status == PACKET_SESSION_RESERVED) {
- pkt_err(pd, "can't write to last track (reserved)\n");
+ dev_err(ddev, "can't write to last track (reserved)\n");
return 0;
}
@@ -1753,6 +1790,7 @@ static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di)
static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd)
{
+ struct device *ddev = disk_to_dev(pd->disk);
struct packet_command cgc;
unsigned char buf[12];
disc_information di;
@@ -1763,14 +1801,14 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd)
cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
cgc.cmd[8] = 8;
ret = pkt_generic_packet(pd, &cgc);
- pd->mmc3_profile = ret ? 0xffff : buf[6] << 8 | buf[7];
+ pd->mmc3_profile = ret ? 0xffff : get_unaligned_be16(&buf[6]);
memset(&di, 0, sizeof(disc_information));
memset(&ti, 0, sizeof(track_information));
ret = pkt_get_disc_info(pd, &di);
if (ret) {
- pkt_err(pd, "failed get_disc\n");
+ dev_err(ddev, "failed get_disc\n");
return ret;
}
@@ -1782,12 +1820,12 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd)
track = 1; /* (di.last_track_msb << 8) | di.last_track_lsb; */
ret = pkt_get_track_info(pd, track, 1, &ti);
if (ret) {
- pkt_err(pd, "failed get_track\n");
+ dev_err(ddev, "failed get_track\n");
return ret;
}
if (!pkt_writable_track(pd, &ti)) {
- pkt_err(pd, "can't write to this track\n");
+ dev_err(ddev, "can't write to this track\n");
return -EROFS;
}
@@ -1797,11 +1835,11 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd)
*/
pd->settings.size = be32_to_cpu(ti.fixed_packet_size) << 2;
if (pd->settings.size == 0) {
- pkt_notice(pd, "detected zero packet size!\n");
+ dev_notice(ddev, "detected zero packet size!\n");
return -ENXIO;
}
if (pd->settings.size > PACKET_MAX_SECTORS) {
- pkt_err(pd, "packet size is too big\n");
+ dev_err(ddev, "packet size is too big\n");
return -EROFS;
}
pd->settings.fp = ti.fp;
@@ -1843,7 +1881,7 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd)
pd->settings.block_mode = PACKET_BLOCK_MODE2;
break;
default:
- pkt_err(pd, "unknown data mode\n");
+ dev_err(ddev, "unknown data mode\n");
return -EROFS;
}
return 0;
@@ -1854,6 +1892,7 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd)
*/
static noinline_for_stack int pkt_write_caching(struct pktcdvd_device *pd)
{
+ struct device *ddev = disk_to_dev(pd->disk);
struct packet_command cgc;
struct scsi_sense_hdr sshdr;
unsigned char buf[64];
@@ -1880,13 +1919,13 @@ static noinline_for_stack int pkt_write_caching(struct pktcdvd_device *pd)
*/
buf[pd->mode_offset + 10] |= (set << 2);
- cgc.buflen = cgc.cmd[8] = 2 + ((buf[0] << 8) | (buf[1] & 0xff));
+ cgc.buflen = cgc.cmd[8] = 2 + get_unaligned_be16(&buf[0]);
ret = pkt_mode_select(pd, &cgc);
if (ret) {
- pkt_err(pd, "write caching control failed\n");
+ dev_err(ddev, "write caching control failed\n");
pkt_dump_sense(pd, &cgc);
} else if (!ret && set)
- pkt_notice(pd, "enabled write caching\n");
+ dev_notice(ddev, "enabled write caching\n");
return ret;
}
@@ -1935,12 +1974,12 @@ static noinline_for_stack int pkt_get_max_speed(struct pktcdvd_device *pd,
* Speed Performance Descriptor Block", use the information
* in the first block. (contains the highest speed)
*/
- int num_spdb = (cap_buf[30] << 8) + cap_buf[31];
+ int num_spdb = get_unaligned_be16(&cap_buf[30]);
if (num_spdb > 0)
offset = 34;
}
- *write_speed = (cap_buf[offset] << 8) | cap_buf[offset + 1];
+ *write_speed = get_unaligned_be16(&cap_buf[offset]);
return 0;
}
@@ -1967,6 +2006,7 @@ static char us_clv_to_speed[16] = {
static noinline_for_stack int pkt_media_speed(struct pktcdvd_device *pd,
unsigned *speed)
{
+ struct device *ddev = disk_to_dev(pd->disk);
struct packet_command cgc;
struct scsi_sense_hdr sshdr;
unsigned char buf[64];
@@ -1984,7 +2024,7 @@ static noinline_for_stack int pkt_media_speed(struct pktcdvd_device *pd,
pkt_dump_sense(pd, &cgc);
return ret;
}
- size = ((unsigned int) buf[0]<<8) + buf[1] + 2;
+ size = 2 + get_unaligned_be16(&buf[0]);
if (size > sizeof(buf))
size = sizeof(buf);
@@ -2001,11 +2041,11 @@ static noinline_for_stack int pkt_media_speed(struct pktcdvd_device *pd,
}
if (!(buf[6] & 0x40)) {
- pkt_notice(pd, "disc type is not CD-RW\n");
+ dev_notice(ddev, "disc type is not CD-RW\n");
return 1;
}
if (!(buf[6] & 0x4)) {
- pkt_notice(pd, "A1 values on media are not valid, maybe not CDRW?\n");
+ dev_notice(ddev, "A1 values on media are not valid, maybe not CDRW?\n");
return 1;
}
@@ -2025,25 +2065,26 @@ static noinline_for_stack int pkt_media_speed(struct pktcdvd_device *pd,
*speed = us_clv_to_speed[sp];
break;
default:
- pkt_notice(pd, "unknown disc sub-type %d\n", st);
+ dev_notice(ddev, "unknown disc sub-type %d\n", st);
return 1;
}
if (*speed) {
- pkt_info(pd, "maximum media speed: %d\n", *speed);
+ dev_info(ddev, "maximum media speed: %d\n", *speed);
return 0;
} else {
- pkt_notice(pd, "unknown speed %d for sub-type %d\n", sp, st);
+ dev_notice(ddev, "unknown speed %d for sub-type %d\n", sp, st);
return 1;
}
}
static noinline_for_stack int pkt_perform_opc(struct pktcdvd_device *pd)
{
+ struct device *ddev = disk_to_dev(pd->disk);
struct packet_command cgc;
struct scsi_sense_hdr sshdr;
int ret;
- pkt_dbg(2, pd, "Performing OPC\n");
+ dev_dbg(ddev, "Performing OPC\n");
init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
cgc.sshdr = &sshdr;
@@ -2058,18 +2099,19 @@ static noinline_for_stack int pkt_perform_opc(struct pktcdvd_device *pd)
static int pkt_open_write(struct pktcdvd_device *pd)
{
+ struct device *ddev = disk_to_dev(pd->disk);
int ret;
unsigned int write_speed, media_write_speed, read_speed;
ret = pkt_probe_settings(pd);
if (ret) {
- pkt_dbg(2, pd, "failed probe\n");
+ dev_dbg(ddev, "failed probe\n");
return ret;
}
ret = pkt_set_write_settings(pd);
if (ret) {
- pkt_dbg(1, pd, "failed saving write settings\n");
+ dev_notice(ddev, "failed saving write settings\n");
return -EIO;
}
@@ -2082,30 +2124,29 @@ static int pkt_open_write(struct pktcdvd_device *pd)
case 0x13: /* DVD-RW */
case 0x1a: /* DVD+RW */
case 0x12: /* DVD-RAM */
- pkt_dbg(1, pd, "write speed %ukB/s\n", write_speed);
+ dev_notice(ddev, "write speed %ukB/s\n", write_speed);
break;
default:
ret = pkt_media_speed(pd, &media_write_speed);
if (ret)
media_write_speed = 16;
write_speed = min(write_speed, media_write_speed * 177);
- pkt_dbg(1, pd, "write speed %ux\n", write_speed / 176);
+ dev_notice(ddev, "write speed %ux\n", write_speed / 176);
break;
}
read_speed = write_speed;
ret = pkt_set_speed(pd, write_speed, read_speed);
if (ret) {
- pkt_dbg(1, pd, "couldn't set write speed\n");
+ dev_notice(ddev, "couldn't set write speed\n");
return -EIO;
}
pd->write_speed = write_speed;
pd->read_speed = read_speed;
ret = pkt_perform_opc(pd);
- if (ret) {
- pkt_dbg(1, pd, "Optimum Power Calibration failed\n");
- }
+ if (ret)
+ dev_notice(ddev, "Optimum Power Calibration failed\n");
return 0;
}
@@ -2113,8 +2154,9 @@ static int pkt_open_write(struct pktcdvd_device *pd)
/*
* called at open time.
*/
-static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
+static int pkt_open_dev(struct pktcdvd_device *pd, bool write)
{
+ struct device *ddev = disk_to_dev(pd->disk);
int ret;
long lba;
struct request_queue *q;
@@ -2125,7 +2167,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
* to read/write from/to it. It is already opened in O_NONBLOCK mode
* so open should not fail.
*/
- bdev = blkdev_get_by_dev(pd->bdev->bd_dev, FMODE_READ | FMODE_EXCL, pd);
+ bdev = blkdev_get_by_dev(pd->bdev->bd_dev, BLK_OPEN_READ, pd, NULL);
if (IS_ERR(bdev)) {
ret = PTR_ERR(bdev);
goto out;
@@ -2133,7 +2175,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
ret = pkt_get_last_written(pd, &lba);
if (ret) {
- pkt_err(pd, "pkt_get_last_written failed\n");
+ dev_err(ddev, "pkt_get_last_written failed\n");
goto out_putdev;
}
@@ -2162,17 +2204,17 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
if (write) {
if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
- pkt_err(pd, "not enough memory for buffers\n");
+ dev_err(ddev, "not enough memory for buffers\n");
ret = -ENOMEM;
goto out_putdev;
}
- pkt_info(pd, "%lukB available on disc\n", lba << 1);
+ dev_info(ddev, "%lukB available on disc\n", lba << 1);
}
return 0;
out_putdev:
- blkdev_put(bdev, FMODE_READ | FMODE_EXCL);
+ blkdev_put(bdev, pd);
out:
return ret;
}
@@ -2183,13 +2225,15 @@ out:
*/
static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
{
+ struct device *ddev = disk_to_dev(pd->disk);
+
if (flush && pkt_flush_cache(pd))
- pkt_dbg(1, pd, "not flushing cache\n");
+ dev_notice(ddev, "not flushing cache\n");
pkt_lock_door(pd, 0);
pkt_set_speed(pd, MAX_SPEED, MAX_SPEED);
- blkdev_put(pd->bdev, FMODE_READ | FMODE_EXCL);
+ blkdev_put(pd->bdev, pd);
pkt_shrink_pktlist(pd);
}
@@ -2203,14 +2247,14 @@ static struct pktcdvd_device *pkt_find_dev_from_minor(unsigned int dev_minor)
return pkt_devs[dev_minor];
}
-static int pkt_open(struct block_device *bdev, fmode_t mode)
+static int pkt_open(struct gendisk *disk, blk_mode_t mode)
{
struct pktcdvd_device *pd = NULL;
int ret;
mutex_lock(&pktcdvd_mutex);
mutex_lock(&ctl_mutex);
- pd = pkt_find_dev_from_minor(MINOR(bdev->bd_dev));
+ pd = pkt_find_dev_from_minor(disk->first_minor);
if (!pd) {
ret = -ENODEV;
goto out;
@@ -2219,22 +2263,21 @@ static int pkt_open(struct block_device *bdev, fmode_t mode)
pd->refcnt++;
if (pd->refcnt > 1) {
- if ((mode & FMODE_WRITE) &&
+ if ((mode & BLK_OPEN_WRITE) &&
!test_bit(PACKET_WRITABLE, &pd->flags)) {
ret = -EBUSY;
goto out_dec;
}
} else {
- ret = pkt_open_dev(pd, mode & FMODE_WRITE);
+ ret = pkt_open_dev(pd, mode & BLK_OPEN_WRITE);
if (ret)
goto out_dec;
/*
* needed here as well, since ext2 (among others) may change
* the blocksize at mount time
*/
- set_blocksize(bdev, CD_FRAMESIZE);
+ set_blocksize(disk->part0, CD_FRAMESIZE);
}
-
mutex_unlock(&ctl_mutex);
mutex_unlock(&pktcdvd_mutex);
return 0;
@@ -2247,7 +2290,7 @@ out:
return ret;
}
-static void pkt_close(struct gendisk *disk, fmode_t mode)
+static void pkt_release(struct gendisk *disk)
{
struct pktcdvd_device *pd = disk->private_data;
@@ -2385,15 +2428,15 @@ static void pkt_make_request_write(struct request_queue *q, struct bio *bio)
static void pkt_submit_bio(struct bio *bio)
{
struct pktcdvd_device *pd = bio->bi_bdev->bd_disk->queue->queuedata;
+ struct device *ddev = disk_to_dev(pd->disk);
struct bio *split;
bio = bio_split_to_limits(bio);
if (!bio)
return;
- pkt_dbg(2, pd, "start = %6llx stop = %6llx\n",
- (unsigned long long)bio->bi_iter.bi_sector,
- (unsigned long long)bio_end_sector(bio));
+ dev_dbg(ddev, "start = %6llx stop = %6llx\n",
+ bio->bi_iter.bi_sector, bio_end_sector(bio));
/*
* Clone READ bios so we can have our own bi_end_io callback.
@@ -2404,13 +2447,12 @@ static void pkt_submit_bio(struct bio *bio)
}
if (!test_bit(PACKET_WRITABLE, &pd->flags)) {
- pkt_notice(pd, "WRITE for ro device (%llu)\n",
- (unsigned long long)bio->bi_iter.bi_sector);
+ dev_notice(ddev, "WRITE for ro device (%llu)\n", bio->bi_iter.bi_sector);
goto end_io;
}
if (!bio->bi_iter.bi_size || (bio->bi_iter.bi_size % CD_FRAMESIZE)) {
- pkt_err(pd, "wrong bio size\n");
+ dev_err(ddev, "wrong bio size\n");
goto end_io;
}
@@ -2446,74 +2488,15 @@ static void pkt_init_queue(struct pktcdvd_device *pd)
q->queuedata = pd;
}
-static int pkt_seq_show(struct seq_file *m, void *p)
-{
- struct pktcdvd_device *pd = m->private;
- char *msg;
- int states[PACKET_NUM_STATES];
-
- seq_printf(m, "Writer %s mapped to %pg:\n", pd->name, pd->bdev);
-
- seq_printf(m, "\nSettings:\n");
- seq_printf(m, "\tpacket size:\t\t%dkB\n", pd->settings.size / 2);
-
- if (pd->settings.write_type == 0)
- msg = "Packet";
- else
- msg = "Unknown";
- seq_printf(m, "\twrite type:\t\t%s\n", msg);
-
- seq_printf(m, "\tpacket type:\t\t%s\n", pd->settings.fp ? "Fixed" : "Variable");
- seq_printf(m, "\tlink loss:\t\t%d\n", pd->settings.link_loss);
-
- seq_printf(m, "\ttrack mode:\t\t%d\n", pd->settings.track_mode);
-
- if (pd->settings.block_mode == PACKET_BLOCK_MODE1)
- msg = "Mode 1";
- else if (pd->settings.block_mode == PACKET_BLOCK_MODE2)
- msg = "Mode 2";
- else
- msg = "Unknown";
- seq_printf(m, "\tblock mode:\t\t%s\n", msg);
-
- seq_printf(m, "\nStatistics:\n");
- seq_printf(m, "\tpackets started:\t%lu\n", pd->stats.pkt_started);
- seq_printf(m, "\tpackets ended:\t\t%lu\n", pd->stats.pkt_ended);
- seq_printf(m, "\twritten:\t\t%lukB\n", pd->stats.secs_w >> 1);
- seq_printf(m, "\tread gather:\t\t%lukB\n", pd->stats.secs_rg >> 1);
- seq_printf(m, "\tread:\t\t\t%lukB\n", pd->stats.secs_r >> 1);
-
- seq_printf(m, "\nMisc:\n");
- seq_printf(m, "\treference count:\t%d\n", pd->refcnt);
- seq_printf(m, "\tflags:\t\t\t0x%lx\n", pd->flags);
- seq_printf(m, "\tread speed:\t\t%ukB/s\n", pd->read_speed);
- seq_printf(m, "\twrite speed:\t\t%ukB/s\n", pd->write_speed);
- seq_printf(m, "\tstart offset:\t\t%lu\n", pd->offset);
- seq_printf(m, "\tmode page offset:\t%u\n", pd->mode_offset);
-
- seq_printf(m, "\nQueue state:\n");
- seq_printf(m, "\tbios queued:\t\t%d\n", pd->bio_queue_size);
- seq_printf(m, "\tbios pending:\t\t%d\n", atomic_read(&pd->cdrw.pending_bios));
- seq_printf(m, "\tcurrent sector:\t\t0x%llx\n", (unsigned long long)pd->current_sector);
-
- pkt_count_states(pd, states);
- seq_printf(m, "\tstate:\t\t\ti:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n",
- states[0], states[1], states[2], states[3], states[4], states[5]);
-
- seq_printf(m, "\twrite congestion marks:\toff=%d on=%d\n",
- pd->write_congestion_off,
- pd->write_congestion_on);
- return 0;
-}
-
static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
{
+ struct device *ddev = disk_to_dev(pd->disk);
int i;
struct block_device *bdev;
struct scsi_device *sdev;
if (pd->pkt_dev == dev) {
- pkt_err(pd, "recursive setup not allowed\n");
+ dev_err(ddev, "recursive setup not allowed\n");
return -EBUSY;
}
for (i = 0; i < MAX_WRITERS; i++) {
@@ -2521,21 +2504,22 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
if (!pd2)
continue;
if (pd2->bdev->bd_dev == dev) {
- pkt_err(pd, "%pg already setup\n", pd2->bdev);
+ dev_err(ddev, "%pg already setup\n", pd2->bdev);
return -EBUSY;
}
if (pd2->pkt_dev == dev) {
- pkt_err(pd, "can't chain pktcdvd devices\n");
+ dev_err(ddev, "can't chain pktcdvd devices\n");
return -EBUSY;
}
}
- bdev = blkdev_get_by_dev(dev, FMODE_READ | FMODE_NDELAY, NULL);
+ bdev = blkdev_get_by_dev(dev, BLK_OPEN_READ | BLK_OPEN_NDELAY, NULL,
+ NULL);
if (IS_ERR(bdev))
return PTR_ERR(bdev);
sdev = scsi_device_from_queue(bdev->bd_disk->queue);
if (!sdev) {
- blkdev_put(bdev, FMODE_READ | FMODE_NDELAY);
+ blkdev_put(bdev, NULL);
return -EINVAL;
}
put_device(&sdev->sdev_gendev);
@@ -2549,30 +2533,31 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
pkt_init_queue(pd);
atomic_set(&pd->cdrw.pending_bios, 0);
- pd->cdrw.thread = kthread_run(kcdrwd, pd, "%s", pd->name);
+ pd->cdrw.thread = kthread_run(kcdrwd, pd, "%s", pd->disk->disk_name);
if (IS_ERR(pd->cdrw.thread)) {
- pkt_err(pd, "can't start kernel thread\n");
+ dev_err(ddev, "can't start kernel thread\n");
goto out_mem;
}
- proc_create_single_data(pd->name, 0, pkt_proc, pkt_seq_show, pd);
- pkt_dbg(1, pd, "writer mapped to %pg\n", bdev);
+ proc_create_single_data(pd->disk->disk_name, 0, pkt_proc, pkt_seq_show, pd);
+ dev_notice(ddev, "writer mapped to %pg\n", bdev);
return 0;
out_mem:
- blkdev_put(bdev, FMODE_READ | FMODE_NDELAY);
+ blkdev_put(bdev, NULL);
/* This is safe: open() is still holding a reference. */
module_put(THIS_MODULE);
return -ENOMEM;
}
-static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg)
+static int pkt_ioctl(struct block_device *bdev, blk_mode_t mode,
+ unsigned int cmd, unsigned long arg)
{
struct pktcdvd_device *pd = bdev->bd_disk->private_data;
+ struct device *ddev = disk_to_dev(pd->disk);
int ret;
- pkt_dbg(2, pd, "cmd %x, dev %d:%d\n",
- cmd, MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
+ dev_dbg(ddev, "cmd %x, dev %d:%d\n", cmd, MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
mutex_lock(&pktcdvd_mutex);
switch (cmd) {
@@ -2598,7 +2583,7 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
ret = bdev->bd_disk->fops->ioctl(bdev, mode, cmd, arg);
break;
default:
- pkt_dbg(2, pd, "Unknown ioctl (%x)\n", cmd);
+ dev_dbg(ddev, "Unknown ioctl (%x)\n", cmd);
ret = -ENOTTY;
}
mutex_unlock(&pktcdvd_mutex);
@@ -2631,7 +2616,7 @@ static const struct block_device_operations pktcdvd_ops = {
.owner = THIS_MODULE,
.submit_bio = pkt_submit_bio,
.open = pkt_open,
- .release = pkt_close,
+ .release = pkt_release,
.ioctl = pkt_ioctl,
.compat_ioctl = blkdev_compat_ptr_ioctl,
.check_events = pkt_check_events,
@@ -2676,7 +2661,6 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
spin_lock_init(&pd->iosched.lock);
bio_list_init(&pd->iosched.read_queue);
bio_list_init(&pd->iosched.write_queue);
- sprintf(pd->name, DRIVER_NAME"%d", idx);
init_waitqueue_head(&pd->wqueue);
pd->bio_queue = RB_ROOT;
@@ -2693,7 +2677,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
disk->minors = 1;
disk->fops = &pktcdvd_ops;
disk->flags = GENHD_FL_REMOVABLE | GENHD_FL_NO_PART;
- strcpy(disk->disk_name, pd->name);
+ snprintf(disk->disk_name, sizeof(disk->disk_name), DRIVER_NAME"%d", idx);
disk->private_data = pd;
pd->pkt_dev = MKDEV(pktdev_major, idx);
@@ -2735,6 +2719,7 @@ out_mutex:
static int pkt_remove_dev(dev_t pkt_dev)
{
struct pktcdvd_device *pd;
+ struct device *ddev;
int idx;
int ret = 0;
@@ -2755,6 +2740,9 @@ static int pkt_remove_dev(dev_t pkt_dev)
ret = -EBUSY;
goto out;
}
+
+ ddev = disk_to_dev(pd->disk);
+
if (!IS_ERR(pd->cdrw.thread))
kthread_stop(pd->cdrw.thread);
@@ -2763,10 +2751,10 @@ static int pkt_remove_dev(dev_t pkt_dev)
pkt_debugfs_dev_remove(pd);
pkt_sysfs_dev_remove(pd);
- blkdev_put(pd->bdev, FMODE_READ | FMODE_NDELAY);
+ blkdev_put(pd->bdev, NULL);
- remove_proc_entry(pd->name, pkt_proc);
- pkt_dbg(1, pd, "writer unmapped\n");
+ remove_proc_entry(pd->disk->disk_name, pkt_proc);
+ dev_notice(ddev, "writer unmapped\n");
del_gendisk(pd->disk);
put_disk(pd->disk);
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 632751ddb287..2328cc05be36 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -660,9 +660,9 @@ static bool pending_result_dec(struct pending_result *pending, int *result)
return true;
}
-static int rbd_open(struct block_device *bdev, fmode_t mode)
+static int rbd_open(struct gendisk *disk, blk_mode_t mode)
{
- struct rbd_device *rbd_dev = bdev->bd_disk->private_data;
+ struct rbd_device *rbd_dev = disk->private_data;
bool removing = false;
spin_lock_irq(&rbd_dev->lock);
@@ -679,7 +679,7 @@ static int rbd_open(struct block_device *bdev, fmode_t mode)
return 0;
}
-static void rbd_release(struct gendisk *disk, fmode_t mode)
+static void rbd_release(struct gendisk *disk)
{
struct rbd_device *rbd_dev = disk->private_data;
unsigned long open_count_before;
@@ -3675,7 +3675,7 @@ static int rbd_lock(struct rbd_device *rbd_dev)
ret = ceph_cls_lock(osdc, &rbd_dev->header_oid, &rbd_dev->header_oloc,
RBD_LOCK_NAME, CEPH_CLS_LOCK_EXCLUSIVE, cookie,
RBD_LOCK_TAG, "", 0);
- if (ret)
+ if (ret && ret != -EEXIST)
return ret;
__rbd_lock(rbd_dev, cookie);
@@ -3849,51 +3849,82 @@ static void wake_lock_waiters(struct rbd_device *rbd_dev, int result)
list_splice_tail_init(&rbd_dev->acquiring_list, &rbd_dev->running_list);
}
-static int get_lock_owner_info(struct rbd_device *rbd_dev,
- struct ceph_locker **lockers, u32 *num_lockers)
+static bool locker_equal(const struct ceph_locker *lhs,
+ const struct ceph_locker *rhs)
+{
+ return lhs->id.name.type == rhs->id.name.type &&
+ lhs->id.name.num == rhs->id.name.num &&
+ !strcmp(lhs->id.cookie, rhs->id.cookie) &&
+ ceph_addr_equal_no_type(&lhs->info.addr, &rhs->info.addr);
+}
+
+static void free_locker(struct ceph_locker *locker)
+{
+ if (locker)
+ ceph_free_lockers(locker, 1);
+}
+
+static struct ceph_locker *get_lock_owner_info(struct rbd_device *rbd_dev)
{
struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
+ struct ceph_locker *lockers;
+ u32 num_lockers;
u8 lock_type;
char *lock_tag;
+ u64 handle;
int ret;
- dout("%s rbd_dev %p\n", __func__, rbd_dev);
-
ret = ceph_cls_lock_info(osdc, &rbd_dev->header_oid,
&rbd_dev->header_oloc, RBD_LOCK_NAME,
- &lock_type, &lock_tag, lockers, num_lockers);
- if (ret)
- return ret;
+ &lock_type, &lock_tag, &lockers, &num_lockers);
+ if (ret) {
+ rbd_warn(rbd_dev, "failed to get header lockers: %d", ret);
+ return ERR_PTR(ret);
+ }
- if (*num_lockers == 0) {
+ if (num_lockers == 0) {
dout("%s rbd_dev %p no lockers detected\n", __func__, rbd_dev);
+ lockers = NULL;
goto out;
}
if (strcmp(lock_tag, RBD_LOCK_TAG)) {
rbd_warn(rbd_dev, "locked by external mechanism, tag %s",
lock_tag);
- ret = -EBUSY;
- goto out;
+ goto err_busy;
}
- if (lock_type == CEPH_CLS_LOCK_SHARED) {
- rbd_warn(rbd_dev, "shared lock type detected");
- ret = -EBUSY;
- goto out;
+ if (lock_type != CEPH_CLS_LOCK_EXCLUSIVE) {
+ rbd_warn(rbd_dev, "incompatible lock type detected");
+ goto err_busy;
}
- if (strncmp((*lockers)[0].id.cookie, RBD_LOCK_COOKIE_PREFIX,
- strlen(RBD_LOCK_COOKIE_PREFIX))) {
+ WARN_ON(num_lockers != 1);
+ ret = sscanf(lockers[0].id.cookie, RBD_LOCK_COOKIE_PREFIX " %llu",
+ &handle);
+ if (ret != 1) {
rbd_warn(rbd_dev, "locked by external mechanism, cookie %s",
- (*lockers)[0].id.cookie);
- ret = -EBUSY;
- goto out;
+ lockers[0].id.cookie);
+ goto err_busy;
+ }
+ if (ceph_addr_is_blank(&lockers[0].info.addr)) {
+ rbd_warn(rbd_dev, "locker has a blank address");
+ goto err_busy;
}
+ dout("%s rbd_dev %p got locker %s%llu@%pISpc/%u handle %llu\n",
+ __func__, rbd_dev, ENTITY_NAME(lockers[0].id.name),
+ &lockers[0].info.addr.in_addr,
+ le32_to_cpu(lockers[0].info.addr.nonce), handle);
+
out:
kfree(lock_tag);
- return ret;
+ return lockers;
+
+err_busy:
+ kfree(lock_tag);
+ ceph_free_lockers(lockers, num_lockers);
+ return ERR_PTR(-EBUSY);
}
static int find_watcher(struct rbd_device *rbd_dev,
@@ -3909,8 +3940,10 @@ static int find_watcher(struct rbd_device *rbd_dev,
ret = ceph_osdc_list_watchers(osdc, &rbd_dev->header_oid,
&rbd_dev->header_oloc, &watchers,
&num_watchers);
- if (ret)
+ if (ret) {
+ rbd_warn(rbd_dev, "failed to get watchers: %d", ret);
return ret;
+ }
sscanf(locker->id.cookie, RBD_LOCK_COOKIE_PREFIX " %llu", &cookie);
for (i = 0; i < num_watchers; i++) {
@@ -3947,51 +3980,72 @@ out:
static int rbd_try_lock(struct rbd_device *rbd_dev)
{
struct ceph_client *client = rbd_dev->rbd_client->client;
- struct ceph_locker *lockers;
- u32 num_lockers;
+ struct ceph_locker *locker, *refreshed_locker;
int ret;
for (;;) {
+ locker = refreshed_locker = NULL;
+
ret = rbd_lock(rbd_dev);
- if (ret != -EBUSY)
- return ret;
+ if (!ret)
+ goto out;
+ if (ret != -EBUSY) {
+ rbd_warn(rbd_dev, "failed to lock header: %d", ret);
+ goto out;
+ }
/* determine if the current lock holder is still alive */
- ret = get_lock_owner_info(rbd_dev, &lockers, &num_lockers);
- if (ret)
- return ret;
-
- if (num_lockers == 0)
+ locker = get_lock_owner_info(rbd_dev);
+ if (IS_ERR(locker)) {
+ ret = PTR_ERR(locker);
+ locker = NULL;
+ goto out;
+ }
+ if (!locker)
goto again;
- ret = find_watcher(rbd_dev, lockers);
+ ret = find_watcher(rbd_dev, locker);
if (ret)
goto out; /* request lock or error */
+ refreshed_locker = get_lock_owner_info(rbd_dev);
+ if (IS_ERR(refreshed_locker)) {
+ ret = PTR_ERR(refreshed_locker);
+ refreshed_locker = NULL;
+ goto out;
+ }
+ if (!refreshed_locker ||
+ !locker_equal(locker, refreshed_locker))
+ goto again;
+
rbd_warn(rbd_dev, "breaking header lock owned by %s%llu",
- ENTITY_NAME(lockers[0].id.name));
+ ENTITY_NAME(locker->id.name));
ret = ceph_monc_blocklist_add(&client->monc,
- &lockers[0].info.addr);
+ &locker->info.addr);
if (ret) {
- rbd_warn(rbd_dev, "blocklist of %s%llu failed: %d",
- ENTITY_NAME(lockers[0].id.name), ret);
+ rbd_warn(rbd_dev, "failed to blocklist %s%llu: %d",
+ ENTITY_NAME(locker->id.name), ret);
goto out;
}
ret = ceph_cls_break_lock(&client->osdc, &rbd_dev->header_oid,
&rbd_dev->header_oloc, RBD_LOCK_NAME,
- lockers[0].id.cookie,
- &lockers[0].id.name);
- if (ret && ret != -ENOENT)
+ locker->id.cookie, &locker->id.name);
+ if (ret && ret != -ENOENT) {
+ rbd_warn(rbd_dev, "failed to break header lock: %d",
+ ret);
goto out;
+ }
again:
- ceph_free_lockers(lockers, num_lockers);
+ free_locker(refreshed_locker);
+ free_locker(locker);
}
out:
- ceph_free_lockers(lockers, num_lockers);
+ free_locker(refreshed_locker);
+ free_locker(locker);
return ret;
}
@@ -4041,11 +4095,8 @@ static int rbd_try_acquire_lock(struct rbd_device *rbd_dev)
ret = rbd_try_lock(rbd_dev);
if (ret < 0) {
- rbd_warn(rbd_dev, "failed to lock header: %d", ret);
- if (ret == -EBLOCKLISTED)
- goto out;
-
- ret = 1; /* request lock anyway */
+ rbd_warn(rbd_dev, "failed to acquire lock: %d", ret);
+ goto out;
}
if (ret > 0) {
up_write(&rbd_dev->lock_rwsem);
@@ -6579,12 +6630,11 @@ static int rbd_add_acquire_lock(struct rbd_device *rbd_dev)
cancel_delayed_work_sync(&rbd_dev->lock_dwork);
if (!ret)
ret = -ETIMEDOUT;
- }
- if (ret) {
- rbd_warn(rbd_dev, "failed to acquire exclusive lock: %ld", ret);
- return ret;
+ rbd_warn(rbd_dev, "failed to acquire lock: %ld", ret);
}
+ if (ret)
+ return ret;
/*
* The lock may have been released by now, unless automatic lock
diff --git a/drivers/block/rnbd/Makefile b/drivers/block/rnbd/Makefile
index 40b31630822c..208e5f865497 100644
--- a/drivers/block/rnbd/Makefile
+++ b/drivers/block/rnbd/Makefile
@@ -3,13 +3,11 @@
ccflags-y := -I$(srctree)/drivers/infiniband/ulp/rtrs
rnbd-client-y := rnbd-clt.o \
- rnbd-clt-sysfs.o \
- rnbd-common.o
+ rnbd-clt-sysfs.o
CFLAGS_rnbd-srv-trace.o = -I$(src)
-rnbd-server-y := rnbd-common.o \
- rnbd-srv.o \
+rnbd-server-y := rnbd-srv.o \
rnbd-srv-sysfs.o \
rnbd-srv-trace.o
diff --git a/drivers/block/rnbd/rnbd-clt-sysfs.c b/drivers/block/rnbd/rnbd-clt-sysfs.c
index 8c6087949794..39887556cf95 100644
--- a/drivers/block/rnbd/rnbd-clt-sysfs.c
+++ b/drivers/block/rnbd/rnbd-clt-sysfs.c
@@ -24,7 +24,9 @@
#include "rnbd-clt.h"
static struct device *rnbd_dev;
-static struct class *rnbd_dev_class;
+static const struct class rnbd_dev_class = {
+ .name = "rnbd-client",
+};
static struct kobject *rnbd_devs_kobj;
enum {
@@ -278,7 +280,7 @@ static ssize_t access_mode_show(struct kobject *kobj,
dev = container_of(kobj, struct rnbd_clt_dev, kobj);
- return sysfs_emit(page, "%s\n", rnbd_access_mode_str(dev->access_mode));
+ return sysfs_emit(page, "%s\n", rnbd_access_modes[dev->access_mode].str);
}
static struct kobj_attribute rnbd_clt_access_mode =
@@ -596,7 +598,7 @@ static ssize_t rnbd_clt_map_device_store(struct kobject *kobj,
pr_info("Mapping device %s on session %s, (access_mode: %s, nr_poll_queues: %d)\n",
pathname, sessname,
- rnbd_access_mode_str(access_mode),
+ rnbd_access_modes[access_mode].str,
nr_poll_queues);
dev = rnbd_clt_map_device(sessname, paths, path_cnt, port_nr, pathname,
@@ -646,11 +648,11 @@ int rnbd_clt_create_sysfs_files(void)
{
int err;
- rnbd_dev_class = class_create("rnbd-client");
- if (IS_ERR(rnbd_dev_class))
- return PTR_ERR(rnbd_dev_class);
+ err = class_register(&rnbd_dev_class);
+ if (err)
+ return err;
- rnbd_dev = device_create_with_groups(rnbd_dev_class, NULL,
+ rnbd_dev = device_create_with_groups(&rnbd_dev_class, NULL,
MKDEV(0, 0), NULL,
default_attr_groups, "ctl");
if (IS_ERR(rnbd_dev)) {
@@ -666,9 +668,9 @@ int rnbd_clt_create_sysfs_files(void)
return 0;
dev_destroy:
- device_destroy(rnbd_dev_class, MKDEV(0, 0));
+ device_destroy(&rnbd_dev_class, MKDEV(0, 0));
cls_destroy:
- class_destroy(rnbd_dev_class);
+ class_unregister(&rnbd_dev_class);
return err;
}
@@ -678,6 +680,6 @@ void rnbd_clt_destroy_sysfs_files(void)
sysfs_remove_group(&rnbd_dev->kobj, &default_attr_group);
kobject_del(rnbd_devs_kobj);
kobject_put(rnbd_devs_kobj);
- device_destroy(rnbd_dev_class, MKDEV(0, 0));
- class_destroy(rnbd_dev_class);
+ device_destroy(&rnbd_dev_class, MKDEV(0, 0));
+ class_unregister(&rnbd_dev_class);
}
diff --git a/drivers/block/rnbd/rnbd-clt.c b/drivers/block/rnbd/rnbd-clt.c
index 5eb8c7855970..b0550b68645d 100644
--- a/drivers/block/rnbd/rnbd-clt.c
+++ b/drivers/block/rnbd/rnbd-clt.c
@@ -921,11 +921,11 @@ rnbd_clt_session *find_or_create_sess(const char *sessname, bool *first)
return sess;
}
-static int rnbd_client_open(struct block_device *block_device, fmode_t mode)
+static int rnbd_client_open(struct gendisk *disk, blk_mode_t mode)
{
- struct rnbd_clt_dev *dev = block_device->bd_disk->private_data;
+ struct rnbd_clt_dev *dev = disk->private_data;
- if (get_disk_ro(dev->gd) && (mode & FMODE_WRITE))
+ if (get_disk_ro(dev->gd) && (mode & BLK_OPEN_WRITE))
return -EPERM;
if (dev->dev_state == DEV_STATE_UNMAPPED ||
@@ -935,7 +935,7 @@ static int rnbd_client_open(struct block_device *block_device, fmode_t mode)
return 0;
}
-static void rnbd_client_release(struct gendisk *gen, fmode_t mode)
+static void rnbd_client_release(struct gendisk *gen)
{
struct rnbd_clt_dev *dev = gen->private_data;
diff --git a/drivers/block/rnbd/rnbd-common.c b/drivers/block/rnbd/rnbd-common.c
deleted file mode 100644
index 596c3f732403..000000000000
--- a/drivers/block/rnbd/rnbd-common.c
+++ /dev/null
@@ -1,23 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * RDMA Network Block Driver
- *
- * Copyright (c) 2014 - 2018 ProfitBricks GmbH. All rights reserved.
- * Copyright (c) 2018 - 2019 1&1 IONOS Cloud GmbH. All rights reserved.
- * Copyright (c) 2019 - 2020 1&1 IONOS SE. All rights reserved.
- */
-#include "rnbd-proto.h"
-
-const char *rnbd_access_mode_str(enum rnbd_access_mode mode)
-{
- switch (mode) {
- case RNBD_ACCESS_RO:
- return "ro";
- case RNBD_ACCESS_RW:
- return "rw";
- case RNBD_ACCESS_MIGRATION:
- return "migration";
- default:
- return "unknown";
- }
-}
diff --git a/drivers/block/rnbd/rnbd-proto.h b/drivers/block/rnbd/rnbd-proto.h
index da1d0542d7e2..e32f8f2c868a 100644
--- a/drivers/block/rnbd/rnbd-proto.h
+++ b/drivers/block/rnbd/rnbd-proto.h
@@ -61,6 +61,15 @@ enum rnbd_access_mode {
RNBD_ACCESS_MIGRATION,
};
+static const __maybe_unused struct {
+ enum rnbd_access_mode mode;
+ const char *str;
+} rnbd_access_modes[] = {
+ [RNBD_ACCESS_RO] = {RNBD_ACCESS_RO, "ro"},
+ [RNBD_ACCESS_RW] = {RNBD_ACCESS_RW, "rw"},
+ [RNBD_ACCESS_MIGRATION] = {RNBD_ACCESS_MIGRATION, "migration"},
+};
+
/**
* struct rnbd_msg_sess_info - initial session info from client to server
* @hdr: message header
@@ -185,7 +194,6 @@ struct rnbd_msg_io {
enum rnbd_io_flags {
/* Operations */
-
RNBD_OP_READ = 0,
RNBD_OP_WRITE = 1,
RNBD_OP_FLUSH = 2,
@@ -193,15 +201,9 @@ enum rnbd_io_flags {
RNBD_OP_SECURE_ERASE = 4,
RNBD_OP_WRITE_SAME = 5,
- RNBD_OP_LAST,
-
/* Flags */
-
RNBD_F_SYNC = 1<<(RNBD_OP_BITS + 0),
RNBD_F_FUA = 1<<(RNBD_OP_BITS + 1),
-
- RNBD_F_ALL = (RNBD_F_SYNC | RNBD_F_FUA)
-
};
static inline u32 rnbd_op(u32 flags)
@@ -214,21 +216,6 @@ static inline u32 rnbd_flags(u32 flags)
return flags & ~RNBD_OP_MASK;
}
-static inline bool rnbd_flags_supported(u32 flags)
-{
- u32 op;
-
- op = rnbd_op(flags);
- flags = rnbd_flags(flags);
-
- if (op >= RNBD_OP_LAST)
- return false;
- if (flags & ~RNBD_F_ALL)
- return false;
-
- return true;
-}
-
static inline blk_opf_t rnbd_to_bio_flags(u32 rnbd_opf)
{
blk_opf_t bio_opf;
diff --git a/drivers/block/rnbd/rnbd-srv-sysfs.c b/drivers/block/rnbd/rnbd-srv-sysfs.c
index d5d9267e1fa5..cba6ba43c2c2 100644
--- a/drivers/block/rnbd/rnbd-srv-sysfs.c
+++ b/drivers/block/rnbd/rnbd-srv-sysfs.c
@@ -9,7 +9,6 @@
#undef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME " L" __stringify(__LINE__) ": " fmt
-#include <uapi/linux/limits.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/stat.h>
@@ -20,7 +19,9 @@
#include "rnbd-srv.h"
static struct device *rnbd_dev;
-static struct class *rnbd_dev_class;
+static const struct class rnbd_dev_class = {
+ .name = "rnbd-server",
+};
static struct kobject *rnbd_devs_kobj;
static void rnbd_srv_dev_release(struct kobject *kobj)
@@ -88,8 +89,7 @@ static ssize_t read_only_show(struct kobject *kobj, struct kobj_attribute *attr,
sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj);
- return sysfs_emit(page, "%d\n",
- !(sess_dev->open_flags & FMODE_WRITE));
+ return sysfs_emit(page, "%d\n", sess_dev->readonly);
}
static struct kobj_attribute rnbd_srv_dev_session_ro_attr =
@@ -104,7 +104,7 @@ static ssize_t access_mode_show(struct kobject *kobj,
sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj);
return sysfs_emit(page, "%s\n",
- rnbd_access_mode_str(sess_dev->access_mode));
+ rnbd_access_modes[sess_dev->access_mode].str);
}
static struct kobj_attribute rnbd_srv_dev_session_access_mode_attr =
@@ -215,12 +215,12 @@ int rnbd_srv_create_sysfs_files(void)
{
int err;
- rnbd_dev_class = class_create("rnbd-server");
- if (IS_ERR(rnbd_dev_class))
- return PTR_ERR(rnbd_dev_class);
+ err = class_register(&rnbd_dev_class);
+ if (err)
+ return err;
- rnbd_dev = device_create(rnbd_dev_class, NULL,
- MKDEV(0, 0), NULL, "ctl");
+ rnbd_dev = device_create(&rnbd_dev_class, NULL,
+ MKDEV(0, 0), NULL, "ctl");
if (IS_ERR(rnbd_dev)) {
err = PTR_ERR(rnbd_dev);
goto cls_destroy;
@@ -234,9 +234,9 @@ int rnbd_srv_create_sysfs_files(void)
return 0;
dev_destroy:
- device_destroy(rnbd_dev_class, MKDEV(0, 0));
+ device_destroy(&rnbd_dev_class, MKDEV(0, 0));
cls_destroy:
- class_destroy(rnbd_dev_class);
+ class_unregister(&rnbd_dev_class);
return err;
}
@@ -245,6 +245,6 @@ void rnbd_srv_destroy_sysfs_files(void)
{
kobject_del(rnbd_devs_kobj);
kobject_put(rnbd_devs_kobj);
- device_destroy(rnbd_dev_class, MKDEV(0, 0));
- class_destroy(rnbd_dev_class);
+ device_destroy(&rnbd_dev_class, MKDEV(0, 0));
+ class_unregister(&rnbd_dev_class);
}
diff --git a/drivers/block/rnbd/rnbd-srv.c b/drivers/block/rnbd/rnbd-srv.c
index 2cfed2e58d64..c186df0ec641 100644
--- a/drivers/block/rnbd/rnbd-srv.c
+++ b/drivers/block/rnbd/rnbd-srv.c
@@ -96,7 +96,7 @@ rnbd_get_sess_dev(int dev_id, struct rnbd_srv_session *srv_sess)
ret = kref_get_unless_zero(&sess_dev->kref);
rcu_read_unlock();
- if (!sess_dev || !ret)
+ if (!ret)
return ERR_PTR(-ENXIO);
return sess_dev;
@@ -180,7 +180,7 @@ static void destroy_device(struct kref *kref)
WARN_ONCE(!list_empty(&dev->sess_dev_list),
"Device %s is being destroyed but still in use!\n",
- dev->id);
+ dev->name);
spin_lock(&dev_lock);
list_del(&dev->list);
@@ -219,10 +219,10 @@ void rnbd_destroy_sess_dev(struct rnbd_srv_sess_dev *sess_dev, bool keep_id)
rnbd_put_sess_dev(sess_dev);
wait_for_completion(&dc); /* wait for inflights to drop to zero */
- blkdev_put(sess_dev->bdev, sess_dev->open_flags);
+ blkdev_put(sess_dev->bdev, NULL);
mutex_lock(&sess_dev->dev->lock);
list_del(&sess_dev->dev_list);
- if (sess_dev->open_flags & FMODE_WRITE)
+ if (!sess_dev->readonly)
sess_dev->dev->open_write_cnt--;
mutex_unlock(&sess_dev->dev->lock);
@@ -356,7 +356,7 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess,
const void *msg, size_t len,
void *data, size_t datalen);
-static int process_msg_sess_info(struct rnbd_srv_session *srv_sess,
+static void process_msg_sess_info(struct rnbd_srv_session *srv_sess,
const void *msg, size_t len,
void *data, size_t datalen);
@@ -384,8 +384,7 @@ static int rnbd_srv_rdma_ev(void *priv, struct rtrs_srv_op *id,
ret = process_msg_open(srv_sess, usr, usrlen, data, datalen);
break;
case RNBD_MSG_SESS_INFO:
- ret = process_msg_sess_info(srv_sess, usr, usrlen, data,
- datalen);
+ process_msg_sess_info(srv_sess, usr, usrlen, data, datalen);
break;
default:
pr_warn("Received unexpected message type %d from session %s\n",
@@ -431,7 +430,7 @@ static struct rnbd_srv_dev *rnbd_srv_init_srv_dev(struct block_device *bdev)
if (!dev)
return ERR_PTR(-ENOMEM);
- snprintf(dev->id, sizeof(dev->id), "%pg", bdev);
+ snprintf(dev->name, sizeof(dev->name), "%pg", bdev);
kref_init(&dev->kref);
INIT_LIST_HEAD(&dev->sess_dev_list);
mutex_init(&dev->lock);
@@ -446,7 +445,7 @@ rnbd_srv_find_or_add_srv_dev(struct rnbd_srv_dev *new_dev)
spin_lock(&dev_lock);
list_for_each_entry(dev, &dev_list, list) {
- if (!strncmp(dev->id, new_dev->id, sizeof(dev->id))) {
+ if (!strncmp(dev->name, new_dev->name, sizeof(dev->name))) {
if (!kref_get_unless_zero(&dev->kref))
/*
* We lost the race, device is almost dead.
@@ -467,39 +466,38 @@ static int rnbd_srv_check_update_open_perm(struct rnbd_srv_dev *srv_dev,
struct rnbd_srv_session *srv_sess,
enum rnbd_access_mode access_mode)
{
- int ret = -EPERM;
+ int ret = 0;
mutex_lock(&srv_dev->lock);
switch (access_mode) {
case RNBD_ACCESS_RO:
- ret = 0;
break;
case RNBD_ACCESS_RW:
if (srv_dev->open_write_cnt == 0) {
srv_dev->open_write_cnt++;
- ret = 0;
} else {
pr_err("Mapping device '%s' for session %s with RW permissions failed. Device already opened as 'RW' by %d client(s), access mode %s.\n",
- srv_dev->id, srv_sess->sessname,
+ srv_dev->name, srv_sess->sessname,
srv_dev->open_write_cnt,
- rnbd_access_mode_str(access_mode));
+ rnbd_access_modes[access_mode].str);
+ ret = -EPERM;
}
break;
case RNBD_ACCESS_MIGRATION:
if (srv_dev->open_write_cnt < 2) {
srv_dev->open_write_cnt++;
- ret = 0;
} else {
pr_err("Mapping device '%s' for session %s with migration permissions failed. Device already opened as 'RW' by %d client(s), access mode %s.\n",
- srv_dev->id, srv_sess->sessname,
+ srv_dev->name, srv_sess->sessname,
srv_dev->open_write_cnt,
- rnbd_access_mode_str(access_mode));
+ rnbd_access_modes[access_mode].str);
+ ret = -EPERM;
}
break;
default:
pr_err("Received mapping request for device '%s' on session %s with invalid access mode: %d\n",
- srv_dev->id, srv_sess->sessname, access_mode);
+ srv_dev->name, srv_sess->sessname, access_mode);
ret = -EINVAL;
}
@@ -561,7 +559,7 @@ static void rnbd_srv_fill_msg_open_rsp(struct rnbd_msg_open_rsp *rsp,
static struct rnbd_srv_sess_dev *
rnbd_srv_create_set_sess_dev(struct rnbd_srv_session *srv_sess,
const struct rnbd_msg_open *open_msg,
- struct block_device *bdev, fmode_t open_flags,
+ struct block_device *bdev, bool readonly,
struct rnbd_srv_dev *srv_dev)
{
struct rnbd_srv_sess_dev *sdev = rnbd_sess_dev_alloc(srv_sess);
@@ -576,7 +574,7 @@ rnbd_srv_create_set_sess_dev(struct rnbd_srv_session *srv_sess,
sdev->bdev = bdev;
sdev->sess = srv_sess;
sdev->dev = srv_dev;
- sdev->open_flags = open_flags;
+ sdev->readonly = readonly;
sdev->access_mode = open_msg->access_mode;
return sdev;
@@ -631,7 +629,7 @@ static char *rnbd_srv_get_full_path(struct rnbd_srv_session *srv_sess,
return full_path;
}
-static int process_msg_sess_info(struct rnbd_srv_session *srv_sess,
+static void process_msg_sess_info(struct rnbd_srv_session *srv_sess,
const void *msg, size_t len,
void *data, size_t datalen)
{
@@ -644,8 +642,6 @@ static int process_msg_sess_info(struct rnbd_srv_session *srv_sess,
rsp->hdr.type = cpu_to_le16(RNBD_MSG_SESS_INFO_RSP);
rsp->ver = srv_sess->ver;
-
- return 0;
}
/**
@@ -681,15 +677,14 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess,
struct rnbd_srv_sess_dev *srv_sess_dev;
const struct rnbd_msg_open *open_msg = msg;
struct block_device *bdev;
- fmode_t open_flags;
+ blk_mode_t open_flags = BLK_OPEN_READ;
char *full_path;
struct rnbd_msg_open_rsp *rsp = data;
trace_process_msg_open(srv_sess, open_msg);
- open_flags = FMODE_READ;
if (open_msg->access_mode != RNBD_ACCESS_RO)
- open_flags |= FMODE_WRITE;
+ open_flags |= BLK_OPEN_WRITE;
mutex_lock(&srv_sess->lock);
@@ -719,7 +714,7 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess,
goto reject;
}
- bdev = blkdev_get_by_path(full_path, open_flags, THIS_MODULE);
+ bdev = blkdev_get_by_path(full_path, open_flags, NULL, NULL);
if (IS_ERR(bdev)) {
ret = PTR_ERR(bdev);
pr_err("Opening device '%s' on session %s failed, failed to open the block device, err: %d\n",
@@ -736,9 +731,9 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess,
goto blkdev_put;
}
- srv_sess_dev = rnbd_srv_create_set_sess_dev(srv_sess, open_msg,
- bdev, open_flags,
- srv_dev);
+ srv_sess_dev = rnbd_srv_create_set_sess_dev(srv_sess, open_msg, bdev,
+ open_msg->access_mode == RNBD_ACCESS_RO,
+ srv_dev);
if (IS_ERR(srv_sess_dev)) {
pr_err("Opening device '%s' on session %s failed, creating sess_dev failed, err: %ld\n",
full_path, srv_sess->sessname, PTR_ERR(srv_sess_dev));
@@ -774,7 +769,7 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess,
list_add(&srv_sess_dev->dev_list, &srv_dev->sess_dev_list);
mutex_unlock(&srv_dev->lock);
- rnbd_srv_info(srv_sess_dev, "Opened device '%s'\n", srv_dev->id);
+ rnbd_srv_info(srv_sess_dev, "Opened device '%s'\n", srv_dev->name);
kfree(full_path);
@@ -795,7 +790,7 @@ srv_dev_put:
}
rnbd_put_srv_dev(srv_dev);
blkdev_put:
- blkdev_put(bdev, open_flags);
+ blkdev_put(bdev, NULL);
free_path:
kfree(full_path);
reject:
@@ -808,7 +803,7 @@ static struct rtrs_srv_ctx *rtrs_ctx;
static struct rtrs_srv_ops rtrs_ops;
static int __init rnbd_srv_init_module(void)
{
- int err;
+ int err = 0;
BUILD_BUG_ON(sizeof(struct rnbd_msg_hdr) != 4);
BUILD_BUG_ON(sizeof(struct rnbd_msg_sess_info) != 36);
@@ -822,19 +817,17 @@ static int __init rnbd_srv_init_module(void)
};
rtrs_ctx = rtrs_srv_open(&rtrs_ops, port_nr);
if (IS_ERR(rtrs_ctx)) {
- err = PTR_ERR(rtrs_ctx);
pr_err("rtrs_srv_open(), err: %d\n", err);
- return err;
+ return PTR_ERR(rtrs_ctx);
}
err = rnbd_srv_create_sysfs_files();
if (err) {
pr_err("rnbd_srv_create_sysfs_files(), err: %d\n", err);
rtrs_srv_close(rtrs_ctx);
- return err;
}
- return 0;
+ return err;
}
static void __exit rnbd_srv_cleanup_module(void)
diff --git a/drivers/block/rnbd/rnbd-srv.h b/drivers/block/rnbd/rnbd-srv.h
index f5962fd31d62..1027656dedb0 100644
--- a/drivers/block/rnbd/rnbd-srv.h
+++ b/drivers/block/rnbd/rnbd-srv.h
@@ -35,7 +35,7 @@ struct rnbd_srv_dev {
struct kobject dev_kobj;
struct kobject *dev_sessions_kobj;
struct kref kref;
- char id[NAME_MAX];
+ char name[NAME_MAX];
/* List of rnbd_srv_sess_dev structs */
struct list_head sess_dev_list;
struct mutex lock;
@@ -52,7 +52,7 @@ struct rnbd_srv_sess_dev {
struct kobject kobj;
u32 device_id;
bool keep_id;
- fmode_t open_flags;
+ bool readonly;
struct kref kref;
struct completion *destroy_comp;
char pathname[NAME_MAX];
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
index 9fa821fa76b0..7bf4b48e2282 100644
--- a/drivers/block/sunvdc.c
+++ b/drivers/block/sunvdc.c
@@ -139,7 +139,7 @@ static int vdc_getgeo(struct block_device *bdev, struct hd_geometry *geo)
* when vdisk_mtype is VD_MEDIA_TYPE_CD or VD_MEDIA_TYPE_DVD.
* Needed to be able to install inside an ldom from an iso image.
*/
-static int vdc_ioctl(struct block_device *bdev, fmode_t mode,
+static int vdc_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned command, unsigned long argument)
{
struct vdc_port *port = bdev->bd_disk->private_data;
diff --git a/drivers/block/swim.c b/drivers/block/swim.c
index 42b4b6828690..f85b6af414b4 100644
--- a/drivers/block/swim.c
+++ b/drivers/block/swim.c
@@ -608,20 +608,18 @@ static void setup_medium(struct floppy_state *fs)
}
}
-static int floppy_open(struct block_device *bdev, fmode_t mode)
+static int floppy_open(struct gendisk *disk, blk_mode_t mode)
{
- struct floppy_state *fs = bdev->bd_disk->private_data;
+ struct floppy_state *fs = disk->private_data;
struct swim __iomem *base = fs->swd->base;
int err;
- if (fs->ref_count == -1 || (fs->ref_count && mode & FMODE_EXCL))
+ if (fs->ref_count == -1 || (fs->ref_count && mode & BLK_OPEN_EXCL))
return -EBUSY;
-
- if (mode & FMODE_EXCL)
+ if (mode & BLK_OPEN_EXCL)
fs->ref_count = -1;
else
fs->ref_count++;
-
swim_write(base, setup, S_IBM_DRIVE | S_FCLK_DIV2);
udelay(10);
swim_drive(base, fs->location);
@@ -636,13 +634,13 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
set_capacity(fs->disk, fs->total_secs);
- if (mode & FMODE_NDELAY)
+ if (mode & BLK_OPEN_NDELAY)
return 0;
- if (mode & (FMODE_READ|FMODE_WRITE)) {
- if (bdev_check_media_change(bdev) && fs->disk_in)
+ if (mode & (BLK_OPEN_READ | BLK_OPEN_WRITE)) {
+ if (disk_check_media_change(disk) && fs->disk_in)
fs->ejected = 0;
- if ((mode & FMODE_WRITE) && fs->write_protected) {
+ if ((mode & BLK_OPEN_WRITE) && fs->write_protected) {
err = -EROFS;
goto out;
}
@@ -659,18 +657,18 @@ out:
return err;
}
-static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode)
+static int floppy_unlocked_open(struct gendisk *disk, blk_mode_t mode)
{
int ret;
mutex_lock(&swim_mutex);
- ret = floppy_open(bdev, mode);
+ ret = floppy_open(disk, mode);
mutex_unlock(&swim_mutex);
return ret;
}
-static void floppy_release(struct gendisk *disk, fmode_t mode)
+static void floppy_release(struct gendisk *disk)
{
struct floppy_state *fs = disk->private_data;
struct swim __iomem *base = fs->swd->base;
@@ -686,7 +684,7 @@ static void floppy_release(struct gendisk *disk, fmode_t mode)
mutex_unlock(&swim_mutex);
}
-static int floppy_ioctl(struct block_device *bdev, fmode_t mode,
+static int floppy_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long param)
{
struct floppy_state *fs = bdev->bd_disk->private_data;
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index da811a7da03f..dc43a63b3469 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -246,10 +246,9 @@ static int grab_drive(struct floppy_state *fs, enum swim_state state,
int interruptible);
static void release_drive(struct floppy_state *fs);
static int fd_eject(struct floppy_state *fs);
-static int floppy_ioctl(struct block_device *bdev, fmode_t mode,
+static int floppy_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long param);
-static int floppy_open(struct block_device *bdev, fmode_t mode);
-static void floppy_release(struct gendisk *disk, fmode_t mode);
+static int floppy_open(struct gendisk *disk, blk_mode_t mode);
static unsigned int floppy_check_events(struct gendisk *disk,
unsigned int clearing);
static int floppy_revalidate(struct gendisk *disk);
@@ -883,7 +882,7 @@ static int fd_eject(struct floppy_state *fs)
static struct floppy_struct floppy_type =
{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }; /* 7 1.44MB 3.5" */
-static int floppy_locked_ioctl(struct block_device *bdev, fmode_t mode,
+static int floppy_locked_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long param)
{
struct floppy_state *fs = bdev->bd_disk->private_data;
@@ -911,7 +910,7 @@ static int floppy_locked_ioctl(struct block_device *bdev, fmode_t mode,
return -ENOTTY;
}
-static int floppy_ioctl(struct block_device *bdev, fmode_t mode,
+static int floppy_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long param)
{
int ret;
@@ -923,9 +922,9 @@ static int floppy_ioctl(struct block_device *bdev, fmode_t mode,
return ret;
}
-static int floppy_open(struct block_device *bdev, fmode_t mode)
+static int floppy_open(struct gendisk *disk, blk_mode_t mode)
{
- struct floppy_state *fs = bdev->bd_disk->private_data;
+ struct floppy_state *fs = disk->private_data;
struct swim3 __iomem *sw = fs->swim3;
int n, err = 0;
@@ -958,18 +957,18 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
swim3_action(fs, SETMFM);
swim3_select(fs, RELAX);
- } else if (fs->ref_count == -1 || mode & FMODE_EXCL)
+ } else if (fs->ref_count == -1 || mode & BLK_OPEN_EXCL)
return -EBUSY;
- if (err == 0 && (mode & FMODE_NDELAY) == 0
- && (mode & (FMODE_READ|FMODE_WRITE))) {
- if (bdev_check_media_change(bdev))
- floppy_revalidate(bdev->bd_disk);
+ if (err == 0 && !(mode & BLK_OPEN_NDELAY) &&
+ (mode & (BLK_OPEN_READ | BLK_OPEN_WRITE))) {
+ if (disk_check_media_change(disk))
+ floppy_revalidate(disk);
if (fs->ejected)
err = -ENXIO;
}
- if (err == 0 && (mode & FMODE_WRITE)) {
+ if (err == 0 && (mode & BLK_OPEN_WRITE)) {
if (fs->write_prot < 0)
fs->write_prot = swim3_readbit(fs, WRITE_PROT);
if (fs->write_prot)
@@ -985,7 +984,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
return err;
}
- if (mode & FMODE_EXCL)
+ if (mode & BLK_OPEN_EXCL)
fs->ref_count = -1;
else
++fs->ref_count;
@@ -993,18 +992,18 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
return 0;
}
-static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode)
+static int floppy_unlocked_open(struct gendisk *disk, blk_mode_t mode)
{
int ret;
mutex_lock(&swim3_mutex);
- ret = floppy_open(bdev, mode);
+ ret = floppy_open(disk, mode);
mutex_unlock(&swim3_mutex);
return ret;
}
-static void floppy_release(struct gendisk *disk, fmode_t mode)
+static void floppy_release(struct gendisk *disk)
{
struct floppy_state *fs = disk->private_data;
struct swim3 __iomem *sw = fs->swim3;
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 33d3298a0da1..21d2e71c5514 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -43,6 +43,7 @@
#include <asm/page.h>
#include <linux/task_work.h>
#include <linux/namei.h>
+#include <linux/kref.h>
#include <uapi/linux/ublk_cmd.h>
#define UBLK_MINORS (1U << MINORBITS)
@@ -54,7 +55,8 @@
| UBLK_F_USER_RECOVERY \
| UBLK_F_USER_RECOVERY_REISSUE \
| UBLK_F_UNPRIVILEGED_DEV \
- | UBLK_F_CMD_IOCTL_ENCODE)
+ | UBLK_F_CMD_IOCTL_ENCODE \
+ | UBLK_F_USER_COPY)
/* All UBLK_PARAM_TYPE_* should be included here */
#define UBLK_PARAM_TYPE_ALL (UBLK_PARAM_TYPE_BASIC | \
@@ -62,7 +64,8 @@
struct ublk_rq_data {
struct llist_node node;
- struct callback_head work;
+
+ struct kref ref;
};
struct ublk_uring_cmd_pdu {
@@ -182,8 +185,13 @@ struct ublk_params_header {
__u32 types;
};
+static inline void __ublk_complete_rq(struct request *req);
+static void ublk_complete_rq(struct kref *ref);
+
static dev_t ublk_chr_devt;
-static struct class *ublk_chr_class;
+static const struct class ublk_chr_class = {
+ .name = "ublk-char",
+};
static DEFINE_IDR(ublk_index_idr);
static DEFINE_SPINLOCK(ublk_idr_lock);
@@ -202,6 +210,23 @@ static unsigned int ublks_added; /* protected by ublk_ctl_mutex */
static struct miscdevice ublk_misc;
+static inline unsigned ublk_pos_to_hwq(loff_t pos)
+{
+ return ((pos - UBLKSRV_IO_BUF_OFFSET) >> UBLK_QID_OFF) &
+ UBLK_QID_BITS_MASK;
+}
+
+static inline unsigned ublk_pos_to_buf_off(loff_t pos)
+{
+ return (pos - UBLKSRV_IO_BUF_OFFSET) & UBLK_IO_BUF_BITS_MASK;
+}
+
+static inline unsigned ublk_pos_to_tag(loff_t pos)
+{
+ return ((pos - UBLKSRV_IO_BUF_OFFSET) >> UBLK_TAG_OFF) &
+ UBLK_TAG_BITS_MASK;
+}
+
static void ublk_dev_param_basic_apply(struct ublk_device *ub)
{
struct request_queue *q = ub->ub_disk->queue;
@@ -290,12 +315,52 @@ static int ublk_apply_params(struct ublk_device *ub)
return 0;
}
-static inline bool ublk_can_use_task_work(const struct ublk_queue *ubq)
+static inline bool ublk_support_user_copy(const struct ublk_queue *ubq)
{
- if (IS_BUILTIN(CONFIG_BLK_DEV_UBLK) &&
- !(ubq->flags & UBLK_F_URING_CMD_COMP_IN_TASK))
- return true;
- return false;
+ return ubq->flags & UBLK_F_USER_COPY;
+}
+
+static inline bool ublk_need_req_ref(const struct ublk_queue *ubq)
+{
+ /*
+ * read()/write() is involved in user copy, so request reference
+ * has to be grabbed
+ */
+ return ublk_support_user_copy(ubq);
+}
+
+static inline void ublk_init_req_ref(const struct ublk_queue *ubq,
+ struct request *req)
+{
+ if (ublk_need_req_ref(ubq)) {
+ struct ublk_rq_data *data = blk_mq_rq_to_pdu(req);
+
+ kref_init(&data->ref);
+ }
+}
+
+static inline bool ublk_get_req_ref(const struct ublk_queue *ubq,
+ struct request *req)
+{
+ if (ublk_need_req_ref(ubq)) {
+ struct ublk_rq_data *data = blk_mq_rq_to_pdu(req);
+
+ return kref_get_unless_zero(&data->ref);
+ }
+
+ return true;
+}
+
+static inline void ublk_put_req_ref(const struct ublk_queue *ubq,
+ struct request *req)
+{
+ if (ublk_need_req_ref(ubq)) {
+ struct ublk_rq_data *data = blk_mq_rq_to_pdu(req);
+
+ kref_put(&data->ref, ublk_complete_rq);
+ } else {
+ __ublk_complete_rq(req);
+ }
}
static inline bool ublk_need_get_data(const struct ublk_queue *ubq)
@@ -384,9 +449,9 @@ static void ublk_store_owner_uid_gid(unsigned int *owner_uid,
*owner_gid = from_kgid(&init_user_ns, gid);
}
-static int ublk_open(struct block_device *bdev, fmode_t mode)
+static int ublk_open(struct gendisk *disk, blk_mode_t mode)
{
- struct ublk_device *ub = bdev->bd_disk->private_data;
+ struct ublk_device *ub = disk->private_data;
if (capable(CAP_SYS_ADMIN))
return 0;
@@ -421,49 +486,39 @@ static const struct block_device_operations ub_fops = {
#define UBLK_MAX_PIN_PAGES 32
-struct ublk_map_data {
- const struct request *rq;
- unsigned long ubuf;
- unsigned int len;
-};
-
struct ublk_io_iter {
struct page *pages[UBLK_MAX_PIN_PAGES];
- unsigned pg_off; /* offset in the 1st page in pages */
- int nr_pages; /* how many page pointers in pages */
struct bio *bio;
struct bvec_iter iter;
};
-static inline unsigned ublk_copy_io_pages(struct ublk_io_iter *data,
- unsigned max_bytes, bool to_vm)
+/* return how many pages are copied */
+static void ublk_copy_io_pages(struct ublk_io_iter *data,
+ size_t total, size_t pg_off, int dir)
{
- const unsigned total = min_t(unsigned, max_bytes,
- PAGE_SIZE - data->pg_off +
- ((data->nr_pages - 1) << PAGE_SHIFT));
unsigned done = 0;
unsigned pg_idx = 0;
while (done < total) {
struct bio_vec bv = bio_iter_iovec(data->bio, data->iter);
- const unsigned int bytes = min3(bv.bv_len, total - done,
- (unsigned)(PAGE_SIZE - data->pg_off));
+ unsigned int bytes = min3(bv.bv_len, (unsigned)total - done,
+ (unsigned)(PAGE_SIZE - pg_off));
void *bv_buf = bvec_kmap_local(&bv);
void *pg_buf = kmap_local_page(data->pages[pg_idx]);
- if (to_vm)
- memcpy(pg_buf + data->pg_off, bv_buf, bytes);
+ if (dir == ITER_DEST)
+ memcpy(pg_buf + pg_off, bv_buf, bytes);
else
- memcpy(bv_buf, pg_buf + data->pg_off, bytes);
+ memcpy(bv_buf, pg_buf + pg_off, bytes);
kunmap_local(pg_buf);
kunmap_local(bv_buf);
/* advance page array */
- data->pg_off += bytes;
- if (data->pg_off == PAGE_SIZE) {
+ pg_off += bytes;
+ if (pg_off == PAGE_SIZE) {
pg_idx += 1;
- data->pg_off = 0;
+ pg_off = 0;
}
done += bytes;
@@ -477,41 +532,58 @@ static inline unsigned ublk_copy_io_pages(struct ublk_io_iter *data,
data->iter = data->bio->bi_iter;
}
}
+}
- return done;
+static bool ublk_advance_io_iter(const struct request *req,
+ struct ublk_io_iter *iter, unsigned int offset)
+{
+ struct bio *bio = req->bio;
+
+ for_each_bio(bio) {
+ if (bio->bi_iter.bi_size > offset) {
+ iter->bio = bio;
+ iter->iter = bio->bi_iter;
+ bio_advance_iter(iter->bio, &iter->iter, offset);
+ return true;
+ }
+ offset -= bio->bi_iter.bi_size;
+ }
+ return false;
}
-static int ublk_copy_user_pages(struct ublk_map_data *data, bool to_vm)
+/*
+ * Copy data between request pages and io_iter, and 'offset'
+ * is the start point of linear offset of request.
+ */
+static size_t ublk_copy_user_pages(const struct request *req,
+ unsigned offset, struct iov_iter *uiter, int dir)
{
- const unsigned int gup_flags = to_vm ? FOLL_WRITE : 0;
- const unsigned long start_vm = data->ubuf;
- unsigned int done = 0;
- struct ublk_io_iter iter = {
- .pg_off = start_vm & (PAGE_SIZE - 1),
- .bio = data->rq->bio,
- .iter = data->rq->bio->bi_iter,
- };
- const unsigned int nr_pages = round_up(data->len +
- (start_vm & (PAGE_SIZE - 1)), PAGE_SIZE) >> PAGE_SHIFT;
-
- while (done < nr_pages) {
- const unsigned to_pin = min_t(unsigned, UBLK_MAX_PIN_PAGES,
- nr_pages - done);
- unsigned i, len;
-
- iter.nr_pages = get_user_pages_fast(start_vm +
- (done << PAGE_SHIFT), to_pin, gup_flags,
- iter.pages);
- if (iter.nr_pages <= 0)
- return done == 0 ? iter.nr_pages : done;
- len = ublk_copy_io_pages(&iter, data->len, to_vm);
- for (i = 0; i < iter.nr_pages; i++) {
- if (to_vm)
+ struct ublk_io_iter iter;
+ size_t done = 0;
+
+ if (!ublk_advance_io_iter(req, &iter, offset))
+ return 0;
+
+ while (iov_iter_count(uiter) && iter.bio) {
+ unsigned nr_pages;
+ ssize_t len;
+ size_t off;
+ int i;
+
+ len = iov_iter_get_pages2(uiter, iter.pages,
+ iov_iter_count(uiter),
+ UBLK_MAX_PIN_PAGES, &off);
+ if (len <= 0)
+ return done;
+
+ ublk_copy_io_pages(&iter, len, off, dir);
+ nr_pages = DIV_ROUND_UP(len + off, PAGE_SIZE);
+ for (i = 0; i < nr_pages; i++) {
+ if (dir == ITER_DEST)
set_page_dirty(iter.pages[i]);
put_page(iter.pages[i]);
}
- data->len -= len;
- done += iter.nr_pages;
+ done += len;
}
return done;
@@ -532,21 +604,23 @@ static int ublk_map_io(const struct ublk_queue *ubq, const struct request *req,
{
const unsigned int rq_bytes = blk_rq_bytes(req);
+ if (ublk_support_user_copy(ubq))
+ return rq_bytes;
+
/*
* no zero copy, we delay copy WRITE request data into ublksrv
* context and the big benefit is that pinning pages in current
* context is pretty fast, see ublk_pin_user_pages
*/
if (ublk_need_map_req(req)) {
- struct ublk_map_data data = {
- .rq = req,
- .ubuf = io->addr,
- .len = rq_bytes,
- };
+ struct iov_iter iter;
+ struct iovec iov;
+ const int dir = ITER_DEST;
- ublk_copy_user_pages(&data, true);
+ import_single_range(dir, u64_to_user_ptr(io->addr), rq_bytes,
+ &iov, &iter);
- return rq_bytes - data.len;
+ return ublk_copy_user_pages(req, 0, &iter, dir);
}
return rq_bytes;
}
@@ -557,18 +631,19 @@ static int ublk_unmap_io(const struct ublk_queue *ubq,
{
const unsigned int rq_bytes = blk_rq_bytes(req);
+ if (ublk_support_user_copy(ubq))
+ return rq_bytes;
+
if (ublk_need_unmap_req(req)) {
- struct ublk_map_data data = {
- .rq = req,
- .ubuf = io->addr,
- .len = io->res,
- };
+ struct iov_iter iter;
+ struct iovec iov;
+ const int dir = ITER_SOURCE;
WARN_ON_ONCE(io->res > rq_bytes);
- ublk_copy_user_pages(&data, false);
-
- return io->res - data.len;
+ import_single_range(dir, u64_to_user_ptr(io->addr), io->res,
+ &iov, &iter);
+ return ublk_copy_user_pages(req, 0, &iter, dir);
}
return rq_bytes;
}
@@ -648,13 +723,19 @@ static inline bool ubq_daemon_is_dying(struct ublk_queue *ubq)
}
/* todo: handle partial completion */
-static void ublk_complete_rq(struct request *req)
+static inline void __ublk_complete_rq(struct request *req)
{
struct ublk_queue *ubq = req->mq_hctx->driver_data;
struct ublk_io *io = &ubq->ios[req->tag];
unsigned int unmapped_bytes;
blk_status_t res = BLK_STS_OK;
+ /* called from ublk_abort_queue() code path */
+ if (io->flags & UBLK_IO_FLAG_ABORTED) {
+ res = BLK_STS_IOERR;
+ goto exit;
+ }
+
/* failed read IO if nothing is read */
if (!io->res && req_op(req) == REQ_OP_READ)
io->res = -EIO;
@@ -694,6 +775,15 @@ exit:
blk_mq_end_request(req, res);
}
+static void ublk_complete_rq(struct kref *ref)
+{
+ struct ublk_rq_data *data = container_of(ref, struct ublk_rq_data,
+ ref);
+ struct request *req = blk_mq_rq_from_pdu(data);
+
+ __ublk_complete_rq(req);
+}
+
/*
* Since __ublk_rq_task_work always fails requests immediately during
* exiting, __ublk_fail_req() is only called from abort context during
@@ -712,7 +802,7 @@ static void __ublk_fail_req(struct ublk_queue *ubq, struct ublk_io *io,
if (ublk_queue_can_use_recovery_reissue(ubq))
blk_mq_requeue_request(req, false);
else
- blk_mq_end_request(req, BLK_STS_IOERR);
+ ublk_put_req_ref(ubq, req);
}
}
@@ -821,6 +911,7 @@ static inline void __ublk_rq_task_work(struct request *req,
mapped_bytes >> 9;
}
+ ublk_init_req_ref(ubq, req);
ubq_complete_io_cmd(io, UBLK_IO_RES_OK, issue_flags);
}
@@ -852,17 +943,6 @@ static void ublk_rq_task_work_cb(struct io_uring_cmd *cmd, unsigned issue_flags)
ublk_forward_io_cmds(ubq, issue_flags);
}
-static void ublk_rq_task_work_fn(struct callback_head *work)
-{
- struct ublk_rq_data *data = container_of(work,
- struct ublk_rq_data, work);
- struct request *req = blk_mq_rq_from_pdu(data);
- struct ublk_queue *ubq = req->mq_hctx->driver_data;
- unsigned issue_flags = IO_URING_F_UNLOCKED;
-
- ublk_forward_io_cmds(ubq, issue_flags);
-}
-
static void ublk_queue_cmd(struct ublk_queue *ubq, struct request *rq)
{
struct ublk_rq_data *data = blk_mq_rq_to_pdu(rq);
@@ -886,10 +966,6 @@ static void ublk_queue_cmd(struct ublk_queue *ubq, struct request *rq)
*/
if (unlikely(io->flags & UBLK_IO_FLAG_ABORTED)) {
ublk_abort_io_cmds(ubq);
- } else if (ublk_can_use_task_work(ubq)) {
- if (task_work_add(ubq->ubq_daemon, &data->work,
- TWA_SIGNAL_NO_IPI))
- ublk_abort_io_cmds(ubq);
} else {
struct io_uring_cmd *cmd = io->cmd;
struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
@@ -961,19 +1037,9 @@ static int ublk_init_hctx(struct blk_mq_hw_ctx *hctx, void *driver_data,
return 0;
}
-static int ublk_init_rq(struct blk_mq_tag_set *set, struct request *req,
- unsigned int hctx_idx, unsigned int numa_node)
-{
- struct ublk_rq_data *data = blk_mq_rq_to_pdu(req);
-
- init_task_work(&data->work, ublk_rq_task_work_fn);
- return 0;
-}
-
static const struct blk_mq_ops ublk_mq_ops = {
.queue_rq = ublk_queue_rq,
.init_hctx = ublk_init_hctx,
- .init_request = ublk_init_rq,
.timeout = ublk_timeout,
};
@@ -1050,7 +1116,7 @@ static void ublk_commit_completion(struct ublk_device *ub,
req = blk_mq_tag_to_rq(ub->tag_set.tags[qid], tag);
if (req && likely(!blk_should_fake_timeout(req->q)))
- ublk_complete_rq(req);
+ ublk_put_req_ref(ubq, req);
}
/*
@@ -1295,6 +1361,14 @@ static inline int ublk_check_cmd_op(u32 cmd_op)
return 0;
}
+static inline void ublk_fill_io_cmd(struct ublk_io *io,
+ struct io_uring_cmd *cmd, unsigned long buf_addr)
+{
+ io->cmd = cmd;
+ io->flags |= UBLK_IO_FLAG_ACTIVE;
+ io->addr = buf_addr;
+}
+
static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
unsigned int issue_flags,
const struct ublksrv_io_cmd *ub_cmd)
@@ -1340,6 +1414,11 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
^ (_IOC_NR(cmd_op) == UBLK_IO_NEED_GET_DATA))
goto out;
+ if (ublk_support_user_copy(ubq) && ub_cmd->addr) {
+ ret = -EINVAL;
+ goto out;
+ }
+
ret = ublk_check_cmd_op(cmd_op);
if (ret)
goto out;
@@ -1358,36 +1437,41 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
*/
if (io->flags & UBLK_IO_FLAG_OWNED_BY_SRV)
goto out;
- /* FETCH_RQ has to provide IO buffer if NEED GET DATA is not enabled */
- if (!ub_cmd->addr && !ublk_need_get_data(ubq))
- goto out;
- io->cmd = cmd;
- io->flags |= UBLK_IO_FLAG_ACTIVE;
- io->addr = ub_cmd->addr;
+ if (!ublk_support_user_copy(ubq)) {
+ /*
+ * FETCH_RQ has to provide IO buffer if NEED GET
+ * DATA is not enabled
+ */
+ if (!ub_cmd->addr && !ublk_need_get_data(ubq))
+ goto out;
+ }
+
+ ublk_fill_io_cmd(io, cmd, ub_cmd->addr);
ublk_mark_io_ready(ub, ubq);
break;
case UBLK_IO_COMMIT_AND_FETCH_REQ:
req = blk_mq_tag_to_rq(ub->tag_set.tags[ub_cmd->q_id], tag);
- /*
- * COMMIT_AND_FETCH_REQ has to provide IO buffer if NEED GET DATA is
- * not enabled or it is Read IO.
- */
- if (!ub_cmd->addr && (!ublk_need_get_data(ubq) || req_op(req) == REQ_OP_READ))
- goto out;
+
if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
goto out;
- io->addr = ub_cmd->addr;
- io->flags |= UBLK_IO_FLAG_ACTIVE;
- io->cmd = cmd;
+
+ if (!ublk_support_user_copy(ubq)) {
+ /*
+ * COMMIT_AND_FETCH_REQ has to provide IO buffer if
+ * NEED GET DATA is not enabled or it is Read IO.
+ */
+ if (!ub_cmd->addr && (!ublk_need_get_data(ubq) ||
+ req_op(req) == REQ_OP_READ))
+ goto out;
+ }
+ ublk_fill_io_cmd(io, cmd, ub_cmd->addr);
ublk_commit_completion(ub, ub_cmd);
break;
case UBLK_IO_NEED_GET_DATA:
if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
goto out;
- io->addr = ub_cmd->addr;
- io->cmd = cmd;
- io->flags |= UBLK_IO_FLAG_ACTIVE;
+ ublk_fill_io_cmd(io, cmd, ub_cmd->addr);
ublk_handle_need_get_data(ub, ub_cmd->q_id, ub_cmd->tag);
break;
default:
@@ -1402,6 +1486,36 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
return -EIOCBQUEUED;
}
+static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub,
+ struct ublk_queue *ubq, int tag, size_t offset)
+{
+ struct request *req;
+
+ if (!ublk_need_req_ref(ubq))
+ return NULL;
+
+ req = blk_mq_tag_to_rq(ub->tag_set.tags[ubq->q_id], tag);
+ if (!req)
+ return NULL;
+
+ if (!ublk_get_req_ref(ubq, req))
+ return NULL;
+
+ if (unlikely(!blk_mq_request_started(req) || req->tag != tag))
+ goto fail_put;
+
+ if (!ublk_rq_has_data(req))
+ goto fail_put;
+
+ if (offset > blk_rq_bytes(req))
+ goto fail_put;
+
+ return req;
+fail_put:
+ ublk_put_req_ref(ubq, req);
+ return NULL;
+}
+
static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
{
/*
@@ -1419,11 +1533,112 @@ static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
return __ublk_ch_uring_cmd(cmd, issue_flags, &ub_cmd);
}
+static inline bool ublk_check_ubuf_dir(const struct request *req,
+ int ubuf_dir)
+{
+ /* copy ubuf to request pages */
+ if (req_op(req) == REQ_OP_READ && ubuf_dir == ITER_SOURCE)
+ return true;
+
+ /* copy request pages to ubuf */
+ if (req_op(req) == REQ_OP_WRITE && ubuf_dir == ITER_DEST)
+ return true;
+
+ return false;
+}
+
+static struct request *ublk_check_and_get_req(struct kiocb *iocb,
+ struct iov_iter *iter, size_t *off, int dir)
+{
+ struct ublk_device *ub = iocb->ki_filp->private_data;
+ struct ublk_queue *ubq;
+ struct request *req;
+ size_t buf_off;
+ u16 tag, q_id;
+
+ if (!ub)
+ return ERR_PTR(-EACCES);
+
+ if (!user_backed_iter(iter))
+ return ERR_PTR(-EACCES);
+
+ if (ub->dev_info.state == UBLK_S_DEV_DEAD)
+ return ERR_PTR(-EACCES);
+
+ tag = ublk_pos_to_tag(iocb->ki_pos);
+ q_id = ublk_pos_to_hwq(iocb->ki_pos);
+ buf_off = ublk_pos_to_buf_off(iocb->ki_pos);
+
+ if (q_id >= ub->dev_info.nr_hw_queues)
+ return ERR_PTR(-EINVAL);
+
+ ubq = ublk_get_queue(ub, q_id);
+ if (!ubq)
+ return ERR_PTR(-EINVAL);
+
+ if (tag >= ubq->q_depth)
+ return ERR_PTR(-EINVAL);
+
+ req = __ublk_check_and_get_req(ub, ubq, tag, buf_off);
+ if (!req)
+ return ERR_PTR(-EINVAL);
+
+ if (!req->mq_hctx || !req->mq_hctx->driver_data)
+ goto fail;
+
+ if (!ublk_check_ubuf_dir(req, dir))
+ goto fail;
+
+ *off = buf_off;
+ return req;
+fail:
+ ublk_put_req_ref(ubq, req);
+ return ERR_PTR(-EACCES);
+}
+
+static ssize_t ublk_ch_read_iter(struct kiocb *iocb, struct iov_iter *to)
+{
+ struct ublk_queue *ubq;
+ struct request *req;
+ size_t buf_off;
+ size_t ret;
+
+ req = ublk_check_and_get_req(iocb, to, &buf_off, ITER_DEST);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
+
+ ret = ublk_copy_user_pages(req, buf_off, to, ITER_DEST);
+ ubq = req->mq_hctx->driver_data;
+ ublk_put_req_ref(ubq, req);
+
+ return ret;
+}
+
+static ssize_t ublk_ch_write_iter(struct kiocb *iocb, struct iov_iter *from)
+{
+ struct ublk_queue *ubq;
+ struct request *req;
+ size_t buf_off;
+ size_t ret;
+
+ req = ublk_check_and_get_req(iocb, from, &buf_off, ITER_SOURCE);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
+
+ ret = ublk_copy_user_pages(req, buf_off, from, ITER_SOURCE);
+ ubq = req->mq_hctx->driver_data;
+ ublk_put_req_ref(ubq, req);
+
+ return ret;
+}
+
static const struct file_operations ublk_ch_fops = {
.owner = THIS_MODULE,
.open = ublk_ch_open,
.release = ublk_ch_release,
.llseek = no_llseek,
+ .read_iter = ublk_ch_read_iter,
+ .write_iter = ublk_ch_write_iter,
.uring_cmd = ublk_ch_uring_cmd,
.mmap = ublk_ch_mmap,
};
@@ -1547,7 +1762,7 @@ static int ublk_add_chdev(struct ublk_device *ub)
dev->parent = ublk_misc.this_device;
dev->devt = MKDEV(MAJOR(ublk_chr_devt), minor);
- dev->class = ublk_chr_class;
+ dev->class = &ublk_chr_class;
dev->release = ublk_cdev_rel;
device_initialize(dev);
@@ -1632,7 +1847,8 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub, struct io_uring_cmd *cmd)
if (ublksrv_pid <= 0)
return -EINVAL;
- wait_for_completion_interruptible(&ub->completion);
+ if (wait_for_completion_interruptible(&ub->completion) != 0)
+ return -EINTR;
schedule_delayed_work(&ub->monitor_work, UBLK_DAEMON_MONITOR_PERIOD);
@@ -1818,10 +2034,12 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd)
*/
ub->dev_info.flags &= UBLK_F_ALL;
- if (!IS_BUILTIN(CONFIG_BLK_DEV_UBLK))
- ub->dev_info.flags |= UBLK_F_URING_CMD_COMP_IN_TASK;
+ ub->dev_info.flags |= UBLK_F_CMD_IOCTL_ENCODE |
+ UBLK_F_URING_CMD_COMP_IN_TASK;
- ub->dev_info.flags |= UBLK_F_CMD_IOCTL_ENCODE;
+ /* GET_DATA isn't needed any more with USER_COPY */
+ if (ub->dev_info.flags & UBLK_F_USER_COPY)
+ ub->dev_info.flags &= ~UBLK_F_NEED_GET_DATA;
/* We are not ready to support zero copy */
ub->dev_info.flags &= ~UBLK_F_SUPPORT_ZERO_COPY;
@@ -1908,8 +2126,8 @@ static int ublk_ctrl_del_dev(struct ublk_device **p_ub)
* - the device number is freed already, we will not find this
* device via ublk_get_device_from_id()
*/
- wait_event_interruptible(ublk_idr_wq, ublk_idr_freed(idx));
-
+ if (wait_event_interruptible(ublk_idr_wq, ublk_idr_freed(idx)))
+ return -EINTR;
return 0;
}
@@ -2106,7 +2324,9 @@ static int ublk_ctrl_end_recovery(struct ublk_device *ub,
pr_devel("%s: Waiting for new ubq_daemons(nr: %d) are ready, dev id %d...\n",
__func__, ub->dev_info.nr_hw_queues, header->dev_id);
/* wait until new ubq_daemon sending all FETCH_REQ */
- wait_for_completion_interruptible(&ub->completion);
+ if (wait_for_completion_interruptible(&ub->completion))
+ return -EINTR;
+
pr_devel("%s: All new ubq_daemons(nr: %d) are ready, dev id %d\n",
__func__, ub->dev_info.nr_hw_queues, header->dev_id);
@@ -2133,6 +2353,21 @@ static int ublk_ctrl_end_recovery(struct ublk_device *ub,
return ret;
}
+static int ublk_ctrl_get_features(struct io_uring_cmd *cmd)
+{
+ const struct ublksrv_ctrl_cmd *header = io_uring_sqe_cmd(cmd->sqe);
+ void __user *argp = (void __user *)(unsigned long)header->addr;
+ u64 features = UBLK_F_ALL & ~UBLK_F_SUPPORT_ZERO_COPY;
+
+ if (header->len != UBLK_FEATURES_LEN || !header->addr)
+ return -EINVAL;
+
+ if (copy_to_user(argp, &features, UBLK_FEATURES_LEN))
+ return -EFAULT;
+
+ return 0;
+}
+
/*
* All control commands are sent via /dev/ublk-control, so we have to check
* the destination device's permission
@@ -2213,6 +2448,7 @@ static int ublk_ctrl_uring_cmd_permission(struct ublk_device *ub,
case UBLK_CMD_GET_DEV_INFO2:
case UBLK_CMD_GET_QUEUE_AFFINITY:
case UBLK_CMD_GET_PARAMS:
+ case (_IOC_NR(UBLK_U_CMD_GET_FEATURES)):
mask = MAY_READ;
break;
case UBLK_CMD_START_DEV:
@@ -2262,6 +2498,11 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
if (ret)
goto out;
+ if (cmd_op == UBLK_U_CMD_GET_FEATURES) {
+ ret = ublk_ctrl_get_features(cmd);
+ goto out;
+ }
+
if (_IOC_NR(cmd_op) != UBLK_CMD_ADD_DEV) {
ret = -ENODEV;
ub = ublk_get_device_from_id(header->dev_id);
@@ -2337,6 +2578,9 @@ static int __init ublk_init(void)
{
int ret;
+ BUILD_BUG_ON((u64)UBLKSRV_IO_BUF_OFFSET +
+ UBLKSRV_IO_BUF_TOTAL_SIZE < UBLKSRV_IO_BUF_OFFSET);
+
init_waitqueue_head(&ublk_idr_wq);
ret = misc_register(&ublk_misc);
@@ -2347,11 +2591,10 @@ static int __init ublk_init(void)
if (ret)
goto unregister_mis;
- ublk_chr_class = class_create("ublk-char");
- if (IS_ERR(ublk_chr_class)) {
- ret = PTR_ERR(ublk_chr_class);
+ ret = class_register(&ublk_chr_class);
+ if (ret)
goto free_chrdev_region;
- }
+
return 0;
free_chrdev_region:
@@ -2369,7 +2612,7 @@ static void __exit ublk_exit(void)
idr_for_each_entry(&ublk_index_idr, ub, id)
ublk_remove(ub);
- class_destroy(ublk_chr_class);
+ class_unregister(&ublk_chr_class);
misc_deregister(&ublk_misc);
idr_destroy(&ublk_index_idr);
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index b47358da92a2..1fe011676d07 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -751,7 +751,6 @@ static int virtblk_probe_zoned_device(struct virtio_device *vdev,
{
u32 v, wg;
u8 model;
- int ret;
virtio_cread(vdev, struct virtio_blk_config,
zoned.model, &model);
@@ -806,6 +805,7 @@ static int virtblk_probe_zoned_device(struct virtio_device *vdev,
vblk->zone_sectors);
return -ENODEV;
}
+ blk_queue_chunk_sectors(q, vblk->zone_sectors);
dev_dbg(&vdev->dev, "zone sectors = %u\n", vblk->zone_sectors);
if (virtio_has_feature(vdev, VIRTIO_BLK_F_DISCARD)) {
@@ -814,26 +814,22 @@ static int virtblk_probe_zoned_device(struct virtio_device *vdev,
blk_queue_max_discard_sectors(q, 0);
}
- ret = blk_revalidate_disk_zones(vblk->disk, NULL);
- if (!ret) {
- virtio_cread(vdev, struct virtio_blk_config,
- zoned.max_append_sectors, &v);
- if (!v) {
- dev_warn(&vdev->dev, "zero max_append_sectors reported\n");
- return -ENODEV;
- }
- if ((v << SECTOR_SHIFT) < wg) {
- dev_err(&vdev->dev,
- "write granularity %u exceeds max_append_sectors %u limit\n",
- wg, v);
- return -ENODEV;
- }
-
- blk_queue_max_zone_append_sectors(q, v);
- dev_dbg(&vdev->dev, "max append sectors = %u\n", v);
+ virtio_cread(vdev, struct virtio_blk_config,
+ zoned.max_append_sectors, &v);
+ if (!v) {
+ dev_warn(&vdev->dev, "zero max_append_sectors reported\n");
+ return -ENODEV;
+ }
+ if ((v << SECTOR_SHIFT) < wg) {
+ dev_err(&vdev->dev,
+ "write granularity %u exceeds max_append_sectors %u limit\n",
+ wg, v);
+ return -ENODEV;
}
+ blk_queue_max_zone_append_sectors(q, v);
+ dev_dbg(&vdev->dev, "max append sectors = %u\n", v);
- return ret;
+ return blk_revalidate_disk_zones(vblk->disk, NULL);
}
#else
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 4807af1d5805..bb66178c432b 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -473,7 +473,7 @@ static void xenvbd_sysfs_delif(struct xenbus_device *dev)
static void xen_vbd_free(struct xen_vbd *vbd)
{
if (vbd->bdev)
- blkdev_put(vbd->bdev, vbd->readonly ? FMODE_READ : FMODE_WRITE);
+ blkdev_put(vbd->bdev, NULL);
vbd->bdev = NULL;
}
@@ -492,7 +492,7 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle,
vbd->pdevice = MKDEV(major, minor);
bdev = blkdev_get_by_dev(vbd->pdevice, vbd->readonly ?
- FMODE_READ : FMODE_WRITE, NULL);
+ BLK_OPEN_READ : BLK_OPEN_WRITE, NULL, NULL);
if (IS_ERR(bdev)) {
pr_warn("xen_vbd_create: device %08x could not be opened\n",
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index c1890c8a9f6e..434fab306777 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -509,7 +509,7 @@ static int blkif_getgeo(struct block_device *bd, struct hd_geometry *hg)
return 0;
}
-static int blkif_ioctl(struct block_device *bdev, fmode_t mode,
+static int blkif_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned command, unsigned long argument)
{
struct blkfront_info *info = bdev->bd_disk->private_data;
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index c1e85f356e4d..11493167b0a8 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -140,16 +140,14 @@ static void get_chipram(void)
return;
}
-static int z2_open(struct block_device *bdev, fmode_t mode)
+static int z2_open(struct gendisk *disk, blk_mode_t mode)
{
- int device;
+ int device = disk->first_minor;
int max_z2_map = (Z2RAM_SIZE / Z2RAM_CHUNKSIZE) * sizeof(z2ram_map[0]);
int max_chip_map = (amiga_chip_size / Z2RAM_CHUNKSIZE) *
sizeof(z2ram_map[0]);
int rc = -ENOMEM;
- device = MINOR(bdev->bd_dev);
-
mutex_lock(&z2ram_mutex);
if (current_device != -1 && current_device != device) {
rc = -EBUSY;
@@ -290,7 +288,7 @@ err_out:
return rc;
}
-static void z2_release(struct gendisk *disk, fmode_t mode)
+static void z2_release(struct gendisk *disk)
{
mutex_lock(&z2ram_mutex);
if (current_device == -1) {
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index f6d90f1ba5cf..06673c6ca255 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -420,7 +420,7 @@ static void reset_bdev(struct zram *zram)
return;
bdev = zram->bdev;
- blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+ blkdev_put(bdev, zram);
/* hope filp_close flush all of IO */
filp_close(zram->backing_dev, NULL);
zram->backing_dev = NULL;
@@ -507,8 +507,8 @@ static ssize_t backing_dev_store(struct device *dev,
goto out;
}
- bdev = blkdev_get_by_dev(inode->i_rdev,
- FMODE_READ | FMODE_WRITE | FMODE_EXCL, zram);
+ bdev = blkdev_get_by_dev(inode->i_rdev, BLK_OPEN_READ | BLK_OPEN_WRITE,
+ zram, NULL);
if (IS_ERR(bdev)) {
err = PTR_ERR(bdev);
bdev = NULL;
@@ -539,7 +539,7 @@ out:
kvfree(bitmap);
if (bdev)
- blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+ blkdev_put(bdev, zram);
if (backing_dev)
filp_close(backing_dev, NULL);
@@ -700,7 +700,7 @@ static ssize_t writeback_store(struct device *dev,
bio_init(&bio, zram->bdev, &bio_vec, 1,
REQ_OP_WRITE | REQ_SYNC);
bio.bi_iter.bi_sector = blk_idx * (PAGE_SIZE >> 9);
- bio_add_page(&bio, page, PAGE_SIZE, 0);
+ __bio_add_page(&bio, page, PAGE_SIZE, 0);
/*
* XXX: A single page IO would be inefficient for write
@@ -1753,7 +1753,7 @@ static ssize_t recompress_store(struct device *dev,
}
}
- if (threshold >= PAGE_SIZE)
+ if (threshold >= huge_class_size)
return -EINVAL;
down_read(&zram->init_lock);
@@ -1870,15 +1870,16 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio)
static void zram_bio_read(struct zram *zram, struct bio *bio)
{
- struct bvec_iter iter;
- struct bio_vec bv;
- unsigned long start_time;
+ unsigned long start_time = bio_start_io_acct(bio);
+ struct bvec_iter iter = bio->bi_iter;
- start_time = bio_start_io_acct(bio);
- bio_for_each_segment(bv, bio, iter) {
+ do {
u32 index = iter.bi_sector >> SECTORS_PER_PAGE_SHIFT;
u32 offset = (iter.bi_sector & (SECTORS_PER_PAGE - 1)) <<
SECTOR_SHIFT;
+ struct bio_vec bv = bio_iter_iovec(bio, iter);
+
+ bv.bv_len = min_t(u32, bv.bv_len, PAGE_SIZE - offset);
if (zram_bvec_read(zram, &bv, index, offset, bio) < 0) {
atomic64_inc(&zram->stats.failed_reads);
@@ -1890,22 +1891,26 @@ static void zram_bio_read(struct zram *zram, struct bio *bio)
zram_slot_lock(zram, index);
zram_accessed(zram, index);
zram_slot_unlock(zram, index);
- }
+
+ bio_advance_iter_single(bio, &iter, bv.bv_len);
+ } while (iter.bi_size);
+
bio_end_io_acct(bio, start_time);
bio_endio(bio);
}
static void zram_bio_write(struct zram *zram, struct bio *bio)
{
- struct bvec_iter iter;
- struct bio_vec bv;
- unsigned long start_time;
+ unsigned long start_time = bio_start_io_acct(bio);
+ struct bvec_iter iter = bio->bi_iter;
- start_time = bio_start_io_acct(bio);
- bio_for_each_segment(bv, bio, iter) {
+ do {
u32 index = iter.bi_sector >> SECTORS_PER_PAGE_SHIFT;
u32 offset = (iter.bi_sector & (SECTORS_PER_PAGE - 1)) <<
SECTOR_SHIFT;
+ struct bio_vec bv = bio_iter_iovec(bio, iter);
+
+ bv.bv_len = min_t(u32, bv.bv_len, PAGE_SIZE - offset);
if (zram_bvec_write(zram, &bv, index, offset, bio) < 0) {
atomic64_inc(&zram->stats.failed_writes);
@@ -1916,7 +1921,10 @@ static void zram_bio_write(struct zram *zram, struct bio *bio)
zram_slot_lock(zram, index);
zram_accessed(zram, index);
zram_slot_unlock(zram, index);
- }
+
+ bio_advance_iter_single(bio, &iter, bv.bv_len);
+ } while (iter.bi_size);
+
bio_end_io_acct(bio, start_time);
bio_endio(bio);
}
@@ -2097,19 +2105,16 @@ static ssize_t reset_store(struct device *dev,
return len;
}
-static int zram_open(struct block_device *bdev, fmode_t mode)
+static int zram_open(struct gendisk *disk, blk_mode_t mode)
{
- int ret = 0;
- struct zram *zram;
+ struct zram *zram = disk->private_data;
- WARN_ON(!mutex_is_locked(&bdev->bd_disk->open_mutex));
+ WARN_ON(!mutex_is_locked(&disk->open_mutex));
- zram = bdev->bd_disk->private_data;
/* zram was claimed to reset so open request fails */
if (zram->claim)
- ret = -EBUSY;
-
- return ret;
+ return -EBUSY;
+ return 0;
}
static const struct block_device_operations zram_devops = {
diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index fd0941fe8608..e7e58a956d15 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -637,7 +637,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
snprintf(config.fwname, sizeof(config.fwname),
"qca/%s", firmware_name);
else if (qca_is_wcn399x(soc_type)) {
- if (ver.soc_id == QCA_WCN3991_SOC_ID) {
+ if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID) {
snprintf(config.fwname, sizeof(config.fwname),
"qca/crnv%02xu.bin", rom_ver);
} else {
diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c
index 2915c82d719d..d978e7cea873 100644
--- a/drivers/bluetooth/btrtl.c
+++ b/drivers/bluetooth/btrtl.c
@@ -1367,14 +1367,30 @@ MODULE_FIRMWARE("rtl_bt/rtl8723cs_vf_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8723cs_vf_config.bin");
MODULE_FIRMWARE("rtl_bt/rtl8723cs_xx_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8723cs_xx_config.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8723d_fw.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8723d_config.bin");
MODULE_FIRMWARE("rtl_bt/rtl8723ds_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8723ds_config.bin");
MODULE_FIRMWARE("rtl_bt/rtl8761a_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8761a_config.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8761b_fw.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8761b_config.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8761bu_fw.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8761bu_config.bin");
MODULE_FIRMWARE("rtl_bt/rtl8821a_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8821a_config.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8821c_fw.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8821c_config.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8821cs_fw.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8821cs_config.bin");
MODULE_FIRMWARE("rtl_bt/rtl8822b_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8822b_config.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8822cs_fw.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8822cs_config.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8822cu_fw.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8822cu_config.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8851bu_fw.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8851bu_config.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852au_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852au_config.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852bs_fw.bin");
@@ -1383,5 +1399,3 @@ MODULE_FIRMWARE("rtl_bt/rtl8852bu_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852bu_config.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852cu_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852cu_config.bin");
-MODULE_FIRMWARE("rtl_bt/rtl8851bu_fw.bin");
-MODULE_FIRMWARE("rtl_bt/rtl8851bu_config.bin");
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 2a8e2bb038f5..764d176e9735 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -613,6 +613,9 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0489, 0xe0d9), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
+ { USB_DEVICE(0x0489, 0xe0f5), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH |
+ BTUSB_VALID_LE_STATES },
{ USB_DEVICE(0x13d3, 0x3568), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
@@ -655,6 +658,8 @@ static const struct usb_device_id blacklist_table[] = {
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0bda, 0x8771), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x6655, 0x8771), .driver_info = BTUSB_REALTEK |
+ BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x7392, 0xc611), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x2b89, 0x8761), .driver_info = BTUSB_REALTEK |
@@ -4099,6 +4104,7 @@ static int btusb_probe(struct usb_interface *intf,
BT_DBG("intf %p id %p", intf, id);
if ((id->driver_info & BTUSB_IFNUM_2) &&
+ (intf->cur_altsetting->desc.bInterfaceNumber != 0) &&
(intf->cur_altsetting->desc.bInterfaceNumber != 2))
return -ENODEV;
diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
index 83bf5d4330c4..874d23089b39 100644
--- a/drivers/bluetooth/hci_bcm.c
+++ b/drivers/bluetooth/hci_bcm.c
@@ -643,7 +643,8 @@ static int bcm_setup(struct hci_uart *hu)
* Allow the bootloader to set a valid address through the
* device tree.
*/
- set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hu->hdev->quirks);
+ if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks))
+ set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hu->hdev->quirks);
if (!bcm_request_irq(bcm))
err = bcm_setup_sleep(hu);
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/intel-ixp4xx-eb.c b/drivers/bus/intel-ixp4xx-eb.c
index f5ba6bee6fd8..320cf307db05 100644
--- a/drivers/bus/intel-ixp4xx-eb.c
+++ b/drivers/bus/intel-ixp4xx-eb.c
@@ -33,7 +33,7 @@
#define IXP4XX_EXP_TIMING_STRIDE 0x04
#define IXP4XX_EXP_CS_EN BIT(31)
#define IXP456_EXP_PAR_EN BIT(30) /* Only on IXP45x and IXP46x */
-#define IXP4XX_EXP_T1_MASK GENMASK(28, 27)
+#define IXP4XX_EXP_T1_MASK GENMASK(29, 28)
#define IXP4XX_EXP_T1_SHIFT 28
#define IXP4XX_EXP_T2_MASK GENMASK(27, 26)
#define IXP4XX_EXP_T2_SHIFT 26
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
index 6c49de37d5e9..4cb23b9e06ea 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));
@@ -2142,6 +2142,8 @@ static int sysc_reset(struct sysc *ddata)
sysc_val = sysc_read_sysconfig(ddata);
sysc_val |= sysc_mask;
sysc_write(ddata, sysc_offset, sysc_val);
+ /* Flush posted write */
+ sysc_val = sysc_read_sysconfig(ddata);
}
if (ddata->cfg.srst_udelay)
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 416f723a2dbb..cc2839805983 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -264,6 +264,7 @@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <linux/nospec.h>
#include <linux/slab.h>
#include <linux/cdrom.h>
#include <linux/sysctl.h>
@@ -978,15 +979,6 @@ static void cdrom_dvd_rw_close_write(struct cdrom_device_info *cdi)
cdi->media_written = 0;
}
-static int cdrom_close_write(struct cdrom_device_info *cdi)
-{
-#if 0
- return cdrom_flush_cache(cdi);
-#else
- return 0;
-#endif
-}
-
/* badly broken, I know. Is due for a fixup anytime. */
static void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype *tracks)
{
@@ -1155,8 +1147,7 @@ clean_up_and_return:
* is in their own interest: device control becomes a lot easier
* this way.
*/
-int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev,
- fmode_t mode)
+int cdrom_open(struct cdrom_device_info *cdi, blk_mode_t mode)
{
int ret;
@@ -1165,7 +1156,7 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev,
/* if this was a O_NONBLOCK open and we should honor the flags,
* do a quick open without drive/disc integrity checks. */
cdi->use_count++;
- if ((mode & FMODE_NDELAY) && (cdi->options & CDO_USE_FFLAGS)) {
+ if ((mode & BLK_OPEN_NDELAY) && (cdi->options & CDO_USE_FFLAGS)) {
ret = cdi->ops->open(cdi, 1);
} else {
ret = open_for_data(cdi);
@@ -1173,7 +1164,7 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev,
goto err;
if (CDROM_CAN(CDC_GENERIC_PACKET))
cdrom_mmc3_profile(cdi);
- if (mode & FMODE_WRITE) {
+ if (mode & BLK_OPEN_WRITE) {
ret = -EROFS;
if (cdrom_open_write(cdi))
goto err_release;
@@ -1182,6 +1173,7 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev,
ret = 0;
cdi->media_written = 0;
}
+ cdi->opened_for_data = true;
}
if (ret)
@@ -1259,10 +1251,9 @@ static int check_for_audio_disc(struct cdrom_device_info *cdi,
return 0;
}
-void cdrom_release(struct cdrom_device_info *cdi, fmode_t mode)
+void cdrom_release(struct cdrom_device_info *cdi)
{
const struct cdrom_device_ops *cdo = cdi->ops;
- int opened_for_data;
cd_dbg(CD_CLOSE, "entering cdrom_release\n");
@@ -1280,20 +1271,12 @@ void cdrom_release(struct cdrom_device_info *cdi, fmode_t mode)
}
}
- opened_for_data = !(cdi->options & CDO_USE_FFLAGS) ||
- !(mode & FMODE_NDELAY);
-
- /*
- * flush cache on last write release
- */
- if (CDROM_CAN(CDC_RAM) && !cdi->use_count && cdi->for_data)
- cdrom_close_write(cdi);
-
cdo->release(cdi);
- if (cdi->use_count == 0) { /* last process that closes dev*/
- if (opened_for_data &&
- cdi->options & CDO_AUTO_EJECT && CDROM_CAN(CDC_OPEN_TRAY))
+
+ if (cdi->use_count == 0 && cdi->opened_for_data) {
+ if (cdi->options & CDO_AUTO_EJECT && CDROM_CAN(CDC_OPEN_TRAY))
cdo->tray_move(cdi, 1);
+ cdi->opened_for_data = false;
}
}
EXPORT_SYMBOL(cdrom_release);
@@ -2329,6 +2312,9 @@ static int cdrom_ioctl_media_changed(struct cdrom_device_info *cdi,
if (arg >= cdi->capacity)
return -EINVAL;
+ /* Prevent arg from speculatively bypassing the length check */
+ barrier_nospec();
+
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
@@ -3337,7 +3323,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
* ATAPI / SCSI specific code now mainly resides in mmc_ioctl().
*/
int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev,
- fmode_t mode, unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
int ret;
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index ceded5772aac..d668b174ace9 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -474,22 +474,22 @@ static const struct cdrom_device_ops gdrom_ops = {
CDC_RESET | CDC_DRIVE_STATUS | CDC_CD_R,
};
-static int gdrom_bdops_open(struct block_device *bdev, fmode_t mode)
+static int gdrom_bdops_open(struct gendisk *disk, blk_mode_t mode)
{
int ret;
- bdev_check_media_change(bdev);
+ disk_check_media_change(disk);
mutex_lock(&gdrom_mutex);
- ret = cdrom_open(gd.cd_info, bdev, mode);
+ ret = cdrom_open(gd.cd_info, mode);
mutex_unlock(&gdrom_mutex);
return ret;
}
-static void gdrom_bdops_release(struct gendisk *disk, fmode_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);
}
@@ -499,13 +499,13 @@ static unsigned int gdrom_bdops_check_events(struct gendisk *disk,
return cdrom_check_events(gd.cd_info, clearing);
}
-static int gdrom_bdops_ioctl(struct block_device *bdev, fmode_t mode,
+static int gdrom_bdops_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned cmd, unsigned long arg)
{
int ret;
mutex_lock(&gdrom_mutex);
- ret = cdrom_ioctl(gd.cd_info, bdev, mode, cmd, arg);
+ ret = cdrom_ioctl(gd.cd_info, bdev, cmd, arg);
mutex_unlock(&gdrom_mutex);
return ret;
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/random.c b/drivers/char/random.c
index 253f2ddb8913..3cb37760dfec 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1546,7 +1546,7 @@ const struct file_operations random_fops = {
.compat_ioctl = compat_ptr_ioctl,
.fasync = random_fasync,
.llseek = noop_llseek,
- .splice_read = generic_file_splice_read,
+ .splice_read = copy_splice_read,
.splice_write = iter_file_splice_write,
};
@@ -1557,7 +1557,7 @@ const struct file_operations urandom_fops = {
.compat_ioctl = compat_ptr_ioctl,
.fasync = random_fasync,
.llseek = noop_llseek,
- .splice_read = generic_file_splice_read,
+ .splice_read = copy_splice_read,
.splice_write = iter_file_splice_write,
};
diff --git a/drivers/char/tpm/st33zp24/i2c.c b/drivers/char/tpm/st33zp24/i2c.c
index 2d28f55ef490..661574bb0acf 100644
--- a/drivers/char/tpm/st33zp24/i2c.c
+++ b/drivers/char/tpm/st33zp24/i2c.c
@@ -160,7 +160,7 @@ static struct i2c_driver st33zp24_i2c_driver = {
.of_match_table = of_match_ptr(of_st33zp24_i2c_match),
.acpi_match_table = ACPI_PTR(st33zp24_i2c_acpi_match),
},
- .probe_new = st33zp24_i2c_probe,
+ .probe = st33zp24_i2c_probe,
.remove = st33zp24_i2c_remove,
.id_table = st33zp24_i2c_id
};
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index cd48033b804a..ea6b4013bc38 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -510,63 +510,6 @@ static int tpm_add_legacy_sysfs(struct tpm_chip *chip)
return 0;
}
-/*
- * Some AMD fTPM versions may cause stutter
- * https://www.amd.com/en/support/kb/faq/pa-410
- *
- * Fixes are available in two series of fTPM firmware:
- * 6.x.y.z series: 6.0.18.6 +
- * 3.x.y.z series: 3.57.y.5 +
- */
-static bool tpm_amd_is_rng_defective(struct tpm_chip *chip)
-{
- u32 val1, val2;
- u64 version;
- int ret;
-
- if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
- return false;
-
- ret = tpm_request_locality(chip);
- if (ret)
- return false;
-
- ret = tpm2_get_tpm_pt(chip, TPM2_PT_MANUFACTURER, &val1, NULL);
- if (ret)
- goto release;
- if (val1 != 0x414D4400U /* AMD */) {
- ret = -ENODEV;
- goto release;
- }
- ret = tpm2_get_tpm_pt(chip, TPM2_PT_FIRMWARE_VERSION_1, &val1, NULL);
- if (ret)
- goto release;
- ret = tpm2_get_tpm_pt(chip, TPM2_PT_FIRMWARE_VERSION_2, &val2, NULL);
-
-release:
- tpm_relinquish_locality(chip);
-
- if (ret)
- return false;
-
- version = ((u64)val1 << 32) | val2;
- if ((version >> 48) == 6) {
- if (version >= 0x0006000000180006ULL)
- return false;
- } else if ((version >> 48) == 3) {
- if (version >= 0x0003005700000005ULL)
- return false;
- } else {
- return false;
- }
-
- dev_warn(&chip->dev,
- "AMD fTPM version 0x%llx causes system stutter; hwrng disabled\n",
- version);
-
- return true;
-}
-
static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng);
@@ -578,10 +521,20 @@ static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
return tpm_get_random(chip, data, max);
}
+static bool tpm_is_hwrng_enabled(struct tpm_chip *chip)
+{
+ if (!IS_ENABLED(CONFIG_HW_RANDOM_TPM))
+ return false;
+ if (tpm_is_firmware_upgrade(chip))
+ return false;
+ if (chip->flags & TPM_CHIP_FLAG_HWRNG_DISABLED)
+ return false;
+ return true;
+}
+
static int tpm_add_hwrng(struct tpm_chip *chip)
{
- if (!IS_ENABLED(CONFIG_HW_RANDOM_TPM) || tpm_is_firmware_upgrade(chip) ||
- tpm_amd_is_rng_defective(chip))
+ if (!tpm_is_hwrng_enabled(chip))
return 0;
snprintf(chip->hwrng_name, sizeof(chip->hwrng_name),
@@ -686,7 +639,7 @@ int tpm_chip_register(struct tpm_chip *chip)
return 0;
out_hwrng:
- if (IS_ENABLED(CONFIG_HW_RANDOM_TPM) && !tpm_is_firmware_upgrade(chip))
+ if (tpm_is_hwrng_enabled(chip))
hwrng_unregister(&chip->hwrng);
out_ppi:
tpm_bios_log_teardown(chip);
@@ -711,8 +664,7 @@ EXPORT_SYMBOL_GPL(tpm_chip_register);
void tpm_chip_unregister(struct tpm_chip *chip)
{
tpm_del_legacy_sysfs(chip);
- if (IS_ENABLED(CONFIG_HW_RANDOM_TPM) && !tpm_is_firmware_upgrade(chip) &&
- !tpm_amd_is_rng_defective(chip))
+ if (tpm_is_hwrng_enabled(chip))
hwrng_unregister(&chip->hwrng);
tpm_bios_log_teardown(chip);
if (chip->flags & TPM_CHIP_FLAG_TPM2 && !tpm_is_firmware_upgrade(chip))
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index d43a0d7b97a8..9eb1a1859012 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -463,6 +463,28 @@ static bool crb_req_canceled(struct tpm_chip *chip, u8 status)
return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE;
}
+static int crb_check_flags(struct tpm_chip *chip)
+{
+ u32 val;
+ int ret;
+
+ ret = crb_request_locality(chip, 0);
+ if (ret)
+ return ret;
+
+ ret = tpm2_get_tpm_pt(chip, TPM2_PT_MANUFACTURER, &val, NULL);
+ if (ret)
+ goto release;
+
+ if (val == 0x414D4400U /* AMD */)
+ chip->flags |= TPM_CHIP_FLAG_HWRNG_DISABLED;
+
+release:
+ crb_relinquish_locality(chip, 0);
+
+ return ret;
+}
+
static const struct tpm_class_ops tpm_crb = {
.flags = TPM_OPS_AUTO_STARTUP,
.status = crb_status,
@@ -563,15 +585,18 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
u32 rsp_size;
int ret;
- INIT_LIST_HEAD(&acpi_resource_list);
- ret = acpi_dev_get_resources(device, &acpi_resource_list,
- crb_check_resource, iores_array);
- if (ret < 0)
- return ret;
- acpi_dev_free_resource_list(&acpi_resource_list);
-
- /* Pluton doesn't appear to define ACPI memory regions */
+ /*
+ * Pluton sometimes does not define ACPI memory regions.
+ * Mapping is then done in crb_map_pluton
+ */
if (priv->sm != ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) {
+ INIT_LIST_HEAD(&acpi_resource_list);
+ ret = acpi_dev_get_resources(device, &acpi_resource_list,
+ crb_check_resource, iores_array);
+ if (ret < 0)
+ return ret;
+ acpi_dev_free_resource_list(&acpi_resource_list);
+
if (resource_type(iores_array) != IORESOURCE_MEM) {
dev_err(dev, FW_BUG "TPM2 ACPI table does not define a memory resource\n");
return -EINVAL;
@@ -797,6 +822,14 @@ static int crb_acpi_add(struct acpi_device *device)
chip->acpi_dev_handle = device->handle;
chip->flags = TPM_CHIP_FLAG_TPM2;
+ rc = tpm_chip_bootstrap(chip);
+ if (rc)
+ goto out;
+
+ rc = crb_check_flags(chip);
+ if (rc)
+ goto out;
+
rc = tpm_chip_register(chip);
out:
diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c
index 8f77154e0550..301a95b3734f 100644
--- a/drivers/char/tpm/tpm_i2c_atmel.c
+++ b/drivers/char/tpm/tpm_i2c_atmel.c
@@ -203,7 +203,7 @@ static SIMPLE_DEV_PM_OPS(i2c_atmel_pm_ops, tpm_pm_suspend, tpm_pm_resume);
static struct i2c_driver i2c_atmel_driver = {
.id_table = i2c_atmel_id,
- .probe_new = i2c_atmel_probe,
+ .probe = i2c_atmel_probe,
.remove = i2c_atmel_remove,
.driver = {
.name = I2C_DRIVER_NAME,
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
index 7cdaff52a96d..81d8a78dc655 100644
--- a/drivers/char/tpm/tpm_i2c_infineon.c
+++ b/drivers/char/tpm/tpm_i2c_infineon.c
@@ -716,7 +716,7 @@ static void tpm_tis_i2c_remove(struct i2c_client *client)
static struct i2c_driver tpm_tis_i2c_driver = {
.id_table = tpm_tis_i2c_table,
- .probe_new = tpm_tis_i2c_probe,
+ .probe = tpm_tis_i2c_probe,
.remove = tpm_tis_i2c_remove,
.driver = {
.name = "tpm_i2c_infineon",
diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c
index a026e98add50..d7be03c41098 100644
--- a/drivers/char/tpm/tpm_i2c_nuvoton.c
+++ b/drivers/char/tpm/tpm_i2c_nuvoton.c
@@ -650,7 +650,7 @@ static SIMPLE_DEV_PM_OPS(i2c_nuvoton_pm_ops, tpm_pm_suspend, tpm_pm_resume);
static struct i2c_driver i2c_nuvoton_driver = {
.id_table = i2c_nuvoton_id,
- .probe_new = i2c_nuvoton_probe,
+ .probe = i2c_nuvoton_probe,
.remove = i2c_nuvoton_remove,
.driver = {
.name = "tpm_i2c_nuvoton",
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 7db3593941ea..7fa3d91042b2 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -89,7 +89,7 @@ static inline void tpm_tis_iowrite32(u32 b, void __iomem *iobase, u32 addr)
tpm_tis_flush(iobase);
}
-static int interrupts = -1;
+static int interrupts;
module_param(interrupts, int, 0444);
MODULE_PARM_DESC(interrupts, "Enable interrupts");
@@ -116,6 +116,22 @@ static int tpm_tis_disable_irq(const struct dmi_system_id *d)
static const struct dmi_system_id tpm_tis_dmi_table[] = {
{
.callback = tpm_tis_disable_irq,
+ .ident = "Framework Laptop (12th Gen Intel Core)",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Laptop (12th Gen Intel Core)"),
+ },
+ },
+ {
+ .callback = tpm_tis_disable_irq,
+ .ident = "Framework Laptop (13th Gen Intel Core)",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Laptop (13th Gen Intel Core)"),
+ },
+ },
+ {
+ .callback = tpm_tis_disable_irq,
.ident = "ThinkPad T490s",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
@@ -140,9 +156,34 @@ static const struct dmi_system_id tpm_tis_dmi_table[] = {
},
{
.callback = tpm_tis_disable_irq,
+ .ident = "ThinkPad L590",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L590"),
+ },
+ },
+ {
+ .callback = tpm_tis_disable_irq,
+ .ident = "ThinkStation P620",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkStation P620"),
+ },
+ },
+ {
+ .callback = tpm_tis_disable_irq,
+ .ident = "TUXEDO InfinityBook S 15/17 Gen7",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TUXEDO InfinityBook S 15/17 Gen7"),
+ },
+ },
+ {
+ .callback = tpm_tis_disable_irq,
.ident = "UPX-TGL",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "UPX-TGL01"),
},
},
{}
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index 558144fa707a..b95963095729 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -24,9 +24,12 @@
#include <linux/wait.h>
#include <linux/acpi.h>
#include <linux/freezer.h>
+#include <linux/dmi.h>
#include "tpm.h"
#include "tpm_tis_core.h"
+#define TPM_TIS_MAX_UNHANDLED_IRQS 1000
+
static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value);
static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask,
@@ -363,8 +366,13 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
goto out;
}
- size += recv_data(chip, &buf[TPM_HEADER_SIZE],
- expected - TPM_HEADER_SIZE);
+ rc = recv_data(chip, &buf[TPM_HEADER_SIZE],
+ expected - TPM_HEADER_SIZE);
+ if (rc < 0) {
+ size = rc;
+ goto out;
+ }
+ size += rc;
if (size < expected) {
dev_err(&chip->dev, "Unable to read remainder of result\n");
size = -ETIME;
@@ -468,25 +476,29 @@ out_err:
return rc;
}
-static void disable_interrupts(struct tpm_chip *chip)
+static void __tpm_tis_disable_interrupts(struct tpm_chip *chip)
+{
+ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+ u32 int_mask = 0;
+
+ tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &int_mask);
+ int_mask &= ~TPM_GLOBAL_INT_ENABLE;
+ tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), int_mask);
+
+ chip->flags &= ~TPM_CHIP_FLAG_IRQ;
+}
+
+static void tpm_tis_disable_interrupts(struct tpm_chip *chip)
{
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
- u32 intmask;
- int rc;
if (priv->irq == 0)
return;
- rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
- if (rc < 0)
- intmask = 0;
-
- intmask &= ~TPM_GLOBAL_INT_ENABLE;
- rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
+ __tpm_tis_disable_interrupts(chip);
devm_free_irq(chip->dev.parent, priv->irq, chip);
priv->irq = 0;
- chip->flags &= ~TPM_CHIP_FLAG_IRQ;
}
/*
@@ -552,7 +564,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
if (!test_bit(TPM_TIS_IRQ_TESTED, &priv->flags))
tpm_msleep(1);
if (!test_bit(TPM_TIS_IRQ_TESTED, &priv->flags))
- disable_interrupts(chip);
+ tpm_tis_disable_interrupts(chip);
set_bit(TPM_TIS_IRQ_TESTED, &priv->flags);
return rc;
}
@@ -752,6 +764,57 @@ static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status)
return status == TPM_STS_COMMAND_READY;
}
+static irqreturn_t tpm_tis_revert_interrupts(struct tpm_chip *chip)
+{
+ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+ const char *product;
+ const char *vendor;
+
+ dev_warn(&chip->dev, FW_BUG
+ "TPM interrupt storm detected, polling instead\n");
+
+ vendor = dmi_get_system_info(DMI_SYS_VENDOR);
+ product = dmi_get_system_info(DMI_PRODUCT_VERSION);
+
+ if (vendor && product) {
+ dev_info(&chip->dev,
+ "Consider adding the following entry to tpm_tis_dmi_table:\n");
+ dev_info(&chip->dev, "\tDMI_SYS_VENDOR: %s\n", vendor);
+ dev_info(&chip->dev, "\tDMI_PRODUCT_VERSION: %s\n", product);
+ }
+
+ if (tpm_tis_request_locality(chip, 0) != 0)
+ return IRQ_NONE;
+
+ __tpm_tis_disable_interrupts(chip);
+ tpm_tis_relinquish_locality(chip, 0);
+
+ schedule_work(&priv->free_irq_work);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t tpm_tis_update_unhandled_irqs(struct tpm_chip *chip)
+{
+ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+ irqreturn_t irqret = IRQ_HANDLED;
+
+ if (!(chip->flags & TPM_CHIP_FLAG_IRQ))
+ return IRQ_HANDLED;
+
+ if (time_after(jiffies, priv->last_unhandled_irq + HZ/10))
+ priv->unhandled_irqs = 1;
+ else
+ priv->unhandled_irqs++;
+
+ priv->last_unhandled_irq = jiffies;
+
+ if (priv->unhandled_irqs > TPM_TIS_MAX_UNHANDLED_IRQS)
+ irqret = tpm_tis_revert_interrupts(chip);
+
+ return irqret;
+}
+
static irqreturn_t tis_int_handler(int dummy, void *dev_id)
{
struct tpm_chip *chip = dev_id;
@@ -761,10 +824,10 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt);
if (rc < 0)
- return IRQ_NONE;
+ goto err;
if (interrupt == 0)
- return IRQ_NONE;
+ goto err;
set_bit(TPM_TIS_IRQ_TESTED, &priv->flags);
if (interrupt & TPM_INTF_DATA_AVAIL_INT)
@@ -780,10 +843,13 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), interrupt);
tpm_tis_relinquish_locality(chip, 0);
if (rc < 0)
- return IRQ_NONE;
+ goto err;
tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt);
return IRQ_HANDLED;
+
+err:
+ return tpm_tis_update_unhandled_irqs(chip);
}
static void tpm_tis_gen_interrupt(struct tpm_chip *chip)
@@ -804,6 +870,15 @@ static void tpm_tis_gen_interrupt(struct tpm_chip *chip)
chip->flags &= ~TPM_CHIP_FLAG_IRQ;
}
+static void tpm_tis_free_irq_func(struct work_struct *work)
+{
+ struct tpm_tis_data *priv = container_of(work, typeof(*priv), free_irq_work);
+ struct tpm_chip *chip = priv->chip;
+
+ devm_free_irq(chip->dev.parent, priv->irq, chip);
+ priv->irq = 0;
+}
+
/* Register the IRQ and issue a command that will cause an interrupt. If an
* irq is seen then leave the chip setup for IRQ operation, otherwise reverse
* everything and leave in polling mode. Returns 0 on success.
@@ -816,6 +891,7 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
int rc;
u32 int_status;
+ INIT_WORK(&priv->free_irq_work, tpm_tis_free_irq_func);
rc = devm_request_threaded_irq(chip->dev.parent, irq, NULL,
tis_int_handler, IRQF_ONESHOT | flags,
@@ -918,6 +994,7 @@ void tpm_tis_remove(struct tpm_chip *chip)
interrupt = 0;
tpm_tis_write32(priv, reg, ~TPM_GLOBAL_INT_ENABLE & interrupt);
+ flush_work(&priv->free_irq_work);
tpm_tis_clkrun_enable(chip, false);
@@ -1021,6 +1098,7 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
chip->timeout_b = msecs_to_jiffies(TIS_TIMEOUT_B_MAX);
chip->timeout_c = msecs_to_jiffies(TIS_TIMEOUT_C_MAX);
chip->timeout_d = msecs_to_jiffies(TIS_TIMEOUT_D_MAX);
+ priv->chip = chip;
priv->timeout_min = TPM_TIMEOUT_USECS_MIN;
priv->timeout_max = TPM_TIMEOUT_USECS_MAX;
priv->phy_ops = phy_ops;
@@ -1179,7 +1257,7 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
rc = tpm_tis_request_locality(chip, 0);
if (rc < 0)
goto out_err;
- disable_interrupts(chip);
+ tpm_tis_disable_interrupts(chip);
tpm_tis_relinquish_locality(chip, 0);
}
}
diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
index 610bfadb6acf..b1a169d7d1ca 100644
--- a/drivers/char/tpm/tpm_tis_core.h
+++ b/drivers/char/tpm/tpm_tis_core.h
@@ -91,11 +91,15 @@ enum tpm_tis_flags {
};
struct tpm_tis_data {
+ struct tpm_chip *chip;
u16 manufacturer_id;
struct mutex locality_count_mutex;
unsigned int locality_count;
int locality;
int irq;
+ struct work_struct free_irq_work;
+ unsigned long last_unhandled_irq;
+ unsigned int unhandled_irqs;
unsigned int int_mask;
unsigned long flags;
void __iomem *ilb_base_addr;
diff --git a/drivers/char/tpm/tpm_tis_i2c.c b/drivers/char/tpm/tpm_tis_i2c.c
index c8c34adc14c0..a897402cc36a 100644
--- a/drivers/char/tpm/tpm_tis_i2c.c
+++ b/drivers/char/tpm/tpm_tis_i2c.c
@@ -189,21 +189,28 @@ static int tpm_tis_i2c_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
int ret;
for (i = 0; i < TPM_RETRY; i++) {
- /* write register */
- msg.len = sizeof(reg);
- msg.buf = &reg;
- msg.flags = 0;
- ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
- if (ret < 0)
- return ret;
-
- /* read data */
- msg.buf = result;
- msg.len = len;
- msg.flags = I2C_M_RD;
- ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
- if (ret < 0)
- return ret;
+ u16 read = 0;
+
+ while (read < len) {
+ /* write register */
+ msg.len = sizeof(reg);
+ msg.buf = &reg;
+ msg.flags = 0;
+ ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
+ if (ret < 0)
+ return ret;
+
+ /* read data */
+ msg.buf = result + read;
+ msg.len = len - read;
+ msg.flags = I2C_M_RD;
+ if (msg.len > I2C_SMBUS_BLOCK_MAX)
+ msg.len = I2C_SMBUS_BLOCK_MAX;
+ ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
+ if (ret < 0)
+ return ret;
+ read += msg.len;
+ }
ret = tpm_tis_i2c_sanity_check_read(reg, len, result);
if (ret == 0)
@@ -223,19 +230,27 @@ static int tpm_tis_i2c_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
struct i2c_msg msg = { .addr = phy->i2c_client->addr };
u8 reg = tpm_tis_i2c_address_to_register(addr);
int ret;
+ u16 wrote = 0;
if (len > TPM_BUFSIZE - 1)
return -EIO;
- /* write register and data in one go */
phy->io_buf[0] = reg;
- memcpy(phy->io_buf + sizeof(reg), value, len);
-
- msg.len = sizeof(reg) + len;
msg.buf = phy->io_buf;
- ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
- if (ret < 0)
- return ret;
+ while (wrote < len) {
+ /* write register and data in one go */
+ msg.len = sizeof(reg) + len - wrote;
+ if (msg.len > I2C_SMBUS_BLOCK_MAX)
+ msg.len = I2C_SMBUS_BLOCK_MAX;
+
+ memcpy(phy->io_buf + sizeof(reg), value + wrote,
+ msg.len - sizeof(reg));
+
+ ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
+ if (ret < 0)
+ return ret;
+ wrote += msg.len - sizeof(reg);
+ }
return 0;
}
@@ -379,7 +394,7 @@ static struct i2c_driver tpm_tis_i2c_driver = {
.pm = &tpm_tis_pm,
.of_match_table = of_match_ptr(of_tis_i2c_match),
},
- .probe_new = tpm_tis_i2c_probe,
+ .probe = tpm_tis_i2c_probe,
.remove = tpm_tis_i2c_remove,
.id_table = tpm_tis_i2c_id,
};
diff --git a/drivers/char/tpm/tpm_tis_i2c_cr50.c b/drivers/char/tpm/tpm_tis_i2c_cr50.c
index 376ae18a04eb..e70abd69e1ae 100644
--- a/drivers/char/tpm/tpm_tis_i2c_cr50.c
+++ b/drivers/char/tpm/tpm_tis_i2c_cr50.c
@@ -779,7 +779,7 @@ static void tpm_cr50_i2c_remove(struct i2c_client *client)
static SIMPLE_DEV_PM_OPS(cr50_i2c_pm, tpm_pm_suspend, tpm_pm_resume);
static struct i2c_driver cr50_i2c_driver = {
- .probe_new = tpm_cr50_i2c_probe,
+ .probe = tpm_cr50_i2c_probe,
.remove = tpm_cr50_i2c_remove,
.driver = {
.name = "cr50_i2c",
diff --git a/drivers/char/tpm/tpm_tis_spi_main.c b/drivers/char/tpm/tpm_tis_spi_main.c
index 1f5207974a17..9bfaba092a06 100644
--- a/drivers/char/tpm/tpm_tis_spi_main.c
+++ b/drivers/char/tpm/tpm_tis_spi_main.c
@@ -136,6 +136,14 @@ int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
}
exit:
+ if (ret < 0) {
+ /* Deactivate chip select */
+ memset(&spi_xfer, 0, sizeof(spi_xfer));
+ spi_message_init(&m);
+ spi_message_add_tail(&spi_xfer, &m);
+ spi_sync_locked(phy->spi_device, &m);
+ }
+
spi_bus_unlock(phy->spi_device->master);
return ret;
}
diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c
index 5c865987ba5c..30e953988cab 100644
--- a/drivers/char/tpm/tpm_vtpm_proxy.c
+++ b/drivers/char/tpm/tpm_vtpm_proxy.c
@@ -683,37 +683,21 @@ static struct miscdevice vtpmx_miscdev = {
.fops = &vtpmx_fops,
};
-static int vtpmx_init(void)
-{
- return misc_register(&vtpmx_miscdev);
-}
-
-static void vtpmx_cleanup(void)
-{
- misc_deregister(&vtpmx_miscdev);
-}
-
static int __init vtpm_module_init(void)
{
int rc;
- rc = vtpmx_init();
- if (rc) {
- pr_err("couldn't create vtpmx device\n");
- return rc;
- }
-
workqueue = create_workqueue("tpm-vtpm");
if (!workqueue) {
pr_err("couldn't create workqueue\n");
- rc = -ENOMEM;
- goto err_vtpmx_cleanup;
+ return -ENOMEM;
}
- return 0;
-
-err_vtpmx_cleanup:
- vtpmx_cleanup();
+ rc = misc_register(&vtpmx_miscdev);
+ if (rc) {
+ pr_err("couldn't create vtpmx device\n");
+ destroy_workqueue(workqueue);
+ }
return rc;
}
@@ -721,7 +705,7 @@ err_vtpmx_cleanup:
static void __exit vtpm_module_exit(void)
{
destroy_workqueue(workqueue);
- vtpmx_cleanup();
+ misc_deregister(&vtpmx_miscdev);
}
module_init(vtpm_module_init);
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 016814e15536..6b3b424addab 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -82,7 +82,7 @@ config COMMON_CLK_MAX9485
config COMMON_CLK_RK808
tristate "Clock driver for RK805/RK808/RK809/RK817/RK818"
- depends on MFD_RK808
+ depends on MFD_RK8XX
help
This driver supports RK805, RK809 and RK817, RK808 and RK818 crystal oscillator clock.
These multi-function devices have two fixed-rate oscillators, clocked at 32KHz each.
@@ -444,6 +444,7 @@ config COMMON_CLK_BD718XX
config COMMON_CLK_FIXED_MMIO
bool "Clock driver for Memory Mapped Fixed values"
depends on COMMON_CLK && OF
+ depends on HAS_IOMEM
help
Support for Memory Mapped IO Fixed clocks
@@ -478,6 +479,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-devres.c b/drivers/clk/clk-devres.c
index 4fb4fd4b06bd..737aa70e2cb3 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -205,18 +205,19 @@ EXPORT_SYMBOL(devm_clk_put);
struct clk *devm_get_clk_from_child(struct device *dev,
struct device_node *np, const char *con_id)
{
- struct clk **ptr, *clk;
+ struct devm_clk_state *state;
+ struct clk *clk;
- ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
- if (!ptr)
+ state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL);
+ if (!state)
return ERR_PTR(-ENOMEM);
clk = of_clk_get_by_name(np, con_id);
if (!IS_ERR(clk)) {
- *ptr = clk;
- devres_add(dev, ptr);
+ state->clk = clk;
+ devres_add(dev, state);
} else {
- devres_free(ptr);
+ devres_free(state);
}
return clk;
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-rk808.c b/drivers/clk/clk-rk808.c
index 32f833d732ed..f7412b137e5e 100644
--- a/drivers/clk/clk-rk808.c
+++ b/drivers/clk/clk-rk808.c
@@ -12,10 +12,9 @@
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/mfd/rk808.h>
-#include <linux/i2c.h>
struct rk808_clkout {
- struct rk808 *rk808;
+ struct regmap *regmap;
struct clk_hw clkout1_hw;
struct clk_hw clkout2_hw;
};
@@ -31,9 +30,8 @@ static int rk808_clkout2_enable(struct clk_hw *hw, bool enable)
struct rk808_clkout *rk808_clkout = container_of(hw,
struct rk808_clkout,
clkout2_hw);
- struct rk808 *rk808 = rk808_clkout->rk808;
- return regmap_update_bits(rk808->regmap, RK808_CLK32OUT_REG,
+ return regmap_update_bits(rk808_clkout->regmap, RK808_CLK32OUT_REG,
CLK32KOUT2_EN, enable ? CLK32KOUT2_EN : 0);
}
@@ -52,10 +50,9 @@ static int rk808_clkout2_is_prepared(struct clk_hw *hw)
struct rk808_clkout *rk808_clkout = container_of(hw,
struct rk808_clkout,
clkout2_hw);
- struct rk808 *rk808 = rk808_clkout->rk808;
uint32_t val;
- int ret = regmap_read(rk808->regmap, RK808_CLK32OUT_REG, &val);
+ int ret = regmap_read(rk808_clkout->regmap, RK808_CLK32OUT_REG, &val);
if (ret < 0)
return ret;
@@ -93,9 +90,8 @@ static int rk817_clkout2_enable(struct clk_hw *hw, bool enable)
struct rk808_clkout *rk808_clkout = container_of(hw,
struct rk808_clkout,
clkout2_hw);
- struct rk808 *rk808 = rk808_clkout->rk808;
- return regmap_update_bits(rk808->regmap, RK817_SYS_CFG(1),
+ return regmap_update_bits(rk808_clkout->regmap, RK817_SYS_CFG(1),
RK817_CLK32KOUT2_EN,
enable ? RK817_CLK32KOUT2_EN : 0);
}
@@ -115,10 +111,9 @@ static int rk817_clkout2_is_prepared(struct clk_hw *hw)
struct rk808_clkout *rk808_clkout = container_of(hw,
struct rk808_clkout,
clkout2_hw);
- struct rk808 *rk808 = rk808_clkout->rk808;
unsigned int val;
- int ret = regmap_read(rk808->regmap, RK817_SYS_CFG(1), &val);
+ int ret = regmap_read(rk808_clkout->regmap, RK817_SYS_CFG(1), &val);
if (ret < 0)
return 0;
@@ -153,18 +148,21 @@ static const struct clk_ops *rkpmic_get_ops(long variant)
static int rk808_clkout_probe(struct platform_device *pdev)
{
struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
- struct i2c_client *client = rk808->i2c;
- struct device_node *node = client->dev.of_node;
+ struct device *dev = &pdev->dev;
struct clk_init_data init = {};
struct rk808_clkout *rk808_clkout;
int ret;
- rk808_clkout = devm_kzalloc(&client->dev,
+ dev->of_node = pdev->dev.parent->of_node;
+
+ rk808_clkout = devm_kzalloc(dev,
sizeof(*rk808_clkout), GFP_KERNEL);
if (!rk808_clkout)
return -ENOMEM;
- rk808_clkout->rk808 = rk808;
+ rk808_clkout->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!rk808_clkout->regmap)
+ return -ENODEV;
init.parent_names = NULL;
init.num_parents = 0;
@@ -173,10 +171,10 @@ static int rk808_clkout_probe(struct platform_device *pdev)
rk808_clkout->clkout1_hw.init = &init;
/* optional override of the clockname */
- of_property_read_string_index(node, "clock-output-names",
+ of_property_read_string_index(dev->of_node, "clock-output-names",
0, &init.name);
- ret = devm_clk_hw_register(&client->dev, &rk808_clkout->clkout1_hw);
+ ret = devm_clk_hw_register(dev, &rk808_clkout->clkout1_hw);
if (ret)
return ret;
@@ -185,10 +183,10 @@ static int rk808_clkout_probe(struct platform_device *pdev)
rk808_clkout->clkout2_hw.init = &init;
/* optional override of the clockname */
- of_property_read_string_index(node, "clock-output-names",
+ of_property_read_string_index(dev->of_node, "clock-output-names",
1, &init.name);
- ret = devm_clk_hw_register(&client->dev, &rk808_clkout->clkout2_hw);
+ ret = devm_clk_hw_register(dev, &rk808_clkout->clkout2_hw);
if (ret)
return ret;
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-imx1.c b/drivers/clk/imx/clk-imx1.c
index 22fc7491ba00..f6ea7e5052d5 100644
--- a/drivers/clk/imx/clk-imx1.c
+++ b/drivers/clk/imx/clk-imx1.c
@@ -10,7 +10,6 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <dt-bindings/clock/imx1-clock.h>
-#include <soc/imx/timer.h>
#include <asm/irq.h>
#include "clk.h"
diff --git a/drivers/clk/imx/clk-imx27.c b/drivers/clk/imx/clk-imx27.c
index 5d177125728d..99618ded0939 100644
--- a/drivers/clk/imx/clk-imx27.c
+++ b/drivers/clk/imx/clk-imx27.c
@@ -8,7 +8,6 @@
#include <linux/of_address.h>
#include <dt-bindings/clock/imx27-clock.h>
#include <soc/imx/revision.h>
-#include <soc/imx/timer.h>
#include <asm/irq.h>
#include "clk.h"
diff --git a/drivers/clk/imx/clk-imx31.c b/drivers/clk/imx/clk-imx31.c
index c44e18c6f63f..4c8d9ff0b2ad 100644
--- a/drivers/clk/imx/clk-imx31.c
+++ b/drivers/clk/imx/clk-imx31.c
@@ -11,7 +11,6 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <soc/imx/revision.h>
-#include <soc/imx/timer.h>
#include <asm/irq.h>
#include "clk.h"
diff --git a/drivers/clk/imx/clk-imx35.c b/drivers/clk/imx/clk-imx35.c
index 7dcbaea3fea3..3b6fdb4e0be7 100644
--- a/drivers/clk/imx/clk-imx35.c
+++ b/drivers/clk/imx/clk-imx35.c
@@ -10,7 +10,6 @@
#include <linux/of.h>
#include <linux/err.h>
#include <soc/imx/revision.h>
-#include <soc/imx/timer.h>
#include <asm/irq.h>
#include "clk.h"
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..44f435103c65 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(anatop_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..935d9a2d8c2b 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,16 +141,20 @@ 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",
data[i].name);
}
- return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
- hw_data);
+ if (num_clks == 1)
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
+ hw_data->hws[0]);
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, hw_data);
}
#define TI_SYSCON_CLK_GATE(_name, _offset, _bit_idx) \
@@ -166,6 +194,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 +212,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..e31f94387d87 100644
--- a/drivers/clk/mediatek/clk-mt8183.c
+++ b/drivers/clk/mediatek/clk-mt8183.c
@@ -328,6 +328,14 @@ static const char * const atb_parents[] = {
"syspll_d5"
};
+static const char * const sspm_parents[] = {
+ "clk26m",
+ "univpll_d2_d4",
+ "syspll_d2_d2",
+ "univpll_d2_d2",
+ "syspll_d3"
+};
+
static const char * const dpi0_parents[] = {
"clk26m",
"tvdpll_d2",
@@ -451,7 +459,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 +495,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),
@@ -506,6 +515,9 @@ static const struct mtk_mux top_muxes[] = {
/* CLK_CFG_6 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_ATB, "atb_sel",
atb_parents, 0xa0, 0xa4, 0xa8, 0, 2, 7, 0x004, 24),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_SSPM, "sspm_sel",
+ sspm_parents, 0xa0, 0xa4, 0xa8, 8, 3, 15, 0x004, 25,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_DPI0, "dpi0_sel",
dpi0_parents, 0xa0, 0xa4, 0xa8, 16, 4, 23, 0x004, 26),
MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SCAM, "scam_sel",
@@ -518,7 +530,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),
@@ -671,10 +684,18 @@ static const struct mtk_gate_regs infra3_cg_regs = {
GATE_MTK(_id, _name, _parent, &infra2_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr)
+#define GATE_INFRA2_FLAGS(_id, _name, _parent, _shift, _flag) \
+ GATE_MTK_FLAGS(_id, _name, _parent, &infra2_cg_regs, \
+ _shift, &mtk_clk_gate_ops_setclr, _flag)
+
#define GATE_INFRA3(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &infra3_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr)
+#define GATE_INFRA3_FLAGS(_id, _name, _parent, _shift, _flag) \
+ GATE_MTK_FLAGS(_id, _name, _parent, &infra3_cg_regs, \
+ _shift, &mtk_clk_gate_ops_setclr, _flag)
+
static const struct mtk_gate infra_clks[] = {
/* INFRA0 */
GATE_INFRA0(CLK_INFRA_PMIC_TMR, "infra_pmic_tmr", "axi_sel", 0),
@@ -746,7 +767,11 @@ static const struct mtk_gate infra_clks[] = {
GATE_INFRA2(CLK_INFRA_UNIPRO_TICK, "infra_unipro_tick", "fufs_sel", 12),
GATE_INFRA2(CLK_INFRA_UFS_MP_SAP_BCLK, "infra_ufs_mp_sap_bck", "fufs_sel", 13),
GATE_INFRA2(CLK_INFRA_MD32_BCLK, "infra_md32_bclk", "axi_sel", 14),
+ /* infra_sspm is main clock in co-processor, should not be closed in Linux. */
+ GATE_INFRA2_FLAGS(CLK_INFRA_SSPM, "infra_sspm", "sspm_sel", 15, CLK_IS_CRITICAL),
GATE_INFRA2(CLK_INFRA_UNIPRO_MBIST, "infra_unipro_mbist", "axi_sel", 16),
+ /* infra_sspm_bus_hclk is main clock in co-processor, should not be closed in Linux. */
+ GATE_INFRA2_FLAGS(CLK_INFRA_SSPM_BUS_HCLK, "infra_sspm_bus_hclk", "axi_sel", 17, CLK_IS_CRITICAL),
GATE_INFRA2(CLK_INFRA_I2C5, "infra_i2c5", "i2c_sel", 18),
GATE_INFRA2(CLK_INFRA_I2C5_ARBITER, "infra_i2c5_arbiter", "i2c_sel", 19),
GATE_INFRA2(CLK_INFRA_I2C5_IMM, "infra_i2c5_imm", "i2c_sel", 20),
@@ -764,6 +789,10 @@ static const struct mtk_gate infra_clks[] = {
GATE_INFRA3(CLK_INFRA_MSDC0_SELF, "infra_msdc0_self", "msdc50_0_sel", 0),
GATE_INFRA3(CLK_INFRA_MSDC1_SELF, "infra_msdc1_self", "msdc50_0_sel", 1),
GATE_INFRA3(CLK_INFRA_MSDC2_SELF, "infra_msdc2_self", "msdc50_0_sel", 2),
+ /* infra_sspm_26m_self is main clock in co-processor, should not be closed in Linux. */
+ GATE_INFRA3_FLAGS(CLK_INFRA_SSPM_26M_SELF, "infra_sspm_26m_self", "f_f26m_ck", 3, CLK_IS_CRITICAL),
+ /* infra_sspm_32k_self is main clock in co-processor, should not be closed in Linux. */
+ GATE_INFRA3_FLAGS(CLK_INFRA_SSPM_32K_SELF, "infra_sspm_32k_self", "f_f26m_ck", 4, CLK_IS_CRITICAL),
GATE_INFRA3(CLK_INFRA_UFS_AXI, "infra_ufs_axi", "axi_sel", 5),
GATE_INFRA3(CLK_INFRA_I2C6, "infra_i2c6", "i2c_sel", 6),
GATE_INFRA3(CLK_INFRA_AP_MSDC0, "infra_ap_msdc0", "msdc50_hclk_sel", 7),
@@ -872,7 +901,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..6fa7639a3050 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)) {
+ udelay(10);
+ meson_parm_write(clk->map, &pll->current_en, 1);
+ udelay(40);
+ }
+
+ 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/Kconfig b/drivers/clocksource/Kconfig
index 526382dc7482..c4d671a5a13d 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -612,6 +612,15 @@ config TIMER_IMX_SYS_CTR
Enable this option to use i.MX system counter timer as a
clockevent.
+config CLKSRC_LOONGSON1_PWM
+ bool "Clocksource using Loongson1 PWM"
+ depends on MACH_LOONGSON32 || COMPILE_TEST
+ select MIPS_EXTERNAL_TIMER
+ select TIMER_OF
+ help
+ Enable this option to use Loongson1 PWM timer as clocksource
+ instead of the performance counter.
+
config CLKSRC_ST_LPC
bool "Low power clocksource found in the LPC" if COMPILE_TEST
select TIMER_OF if OF
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index f12d3987a960..5d93c9e3fc55 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -89,3 +89,4 @@ obj-$(CONFIG_MICROCHIP_PIT64B) += timer-microchip-pit64b.o
obj-$(CONFIG_MSC313E_TIMER) += timer-msc313e.o
obj-$(CONFIG_GOLDFISH_TIMER) += timer-goldfish.o
obj-$(CONFIG_GXP_TIMER) += timer-gxp.o
+obj-$(CONFIG_CLKSRC_LOONGSON1_PWM) += timer-loongson1-pwm.o
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index e09d4427f604..e733a2a1927a 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -191,22 +191,40 @@ u32 arch_timer_reg_read(int access, enum arch_timer_reg reg,
return val;
}
-static notrace u64 arch_counter_get_cntpct_stable(void)
+static noinstr u64 raw_counter_get_cntpct_stable(void)
{
return __arch_counter_get_cntpct_stable();
}
-static notrace u64 arch_counter_get_cntpct(void)
+static notrace u64 arch_counter_get_cntpct_stable(void)
+{
+ u64 val;
+ preempt_disable_notrace();
+ val = __arch_counter_get_cntpct_stable();
+ preempt_enable_notrace();
+ return val;
+}
+
+static noinstr u64 arch_counter_get_cntpct(void)
{
return __arch_counter_get_cntpct();
}
-static notrace u64 arch_counter_get_cntvct_stable(void)
+static noinstr u64 raw_counter_get_cntvct_stable(void)
{
return __arch_counter_get_cntvct_stable();
}
-static notrace u64 arch_counter_get_cntvct(void)
+static notrace u64 arch_counter_get_cntvct_stable(void)
+{
+ u64 val;
+ preempt_disable_notrace();
+ val = __arch_counter_get_cntvct_stable();
+ preempt_enable_notrace();
+ return val;
+}
+
+static noinstr u64 arch_counter_get_cntvct(void)
{
return __arch_counter_get_cntvct();
}
@@ -753,14 +771,14 @@ static int arch_timer_set_next_event_phys(unsigned long evt,
return 0;
}
-static u64 arch_counter_get_cnt_mem(struct arch_timer *t, int offset_lo)
+static noinstr u64 arch_counter_get_cnt_mem(struct arch_timer *t, int offset_lo)
{
u32 cnt_lo, cnt_hi, tmp_hi;
do {
- cnt_hi = readl_relaxed(t->base + offset_lo + 4);
- cnt_lo = readl_relaxed(t->base + offset_lo);
- tmp_hi = readl_relaxed(t->base + offset_lo + 4);
+ cnt_hi = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo + 4));
+ cnt_lo = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo));
+ tmp_hi = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo + 4));
} while (cnt_hi != tmp_hi);
return ((u64) cnt_hi << 32) | cnt_lo;
@@ -1060,7 +1078,7 @@ bool arch_timer_evtstrm_available(void)
return cpumask_test_cpu(raw_smp_processor_id(), &evtstrm_available);
}
-static u64 arch_counter_get_cntvct_mem(void)
+static noinstr u64 arch_counter_get_cntvct_mem(void)
{
return arch_counter_get_cnt_mem(arch_timer_mem, CNTVCT_LO);
}
@@ -1074,6 +1092,7 @@ struct arch_timer_kvm_info *arch_timer_get_kvm_info(void)
static void __init arch_counter_register(unsigned type)
{
+ u64 (*scr)(void);
u64 start_count;
int width;
@@ -1083,21 +1102,28 @@ static void __init arch_counter_register(unsigned type)
if ((IS_ENABLED(CONFIG_ARM64) && !is_hyp_mode_available()) ||
arch_timer_uses_ppi == ARCH_TIMER_VIRT_PPI) {
- if (arch_timer_counter_has_wa())
+ if (arch_timer_counter_has_wa()) {
rd = arch_counter_get_cntvct_stable;
- else
+ scr = raw_counter_get_cntvct_stable;
+ } else {
rd = arch_counter_get_cntvct;
+ scr = arch_counter_get_cntvct;
+ }
} else {
- if (arch_timer_counter_has_wa())
+ if (arch_timer_counter_has_wa()) {
rd = arch_counter_get_cntpct_stable;
- else
+ scr = raw_counter_get_cntpct_stable;
+ } else {
rd = arch_counter_get_cntpct;
+ scr = arch_counter_get_cntpct;
+ }
}
arch_timer_read_counter = rd;
clocksource_counter.vdso_clock_mode = vdso_default;
} else {
arch_timer_read_counter = arch_counter_get_cntvct_mem;
+ scr = arch_counter_get_cntvct_mem;
}
width = arch_counter_get_width();
@@ -1113,7 +1139,7 @@ static void __init arch_counter_register(unsigned type)
timecounter_init(&arch_timer_kvm_info.timecounter,
&cyclecounter, start_count);
- sched_clock_register(arch_timer_read_counter, width, arch_timer_rate);
+ sched_clock_register(scr, width, arch_timer_rate);
}
static void arch_timer_stop(struct clock_event_device *clk)
diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c
index bcd9042a0c9f..e56307a81f4d 100644
--- a/drivers/clocksource/hyperv_timer.c
+++ b/drivers/clocksource/hyperv_timer.c
@@ -365,6 +365,20 @@ void hv_stimer_global_cleanup(void)
}
EXPORT_SYMBOL_GPL(hv_stimer_global_cleanup);
+static __always_inline u64 read_hv_clock_msr(void)
+{
+ /*
+ * Read the partition counter to get the current tick count. This count
+ * is set to 0 when the partition is created and is incremented in 100
+ * nanosecond units.
+ *
+ * Use hv_raw_get_register() because this function is used from
+ * noinstr. Notable; while HV_REGISTER_TIME_REF_COUNT is a synthetic
+ * register it doesn't need the GHCB path.
+ */
+ return hv_raw_get_register(HV_REGISTER_TIME_REF_COUNT);
+}
+
/*
* Code and definitions for the Hyper-V clocksources. Two
* clocksources are defined: one that reads the Hyper-V defined MSR, and
@@ -393,14 +407,20 @@ struct ms_hyperv_tsc_page *hv_get_tsc_page(void)
}
EXPORT_SYMBOL_GPL(hv_get_tsc_page);
-static u64 notrace read_hv_clock_tsc(void)
+static __always_inline u64 read_hv_clock_tsc(void)
{
- u64 current_tick = hv_read_tsc_page(hv_get_tsc_page());
+ u64 cur_tsc, time;
- if (current_tick == U64_MAX)
- current_tick = hv_get_register(HV_REGISTER_TIME_REF_COUNT);
+ /*
+ * The Hyper-V Top-Level Function Spec (TLFS), section Timers,
+ * subsection Refererence Counter, guarantees that the TSC and MSR
+ * times are in sync and monotonic. Therefore we can fall back
+ * to the MSR in case the TSC page indicates unavailability.
+ */
+ if (!hv_read_tsc_page_tsc(tsc_page, &cur_tsc, &time))
+ time = read_hv_clock_msr();
- return current_tick;
+ return time;
}
static u64 notrace read_hv_clock_tsc_cs(struct clocksource *arg)
@@ -408,7 +428,7 @@ static u64 notrace read_hv_clock_tsc_cs(struct clocksource *arg)
return read_hv_clock_tsc();
}
-static u64 notrace read_hv_sched_clock_tsc(void)
+static u64 noinstr read_hv_sched_clock_tsc(void)
{
return (read_hv_clock_tsc() - hv_sched_clock_offset) *
(NSEC_PER_SEC / HV_CLOCK_HZ);
@@ -460,30 +480,14 @@ static struct clocksource hyperv_cs_tsc = {
#endif
};
-static u64 notrace read_hv_clock_msr(void)
-{
- /*
- * Read the partition counter to get the current tick count. This count
- * is set to 0 when the partition is created and is incremented in
- * 100 nanosecond units.
- */
- return hv_get_register(HV_REGISTER_TIME_REF_COUNT);
-}
-
static u64 notrace read_hv_clock_msr_cs(struct clocksource *arg)
{
return read_hv_clock_msr();
}
-static u64 notrace read_hv_sched_clock_msr(void)
-{
- return (read_hv_clock_msr() - hv_sched_clock_offset) *
- (NSEC_PER_SEC / HV_CLOCK_HZ);
-}
-
static struct clocksource hyperv_cs_msr = {
.name = "hyperv_clocksource_msr",
- .rating = 500,
+ .rating = 495,
.read = read_hv_clock_msr_cs,
.mask = CLOCKSOURCE_MASK(64),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
@@ -513,7 +517,7 @@ static __always_inline void hv_setup_sched_clock(void *sched_clock)
static __always_inline void hv_setup_sched_clock(void *sched_clock) {}
#endif /* CONFIG_GENERIC_SCHED_CLOCK */
-static bool __init hv_init_tsc_clocksource(void)
+static void __init hv_init_tsc_clocksource(void)
{
union hv_reference_tsc_msr tsc_msr;
@@ -524,17 +528,14 @@ static bool __init hv_init_tsc_clocksource(void)
* Hyper-V Reference TSC rating, causing the generic TSC to be used.
* TSC_INVARIANT is not offered on ARM64, so the Hyper-V Reference
* TSC will be preferred over the virtualized ARM64 arch counter.
- * While the Hyper-V MSR clocksource won't be used since the
- * Reference TSC clocksource is present, change its rating as
- * well for consistency.
*/
if (ms_hyperv.features & HV_ACCESS_TSC_INVARIANT) {
hyperv_cs_tsc.rating = 250;
- hyperv_cs_msr.rating = 250;
+ hyperv_cs_msr.rating = 245;
}
if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE))
- return false;
+ return;
hv_read_reference_counter = read_hv_clock_tsc;
@@ -565,33 +566,34 @@ static bool __init hv_init_tsc_clocksource(void)
clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100);
- hv_sched_clock_offset = hv_read_reference_counter();
- hv_setup_sched_clock(read_hv_sched_clock_tsc);
-
- return true;
+ /*
+ * If TSC is invariant, then let it stay as the sched clock since it
+ * will be faster than reading the TSC page. But if not invariant, use
+ * the TSC page so that live migrations across hosts with different
+ * frequencies is handled correctly.
+ */
+ if (!(ms_hyperv.features & HV_ACCESS_TSC_INVARIANT)) {
+ hv_sched_clock_offset = hv_read_reference_counter();
+ hv_setup_sched_clock(read_hv_sched_clock_tsc);
+ }
}
void __init hv_init_clocksource(void)
{
/*
- * Try to set up the TSC page clocksource. If it succeeds, we're
- * done. Otherwise, set up the MSR clocksource. At least one of
- * these will always be available except on very old versions of
- * Hyper-V on x86. In that case we won't have a Hyper-V
+ * Try to set up the TSC page clocksource, then the MSR clocksource.
+ * At least one of these will always be available except on very old
+ * versions of Hyper-V on x86. In that case we won't have a Hyper-V
* clocksource, but Linux will still run with a clocksource based
* on the emulated PIT or LAPIC timer.
+ *
+ * Never use the MSR clocksource as sched clock. It's too slow.
+ * Better to use the native sched clock as the fallback.
*/
- if (hv_init_tsc_clocksource())
- return;
-
- if (!(ms_hyperv.features & HV_MSR_TIME_REF_COUNT_AVAILABLE))
- return;
-
- hv_read_reference_counter = read_hv_clock_msr;
- clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100);
+ hv_init_tsc_clocksource();
- hv_sched_clock_offset = hv_read_reference_counter();
- hv_setup_sched_clock(read_hv_sched_clock_msr);
+ if (ms_hyperv.features & HV_MSR_TIME_REF_COUNT_AVAILABLE)
+ clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100);
}
void __init hv_remap_tsc_clocksource(void)
diff --git a/drivers/clocksource/ingenic-timer.c b/drivers/clocksource/ingenic-timer.c
index 089ce64b1c3f..154ee5f7954a 100644
--- a/drivers/clocksource/ingenic-timer.c
+++ b/drivers/clocksource/ingenic-timer.c
@@ -369,7 +369,7 @@ static int __init ingenic_tcu_probe(struct platform_device *pdev)
return 0;
}
-static int __maybe_unused ingenic_tcu_suspend(struct device *dev)
+static int ingenic_tcu_suspend(struct device *dev)
{
struct ingenic_tcu *tcu = dev_get_drvdata(dev);
unsigned int cpu;
@@ -382,7 +382,7 @@ static int __maybe_unused ingenic_tcu_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused ingenic_tcu_resume(struct device *dev)
+static int ingenic_tcu_resume(struct device *dev)
{
struct ingenic_tcu *tcu = dev_get_drvdata(dev);
unsigned int cpu;
@@ -406,7 +406,7 @@ err_timer_clk_disable:
return ret;
}
-static const struct dev_pm_ops __maybe_unused ingenic_tcu_pm_ops = {
+static const struct dev_pm_ops ingenic_tcu_pm_ops = {
/* _noirq: We want the TCU clocks to be gated last / ungated first */
.suspend_noirq = ingenic_tcu_suspend,
.resume_noirq = ingenic_tcu_resume,
@@ -415,9 +415,7 @@ static const struct dev_pm_ops __maybe_unused ingenic_tcu_pm_ops = {
static struct platform_driver ingenic_tcu_driver = {
.driver = {
.name = "ingenic-tcu-timer",
-#ifdef CONFIG_PM_SLEEP
- .pm = &ingenic_tcu_pm_ops,
-#endif
+ .pm = pm_sleep_ptr(&ingenic_tcu_pm_ops),
.of_match_table = ingenic_tcu_of_match,
},
};
diff --git a/drivers/clocksource/timer-cadence-ttc.c b/drivers/clocksource/timer-cadence-ttc.c
index 4efd0cf3b602..0d52e28fea4d 100644
--- a/drivers/clocksource/timer-cadence-ttc.c
+++ b/drivers/clocksource/timer-cadence-ttc.c
@@ -486,10 +486,10 @@ static int __init ttc_timer_probe(struct platform_device *pdev)
* and use it. Note that the event timer uses the interrupt and it's the
* 2nd TTC hence the irq_of_parse_and_map(,1)
*/
- timer_baseaddr = of_iomap(timer, 0);
- if (!timer_baseaddr) {
+ timer_baseaddr = devm_of_iomap(&pdev->dev, timer, 0, NULL);
+ if (IS_ERR(timer_baseaddr)) {
pr_err("ERROR: invalid timer base address\n");
- return -ENXIO;
+ return PTR_ERR(timer_baseaddr);
}
irq = irq_of_parse_and_map(timer, 1);
@@ -513,20 +513,27 @@ static int __init ttc_timer_probe(struct platform_device *pdev)
clk_ce = of_clk_get(timer, clksel);
if (IS_ERR(clk_ce)) {
pr_err("ERROR: timer input clock not found\n");
- return PTR_ERR(clk_ce);
+ ret = PTR_ERR(clk_ce);
+ goto put_clk_cs;
}
ret = ttc_setup_clocksource(clk_cs, timer_baseaddr, timer_width);
if (ret)
- return ret;
+ goto put_clk_ce;
ret = ttc_setup_clockevent(clk_ce, timer_baseaddr + 4, irq);
if (ret)
- return ret;
+ goto put_clk_ce;
pr_info("%pOFn #0 at %p, irq=%d\n", timer, timer_baseaddr, irq);
return 0;
+
+put_clk_ce:
+ clk_put(clk_ce);
+put_clk_cs:
+ clk_put(clk_cs);
+ return ret;
}
static const struct of_device_id ttc_timer_of_match[] = {
diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c
index ca3e4cbc80c6..28ab4f1a7c71 100644
--- a/drivers/clocksource/timer-imx-gpt.c
+++ b/drivers/clocksource/timer-imx-gpt.c
@@ -16,7 +16,6 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
-#include <soc/imx/timer.h>
/*
* There are 4 versions of the timer hardware on Freescale MXC hardware.
@@ -25,6 +24,12 @@
* - MX25, MX31, MX35, MX37, MX51, MX6Q(rev1.0)
* - MX6DL, MX6SX, MX6Q(rev1.1+)
*/
+enum imx_gpt_type {
+ GPT_TYPE_IMX1, /* i.MX1 */
+ GPT_TYPE_IMX21, /* i.MX21/27 */
+ GPT_TYPE_IMX31, /* i.MX31/35/25/37/51/6Q */
+ GPT_TYPE_IMX6DL, /* i.MX6DL/SX/SL */
+};
/* defines common for all i.MX */
#define MXC_TCTL 0x00
@@ -93,13 +98,11 @@ static void imx1_gpt_irq_disable(struct imx_timer *imxtm)
tmp = readl_relaxed(imxtm->base + MXC_TCTL);
writel_relaxed(tmp & ~MX1_2_TCTL_IRQEN, imxtm->base + MXC_TCTL);
}
-#define imx21_gpt_irq_disable imx1_gpt_irq_disable
static void imx31_gpt_irq_disable(struct imx_timer *imxtm)
{
writel_relaxed(0, imxtm->base + V2_IR);
}
-#define imx6dl_gpt_irq_disable imx31_gpt_irq_disable
static void imx1_gpt_irq_enable(struct imx_timer *imxtm)
{
@@ -108,13 +111,11 @@ static void imx1_gpt_irq_enable(struct imx_timer *imxtm)
tmp = readl_relaxed(imxtm->base + MXC_TCTL);
writel_relaxed(tmp | MX1_2_TCTL_IRQEN, imxtm->base + MXC_TCTL);
}
-#define imx21_gpt_irq_enable imx1_gpt_irq_enable
static void imx31_gpt_irq_enable(struct imx_timer *imxtm)
{
writel_relaxed(1<<0, imxtm->base + V2_IR);
}
-#define imx6dl_gpt_irq_enable imx31_gpt_irq_enable
static void imx1_gpt_irq_acknowledge(struct imx_timer *imxtm)
{
@@ -131,7 +132,6 @@ static void imx31_gpt_irq_acknowledge(struct imx_timer *imxtm)
{
writel_relaxed(V2_TSTAT_OF1, imxtm->base + V2_TSTAT);
}
-#define imx6dl_gpt_irq_acknowledge imx31_gpt_irq_acknowledge
static void __iomem *sched_clock_reg;
@@ -296,7 +296,6 @@ static void imx1_gpt_setup_tctl(struct imx_timer *imxtm)
tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
writel_relaxed(tctl_val, imxtm->base + MXC_TCTL);
}
-#define imx21_gpt_setup_tctl imx1_gpt_setup_tctl
static void imx31_gpt_setup_tctl(struct imx_timer *imxtm)
{
@@ -343,10 +342,10 @@ static const struct imx_gpt_data imx21_gpt_data = {
.reg_tstat = MX1_2_TSTAT,
.reg_tcn = MX1_2_TCN,
.reg_tcmp = MX1_2_TCMP,
- .gpt_irq_enable = imx21_gpt_irq_enable,
- .gpt_irq_disable = imx21_gpt_irq_disable,
+ .gpt_irq_enable = imx1_gpt_irq_enable,
+ .gpt_irq_disable = imx1_gpt_irq_disable,
.gpt_irq_acknowledge = imx21_gpt_irq_acknowledge,
- .gpt_setup_tctl = imx21_gpt_setup_tctl,
+ .gpt_setup_tctl = imx1_gpt_setup_tctl,
.set_next_event = mx1_2_set_next_event,
};
@@ -365,9 +364,9 @@ static const struct imx_gpt_data imx6dl_gpt_data = {
.reg_tstat = V2_TSTAT,
.reg_tcn = V2_TCN,
.reg_tcmp = V2_TCMP,
- .gpt_irq_enable = imx6dl_gpt_irq_enable,
- .gpt_irq_disable = imx6dl_gpt_irq_disable,
- .gpt_irq_acknowledge = imx6dl_gpt_irq_acknowledge,
+ .gpt_irq_enable = imx31_gpt_irq_enable,
+ .gpt_irq_disable = imx31_gpt_irq_disable,
+ .gpt_irq_acknowledge = imx31_gpt_irq_acknowledge,
.gpt_setup_tctl = imx6dl_gpt_setup_tctl,
.set_next_event = v2_set_next_event,
};
diff --git a/drivers/clocksource/timer-loongson1-pwm.c b/drivers/clocksource/timer-loongson1-pwm.c
new file mode 100644
index 000000000000..6335fee03017
--- /dev/null
+++ b/drivers/clocksource/timer-loongson1-pwm.c
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Clocksource driver for Loongson-1 SoC
+ *
+ * Copyright (c) 2023 Keguang Zhang <keguang.zhang@gmail.com>
+ */
+
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/sizes.h>
+#include "timer-of.h"
+
+/* Loongson-1 PWM Timer Register Definitions */
+#define PWM_CNTR 0x0
+#define PWM_HRC 0x4
+#define PWM_LRC 0x8
+#define PWM_CTRL 0xc
+
+/* PWM Control Register Bits */
+#define INT_LRC_EN BIT(11)
+#define INT_HRC_EN BIT(10)
+#define CNTR_RST BIT(7)
+#define INT_SR BIT(6)
+#define INT_EN BIT(5)
+#define PWM_SINGLE BIT(4)
+#define PWM_OE BIT(3)
+#define CNT_EN BIT(0)
+
+#define CNTR_WIDTH 24
+
+DEFINE_RAW_SPINLOCK(ls1x_timer_lock);
+
+struct ls1x_clocksource {
+ void __iomem *reg_base;
+ unsigned long ticks_per_jiffy;
+ struct clocksource clksrc;
+};
+
+static inline struct ls1x_clocksource *to_ls1x_clksrc(struct clocksource *c)
+{
+ return container_of(c, struct ls1x_clocksource, clksrc);
+}
+
+static inline void ls1x_pwmtimer_set_period(unsigned int period,
+ struct timer_of *to)
+{
+ writel(period, timer_of_base(to) + PWM_LRC);
+ writel(period, timer_of_base(to) + PWM_HRC);
+}
+
+static inline void ls1x_pwmtimer_clear(struct timer_of *to)
+{
+ writel(0, timer_of_base(to) + PWM_CNTR);
+}
+
+static inline void ls1x_pwmtimer_start(struct timer_of *to)
+{
+ writel((INT_EN | PWM_OE | CNT_EN), timer_of_base(to) + PWM_CTRL);
+}
+
+static inline void ls1x_pwmtimer_stop(struct timer_of *to)
+{
+ writel(0, timer_of_base(to) + PWM_CTRL);
+}
+
+static inline void ls1x_pwmtimer_irq_ack(struct timer_of *to)
+{
+ int val;
+
+ val = readl(timer_of_base(to) + PWM_CTRL);
+ val |= INT_SR;
+ writel(val, timer_of_base(to) + PWM_CTRL);
+}
+
+static irqreturn_t ls1x_clockevent_isr(int irq, void *dev_id)
+{
+ struct clock_event_device *clkevt = dev_id;
+ struct timer_of *to = to_timer_of(clkevt);
+
+ ls1x_pwmtimer_irq_ack(to);
+ ls1x_pwmtimer_clear(to);
+ ls1x_pwmtimer_start(to);
+
+ clkevt->event_handler(clkevt);
+
+ return IRQ_HANDLED;
+}
+
+static int ls1x_clockevent_set_state_periodic(struct clock_event_device *clkevt)
+{
+ struct timer_of *to = to_timer_of(clkevt);
+
+ raw_spin_lock(&ls1x_timer_lock);
+ ls1x_pwmtimer_set_period(timer_of_period(to), to);
+ ls1x_pwmtimer_clear(to);
+ ls1x_pwmtimer_start(to);
+ raw_spin_unlock(&ls1x_timer_lock);
+
+ return 0;
+}
+
+static int ls1x_clockevent_tick_resume(struct clock_event_device *clkevt)
+{
+ raw_spin_lock(&ls1x_timer_lock);
+ ls1x_pwmtimer_start(to_timer_of(clkevt));
+ raw_spin_unlock(&ls1x_timer_lock);
+
+ return 0;
+}
+
+static int ls1x_clockevent_set_state_shutdown(struct clock_event_device *clkevt)
+{
+ raw_spin_lock(&ls1x_timer_lock);
+ ls1x_pwmtimer_stop(to_timer_of(clkevt));
+ raw_spin_unlock(&ls1x_timer_lock);
+
+ return 0;
+}
+
+static int ls1x_clockevent_set_next(unsigned long evt,
+ struct clock_event_device *clkevt)
+{
+ struct timer_of *to = to_timer_of(clkevt);
+
+ raw_spin_lock(&ls1x_timer_lock);
+ ls1x_pwmtimer_set_period(evt, to);
+ ls1x_pwmtimer_clear(to);
+ ls1x_pwmtimer_start(to);
+ raw_spin_unlock(&ls1x_timer_lock);
+
+ return 0;
+}
+
+static struct timer_of ls1x_to = {
+ .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
+ .clkevt = {
+ .name = "ls1x-pwmtimer",
+ .features = CLOCK_EVT_FEAT_PERIODIC |
+ CLOCK_EVT_FEAT_ONESHOT,
+ .rating = 300,
+ .set_next_event = ls1x_clockevent_set_next,
+ .set_state_periodic = ls1x_clockevent_set_state_periodic,
+ .set_state_oneshot = ls1x_clockevent_set_state_shutdown,
+ .set_state_shutdown = ls1x_clockevent_set_state_shutdown,
+ .tick_resume = ls1x_clockevent_tick_resume,
+ },
+ .of_irq = {
+ .handler = ls1x_clockevent_isr,
+ .flags = IRQF_TIMER,
+ },
+};
+
+/*
+ * Since the PWM timer overflows every two ticks, its not very useful
+ * to just read by itself. So use jiffies to emulate a free
+ * running counter:
+ */
+static u64 ls1x_clocksource_read(struct clocksource *cs)
+{
+ struct ls1x_clocksource *ls1x_cs = to_ls1x_clksrc(cs);
+ unsigned long flags;
+ int count;
+ u32 jifs;
+ static int old_count;
+ static u32 old_jifs;
+
+ raw_spin_lock_irqsave(&ls1x_timer_lock, flags);
+ /*
+ * Although our caller may have the read side of xtime_lock,
+ * this is now a seqlock, and we are cheating in this routine
+ * by having side effects on state that we cannot undo if
+ * there is a collision on the seqlock and our caller has to
+ * retry. (Namely, old_jifs and old_count.) So we must treat
+ * jiffies as volatile despite the lock. We read jiffies
+ * before latching the timer count to guarantee that although
+ * the jiffies value might be older than the count (that is,
+ * the counter may underflow between the last point where
+ * jiffies was incremented and the point where we latch the
+ * count), it cannot be newer.
+ */
+ jifs = jiffies;
+ /* read the count */
+ count = readl(ls1x_cs->reg_base + PWM_CNTR);
+
+ /*
+ * It's possible for count to appear to go the wrong way for this
+ * reason:
+ *
+ * The timer counter underflows, but we haven't handled the resulting
+ * interrupt and incremented jiffies yet.
+ *
+ * Previous attempts to handle these cases intelligently were buggy, so
+ * we just do the simple thing now.
+ */
+ if (count < old_count && jifs == old_jifs)
+ count = old_count;
+
+ old_count = count;
+ old_jifs = jifs;
+
+ raw_spin_unlock_irqrestore(&ls1x_timer_lock, flags);
+
+ return (u64)(jifs * ls1x_cs->ticks_per_jiffy) + count;
+}
+
+static struct ls1x_clocksource ls1x_clocksource = {
+ .clksrc = {
+ .name = "ls1x-pwmtimer",
+ .rating = 300,
+ .read = ls1x_clocksource_read,
+ .mask = CLOCKSOURCE_MASK(CNTR_WIDTH),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ },
+};
+
+static int __init ls1x_pwm_clocksource_init(struct device_node *np)
+{
+ struct timer_of *to = &ls1x_to;
+ int ret;
+
+ ret = timer_of_init(np, to);
+ if (ret)
+ return ret;
+
+ clockevents_config_and_register(&to->clkevt, timer_of_rate(to),
+ 0x1, GENMASK(CNTR_WIDTH - 1, 0));
+
+ ls1x_clocksource.reg_base = timer_of_base(to);
+ ls1x_clocksource.ticks_per_jiffy = timer_of_period(to);
+
+ return clocksource_register_hz(&ls1x_clocksource.clksrc,
+ timer_of_rate(to));
+}
+
+TIMER_OF_DECLARE(ls1x_pwm_clocksource, "loongson,ls1b-pwmtimer",
+ ls1x_pwm_clocksource_init);
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..62962ae84b77 100644
--- a/drivers/counter/Kconfig
+++ b/drivers/counter/Kconfig
@@ -3,6 +3,21 @@
# Counter devices
#
+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.
+
menuconfig COUNTER
tristate "Counter support"
help
@@ -15,15 +30,17 @@ 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 2c839bd2b051..f429b9b37b76 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -38,7 +38,7 @@ choice
prompt "Default CPUFreq governor"
default CPU_FREQ_DEFAULT_GOV_USERSPACE if ARM_SA1110_CPUFREQ
default CPU_FREQ_DEFAULT_GOV_SCHEDUTIL if ARM64 || ARM
- default CPU_FREQ_DEFAULT_GOV_SCHEDUTIL if X86_INTEL_PSTATE && SMP
+ default CPU_FREQ_DEFAULT_GOV_SCHEDUTIL if (X86_INTEL_PSTATE || X86_AMD_PSTATE) && SMP
default CPU_FREQ_DEFAULT_GOV_PERFORMANCE
help
This option sets which CPUFreq governor shall be loaded at
@@ -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/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
index 00476e94db90..438c9e75a04d 100644
--- a/drivers/cpufreq/Kconfig.x86
+++ b/drivers/cpufreq/Kconfig.x86
@@ -51,6 +51,23 @@ config X86_AMD_PSTATE
If in doubt, say N.
+config X86_AMD_PSTATE_DEFAULT_MODE
+ int "AMD Processor P-State default mode"
+ depends on X86_AMD_PSTATE
+ default 3 if X86_AMD_PSTATE
+ range 1 4
+ help
+ Select the default mode the amd-pstate driver will use on
+ supported hardware.
+ The value set has the following meanings:
+ 1 -> Disabled
+ 2 -> Passive
+ 3 -> Active (EPP)
+ 4 -> Guided
+
+ For details, take a look at:
+ <file:Documentation/admin-guide/pm/amd-pstate.rst>.
+
config X86_AMD_PSTATE_UT
tristate "selftest for AMD Processor P-State driver"
depends on X86 && ACPI_PROCESSOR
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index ddd346a239e0..9a1e194d5cf8 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -62,7 +62,8 @@
static struct cpufreq_driver *current_pstate_driver;
static struct cpufreq_driver amd_pstate_driver;
static struct cpufreq_driver amd_pstate_epp_driver;
-static int cppc_state = AMD_PSTATE_DISABLE;
+static int cppc_state = AMD_PSTATE_UNDEFINED;
+static bool cppc_enabled;
/*
* AMD Energy Preference Performance (EPP)
@@ -228,7 +229,28 @@ static int amd_pstate_set_energy_pref_index(struct amd_cpudata *cpudata,
static inline int pstate_enable(bool enable)
{
- return wrmsrl_safe(MSR_AMD_CPPC_ENABLE, enable);
+ int ret, cpu;
+ unsigned long logical_proc_id_mask = 0;
+
+ if (enable == cppc_enabled)
+ return 0;
+
+ for_each_present_cpu(cpu) {
+ unsigned long logical_id = topology_logical_die_id(cpu);
+
+ if (test_bit(logical_id, &logical_proc_id_mask))
+ continue;
+
+ set_bit(logical_id, &logical_proc_id_mask);
+
+ ret = wrmsrl_safe_on_cpu(cpu, MSR_AMD_CPPC_ENABLE,
+ enable);
+ if (ret)
+ return ret;
+ }
+
+ cppc_enabled = enable;
+ return 0;
}
static int cppc_enable(bool enable)
@@ -236,6 +258,9 @@ static int cppc_enable(bool enable)
int cpu, ret = 0;
struct cppc_perf_ctrls perf_ctrls;
+ if (enable == cppc_enabled)
+ return 0;
+
for_each_present_cpu(cpu) {
ret = cppc_set_enable(cpu, enable);
if (ret)
@@ -251,6 +276,7 @@ static int cppc_enable(bool enable)
}
}
+ cppc_enabled = enable;
return ret;
}
@@ -986,8 +1012,8 @@ static int amd_pstate_update_status(const char *buf, size_t size)
return 0;
}
-static ssize_t show_status(struct kobject *kobj,
- struct kobj_attribute *attr, char *buf)
+static ssize_t status_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
ssize_t ret;
@@ -998,7 +1024,7 @@ static ssize_t show_status(struct kobject *kobj,
return ret;
}
-static ssize_t store_status(struct kobject *a, struct kobj_attribute *b,
+static ssize_t status_store(struct device *a, struct device_attribute *b,
const char *buf, size_t count)
{
char *p = memchr(buf, '\n', count);
@@ -1017,7 +1043,7 @@ cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq);
cpufreq_freq_attr_ro(amd_pstate_highest_perf);
cpufreq_freq_attr_rw(energy_performance_preference);
cpufreq_freq_attr_ro(energy_performance_available_preferences);
-define_one_global_rw(status);
+static DEVICE_ATTR_RW(status);
static struct freq_attr *amd_pstate_attr[] = {
&amd_pstate_max_freq,
@@ -1036,7 +1062,7 @@ static struct freq_attr *amd_pstate_epp_attr[] = {
};
static struct attribute *pstate_global_attributes[] = {
- &status.attr,
+ &dev_attr_status.attr,
NULL
};
@@ -1045,6 +1071,26 @@ static const struct attribute_group amd_pstate_global_attr_group = {
.attrs = pstate_global_attributes,
};
+static bool amd_pstate_acpi_pm_profile_server(void)
+{
+ switch (acpi_gbl_FADT.preferred_profile) {
+ case PM_ENTERPRISE_SERVER:
+ case PM_SOHO_SERVER:
+ case PM_PERFORMANCE_SERVER:
+ return true;
+ }
+ return false;
+}
+
+static bool amd_pstate_acpi_pm_profile_undefined(void)
+{
+ if (acpi_gbl_FADT.preferred_profile == PM_UNSPECIFIED)
+ return true;
+ if (acpi_gbl_FADT.preferred_profile >= NR_PM_PROFILES)
+ return true;
+ return false;
+}
+
static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
{
int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret;
@@ -1102,10 +1148,14 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
policy->max = policy->cpuinfo.max_freq;
/*
- * Set the policy to powersave to provide a valid fallback value in case
+ * Set the policy to provide a valid fallback value in case
* the default cpufreq governor is neither powersave nor performance.
*/
- policy->policy = CPUFREQ_POLICY_POWERSAVE;
+ if (amd_pstate_acpi_pm_profile_server() ||
+ amd_pstate_acpi_pm_profile_undefined())
+ policy->policy = CPUFREQ_POLICY_PERFORMANCE;
+ else
+ policy->policy = CPUFREQ_POLICY_POWERSAVE;
if (boot_cpu_has(X86_FEATURE_CPPC)) {
ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value);
@@ -1356,10 +1406,29 @@ static struct cpufreq_driver amd_pstate_epp_driver = {
.online = amd_pstate_epp_cpu_online,
.suspend = amd_pstate_epp_suspend,
.resume = amd_pstate_epp_resume,
- .name = "amd_pstate_epp",
+ .name = "amd-pstate-epp",
.attr = amd_pstate_epp_attr,
};
+static int __init amd_pstate_set_driver(int mode_idx)
+{
+ if (mode_idx >= AMD_PSTATE_DISABLE && mode_idx < AMD_PSTATE_MAX) {
+ cppc_state = mode_idx;
+ if (cppc_state == AMD_PSTATE_DISABLE)
+ pr_info("driver is explicitly disabled\n");
+
+ if (cppc_state == AMD_PSTATE_ACTIVE)
+ current_pstate_driver = &amd_pstate_epp_driver;
+
+ if (cppc_state == AMD_PSTATE_PASSIVE || cppc_state == AMD_PSTATE_GUIDED)
+ current_pstate_driver = &amd_pstate_driver;
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
static int __init amd_pstate_init(void)
{
struct device *dev_root;
@@ -1367,15 +1436,6 @@ static int __init amd_pstate_init(void)
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
return -ENODEV;
- /*
- * by default the pstate driver is disabled to load
- * enable the amd_pstate passive mode driver explicitly
- * with amd_pstate=passive or other modes in kernel command line
- */
- if (cppc_state == AMD_PSTATE_DISABLE) {
- pr_info("driver load is disabled, boot with specific mode to enable this\n");
- return -ENODEV;
- }
if (!acpi_cpc_valid()) {
pr_warn_once("the _CPC object is not present in SBIOS or ACPI disabled\n");
@@ -1386,6 +1446,33 @@ static int __init amd_pstate_init(void)
if (cpufreq_get_current_driver())
return -EEXIST;
+ switch (cppc_state) {
+ case AMD_PSTATE_UNDEFINED:
+ /* Disable on the following configs by default:
+ * 1. Undefined platforms
+ * 2. Server platforms
+ * 3. Shared memory designs
+ */
+ if (amd_pstate_acpi_pm_profile_undefined() ||
+ amd_pstate_acpi_pm_profile_server() ||
+ !boot_cpu_has(X86_FEATURE_CPPC)) {
+ pr_info("driver load is disabled, boot with specific mode to enable this\n");
+ return -ENODEV;
+ }
+ ret = amd_pstate_set_driver(CONFIG_X86_AMD_PSTATE_DEFAULT_MODE);
+ if (ret)
+ return ret;
+ break;
+ case AMD_PSTATE_DISABLE:
+ return -ENODEV;
+ case AMD_PSTATE_PASSIVE:
+ case AMD_PSTATE_ACTIVE:
+ case AMD_PSTATE_GUIDED:
+ break;
+ default:
+ return -EINVAL;
+ }
+
/* capability check */
if (boot_cpu_has(X86_FEATURE_CPPC)) {
pr_debug("AMD CPPC MSR based functionality is supported\n");
@@ -1438,21 +1525,7 @@ static int __init amd_pstate_param(char *str)
size = strlen(str);
mode_idx = get_mode_idx_from_str(str, size);
- if (mode_idx >= AMD_PSTATE_DISABLE && mode_idx < AMD_PSTATE_MAX) {
- cppc_state = mode_idx;
- if (cppc_state == AMD_PSTATE_DISABLE)
- pr_info("driver is explicitly disabled\n");
-
- if (cppc_state == AMD_PSTATE_ACTIVE)
- current_pstate_driver = &amd_pstate_epp_driver;
-
- if (cppc_state == AMD_PSTATE_PASSIVE || cppc_state == AMD_PSTATE_GUIDED)
- current_pstate_driver = &amd_pstate_driver;
-
- return 0;
- }
-
- return -EINVAL;
+ return amd_pstate_set_driver(mode_idx);
}
early_param("amd_pstate", amd_pstate_param);
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/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 6b52ebe5a890..50bbc969ffe5 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2828,7 +2828,8 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
(driver_data->setpolicy && (driver_data->target_index ||
driver_data->target)) ||
(!driver_data->get_intermediate != !driver_data->target_intermediate) ||
- (!driver_data->online != !driver_data->offline))
+ (!driver_data->online != !driver_data->offline) ||
+ (driver_data->adjust_perf && !driver_data->fast_switch))
return -EINVAL;
pr_debug("trying to register driver %s\n", driver_data->name);
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 2548ec92faa2..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 */
/**
@@ -824,6 +856,8 @@ static ssize_t store_energy_performance_preference(
err = cpufreq_start_governor(policy);
if (!ret)
ret = err;
+ } else {
+ ret = 0;
}
}
@@ -1895,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;
@@ -1936,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)
@@ -3393,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..2783d3d55fce 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];
};
@@ -271,7 +269,7 @@ static int us2e_freq_target(struct cpufreq_policy *policy, unsigned int index)
return smp_call_function_single(cpu, __us2e_freq_target, &index, 1);
}
-static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy)
+static int us2e_freq_cpu_init(struct cpufreq_policy *policy)
{
unsigned int cpu = policy->cpu;
unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000;
@@ -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..6c3657679a88 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];
};
@@ -119,7 +117,7 @@ static int us3_freq_target(struct cpufreq_policy *policy, unsigned int index)
return smp_call_function_single(cpu, update_safari_cfg, &new_bits, 1);
}
-static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
+static int us3_freq_cpu_init(struct cpufreq_policy *policy)
{
unsigned int cpu = policy->cpu;
unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000;
@@ -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/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
index c2d6d9c3c930..b88af1262f1a 100644
--- a/drivers/cpuidle/cpuidle-psci-domain.c
+++ b/drivers/cpuidle/cpuidle-psci-domain.c
@@ -120,20 +120,6 @@ static void psci_pd_remove(void)
}
}
-static bool psci_pd_try_set_osi_mode(void)
-{
- int ret;
-
- if (!psci_has_osi_support())
- return false;
-
- ret = psci_set_osi_mode(true);
- if (ret)
- return false;
-
- return true;
-}
-
static void psci_cpuidle_domain_sync_state(struct device *dev)
{
/*
@@ -152,15 +138,12 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *node;
- bool use_osi;
+ bool use_osi = psci_has_osi_support();
int ret = 0, pd_count = 0;
if (!np)
return -ENODEV;
- /* If OSI mode is supported, let's try to enable it. */
- use_osi = psci_pd_try_set_osi_mode();
-
/*
* Parse child nodes for the "#power-domain-cells" property and
* initialize a genpd/genpd-of-provider pair when it's found.
@@ -170,33 +153,37 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev)
continue;
ret = psci_pd_init(node, use_osi);
- if (ret)
- goto put_node;
+ if (ret) {
+ of_node_put(node);
+ goto exit;
+ }
pd_count++;
}
/* Bail out if not using the hierarchical CPU topology. */
if (!pd_count)
- goto no_pd;
+ return 0;
/* Link genpd masters/subdomains to model the CPU topology. */
ret = dt_idle_pd_init_topology(np);
if (ret)
goto remove_pd;
+ /* let's try to enable OSI. */
+ ret = psci_set_osi_mode(use_osi);
+ if (ret)
+ goto remove_pd;
+
pr_info("Initialized CPU PM domain topology using %s mode\n",
use_osi ? "OSI" : "PC");
return 0;
-put_node:
- of_node_put(node);
remove_pd:
+ dt_idle_pd_remove_topology(np);
psci_pd_remove();
+exit:
pr_err("failed to create CPU PM domains ret=%d\n", ret);
-no_pd:
- if (use_osi)
- psci_set_osi_mode(false);
return ret;
}
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 8e929f6602ce..737a026ef58a 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -145,7 +145,7 @@ static noinstr void enter_s2idle_proper(struct cpuidle_driver *drv,
instrumentation_begin();
- time_start = ns_to_ktime(local_clock());
+ time_start = ns_to_ktime(local_clock_noinstr());
tick_freeze();
/*
@@ -169,7 +169,7 @@ static noinstr void enter_s2idle_proper(struct cpuidle_driver *drv,
tick_unfreeze();
start_critical_timings();
- time_end = ns_to_ktime(local_clock());
+ time_end = ns_to_ktime(local_clock_noinstr());
dev->states_usage[index].s2idle_time += ktime_us_delta(time_end, time_start);
dev->states_usage[index].s2idle_usage++;
@@ -243,7 +243,7 @@ noinstr int cpuidle_enter_state(struct cpuidle_device *dev,
sched_idle_set_state(target_state);
trace_cpu_idle(index, dev->cpu);
- time_start = ns_to_ktime(local_clock());
+ time_start = ns_to_ktime(local_clock_noinstr());
stop_critical_timings();
if (!(target_state->flags & CPUIDLE_FLAG_RCU_IDLE)) {
@@ -276,7 +276,7 @@ noinstr int cpuidle_enter_state(struct cpuidle_device *dev,
start_critical_timings();
sched_clock_idle_wakeup_event();
- time_end = ns_to_ktime(local_clock());
+ time_end = ns_to_ktime(local_clock_noinstr());
trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu);
/* The cpu is no longer idle or about to enter idle. */
diff --git a/drivers/cpuidle/dt_idle_genpd.c b/drivers/cpuidle/dt_idle_genpd.c
index b37165514d4e..1af63c189039 100644
--- a/drivers/cpuidle/dt_idle_genpd.c
+++ b/drivers/cpuidle/dt_idle_genpd.c
@@ -152,6 +152,30 @@ int dt_idle_pd_init_topology(struct device_node *np)
return 0;
}
+int dt_idle_pd_remove_topology(struct device_node *np)
+{
+ struct device_node *node;
+ struct of_phandle_args child, parent;
+ int ret;
+
+ for_each_child_of_node(np, node) {
+ if (of_parse_phandle_with_args(node, "power-domains",
+ "#power-domain-cells", 0, &parent))
+ continue;
+
+ child.np = node;
+ child.args_count = 0;
+ ret = of_genpd_remove_subdomain(&parent, &child);
+ of_node_put(parent.np);
+ if (ret) {
+ of_node_put(node);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
struct device *dt_idle_attach_cpu(int cpu, const char *name)
{
struct device *dev;
diff --git a/drivers/cpuidle/dt_idle_genpd.h b/drivers/cpuidle/dt_idle_genpd.h
index a95483d08a02..3be1f70f55b5 100644
--- a/drivers/cpuidle/dt_idle_genpd.h
+++ b/drivers/cpuidle/dt_idle_genpd.h
@@ -14,6 +14,8 @@ struct generic_pm_domain *dt_idle_pd_alloc(struct device_node *np,
int dt_idle_pd_init_topology(struct device_node *np);
+int dt_idle_pd_remove_topology(struct device_node *np);
+
struct device *dt_idle_attach_cpu(int cpu, const char *name);
void dt_idle_detach_cpu(struct device *dev);
@@ -36,6 +38,11 @@ static inline int dt_idle_pd_init_topology(struct device_node *np)
return 0;
}
+static inline int dt_idle_pd_remove_topology(struct device_node *np)
+{
+ return 0;
+}
+
static inline struct device *dt_idle_attach_cpu(int cpu, const char *name)
{
return NULL;
diff --git a/drivers/cpuidle/poll_state.c b/drivers/cpuidle/poll_state.c
index bdcfeaecd228..9b6d90a72601 100644
--- a/drivers/cpuidle/poll_state.c
+++ b/drivers/cpuidle/poll_state.c
@@ -15,7 +15,7 @@ static int __cpuidle poll_idle(struct cpuidle_device *dev,
{
u64 time_start;
- time_start = local_clock();
+ time_start = local_clock_noinstr();
dev->poll_time_limit = false;
@@ -32,7 +32,7 @@ static int __cpuidle poll_idle(struct cpuidle_device *dev,
continue;
loop_count = 0;
- if (local_clock() - time_start > limit) {
+ if (local_clock_noinstr() - time_start > limit) {
dev->poll_time_limit = true;
break;
}
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 9c440cd0fed0..44e44b8d9ce6 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -92,17 +92,6 @@ config ZCRYPT_DEBUG
If unsure, say N.
-config ZCRYPT_MULTIDEVNODES
- bool "Support for multiple zcrypt device nodes"
- default y
- depends on S390
- depends on ZCRYPT
- help
- With this option enabled the zcrypt device driver can
- provide multiple devices nodes in /dev. Each device
- node can get customized to limit access and narrow
- down the use of the available crypto hardware.
-
config PKEY
tristate "Kernel API for protected key handling"
depends on S390
@@ -807,5 +796,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/allwinner/sun4i-ss/sun4i-ss-cipher.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c
index 10fe9f73a5fb..f2dd66706c10 100644
--- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c
+++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c
@@ -8,7 +8,7 @@
* keysize in CBC and ECB mode.
* Add support also for DES and 3DES in CBC and ECB mode.
*
- * You could find the datasheet in Documentation/arm/sunxi.rst
+ * You could find the datasheet in Documentation/arch/arm/sunxi.rst
*/
#include "sun4i-ss.h"
diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
index 006e40133c28..51a3a7b5b985 100644
--- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
+++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
@@ -6,7 +6,7 @@
*
* Core file which registers crypto algorithms supported by the SS.
*
- * You could find a link for the datasheet in Documentation/arm/sunxi.rst
+ * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst
*/
#include <linux/clk.h>
#include <linux/crypto.h>
diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-hash.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-hash.c
index d28292762b32..f7893e4ac59d 100644
--- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-hash.c
+++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-hash.c
@@ -6,7 +6,7 @@
*
* This file add support for MD5 and SHA1.
*
- * You could find the datasheet in Documentation/arm/sunxi.rst
+ * You could find the datasheet in Documentation/arch/arm/sunxi.rst
*/
#include "sun4i-ss.h"
#include <asm/unaligned.h>
diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h
index ba59c7a48825..6c5d4aa6453c 100644
--- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h
+++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h
@@ -8,7 +8,7 @@
* Support MD5 and SHA1 hash algorithms.
* Support DES and 3DES
*
- * You could find the datasheet in Documentation/arm/sunxi.rst
+ * You could find the datasheet in Documentation/arch/arm/sunxi.rst
*/
#include <linux/clk.h>
diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c
index 74b4e910a38d..c13550090785 100644
--- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c
+++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c
@@ -8,7 +8,7 @@
* This file add support for AES cipher with 128,192,256 bits keysize in
* CBC and ECB mode.
*
- * You could find a link for the datasheet in Documentation/arm/sunxi.rst
+ * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst
*/
#include <linux/bottom_half.h>
diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c
index a6865ff4d400..07ea0cc82b16 100644
--- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c
+++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c
@@ -7,7 +7,7 @@
*
* Core file which registers crypto algorithms supported by the CryptoEngine.
*
- * You could find a link for the datasheet in Documentation/arm/sunxi.rst
+ * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst
*/
#include <linux/clk.h>
#include <linux/crypto.h>
diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c
index 8b5b9b9d04c3..930ad157004c 100644
--- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c
+++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c
@@ -7,7 +7,7 @@
*
* This file add support for MD5 and SHA1/SHA224/SHA256/SHA384/SHA512.
*
- * You could find the datasheet in Documentation/arm/sunxi.rst
+ * You could find the datasheet in Documentation/arch/arm/sunxi.rst
*/
#include <linux/bottom_half.h>
#include <linux/dma-mapping.h>
diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c
index b3cc43ea6c8a..80815379f6fc 100644
--- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c
+++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c
@@ -7,7 +7,7 @@
*
* This file handle the PRNG
*
- * You could find a link for the datasheet in Documentation/arm/sunxi.rst
+ * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst
*/
#include "sun8i-ce.h"
#include <linux/dma-mapping.h>
diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-trng.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-trng.c
index e2b9b9104694..9c35f2a83eda 100644
--- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-trng.c
+++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-trng.c
@@ -7,7 +7,7 @@
*
* This file handle the TRNG
*
- * You could find a link for the datasheet in Documentation/arm/sunxi.rst
+ * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst
*/
#include "sun8i-ce.h"
#include <linux/dma-mapping.h>
diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c
index 16966cc94e24..381a90fbeaff 100644
--- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c
+++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c
@@ -8,7 +8,7 @@
* This file add support for AES cipher with 128,192,256 bits keysize in
* CBC and ECB mode.
*
- * You could find a link for the datasheet in Documentation/arm/sunxi.rst
+ * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst
*/
#include <linux/bottom_half.h>
diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c
index c9dc06f97857..3dd844b40ff7 100644
--- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c
+++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c
@@ -7,7 +7,7 @@
*
* Core file which registers crypto algorithms supported by the SecuritySystem
*
- * You could find a link for the datasheet in Documentation/arm/sunxi.rst
+ * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst
*/
#include <linux/clk.h>
#include <linux/crypto.h>
diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c
index 577bf636f7fb..a4b67d130d11 100644
--- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c
+++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c
@@ -7,7 +7,7 @@
*
* This file add support for MD5 and SHA1/SHA224/SHA256.
*
- * You could find the datasheet in Documentation/arm/sunxi.rst
+ * You could find the datasheet in Documentation/arch/arm/sunxi.rst
*/
#include <linux/bottom_half.h>
#include <linux/dma-mapping.h>
diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c
index 70c7b5d571b8..a923cfc6553f 100644
--- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c
+++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c
@@ -7,7 +7,7 @@
*
* This file handle the PRNG found in the SS
*
- * You could find a link for the datasheet in Documentation/arm/sunxi.rst
+ * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst
*/
#include "sun8i-ss.h"
#include <linux/dma-mapping.h>
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..68e73775392d 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);
+ /* disable maximum frequency count */
+ wr_reg32(&r4tst->rtfrqmax, RTFRQMAX_DISABLE);
+ }
+
+ 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 ddf6e913c1c4..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)
{
@@ -357,9 +359,9 @@ static int cptpf_vfpf_mbox_init(struct otx2_cptpf_dev *cptpf, int num_vfs)
u64 vfpf_mbox_base;
int err, i;
- cptpf->vfpf_mbox_wq = alloc_workqueue("cpt_vfpf_mailbox",
- WQ_UNBOUND | WQ_HIGHPRI |
- WQ_MEM_RECLAIM, 1);
+ cptpf->vfpf_mbox_wq =
+ alloc_ordered_workqueue("cpt_vfpf_mailbox",
+ WQ_HIGHPRI | WQ_MEM_RECLAIM);
if (!cptpf->vfpf_mbox_wq)
return -ENOMEM;
@@ -453,9 +455,9 @@ static int cptpf_afpf_mbox_init(struct otx2_cptpf_dev *cptpf)
resource_size_t offset;
int err;
- cptpf->afpf_mbox_wq = alloc_workqueue("cpt_afpf_mailbox",
- WQ_UNBOUND | WQ_HIGHPRI |
- WQ_MEM_RECLAIM, 1);
+ cptpf->afpf_mbox_wq =
+ alloc_ordered_workqueue("cpt_afpf_mailbox",
+ WQ_HIGHPRI | WQ_MEM_RECLAIM);
if (!cptpf->afpf_mbox_wq)
return -ENOMEM;
@@ -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 392e9fee05e8..bac729c885f9 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c
+++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c
@@ -75,9 +75,9 @@ static int cptvf_pfvf_mbox_init(struct otx2_cptvf_dev *cptvf)
resource_size_t offset, size;
int ret;
- cptvf->pfvf_mbox_wq = alloc_workqueue("cpt_pfvf_mailbox",
- WQ_UNBOUND | WQ_HIGHPRI |
- WQ_MEM_RECLAIM, 1);
+ cptvf->pfvf_mbox_wq =
+ alloc_ordered_workqueue("cpt_pfvf_mailbox",
+ WQ_HIGHPRI | WQ_MEM_RECLAIM);
if (!cptvf->pfvf_mbox_wq)
return -ENOMEM;
@@ -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..8ea1d340e438 100644
--- a/drivers/cxl/Kconfig
+++ b/drivers/cxl/Kconfig
@@ -2,6 +2,8 @@
menuconfig CXL_BUS
tristate "CXL (Compute Express Link) Devices Support"
depends on PCI
+ select FW_LOADER
+ select FW_UPLOAD
select PCI_DOE
help
CXL is a bus that is electrically compatible with PCI Express, but
@@ -139,4 +141,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..d1c559879dcc 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,
@@ -296,9 +296,8 @@ err_xormap:
else
rc = cxl_decoder_autoremove(dev, cxld);
if (rc) {
- dev_err(dev, "Failed to add decode range [%#llx - %#llx]\n",
- cxld->hpa_range.start, cxld->hpa_range.end);
- return 0;
+ dev_err(dev, "Failed to add decode range: %pr", res);
+ return rc;
}
dev_dbg(dev, "add: %s node: %d range [%#llx - %#llx]\n",
dev_name(&cxld->dev),
@@ -327,66 +326,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 +349,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 +390,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 +400,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..ca60bb8114f2 100644
--- a/drivers/cxl/core/mbox.c
+++ b/drivers/cxl/core/mbox.c
@@ -121,6 +121,45 @@ static bool cxl_is_security_command(u16 opcode)
return false;
}
+static void cxl_set_security_cmd_enabled(struct cxl_security_state *security,
+ u16 opcode)
+{
+ switch (opcode) {
+ case CXL_MBOX_OP_SANITIZE:
+ set_bit(CXL_SEC_ENABLED_SANITIZE, security->enabled_cmds);
+ break;
+ case CXL_MBOX_OP_SECURE_ERASE:
+ set_bit(CXL_SEC_ENABLED_SECURE_ERASE,
+ security->enabled_cmds);
+ break;
+ case CXL_MBOX_OP_GET_SECURITY_STATE:
+ set_bit(CXL_SEC_ENABLED_GET_SECURITY_STATE,
+ security->enabled_cmds);
+ break;
+ case CXL_MBOX_OP_SET_PASSPHRASE:
+ set_bit(CXL_SEC_ENABLED_SET_PASSPHRASE,
+ security->enabled_cmds);
+ break;
+ case CXL_MBOX_OP_DISABLE_PASSPHRASE:
+ set_bit(CXL_SEC_ENABLED_DISABLE_PASSPHRASE,
+ security->enabled_cmds);
+ break;
+ case CXL_MBOX_OP_UNLOCK:
+ set_bit(CXL_SEC_ENABLED_UNLOCK, security->enabled_cmds);
+ break;
+ case CXL_MBOX_OP_FREEZE_SECURITY:
+ set_bit(CXL_SEC_ENABLED_FREEZE_SECURITY,
+ security->enabled_cmds);
+ break;
+ case CXL_MBOX_OP_PASSPHRASE_SECURE_ERASE:
+ set_bit(CXL_SEC_ENABLED_PASSPHRASE_SECURE_ERASE,
+ security->enabled_cmds);
+ break;
+ default:
+ break;
+ }
+}
+
static bool cxl_is_poison_command(u16 opcode)
{
#define CXL_MBOX_OP_POISON_CMDS 0x43
@@ -182,7 +221,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 +237,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 +259,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 +337,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 +352,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 +361,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 +383,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 +393,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 +415,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 +430,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 +463,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 +478,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 +492,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 +513,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 +535,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 +552,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 +573,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 +588,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 +617,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 +628,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 +643,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 +669,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 +696,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;
@@ -673,40 +716,44 @@ static void cxl_walk_cel(struct cxl_dev_state *cxlds, size_t size, u8 *cel)
u16 opcode = le16_to_cpu(cel_entry[i].opcode);
struct cxl_mem_command *cmd = cxl_mem_find_command(opcode);
- if (!cmd && !cxl_is_poison_command(opcode)) {
- dev_dbg(cxlds->dev,
+ if (!cmd && (!cxl_is_poison_command(opcode) ||
+ !cxl_is_security_command(opcode))) {
+ dev_dbg(dev,
"Opcode 0x%04x unsupported by driver\n", opcode);
continue;
}
if (cmd)
- 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);
+
+ if (cxl_is_security_command(opcode))
+ cxl_set_security_cmd_enabled(&mds->security, 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 +776,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 +812,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 +885,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 +899,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 +926,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 +942,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 +952,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 +990,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 +1019,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 +1046,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 +1057,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 +1075,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 +1090,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 +1098,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 +1210,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 +1224,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 +1265,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 +1281,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 +1300,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 +1317,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 +1334,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..14b547c07f54 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,35 @@ static struct attribute_group cxl_memdev_pmem_attribute_group = {
.attrs = cxl_memdev_pmem_attributes,
};
+static umode_t cxl_memdev_security_visible(struct kobject *kobj,
+ struct attribute *a, int n)
+{
+ 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 (a == &dev_attr_security_sanitize.attr &&
+ !test_bit(CXL_SEC_ENABLED_SANITIZE, mds->security.enabled_cmds))
+ return 0;
+
+ if (a == &dev_attr_security_erase.attr &&
+ !test_bit(CXL_SEC_ENABLED_SECURE_ERASE, mds->security.enabled_cmds))
+ return 0;
+
+ return a->mode;
+}
+
+static struct attribute_group cxl_memdev_security_attribute_group = {
+ .name = "security",
+ .attrs = cxl_memdev_security_attributes,
+ .is_visible = cxl_memdev_security_visible,
+};
+
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 +524,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 +543,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 +650,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 +683,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 +1002,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 +1059,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..706f8a6d1ef4 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;
@@ -234,6 +244,19 @@ enum poison_cmd_enabled_bits {
CXL_POISON_ENABLED_MAX
};
+/* Device enabled security commands */
+enum security_cmd_enabled_bits {
+ CXL_SEC_ENABLED_SANITIZE,
+ CXL_SEC_ENABLED_SECURE_ERASE,
+ CXL_SEC_ENABLED_GET_SECURITY_STATE,
+ CXL_SEC_ENABLED_SET_PASSPHRASE,
+ CXL_SEC_ENABLED_DISABLE_PASSPHRASE,
+ CXL_SEC_ENABLED_UNLOCK,
+ CXL_SEC_ENABLED_FREEZE_SECURITY,
+ CXL_SEC_ENABLED_PASSPHRASE_SECURE_ERASE,
+ CXL_SEC_ENABLED_MAX
+};
+
/**
* struct cxl_poison_state - Driver poison state info
*
@@ -254,6 +277,117 @@ 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 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
+ * @enabled_cmds: All security commands enabled in the CEL
+ * @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;
+ DECLARE_BITMAP(enabled_cmds, CXL_SEC_ENABLED_MAX);
+ 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 +401,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 +439,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 +447,49 @@ 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
+ * @security: security 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 +498,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 +519,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 +851,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 +883,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/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
index 88414445adf3..245898f1a88e 100644
--- a/drivers/devfreq/exynos-bus.c
+++ b/drivers/devfreq/exynos-bus.c
@@ -518,6 +518,7 @@ static struct platform_driver exynos_bus_platdrv = {
};
module_platform_driver(exynos_bus_platdrv);
+MODULE_SOFTDEP("pre: exynos_ppmu");
MODULE_DESCRIPTION("Generic Exynos Bus frequency driver");
MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/devfreq/mtk-cci-devfreq.c b/drivers/devfreq/mtk-cci-devfreq.c
index e5458ada5197..6354622eda65 100644
--- a/drivers/devfreq/mtk-cci-devfreq.c
+++ b/drivers/devfreq/mtk-cci-devfreq.c
@@ -127,7 +127,7 @@ static int mtk_ccifreq_target(struct device *dev, unsigned long *freq,
u32 flags)
{
struct mtk_ccifreq_drv *drv = dev_get_drvdata(dev);
- struct clk *cci_pll = clk_get_parent(drv->cci_clk);
+ struct clk *cci_pll;
struct dev_pm_opp *opp;
unsigned long opp_rate;
int voltage, pre_voltage, inter_voltage, target_voltage, ret;
@@ -139,6 +139,7 @@ static int mtk_ccifreq_target(struct device *dev, unsigned long *freq,
return 0;
inter_voltage = drv->inter_voltage;
+ cci_pll = clk_get_parent(drv->cci_clk);
opp_rate = *freq;
opp = devfreq_recommended_opp(dev, &opp_rate, 1);
diff --git a/drivers/dma-buf/dma-fence-unwrap.c b/drivers/dma-buf/dma-fence-unwrap.c
index 7002bca792ff..c625bb2b5d56 100644
--- a/drivers/dma-buf/dma-fence-unwrap.c
+++ b/drivers/dma-buf/dma-fence-unwrap.c
@@ -66,18 +66,36 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
{
struct dma_fence_array *result;
struct dma_fence *tmp, **array;
+ ktime_t timestamp;
unsigned int i;
size_t count;
count = 0;
+ timestamp = ns_to_ktime(0);
for (i = 0; i < num_fences; ++i) {
- dma_fence_unwrap_for_each(tmp, &iter[i], fences[i])
- if (!dma_fence_is_signaled(tmp))
+ dma_fence_unwrap_for_each(tmp, &iter[i], fences[i]) {
+ if (!dma_fence_is_signaled(tmp)) {
++count;
+ } else if (test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT,
+ &tmp->flags)) {
+ if (ktime_after(tmp->timestamp, timestamp))
+ timestamp = tmp->timestamp;
+ } else {
+ /*
+ * Use the current time if the fence is
+ * currently signaling.
+ */
+ timestamp = ktime_get();
+ }
+ }
}
+ /*
+ * If we couldn't find a pending fence just return a private signaled
+ * fence with the timestamp of the last signaled one.
+ */
if (count == 0)
- return dma_fence_get_stub();
+ return dma_fence_allocate_private_stub(timestamp);
array = kmalloc_array(count, sizeof(*array), GFP_KERNEL);
if (!array)
@@ -138,7 +156,7 @@ restart:
} while (tmp);
if (count == 0) {
- tmp = dma_fence_get_stub();
+ tmp = dma_fence_allocate_private_stub(ktime_get());
goto return_tmp;
}
diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c
index f177c56269bb..8aa8f8cb7071 100644
--- a/drivers/dma-buf/dma-fence.c
+++ b/drivers/dma-buf/dma-fence.c
@@ -150,16 +150,17 @@ EXPORT_SYMBOL(dma_fence_get_stub);
/**
* dma_fence_allocate_private_stub - return a private, signaled fence
+ * @timestamp: timestamp when the fence was signaled
*
* Return a newly allocated and signaled stub fence.
*/
-struct dma_fence *dma_fence_allocate_private_stub(void)
+struct dma_fence *dma_fence_allocate_private_stub(ktime_t timestamp)
{
struct dma_fence *fence;
fence = kzalloc(sizeof(*fence), GFP_KERNEL);
if (fence == NULL)
- return ERR_PTR(-ENOMEM);
+ return NULL;
dma_fence_init(fence,
&dma_fence_stub_ops,
@@ -169,7 +170,7 @@ struct dma_fence *dma_fence_allocate_private_stub(void)
set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
&fence->flags);
- dma_fence_signal(fence);
+ dma_fence_signal_timestamp(fence, timestamp);
return fence;
}
diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
index 2a594b754af1..38b4110378de 100644
--- a/drivers/dma-buf/dma-resv.c
+++ b/drivers/dma-buf/dma-resv.c
@@ -571,6 +571,7 @@ int dma_resv_get_fences(struct dma_resv *obj, enum dma_resv_usage usage,
dma_resv_for_each_fence_unlocked(&cursor, fence) {
if (dma_resv_iter_is_restarted(&cursor)) {
+ struct dma_fence **new_fences;
unsigned int count;
while (*num_fences)
@@ -579,13 +580,17 @@ int dma_resv_get_fences(struct dma_resv *obj, enum dma_resv_usage usage,
count = cursor.num_fences + 1;
/* Eventually re-allocate the array */
- *fences = krealloc_array(*fences, count,
- sizeof(void *),
- GFP_KERNEL);
- if (count && !*fences) {
+ new_fences = krealloc_array(*fences, count,
+ sizeof(void *),
+ GFP_KERNEL);
+ if (count && !new_fences) {
+ kfree(*fences);
+ *fences = NULL;
+ *num_fences = 0;
dma_resv_iter_end(&cursor);
return -ENOMEM;
}
+ *fences = new_fences;
}
(*fences)[(*num_fences)++] = dma_fence_get(fence);
@@ -660,7 +665,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..f0a35277fd84 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);
@@ -191,6 +191,7 @@ static const struct dma_fence_ops timeline_fence_ops = {
*/
static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc)
{
+ LIST_HEAD(signalled);
struct sync_pt *pt, *next;
trace_sync_timeline(obj);
@@ -203,21 +204,20 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc)
if (!timeline_fence_signaled(&pt->base))
break;
- list_del_init(&pt->link);
+ dma_fence_get(&pt->base);
+
+ list_move_tail(&pt->link, &signalled);
rb_erase(&pt->node, &obj->pt_tree);
- /*
- * A signal callback may release the last reference to this
- * fence, causing it to be freed. That operation has to be
- * last to avoid a use after free inside this loop, and must
- * be after we remove the fence from the timeline in order to
- * prevent deadlocking on timeline->lock inside
- * timeline_fence_release().
- */
dma_fence_signal_locked(&pt->base);
}
spin_unlock_irq(&obj->lock);
+
+ list_for_each_entry_safe(pt, next, &signalled, link) {
+ list_del_init(&pt->link);
+ dma_fence_put(&pt->base);
+ }
}
/**
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index f5f422f9b850..08fdd0e2ed1b 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -211,6 +211,7 @@ config FSL_DMA
config FSL_EDMA
tristate "Freescale eDMA engine support"
depends on OF
+ depends on HAS_IOMEM
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
help
@@ -280,6 +281,7 @@ config IMX_SDMA
config INTEL_IDMA64
tristate "Intel integrated DMA 64-bit support"
+ depends on HAS_IOMEM
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
help
@@ -553,6 +555,7 @@ config STE_DMA40
bool "ST-Ericsson DMA40 support"
depends on ARCH_U8500
select DMA_ENGINE
+ select SRAM
help
Support for ST-Ericsson DMA40 controller
diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index a812b9b00e6b..fc7cdad37161 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -963,7 +963,6 @@ static int axi_dmac_probe(struct platform_device *pdev)
dma_dev->device_terminate_all = axi_dmac_terminate_all;
dma_dev->device_synchronize = axi_dmac_synchronize;
dma_dev->dev = &pdev->dev;
- dma_dev->chancnt = 1;
dma_dev->src_addr_widths = BIT(dmac->chan.src_width);
dma_dev->dst_addr_widths = BIT(dmac->chan.dest_width);
dma_dev->directions = BIT(dmac->chan.direction);
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
index 6937cc0c0b65..796b6caf0bab 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
@@ -1466,7 +1466,6 @@ static int dw_probe(struct platform_device *pdev)
dma_cap_set(DMA_CYCLIC, dw->dma.cap_mask);
/* DMA capabilities */
- dw->dma.chancnt = hdata->nr_channels;
dw->dma.max_burst = hdata->axi_rw_burst_len;
dw->dma.src_addr_widths = AXI_DMA_BUSWIDTHS;
dw->dma.dst_addr_widths = AXI_DMA_BUSWIDTHS;
diff --git a/drivers/dma/dw-edma/Makefile b/drivers/dma/dw-edma/Makefile
index 8d45c0d5689d..83ab58f87760 100644
--- a/drivers/dma/dw-edma/Makefile
+++ b/drivers/dma/dw-edma/Makefile
@@ -1,7 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_DW_EDMA) += dw-edma.o
-dw-edma-$(CONFIG_DEBUG_FS) := dw-edma-v0-debugfs.o
-dw-edma-objs := dw-edma-core.o \
- dw-edma-v0-core.o $(dw-edma-y)
+dw-edma-$(CONFIG_DEBUG_FS) := dw-edma-v0-debugfs.o \
+ dw-hdma-v0-debugfs.o
+dw-edma-objs := dw-edma-core.o \
+ dw-edma-v0-core.o \
+ dw-hdma-v0-core.o $(dw-edma-y)
obj-$(CONFIG_DW_EDMA_PCIE) += dw-edma-pcie.o
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index 7d2b73ef0872..68236247059d 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -18,6 +18,7 @@
#include "dw-edma-core.h"
#include "dw-edma-v0-core.h"
+#include "dw-hdma-v0-core.h"
#include "../dmaengine.h"
#include "../virt-dma.h"
@@ -183,6 +184,7 @@ static void vchan_free_desc(struct virt_dma_desc *vdesc)
static int dw_edma_start_transfer(struct dw_edma_chan *chan)
{
+ struct dw_edma *dw = chan->dw;
struct dw_edma_chunk *child;
struct dw_edma_desc *desc;
struct virt_dma_desc *vd;
@@ -200,7 +202,7 @@ static int dw_edma_start_transfer(struct dw_edma_chan *chan)
if (!child)
return 0;
- dw_edma_v0_core_start(child, !desc->xfer_sz);
+ dw_edma_core_start(dw, child, !desc->xfer_sz);
desc->xfer_sz += child->ll_region.sz;
dw_edma_free_burst(child);
list_del(&child->list);
@@ -287,7 +289,7 @@ static int dw_edma_device_terminate_all(struct dma_chan *dchan)
chan->configured = false;
} else if (chan->status == EDMA_ST_IDLE) {
chan->configured = false;
- } else if (dw_edma_v0_core_ch_status(chan) == DMA_COMPLETE) {
+ } else if (dw_edma_core_ch_status(chan) == DMA_COMPLETE) {
/*
* The channel is in a false BUSY state, probably didn't
* receive or lost an interrupt
@@ -599,8 +601,6 @@ static void dw_edma_done_interrupt(struct dw_edma_chan *chan)
struct virt_dma_desc *vd;
unsigned long flags;
- dw_edma_v0_core_clear_done_int(chan);
-
spin_lock_irqsave(&chan->vc.lock, flags);
vd = vchan_next_desc(&chan->vc);
if (vd) {
@@ -641,8 +641,6 @@ static void dw_edma_abort_interrupt(struct dw_edma_chan *chan)
struct virt_dma_desc *vd;
unsigned long flags;
- dw_edma_v0_core_clear_abort_int(chan);
-
spin_lock_irqsave(&chan->vc.lock, flags);
vd = vchan_next_desc(&chan->vc);
if (vd) {
@@ -654,63 +652,32 @@ static void dw_edma_abort_interrupt(struct dw_edma_chan *chan)
chan->status = EDMA_ST_IDLE;
}
-static irqreturn_t dw_edma_interrupt(int irq, void *data, bool write)
+static inline irqreturn_t dw_edma_interrupt_write(int irq, void *data)
{
struct dw_edma_irq *dw_irq = data;
- struct dw_edma *dw = dw_irq->dw;
- unsigned long total, pos, val;
- unsigned long off;
- u32 mask;
-
- if (write) {
- total = dw->wr_ch_cnt;
- off = 0;
- mask = dw_irq->wr_mask;
- } else {
- total = dw->rd_ch_cnt;
- off = dw->wr_ch_cnt;
- mask = dw_irq->rd_mask;
- }
-
- val = dw_edma_v0_core_status_done_int(dw, write ?
- EDMA_DIR_WRITE :
- EDMA_DIR_READ);
- val &= mask;
- for_each_set_bit(pos, &val, total) {
- struct dw_edma_chan *chan = &dw->chan[pos + off];
-
- dw_edma_done_interrupt(chan);
- }
-
- val = dw_edma_v0_core_status_abort_int(dw, write ?
- EDMA_DIR_WRITE :
- EDMA_DIR_READ);
- val &= mask;
- for_each_set_bit(pos, &val, total) {
- struct dw_edma_chan *chan = &dw->chan[pos + off];
-
- dw_edma_abort_interrupt(chan);
- }
- return IRQ_HANDLED;
-}
-
-static inline irqreturn_t dw_edma_interrupt_write(int irq, void *data)
-{
- return dw_edma_interrupt(irq, data, true);
+ return dw_edma_core_handle_int(dw_irq, EDMA_DIR_WRITE,
+ dw_edma_done_interrupt,
+ dw_edma_abort_interrupt);
}
static inline irqreturn_t dw_edma_interrupt_read(int irq, void *data)
{
- return dw_edma_interrupt(irq, data, false);
+ struct dw_edma_irq *dw_irq = data;
+
+ return dw_edma_core_handle_int(dw_irq, EDMA_DIR_READ,
+ dw_edma_done_interrupt,
+ dw_edma_abort_interrupt);
}
static irqreturn_t dw_edma_interrupt_common(int irq, void *data)
{
- dw_edma_interrupt(irq, data, true);
- dw_edma_interrupt(irq, data, false);
+ irqreturn_t ret = IRQ_NONE;
+
+ ret |= dw_edma_interrupt_write(irq, data);
+ ret |= dw_edma_interrupt_read(irq, data);
- return IRQ_HANDLED;
+ return ret;
}
static int dw_edma_alloc_chan_resources(struct dma_chan *dchan)
@@ -811,7 +778,7 @@ static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc)
vchan_init(&chan->vc, dma);
- dw_edma_v0_core_device_config(chan);
+ dw_edma_core_ch_config(chan);
}
/* Set DMA channel capabilities */
@@ -956,14 +923,19 @@ int dw_edma_probe(struct dw_edma_chip *chip)
dw->chip = chip;
+ if (dw->chip->mf == EDMA_MF_HDMA_NATIVE)
+ dw_hdma_v0_core_register(dw);
+ else
+ dw_edma_v0_core_register(dw);
+
raw_spin_lock_init(&dw->lock);
dw->wr_ch_cnt = min_t(u16, chip->ll_wr_cnt,
- dw_edma_v0_core_ch_count(dw, EDMA_DIR_WRITE));
+ dw_edma_core_ch_count(dw, EDMA_DIR_WRITE));
dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt, EDMA_MAX_WR_CH);
dw->rd_ch_cnt = min_t(u16, chip->ll_rd_cnt,
- dw_edma_v0_core_ch_count(dw, EDMA_DIR_READ));
+ dw_edma_core_ch_count(dw, EDMA_DIR_READ));
dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt, EDMA_MAX_RD_CH);
if (!dw->wr_ch_cnt && !dw->rd_ch_cnt)
@@ -982,7 +954,7 @@ int dw_edma_probe(struct dw_edma_chip *chip)
dev_name(chip->dev));
/* Disable eDMA, only to establish the ideal initial conditions */
- dw_edma_v0_core_off(dw);
+ dw_edma_core_off(dw);
/* Request IRQs */
err = dw_edma_irq_request(dw, &wr_alloc, &rd_alloc);
@@ -995,7 +967,7 @@ int dw_edma_probe(struct dw_edma_chip *chip)
goto err_irq_free;
/* Turn debugfs on */
- dw_edma_v0_core_debugfs_on(dw);
+ dw_edma_core_debugfs_on(dw);
chip->dw = dw;
@@ -1021,7 +993,7 @@ int dw_edma_remove(struct dw_edma_chip *chip)
return -ENODEV;
/* Disable eDMA */
- dw_edma_v0_core_off(dw);
+ dw_edma_core_off(dw);
/* Free irqs */
for (i = (dw->nr_irqs - 1); i >= 0; i--)
diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h
index 0ab2b6dba880..71894b9e0b15 100644
--- a/drivers/dma/dw-edma/dw-edma-core.h
+++ b/drivers/dma/dw-edma/dw-edma-core.h
@@ -111,6 +111,21 @@ struct dw_edma {
raw_spinlock_t lock; /* Only for legacy */
struct dw_edma_chip *chip;
+
+ const struct dw_edma_core_ops *core;
+};
+
+typedef void (*dw_edma_handler_t)(struct dw_edma_chan *);
+
+struct dw_edma_core_ops {
+ void (*off)(struct dw_edma *dw);
+ u16 (*ch_count)(struct dw_edma *dw, enum dw_edma_dir dir);
+ enum dma_status (*ch_status)(struct dw_edma_chan *chan);
+ irqreturn_t (*handle_int)(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir,
+ dw_edma_handler_t done, dw_edma_handler_t abort);
+ void (*start)(struct dw_edma_chunk *chunk, bool first);
+ void (*ch_config)(struct dw_edma_chan *chan);
+ void (*debugfs_on)(struct dw_edma *dw);
};
struct dw_edma_sg {
@@ -148,4 +163,47 @@ struct dw_edma_chan *dchan2dw_edma_chan(struct dma_chan *dchan)
return vc2dw_edma_chan(to_virt_chan(dchan));
}
+static inline
+void dw_edma_core_off(struct dw_edma *dw)
+{
+ dw->core->off(dw);
+}
+
+static inline
+u16 dw_edma_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)
+{
+ return dw->core->ch_count(dw, dir);
+}
+
+static inline
+enum dma_status dw_edma_core_ch_status(struct dw_edma_chan *chan)
+{
+ return chan->dw->core->ch_status(chan);
+}
+
+static inline irqreturn_t
+dw_edma_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir,
+ dw_edma_handler_t done, dw_edma_handler_t abort)
+{
+ return dw_irq->dw->core->handle_int(dw_irq, dir, done, abort);
+}
+
+static inline
+void dw_edma_core_start(struct dw_edma *dw, struct dw_edma_chunk *chunk, bool first)
+{
+ dw->core->start(chunk, first);
+}
+
+static inline
+void dw_edma_core_ch_config(struct dw_edma_chan *chan)
+{
+ chan->dw->core->ch_config(chan);
+}
+
+static inline
+void dw_edma_core_debugfs_on(struct dw_edma *dw)
+{
+ dw->core->debugfs_on(dw);
+}
+
#endif /* _DW_EDMA_CORE_H */
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index 2b40f2b44f5e..1c6043751dc9 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -109,7 +109,7 @@ static u64 dw_edma_pcie_address(struct device *dev, phys_addr_t cpu_addr)
return region.start;
}
-static const struct dw_edma_core_ops dw_edma_pcie_core_ops = {
+static const struct dw_edma_plat_ops dw_edma_pcie_plat_ops = {
.irq_vector = dw_edma_pcie_irq_vector,
.pci_address = dw_edma_pcie_address,
};
@@ -225,7 +225,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
chip->mf = vsec_data.mf;
chip->nr_irqs = nr_irqs;
- chip->ops = &dw_edma_pcie_core_ops;
+ chip->ops = &dw_edma_pcie_plat_ops;
chip->ll_wr_cnt = vsec_data.wr_ch_cnt;
chip->ll_rd_cnt = vsec_data.rd_ch_cnt;
diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
index 32f834a3848a..b38786f0ad79 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
@@ -7,7 +7,7 @@
*/
#include <linux/bitfield.h>
-
+#include <linux/irqreturn.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include "dw-edma-core.h"
@@ -160,7 +160,7 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
readl_ch(dw, dir, ch, &(__dw_ch_regs(dw, dir, ch)->name))
/* eDMA management callbacks */
-void dw_edma_v0_core_off(struct dw_edma *dw)
+static void dw_edma_v0_core_off(struct dw_edma *dw)
{
SET_BOTH_32(dw, int_mask,
EDMA_V0_DONE_INT_MASK | EDMA_V0_ABORT_INT_MASK);
@@ -169,7 +169,7 @@ void dw_edma_v0_core_off(struct dw_edma *dw)
SET_BOTH_32(dw, engine_en, 0);
}
-u16 dw_edma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)
+static u16 dw_edma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)
{
u32 num_ch;
@@ -186,7 +186,7 @@ u16 dw_edma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)
return (u16)num_ch;
}
-enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)
+static enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)
{
struct dw_edma *dw = chan->dw;
u32 tmp;
@@ -202,7 +202,7 @@ enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)
return DMA_ERROR;
}
-void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan)
+static void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan)
{
struct dw_edma *dw = chan->dw;
@@ -210,7 +210,7 @@ void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan)
FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id)));
}
-void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan)
+static void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan)
{
struct dw_edma *dw = chan->dw;
@@ -218,18 +218,64 @@ void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan)
FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id)));
}
-u32 dw_edma_v0_core_status_done_int(struct dw_edma *dw, enum dw_edma_dir dir)
+static u32 dw_edma_v0_core_status_done_int(struct dw_edma *dw, enum dw_edma_dir dir)
{
return FIELD_GET(EDMA_V0_DONE_INT_MASK,
GET_RW_32(dw, dir, int_status));
}
-u32 dw_edma_v0_core_status_abort_int(struct dw_edma *dw, enum dw_edma_dir dir)
+static u32 dw_edma_v0_core_status_abort_int(struct dw_edma *dw, enum dw_edma_dir dir)
{
return FIELD_GET(EDMA_V0_ABORT_INT_MASK,
GET_RW_32(dw, dir, int_status));
}
+static irqreturn_t
+dw_edma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir,
+ dw_edma_handler_t done, dw_edma_handler_t abort)
+{
+ struct dw_edma *dw = dw_irq->dw;
+ unsigned long total, pos, val;
+ irqreturn_t ret = IRQ_NONE;
+ struct dw_edma_chan *chan;
+ unsigned long off;
+ u32 mask;
+
+ if (dir == EDMA_DIR_WRITE) {
+ total = dw->wr_ch_cnt;
+ off = 0;
+ mask = dw_irq->wr_mask;
+ } else {
+ total = dw->rd_ch_cnt;
+ off = dw->wr_ch_cnt;
+ mask = dw_irq->rd_mask;
+ }
+
+ val = dw_edma_v0_core_status_done_int(dw, dir);
+ val &= mask;
+ for_each_set_bit(pos, &val, total) {
+ chan = &dw->chan[pos + off];
+
+ dw_edma_v0_core_clear_done_int(chan);
+ done(chan);
+
+ ret = IRQ_HANDLED;
+ }
+
+ val = dw_edma_v0_core_status_abort_int(dw, dir);
+ val &= mask;
+ for_each_set_bit(pos, &val, total) {
+ chan = &dw->chan[pos + off];
+
+ dw_edma_v0_core_clear_abort_int(chan);
+ abort(chan);
+
+ ret = IRQ_HANDLED;
+ }
+
+ return ret;
+}
+
static void dw_edma_v0_write_ll_data(struct dw_edma_chunk *chunk, int i,
u32 control, u32 size, u64 sar, u64 dar)
{
@@ -300,7 +346,7 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
dw_edma_v0_write_ll_link(chunk, i, control, chunk->ll_region.paddr);
}
-void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
+static void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
{
struct dw_edma_chan *chan = chunk->chan;
struct dw_edma *dw = chan->dw;
@@ -371,7 +417,7 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
FIELD_PREP(EDMA_V0_DOORBELL_CH_MASK, chan->id));
}
-int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)
+static void dw_edma_v0_core_ch_config(struct dw_edma_chan *chan)
{
struct dw_edma *dw = chan->dw;
u32 tmp = 0;
@@ -438,12 +484,25 @@ int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)
SET_RW_32(dw, chan->dir, ch67_imwr_data, tmp);
break;
}
-
- return 0;
}
/* eDMA debugfs callbacks */
-void dw_edma_v0_core_debugfs_on(struct dw_edma *dw)
+static void dw_edma_v0_core_debugfs_on(struct dw_edma *dw)
{
dw_edma_v0_debugfs_on(dw);
}
+
+static const struct dw_edma_core_ops dw_edma_v0_core = {
+ .off = dw_edma_v0_core_off,
+ .ch_count = dw_edma_v0_core_ch_count,
+ .ch_status = dw_edma_v0_core_ch_status,
+ .handle_int = dw_edma_v0_core_handle_int,
+ .start = dw_edma_v0_core_start,
+ .ch_config = dw_edma_v0_core_ch_config,
+ .debugfs_on = dw_edma_v0_core_debugfs_on,
+};
+
+void dw_edma_v0_core_register(struct dw_edma *dw)
+{
+ dw->core = &dw_edma_v0_core;
+}
diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.h b/drivers/dma/dw-edma/dw-edma-v0-core.h
index ab96a1f48080..04a882222f99 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-core.h
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.h
@@ -11,17 +11,7 @@
#include <linux/dma/edma.h>
-/* eDMA management callbacks */
-void dw_edma_v0_core_off(struct dw_edma *chan);
-u16 dw_edma_v0_core_ch_count(struct dw_edma *chan, enum dw_edma_dir dir);
-enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan);
-void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan);
-void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan);
-u32 dw_edma_v0_core_status_done_int(struct dw_edma *chan, enum dw_edma_dir dir);
-u32 dw_edma_v0_core_status_abort_int(struct dw_edma *chan, enum dw_edma_dir dir);
-void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first);
-int dw_edma_v0_core_device_config(struct dw_edma_chan *chan);
-/* eDMA debug fs callbacks */
-void dw_edma_v0_core_debugfs_on(struct dw_edma *dw);
+/* eDMA core register */
+void dw_edma_v0_core_register(struct dw_edma *dw);
#endif /* _DW_EDMA_V0_CORE_H */
diff --git a/drivers/dma/dw-edma/dw-hdma-v0-core.c b/drivers/dma/dw-edma/dw-hdma-v0-core.c
new file mode 100644
index 000000000000..00b735a0202a
--- /dev/null
+++ b/drivers/dma/dw-edma/dw-hdma-v0-core.c
@@ -0,0 +1,296 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 Cai Huoqing
+ * Synopsys DesignWare HDMA v0 core
+ */
+
+#include <linux/bitfield.h>
+#include <linux/irqreturn.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+
+#include "dw-edma-core.h"
+#include "dw-hdma-v0-core.h"
+#include "dw-hdma-v0-regs.h"
+#include "dw-hdma-v0-debugfs.h"
+
+enum dw_hdma_control {
+ DW_HDMA_V0_CB = BIT(0),
+ DW_HDMA_V0_TCB = BIT(1),
+ DW_HDMA_V0_LLP = BIT(2),
+ DW_HDMA_V0_LIE = BIT(3),
+ DW_HDMA_V0_RIE = BIT(4),
+ DW_HDMA_V0_CCS = BIT(8),
+ DW_HDMA_V0_LLE = BIT(9),
+};
+
+static inline struct dw_hdma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
+{
+ return dw->chip->reg_base;
+}
+
+static inline struct dw_hdma_v0_ch_regs __iomem *
+__dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch)
+{
+ if (dir == EDMA_DIR_WRITE)
+ return &(__dw_regs(dw)->ch[ch].wr);
+ else
+ return &(__dw_regs(dw)->ch[ch].rd);
+}
+
+#define SET_CH_32(dw, dir, ch, name, value) \
+ writel(value, &(__dw_ch_regs(dw, dir, ch)->name))
+
+#define GET_CH_32(dw, dir, ch, name) \
+ readl(&(__dw_ch_regs(dw, dir, ch)->name))
+
+#define SET_BOTH_CH_32(dw, ch, name, value) \
+ do { \
+ writel(value, &(__dw_ch_regs(dw, EDMA_DIR_WRITE, ch)->name)); \
+ writel(value, &(__dw_ch_regs(dw, EDMA_DIR_READ, ch)->name)); \
+ } while (0)
+
+/* HDMA management callbacks */
+static void dw_hdma_v0_core_off(struct dw_edma *dw)
+{
+ int id;
+
+ for (id = 0; id < HDMA_V0_MAX_NR_CH; id++) {
+ SET_BOTH_CH_32(dw, id, int_setup,
+ HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK);
+ SET_BOTH_CH_32(dw, id, int_clear,
+ HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK);
+ SET_BOTH_CH_32(dw, id, ch_en, 0);
+ }
+}
+
+static u16 dw_hdma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)
+{
+ u32 num_ch = 0;
+ int id;
+
+ for (id = 0; id < HDMA_V0_MAX_NR_CH; id++) {
+ if (GET_CH_32(dw, id, dir, ch_en) & BIT(0))
+ num_ch++;
+ }
+
+ if (num_ch > HDMA_V0_MAX_NR_CH)
+ num_ch = HDMA_V0_MAX_NR_CH;
+
+ return (u16)num_ch;
+}
+
+static enum dma_status dw_hdma_v0_core_ch_status(struct dw_edma_chan *chan)
+{
+ struct dw_edma *dw = chan->dw;
+ u32 tmp;
+
+ tmp = FIELD_GET(HDMA_V0_CH_STATUS_MASK,
+ GET_CH_32(dw, chan->id, chan->dir, ch_stat));
+
+ if (tmp == 1)
+ return DMA_IN_PROGRESS;
+ else if (tmp == 3)
+ return DMA_COMPLETE;
+ else
+ return DMA_ERROR;
+}
+
+static void dw_hdma_v0_core_clear_done_int(struct dw_edma_chan *chan)
+{
+ struct dw_edma *dw = chan->dw;
+
+ SET_CH_32(dw, chan->dir, chan->id, int_clear, HDMA_V0_STOP_INT_MASK);
+}
+
+static void dw_hdma_v0_core_clear_abort_int(struct dw_edma_chan *chan)
+{
+ struct dw_edma *dw = chan->dw;
+
+ SET_CH_32(dw, chan->dir, chan->id, int_clear, HDMA_V0_ABORT_INT_MASK);
+}
+
+static u32 dw_hdma_v0_core_status_int(struct dw_edma_chan *chan)
+{
+ struct dw_edma *dw = chan->dw;
+
+ return GET_CH_32(dw, chan->dir, chan->id, int_stat);
+}
+
+static irqreturn_t
+dw_hdma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir,
+ dw_edma_handler_t done, dw_edma_handler_t abort)
+{
+ struct dw_edma *dw = dw_irq->dw;
+ unsigned long total, pos, val;
+ irqreturn_t ret = IRQ_NONE;
+ struct dw_edma_chan *chan;
+ unsigned long off, mask;
+
+ if (dir == EDMA_DIR_WRITE) {
+ total = dw->wr_ch_cnt;
+ off = 0;
+ mask = dw_irq->wr_mask;
+ } else {
+ total = dw->rd_ch_cnt;
+ off = dw->wr_ch_cnt;
+ mask = dw_irq->rd_mask;
+ }
+
+ for_each_set_bit(pos, &mask, total) {
+ chan = &dw->chan[pos + off];
+
+ val = dw_hdma_v0_core_status_int(chan);
+ if (FIELD_GET(HDMA_V0_STOP_INT_MASK, val)) {
+ dw_hdma_v0_core_clear_done_int(chan);
+ done(chan);
+
+ ret = IRQ_HANDLED;
+ }
+
+ if (FIELD_GET(HDMA_V0_ABORT_INT_MASK, val)) {
+ dw_hdma_v0_core_clear_abort_int(chan);
+ abort(chan);
+
+ ret = IRQ_HANDLED;
+ }
+ }
+
+ return ret;
+}
+
+static void dw_hdma_v0_write_ll_data(struct dw_edma_chunk *chunk, int i,
+ u32 control, u32 size, u64 sar, u64 dar)
+{
+ ptrdiff_t ofs = i * sizeof(struct dw_hdma_v0_lli);
+
+ if (chunk->chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) {
+ struct dw_hdma_v0_lli *lli = chunk->ll_region.vaddr.mem + ofs;
+
+ lli->control = control;
+ lli->transfer_size = size;
+ lli->sar.reg = sar;
+ lli->dar.reg = dar;
+ } else {
+ struct dw_hdma_v0_lli __iomem *lli = chunk->ll_region.vaddr.io + ofs;
+
+ writel(control, &lli->control);
+ writel(size, &lli->transfer_size);
+ writeq(sar, &lli->sar.reg);
+ writeq(dar, &lli->dar.reg);
+ }
+}
+
+static void dw_hdma_v0_write_ll_link(struct dw_edma_chunk *chunk,
+ int i, u32 control, u64 pointer)
+{
+ ptrdiff_t ofs = i * sizeof(struct dw_hdma_v0_lli);
+
+ if (chunk->chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) {
+ struct dw_hdma_v0_llp *llp = chunk->ll_region.vaddr.mem + ofs;
+
+ llp->control = control;
+ llp->llp.reg = pointer;
+ } else {
+ struct dw_hdma_v0_llp __iomem *llp = chunk->ll_region.vaddr.io + ofs;
+
+ writel(control, &llp->control);
+ writeq(pointer, &llp->llp.reg);
+ }
+}
+
+static void dw_hdma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
+{
+ struct dw_edma_burst *child;
+ struct dw_edma_chan *chan = chunk->chan;
+ u32 control = 0, i = 0;
+ int j;
+
+ if (chunk->cb)
+ control = DW_HDMA_V0_CB;
+
+ j = chunk->bursts_alloc;
+ list_for_each_entry(child, &chunk->burst->list, list) {
+ j--;
+ if (!j) {
+ control |= DW_HDMA_V0_LIE;
+ if (!(chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL))
+ control |= DW_HDMA_V0_RIE;
+ }
+
+ dw_hdma_v0_write_ll_data(chunk, i++, control, child->sz,
+ child->sar, child->dar);
+ }
+
+ control = DW_HDMA_V0_LLP | DW_HDMA_V0_TCB;
+ if (!chunk->cb)
+ control |= DW_HDMA_V0_CB;
+
+ dw_hdma_v0_write_ll_link(chunk, i, control, chunk->ll_region.paddr);
+}
+
+static void dw_hdma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
+{
+ struct dw_edma_chan *chan = chunk->chan;
+ struct dw_edma *dw = chan->dw;
+ u32 tmp;
+
+ dw_hdma_v0_core_write_chunk(chunk);
+
+ if (first) {
+ /* Enable engine */
+ SET_CH_32(dw, chan->dir, chan->id, ch_en, BIT(0));
+ /* Interrupt enable&unmask - done, abort */
+ tmp = GET_CH_32(dw, chan->dir, chan->id, int_setup) |
+ HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK |
+ HDMA_V0_LOCAL_STOP_INT_EN | HDMA_V0_LOCAL_STOP_INT_EN;
+ SET_CH_32(dw, chan->dir, chan->id, int_setup, tmp);
+ /* Channel control */
+ SET_CH_32(dw, chan->dir, chan->id, control1, HDMA_V0_LINKLIST_EN);
+ /* Linked list */
+ /* llp is not aligned on 64bit -> keep 32bit accesses */
+ SET_CH_32(dw, chan->dir, chan->id, llp.lsb,
+ lower_32_bits(chunk->ll_region.paddr));
+ SET_CH_32(dw, chan->dir, chan->id, llp.msb,
+ upper_32_bits(chunk->ll_region.paddr));
+ }
+ /* Set consumer cycle */
+ SET_CH_32(dw, chan->dir, chan->id, cycle_sync,
+ HDMA_V0_CONSUMER_CYCLE_STAT | HDMA_V0_CONSUMER_CYCLE_BIT);
+ /* Doorbell */
+ SET_CH_32(dw, chan->dir, chan->id, doorbell, HDMA_V0_DOORBELL_START);
+}
+
+static void dw_hdma_v0_core_ch_config(struct dw_edma_chan *chan)
+{
+ struct dw_edma *dw = chan->dw;
+
+ /* MSI done addr - low, high */
+ SET_CH_32(dw, chan->dir, chan->id, msi_stop.lsb, chan->msi.address_lo);
+ SET_CH_32(dw, chan->dir, chan->id, msi_stop.msb, chan->msi.address_hi);
+ /* MSI abort addr - low, high */
+ SET_CH_32(dw, chan->dir, chan->id, msi_abort.lsb, chan->msi.address_lo);
+ SET_CH_32(dw, chan->dir, chan->id, msi_abort.msb, chan->msi.address_hi);
+ /* config MSI data */
+ SET_CH_32(dw, chan->dir, chan->id, msi_msgdata, chan->msi.data);
+}
+
+/* HDMA debugfs callbacks */
+static void dw_hdma_v0_core_debugfs_on(struct dw_edma *dw)
+{
+ dw_hdma_v0_debugfs_on(dw);
+}
+
+static const struct dw_edma_core_ops dw_hdma_v0_core = {
+ .off = dw_hdma_v0_core_off,
+ .ch_count = dw_hdma_v0_core_ch_count,
+ .ch_status = dw_hdma_v0_core_ch_status,
+ .handle_int = dw_hdma_v0_core_handle_int,
+ .start = dw_hdma_v0_core_start,
+ .ch_config = dw_hdma_v0_core_ch_config,
+ .debugfs_on = dw_hdma_v0_core_debugfs_on,
+};
+
+void dw_hdma_v0_core_register(struct dw_edma *dw)
+{
+ dw->core = &dw_hdma_v0_core;
+}
diff --git a/drivers/dma/dw-edma/dw-hdma-v0-core.h b/drivers/dma/dw-edma/dw-hdma-v0-core.h
new file mode 100644
index 000000000000..c373b4f0bd8a
--- /dev/null
+++ b/drivers/dma/dw-edma/dw-hdma-v0-core.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 Cai Huoqing
+ * Synopsys DesignWare HDMA v0 core
+ *
+ * Author: Cai Huoqing <cai.huoqing@linux.dev>
+ */
+
+#ifndef _DW_HDMA_V0_CORE_H
+#define _DW_HDMA_V0_CORE_H
+
+#include <linux/dma/edma.h>
+
+/* HDMA core register */
+void dw_hdma_v0_core_register(struct dw_edma *dw);
+
+#endif /* _DW_HDMA_V0_CORE_H */
diff --git a/drivers/dma/dw-edma/dw-hdma-v0-debugfs.c b/drivers/dma/dw-edma/dw-hdma-v0-debugfs.c
new file mode 100644
index 000000000000..520c81978b08
--- /dev/null
+++ b/drivers/dma/dw-edma/dw-hdma-v0-debugfs.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 Cai Huoqing
+ * Synopsys DesignWare HDMA v0 debugfs
+ *
+ * Author: Cai Huoqing <cai.huoqing@linux.dev>
+ */
+
+#include <linux/debugfs.h>
+#include <linux/bitfield.h>
+
+#include "dw-hdma-v0-debugfs.h"
+#include "dw-hdma-v0-regs.h"
+#include "dw-edma-core.h"
+
+#define REGS_ADDR(dw, name) \
+ ({ \
+ struct dw_hdma_v0_regs __iomem *__regs = (dw)->chip->reg_base; \
+ \
+ (void __iomem *)&__regs->name; \
+ })
+
+#define REGS_CH_ADDR(dw, name, _dir, _ch) \
+ ({ \
+ struct dw_hdma_v0_ch_regs __iomem *__ch_regs; \
+ \
+ if (_dir == EDMA_DIR_READ) \
+ __ch_regs = REGS_ADDR(dw, ch[_ch].rd); \
+ else \
+ __ch_regs = REGS_ADDR(dw, ch[_ch].wr); \
+ \
+ (void __iomem *)&__ch_regs->name; \
+ })
+
+#define CTX_REGISTER(dw, name, dir, ch) \
+ {#name, REGS_CH_ADDR(dw, name, dir, ch)}
+
+#define WRITE_STR "write"
+#define READ_STR "read"
+#define CHANNEL_STR "channel"
+#define REGISTERS_STR "registers"
+
+struct dw_hdma_debugfs_entry {
+ const char *name;
+ void __iomem *reg;
+};
+
+static int dw_hdma_debugfs_u32_get(void *data, u64 *val)
+{
+ struct dw_hdma_debugfs_entry *entry = data;
+ void __iomem *reg = entry->reg;
+
+ *val = readl(reg);
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(fops_x32, dw_hdma_debugfs_u32_get, NULL, "0x%08llx\n");
+
+static void dw_hdma_debugfs_create_x32(struct dw_edma *dw,
+ const struct dw_hdma_debugfs_entry ini[],
+ int nr_entries, struct dentry *dent)
+{
+ struct dw_hdma_debugfs_entry *entries;
+ int i;
+
+ entries = devm_kcalloc(dw->chip->dev, nr_entries, sizeof(*entries),
+ GFP_KERNEL);
+ if (!entries)
+ return;
+
+ for (i = 0; i < nr_entries; i++) {
+ entries[i] = ini[i];
+
+ debugfs_create_file_unsafe(entries[i].name, 0444, dent,
+ &entries[i], &fops_x32);
+ }
+}
+
+static void dw_hdma_debugfs_regs_ch(struct dw_edma *dw, enum dw_edma_dir dir,
+ u16 ch, struct dentry *dent)
+{
+ const struct dw_hdma_debugfs_entry debugfs_regs[] = {
+ CTX_REGISTER(dw, ch_en, dir, ch),
+ CTX_REGISTER(dw, doorbell, dir, ch),
+ CTX_REGISTER(dw, prefetch, dir, ch),
+ CTX_REGISTER(dw, handshake, dir, ch),
+ CTX_REGISTER(dw, llp.lsb, dir, ch),
+ CTX_REGISTER(dw, llp.msb, dir, ch),
+ CTX_REGISTER(dw, cycle_sync, dir, ch),
+ CTX_REGISTER(dw, transfer_size, dir, ch),
+ CTX_REGISTER(dw, sar.lsb, dir, ch),
+ CTX_REGISTER(dw, sar.msb, dir, ch),
+ CTX_REGISTER(dw, dar.lsb, dir, ch),
+ CTX_REGISTER(dw, dar.msb, dir, ch),
+ CTX_REGISTER(dw, watermark_en, dir, ch),
+ CTX_REGISTER(dw, control1, dir, ch),
+ CTX_REGISTER(dw, func_num, dir, ch),
+ CTX_REGISTER(dw, qos, dir, ch),
+ CTX_REGISTER(dw, ch_stat, dir, ch),
+ CTX_REGISTER(dw, int_stat, dir, ch),
+ CTX_REGISTER(dw, int_setup, dir, ch),
+ CTX_REGISTER(dw, int_clear, dir, ch),
+ CTX_REGISTER(dw, msi_stop.lsb, dir, ch),
+ CTX_REGISTER(dw, msi_stop.msb, dir, ch),
+ CTX_REGISTER(dw, msi_watermark.lsb, dir, ch),
+ CTX_REGISTER(dw, msi_watermark.msb, dir, ch),
+ CTX_REGISTER(dw, msi_abort.lsb, dir, ch),
+ CTX_REGISTER(dw, msi_abort.msb, dir, ch),
+ CTX_REGISTER(dw, msi_msgdata, dir, ch),
+ };
+ int nr_entries = ARRAY_SIZE(debugfs_regs);
+
+ dw_hdma_debugfs_create_x32(dw, debugfs_regs, nr_entries, dent);
+}
+
+static void dw_hdma_debugfs_regs_wr(struct dw_edma *dw, struct dentry *dent)
+{
+ struct dentry *regs_dent, *ch_dent;
+ char name[16];
+ int i;
+
+ regs_dent = debugfs_create_dir(WRITE_STR, dent);
+
+ for (i = 0; i < dw->wr_ch_cnt; i++) {
+ snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i);
+
+ ch_dent = debugfs_create_dir(name, regs_dent);
+
+ dw_hdma_debugfs_regs_ch(dw, EDMA_DIR_WRITE, i, ch_dent);
+ }
+}
+
+static void dw_hdma_debugfs_regs_rd(struct dw_edma *dw, struct dentry *dent)
+{
+ struct dentry *regs_dent, *ch_dent;
+ char name[16];
+ int i;
+
+ regs_dent = debugfs_create_dir(READ_STR, dent);
+
+ for (i = 0; i < dw->rd_ch_cnt; i++) {
+ snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i);
+
+ ch_dent = debugfs_create_dir(name, regs_dent);
+
+ dw_hdma_debugfs_regs_ch(dw, EDMA_DIR_READ, i, ch_dent);
+ }
+}
+
+static void dw_hdma_debugfs_regs(struct dw_edma *dw)
+{
+ struct dentry *regs_dent;
+
+ regs_dent = debugfs_create_dir(REGISTERS_STR, dw->dma.dbg_dev_root);
+
+ dw_hdma_debugfs_regs_wr(dw, regs_dent);
+ dw_hdma_debugfs_regs_rd(dw, regs_dent);
+}
+
+void dw_hdma_v0_debugfs_on(struct dw_edma *dw)
+{
+ if (!debugfs_initialized())
+ return;
+
+ debugfs_create_u32("mf", 0444, dw->dma.dbg_dev_root, &dw->chip->mf);
+ debugfs_create_u16("wr_ch_cnt", 0444, dw->dma.dbg_dev_root, &dw->wr_ch_cnt);
+ debugfs_create_u16("rd_ch_cnt", 0444, dw->dma.dbg_dev_root, &dw->rd_ch_cnt);
+
+ dw_hdma_debugfs_regs(dw);
+}
diff --git a/drivers/dma/dw-edma/dw-hdma-v0-debugfs.h b/drivers/dma/dw-edma/dw-hdma-v0-debugfs.h
new file mode 100644
index 000000000000..e6842c83777d
--- /dev/null
+++ b/drivers/dma/dw-edma/dw-hdma-v0-debugfs.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 Cai Huoqing
+ * Synopsys DesignWare HDMA v0 debugfs
+ *
+ * Author: Cai Huoqing <cai.huoqing@linux.dev>
+ */
+
+#ifndef _DW_HDMA_V0_DEBUG_FS_H
+#define _DW_HDMA_V0_DEBUG_FS_H
+
+#include <linux/dma/edma.h>
+
+#ifdef CONFIG_DEBUG_FS
+void dw_hdma_v0_debugfs_on(struct dw_edma *dw);
+#else
+static inline void dw_hdma_v0_debugfs_on(struct dw_edma *dw)
+{
+}
+#endif /* CONFIG_DEBUG_FS */
+
+#endif /* _DW_HDMA_V0_DEBUG_FS_H */
diff --git a/drivers/dma/dw-edma/dw-hdma-v0-regs.h b/drivers/dma/dw-edma/dw-hdma-v0-regs.h
new file mode 100644
index 000000000000..a974abdf8aaf
--- /dev/null
+++ b/drivers/dma/dw-edma/dw-hdma-v0-regs.h
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 Cai Huoqing
+ * Synopsys DesignWare HDMA v0 reg
+ *
+ * Author: Cai Huoqing <cai.huoqing@linux.dev>
+ */
+
+#ifndef _DW_HDMA_V0_REGS_H
+#define _DW_HDMA_V0_REGS_H
+
+#include <linux/dmaengine.h>
+
+#define HDMA_V0_MAX_NR_CH 8
+#define HDMA_V0_LOCAL_ABORT_INT_EN BIT(6)
+#define HDMA_V0_REMOTE_ABORT_INT_EN BIT(5)
+#define HDMA_V0_LOCAL_STOP_INT_EN BIT(4)
+#define HDMA_V0_REMOTEL_STOP_INT_EN BIT(3)
+#define HDMA_V0_ABORT_INT_MASK BIT(2)
+#define HDMA_V0_STOP_INT_MASK BIT(0)
+#define HDMA_V0_LINKLIST_EN BIT(0)
+#define HDMA_V0_CONSUMER_CYCLE_STAT BIT(1)
+#define HDMA_V0_CONSUMER_CYCLE_BIT BIT(0)
+#define HDMA_V0_DOORBELL_START BIT(0)
+#define HDMA_V0_CH_STATUS_MASK GENMASK(1, 0)
+
+struct dw_hdma_v0_ch_regs {
+ u32 ch_en; /* 0x0000 */
+ u32 doorbell; /* 0x0004 */
+ u32 prefetch; /* 0x0008 */
+ u32 handshake; /* 0x000c */
+ union {
+ u64 reg; /* 0x0010..0x0014 */
+ struct {
+ u32 lsb; /* 0x0010 */
+ u32 msb; /* 0x0014 */
+ };
+ } llp;
+ u32 cycle_sync; /* 0x0018 */
+ u32 transfer_size; /* 0x001c */
+ union {
+ u64 reg; /* 0x0020..0x0024 */
+ struct {
+ u32 lsb; /* 0x0020 */
+ u32 msb; /* 0x0024 */
+ };
+ } sar;
+ union {
+ u64 reg; /* 0x0028..0x002c */
+ struct {
+ u32 lsb; /* 0x0028 */
+ u32 msb; /* 0x002c */
+ };
+ } dar;
+ u32 watermark_en; /* 0x0030 */
+ u32 control1; /* 0x0034 */
+ u32 func_num; /* 0x0038 */
+ u32 qos; /* 0x003c */
+ u32 padding_1[16]; /* 0x0040..0x007c */
+ u32 ch_stat; /* 0x0080 */
+ u32 int_stat; /* 0x0084 */
+ u32 int_setup; /* 0x0088 */
+ u32 int_clear; /* 0x008c */
+ union {
+ u64 reg; /* 0x0090..0x0094 */
+ struct {
+ u32 lsb; /* 0x0090 */
+ u32 msb; /* 0x0094 */
+ };
+ } msi_stop;
+ union {
+ u64 reg; /* 0x0098..0x009c */
+ struct {
+ u32 lsb; /* 0x0098 */
+ u32 msb; /* 0x009c */
+ };
+ } msi_watermark;
+ union {
+ u64 reg; /* 0x00a0..0x00a4 */
+ struct {
+ u32 lsb; /* 0x00a0 */
+ u32 msb; /* 0x00a4 */
+ };
+ } msi_abort;
+ u32 msi_msgdata; /* 0x00a8 */
+ u32 padding_2[21]; /* 0x00ac..0x00fc */
+} __packed;
+
+struct dw_hdma_v0_ch {
+ struct dw_hdma_v0_ch_regs wr; /* 0x0000 */
+ struct dw_hdma_v0_ch_regs rd; /* 0x0100 */
+} __packed;
+
+struct dw_hdma_v0_regs {
+ struct dw_hdma_v0_ch ch[HDMA_V0_MAX_NR_CH]; /* 0x0000..0x0fa8 */
+} __packed;
+
+struct dw_hdma_v0_lli {
+ u32 control;
+ u32 transfer_size;
+ union {
+ u64 reg;
+ struct {
+ u32 lsb;
+ u32 msb;
+ };
+ } sar;
+ union {
+ u64 reg;
+ struct {
+ u32 lsb;
+ u32 msb;
+ };
+ } dar;
+} __packed;
+
+struct dw_hdma_v0_llp {
+ u32 control;
+ u32 reserved;
+ union {
+ u64 reg;
+ struct {
+ u32 lsb;
+ u32 msb;
+ };
+ } llp;
+} __packed;
+
+#endif /* _DW_HDMA_V0_REGS_H */
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/idxd/device.c b/drivers/dma/idxd/device.c
index 5abbcc61c528..9a15f0d12c79 100644
--- a/drivers/dma/idxd/device.c
+++ b/drivers/dma/idxd/device.c
@@ -384,9 +384,7 @@ static void idxd_wq_disable_cleanup(struct idxd_wq *wq)
wq->threshold = 0;
wq->priority = 0;
wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES;
- clear_bit(WQ_FLAG_DEDICATED, &wq->flags);
- clear_bit(WQ_FLAG_BLOCK_ON_FAULT, &wq->flags);
- clear_bit(WQ_FLAG_ATS_DISABLE, &wq->flags);
+ wq->flags = 0;
memset(wq->name, 0, WQ_NAME_SIZE);
wq->max_xfer_bytes = WQ_DEFAULT_MAX_XFER;
idxd_wq_set_max_batch_size(idxd->data->type, wq, WQ_DEFAULT_MAX_BATCH);
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/dma/mcf-edma.c b/drivers/dma/mcf-edma.c
index ebd8733f72ad..9413fad08a60 100644
--- a/drivers/dma/mcf-edma.c
+++ b/drivers/dma/mcf-edma.c
@@ -190,7 +190,13 @@ static int mcf_edma_probe(struct platform_device *pdev)
return -EINVAL;
}
- chans = pdata->dma_channels;
+ if (!pdata->dma_channels) {
+ dev_info(&pdev->dev, "setting default channel number to 64");
+ chans = 64;
+ } else {
+ chans = pdata->dma_channels;
+ }
+
len = sizeof(*mcf_edma) + sizeof(*mcf_chan) * chans;
mcf_edma = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
if (!mcf_edma)
@@ -202,11 +208,6 @@ static int mcf_edma_probe(struct platform_device *pdev)
mcf_edma->drvdata = &mcf_data;
mcf_edma->big_endian = 1;
- if (!mcf_edma->n_chans) {
- dev_info(&pdev->dev, "setting default channel number to 64");
- mcf_edma->n_chans = 64;
- }
-
mutex_init(&mcf_edma->fsl_edma_mutex);
mcf_edma->membase = devm_platform_ioremap_resource(pdev, 0);
diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c
index 95a462a1f511..b6e0ac8314e5 100644
--- a/drivers/dma/owl-dma.c
+++ b/drivers/dma/owl-dma.c
@@ -192,7 +192,7 @@ struct owl_dma_pchan {
};
/**
- * struct owl_dma_pchan - Wrapper for DMA ENGINE channel
+ * struct owl_dma_vchan - Wrapper for DMA ENGINE channel
* @vc: wrapped virtual channel
* @pchan: the physical channel utilized by this channel
* @txd: active transaction on this channel
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index b4731fe6bbc1..3cf0b38387ae 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -404,6 +404,12 @@ enum desc_status {
*/
BUSY,
/*
+ * Pause was called while descriptor was BUSY. Due to hardware
+ * limitations, only termination is possible for descriptors
+ * that have been paused.
+ */
+ PAUSED,
+ /*
* Sitting on the channel work_list but xfer done
* by PL330 core
*/
@@ -2041,7 +2047,7 @@ static inline void fill_queue(struct dma_pl330_chan *pch)
list_for_each_entry(desc, &pch->work_list, node) {
/* If already submitted */
- if (desc->status == BUSY)
+ if (desc->status == BUSY || desc->status == PAUSED)
continue;
ret = pl330_submit_req(pch->thread, desc);
@@ -2326,6 +2332,7 @@ static int pl330_pause(struct dma_chan *chan)
{
struct dma_pl330_chan *pch = to_pchan(chan);
struct pl330_dmac *pl330 = pch->dmac;
+ struct dma_pl330_desc *desc;
unsigned long flags;
pm_runtime_get_sync(pl330->ddma.dev);
@@ -2335,6 +2342,10 @@ static int pl330_pause(struct dma_chan *chan)
_stop(pch->thread);
spin_unlock(&pl330->lock);
+ list_for_each_entry(desc, &pch->work_list, node) {
+ if (desc->status == BUSY)
+ desc->status = PAUSED;
+ }
spin_unlock_irqrestore(&pch->lock, flags);
pm_runtime_mark_last_busy(pl330->ddma.dev);
pm_runtime_put_autosuspend(pl330->ddma.dev);
@@ -2425,7 +2436,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
else if (running && desc == running)
transferred =
pl330_get_current_xferred_count(pch, desc);
- else if (desc->status == BUSY)
+ else if (desc->status == BUSY || desc->status == PAUSED)
/*
* Busy but not running means either just enqueued,
* or finished and not yet marked done
@@ -2442,6 +2453,9 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
case DONE:
ret = DMA_COMPLETE;
break;
+ case PAUSED:
+ ret = DMA_PAUSED;
+ break;
case PREP:
case BUSY:
ret = DMA_IN_PROGRESS;
diff --git a/drivers/dma/plx_dma.c b/drivers/dma/plx_dma.c
index 12725fa1655f..34b6416c3287 100644
--- a/drivers/dma/plx_dma.c
+++ b/drivers/dma/plx_dma.c
@@ -517,7 +517,6 @@ static int plx_dma_create(struct pci_dev *pdev)
plxdev->bar = pcim_iomap_table(pdev)[0];
dma = &plxdev->dma_dev;
- dma->chancnt = 1;
INIT_LIST_HEAD(&dma->channels);
dma_cap_set(DMA_MEMCPY, dma->cap_mask);
dma->copy_align = DMAENGINE_ALIGN_1_BYTE;
diff --git a/drivers/dma/qcom/Kconfig b/drivers/dma/qcom/Kconfig
index 3f926a653bd8..ace75d7b835a 100644
--- a/drivers/dma/qcom/Kconfig
+++ b/drivers/dma/qcom/Kconfig
@@ -45,6 +45,7 @@ config QCOM_HIDMA_MGMT
config QCOM_HIDMA
tristate "Qualcomm Technologies HIDMA Channel support"
+ depends on HAS_IOMEM
select DMA_ENGINE
help
Enable support for the Qualcomm Technologies HIDMA controller.
diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c
index 1e47d27e1f81..4c3eb972039d 100644
--- a/drivers/dma/qcom/bam_dma.c
+++ b/drivers/dma/qcom/bam_dma.c
@@ -1272,7 +1272,15 @@ static int bam_dma_probe(struct platform_device *pdev)
bdev->powered_remotely = of_property_read_bool(pdev->dev.of_node,
"qcom,powered-remotely");
- if (bdev->controlled_remotely || bdev->powered_remotely) {
+ if (bdev->controlled_remotely || bdev->powered_remotely)
+ bdev->bamclk = devm_clk_get_optional(bdev->dev, "bam_clk");
+ else
+ bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk");
+
+ if (IS_ERR(bdev->bamclk))
+ return PTR_ERR(bdev->bamclk);
+
+ if (!bdev->bamclk) {
ret = of_property_read_u32(pdev->dev.of_node, "num-channels",
&bdev->num_channels);
if (ret)
@@ -1284,14 +1292,6 @@ static int bam_dma_probe(struct platform_device *pdev)
dev_err(bdev->dev, "num-ees unspecified in dt\n");
}
- if (bdev->controlled_remotely || bdev->powered_remotely)
- bdev->bamclk = devm_clk_get_optional(bdev->dev, "bam_clk");
- else
- bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk");
-
- if (IS_ERR(bdev->bamclk))
- return PTR_ERR(bdev->bamclk);
-
ret = clk_prepare_enable(bdev->bamclk);
if (ret) {
dev_err(bdev->dev, "failed to prepare/enable clock\n");
diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c
index 04d1c33afc12..344525c3a32f 100644
--- a/drivers/dma/qcom/hidma.c
+++ b/drivers/dma/qcom/hidma.c
@@ -214,7 +214,6 @@ static int hidma_chan_init(struct hidma_dev *dmadev, u32 dma_sig)
spin_lock_init(&mchan->lock);
list_add_tail(&mchan->chan.device_node, &ddev->channels);
- dmadev->ddev.chancnt++;
return 0;
}
diff --git a/drivers/dma/sprd-dma.c b/drivers/dma/sprd-dma.c
index 474d3ba8ec9f..2b639adb48ba 100644
--- a/drivers/dma/sprd-dma.c
+++ b/drivers/dma/sprd-dma.c
@@ -1169,7 +1169,6 @@ static int sprd_dma_probe(struct platform_device *pdev)
dma_cap_set(DMA_MEMCPY, sdev->dma_dev.cap_mask);
sdev->total_chns = chn_count;
- sdev->dma_dev.chancnt = chn_count;
INIT_LIST_HEAD(&sdev->dma_dev.channels);
INIT_LIST_HEAD(&sdev->dma_dev.global_node);
sdev->dma_dev.dev = &pdev->dev;
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index f093e08c23b1..825001bde42c 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -19,14 +19,43 @@
#include <linux/pm_runtime.h>
#include <linux/err.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/of_dma.h>
#include <linux/amba/bus.h>
#include <linux/regulator/consumer.h>
-#include <linux/platform_data/dma-ste-dma40.h>
#include "dmaengine.h"
+#include "ste_dma40.h"
#include "ste_dma40_ll.h"
+/**
+ * struct stedma40_platform_data - Configuration struct for the dma device.
+ *
+ * @dev_tx: mapping between destination event line and io address
+ * @dev_rx: mapping between source event line and io address
+ * @disabled_channels: A vector, ending with -1, that marks physical channels
+ * that are for different reasons not available for the driver.
+ * @soft_lli_chans: A vector, that marks physical channels will use LLI by SW
+ * which avoids HW bug that exists in some versions of the controller.
+ * SoftLLI introduces relink overhead that could impact performace for
+ * certain use cases.
+ * @num_of_soft_lli_chans: The number of channels that needs to be configured
+ * to use SoftLLI.
+ * @use_esram_lcla: flag for mapping the lcla into esram region
+ * @num_of_memcpy_chans: The number of channels reserved for memcpy.
+ * @num_of_phy_chans: The number of physical channels implemented in HW.
+ * 0 means reading the number of channels from DMA HW but this is only valid
+ * for 'multiple of 4' channels, like 8.
+ */
+struct stedma40_platform_data {
+ int disabled_channels[STEDMA40_MAX_PHYS];
+ int *soft_lli_chans;
+ int num_of_soft_lli_chans;
+ bool use_esram_lcla;
+ int num_of_memcpy_chans;
+ int num_of_phy_chans;
+};
+
#define D40_NAME "dma40"
#define D40_PHY_CHAN -1
@@ -107,7 +136,7 @@ static const struct stedma40_chan_cfg dma40_memcpy_conf_log = {
};
/**
- * enum 40_command - The different commands and/or statuses.
+ * enum d40_command - The different commands and/or statuses.
*
* @D40_DMA_STOP: DMA channel command STOP or status STOPPED,
* @D40_DMA_RUN: The DMA channel is RUNNING of the command RUN.
@@ -525,8 +554,6 @@ struct d40_gen_dmac {
* @virtbase: The virtual base address of the DMA's register.
* @rev: silicon revision detected.
* @clk: Pointer to the DMA clock structure.
- * @phy_start: Physical memory start of the DMA registers.
- * @phy_size: Size of the DMA register map.
* @irq: The IRQ number.
* @num_memcpy_chans: The number of channels used for memcpy (mem-to-mem
* transfers).
@@ -570,8 +597,6 @@ struct d40_base {
void __iomem *virtbase;
u8 rev:4;
struct clk *clk;
- phys_addr_t phy_start;
- resource_size_t phy_size;
int irq;
int num_memcpy_chans;
int num_phy_chans;
@@ -2268,7 +2293,7 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
return NULL;
}
-bool stedma40_filter(struct dma_chan *chan, void *data)
+static bool stedma40_filter(struct dma_chan *chan, void *data)
{
struct stedma40_chan_cfg *info = data;
struct d40_chan *d40c =
@@ -2287,7 +2312,6 @@ bool stedma40_filter(struct dma_chan *chan, void *data)
return err == 0;
}
-EXPORT_SYMBOL(stedma40_filter);
static void __d40_set_prio_rt(struct d40_chan *d40c, int dev_type, bool src)
{
@@ -3100,64 +3124,57 @@ static int __init d40_phy_res_init(struct d40_base *base)
return num_phy_chans_avail;
}
-static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
+/* Called from the registered devm action */
+static void d40_drop_kmem_cache_action(void *d)
+{
+ struct kmem_cache *desc_slab = d;
+
+ kmem_cache_destroy(desc_slab);
+}
+
+static int __init d40_hw_detect_init(struct platform_device *pdev,
+ struct d40_base **retbase)
{
struct stedma40_platform_data *plat_data = dev_get_platdata(&pdev->dev);
+ struct device *dev = &pdev->dev;
struct clk *clk;
void __iomem *virtbase;
- struct resource *res;
struct d40_base *base;
int num_log_chans;
int num_phy_chans;
int num_memcpy_chans;
- int clk_ret = -EINVAL;
int i;
u32 pid;
u32 cid;
u8 rev;
+ int ret;
- clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(clk)) {
- d40_err(&pdev->dev, "No matching clock found\n");
- goto check_prepare_enabled;
- }
-
- clk_ret = clk_prepare_enable(clk);
- if (clk_ret) {
- d40_err(&pdev->dev, "Failed to prepare/enable clock\n");
- goto disable_unprepare;
- }
+ clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
/* Get IO for DMAC base address */
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "base");
- if (!res)
- goto disable_unprepare;
-
- if (request_mem_region(res->start, resource_size(res),
- D40_NAME " I/O base") == NULL)
- goto release_region;
-
- virtbase = ioremap(res->start, resource_size(res));
- if (!virtbase)
- goto release_region;
+ virtbase = devm_platform_ioremap_resource_byname(pdev, "base");
+ if (IS_ERR(virtbase))
+ return PTR_ERR(virtbase);
/* This is just a regular AMBA PrimeCell ID actually */
for (pid = 0, i = 0; i < 4; i++)
- pid |= (readl(virtbase + resource_size(res) - 0x20 + 4 * i)
+ pid |= (readl(virtbase + SZ_4K - 0x20 + 4 * i)
& 255) << (i * 8);
for (cid = 0, i = 0; i < 4; i++)
- cid |= (readl(virtbase + resource_size(res) - 0x10 + 4 * i)
+ cid |= (readl(virtbase + SZ_4K - 0x10 + 4 * i)
& 255) << (i * 8);
if (cid != AMBA_CID) {
- d40_err(&pdev->dev, "Unknown hardware! No PrimeCell ID\n");
- goto unmap_io;
+ d40_err(dev, "Unknown hardware! No PrimeCell ID\n");
+ return -EINVAL;
}
if (AMBA_MANF_BITS(pid) != AMBA_VENDOR_ST) {
- d40_err(&pdev->dev, "Unknown designer! Got %x wanted %x\n",
+ d40_err(dev, "Unknown designer! Got %x wanted %x\n",
AMBA_MANF_BITS(pid),
AMBA_VENDOR_ST);
- goto unmap_io;
+ return -EINVAL;
}
/*
* HW revision:
@@ -3170,8 +3187,8 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
*/
rev = AMBA_REV_BITS(pid);
if (rev < 2) {
- d40_err(&pdev->dev, "hardware revision: %d is not supported", rev);
- goto unmap_io;
+ d40_err(dev, "hardware revision: %d is not supported", rev);
+ return -EINVAL;
}
/* The number of physical channels on this HW */
@@ -3188,27 +3205,26 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
num_log_chans = num_phy_chans * D40_MAX_LOG_CHAN_PER_PHY;
- dev_info(&pdev->dev,
- "hardware rev: %d @ %pa with %d physical and %d logical channels\n",
- rev, &res->start, num_phy_chans, num_log_chans);
+ dev_info(dev,
+ "hardware rev: %d with %d physical and %d logical channels\n",
+ rev, num_phy_chans, num_log_chans);
- base = kzalloc(ALIGN(sizeof(struct d40_base), 4) +
- (num_phy_chans + num_log_chans + num_memcpy_chans) *
- sizeof(struct d40_chan), GFP_KERNEL);
+ base = devm_kzalloc(dev,
+ ALIGN(sizeof(struct d40_base), 4) +
+ (num_phy_chans + num_log_chans + num_memcpy_chans) *
+ sizeof(struct d40_chan), GFP_KERNEL);
- if (base == NULL)
- goto unmap_io;
+ if (!base)
+ return -ENOMEM;
base->rev = rev;
base->clk = clk;
base->num_memcpy_chans = num_memcpy_chans;
base->num_phy_chans = num_phy_chans;
base->num_log_chans = num_log_chans;
- base->phy_start = res->start;
- base->phy_size = resource_size(res);
base->virtbase = virtbase;
base->plat_data = plat_data;
- base->dev = &pdev->dev;
+ base->dev = dev;
base->phy_chans = ((void *)base) + ALIGN(sizeof(struct d40_base), 4);
base->log_chans = &base->phy_chans[num_phy_chans];
@@ -3242,76 +3258,57 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
base->gen_dmac.init_reg_size = ARRAY_SIZE(dma_init_reg_v4a);
}
- base->phy_res = kcalloc(num_phy_chans,
- sizeof(*base->phy_res),
- GFP_KERNEL);
+ base->phy_res = devm_kcalloc(dev, num_phy_chans,
+ sizeof(*base->phy_res),
+ GFP_KERNEL);
if (!base->phy_res)
- goto free_base;
+ return -ENOMEM;
- base->lookup_phy_chans = kcalloc(num_phy_chans,
- sizeof(*base->lookup_phy_chans),
- GFP_KERNEL);
+ base->lookup_phy_chans = devm_kcalloc(dev, num_phy_chans,
+ sizeof(*base->lookup_phy_chans),
+ GFP_KERNEL);
if (!base->lookup_phy_chans)
- goto free_phy_res;
+ return -ENOMEM;
- base->lookup_log_chans = kcalloc(num_log_chans,
- sizeof(*base->lookup_log_chans),
- GFP_KERNEL);
+ base->lookup_log_chans = devm_kcalloc(dev, num_log_chans,
+ sizeof(*base->lookup_log_chans),
+ GFP_KERNEL);
if (!base->lookup_log_chans)
- goto free_phy_chans;
+ return -ENOMEM;
- base->reg_val_backup_chan = kmalloc_array(base->num_phy_chans,
+ base->reg_val_backup_chan = devm_kmalloc_array(dev, base->num_phy_chans,
sizeof(d40_backup_regs_chan),
GFP_KERNEL);
if (!base->reg_val_backup_chan)
- goto free_log_chans;
+ return -ENOMEM;
- base->lcla_pool.alloc_map = kcalloc(num_phy_chans
+ base->lcla_pool.alloc_map = devm_kcalloc(dev, num_phy_chans
* D40_LCLA_LINK_PER_EVENT_GRP,
sizeof(*base->lcla_pool.alloc_map),
GFP_KERNEL);
if (!base->lcla_pool.alloc_map)
- goto free_backup_chan;
+ return -ENOMEM;
- base->regs_interrupt = kmalloc_array(base->gen_dmac.il_size,
+ base->regs_interrupt = devm_kmalloc_array(dev, base->gen_dmac.il_size,
sizeof(*base->regs_interrupt),
GFP_KERNEL);
if (!base->regs_interrupt)
- goto free_map;
+ return -ENOMEM;
base->desc_slab = kmem_cache_create(D40_NAME, sizeof(struct d40_desc),
0, SLAB_HWCACHE_ALIGN,
NULL);
- if (base->desc_slab == NULL)
- goto free_regs;
-
-
- return base;
- free_regs:
- kfree(base->regs_interrupt);
- free_map:
- kfree(base->lcla_pool.alloc_map);
- free_backup_chan:
- kfree(base->reg_val_backup_chan);
- free_log_chans:
- kfree(base->lookup_log_chans);
- free_phy_chans:
- kfree(base->lookup_phy_chans);
- free_phy_res:
- kfree(base->phy_res);
- free_base:
- kfree(base);
- unmap_io:
- iounmap(virtbase);
- release_region:
- release_mem_region(res->start, resource_size(res));
- check_prepare_enabled:
- if (!clk_ret)
- disable_unprepare:
- clk_disable_unprepare(clk);
- if (!IS_ERR(clk))
- clk_put(clk);
- return NULL;
+ if (!base->desc_slab)
+ return -ENOMEM;
+
+ ret = devm_add_action_or_reset(dev, d40_drop_kmem_cache_action,
+ base->desc_slab);
+ if (ret)
+ return ret;
+
+ *retbase = base;
+
+ return 0;
}
static void __init d40_hw_init(struct d40_base *base)
@@ -3451,14 +3448,14 @@ static int __init d40_lcla_allocate(struct d40_base *base)
return ret;
}
-static int __init d40_of_probe(struct platform_device *pdev,
+static int __init d40_of_probe(struct device *dev,
struct device_node *np)
{
struct stedma40_platform_data *pdata;
int num_phy = 0, num_memcpy = 0, num_disabled = 0;
const __be32 *list;
- pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
@@ -3471,7 +3468,7 @@ static int __init d40_of_probe(struct platform_device *pdev,
num_memcpy /= sizeof(*list);
if (num_memcpy > D40_MEMCPY_MAX_CHANS || num_memcpy <= 0) {
- d40_err(&pdev->dev,
+ d40_err(dev,
"Invalid number of memcpy channels specified (%d)\n",
num_memcpy);
return -EINVAL;
@@ -3486,7 +3483,7 @@ static int __init d40_of_probe(struct platform_device *pdev,
num_disabled /= sizeof(*list);
if (num_disabled >= STEDMA40_MAX_PHYS || num_disabled < 0) {
- d40_err(&pdev->dev,
+ d40_err(dev,
"Invalid number of disabled channels specified (%d)\n",
num_disabled);
return -EINVAL;
@@ -3497,35 +3494,30 @@ static int __init d40_of_probe(struct platform_device *pdev,
num_disabled);
pdata->disabled_channels[num_disabled] = -1;
- pdev->dev.platform_data = pdata;
+ dev->platform_data = pdata;
return 0;
}
static int __init d40_probe(struct platform_device *pdev)
{
- struct stedma40_platform_data *plat_data = dev_get_platdata(&pdev->dev);
+ struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node;
- int ret = -ENOENT;
+ struct device_node *np_lcpa;
struct d40_base *base;
struct resource *res;
+ struct resource res_lcpa;
int num_reserved_chans;
u32 val;
+ int ret;
- if (!plat_data) {
- if (np) {
- if (d40_of_probe(pdev, np)) {
- ret = -ENOMEM;
- goto report_failure;
- }
- } else {
- d40_err(&pdev->dev, "No pdata or Device Tree provided\n");
- goto report_failure;
- }
+ if (d40_of_probe(dev, np)) {
+ ret = -ENOMEM;
+ goto report_failure;
}
- base = d40_hw_detect_init(pdev);
- if (!base)
+ ret = d40_hw_detect_init(pdev, &base);
+ if (ret)
goto report_failure;
num_reserved_chans = d40_phy_res_init(base);
@@ -3535,37 +3527,38 @@ static int __init d40_probe(struct platform_device *pdev)
spin_lock_init(&base->interrupt_lock);
spin_lock_init(&base->execmd_lock);
- /* Get IO for logical channel parameter address */
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lcpa");
- if (!res) {
- ret = -ENOENT;
- d40_err(&pdev->dev, "No \"lcpa\" memory resource\n");
- goto destroy_cache;
+ /* Get IO for logical channel parameter address (LCPA) */
+ np_lcpa = of_parse_phandle(np, "sram", 0);
+ if (!np_lcpa) {
+ dev_err(dev, "no LCPA SRAM node\n");
+ ret = -EINVAL;
+ goto report_failure;
}
- base->lcpa_size = resource_size(res);
- base->phy_lcpa = res->start;
-
- if (request_mem_region(res->start, resource_size(res),
- D40_NAME " I/O lcpa") == NULL) {
- ret = -EBUSY;
- d40_err(&pdev->dev, "Failed to request LCPA region %pR\n", res);
- goto destroy_cache;
+ /* This is no device so read the address directly from the node */
+ ret = of_address_to_resource(np_lcpa, 0, &res_lcpa);
+ if (ret) {
+ dev_err(dev, "no LCPA SRAM resource\n");
+ goto report_failure;
}
+ base->lcpa_size = resource_size(&res_lcpa);
+ base->phy_lcpa = res_lcpa.start;
+ dev_info(dev, "found LCPA SRAM at %pad, size %pa\n",
+ &base->phy_lcpa, &base->lcpa_size);
/* We make use of ESRAM memory for this. */
val = readl(base->virtbase + D40_DREG_LCPA);
- if (res->start != val && val != 0) {
- dev_warn(&pdev->dev,
- "[%s] Mismatch LCPA dma 0x%x, def %pa\n",
- __func__, val, &res->start);
+ if (base->phy_lcpa != val && val != 0) {
+ dev_warn(dev,
+ "[%s] Mismatch LCPA dma 0x%x, def %08x\n",
+ __func__, val, (u32)base->phy_lcpa);
} else
- writel(res->start, base->virtbase + D40_DREG_LCPA);
+ writel(base->phy_lcpa, base->virtbase + D40_DREG_LCPA);
- base->lcpa_base = ioremap(res->start, resource_size(res));
+ base->lcpa_base = devm_ioremap(dev, base->phy_lcpa, base->lcpa_size);
if (!base->lcpa_base) {
ret = -ENOMEM;
- d40_err(&pdev->dev, "Failed to ioremap LCPA region\n");
- goto destroy_cache;
+ d40_err(dev, "Failed to ioremap LCPA region\n");
+ goto report_failure;
}
/* If lcla has to be located in ESRAM we don't need to allocate */
if (base->plat_data->use_esram_lcla) {
@@ -3573,23 +3566,23 @@ static int __init d40_probe(struct platform_device *pdev)
"lcla_esram");
if (!res) {
ret = -ENOENT;
- d40_err(&pdev->dev,
+ d40_err(dev,
"No \"lcla_esram\" memory resource\n");
- goto destroy_cache;
+ goto report_failure;
}
- base->lcla_pool.base = ioremap(res->start,
- resource_size(res));
+ base->lcla_pool.base = devm_ioremap(dev, res->start,
+ resource_size(res));
if (!base->lcla_pool.base) {
ret = -ENOMEM;
- d40_err(&pdev->dev, "Failed to ioremap LCLA region\n");
- goto destroy_cache;
+ d40_err(dev, "Failed to ioremap LCLA region\n");
+ goto report_failure;
}
writel(res->start, base->virtbase + D40_DREG_LCLA);
} else {
ret = d40_lcla_allocate(base);
if (ret) {
- d40_err(&pdev->dev, "Failed to allocate LCLA area\n");
+ d40_err(dev, "Failed to allocate LCLA area\n");
goto destroy_cache;
}
}
@@ -3600,7 +3593,7 @@ static int __init d40_probe(struct platform_device *pdev)
ret = request_irq(base->irq, d40_handle_interrupt, 0, D40_NAME, base);
if (ret) {
- d40_err(&pdev->dev, "No IRQ defined\n");
+ d40_err(dev, "No IRQ defined\n");
goto destroy_cache;
}
@@ -3608,7 +3601,7 @@ static int __init d40_probe(struct platform_device *pdev)
base->lcpa_regulator = regulator_get(base->dev, "lcla_esram");
if (IS_ERR(base->lcpa_regulator)) {
- d40_err(&pdev->dev, "Failed to get lcpa_regulator\n");
+ d40_err(dev, "Failed to get lcpa_regulator\n");
ret = PTR_ERR(base->lcpa_regulator);
base->lcpa_regulator = NULL;
goto destroy_cache;
@@ -3616,7 +3609,7 @@ static int __init d40_probe(struct platform_device *pdev)
ret = regulator_enable(base->lcpa_regulator);
if (ret) {
- d40_err(&pdev->dev,
+ d40_err(dev,
"Failed to enable lcpa_regulator\n");
regulator_put(base->lcpa_regulator);
base->lcpa_regulator = NULL;
@@ -3639,31 +3632,23 @@ static int __init d40_probe(struct platform_device *pdev)
ret = dma_set_max_seg_size(base->dev, STEDMA40_MAX_SEG_SIZE);
if (ret) {
- d40_err(&pdev->dev, "Failed to set dma max seg size\n");
+ d40_err(dev, "Failed to set dma max seg size\n");
goto destroy_cache;
}
d40_hw_init(base);
- if (np) {
- ret = of_dma_controller_register(np, d40_xlate, NULL);
- if (ret)
- dev_err(&pdev->dev,
- "could not register of_dma_controller\n");
+ ret = of_dma_controller_register(np, d40_xlate, NULL);
+ if (ret) {
+ dev_err(dev,
+ "could not register of_dma_controller\n");
+ goto destroy_cache;
}
dev_info(base->dev, "initialized\n");
return 0;
- destroy_cache:
- kmem_cache_destroy(base->desc_slab);
- if (base->virtbase)
- iounmap(base->virtbase);
-
- if (base->lcla_pool.base && base->plat_data->use_esram_lcla) {
- iounmap(base->lcla_pool.base);
- base->lcla_pool.base = NULL;
- }
+ destroy_cache:
if (base->lcla_pool.dma_addr)
dma_unmap_single(base->dev, base->lcla_pool.dma_addr,
SZ_1K * base->num_phy_chans,
@@ -3675,32 +3660,13 @@ static int __init d40_probe(struct platform_device *pdev)
kfree(base->lcla_pool.base_unaligned);
- if (base->lcpa_base)
- iounmap(base->lcpa_base);
-
- if (base->phy_lcpa)
- release_mem_region(base->phy_lcpa,
- base->lcpa_size);
- if (base->phy_start)
- release_mem_region(base->phy_start,
- base->phy_size);
- if (base->clk) {
- clk_disable_unprepare(base->clk);
- clk_put(base->clk);
- }
-
if (base->lcpa_regulator) {
regulator_disable(base->lcpa_regulator);
regulator_put(base->lcpa_regulator);
}
- kfree(base->lcla_pool.alloc_map);
- kfree(base->lookup_log_chans);
- kfree(base->lookup_phy_chans);
- kfree(base->phy_res);
- kfree(base);
report_failure:
- d40_err(&pdev->dev, "probe failed\n");
+ d40_err(dev, "probe failed\n");
return ret;
}
diff --git a/drivers/dma/ste_dma40.h b/drivers/dma/ste_dma40.h
new file mode 100644
index 000000000000..c697bfe16a01
--- /dev/null
+++ b/drivers/dma/ste_dma40.h
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef STE_DMA40_H
+#define STE_DMA40_H
+
+/*
+ * Maxium size for a single dma descriptor
+ * Size is limited to 16 bits.
+ * Size is in the units of addr-widths (1,2,4,8 bytes)
+ * Larger transfers will be split up to multiple linked desc
+ */
+#define STEDMA40_MAX_SEG_SIZE 0xFFFF
+
+/* dev types for memcpy */
+#define STEDMA40_DEV_DST_MEMORY (-1)
+#define STEDMA40_DEV_SRC_MEMORY (-1)
+
+enum stedma40_mode {
+ STEDMA40_MODE_LOGICAL = 0,
+ STEDMA40_MODE_PHYSICAL,
+ STEDMA40_MODE_OPERATION,
+};
+
+enum stedma40_mode_opt {
+ STEDMA40_PCHAN_BASIC_MODE = 0,
+ STEDMA40_LCHAN_SRC_LOG_DST_LOG = 0,
+ STEDMA40_PCHAN_MODULO_MODE,
+ STEDMA40_PCHAN_DOUBLE_DST_MODE,
+ STEDMA40_LCHAN_SRC_PHY_DST_LOG,
+ STEDMA40_LCHAN_SRC_LOG_DST_PHY,
+};
+
+#define STEDMA40_ESIZE_8_BIT 0x0
+#define STEDMA40_ESIZE_16_BIT 0x1
+#define STEDMA40_ESIZE_32_BIT 0x2
+#define STEDMA40_ESIZE_64_BIT 0x3
+
+/* The value 4 indicates that PEN-reg shall be set to 0 */
+#define STEDMA40_PSIZE_PHY_1 0x4
+#define STEDMA40_PSIZE_PHY_2 0x0
+#define STEDMA40_PSIZE_PHY_4 0x1
+#define STEDMA40_PSIZE_PHY_8 0x2
+#define STEDMA40_PSIZE_PHY_16 0x3
+
+/*
+ * The number of elements differ in logical and
+ * physical mode
+ */
+#define STEDMA40_PSIZE_LOG_1 STEDMA40_PSIZE_PHY_2
+#define STEDMA40_PSIZE_LOG_4 STEDMA40_PSIZE_PHY_4
+#define STEDMA40_PSIZE_LOG_8 STEDMA40_PSIZE_PHY_8
+#define STEDMA40_PSIZE_LOG_16 STEDMA40_PSIZE_PHY_16
+
+/* Maximum number of possible physical channels */
+#define STEDMA40_MAX_PHYS 32
+
+enum stedma40_flow_ctrl {
+ STEDMA40_NO_FLOW_CTRL,
+ STEDMA40_FLOW_CTRL,
+};
+
+/**
+ * struct stedma40_half_channel_info - dst/src channel configuration
+ *
+ * @big_endian: true if the src/dst should be read as big endian
+ * @data_width: Data width of the src/dst hardware
+ * @p_size: Burst size
+ * @flow_ctrl: Flow control on/off.
+ */
+struct stedma40_half_channel_info {
+ bool big_endian;
+ enum dma_slave_buswidth data_width;
+ int psize;
+ enum stedma40_flow_ctrl flow_ctrl;
+};
+
+/**
+ * struct stedma40_chan_cfg - Structure to be filled by client drivers.
+ *
+ * @dir: MEM 2 MEM, PERIPH 2 MEM , MEM 2 PERIPH, PERIPH 2 PERIPH
+ * @high_priority: true if high-priority
+ * @realtime: true if realtime mode is to be enabled. Only available on DMA40
+ * version 3+, i.e DB8500v2+
+ * @mode: channel mode: physical, logical, or operation
+ * @mode_opt: options for the chosen channel mode
+ * @dev_type: src/dst device type (driver uses dir to figure out which)
+ * @src_info: Parameters for dst half channel
+ * @dst_info: Parameters for dst half channel
+ * @use_fixed_channel: if true, use physical channel specified by phy_channel
+ * @phy_channel: physical channel to use, only if use_fixed_channel is true
+ *
+ * This structure has to be filled by the client drivers.
+ * It is recommended to do all dma configurations for clients in the machine.
+ *
+ */
+struct stedma40_chan_cfg {
+ enum dma_transfer_direction dir;
+ bool high_priority;
+ bool realtime;
+ enum stedma40_mode mode;
+ enum stedma40_mode_opt mode_opt;
+ int dev_type;
+ struct stedma40_half_channel_info src_info;
+ struct stedma40_half_channel_info dst_info;
+
+ bool use_fixed_channel;
+ int phy_channel;
+};
+
+#endif /* STE_DMA40_H */
diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c
index b5287c661eb7..4c489b126cb2 100644
--- a/drivers/dma/ste_dma40_ll.c
+++ b/drivers/dma/ste_dma40_ll.c
@@ -6,8 +6,9 @@
*/
#include <linux/kernel.h>
-#include <linux/platform_data/dma-ste-dma40.h>
+#include <linux/dmaengine.h>
+#include "ste_dma40.h"
#include "ste_dma40_ll.h"
static u8 d40_width_to_bits(enum dma_slave_buswidth width)
diff --git a/drivers/dma/ti/k3-psil-j721s2.c b/drivers/dma/ti/k3-psil-j721s2.c
index a488c2250623..1d5430fc5724 100644
--- a/drivers/dma/ti/k3-psil-j721s2.c
+++ b/drivers/dma/ti/k3-psil-j721s2.c
@@ -99,6 +99,8 @@ static struct psil_ep j721s2_src_ep_map[] = {
PSIL_PDMA_XY_PKT(0x461d),
PSIL_PDMA_XY_PKT(0x461e),
PSIL_PDMA_XY_PKT(0x461f),
+ /* MAIN_CPSW2G */
+ PSIL_ETHERNET(0x4640),
/* PDMA_USART_G0 - UART0-1 */
PSIL_PDMA_XY_PKT(0x4700),
PSIL_PDMA_XY_PKT(0x4701),
@@ -161,6 +163,15 @@ static struct psil_ep j721s2_dst_ep_map[] = {
PSIL_ETHERNET(0xf005),
PSIL_ETHERNET(0xf006),
PSIL_ETHERNET(0xf007),
+ /* MAIN_CPSW2G */
+ PSIL_ETHERNET(0xc640),
+ PSIL_ETHERNET(0xc641),
+ PSIL_ETHERNET(0xc642),
+ PSIL_ETHERNET(0xc643),
+ PSIL_ETHERNET(0xc644),
+ PSIL_ETHERNET(0xc645),
+ PSIL_ETHERNET(0xc646),
+ PSIL_ETHERNET(0xc647),
/* SA2UL */
PSIL_SA2UL(0xf500, 1),
PSIL_SA2UL(0xf501, 1),
diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
index b8329a23728d..eb4dc5fffe64 100644
--- a/drivers/dma/ti/k3-udma.c
+++ b/drivers/dma/ti/k3-udma.c
@@ -4308,6 +4308,15 @@ static struct udma_soc_data am62a_dmss_csi_soc_data = {
},
};
+static struct udma_soc_data j721s2_bcdma_csi_soc_data = {
+ .oes = {
+ .bcdma_tchan_data = 0x800,
+ .bcdma_tchan_ring = 0xa00,
+ .bcdma_rchan_data = 0xe00,
+ .bcdma_rchan_ring = 0x1000,
+ },
+};
+
static struct udma_match_data am62a_bcdma_csirx_data = {
.type = DMA_TYPE_BCDMA,
.psil_base = 0x3100,
@@ -4346,6 +4355,18 @@ static struct udma_match_data am64_pktdma_data = {
},
};
+static struct udma_match_data j721s2_bcdma_csi_data = {
+ .type = DMA_TYPE_BCDMA,
+ .psil_base = 0x2000,
+ .enable_memcpy_support = false,
+ .burst_size = {
+ TI_SCI_RM_UDMAP_CHAN_BURST_SIZE_64_BYTES, /* Normal Channels */
+ 0, /* No H Channels */
+ 0, /* No UH Channels */
+ },
+ .soc_data = &j721s2_bcdma_csi_soc_data,
+};
+
static const struct of_device_id udma_of_match[] = {
{
.compatible = "ti,am654-navss-main-udmap",
@@ -4373,6 +4394,10 @@ static const struct of_device_id udma_of_match[] = {
.compatible = "ti,am62a-dmss-bcdma-csirx",
.data = &am62a_bcdma_csirx_data,
},
+ {
+ .compatible = "ti,j721s2-dmss-bcdma-csi",
+ .data = &j721s2_bcdma_csi_data,
+ },
{ /* Sentinel */ },
};
diff --git a/drivers/dma/xilinx/xdma.c b/drivers/dma/xilinx/xdma.c
index 93ee298d52b8..e0bfd129d563 100644
--- a/drivers/dma/xilinx/xdma.c
+++ b/drivers/dma/xilinx/xdma.c
@@ -668,6 +668,8 @@ static int xdma_set_vector_reg(struct xdma_device *xdev, u32 vec_tbl_start,
val |= irq_start << shift;
irq_start++;
irq_num--;
+ if (!irq_num)
+ break;
}
/* write IRQ register */
@@ -715,7 +717,7 @@ static int xdma_irq_init(struct xdma_device *xdev)
ret = request_irq(irq, xdma_channel_isr, 0,
"xdma-c2h-channel", &xdev->c2h_chans[j]);
if (ret) {
- xdma_err(xdev, "H2C channel%d request irq%d failed: %d",
+ xdma_err(xdev, "C2H channel%d request irq%d failed: %d",
j, irq, ret);
goto failed_init_c2h;
}
@@ -892,7 +894,7 @@ static int xdma_probe(struct platform_device *pdev)
}
reg_base = devm_ioremap_resource(&pdev->dev, res);
- if (!reg_base) {
+ if (IS_ERR(reg_base)) {
xdma_err(xdev, "ioremap failed");
goto failed;
}
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 68f576700911..110e99b86a66 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -550,4 +550,15 @@ config EDAC_ZYNQMP
Xilinx ZynqMP OCM (On Chip Memory) controller. It can also be
built as a module. In that case it will be called zynqmp_edac.
+config EDAC_NPCM
+ tristate "Nuvoton NPCM DDR Memory Controller"
+ depends on (ARCH_NPCM || COMPILE_TEST)
+ help
+ Support for error detection and correction on the Nuvoton NPCM DDR
+ memory controller.
+
+ The memory controller supports single bit error correction, double bit
+ error detection (in-line ECC in which a section 1/8th of the memory
+ device used to store data is used for ECC storage).
+
endif # EDAC
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index 9b025c5b3061..61945d3113cc 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -84,4 +84,5 @@ obj-$(CONFIG_EDAC_QCOM) += qcom_edac.o
obj-$(CONFIG_EDAC_ASPEED) += aspeed_edac.o
obj-$(CONFIG_EDAC_BLUEFIELD) += bluefield_edac.o
obj-$(CONFIG_EDAC_DMC520) += dmc520_edac.o
+obj-$(CONFIG_EDAC_NPCM) += npcm_edac.o
obj-$(CONFIG_EDAC_ZYNQMP) += zynqmp_edac.o
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 5c4292e65b96..597dae7692b1 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -975,6 +975,74 @@ static int sys_addr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr)
return csrow;
}
+/*
+ * See AMD PPR DF::LclNodeTypeMap
+ *
+ * This register gives information for nodes of the same type within a system.
+ *
+ * Reading this register from a GPU node will tell how many GPU nodes are in the
+ * system and what the lowest AMD Node ID value is for the GPU nodes. Use this
+ * info to fixup the Linux logical "Node ID" value set in the AMD NB code and EDAC.
+ */
+static struct local_node_map {
+ u16 node_count;
+ u16 base_node_id;
+} gpu_node_map;
+
+#define PCI_DEVICE_ID_AMD_MI200_DF_F1 0x14d1
+#define REG_LOCAL_NODE_TYPE_MAP 0x144
+
+/* Local Node Type Map (LNTM) fields */
+#define LNTM_NODE_COUNT GENMASK(27, 16)
+#define LNTM_BASE_NODE_ID GENMASK(11, 0)
+
+static int gpu_get_node_map(void)
+{
+ struct pci_dev *pdev;
+ int ret;
+ u32 tmp;
+
+ /*
+ * Node ID 0 is reserved for CPUs.
+ * Therefore, a non-zero Node ID means we've already cached the values.
+ */
+ if (gpu_node_map.base_node_id)
+ return 0;
+
+ pdev = pci_get_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI200_DF_F1, NULL);
+ if (!pdev) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ ret = pci_read_config_dword(pdev, REG_LOCAL_NODE_TYPE_MAP, &tmp);
+ if (ret)
+ goto out;
+
+ gpu_node_map.node_count = FIELD_GET(LNTM_NODE_COUNT, tmp);
+ gpu_node_map.base_node_id = FIELD_GET(LNTM_BASE_NODE_ID, tmp);
+
+out:
+ pci_dev_put(pdev);
+ return ret;
+}
+
+static int fixup_node_id(int node_id, struct mce *m)
+{
+ /* MCA_IPID[InstanceIdHi] give the AMD Node ID for the bank. */
+ u8 nid = (m->ipid >> 44) & 0xF;
+
+ if (smca_get_bank_type(m->extcpu, m->bank) != SMCA_UMC_V2)
+ return node_id;
+
+ /* Nodes below the GPU base node are CPU nodes and don't need a fixup. */
+ if (nid < gpu_node_map.base_node_id)
+ return node_id;
+
+ /* Convert the hardware-provided AMD Node ID to a Linux logical one. */
+ return nid - gpu_node_map.base_node_id + 1;
+}
+
/* Protect the PCI config register pairs used for DF indirect access. */
static DEFINE_MUTEX(df_indirect_mutex);
@@ -1426,12 +1494,47 @@ static int umc_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
return cs_mode;
}
+static int __addr_mask_to_cs_size(u32 addr_mask_orig, unsigned int cs_mode,
+ int csrow_nr, int dimm)
+{
+ u32 msb, weight, num_zero_bits;
+ u32 addr_mask_deinterleaved;
+ int size = 0;
+
+ /*
+ * The number of zero bits in the mask is equal to the number of bits
+ * in a full mask minus the number of bits in the current mask.
+ *
+ * The MSB is the number of bits in the full mask because BIT[0] is
+ * always 0.
+ *
+ * In the special 3 Rank interleaving case, a single bit is flipped
+ * without swapping with the most significant bit. This can be handled
+ * by keeping the MSB where it is and ignoring the single zero bit.
+ */
+ msb = fls(addr_mask_orig) - 1;
+ weight = hweight_long(addr_mask_orig);
+ num_zero_bits = msb - weight - !!(cs_mode & CS_3R_INTERLEAVE);
+
+ /* Take the number of zero bits off from the top of the mask. */
+ addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1);
+
+ edac_dbg(1, "CS%d DIMM%d AddrMasks:\n", csrow_nr, dimm);
+ edac_dbg(1, " Original AddrMask: 0x%x\n", addr_mask_orig);
+ edac_dbg(1, " Deinterleaved AddrMask: 0x%x\n", addr_mask_deinterleaved);
+
+ /* Register [31:1] = Address [39:9]. Size is in kBs here. */
+ size = (addr_mask_deinterleaved >> 2) + 1;
+
+ /* Return size in MBs. */
+ return size >> 10;
+}
+
static int umc_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc,
unsigned int cs_mode, int csrow_nr)
{
- u32 addr_mask_orig, addr_mask_deinterleaved;
- u32 msb, weight, num_zero_bits;
int cs_mask_nr = csrow_nr;
+ u32 addr_mask_orig;
int dimm, size = 0;
/* No Chip Selects are enabled. */
@@ -1475,33 +1578,7 @@ static int umc_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc,
else
addr_mask_orig = pvt->csels[umc].csmasks[cs_mask_nr];
- /*
- * The number of zero bits in the mask is equal to the number of bits
- * in a full mask minus the number of bits in the current mask.
- *
- * The MSB is the number of bits in the full mask because BIT[0] is
- * always 0.
- *
- * In the special 3 Rank interleaving case, a single bit is flipped
- * without swapping with the most significant bit. This can be handled
- * by keeping the MSB where it is and ignoring the single zero bit.
- */
- msb = fls(addr_mask_orig) - 1;
- weight = hweight_long(addr_mask_orig);
- num_zero_bits = msb - weight - !!(cs_mode & CS_3R_INTERLEAVE);
-
- /* Take the number of zero bits off from the top of the mask. */
- addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1);
-
- edac_dbg(1, "CS%d DIMM%d AddrMasks:\n", csrow_nr, dimm);
- edac_dbg(1, " Original AddrMask: 0x%x\n", addr_mask_orig);
- edac_dbg(1, " Deinterleaved AddrMask: 0x%x\n", addr_mask_deinterleaved);
-
- /* Register [31:1] = Address [39:9]. Size is in kBs here. */
- size = (addr_mask_deinterleaved >> 2) + 1;
-
- /* Return size in MBs. */
- return size >> 10;
+ return __addr_mask_to_cs_size(addr_mask_orig, cs_mode, csrow_nr, dimm);
}
static void umc_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
@@ -2992,6 +3069,8 @@ static void decode_umc_error(int node_id, struct mce *m)
struct err_info err;
u64 sys_addr;
+ node_id = fixup_node_id(node_id, m);
+
mci = edac_mc_find(node_id);
if (!mci)
return;
@@ -3675,6 +3754,227 @@ static int umc_hw_info_get(struct amd64_pvt *pvt)
return 0;
}
+/*
+ * The CPUs have one channel per UMC, so UMC number is equivalent to a
+ * channel number. The GPUs have 8 channels per UMC, so the UMC number no
+ * longer works as a channel number.
+ *
+ * The channel number within a GPU UMC is given in MCA_IPID[15:12].
+ * However, the IDs are split such that two UMC values go to one UMC, and
+ * the channel numbers are split in two groups of four.
+ *
+ * Refer to comment on gpu_get_umc_base().
+ *
+ * For example,
+ * UMC0 CH[3:0] = 0x0005[3:0]000
+ * UMC0 CH[7:4] = 0x0015[3:0]000
+ * UMC1 CH[3:0] = 0x0025[3:0]000
+ * UMC1 CH[7:4] = 0x0035[3:0]000
+ */
+static void gpu_get_err_info(struct mce *m, struct err_info *err)
+{
+ u8 ch = (m->ipid & GENMASK(31, 0)) >> 20;
+ u8 phy = ((m->ipid >> 12) & 0xf);
+
+ err->channel = ch % 2 ? phy + 4 : phy;
+ err->csrow = phy;
+}
+
+static int gpu_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc,
+ unsigned int cs_mode, int csrow_nr)
+{
+ u32 addr_mask_orig = pvt->csels[umc].csmasks[csrow_nr];
+
+ return __addr_mask_to_cs_size(addr_mask_orig, cs_mode, csrow_nr, csrow_nr >> 1);
+}
+
+static void gpu_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
+{
+ int size, cs_mode, cs = 0;
+
+ edac_printk(KERN_DEBUG, EDAC_MC, "UMC%d chip selects:\n", ctrl);
+
+ cs_mode = CS_EVEN_PRIMARY | CS_ODD_PRIMARY;
+
+ for_each_chip_select(cs, ctrl, pvt) {
+ size = gpu_addr_mask_to_cs_size(pvt, ctrl, cs_mode, cs);
+ amd64_info(EDAC_MC ": %d: %5dMB\n", cs, size);
+ }
+}
+
+static void gpu_dump_misc_regs(struct amd64_pvt *pvt)
+{
+ struct amd64_umc *umc;
+ u32 i;
+
+ for_each_umc(i) {
+ umc = &pvt->umc[i];
+
+ edac_dbg(1, "UMC%d UMC cfg: 0x%x\n", i, umc->umc_cfg);
+ edac_dbg(1, "UMC%d SDP ctrl: 0x%x\n", i, umc->sdp_ctrl);
+ edac_dbg(1, "UMC%d ECC ctrl: 0x%x\n", i, umc->ecc_ctrl);
+ edac_dbg(1, "UMC%d All HBMs support ECC: yes\n", i);
+
+ gpu_debug_display_dimm_sizes(pvt, i);
+ }
+}
+
+static u32 gpu_get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
+{
+ u32 nr_pages;
+ int cs_mode = CS_EVEN_PRIMARY | CS_ODD_PRIMARY;
+
+ nr_pages = gpu_addr_mask_to_cs_size(pvt, dct, cs_mode, csrow_nr);
+ nr_pages <<= 20 - PAGE_SHIFT;
+
+ edac_dbg(0, "csrow: %d, channel: %d\n", csrow_nr, dct);
+ edac_dbg(0, "nr_pages/channel: %u\n", nr_pages);
+
+ return nr_pages;
+}
+
+static void gpu_init_csrows(struct mem_ctl_info *mci)
+{
+ struct amd64_pvt *pvt = mci->pvt_info;
+ struct dimm_info *dimm;
+ u8 umc, cs;
+
+ for_each_umc(umc) {
+ for_each_chip_select(cs, umc, pvt) {
+ if (!csrow_enabled(cs, umc, pvt))
+ continue;
+
+ dimm = mci->csrows[umc]->channels[cs]->dimm;
+
+ edac_dbg(1, "MC node: %d, csrow: %d\n",
+ pvt->mc_node_id, cs);
+
+ dimm->nr_pages = gpu_get_csrow_nr_pages(pvt, umc, cs);
+ dimm->edac_mode = EDAC_SECDED;
+ dimm->mtype = MEM_HBM2;
+ dimm->dtype = DEV_X16;
+ dimm->grain = 64;
+ }
+ }
+}
+
+static void gpu_setup_mci_misc_attrs(struct mem_ctl_info *mci)
+{
+ struct amd64_pvt *pvt = mci->pvt_info;
+
+ mci->mtype_cap = MEM_FLAG_HBM2;
+ mci->edac_ctl_cap = EDAC_FLAG_SECDED;
+
+ mci->edac_cap = EDAC_FLAG_EC;
+ mci->mod_name = EDAC_MOD_STR;
+ mci->ctl_name = pvt->ctl_name;
+ mci->dev_name = pci_name(pvt->F3);
+ mci->ctl_page_to_phys = NULL;
+
+ gpu_init_csrows(mci);
+}
+
+/* ECC is enabled by default on GPU nodes */
+static bool gpu_ecc_enabled(struct amd64_pvt *pvt)
+{
+ return true;
+}
+
+static inline u32 gpu_get_umc_base(u8 umc, u8 channel)
+{
+ /*
+ * On CPUs, there is one channel per UMC, so UMC numbering equals
+ * channel numbering. On GPUs, there are eight channels per UMC,
+ * so the channel numbering is different from UMC numbering.
+ *
+ * On CPU nodes channels are selected in 6th nibble
+ * UMC chY[3:0]= [(chY*2 + 1) : (chY*2)]50000;
+ *
+ * On GPU nodes channels are selected in 3rd nibble
+ * HBM chX[3:0]= [Y ]5X[3:0]000;
+ * HBM chX[7:4]= [Y+1]5X[3:0]000
+ */
+ umc *= 2;
+
+ if (channel >= 4)
+ umc++;
+
+ return 0x50000 + (umc << 20) + ((channel % 4) << 12);
+}
+
+static void gpu_read_mc_regs(struct amd64_pvt *pvt)
+{
+ u8 nid = pvt->mc_node_id;
+ struct amd64_umc *umc;
+ u32 i, umc_base;
+
+ /* Read registers from each UMC */
+ for_each_umc(i) {
+ umc_base = gpu_get_umc_base(i, 0);
+ umc = &pvt->umc[i];
+
+ amd_smn_read(nid, umc_base + UMCCH_UMC_CFG, &umc->umc_cfg);
+ amd_smn_read(nid, umc_base + UMCCH_SDP_CTRL, &umc->sdp_ctrl);
+ amd_smn_read(nid, umc_base + UMCCH_ECC_CTRL, &umc->ecc_ctrl);
+ }
+}
+
+static void gpu_read_base_mask(struct amd64_pvt *pvt)
+{
+ u32 base_reg, mask_reg;
+ u32 *base, *mask;
+ int umc, cs;
+
+ for_each_umc(umc) {
+ for_each_chip_select(cs, umc, pvt) {
+ base_reg = gpu_get_umc_base(umc, cs) + UMCCH_BASE_ADDR;
+ base = &pvt->csels[umc].csbases[cs];
+
+ if (!amd_smn_read(pvt->mc_node_id, base_reg, base)) {
+ edac_dbg(0, " DCSB%d[%d]=0x%08x reg: 0x%x\n",
+ umc, cs, *base, base_reg);
+ }
+
+ mask_reg = gpu_get_umc_base(umc, cs) + UMCCH_ADDR_MASK;
+ mask = &pvt->csels[umc].csmasks[cs];
+
+ if (!amd_smn_read(pvt->mc_node_id, mask_reg, mask)) {
+ edac_dbg(0, " DCSM%d[%d]=0x%08x reg: 0x%x\n",
+ umc, cs, *mask, mask_reg);
+ }
+ }
+ }
+}
+
+static void gpu_prep_chip_selects(struct amd64_pvt *pvt)
+{
+ int umc;
+
+ for_each_umc(umc) {
+ pvt->csels[umc].b_cnt = 8;
+ pvt->csels[umc].m_cnt = 8;
+ }
+}
+
+static int gpu_hw_info_get(struct amd64_pvt *pvt)
+{
+ int ret;
+
+ ret = gpu_get_node_map();
+ if (ret)
+ return ret;
+
+ pvt->umc = kcalloc(pvt->max_mcs, sizeof(struct amd64_umc), GFP_KERNEL);
+ if (!pvt->umc)
+ return -ENOMEM;
+
+ gpu_prep_chip_selects(pvt);
+ gpu_read_base_mask(pvt);
+ gpu_read_mc_regs(pvt);
+
+ return 0;
+}
+
static void hw_info_put(struct amd64_pvt *pvt)
{
pci_dev_put(pvt->F1);
@@ -3690,6 +3990,14 @@ static struct low_ops umc_ops = {
.get_err_info = umc_get_err_info,
};
+static struct low_ops gpu_ops = {
+ .hw_info_get = gpu_hw_info_get,
+ .ecc_enabled = gpu_ecc_enabled,
+ .setup_mci_misc_attrs = gpu_setup_mci_misc_attrs,
+ .dump_misc_regs = gpu_dump_misc_regs,
+ .get_err_info = gpu_get_err_info,
+};
+
/* Use Family 16h versions for defaults and adjust as needed below. */
static struct low_ops dct_ops = {
.map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow,
@@ -3813,9 +4121,27 @@ static int per_family_init(struct amd64_pvt *pvt)
case 0x20 ... 0x2f:
pvt->ctl_name = "F19h_M20h";
break;
+ case 0x30 ... 0x3f:
+ if (pvt->F3->device == PCI_DEVICE_ID_AMD_MI200_DF_F3) {
+ pvt->ctl_name = "MI200";
+ pvt->max_mcs = 4;
+ pvt->ops = &gpu_ops;
+ } else {
+ pvt->ctl_name = "F19h_M30h";
+ pvt->max_mcs = 8;
+ }
+ break;
case 0x50 ... 0x5f:
pvt->ctl_name = "F19h_M50h";
break;
+ case 0x60 ... 0x6f:
+ pvt->ctl_name = "F19h_M60h";
+ pvt->flags.zn_regs_v2 = 1;
+ break;
+ case 0x70 ... 0x7f:
+ pvt->ctl_name = "F19h_M70h";
+ pvt->flags.zn_regs_v2 = 1;
+ break;
case 0xa0 ... 0xaf:
pvt->ctl_name = "F19h_MA0h";
pvt->max_mcs = 12;
@@ -3846,11 +4172,17 @@ static int init_one_instance(struct amd64_pvt *pvt)
struct edac_mc_layer layers[2];
int ret = -ENOMEM;
+ /*
+ * For Heterogeneous family EDAC CHIP_SELECT and CHANNEL layers should
+ * be swapped to fit into the layers.
+ */
layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
- layers[0].size = pvt->csels[0].b_cnt;
+ layers[0].size = (pvt->F3->device == PCI_DEVICE_ID_AMD_MI200_DF_F3) ?
+ pvt->max_mcs : pvt->csels[0].b_cnt;
layers[0].is_virt_csrow = true;
layers[1].type = EDAC_MC_LAYER_CHANNEL;
- layers[1].size = pvt->max_mcs;
+ layers[1].size = (pvt->F3->device == PCI_DEVICE_ID_AMD_MI200_DF_F3) ?
+ pvt->csels[0].b_cnt : pvt->max_mcs;
layers[1].is_virt_csrow = false;
mci = edac_mc_alloc(pvt->mc_node_id, ARRAY_SIZE(layers), layers, 0);
@@ -4074,8 +4406,6 @@ static int __init amd64_edac_init(void)
amd64_err("%s on 32-bit is unsupported. USE AT YOUR OWN RISK!\n", EDAC_MOD_STR);
#endif
- printk(KERN_INFO "AMD64 EDAC driver v%s\n", EDAC_AMD64_VERSION);
-
return 0;
err_pci:
@@ -4121,7 +4451,7 @@ module_exit(amd64_edac_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("SoftwareBitMaker: Doug Thompson, Dave Peterson, Thayne Harbaugh; AMD");
-MODULE_DESCRIPTION("MC support for AMD64 memory controllers - " EDAC_AMD64_VERSION);
+MODULE_DESCRIPTION("MC support for AMD64 memory controllers");
module_param(edac_op_state, int, 0444);
MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index e84fe0d4120a..5a4e4a59682b 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/mmzone.h>
#include <linux/edac.h>
+#include <linux/bitfield.h>
#include <asm/cpu_device_id.h>
#include <asm/msr.h>
#include "edac_module.h"
@@ -85,7 +86,6 @@
* sections 3.5.4 and 3.5.5 for more information.
*/
-#define EDAC_AMD64_VERSION "3.5.0"
#define EDAC_MOD_STR "amd64_edac"
/* Extended Model from CPUID, for CPU Revision numbers */
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index cc5c63feb26a..9215c06783df 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -1186,7 +1186,8 @@ static void decode_smca_error(struct mce *m)
if (xec < smca_mce_descs[bank_type].num_descs)
pr_cont(", %s.\n", smca_mce_descs[bank_type].descs[xec]);
- if (bank_type == SMCA_UMC && xec == 0 && decode_dram_ecc)
+ if ((bank_type == SMCA_UMC || bank_type == SMCA_UMC_V2) &&
+ xec == 0 && decode_dram_ecc)
decode_dram_ecc(topology_die_id(m->extcpu), m);
}
diff --git a/drivers/edac/npcm_edac.c b/drivers/edac/npcm_edac.c
new file mode 100644
index 000000000000..12b95be3e989
--- /dev/null
+++ b/drivers/edac/npcm_edac.c
@@ -0,0 +1,543 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2022 Nuvoton Technology Corporation
+
+#include <linux/debugfs.h>
+#include <linux/iopoll.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include "edac_module.h"
+
+#define EDAC_MOD_NAME "npcm-edac"
+#define EDAC_MSG_SIZE 256
+
+/* chip serials */
+#define NPCM7XX_CHIP BIT(0)
+#define NPCM8XX_CHIP BIT(1)
+
+/* syndrome values */
+#define UE_SYNDROME 0x03
+
+/* error injection */
+#define ERROR_TYPE_CORRECTABLE 0
+#define ERROR_TYPE_UNCORRECTABLE 1
+#define ERROR_LOCATION_DATA 0
+#define ERROR_LOCATION_CHECKCODE 1
+#define ERROR_BIT_DATA_MAX 63
+#define ERROR_BIT_CHECKCODE_MAX 7
+
+static char data_synd[] = {
+ 0xf4, 0xf1, 0xec, 0xea, 0xe9, 0xe6, 0xe5, 0xe3,
+ 0xdc, 0xda, 0xd9, 0xd6, 0xd5, 0xd3, 0xce, 0xcb,
+ 0xb5, 0xb0, 0xad, 0xab, 0xa8, 0xa7, 0xa4, 0xa2,
+ 0x9d, 0x9b, 0x98, 0x97, 0x94, 0x92, 0x8f, 0x8a,
+ 0x75, 0x70, 0x6d, 0x6b, 0x68, 0x67, 0x64, 0x62,
+ 0x5e, 0x5b, 0x58, 0x57, 0x54, 0x52, 0x4f, 0x4a,
+ 0x34, 0x31, 0x2c, 0x2a, 0x29, 0x26, 0x25, 0x23,
+ 0x1c, 0x1a, 0x19, 0x16, 0x15, 0x13, 0x0e, 0x0b
+};
+
+static struct regmap *npcm_regmap;
+
+struct npcm_platform_data {
+ /* chip serials */
+ int chip;
+
+ /* memory controller registers */
+ u32 ctl_ecc_en;
+ u32 ctl_int_status;
+ u32 ctl_int_ack;
+ u32 ctl_int_mask_master;
+ u32 ctl_int_mask_ecc;
+ u32 ctl_ce_addr_l;
+ u32 ctl_ce_addr_h;
+ u32 ctl_ce_data_l;
+ u32 ctl_ce_data_h;
+ u32 ctl_ce_synd;
+ u32 ctl_ue_addr_l;
+ u32 ctl_ue_addr_h;
+ u32 ctl_ue_data_l;
+ u32 ctl_ue_data_h;
+ u32 ctl_ue_synd;
+ u32 ctl_source_id;
+ u32 ctl_controller_busy;
+ u32 ctl_xor_check_bits;
+
+ /* masks and shifts */
+ u32 ecc_en_mask;
+ u32 int_status_ce_mask;
+ u32 int_status_ue_mask;
+ u32 int_ack_ce_mask;
+ u32 int_ack_ue_mask;
+ u32 int_mask_master_non_ecc_mask;
+ u32 int_mask_master_global_mask;
+ u32 int_mask_ecc_non_event_mask;
+ u32 ce_addr_h_mask;
+ u32 ce_synd_mask;
+ u32 ce_synd_shift;
+ u32 ue_addr_h_mask;
+ u32 ue_synd_mask;
+ u32 ue_synd_shift;
+ u32 source_id_ce_mask;
+ u32 source_id_ce_shift;
+ u32 source_id_ue_mask;
+ u32 source_id_ue_shift;
+ u32 controller_busy_mask;
+ u32 xor_check_bits_mask;
+ u32 xor_check_bits_shift;
+ u32 writeback_en_mask;
+ u32 fwc_mask;
+};
+
+struct priv_data {
+ void __iomem *reg;
+ char message[EDAC_MSG_SIZE];
+ const struct npcm_platform_data *pdata;
+
+ /* error injection */
+ struct dentry *debugfs;
+ u8 error_type;
+ u8 location;
+ u8 bit;
+};
+
+static void handle_ce(struct mem_ctl_info *mci)
+{
+ struct priv_data *priv = mci->pvt_info;
+ const struct npcm_platform_data *pdata;
+ u32 val_h = 0, val_l, id, synd;
+ u64 addr = 0, data = 0;
+
+ pdata = priv->pdata;
+ regmap_read(npcm_regmap, pdata->ctl_ce_addr_l, &val_l);
+ if (pdata->chip == NPCM8XX_CHIP) {
+ regmap_read(npcm_regmap, pdata->ctl_ce_addr_h, &val_h);
+ val_h &= pdata->ce_addr_h_mask;
+ }
+ addr = ((addr | val_h) << 32) | val_l;
+
+ regmap_read(npcm_regmap, pdata->ctl_ce_data_l, &val_l);
+ if (pdata->chip == NPCM8XX_CHIP)
+ regmap_read(npcm_regmap, pdata->ctl_ce_data_h, &val_h);
+ data = ((data | val_h) << 32) | val_l;
+
+ regmap_read(npcm_regmap, pdata->ctl_source_id, &id);
+ id = (id & pdata->source_id_ce_mask) >> pdata->source_id_ce_shift;
+
+ regmap_read(npcm_regmap, pdata->ctl_ce_synd, &synd);
+ synd = (synd & pdata->ce_synd_mask) >> pdata->ce_synd_shift;
+
+ snprintf(priv->message, EDAC_MSG_SIZE,
+ "addr = 0x%llx, data = 0x%llx, id = 0x%x", addr, data, id);
+
+ edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, addr >> PAGE_SHIFT,
+ addr & ~PAGE_MASK, synd, 0, 0, -1, priv->message, "");
+}
+
+static void handle_ue(struct mem_ctl_info *mci)
+{
+ struct priv_data *priv = mci->pvt_info;
+ const struct npcm_platform_data *pdata;
+ u32 val_h = 0, val_l, id, synd;
+ u64 addr = 0, data = 0;
+
+ pdata = priv->pdata;
+ regmap_read(npcm_regmap, pdata->ctl_ue_addr_l, &val_l);
+ if (pdata->chip == NPCM8XX_CHIP) {
+ regmap_read(npcm_regmap, pdata->ctl_ue_addr_h, &val_h);
+ val_h &= pdata->ue_addr_h_mask;
+ }
+ addr = ((addr | val_h) << 32) | val_l;
+
+ regmap_read(npcm_regmap, pdata->ctl_ue_data_l, &val_l);
+ if (pdata->chip == NPCM8XX_CHIP)
+ regmap_read(npcm_regmap, pdata->ctl_ue_data_h, &val_h);
+ data = ((data | val_h) << 32) | val_l;
+
+ regmap_read(npcm_regmap, pdata->ctl_source_id, &id);
+ id = (id & pdata->source_id_ue_mask) >> pdata->source_id_ue_shift;
+
+ regmap_read(npcm_regmap, pdata->ctl_ue_synd, &synd);
+ synd = (synd & pdata->ue_synd_mask) >> pdata->ue_synd_shift;
+
+ snprintf(priv->message, EDAC_MSG_SIZE,
+ "addr = 0x%llx, data = 0x%llx, id = 0x%x", addr, data, id);
+
+ edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, addr >> PAGE_SHIFT,
+ addr & ~PAGE_MASK, synd, 0, 0, -1, priv->message, "");
+}
+
+static irqreturn_t edac_ecc_isr(int irq, void *dev_id)
+{
+ const struct npcm_platform_data *pdata;
+ struct mem_ctl_info *mci = dev_id;
+ u32 status;
+
+ pdata = ((struct priv_data *)mci->pvt_info)->pdata;
+ regmap_read(npcm_regmap, pdata->ctl_int_status, &status);
+ if (status & pdata->int_status_ce_mask) {
+ handle_ce(mci);
+
+ /* acknowledge the CE interrupt */
+ regmap_write(npcm_regmap, pdata->ctl_int_ack,
+ pdata->int_ack_ce_mask);
+ return IRQ_HANDLED;
+ } else if (status & pdata->int_status_ue_mask) {
+ handle_ue(mci);
+
+ /* acknowledge the UE interrupt */
+ regmap_write(npcm_regmap, pdata->ctl_int_ack,
+ pdata->int_ack_ue_mask);
+ return IRQ_HANDLED;
+ }
+
+ WARN_ON_ONCE(1);
+ return IRQ_NONE;
+}
+
+static ssize_t force_ecc_error(struct file *file, const char __user *data,
+ size_t count, loff_t *ppos)
+{
+ struct device *dev = file->private_data;
+ struct mem_ctl_info *mci = to_mci(dev);
+ struct priv_data *priv = mci->pvt_info;
+ const struct npcm_platform_data *pdata;
+ u32 val, syndrome;
+ int ret;
+
+ pdata = priv->pdata;
+ edac_printk(KERN_INFO, EDAC_MOD_NAME,
+ "force an ECC error, type = %d, location = %d, bit = %d\n",
+ priv->error_type, priv->location, priv->bit);
+
+ /* ensure no pending writes */
+ ret = regmap_read_poll_timeout(npcm_regmap, pdata->ctl_controller_busy,
+ val, !(val & pdata->controller_busy_mask),
+ 1000, 10000);
+ if (ret) {
+ edac_printk(KERN_INFO, EDAC_MOD_NAME,
+ "wait pending writes timeout\n");
+ return count;
+ }
+
+ regmap_read(npcm_regmap, pdata->ctl_xor_check_bits, &val);
+ val &= ~pdata->xor_check_bits_mask;
+
+ /* write syndrome to XOR_CHECK_BITS */
+ if (priv->error_type == ERROR_TYPE_CORRECTABLE) {
+ if (priv->location == ERROR_LOCATION_DATA &&
+ priv->bit > ERROR_BIT_DATA_MAX) {
+ edac_printk(KERN_INFO, EDAC_MOD_NAME,
+ "data bit should not exceed %d (%d)\n",
+ ERROR_BIT_DATA_MAX, priv->bit);
+ return count;
+ }
+
+ if (priv->location == ERROR_LOCATION_CHECKCODE &&
+ priv->bit > ERROR_BIT_CHECKCODE_MAX) {
+ edac_printk(KERN_INFO, EDAC_MOD_NAME,
+ "checkcode bit should not exceed %d (%d)\n",
+ ERROR_BIT_CHECKCODE_MAX, priv->bit);
+ return count;
+ }
+
+ syndrome = priv->location ? 1 << priv->bit
+ : data_synd[priv->bit];
+
+ regmap_write(npcm_regmap, pdata->ctl_xor_check_bits,
+ val | (syndrome << pdata->xor_check_bits_shift) |
+ pdata->writeback_en_mask);
+ } else if (priv->error_type == ERROR_TYPE_UNCORRECTABLE) {
+ regmap_write(npcm_regmap, pdata->ctl_xor_check_bits,
+ val | (UE_SYNDROME << pdata->xor_check_bits_shift));
+ }
+
+ /* force write check */
+ regmap_update_bits(npcm_regmap, pdata->ctl_xor_check_bits,
+ pdata->fwc_mask, pdata->fwc_mask);
+
+ return count;
+}
+
+static const struct file_operations force_ecc_error_fops = {
+ .open = simple_open,
+ .write = force_ecc_error,
+ .llseek = generic_file_llseek,
+};
+
+/*
+ * Setup debugfs for error injection.
+ *
+ * Nodes:
+ * error_type - 0: CE, 1: UE
+ * location - 0: data, 1: checkcode
+ * bit - 0 ~ 63 for data and 0 ~ 7 for checkcode
+ * force_ecc_error - trigger
+ *
+ * Examples:
+ * 1. Inject a correctable error (CE) at checkcode bit 7.
+ * ~# echo 0 > /sys/kernel/debug/edac/npcm-edac/error_type
+ * ~# echo 1 > /sys/kernel/debug/edac/npcm-edac/location
+ * ~# echo 7 > /sys/kernel/debug/edac/npcm-edac/bit
+ * ~# echo 1 > /sys/kernel/debug/edac/npcm-edac/force_ecc_error
+ *
+ * 2. Inject an uncorrectable error (UE).
+ * ~# echo 1 > /sys/kernel/debug/edac/npcm-edac/error_type
+ * ~# echo 1 > /sys/kernel/debug/edac/npcm-edac/force_ecc_error
+ */
+static void setup_debugfs(struct mem_ctl_info *mci)
+{
+ struct priv_data *priv = mci->pvt_info;
+
+ priv->debugfs = edac_debugfs_create_dir(mci->mod_name);
+ if (!priv->debugfs)
+ return;
+
+ edac_debugfs_create_x8("error_type", 0644, priv->debugfs, &priv->error_type);
+ edac_debugfs_create_x8("location", 0644, priv->debugfs, &priv->location);
+ edac_debugfs_create_x8("bit", 0644, priv->debugfs, &priv->bit);
+ edac_debugfs_create_file("force_ecc_error", 0200, priv->debugfs,
+ &mci->dev, &force_ecc_error_fops);
+}
+
+static int setup_irq(struct mem_ctl_info *mci, struct platform_device *pdev)
+{
+ const struct npcm_platform_data *pdata;
+ int ret, irq;
+
+ pdata = ((struct priv_data *)mci->pvt_info)->pdata;
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ edac_printk(KERN_ERR, EDAC_MOD_NAME, "IRQ not defined in DTS\n");
+ return irq;
+ }
+
+ ret = devm_request_irq(&pdev->dev, irq, edac_ecc_isr, 0,
+ dev_name(&pdev->dev), mci);
+ if (ret < 0) {
+ edac_printk(KERN_ERR, EDAC_MOD_NAME, "failed to request IRQ\n");
+ return ret;
+ }
+
+ /* enable the functional group of ECC and mask the others */
+ regmap_write(npcm_regmap, pdata->ctl_int_mask_master,
+ pdata->int_mask_master_non_ecc_mask);
+
+ if (pdata->chip == NPCM8XX_CHIP)
+ regmap_write(npcm_regmap, pdata->ctl_int_mask_ecc,
+ pdata->int_mask_ecc_non_event_mask);
+
+ return 0;
+}
+
+static const struct regmap_config npcm_regmap_cfg = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+};
+
+static int edac_probe(struct platform_device *pdev)
+{
+ const struct npcm_platform_data *pdata;
+ struct device *dev = &pdev->dev;
+ struct edac_mc_layer layers[1];
+ struct mem_ctl_info *mci;
+ struct priv_data *priv;
+ void __iomem *reg;
+ u32 val;
+ int rc;
+
+ reg = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ npcm_regmap = devm_regmap_init_mmio(dev, reg, &npcm_regmap_cfg);
+ if (IS_ERR(npcm_regmap))
+ return PTR_ERR(npcm_regmap);
+
+ pdata = of_device_get_match_data(dev);
+ if (!pdata)
+ return -EINVAL;
+
+ /* bail out if ECC is not enabled */
+ regmap_read(npcm_regmap, pdata->ctl_ecc_en, &val);
+ if (!(val & pdata->ecc_en_mask)) {
+ edac_printk(KERN_ERR, EDAC_MOD_NAME, "ECC is not enabled\n");
+ return -EPERM;
+ }
+
+ edac_op_state = EDAC_OPSTATE_INT;
+
+ layers[0].type = EDAC_MC_LAYER_ALL_MEM;
+ layers[0].size = 1;
+
+ mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers,
+ sizeof(struct priv_data));
+ if (!mci)
+ return -ENOMEM;
+
+ mci->pdev = &pdev->dev;
+ priv = mci->pvt_info;
+ priv->reg = reg;
+ priv->pdata = pdata;
+ platform_set_drvdata(pdev, mci);
+
+ mci->mtype_cap = MEM_FLAG_DDR4;
+ mci->edac_ctl_cap = EDAC_FLAG_SECDED;
+ mci->scrub_cap = SCRUB_FLAG_HW_SRC;
+ mci->scrub_mode = SCRUB_HW_SRC;
+ mci->edac_cap = EDAC_FLAG_SECDED;
+ mci->ctl_name = "npcm_ddr_controller";
+ mci->dev_name = dev_name(&pdev->dev);
+ mci->mod_name = EDAC_MOD_NAME;
+ mci->ctl_page_to_phys = NULL;
+
+ rc = setup_irq(mci, pdev);
+ if (rc)
+ goto free_edac_mc;
+
+ rc = edac_mc_add_mc(mci);
+ if (rc)
+ goto free_edac_mc;
+
+ if (IS_ENABLED(CONFIG_EDAC_DEBUG) && pdata->chip == NPCM8XX_CHIP)
+ setup_debugfs(mci);
+
+ return rc;
+
+free_edac_mc:
+ edac_mc_free(mci);
+ return rc;
+}
+
+static int edac_remove(struct platform_device *pdev)
+{
+ struct mem_ctl_info *mci = platform_get_drvdata(pdev);
+ struct priv_data *priv = mci->pvt_info;
+ const struct npcm_platform_data *pdata;
+
+ pdata = priv->pdata;
+ if (IS_ENABLED(CONFIG_EDAC_DEBUG) && pdata->chip == NPCM8XX_CHIP)
+ edac_debugfs_remove_recursive(priv->debugfs);
+
+ edac_mc_del_mc(&pdev->dev);
+ edac_mc_free(mci);
+
+ regmap_write(npcm_regmap, pdata->ctl_int_mask_master,
+ pdata->int_mask_master_global_mask);
+ regmap_update_bits(npcm_regmap, pdata->ctl_ecc_en, pdata->ecc_en_mask, 0);
+
+ return 0;
+}
+
+static const struct npcm_platform_data npcm750_edac = {
+ .chip = NPCM7XX_CHIP,
+
+ /* memory controller registers */
+ .ctl_ecc_en = 0x174,
+ .ctl_int_status = 0x1d0,
+ .ctl_int_ack = 0x1d4,
+ .ctl_int_mask_master = 0x1d8,
+ .ctl_ce_addr_l = 0x188,
+ .ctl_ce_data_l = 0x190,
+ .ctl_ce_synd = 0x18c,
+ .ctl_ue_addr_l = 0x17c,
+ .ctl_ue_data_l = 0x184,
+ .ctl_ue_synd = 0x180,
+ .ctl_source_id = 0x194,
+
+ /* masks and shifts */
+ .ecc_en_mask = BIT(24),
+ .int_status_ce_mask = GENMASK(4, 3),
+ .int_status_ue_mask = GENMASK(6, 5),
+ .int_ack_ce_mask = GENMASK(4, 3),
+ .int_ack_ue_mask = GENMASK(6, 5),
+ .int_mask_master_non_ecc_mask = GENMASK(30, 7) | GENMASK(2, 0),
+ .int_mask_master_global_mask = BIT(31),
+ .ce_synd_mask = GENMASK(6, 0),
+ .ce_synd_shift = 0,
+ .ue_synd_mask = GENMASK(6, 0),
+ .ue_synd_shift = 0,
+ .source_id_ce_mask = GENMASK(29, 16),
+ .source_id_ce_shift = 16,
+ .source_id_ue_mask = GENMASK(13, 0),
+ .source_id_ue_shift = 0,
+};
+
+static const struct npcm_platform_data npcm845_edac = {
+ .chip = NPCM8XX_CHIP,
+
+ /* memory controller registers */
+ .ctl_ecc_en = 0x16c,
+ .ctl_int_status = 0x228,
+ .ctl_int_ack = 0x244,
+ .ctl_int_mask_master = 0x220,
+ .ctl_int_mask_ecc = 0x260,
+ .ctl_ce_addr_l = 0x18c,
+ .ctl_ce_addr_h = 0x190,
+ .ctl_ce_data_l = 0x194,
+ .ctl_ce_data_h = 0x198,
+ .ctl_ce_synd = 0x190,
+ .ctl_ue_addr_l = 0x17c,
+ .ctl_ue_addr_h = 0x180,
+ .ctl_ue_data_l = 0x184,
+ .ctl_ue_data_h = 0x188,
+ .ctl_ue_synd = 0x180,
+ .ctl_source_id = 0x19c,
+ .ctl_controller_busy = 0x20c,
+ .ctl_xor_check_bits = 0x174,
+
+ /* masks and shifts */
+ .ecc_en_mask = GENMASK(17, 16),
+ .int_status_ce_mask = GENMASK(1, 0),
+ .int_status_ue_mask = GENMASK(3, 2),
+ .int_ack_ce_mask = GENMASK(1, 0),
+ .int_ack_ue_mask = GENMASK(3, 2),
+ .int_mask_master_non_ecc_mask = GENMASK(30, 3) | GENMASK(1, 0),
+ .int_mask_master_global_mask = BIT(31),
+ .int_mask_ecc_non_event_mask = GENMASK(8, 4),
+ .ce_addr_h_mask = GENMASK(1, 0),
+ .ce_synd_mask = GENMASK(15, 8),
+ .ce_synd_shift = 8,
+ .ue_addr_h_mask = GENMASK(1, 0),
+ .ue_synd_mask = GENMASK(15, 8),
+ .ue_synd_shift = 8,
+ .source_id_ce_mask = GENMASK(29, 16),
+ .source_id_ce_shift = 16,
+ .source_id_ue_mask = GENMASK(13, 0),
+ .source_id_ue_shift = 0,
+ .controller_busy_mask = BIT(0),
+ .xor_check_bits_mask = GENMASK(23, 16),
+ .xor_check_bits_shift = 16,
+ .writeback_en_mask = BIT(24),
+ .fwc_mask = BIT(8),
+};
+
+static const struct of_device_id npcm_edac_of_match[] = {
+ {
+ .compatible = "nuvoton,npcm750-memory-controller",
+ .data = &npcm750_edac
+ },
+ {
+ .compatible = "nuvoton,npcm845-memory-controller",
+ .data = &npcm845_edac
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, npcm_edac_of_match);
+
+static struct platform_driver npcm_edac_driver = {
+ .driver = {
+ .name = "npcm-edac",
+ .of_match_table = npcm_edac_of_match,
+ },
+ .probe = edac_probe,
+ .remove = edac_remove,
+};
+
+module_platform_driver(npcm_edac_driver);
+
+MODULE_AUTHOR("Medad CChien <medadyoung@gmail.com>");
+MODULE_AUTHOR("Marvin Lin <kflin@nuvoton.com>");
+MODULE_DESCRIPTION("Nuvoton NPCM EDAC Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/edac/thunderx_edac.c b/drivers/edac/thunderx_edac.c
index 0bcd9f02c84a..b9c5772da959 100644
--- a/drivers/edac/thunderx_edac.c
+++ b/drivers/edac/thunderx_edac.c
@@ -481,7 +481,7 @@ static int thunderx_create_debugfs_nodes(struct dentry *parent,
ent = edac_debugfs_create_file(attrs[i]->name, attrs[i]->mode,
parent, data, &attrs[i]->fops);
- if (!ent)
+ if (IS_ERR(ent))
break;
}
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/mailbox.c b/drivers/firmware/arm_scmi/mailbox.c
index 1efa5e9392c4..19246ed1f01f 100644
--- a/drivers/firmware/arm_scmi/mailbox.c
+++ b/drivers/firmware/arm_scmi/mailbox.c
@@ -166,8 +166,10 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
return -ENOMEM;
shmem = of_parse_phandle(cdev->of_node, "shmem", idx);
- if (!of_device_is_compatible(shmem, "arm,scmi-shmem"))
+ if (!of_device_is_compatible(shmem, "arm,scmi-shmem")) {
+ of_node_put(shmem);
return -ENXIO;
+ }
ret = of_address_to_resource(shmem, 0, &res);
of_node_put(shmem);
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/raw_mode.c b/drivers/firmware/arm_scmi/raw_mode.c
index 6971dcf72fb9..0493aa3c12bf 100644
--- a/drivers/firmware/arm_scmi/raw_mode.c
+++ b/drivers/firmware/arm_scmi/raw_mode.c
@@ -818,10 +818,13 @@ static ssize_t scmi_dbg_raw_mode_common_write(struct file *filp,
* before sending it with a single RAW xfer.
*/
if (rd->tx_size < rd->tx_req_size) {
- size_t cnt;
+ ssize_t cnt;
cnt = simple_write_to_buffer(rd->tx.buf, rd->tx.len, ppos,
buf, count);
+ if (cnt < 0)
+ return cnt;
+
rd->tx_size += cnt;
if (cnt < count)
return cnt;
diff --git a/drivers/firmware/arm_scmi/smc.c b/drivers/firmware/arm_scmi/smc.c
index 93272e4bbd12..c193516a254d 100644
--- a/drivers/firmware/arm_scmi/smc.c
+++ b/drivers/firmware/arm_scmi/smc.c
@@ -20,9 +20,27 @@
#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
*
+ * @irq: An optional IRQ for completion
* @cinfo: SCMI channel info
* @shmem: Transmit/Receive shared memory area
* @shmem_lock: Lock to protect access to Tx/Rx shared memory area.
@@ -30,9 +48,12 @@
* @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 {
+ int irq;
struct scmi_chan_info *cinfo;
struct scmi_shared_mem __iomem *shmem;
/* Protect access to shmem area */
@@ -40,6 +61,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)
@@ -106,7 +129,7 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
struct resource res;
struct device_node *np;
u32 func_id;
- int ret, irq;
+ int ret;
if (!tx)
return -ENODEV;
@@ -116,8 +139,10 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
return -ENOMEM;
np = of_parse_phandle(cdev->of_node, "shmem", 0);
- if (!of_device_is_compatible(np, "arm,scmi-shmem"))
+ if (!of_device_is_compatible(np, "arm,scmi-shmem")) {
+ of_node_put(np);
return -ENXIO;
+ }
ret = of_address_to_resource(np, 0, &res);
of_node_put(np);
@@ -137,16 +162,19 @@ 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
* the return of the SMC call.
*/
- irq = of_irq_get_byname(cdev->of_node, "a2p");
- if (irq > 0) {
- ret = devm_request_irq(dev, irq, smc_msg_done_isr,
- IRQF_NO_SUSPEND,
- dev_name(dev), scmi_info);
+ scmi_info->irq = of_irq_get_byname(cdev->of_node, "a2p");
+ if (scmi_info->irq > 0) {
+ ret = request_irq(scmi_info->irq, smc_msg_done_isr,
+ IRQF_NO_SUSPEND, dev_name(dev), scmi_info);
if (ret) {
dev_err(dev, "failed to setup SCMI smc irq\n");
return ret;
@@ -168,6 +196,10 @@ static int smc_chan_free(int id, void *p, void *data)
struct scmi_chan_info *cinfo = p;
struct scmi_smc *scmi_info = cinfo->transport_info;
+ /* Ignore any possible further reception on the IRQ path */
+ if (scmi_info->irq > 0)
+ free_irq(scmi_info->irq, scmi_info);
+
cinfo->transport_info = NULL;
scmi_info->cinfo = NULL;
@@ -179,6 +211,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 +222,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/Kconfig b/drivers/firmware/efi/Kconfig
index 043ca31c114e..231f1c70d1db 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -269,6 +269,20 @@ config EFI_COCO_SECRET
virt/coco/efi_secret module to access the secrets, which in turn
allows userspace programs to access the injected secrets.
+config UNACCEPTED_MEMORY
+ bool
+ depends on EFI_STUB
+ help
+ Some Virtual Machine platforms, such as Intel TDX, require
+ some memory to be "accepted" by the guest before it can be used.
+ This mechanism helps prevent malicious hosts from making changes
+ to guest memory.
+
+ UEFI specification v2.9 introduced EFI_UNACCEPTED_MEMORY memory type.
+
+ This option adds support for unaccepted memory and makes such memory
+ usable by the kernel.
+
config EFI_EMBEDDED_FIRMWARE
bool
select CRYPTO_LIB_SHA256
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index b51f2a4c821e..e489fefd23da 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -41,3 +41,4 @@ obj-$(CONFIG_EFI_CAPSULE_LOADER) += capsule-loader.o
obj-$(CONFIG_EFI_EARLYCON) += earlycon.o
obj-$(CONFIG_UEFI_CPER_ARM) += cper-arm.o
obj-$(CONFIG_UEFI_CPER_X86) += cper-x86.o
+obj-$(CONFIG_UNACCEPTED_MEMORY) += unaccepted_memory.o
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 34b9e7876538..1599f1176842 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -50,6 +50,9 @@ struct efi __read_mostly efi = {
#ifdef CONFIG_EFI_COCO_SECRET
.coco_secret = EFI_INVALID_TABLE_ADDR,
#endif
+#ifdef CONFIG_UNACCEPTED_MEMORY
+ .unaccepted = EFI_INVALID_TABLE_ADDR,
+#endif
};
EXPORT_SYMBOL(efi);
@@ -211,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;
@@ -584,6 +588,9 @@ static const efi_config_table_type_t common_tables[] __initconst = {
#ifdef CONFIG_EFI_COCO_SECRET
{LINUX_EFI_COCO_SECRET_AREA_GUID, &efi.coco_secret, "CocoSecret" },
#endif
+#ifdef CONFIG_UNACCEPTED_MEMORY
+ {LINUX_EFI_UNACCEPTED_MEM_TABLE_GUID, &efi.unaccepted, "Unaccepted" },
+#endif
#ifdef CONFIG_EFI_GENERIC_STUB
{LINUX_EFI_SCREEN_INFO_TABLE_GUID, &screen_info_table },
#endif
@@ -738,6 +745,25 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
}
}
+ if (IS_ENABLED(CONFIG_UNACCEPTED_MEMORY) &&
+ efi.unaccepted != EFI_INVALID_TABLE_ADDR) {
+ struct efi_unaccepted_memory *unaccepted;
+
+ unaccepted = early_memremap(efi.unaccepted, sizeof(*unaccepted));
+ if (unaccepted) {
+ unsigned long size;
+
+ if (unaccepted->version == 1) {
+ size = sizeof(*unaccepted) + unaccepted->size;
+ memblock_reserve(efi.unaccepted, size);
+ } else {
+ efi.unaccepted = EFI_INVALID_TABLE_ADDR;
+ }
+
+ early_memunmap(unaccepted, sizeof(*unaccepted));
+ }
+ }
+
return 0;
}
@@ -822,6 +848,7 @@ static __initdata char memory_type_name[][13] = {
"MMIO Port",
"PAL Code",
"Persistent",
+ "Unaccepted",
};
char * __init efi_md_typeattr_format(char *buf, size_t size,
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/Makefile b/drivers/firmware/efi/libstub/Makefile
index 3abb2b357482..16d64a34d1e1 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -96,6 +96,8 @@ CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
zboot-obj-$(CONFIG_RISCV) := lib-clz_ctz.o lib-ashldi3.o
lib-$(CONFIG_EFI_ZBOOT) += zboot.o $(zboot-obj-y)
+lib-$(CONFIG_UNACCEPTED_MEMORY) += unaccepted_memory.o bitmap.o find.o
+
extra-y := $(lib-y)
lib-y := $(patsubst %.o,%.stub.o,$(lib-y))
diff --git a/drivers/firmware/efi/libstub/bitmap.c b/drivers/firmware/efi/libstub/bitmap.c
new file mode 100644
index 000000000000..5c9bba0d549b
--- /dev/null
+++ b/drivers/firmware/efi/libstub/bitmap.c
@@ -0,0 +1,41 @@
+#include <linux/bitmap.h>
+
+void __bitmap_set(unsigned long *map, unsigned int start, int len)
+{
+ unsigned long *p = map + BIT_WORD(start);
+ const unsigned int size = start + len;
+ int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
+ unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
+
+ while (len - bits_to_set >= 0) {
+ *p |= mask_to_set;
+ len -= bits_to_set;
+ bits_to_set = BITS_PER_LONG;
+ mask_to_set = ~0UL;
+ p++;
+ }
+ if (len) {
+ mask_to_set &= BITMAP_LAST_WORD_MASK(size);
+ *p |= mask_to_set;
+ }
+}
+
+void __bitmap_clear(unsigned long *map, unsigned int start, int len)
+{
+ unsigned long *p = map + BIT_WORD(start);
+ const unsigned int size = start + len;
+ int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
+ unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
+
+ while (len - bits_to_clear >= 0) {
+ *p &= ~mask_to_clear;
+ len -= bits_to_clear;
+ bits_to_clear = BITS_PER_LONG;
+ mask_to_clear = ~0UL;
+ p++;
+ }
+ if (len) {
+ mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
+ *p &= ~mask_to_clear;
+ }
+}
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/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 54a2822cae77..6aa38a1bf126 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -1136,4 +1136,10 @@ void efi_remap_image(unsigned long image_base, unsigned alloc_size,
asmlinkage efi_status_t __efiapi
efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab);
+efi_status_t allocate_unaccepted_bitmap(__u32 nr_desc,
+ struct efi_boot_memmap *map);
+void process_unaccepted_memory(u64 start, u64 end);
+void accept_memory(phys_addr_t start, phys_addr_t end);
+void arch_accept_memory(phys_addr_t start, phys_addr_t end);
+
#endif
diff --git a/drivers/firmware/efi/libstub/find.c b/drivers/firmware/efi/libstub/find.c
new file mode 100644
index 000000000000..4e7740d28987
--- /dev/null
+++ b/drivers/firmware/efi/libstub/find.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/bitmap.h>
+#include <linux/math.h>
+#include <linux/minmax.h>
+
+/*
+ * Common helper for find_next_bit() function family
+ * @FETCH: The expression that fetches and pre-processes each word of bitmap(s)
+ * @MUNGE: The expression that post-processes a word containing found bit (may be empty)
+ * @size: The bitmap size in bits
+ * @start: The bitnumber to start searching at
+ */
+#define FIND_NEXT_BIT(FETCH, MUNGE, size, start) \
+({ \
+ unsigned long mask, idx, tmp, sz = (size), __start = (start); \
+ \
+ if (unlikely(__start >= sz)) \
+ goto out; \
+ \
+ mask = MUNGE(BITMAP_FIRST_WORD_MASK(__start)); \
+ idx = __start / BITS_PER_LONG; \
+ \
+ for (tmp = (FETCH) & mask; !tmp; tmp = (FETCH)) { \
+ if ((idx + 1) * BITS_PER_LONG >= sz) \
+ goto out; \
+ idx++; \
+ } \
+ \
+ sz = min(idx * BITS_PER_LONG + __ffs(MUNGE(tmp)), sz); \
+out: \
+ sz; \
+})
+
+unsigned long _find_next_bit(const unsigned long *addr, unsigned long nbits, unsigned long start)
+{
+ return FIND_NEXT_BIT(addr[idx], /* nop */, nbits, start);
+}
+
+unsigned long _find_next_zero_bit(const unsigned long *addr, unsigned long nbits,
+ unsigned long start)
+{
+ return FIND_NEXT_BIT(~addr[idx], /* nop */, nbits, start);
+}
diff --git a/drivers/firmware/efi/libstub/unaccepted_memory.c b/drivers/firmware/efi/libstub/unaccepted_memory.c
new file mode 100644
index 000000000000..ca61f4733ea5
--- /dev/null
+++ b/drivers/firmware/efi/libstub/unaccepted_memory.c
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/efi.h>
+#include <asm/efi.h>
+#include "efistub.h"
+
+struct efi_unaccepted_memory *unaccepted_table;
+
+efi_status_t allocate_unaccepted_bitmap(__u32 nr_desc,
+ struct efi_boot_memmap *map)
+{
+ efi_guid_t unaccepted_table_guid = LINUX_EFI_UNACCEPTED_MEM_TABLE_GUID;
+ u64 unaccepted_start = ULLONG_MAX, unaccepted_end = 0, bitmap_size;
+ efi_status_t status;
+ int i;
+
+ /* Check if the table is already installed */
+ unaccepted_table = get_efi_config_table(unaccepted_table_guid);
+ if (unaccepted_table) {
+ if (unaccepted_table->version != 1) {
+ efi_err("Unknown version of unaccepted memory table\n");
+ return EFI_UNSUPPORTED;
+ }
+ return EFI_SUCCESS;
+ }
+
+ /* Check if there's any unaccepted memory and find the max address */
+ for (i = 0; i < nr_desc; i++) {
+ efi_memory_desc_t *d;
+ unsigned long m = (unsigned long)map->map;
+
+ d = efi_early_memdesc_ptr(m, map->desc_size, i);
+ if (d->type != EFI_UNACCEPTED_MEMORY)
+ continue;
+
+ unaccepted_start = min(unaccepted_start, d->phys_addr);
+ unaccepted_end = max(unaccepted_end,
+ d->phys_addr + d->num_pages * PAGE_SIZE);
+ }
+
+ if (unaccepted_start == ULLONG_MAX)
+ return EFI_SUCCESS;
+
+ unaccepted_start = round_down(unaccepted_start,
+ EFI_UNACCEPTED_UNIT_SIZE);
+ unaccepted_end = round_up(unaccepted_end, EFI_UNACCEPTED_UNIT_SIZE);
+
+ /*
+ * If unaccepted memory is present, allocate a bitmap to track what
+ * memory has to be accepted before access.
+ *
+ * One bit in the bitmap represents 2MiB in the address space:
+ * A 4k bitmap can track 64GiB of physical address space.
+ *
+ * In the worst case scenario -- a huge hole in the middle of the
+ * address space -- It needs 256MiB to handle 4PiB of the address
+ * space.
+ *
+ * The bitmap will be populated in setup_e820() according to the memory
+ * map after efi_exit_boot_services().
+ */
+ bitmap_size = DIV_ROUND_UP(unaccepted_end - unaccepted_start,
+ EFI_UNACCEPTED_UNIT_SIZE * BITS_PER_BYTE);
+
+ status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
+ sizeof(*unaccepted_table) + bitmap_size,
+ (void **)&unaccepted_table);
+ if (status != EFI_SUCCESS) {
+ efi_err("Failed to allocate unaccepted memory config table\n");
+ return status;
+ }
+
+ unaccepted_table->version = 1;
+ unaccepted_table->unit_size = EFI_UNACCEPTED_UNIT_SIZE;
+ unaccepted_table->phys_base = unaccepted_start;
+ unaccepted_table->size = bitmap_size;
+ memset(unaccepted_table->bitmap, 0, bitmap_size);
+
+ status = efi_bs_call(install_configuration_table,
+ &unaccepted_table_guid, unaccepted_table);
+ if (status != EFI_SUCCESS) {
+ efi_bs_call(free_pool, unaccepted_table);
+ efi_err("Failed to install unaccepted memory config table!\n");
+ }
+
+ return status;
+}
+
+/*
+ * The accepted memory bitmap only works at unit_size granularity. Take
+ * unaligned start/end addresses and either:
+ * 1. Accepts the memory immediately and in its entirety
+ * 2. Accepts unaligned parts, and marks *some* aligned part unaccepted
+ *
+ * The function will never reach the bitmap_set() with zero bits to set.
+ */
+void process_unaccepted_memory(u64 start, u64 end)
+{
+ u64 unit_size = unaccepted_table->unit_size;
+ u64 unit_mask = unaccepted_table->unit_size - 1;
+ u64 bitmap_size = unaccepted_table->size;
+
+ /*
+ * Ensure that at least one bit will be set in the bitmap by
+ * immediately accepting all regions under 2*unit_size. This is
+ * imprecise and may immediately accept some areas that could
+ * have been represented in the bitmap. But, results in simpler
+ * code below
+ *
+ * Consider case like this (assuming unit_size == 2MB):
+ *
+ * | 4k | 2044k | 2048k |
+ * ^ 0x0 ^ 2MB ^ 4MB
+ *
+ * Only the first 4k has been accepted. The 0MB->2MB region can not be
+ * represented in the bitmap. The 2MB->4MB region can be represented in
+ * the bitmap. But, the 0MB->4MB region is <2*unit_size and will be
+ * immediately accepted in its entirety.
+ */
+ if (end - start < 2 * unit_size) {
+ arch_accept_memory(start, end);
+ return;
+ }
+
+ /*
+ * No matter how the start and end are aligned, at least one unaccepted
+ * unit_size area will remain to be marked in the bitmap.
+ */
+
+ /* Immediately accept a <unit_size piece at the start: */
+ if (start & unit_mask) {
+ arch_accept_memory(start, round_up(start, unit_size));
+ start = round_up(start, unit_size);
+ }
+
+ /* Immediately accept a <unit_size piece at the end: */
+ if (end & unit_mask) {
+ arch_accept_memory(round_down(end, unit_size), end);
+ end = round_down(end, unit_size);
+ }
+
+ /*
+ * Accept part of the range that before phys_base and cannot be recorded
+ * into the bitmap.
+ */
+ if (start < unaccepted_table->phys_base) {
+ arch_accept_memory(start,
+ min(unaccepted_table->phys_base, end));
+ start = unaccepted_table->phys_base;
+ }
+
+ /* Nothing to record */
+ if (end < unaccepted_table->phys_base)
+ return;
+
+ /* Translate to offsets from the beginning of the bitmap */
+ start -= unaccepted_table->phys_base;
+ end -= unaccepted_table->phys_base;
+
+ /* Accept memory that doesn't fit into bitmap */
+ if (end > bitmap_size * unit_size * BITS_PER_BYTE) {
+ unsigned long phys_start, phys_end;
+
+ phys_start = bitmap_size * unit_size * BITS_PER_BYTE +
+ unaccepted_table->phys_base;
+ phys_end = end + unaccepted_table->phys_base;
+
+ arch_accept_memory(phys_start, phys_end);
+ end = bitmap_size * unit_size * BITS_PER_BYTE;
+ }
+
+ /*
+ * 'start' and 'end' are now both unit_size-aligned.
+ * Record the range as being unaccepted:
+ */
+ bitmap_set(unaccepted_table->bitmap,
+ start / unit_size, (end - start) / unit_size);
+}
+
+void accept_memory(phys_addr_t start, phys_addr_t end)
+{
+ unsigned long range_start, range_end;
+ unsigned long bitmap_size;
+ u64 unit_size;
+
+ if (!unaccepted_table)
+ return;
+
+ unit_size = unaccepted_table->unit_size;
+
+ /*
+ * Only care for the part of the range that is represented
+ * in the bitmap.
+ */
+ if (start < unaccepted_table->phys_base)
+ start = unaccepted_table->phys_base;
+ if (end < unaccepted_table->phys_base)
+ return;
+
+ /* Translate to offsets from the beginning of the bitmap */
+ start -= unaccepted_table->phys_base;
+ end -= unaccepted_table->phys_base;
+
+ /* Make sure not to overrun the bitmap */
+ if (end > unaccepted_table->size * unit_size * BITS_PER_BYTE)
+ end = unaccepted_table->size * unit_size * BITS_PER_BYTE;
+
+ range_start = start / unit_size;
+ bitmap_size = DIV_ROUND_UP(end, unit_size);
+
+ for_each_set_bitrange_from(range_start, range_end,
+ unaccepted_table->bitmap, bitmap_size) {
+ unsigned long phys_start, phys_end;
+
+ phys_start = range_start * unit_size + unaccepted_table->phys_base;
+ phys_end = range_end * unit_size + unaccepted_table->phys_base;
+
+ arch_accept_memory(phys_start, phys_end);
+ bitmap_clear(unaccepted_table->bitmap,
+ range_start, range_end - range_start);
+ }
+}
diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index a0bfd31358ba..220be75a5cdc 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -26,6 +26,17 @@ const efi_dxe_services_table_t *efi_dxe_table;
u32 image_offset __section(".data");
static efi_loaded_image_t *image = NULL;
+typedef union sev_memory_acceptance_protocol sev_memory_acceptance_protocol_t;
+union sev_memory_acceptance_protocol {
+ struct {
+ efi_status_t (__efiapi * allow_unaccepted_memory)(
+ sev_memory_acceptance_protocol_t *);
+ };
+ struct {
+ u32 allow_unaccepted_memory;
+ } mixed_mode;
+};
+
static efi_status_t
preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
{
@@ -310,6 +321,29 @@ setup_memory_protection(unsigned long image_base, unsigned long image_size)
#endif
}
+static void setup_unaccepted_memory(void)
+{
+ efi_guid_t mem_acceptance_proto = OVMF_SEV_MEMORY_ACCEPTANCE_PROTOCOL_GUID;
+ sev_memory_acceptance_protocol_t *proto;
+ efi_status_t status;
+
+ if (!IS_ENABLED(CONFIG_UNACCEPTED_MEMORY))
+ return;
+
+ /*
+ * Enable unaccepted memory before calling exit boot services in order
+ * for the UEFI to not accept all memory on EBS.
+ */
+ status = efi_bs_call(locate_protocol, &mem_acceptance_proto, NULL,
+ (void **)&proto);
+ if (status != EFI_SUCCESS)
+ return;
+
+ status = efi_call_proto(proto, allow_unaccepted_memory);
+ if (status != EFI_SUCCESS)
+ efi_err("Memory acceptance protocol failed\n");
+}
+
static const efi_char16_t apple[] = L"Apple";
static void setup_quirks(struct boot_params *boot_params,
@@ -613,6 +647,16 @@ setup_e820(struct boot_params *params, struct setup_data *e820ext, u32 e820ext_s
e820_type = E820_TYPE_PMEM;
break;
+ case EFI_UNACCEPTED_MEMORY:
+ if (!IS_ENABLED(CONFIG_UNACCEPTED_MEMORY)) {
+ efi_warn_once(
+"The system has unaccepted memory, but kernel does not support it\nConsider enabling CONFIG_UNACCEPTED_MEMORY\n");
+ continue;
+ }
+ e820_type = E820_TYPE_RAM;
+ process_unaccepted_memory(d->phys_addr,
+ d->phys_addr + PAGE_SIZE * d->num_pages);
+ break;
default:
continue;
}
@@ -681,28 +725,27 @@ static efi_status_t allocate_e820(struct boot_params *params,
struct setup_data **e820ext,
u32 *e820ext_size)
{
- unsigned long map_size, desc_size, map_key;
+ struct efi_boot_memmap *map;
efi_status_t status;
- __u32 nr_desc, desc_version;
-
- /* Only need the size of the mem map and size of each mem descriptor */
- map_size = 0;
- status = efi_bs_call(get_memory_map, &map_size, NULL, &map_key,
- &desc_size, &desc_version);
- if (status != EFI_BUFFER_TOO_SMALL)
- return (status != EFI_SUCCESS) ? status : EFI_UNSUPPORTED;
+ __u32 nr_desc;
- nr_desc = map_size / desc_size + EFI_MMAP_NR_SLACK_SLOTS;
+ status = efi_get_memory_map(&map, false);
+ if (status != EFI_SUCCESS)
+ return status;
- if (nr_desc > ARRAY_SIZE(params->e820_table)) {
- u32 nr_e820ext = nr_desc - ARRAY_SIZE(params->e820_table);
+ nr_desc = map->map_size / map->desc_size;
+ if (nr_desc > ARRAY_SIZE(params->e820_table) - EFI_MMAP_NR_SLACK_SLOTS) {
+ u32 nr_e820ext = nr_desc - ARRAY_SIZE(params->e820_table) +
+ EFI_MMAP_NR_SLACK_SLOTS;
status = alloc_e820ext(nr_e820ext, e820ext, e820ext_size);
- if (status != EFI_SUCCESS)
- return status;
}
- return EFI_SUCCESS;
+ if (IS_ENABLED(CONFIG_UNACCEPTED_MEMORY) && status == EFI_SUCCESS)
+ status = allocate_unaccepted_bitmap(nr_desc, map);
+
+ efi_bs_call(free_pool, map);
+ return status;
}
struct exit_boot_struct {
@@ -899,6 +942,8 @@ asmlinkage unsigned long efi_main(efi_handle_t handle,
setup_quirks(boot_params, bzimage_addr, buffer_end - buffer_start);
+ setup_unaccepted_memory();
+
status = exit_boot(boot_params, handle);
if (status != EFI_SUCCESS) {
efi_err("exit_boot() failed!\n");
diff --git a/drivers/firmware/efi/unaccepted_memory.c b/drivers/firmware/efi/unaccepted_memory.c
new file mode 100644
index 000000000000..853f7dc3c21d
--- /dev/null
+++ b/drivers/firmware/efi/unaccepted_memory.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/efi.h>
+#include <linux/memblock.h>
+#include <linux/spinlock.h>
+#include <asm/unaccepted_memory.h>
+
+/* Protects unaccepted memory bitmap */
+static DEFINE_SPINLOCK(unaccepted_memory_lock);
+
+/*
+ * accept_memory() -- Consult bitmap and accept the memory if needed.
+ *
+ * Only memory that is explicitly marked as unaccepted in the bitmap requires
+ * an action. All the remaining memory is implicitly accepted and doesn't need
+ * acceptance.
+ *
+ * No need to accept:
+ * - anything if the system has no unaccepted table;
+ * - memory that is below phys_base;
+ * - memory that is above the memory that addressable by the bitmap;
+ */
+void accept_memory(phys_addr_t start, phys_addr_t end)
+{
+ struct efi_unaccepted_memory *unaccepted;
+ unsigned long range_start, range_end;
+ unsigned long flags;
+ u64 unit_size;
+
+ unaccepted = efi_get_unaccepted_table();
+ if (!unaccepted)
+ return;
+
+ unit_size = unaccepted->unit_size;
+
+ /*
+ * Only care for the part of the range that is represented
+ * in the bitmap.
+ */
+ if (start < unaccepted->phys_base)
+ start = unaccepted->phys_base;
+ if (end < unaccepted->phys_base)
+ return;
+
+ /* Translate to offsets from the beginning of the bitmap */
+ start -= unaccepted->phys_base;
+ end -= unaccepted->phys_base;
+
+ /*
+ * load_unaligned_zeropad() can lead to unwanted loads across page
+ * boundaries. The unwanted loads are typically harmless. But, they
+ * might be made to totally unrelated or even unmapped memory.
+ * load_unaligned_zeropad() relies on exception fixup (#PF, #GP and now
+ * #VE) to recover from these unwanted loads.
+ *
+ * But, this approach does not work for unaccepted memory. For TDX, a
+ * load from unaccepted memory will not lead to a recoverable exception
+ * within the guest. The guest will exit to the VMM where the only
+ * recourse is to terminate the guest.
+ *
+ * There are two parts to fix this issue and comprehensively avoid
+ * access to unaccepted memory. Together these ensure that an extra
+ * "guard" page is accepted in addition to the memory that needs to be
+ * used:
+ *
+ * 1. Implicitly extend the range_contains_unaccepted_memory(start, end)
+ * checks up to end+unit_size if 'end' is aligned on a unit_size
+ * boundary.
+ *
+ * 2. Implicitly extend accept_memory(start, end) to end+unit_size if
+ * 'end' is aligned on a unit_size boundary. (immediately following
+ * this comment)
+ */
+ if (!(end % unit_size))
+ end += unit_size;
+
+ /* Make sure not to overrun the bitmap */
+ if (end > unaccepted->size * unit_size * BITS_PER_BYTE)
+ end = unaccepted->size * unit_size * BITS_PER_BYTE;
+
+ range_start = start / unit_size;
+
+ spin_lock_irqsave(&unaccepted_memory_lock, flags);
+ for_each_set_bitrange_from(range_start, range_end, unaccepted->bitmap,
+ DIV_ROUND_UP(end, unit_size)) {
+ unsigned long phys_start, phys_end;
+ unsigned long len = range_end - range_start;
+
+ phys_start = range_start * unit_size + unaccepted->phys_base;
+ phys_end = range_end * unit_size + unaccepted->phys_base;
+
+ arch_accept_memory(phys_start, phys_end);
+ bitmap_clear(unaccepted->bitmap, range_start, len);
+ }
+ spin_unlock_irqrestore(&unaccepted_memory_lock, flags);
+}
+
+bool range_contains_unaccepted_memory(phys_addr_t start, phys_addr_t end)
+{
+ struct efi_unaccepted_memory *unaccepted;
+ unsigned long flags;
+ bool ret = false;
+ u64 unit_size;
+
+ unaccepted = efi_get_unaccepted_table();
+ if (!unaccepted)
+ return false;
+
+ unit_size = unaccepted->unit_size;
+
+ /*
+ * Only care for the part of the range that is represented
+ * in the bitmap.
+ */
+ if (start < unaccepted->phys_base)
+ start = unaccepted->phys_base;
+ if (end < unaccepted->phys_base)
+ return false;
+
+ /* Translate to offsets from the beginning of the bitmap */
+ start -= unaccepted->phys_base;
+ end -= unaccepted->phys_base;
+
+ /*
+ * Also consider the unaccepted state of the *next* page. See fix #1 in
+ * the comment on load_unaligned_zeropad() in accept_memory().
+ */
+ if (!(end % unit_size))
+ end += unit_size;
+
+ /* Make sure not to overrun the bitmap */
+ if (end > unaccepted->size * unit_size * BITS_PER_BYTE)
+ end = unaccepted->size * unit_size * BITS_PER_BYTE;
+
+ spin_lock_irqsave(&unaccepted_memory_lock, flags);
+ while (start < end) {
+ if (test_bit(start / unit_size, unaccepted->bitmap)) {
+ ret = true;
+ break;
+ }
+
+ start += unit_size;
+ }
+ spin_unlock_irqrestore(&unaccepted_memory_lock, flags);
+
+ return ret;
+}
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/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c
index 94b49ccd23ac..71f51303c2ba 100644
--- a/drivers/firmware/iscsi_ibft_find.c
+++ b/drivers/firmware/iscsi_ibft_find.c
@@ -42,8 +42,6 @@ static const struct {
};
#define IBFT_SIGN_LEN 4
-#define IBFT_START 0x80000 /* 512kB */
-#define IBFT_END 0x100000 /* 1MB */
#define VGA_MEM 0xA0000 /* VGA buffer */
#define VGA_SIZE 0x20000 /* 128kB */
@@ -52,9 +50,9 @@ static const struct {
*/
void __init reserve_ibft_region(void)
{
- unsigned long pos;
+ unsigned long pos, virt_pos = 0;
unsigned int len = 0;
- void *virt;
+ void *virt = NULL;
int i;
ibft_phys_addr = 0;
@@ -70,13 +68,20 @@ void __init reserve_ibft_region(void)
* so skip that area */
if (pos == VGA_MEM)
pos += VGA_SIZE;
- virt = isa_bus_to_virt(pos);
+
+ /* Map page by page */
+ if (offset_in_page(pos) == 0) {
+ if (virt)
+ early_memunmap(virt, PAGE_SIZE);
+ virt = early_memremap_ro(pos, PAGE_SIZE);
+ virt_pos = pos;
+ }
for (i = 0; i < ARRAY_SIZE(ibft_signs); i++) {
- if (memcmp(virt, ibft_signs[i].sign, IBFT_SIGN_LEN) ==
- 0) {
+ if (memcmp(virt + (pos - virt_pos), ibft_signs[i].sign,
+ IBFT_SIGN_LEN) == 0) {
unsigned long *addr =
- (unsigned long *)isa_bus_to_virt(pos + 4);
+ (unsigned long *)(virt + pos - virt_pos + 4);
len = *addr;
/* if the length of the table extends past 1M,
* the table cannot be valid. */
@@ -84,9 +89,12 @@ void __init reserve_ibft_region(void)
ibft_phys_addr = pos;
memblock_reserve(ibft_phys_addr, PAGE_ALIGN(len));
pr_info("iBFT found at %pa.\n", &ibft_phys_addr);
- return;
+ goto out;
}
}
}
}
+
+out:
+ early_memunmap(virt, PAGE_SIZE);
}
diff --git a/drivers/firmware/smccc/soc_id.c b/drivers/firmware/smccc/soc_id.c
index 890eb454599a..1990263fbba0 100644
--- a/drivers/firmware/smccc/soc_id.c
+++ b/drivers/firmware/smccc/soc_id.c
@@ -34,7 +34,6 @@ static struct soc_device_attribute *soc_dev_attr;
static int __init smccc_soc_init(void)
{
- struct arm_smccc_res res;
int soc_id_rev, soc_id_version;
static char soc_id_str[20], soc_id_rev_str[12];
static char soc_id_jep106_id_str[12];
@@ -49,13 +48,13 @@ static int __init smccc_soc_init(void)
}
if (soc_id_version < 0) {
- pr_err("ARCH_SOC_ID(0) returned error: %lx\n", res.a0);
+ pr_err("Invalid SoC Version: %x\n", soc_id_version);
return -EINVAL;
}
soc_id_rev = arm_smccc_get_soc_id_revision();
if (soc_id_rev < 0) {
- pr_err("ARCH_SOC_ID(1) returned error: %lx\n", res.a0);
+ pr_err("Invalid SoC Revision: %x\n", soc_id_rev);
return -EINVAL;
}
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-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c
index f2253fd5ab4b..8ff5f4ff5958 100644
--- a/drivers/gpio/gpio-104-dio-48e.c
+++ b/drivers/gpio/gpio-104-dio-48e.c
@@ -100,13 +100,23 @@ static const struct regmap_irq dio48e_regmap_irqs[] = {
DIO48E_REGMAP_IRQ(0), DIO48E_REGMAP_IRQ(1),
};
-static int dio48e_handle_mask_sync(struct regmap *const map, const int index,
+/**
+ * struct dio48e_gpio - GPIO device private data structure
+ * @map: Regmap for the device
+ * @irq_mask: Current IRQ mask state on the device
+ */
+struct dio48e_gpio {
+ struct regmap *map;
+ unsigned int irq_mask;
+};
+
+static int dio48e_handle_mask_sync(const int index,
const unsigned int mask_buf_def,
const unsigned int mask_buf,
void *const irq_drv_data)
{
- unsigned int *const irq_mask = irq_drv_data;
- const unsigned int prev_mask = *irq_mask;
+ struct dio48e_gpio *const dio48egpio = irq_drv_data;
+ const unsigned int prev_mask = dio48egpio->irq_mask;
int err;
unsigned int val;
@@ -115,19 +125,19 @@ static int dio48e_handle_mask_sync(struct regmap *const map, const int index,
return 0;
/* remember the current mask for the next mask sync */
- *irq_mask = mask_buf;
+ dio48egpio->irq_mask = mask_buf;
/* if all previously masked, enable interrupts when unmasking */
if (prev_mask == mask_buf_def) {
- err = regmap_write(map, DIO48E_CLEAR_INTERRUPT, 0x00);
+ err = regmap_write(dio48egpio->map, DIO48E_CLEAR_INTERRUPT, 0x00);
if (err)
return err;
- return regmap_write(map, DIO48E_ENABLE_INTERRUPT, 0x00);
+ return regmap_write(dio48egpio->map, DIO48E_ENABLE_INTERRUPT, 0x00);
}
/* if all are currently masked, disable interrupts */
if (mask_buf == mask_buf_def)
- return regmap_read(map, DIO48E_DISABLE_INTERRUPT, &val);
+ return regmap_read(dio48egpio->map, DIO48E_DISABLE_INTERRUPT, &val);
return 0;
}
@@ -168,7 +178,7 @@ static int dio48e_probe(struct device *dev, unsigned int id)
struct regmap *map;
int err;
struct regmap_irq_chip *chip;
- unsigned int irq_mask;
+ struct dio48e_gpio *dio48egpio;
struct regmap_irq_chip_data *chip_data;
if (!devm_request_region(dev, base[id], DIO48E_EXTENT, name)) {
@@ -186,12 +196,14 @@ static int dio48e_probe(struct device *dev, unsigned int id)
return dev_err_probe(dev, PTR_ERR(map),
"Unable to initialize register map\n");
- chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
- if (!chip)
+ dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL);
+ if (!dio48egpio)
return -ENOMEM;
- chip->irq_drv_data = devm_kzalloc(dev, sizeof(irq_mask), GFP_KERNEL);
- if (!chip->irq_drv_data)
+ dio48egpio->map = map;
+
+ chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
return -ENOMEM;
chip->name = name;
@@ -202,6 +214,7 @@ static int dio48e_probe(struct device *dev, unsigned int id)
chip->irqs = dio48e_regmap_irqs;
chip->num_irqs = ARRAY_SIZE(dio48e_regmap_irqs);
chip->handle_mask_sync = dio48e_handle_mask_sync;
+ chip->irq_drv_data = dio48egpio;
/* Initialize to prevent spurious interrupts before we're ready */
err = dio48e_irq_init_hw(map);
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-mvebu.c b/drivers/gpio/gpio-mvebu.c
index a68f682aec01..67497116ce27 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -874,7 +874,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
spin_lock_init(&mvpwm->lock);
- return pwmchip_add(&mvpwm->chip);
+ return devm_pwmchip_add(dev, &mvpwm->chip);
}
#ifdef CONFIG_DEBUG_FS
@@ -1112,6 +1112,13 @@ static int mvebu_gpio_probe_syscon(struct platform_device *pdev,
return 0;
}
+static void mvebu_gpio_remove_irq_domain(void *data)
+{
+ struct irq_domain *domain = data;
+
+ irq_domain_remove(domain);
+}
+
static int mvebu_gpio_probe(struct platform_device *pdev)
{
struct mvebu_gpio_chip *mvchip;
@@ -1243,17 +1250,21 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
if (!mvchip->domain) {
dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n",
mvchip->chip.label);
- err = -ENODEV;
- goto err_pwm;
+ return -ENODEV;
}
+ err = devm_add_action_or_reset(&pdev->dev, mvebu_gpio_remove_irq_domain,
+ mvchip->domain);
+ if (err)
+ return err;
+
err = irq_alloc_domain_generic_chips(
mvchip->domain, ngpios, 2, np->name, handle_level_irq,
IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_LEVEL, 0, 0);
if (err) {
dev_err(&pdev->dev, "couldn't allocate irq chips %s (DT).\n",
mvchip->chip.label);
- goto err_domain;
+ return err;
}
/*
@@ -1293,13 +1304,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
}
return 0;
-
-err_domain:
- irq_domain_remove(mvchip->domain);
-err_pwm:
- pwmchip_remove(&mvchip->mvpwm->chip);
-
- return err;
}
static struct platform_driver mvebu_gpio_driver = {
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-sim.c b/drivers/gpio/gpio-sim.c
index 8b49b0abacd5..533d81572579 100644
--- a/drivers/gpio/gpio-sim.c
+++ b/drivers/gpio/gpio-sim.c
@@ -291,6 +291,15 @@ static void gpio_sim_mutex_destroy(void *data)
mutex_destroy(lock);
}
+static void gpio_sim_dispose_mappings(void *data)
+{
+ struct gpio_sim_chip *chip = data;
+ unsigned int i;
+
+ for (i = 0; i < chip->gc.ngpio; i++)
+ irq_dispose_mapping(irq_find_mapping(chip->irq_sim, i));
+}
+
static void gpio_sim_sysfs_remove(void *data)
{
struct gpio_sim_chip *chip = data;
@@ -402,10 +411,14 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev)
if (!chip->pull_map)
return -ENOMEM;
- chip->irq_sim = devm_irq_domain_create_sim(dev, NULL, num_lines);
+ chip->irq_sim = devm_irq_domain_create_sim(dev, swnode, num_lines);
if (IS_ERR(chip->irq_sim))
return PTR_ERR(chip->irq_sim);
+ ret = devm_add_action_or_reset(dev, gpio_sim_dispose_mappings, chip);
+ if (ret)
+ return ret;
+
mutex_init(&chip->lock);
ret = devm_add_action_or_reset(dev, gpio_sim_mutex_destroy,
&chip->lock);
@@ -429,6 +442,7 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev)
gc->set_config = gpio_sim_set_config;
gc->to_irq = gpio_sim_to_irq;
gc->free = gpio_sim_free;
+ gc->can_sleep = true;
ret = devm_gpiochip_add_data(dev, gc, chip);
if (ret)
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-tps68470.c b/drivers/gpio/gpio-tps68470.c
index aaddcabe9b35..532deaddfd4e 100644
--- a/drivers/gpio/gpio-tps68470.c
+++ b/drivers/gpio/gpio-tps68470.c
@@ -91,13 +91,13 @@ static int tps68470_gpio_output(struct gpio_chip *gc, unsigned int offset,
struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
struct regmap *regmap = tps68470_gpio->tps68470_regmap;
+ /* Set the initial value */
+ tps68470_gpio_set(gc, offset, value);
+
/* rest are always outputs */
if (offset >= TPS68470_N_REGULAR_GPIO)
return 0;
- /* Set the initial value */
- tps68470_gpio_set(gc, offset, value);
-
return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset),
TPS68470_GPIO_MODE_MASK,
TPS68470_GPIO_MODE_OUT_CMOS);
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-ws16c48.c b/drivers/gpio/gpio-ws16c48.c
index e73885a4dc32..afb42a8e916f 100644
--- a/drivers/gpio/gpio-ws16c48.c
+++ b/drivers/gpio/gpio-ws16c48.c
@@ -18,7 +18,7 @@
#include <linux/spinlock.h>
#include <linux/types.h>
-#define WS16C48_EXTENT 10
+#define WS16C48_EXTENT 11
#define MAX_NUM_WS16C48 max_num_isa_dev(WS16C48_EXTENT)
static unsigned int base[MAX_NUM_WS16C48];
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-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index 530dfd19d7b5..50503a4525eb 100644
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -515,8 +515,9 @@ static ssize_t unexport_store(const struct class *class,
* they may be undone on its behalf too.
*/
if (test_and_clear_bit(FLAG_SYSFS, &desc->flags)) {
- status = 0;
+ gpiod_unexport(desc);
gpiod_free(desc);
+ status = 0;
}
done:
if (status)
@@ -781,8 +782,10 @@ void gpiochip_sysfs_unregister(struct gpio_device *gdev)
mutex_unlock(&sysfs_lock);
/* unregister gpiod class devices owned by sysfs */
- for_each_gpio_desc_with_flag(chip, desc, FLAG_SYSFS)
+ for_each_gpio_desc_with_flag(chip, desc, FLAG_SYSFS) {
+ gpiod_unexport(desc);
gpiod_free(desc);
+ }
}
static int __init gpiolib_sysfs_init(void)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 5be8ad61523e..76e0c38026c3 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;
@@ -2175,12 +2167,18 @@ static bool gpiod_free_commit(struct gpio_desc *desc)
void gpiod_free(struct gpio_desc *desc)
{
- if (desc && desc->gdev && gpiod_free_commit(desc)) {
- module_put(desc->gdev->owner);
- gpio_device_put(desc->gdev);
- } else {
+ /*
+ * We must not use VALIDATE_DESC_VOID() as the underlying gdev->chip
+ * may already be NULL but we still want to put the references.
+ */
+ if (!desc)
+ return;
+
+ if (!gpiod_free_commit(desc))
WARN_ON(extra_checks);
- }
+
+ module_put(desc->gdev->owner);
+ gpio_device_put(desc->gdev);
}
/**
@@ -4252,7 +4250,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..6dc950c1b689 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,10 @@ extern int amdgpu_sg_display;
#define AMDGPU_SMARTSHIFT_MAX_BIAS (100)
#define AMDGPU_SMARTSHIFT_MIN_BIAS (-100)
+/* Extra time delay(in ms) to eliminate the influence of temperature momentary fluctuation */
+#define AMDGPU_SWCTF_EXTRA_DELAY 50
+
+struct amdgpu_xcp_mgr;
struct amdgpu_device;
struct amdgpu_irq_src;
struct amdgpu_fpriv;
@@ -463,6 +471,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 +583,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 +619,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 +672,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 +680,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 +776,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 +824,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 +859,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 +991,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 +1050,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 +1083,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 +1116,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 +1179,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 +1248,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 +1280,11 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
#define amdgpu_inc_vram_lost(adev) atomic_inc(&((adev)->vram_lost_counter));
+#define BIT_MASK_UPPER(i) ((i) >= BITS_PER_LONG ? 0 : ~0UL << (i))
+#define for_each_inst(i, inst_mask) \
+ for (i = ffs(inst_mask); i-- != 0; \
+ i = ffs(inst_mask & BIT_MASK_UPPER(i + 1)))
+
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
/* Common functions */
@@ -1246,6 +1296,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
void amdgpu_device_pci_config_reset(struct amdgpu_device *adev);
int amdgpu_device_pci_reset(struct amdgpu_device *adev);
bool amdgpu_device_need_post(struct amdgpu_device *adev);
+bool amdgpu_sg_display_supported(struct amdgpu_device *adev);
+bool amdgpu_device_pcie_dynamic_switching_supported(void);
bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev);
bool amdgpu_device_aspm_support_quirk(void);
@@ -1348,6 +1400,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 +1423,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..d34c3ef8f3ed 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,18 @@ 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 == AMDGPU_XCP_NO_PARTITION ?
+ 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 +1762,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 +1799,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 +1831,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 +1927,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 +2357,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 +2521,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 +2655,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 +2671,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);
@@ -2792,6 +2882,9 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef)
if (!attachment->is_mapped)
continue;
+ if (attachment->bo_va->base.bo->tbo.pin_count)
+ continue;
+
kfd_mem_dmaunmap_attachment(mem, attachment);
ret = update_gpuvm_pte(mem, attachment, &sync_obj);
if (ret) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
index 9ba4817a9148..f4e3c133a16c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
@@ -1791,6 +1791,15 @@ const struct attribute_group amdgpu_vbios_version_attr_group = {
.attrs = amdgpu_vbios_version_attrs
};
+int amdgpu_atombios_sysfs_init(struct amdgpu_device *adev)
+{
+ if (adev->mode_info.atom_context)
+ return devm_device_add_group(adev->dev,
+ &amdgpu_vbios_version_attr_group);
+
+ return 0;
+}
+
/**
* amdgpu_atombios_fini - free the driver info and callbacks for atombios
*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h
index 4153d520e2a3..b639a80ee3fc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h
@@ -217,5 +217,6 @@ int amdgpu_atombios_get_data_table(struct amdgpu_device *adev,
void amdgpu_atombios_fini(struct amdgpu_device *adev);
int amdgpu_atombios_init(struct amdgpu_device *adev);
+int amdgpu_atombios_sysfs_init(struct amdgpu_device *adev);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
index ac6fe0ae4609..0b7f4c4d58e5 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:
@@ -326,10 +327,13 @@ amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
mem_channel_number = igp_info->v11.umachannelnumber;
if (!mem_channel_number)
mem_channel_number = 1;
- /* channel width is 64 */
- if (vram_width)
- *vram_width = mem_channel_number * 64;
mem_type = igp_info->v11.memorytype;
+ if (mem_type == LpDdr5MemType)
+ mem_channel_width = 32;
+ else
+ mem_channel_width = 64;
+ if (vram_width)
+ *vram_width = mem_channel_number * mem_channel_width;
if (vram_type)
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
break;
@@ -344,10 +348,13 @@ amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
mem_channel_number = igp_info->v21.umachannelnumber;
if (!mem_channel_number)
mem_channel_number = 1;
- /* channel width is 64 */
- if (vram_width)
- *vram_width = mem_channel_number * 64;
mem_type = igp_info->v21.memorytype;
+ if (mem_type == LpDdr5MemType)
+ mem_channel_width = 32;
+ else
+ mem_channel_width = 64;
+ if (vram_width)
+ *vram_width = mem_channel_number * mem_channel_width;
if (vram_type)
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
break;
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..fb78a8f47587 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;
@@ -133,9 +136,6 @@ static int amdgpu_cs_p1_user_fence(struct amdgpu_cs_parser *p,
bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
p->uf_entry.priority = 0;
p->uf_entry.tv.bo = &bo->tbo;
- /* One for TTM and two for the CS job */
- p->uf_entry.tv.num_shared = 3;
-
drm_gem_object_put(gobj);
size = amdgpu_bo_size(bo);
@@ -192,7 +192,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 +285,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:
@@ -294,7 +295,7 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
if (!p->gang_size) {
ret = -EINVAL;
- goto free_partial_kdata;
+ goto free_all_kdata;
}
for (i = 0; i < p->gang_size; ++i) {
@@ -305,7 +306,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 +394,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 +465,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 +483,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 +503,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 +537,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 +576,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 +638,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 +755,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);
@@ -882,15 +909,19 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
mutex_lock(&p->bo_list->bo_list_mutex);
- /* One for TTM and one for the CS job */
+ /* One for TTM and one for each CS job */
amdgpu_bo_list_for_each_entry(e, p->bo_list)
- e->tv.num_shared = 2;
+ e->tv.num_shared = 1 + p->gang_size;
+ p->uf_entry.tv.num_shared = 1 + p->gang_size;
amdgpu_bo_list_get_list(p->bo_list, &p->validated);
INIT_LIST_HEAD(&duplicates);
amdgpu_vm_get_pd_bo(&fpriv->vm, &p->validated, &p->vm_pd);
+ /* Two for VM updates, one for TTM and one for each CS job */
+ p->vm_pd.tv.num_shared = 3 + p->gang_size;
+
if (p->uf_entry.tv.bo && !ttm_to_amdgpu_bo(p->uf_entry.tv.bo)->parent)
list_add(&p->uf_entry.tv.head, &p->validated);
@@ -1047,9 +1078,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 +1386,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++) {
@@ -1624,15 +1654,15 @@ static int amdgpu_cs_wait_all_fences(struct amdgpu_device *adev,
continue;
r = dma_fence_wait_timeout(fence, true, timeout);
+ if (r > 0 && fence->error)
+ r = fence->error;
+
dma_fence_put(fence);
if (r < 0)
return r;
if (r == 0)
break;
-
- if (fence->error)
- return fence->error;
}
memset(wait, 0, sizeof(*wait));
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..6238701cde23 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
@@ -1352,6 +1458,51 @@ bool amdgpu_device_need_post(struct amdgpu_device *adev)
return true;
}
+/*
+ * On APUs with >= 64GB white flickering has been observed w/ SG enabled.
+ * Disable S/G on such systems until we have a proper fix.
+ * https://gitlab.freedesktop.org/drm/amd/-/issues/2354
+ * https://gitlab.freedesktop.org/drm/amd/-/issues/2735
+ */
+bool amdgpu_sg_display_supported(struct amdgpu_device *adev)
+{
+ switch (amdgpu_sg_display) {
+ case -1:
+ break;
+ case 0:
+ return false;
+ case 1:
+ return true;
+ default:
+ return false;
+ }
+ if ((totalram_pages() << (PAGE_SHIFT - 10)) +
+ (adev->gmc.real_vram_size / 1024) >= 64000000) {
+ DRM_WARN("Disabling S/G due to >=64GB RAM\n");
+ return false;
+ }
+ return true;
+}
+
+/*
+ * Intel hosts such as Raptor Lake and Sapphire Rapids don't support dynamic
+ * speed switching. Until we have confirmation from Intel that a specific host
+ * supports it, it's safer that we keep it disabled for all.
+ *
+ * https://edc.intel.com/content/www/us/en/design/products/platforms/details/raptor-lake-s/13th-generation-core-processors-datasheet-volume-1-of-2/005/pci-express-support/
+ * https://gitlab.freedesktop.org/drm/amd/-/issues/2663
+ */
+bool amdgpu_device_pcie_dynamic_switching_supported(void)
+{
+#if IS_ENABLED(CONFIG_X86)
+ struct cpuinfo_x86 *c = &cpu_data(0);
+
+ if (c->x86_vendor == X86_VENDOR_INTEL)
+ return false;
+#endif
+ return true;
+}
+
/**
* amdgpu_device_should_use_aspm - check if the device should program ASPM
*
@@ -1547,7 +1698,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 +2345,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 +2371,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 +2529,8 @@ static int amdgpu_device_init_schedulers(struct amdgpu_device *adev)
}
}
+ amdgpu_xcp_update_partition_sched_list(adev);
+
return 0;
}
@@ -2442,7 +2597,7 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
adev->ip_blocks[i].status.hw = true;
/* right after GMC hw init, we create CSA */
- if (amdgpu_mcbp) {
+ if (adev->gfx.mcbp) {
r = amdgpu_allocate_static_csa(adev, &adev->virt.csa_obj,
AMDGPU_GEM_DOMAIN_VRAM |
AMDGPU_GEM_DOMAIN_GTT,
@@ -2533,8 +2688,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 +2916,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 +3247,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) {
@@ -3560,6 +3718,24 @@ static const struct attribute *amdgpu_dev_attributes[] = {
NULL
};
+static void amdgpu_device_set_mcbp(struct amdgpu_device *adev)
+{
+ if (amdgpu_mcbp == 1)
+ adev->gfx.mcbp = true;
+ else if (amdgpu_mcbp == 0)
+ adev->gfx.mcbp = false;
+ else if ((adev->ip_versions[GC_HWIP][0] >= IP_VERSION(9, 0, 0)) &&
+ (adev->ip_versions[GC_HWIP][0] < IP_VERSION(10, 0, 0)) &&
+ adev->gfx.num_gfx_rings)
+ adev->gfx.mcbp = true;
+
+ if (amdgpu_sriov_vf(adev))
+ adev->gfx.mcbp = true;
+
+ if (adev->gfx.mcbp)
+ DRM_INFO("MCBP is enabled\n");
+}
+
/**
* amdgpu_device_init - initialize the driver
*
@@ -3608,6 +3784,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 +3811,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,11 +3887,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");
-
/*
* Reset domain needs to be present early, before XGMI hive discovered
* (if any) and intitialized to use reset sem and in_gpu reset flag
@@ -3725,6 +3899,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");
@@ -3736,6 +3912,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
if (r)
return r;
+ amdgpu_device_set_mcbp(adev);
+
/* Get rid of things like offb */
r = drm_aperture_remove_conflicting_pci_framebuffers(adev->pdev, &amdgpu_kms_driver);
if (r)
@@ -3753,21 +3931,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 +3964,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 +4017,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:
@@ -3896,6 +4080,11 @@ fence_driver_init:
/* Get a log2 for easy divisions. */
adev->mm_stats.log2_max_MBps = ilog2(max(1u, max_MBps));
+ r = amdgpu_atombios_sysfs_init(adev);
+ if (r)
+ drm_err(&adev->ddev,
+ "registering atombios sysfs failed (%d).\n", r);
+
r = amdgpu_pm_sysfs_init(adev);
if (r)
DRM_ERROR("registering pm sysfs failed (%d).\n", r);
@@ -4019,7 +4208,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 +4238,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
@@ -4205,6 +4394,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, true);
cancel_delayed_work_sync(&adev->delayed_init_work);
+ flush_delayed_work(&adev->gfx.gfx_off_delay_work);
amdgpu_ras_suspend(adev);
@@ -4714,42 +4904,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 +5668,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 +6149,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 +6270,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..0593ef8fe0a6 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
@@ -177,7 +180,7 @@ uint amdgpu_dc_feature_mask = 2;
uint amdgpu_dc_debug_mask;
uint amdgpu_dc_visual_confirm;
int amdgpu_async_gfx_ring = 1;
-int amdgpu_mcbp;
+int amdgpu_mcbp = -1;
int amdgpu_discovery = -1;
int amdgpu_mes;
int amdgpu_mes_kiq;
@@ -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);
@@ -630,10 +634,10 @@ module_param_named(async_gfx_ring, amdgpu_async_gfx_ring, int, 0444);
/**
* DOC: mcbp (int)
- * It is used to enable mid command buffer preemption. (0 = disabled (default), 1 = enabled)
+ * It is used to enable mid command buffer preemption. (0 = disabled, 1 = enabled, -1 auto (default))
*/
MODULE_PARM_DESC(mcbp,
- "Enable Mid-command buffer preemption (0 = disabled (default), 1 = enabled)");
+ "Enable Mid-command buffer preemption (0 = disabled, 1 = enabled), -1 = auto (default)");
module_param_named(mcbp, amdgpu_mcbp, int, 0444);
/**
@@ -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,
@@ -2826,12 +2899,10 @@ static struct pci_error_handlers amdgpu_pci_err_handler = {
extern const struct attribute_group amdgpu_vram_mgr_attr_group;
extern const struct attribute_group amdgpu_gtt_mgr_attr_group;
-extern const struct attribute_group amdgpu_vbios_version_attr_group;
static const struct attribute_group *amdgpu_sysfs_groups[] = {
&amdgpu_vram_mgr_attr_group,
&amdgpu_gtt_mgr_attr_group,
- &amdgpu_vbios_version_attr_group,
NULL,
};
@@ -2884,9 +2955,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..7537f5aa76f0 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;
@@ -556,6 +552,41 @@ int amdgpu_fence_driver_sw_init(struct amdgpu_device *adev)
}
/**
+ * amdgpu_fence_need_ring_interrupt_restore - helper function to check whether
+ * fence driver interrupts need to be restored.
+ *
+ * @ring: ring that to be checked
+ *
+ * Interrupts for rings that belong to GFX IP don't need to be restored
+ * when the target power state is s0ix.
+ *
+ * Return true if need to restore interrupts, false otherwise.
+ */
+static bool amdgpu_fence_need_ring_interrupt_restore(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+ bool is_gfx_power_domain = false;
+
+ switch (ring->funcs->type) {
+ case AMDGPU_RING_TYPE_SDMA:
+ /* SDMA 5.x+ is part of GFX power domain so it's covered by GFXOFF */
+ if (adev->ip_versions[SDMA0_HWIP][0] >= IP_VERSION(5, 0, 0))
+ is_gfx_power_domain = true;
+ break;
+ case AMDGPU_RING_TYPE_GFX:
+ case AMDGPU_RING_TYPE_COMPUTE:
+ case AMDGPU_RING_TYPE_KIQ:
+ case AMDGPU_RING_TYPE_MES:
+ is_gfx_power_domain = true;
+ break;
+ default:
+ break;
+ }
+
+ return !(adev->in_s0ix && is_gfx_power_domain);
+}
+
+/**
* amdgpu_fence_driver_hw_fini - tear down the fence driver
* for all possible rings.
*
@@ -583,7 +614,8 @@ void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev)
amdgpu_fence_driver_force_completion(ring);
if (!drm_dev_is_unplugged(adev_to_drm(adev)) &&
- ring->fence_drv.irq_src)
+ ring->fence_drv.irq_src &&
+ amdgpu_fence_need_ring_interrupt_restore(ring))
amdgpu_irq_put(adev, ring->fence_drv.irq_src,
ring->fence_drv.irq_type);
@@ -654,11 +686,13 @@ 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;
/* enable the interrupt */
- if (ring->fence_drv.irq_src)
+ if (ring->fence_drv.irq_src &&
+ amdgpu_fence_need_ring_interrupt_restore(ring))
amdgpu_irq_get(adev, ring->fence_drv.irq_src,
ring->fence_drv.irq_type);
}
@@ -695,6 +729,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 +760,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 +895,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 +974,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..fd81b04559d4 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");
@@ -589,15 +692,8 @@ void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable)
if (adev->gfx.gfx_off_req_count == 0 &&
!adev->gfx.gfx_off_state) {
- /* If going to s2idle, no need to wait */
- if (adev->in_s0ix) {
- if (!amdgpu_dpm_set_powergating_by_smu(adev,
- AMD_IP_BLOCK_TYPE_GFX, true))
- adev->gfx.gfx_off_state = true;
- } else {
- schedule_delayed_work(&adev->gfx.gfx_off_delay_work,
+ schedule_delayed_work(&adev->gfx.gfx_off_delay_work,
delay);
- }
}
} else {
if (adev->gfx.gfx_off_req_count == 0) {
@@ -785,12 +881,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 +973,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 +1177,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..a4ff515ce896 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,32 @@ 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;
+ bool mcbp; /* mid command buffer preemption */
};
+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 +474,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 +497,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 +530,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..2ff2897fd1db 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);
@@ -251,7 +255,8 @@ int amdgpu_jpeg_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *
if (amdgpu_ras_is_supported(adev, ras_block->block)) {
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
- if (adev->jpeg.harvest_config & (1 << i))
+ if (adev->jpeg.harvest_config & (1 << i) ||
+ !adev->jpeg.inst[i].ras_poison_irq.funcs)
continue;
r = amdgpu_irq_get(adev, &adev->jpeg.inst[i].ras_poison_irq, 0);
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..12414a713256 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;
@@ -804,7 +805,7 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
dev_info->ids_flags = 0;
if (adev->flags & AMD_IS_APU)
dev_info->ids_flags |= AMDGPU_IDS_FLAGS_FUSION;
- if (amdgpu_mcbp)
+ if (adev->gfx.mcbp)
dev_info->ids_flags |= AMDGPU_IDS_FLAGS_PREEMPTION;
if (amdgpu_is_tmz(adev))
dev_info->ids_flags |= AMDGPU_IDS_FLAGS_TMZ;
@@ -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;
@@ -1206,7 +1229,11 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
pasid = 0;
}
- r = amdgpu_vm_init(adev, &fpriv->vm);
+ r = amdgpu_xcp_open_device(adev, fpriv, file_priv);
+ if (r)
+ goto error_pasid;
+
+ r = amdgpu_vm_init(adev, &fpriv->vm, fpriv->xcp_id);
if (r)
goto error_pasid;
@@ -1220,7 +1247,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
goto error_vm;
}
- if (amdgpu_mcbp) {
+ if (adev->gfx.mcbp) {
uint64_t csa_addr = amdgpu_csa_vaddr(adev) & AMDGPU_GMC_HOLE_MASK;
r = amdgpu_map_static_csa(adev, &fpriv->vm, adev->virt.csa_obj,
@@ -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..f808841310fd 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) {
@@ -1350,7 +1382,7 @@ int amdgpu_mes_self_test(struct amdgpu_device *adev)
goto error_pasid;
}
- r = amdgpu_vm_init(adev, vm);
+ r = amdgpu_vm_init(adev, vm, -1);
if (r) {
DRM_ERROR("failed to initialize vm\n");
goto error_pasid;
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..78d1ee71f3f4 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)
@@ -491,11 +498,11 @@ static int psp_sw_init(void *handle)
return 0;
failed2:
- amdgpu_bo_free_kernel(&psp->fw_pri_bo,
- &psp->fw_pri_mc_addr, &psp->fw_pri_buf);
-failed1:
amdgpu_bo_free_kernel(&psp->fence_buf_bo,
&psp->fence_buf_mc_addr, &psp->fence_buf);
+failed1:
+ amdgpu_bo_free_kernel(&psp->fw_pri_bo,
+ &psp->fw_pri_mc_addr, &psp->fw_pri_buf);
return 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)
{
@@ -795,6 +839,7 @@ static bool psp_skip_tmr(struct psp_context *psp)
case IP_VERSION(11, 0, 9):
case IP_VERSION(11, 0, 7):
case IP_VERSION(13, 0, 2):
+ case IP_VERSION(13, 0, 6):
case IP_VERSION(13, 0, 10):
return true;
default:
@@ -816,8 +861,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 +874,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 +1015,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 +1132,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 +1203,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 +1320,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 +1430,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 +1447,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 +1535,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 +1545,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 +1641,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 +1674,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 +1696,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));
@@ -1947,6 +2040,8 @@ static int psp_securedisplay_initialize(struct psp_context *psp)
psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status);
dev_err(psp->adev->dev, "SECUREDISPLAY: query securedisplay TA failed. ret 0x%x\n",
securedisplay_cmd->securedisplay_out_message.query_ta.query_cmd_ret);
+ /* don't try again */
+ psp->securedisplay_context.context.bin_desc.size_bytes = 0;
}
return 0;
@@ -2077,10 +2172,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 +2460,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 +2499,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 +2751,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 +2810,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 +3060,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 +3584,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);
@@ -3613,7 +3706,6 @@ static DEVICE_ATTR(psp_vbflash_status, 0440, amdgpu_psp_vbflash_status, NULL);
int amdgpu_psp_sysfs_init(struct amdgpu_device *adev)
{
int ret = 0;
- struct psp_context *psp = &adev->psp;
if (amdgpu_sriov_vf(adev))
return -EINVAL;
@@ -3621,10 +3713,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):
- if (!psp->adev) {
- psp->adev = adev;
- psp_v13_0_set_psp_funcs(psp);
- }
+ case IP_VERSION(13, 0, 10):
ret = sysfs_create_bin_file(&adev->dev->kobj, &psp_vbflash_bin_attr);
if (ret)
dev_err(adev->dev, "Failed to create device file psp_vbflash");
@@ -3676,8 +3765,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 +3773,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 +3781,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 +3797,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_rap.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c
index 12010c988c8b..123bcf5c2bb1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c
@@ -116,7 +116,6 @@ static const struct file_operations amdgpu_rap_debugfs_ops = {
void amdgpu_rap_debugfs_init(struct amdgpu_device *adev)
{
-#if defined(CONFIG_DEBUG_FS)
struct drm_minor *minor = adev_to_drm(adev)->primary;
if (!adev->psp.rap_context.context.initialized)
@@ -124,5 +123,4 @@ void amdgpu_rap_debugfs_init(struct amdgpu_device *adev)
debugfs_create_file("rap_test", S_IWUSR, minor->debugfs_root,
adev, &amdgpu_rap_debugfs_ops);
-#endif
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index 3ab8a88789c8..8aaa427f8c0f 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,23 @@ 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;
+ }
+
+ /* Fatal error occurs in poison mode, mode1 reset is used to
+ * recover gpu.
+ */
+ if (ras->gpu_reset_flags & AMDGPU_RAS_GPU_RESET_MODE1_RESET) {
+ ras->gpu_reset_flags &= ~AMDGPU_RAS_GPU_RESET_MODE1_RESET;
+ set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
+ }
+ }
+
amdgpu_device_gpu_recover(ras->adev, NULL, &reset_context);
}
atomic_set(&ras->in_recovery, 0);
@@ -2259,7 +2323,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 +2460,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 +2688,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;
}
@@ -2899,9 +2963,12 @@ void amdgpu_ras_global_ras_isr(struct amdgpu_device *adev)
return;
if (atomic_cmpxchg(&amdgpu_ras_in_intr, 0, 1) == 0) {
+ struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+
dev_info(adev->dev, "uncorrectable hardware error"
"(ERREVENT_ATHUB_INTERRUPT) detected!\n");
+ ras->gpu_reset_flags |= AMDGPU_RAS_GPU_RESET_MODE1_RESET;
amdgpu_ras_reset_gpu(adev);
}
}
@@ -3104,3 +3171,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..ffb49b2d533a 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,46 @@ 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)
+#define AMDGPU_RAS_GPU_RESET_MODE1_RESET (0x1 << 1)
+
+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 +430,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 +519,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 +557,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 +746,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_ring_mux.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c
index 73516abef662..e1ee1c7117fb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c
@@ -397,7 +397,7 @@ void amdgpu_sw_ring_ib_begin(struct amdgpu_ring *ring)
struct amdgpu_ring_mux *mux = &adev->gfx.muxer;
WARN_ON(!ring->is_sw_ring);
- if (ring->hw_prio > AMDGPU_RING_PRIO_DEFAULT) {
+ if (adev->gfx.mcbp && ring->hw_prio > AMDGPU_RING_PRIO_DEFAULT) {
if (amdgpu_mcbp_scan(mux) > 0)
amdgpu_mcbp_trigger_preempt(mux);
return;
@@ -423,6 +423,9 @@ void amdgpu_sw_ring_ib_mark_offset(struct amdgpu_ring *ring, enum amdgpu_ring_mu
struct amdgpu_ring_mux *mux = &adev->gfx.muxer;
unsigned offset;
+ if (ring->hw_prio > AMDGPU_RING_PRIO_DEFAULT)
+ return;
+
offset = ring->wptr & ring->buf_mask;
amdgpu_ring_mux_ib_mark_offset(mux, ring, offset, type);
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..dacf281d2b21 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;
@@ -72,7 +72,7 @@ uint64_t amdgpu_sdma_get_csa_mc_addr(struct amdgpu_ring *ring,
int r;
/* don't enable OS preemption on SDMA under SRIOV */
- if (amdgpu_sriov_vf(adev) || vmid == 0 || !amdgpu_mcbp)
+ if (amdgpu_sriov_vf(adev) || vmid == 0 || !adev->gfx.mcbp)
return 0;
if (ring->is_mes_queue) {
@@ -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..ae455aab5d29 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);
@@ -1191,7 +1198,8 @@ int amdgpu_vcn_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *r
if (amdgpu_ras_is_supported(adev, ras_block->block)) {
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
- if (adev->vcn.harvest_config & (1 << i))
+ if (adev->vcn.harvest_config & (1 << i) ||
+ !adev->vcn.inst[i].ras_poison_irq.funcs)
continue;
r = amdgpu_irq_get(adev, &adev->vcn.inst[i].ras_poison_irq, 0);
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..41aa853a07d2 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,16 @@ 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;
-
+ /* 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 +558,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_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
index 53ff91fc6cf6..d0748bcfad16 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
@@ -55,8 +55,9 @@ static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct hrtimer *timer)
DRM_WARN("%s: vblank timer overrun\n", __func__);
ret = drm_crtc_handle_vblank(crtc);
+ /* Don't queue timer again when vblank is disabled. */
if (!ret)
- DRM_ERROR("amdgpu_vkms failure on handling vblank");
+ return HRTIMER_NORESTART;
return HRTIMER_RESTART;
}
@@ -81,7 +82,7 @@ static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
- hrtimer_cancel(&amdgpu_crtc->vblank_timer);
+ hrtimer_try_to_cancel(&amdgpu_crtc->vblank_timer);
}
static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 3c0310576b3b..ec1ec08d4058 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;
@@ -1674,18 +1771,30 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev,
/* Insert partial mapping before the range */
if (!list_empty(&before->list)) {
+ struct amdgpu_bo *bo = before->bo_va->base.bo;
+
amdgpu_vm_it_insert(before, &vm->va);
if (before->flags & AMDGPU_PTE_PRT)
amdgpu_vm_prt_get(adev);
+
+ if (bo && bo->tbo.base.resv == vm->root.bo->tbo.base.resv &&
+ !before->bo_va->base.moved)
+ amdgpu_vm_bo_moved(&before->bo_va->base);
} else {
kfree(before);
}
/* Insert partial mapping after the range */
if (!list_empty(&after->list)) {
+ struct amdgpu_bo *bo = after->bo_va->base.bo;
+
amdgpu_vm_it_insert(after, &vm->va);
if (after->flags & AMDGPU_PTE_PRT)
amdgpu_vm_prt_get(adev);
+
+ if (bo && bo->tbo.base.resv == vm->root.bo->tbo.base.resv &&
+ !after->bo_va->base.moved)
+ amdgpu_vm_bo_moved(&after->bo_va->base);
} else {
kfree(after);
}
@@ -2012,13 +2121,14 @@ long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout)
*
* @adev: amdgpu_device pointer
* @vm: requested vm
+ * @xcp_id: GPU partition selection id
*
* Init @vm fields.
*
* Returns:
* 0 for success, error for failure.
*/
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t xcp_id)
{
struct amdgpu_bo *root_bo;
struct amdgpu_bo_vm *root;
@@ -2038,19 +2148,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,15 +2168,17 @@ 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;
r = amdgpu_vm_pt_create(adev, vm, adev->vm_manager.root_level,
- false, &root);
+ false, &root, xcp_id);
if (r)
goto error_free_delayed;
root_bo = &root->bo;
@@ -2110,10 +2213,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;
}
@@ -2146,16 +2246,16 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)
if (r)
return r;
- /* Sanity checks */
- if (!amdgpu_vm_pt_is_root_clean(adev, vm)) {
- r = -EINVAL;
- goto unreserve_bo;
- }
-
/* Check if PD needs to be reinitialized and do it before
* changing any other state, in case it fails.
*/
if (pte_support_ats != vm->pte_support_ats) {
+ /* Sanity checks */
+ if (!amdgpu_vm_pt_is_root_clean(adev, vm)) {
+ r = -EINVAL;
+ goto unreserve_bo;
+ }
+
vm->pte_support_ats = pte_support_ats;
r = amdgpu_vm_pt_clear(adev, vm, to_amdgpu_bo_vm(vm->root.bo),
false);
@@ -2192,7 +2292,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 +2366,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 +2381,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 +2471,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 +2544,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 +2554,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 +2579,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..ffac7413c657 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 {
@@ -383,7 +392,7 @@ int amdgpu_vm_set_pasid(struct amdgpu_device *adev, struct amdgpu_vm *vm,
u32 pasid);
long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout);
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm);
+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t xcp_id);
int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm);
void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm);
void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
@@ -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);
@@ -464,7 +475,8 @@ void amdgpu_vm_get_memory(struct amdgpu_vm *vm,
int amdgpu_vm_pt_clear(struct amdgpu_device *adev, struct amdgpu_vm *vm,
struct amdgpu_bo_vm *vmbo, bool immediate);
int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct amdgpu_vm *vm,
- int level, bool immediate, struct amdgpu_bo_vm **vmbo);
+ int level, bool immediate, struct amdgpu_bo_vm **vmbo,
+ int32_t xcp_id);
void amdgpu_vm_pt_free_root(struct amdgpu_device *adev, struct amdgpu_vm *vm);
bool amdgpu_vm_pt_is_root_clean(struct amdgpu_device *adev,
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..5431332bbdb8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
@@ -498,9 +498,11 @@ exit:
* @level: the page table level
* @immediate: use a immediate update
* @vmbo: pointer to the buffer object pointer
+ * @xcp_id: GPU partition id
*/
int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct amdgpu_vm *vm,
- int level, bool immediate, struct amdgpu_bo_vm **vmbo)
+ int level, bool immediate, struct amdgpu_bo_vm **vmbo,
+ int32_t xcp_id)
{
struct amdgpu_bo_param bp;
struct amdgpu_bo *bo;
@@ -512,7 +514,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 +536,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 = xcp_id + 1;
+
if (vm->root.bo)
bp.resv = vm->root.bo->tbo.base.resv;
@@ -553,6 +562,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 = xcp_id + 1;
r = amdgpu_bo_create(adev, &bp, &(*vmbo)->shadow);
@@ -597,7 +607,8 @@ static int amdgpu_vm_pt_alloc(struct amdgpu_device *adev,
return 0;
amdgpu_vm_eviction_unlock(vm);
- r = amdgpu_vm_pt_create(adev, vm, cursor->level, immediate, &pt);
+ r = amdgpu_vm_pt_create(adev, vm, cursor->level, immediate, &pt,
+ vm->root.bo->xcp_id);
amdgpu_vm_eviction_lock(vm);
if (r)
return r;
@@ -780,13 +791,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 +806,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..565a1fa436d4
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
@@ -0,0 +1,415 @@
+/*
+ * 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;
+
+ /* This is needed for figuring out memory id of xcp */
+ xcp_mgr->num_xcp_per_mem_partition = num_xcps / xcp_mgr->adev->gmc.num_mem_partitions;
+
+ 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);
+
+ 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);
+
+ /* xcp #0 shares drm device setting with adev */
+ adev->xcp_mgr->xcp->ddev = ddev;
+
+ for (i = 1; i < MAX_XCP; i++) {
+ ret = amdgpu_xcp_drm_dev_alloc(&p_ddev);
+ if (ret == -ENOSPC) {
+ dev_warn(adev->dev,
+ "Skip xcp node #%d when out of drm node resource.", i);
+ return 0;
+ } else 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 = 1; i < MAX_XCP; i++) {
+ if (!adev->xcp_mgr->xcp[i].ddev)
+ break;
+
+ 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 = 1; i < MAX_XCP; i++) {
+ if (!adev->xcp_mgr->xcp[i].ddev)
+ break;
+
+ 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 = AMDGPU_XCP_NO_PARTITION;
+ 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 == AMDGPU_XCP_NO_PARTITION ? -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..9a1036aeec2a
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
@@ -0,0 +1,184 @@
+/*
+ * 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)
+
+#define AMDGPU_XCP_NO_PARTITION (~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..72b629a78c62
--- /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 = AMDGPU_XCP_NO_PARTITION;
+ 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 == AMDGPU_XCP_NO_PARTITION) {
+ 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/atom.c b/drivers/gpu/drm/amd/amdgpu/atom.c
index 1c5d9388ad0b..5f610e9a5f0f 100644
--- a/drivers/gpu/drm/amd/amdgpu/atom.c
+++ b/drivers/gpu/drm/amd/amdgpu/atom.c
@@ -1509,7 +1509,7 @@ struct atom_context *amdgpu_atom_parse(struct card_info *card, void *bios)
str = CSTR(idx);
if (*str != '\0') {
pr_info("ATOM BIOS: %s\n", str);
- strlcpy(ctx->vbios_version, str, sizeof(ctx->vbios_version));
+ strscpy(ctx->vbios_version, str, sizeof(ctx->vbios_version));
}
atom_rom_header = (struct _ATOM_ROM_HEADER *)CSTR(base);
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..44af8022b89f 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 = {
@@ -8413,7 +8307,7 @@ static void gfx_v10_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
control |= ib->length_dw | (vmid << 24);
- if (amdgpu_mcbp && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) {
+ if (ring->adev->gfx.mcbp && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) {
control |= INDIRECT_BUFFER_PRE_ENB(1);
if (flags & AMDGPU_IB_PREEMPTED)
@@ -8588,7 +8482,7 @@ static void gfx_v10_0_ring_emit_cntxcntl(struct amdgpu_ring *ring,
{
uint32_t dw2 = 0;
- if (amdgpu_mcbp)
+ if (ring->adev->gfx.mcbp)
gfx_v10_0_ring_emit_ce_meta(ring,
(!amdgpu_sriov_vf(ring->adev) && flags & AMDGPU_IB_PREEMPTED) ? true : false);
@@ -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..0451533ddde4 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,27 @@ 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)) {
+ if (amdgpu_sriov_vf(adev))
+ adev->gfx.cp_gfx_shadow = true;
+ else
+ adev->gfx.cp_gfx_shadow = false;
+ }
+ 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 +560,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 +721,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 +769,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 +795,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 +806,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 +817,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 +851,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 +910,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 +941,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 +1411,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 +1426,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 +1500,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 +1521,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 +1642,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 +1712,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 +3233,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 +3324,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 +3369,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 +3670,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 +3681,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 +3708,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 +3718,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 +3971,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 +3999,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 +4022,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 +4040,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 +4085,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 +4178,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 +4346,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 +4436,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 +4536,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 +4705,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 +4724,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 +4952,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 +4972,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 +5040,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,
@@ -5404,7 +5315,7 @@ static void gfx_v11_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
control |= ib->length_dw | (vmid << 24);
- if (amdgpu_mcbp && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) {
+ if (ring->adev->gfx.mcbp && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) {
control |= INDIRECT_BUFFER_PRE_ENB(1);
if (flags & AMDGPU_IB_PREEMPTED)
@@ -5592,6 +5503,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 +5557,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 +6025,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 +6116,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 +6143,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 +6224,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 +6373,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 +6405,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..4f883b94f98e 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,505 @@
#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
+#define CP_HQD_PERSISTENT_STATE_DEFAULT 0xbe05301
+
+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 +546,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 +571,497 @@ 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, i, num_xcc;
+ u32 tmp = 0;
+
+ if (adev->psp.funcs) {
+ ret = psp_spatial_partition(&adev->psp,
+ NUM_XCC(adev->gfx.xcc_mask) /
+ num_xccs_per_xcp);
+ if (ret)
+ return ret;
+ } else {
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+
+ for (i = 0; i < num_xcc; i++) {
+ tmp = REG_SET_FIELD(tmp, CP_HYP_XCP_CTL, NUM_XCC_IN_XCP,
+ num_xccs_per_xcp);
+ tmp = REG_SET_FIELD(tmp, CP_HYP_XCP_CTL, VIRTUAL_XCC_ID,
+ i % num_xccs_per_xcp);
+ WREG32_SOC15(GC, GET_INST(GC, i), regCP_HYP_XCP_CTL,
+ tmp);
+ }
+ ret = 0;
+ }
+
+ 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)
{
- soc15_grbm_select(adev, me, pipe, q, vm);
+ 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)
+{
+ 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 +1069,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 +1111,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 +1120,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 +1138,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 +1147,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;
- WREG32_FIELD15_PREREG(GC, 0, RLC_CNTL, RLC_ENABLE_F32, 1);
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ for (i = 0; i < num_xcc; i++)
+ gfx_v9_4_3_xcc_rlc_reset(adev, i);
+}
+
+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 +1264,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 +1332,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 +1346,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 +1356,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 +1376,1038 @@ 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, CP_HQD_PERSISTENT_STATE_DEFAULT);
+ 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);
+ if (amdgpu_sriov_vf(adev) && adev->in_suspend)
+ amdgpu_ring_clear_ring(ring);
+ 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);
-const struct amdgpu_rlc_funcs gfx_v9_4_3_rlc_funcs = {
+ 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);
+
+ if (amdgpu_sriov_vf(adev)) {
+ /* must disable polling for SRIOV when hw finished, otherwise
+ * CPC engine may still keep fetching WB address which is already
+ * invalid after sw finished and trigger DMAR reading error in
+ * hypervisor side.
+ */
+ WREG32_FIELD15_PREREG(GC, GET_INST(GC, xcc_id), CP_PQ_WPTR_POLL_CNTL, EN, 0);
+ return;
+ }
+
+ /* 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;
+
+ if (!amdgpu_sriov_vf(adev))
+ 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);
+ }
+
+}
+
+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 +2416,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..d9f14dc55998 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,202 @@ 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);
+ int i;
+
+ /*
+ * 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, xcc_mask) {
+ 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 +533,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 +635,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_v2_3.c b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c
index aa761ff3a5fa..4038455d7998 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c
@@ -345,8 +345,8 @@ static void nbio_v2_3_init_registers(struct amdgpu_device *adev)
}
#define NAVI10_PCIE__LC_L0S_INACTIVITY_DEFAULT 0x00000000 // off by default, no gains over L1
-#define NAVI10_PCIE__LC_L1_INACTIVITY_DEFAULT 0x00000009 // 1=1us, 9=1ms
-#define NAVI10_PCIE__LC_L1_INACTIVITY_TBT_DEFAULT 0x0000000E // 4ms
+#define NAVI10_PCIE__LC_L1_INACTIVITY_DEFAULT 0x0000000A // 1=1us, 9=1ms, 10=4ms
+#define NAVI10_PCIE__LC_L1_INACTIVITY_TBT_DEFAULT 0x0000000E // 400ms
static void nbio_v2_3_enable_aspm(struct amdgpu_device *adev,
bool enable)
@@ -479,9 +479,12 @@ static void nbio_v2_3_program_aspm(struct amdgpu_device *adev)
WREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP5, data);
def = data = RREG32_PCIE(smnPCIE_LC_CNTL);
- data &= ~PCIE_LC_CNTL__LC_L0S_INACTIVITY_MASK;
- data |= 0x9 << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;
- data |= 0x1 << PCIE_LC_CNTL__LC_PMI_TO_L1_DIS__SHIFT;
+ data |= NAVI10_PCIE__LC_L0S_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L0S_INACTIVITY__SHIFT;
+ if (pci_is_thunderbolt_attached(adev->pdev))
+ data |= NAVI10_PCIE__LC_L1_INACTIVITY_TBT_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;
+ else
+ data |= NAVI10_PCIE__LC_L1_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;
+ data &= ~PCIE_LC_CNTL__LC_PMI_TO_L1_DIS_MASK;
if (def != data)
WREG32_PCIE(smnPCIE_LC_CNTL, data);
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..af5685f4cb34 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
@@ -49,6 +49,7 @@ MODULE_FIRMWARE("amdgpu/psp_13_0_10_ta.bin");
MODULE_FIRMWARE("amdgpu/psp_13_0_11_toc.bin");
MODULE_FIRMWARE("amdgpu/psp_13_0_11_ta.bin");
MODULE_FIRMWARE("amdgpu/psp_13_0_6_sos.bin");
+MODULE_FIRMWARE("amdgpu/psp_13_0_6_ta.bin");
/* For large FW files the time to complete can be very long */
#define USBC_PD_POLLING_LIMIT_S 240
@@ -136,14 +137,15 @@ static int psp_v13_0_wait_for_bootloader(struct psp_context *psp)
int ret;
int retry_loop;
+ /* Wait for bootloader to signify that it is ready having bit 31 of
+ * C2PMSG_35 set to 1. All other bits are expected to be cleared.
+ * If there is an error in processing command, bits[7:0] will be set.
+ * This is applicable for PSP v13.0.6 and newer.
+ */
for (retry_loop = 0; retry_loop < 10; retry_loop++) {
- /* Wait for bootloader to signify that is
- ready having bit 31 of C2PMSG_35 set to 1 */
- ret = psp_wait_for(psp,
- SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35),
- 0x80000000,
- 0x80000000,
- false);
+ ret = psp_wait_for(
+ psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35),
+ 0x80000000, 0xffffffff, false);
if (ret == 0)
return 0;
@@ -624,10 +626,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..f413898dda37 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,39 @@ 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++) {
+ if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)
+ return;
+
+ 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 +692,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 +781,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 +789,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 +806,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 +823,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 +851,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,31 +897,31 @@ 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)) {
- ring = &adev->sdma.instance[i].ring;
- adev->nbio.funcs->sdma_doorbell_range(adev, i,
- ring->use_doorbell, ring->doorbell_index,
- adev->doorbell_index.sdma_doorbell_range);
-
- /* unhalt engine */
- temp = RREG32_SDMA(i, regSDMA_F32_CNTL);
- temp = REG_SET_FIELD(temp, SDMA_F32_CNTL, HALT, 0);
- WREG32_SDMA(i, regSDMA_F32_CNTL, temp);
+ if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
+ /* unhalt engine */
+ temp = RREG32_SDMA(i, regSDMA_F32_CNTL);
+ temp = REG_SET_FIELD(temp, SDMA_F32_CNTL, HALT, 0);
+ WREG32_SDMA(i, regSDMA_F32_CNTL, temp);
+ }
}
}
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..259795098173 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;
@@ -1424,8 +1424,10 @@ static int vcn_v4_0_start_sriov(struct amdgpu_device *adev)
*/
static void vcn_v4_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
{
+ struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
uint32_t tmp;
+ vcn_v4_0_pause_dpg_mode(adev, inst_idx, &state);
/* Wait for power status to be 1 */
SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1,
UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
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..f5a6f562e2a8 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;
@@ -1543,11 +1543,7 @@ static bool kfd_ignore_crat(void)
if (ignore_crat)
return true;
-#ifndef KFD_SUPPORT_IOMMU_V2
ret = true;
-#else
- ret = false;
-#endif
return ret;
}
@@ -1858,7 +1854,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 +1883,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 +1968,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 +1981,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 +2001,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 +2018,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 +2032,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 +2048,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 +2070,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 +2100,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 +2172,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 +2235,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 +2274,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..9766076e9ec4
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_debug.c
@@ -0,0 +1,1117 @@
+/*
+ * 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_dbg_has_cwsr_workaround(q->device))
+ 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 || !kfd_dbg_has_cwsr_workaround(pdd->dev);
+
+ 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..662a13a0d582
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_debug.h
@@ -0,0 +1,129 @@
+/*
+ * 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_cwsr_workaround(struct kfd_node *dev)
+{
+ return KFD_GC_VERSION(dev) >= IP_VERSION(11, 0, 0) &&
+ KFD_GC_VERSION(dev) <= IP_VERSION(11, 0, 3);
+}
+
+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..a53e0757fe64 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,12 @@ 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 */
+ kfd->device_info.event_interrupt_class = &event_interrupt_class_v9;
+ break;
+ case IP_VERSION(9, 4, 3): /* GC 9.4.3 */
+ kfd->device_info.event_interrupt_class =
+ &event_interrupt_class_v9_4_3;
+ 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 +157,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):
@@ -185,11 +194,6 @@ static void kfd_device_info_init(struct kfd_dev *kfd,
kfd_device_info_set_event_interrupt_class(kfd);
- /* Raven */
- if (gc_version == IP_VERSION(9, 1, 0) ||
- gc_version == IP_VERSION(9, 2, 2))
- kfd->device_info.needs_iommu_device = true;
-
if (gc_version < IP_VERSION(11, 0, 0)) {
/* Navi2x+, Navi1x+ */
if (gc_version == IP_VERSION(10, 3, 6))
@@ -224,10 +228,6 @@ static void kfd_device_info_init(struct kfd_dev *kfd,
asic_type != CHIP_TONGA)
kfd->device_info.supports_cwsr = true;
- if (asic_type == CHIP_KAVERI ||
- asic_type == CHIP_CARRIZO)
- kfd->device_info.needs_iommu_device = true;
-
if (asic_type != CHIP_HAWAII && !vf)
kfd->device_info.needs_pci_atomics = true;
}
@@ -240,7 +240,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
uint32_t gfx_target_version = 0;
switch (adev->asic_type) {
-#ifdef KFD_SUPPORT_IOMMU_V2
#ifdef CONFIG_DRM_AMDGPU_CIK
case CHIP_KAVERI:
gfx_target_version = 70000;
@@ -253,7 +252,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
if (!vf)
f2g = &gfx_v8_kfd2kgd;
break;
-#endif
#ifdef CONFIG_DRM_AMDGPU_CIK
case CHIP_HAWAII:
gfx_target_version = 70001;
@@ -289,7 +287,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
gfx_target_version = 90000;
f2g = &gfx_v9_kfd2kgd;
break;
-#ifdef KFD_SUPPORT_IOMMU_V2
/* Raven */
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 2):
@@ -297,7 +294,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
if (!vf)
f2g = &gfx_v9_kfd2kgd;
break;
-#endif
/* Vega12 */
case IP_VERSION(9, 2, 1):
gfx_target_version = 90004;
@@ -327,8 +323,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 +404,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 +445,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 +491,148 @@ 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(9, 4, 3)) ||
+ (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;
+ }
+}
+
+static void kfd_setup_interrupt_bitmap(struct kfd_node *node,
+ unsigned int kfd_node_idx)
+{
+ struct amdgpu_device *adev = node->adev;
+ uint32_t xcc_mask = node->xcc_mask;
+ uint32_t xcc, mapped_xcc;
+ /*
+ * Interrupt bitmap is setup for processing interrupts from
+ * different XCDs and AIDs.
+ * Interrupt bitmap is defined as follows:
+ * 1. Bits 0-15 - correspond to the NodeId field.
+ * Each bit corresponds to NodeId number. For example, if
+ * a KFD node has interrupt bitmap set to 0x7, then this
+ * KFD node will process interrupts with NodeId = 0, 1 and 2
+ * in the IH cookie.
+ * 2. Bits 16-31 - unused.
+ *
+ * Please note that the kfd_node_idx argument passed to this
+ * function is not related to NodeId field received in the
+ * IH cookie.
+ *
+ * In CPX mode, a KFD node will process an interrupt if:
+ * - the Node Id matches the corresponding bit set in
+ * Bits 0-15.
+ * - AND VMID reported in the interrupt lies within the
+ * VMID range of the node.
+ */
+ for_each_inst(xcc, xcc_mask) {
+ mapped_xcc = GET_INST(GC, xcc);
+ node->interrupt_bitmap |= (mapped_xcc % 2 ? 5 : 3) << (4 * (mapped_xcc / 2));
+ }
+ dev_info(kfd_device, "Node: %d, interrupt_bitmap: %x\n", kfd_node_idx,
+ node->interrupt_bitmap);
+}
+
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 +642,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 +668,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 +743,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 +764,103 @@ 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 (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_iommu(kfd))
- goto device_iommu_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.
+ */
- if (kfd_resume(kfd))
- goto kfd_resume_error;
+ 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);
- amdgpu_amdkfd_get_local_mem_info(kfd->adev, &kfd->local_mem_info);
+ amdgpu_amdkfd_get_local_mem_info(kfd->adev,
+ &node->local_mem_info, node->xcp);
- if (kfd_topology_add_device(kfd)) {
- dev_err(kfd_device, "Error adding device to topology\n");
- goto kfd_topology_add_device_error;
+ if (KFD_GC_VERSION(kfd) == IP_VERSION(9, 4, 3))
+ kfd_setup_interrupt_bitmap(node, i);
+
+ /* 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 +871,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 +885,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 +914,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 +1019,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 +1050,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 +1063,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 +1216,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 +1320,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 +1345,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 +1386,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 +1428,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..01192f5abe46 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,8 @@ 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_dbg_has_cwsr_workaround(q->device);
+ 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 +347,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 +366,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 +408,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 +417,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 +431,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 +471,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 +490,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 +691,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 +701,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 +747,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 +870,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 +891,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 +928,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 +950,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 +1070,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 +1098,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 +1120,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 +1130,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 +1228,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 +1241,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 +1264,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 +1273,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 +1362,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 +1412,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 +1452,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 +1479,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 +1548,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 +1565,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 +1614,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 +1632,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 +1659,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 +1685,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 +1694,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 +1728,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 +1743,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 +1804,8 @@ 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_dbg_has_cwsr_workaround(q->device);
if (qd)
mqd_mgr->restore_mqd(mqd_mgr, &q->mqd, q->mqd_mem_obj, &q->gart_mqd_addr,
@@ -1673,9 +1821,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 +1912,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 +1926,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 +1964,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 +1986,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 +1995,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 +2053,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 +2087,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 +2109,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 +2258,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 +2271,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 +2307,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 +2360,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 +2382,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 +2444,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 +2459,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;
@@ -2335,18 +2538,12 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev)
}
switch (dev->adev->asic_type) {
- case CHIP_CARRIZO:
- device_queue_manager_init_vi(&dqm->asic_ops);
- break;
-
case CHIP_KAVERI:
- device_queue_manager_init_cik(&dqm->asic_ops);
- break;
-
case CHIP_HAWAII:
device_queue_manager_init_cik_hawaii(&dqm->asic_ops);
break;
+ case CHIP_CARRIZO:
case CHIP_TONGA:
case CHIP_FIJI:
case CHIP_POLARIS10:
@@ -2373,20 +2570,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 +2595,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 +2626,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 +3144,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 +3232,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..f0731a6a5306 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,13 +426,56 @@ 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);
}
}
+static bool event_interrupt_isr_v9_4_3(struct kfd_node *node,
+ const uint32_t *ih_ring_entry,
+ uint32_t *patched_ihre,
+ bool *patched_flag)
+{
+ uint16_t node_id, vmid;
+
+ /*
+ * For GFX 9.4.3, process the interrupt if:
+ * - NodeID field in IH entry matches the corresponding bit
+ * set in interrupt_bitmap Bits 0-15.
+ * OR
+ * - If partition mode is CPX and interrupt came from
+ * Node_id 0,4,8,12, then check if the Bit (16 + client id)
+ * is set in interrupt bitmap Bits 16-31.
+ */
+ node_id = SOC15_NODEID_FROM_IH_ENTRY(ih_ring_entry);
+ vmid = SOC15_VMID_FROM_IH_ENTRY(ih_ring_entry);
+ if (kfd_irq_is_from_node(node, node_id, vmid))
+ return event_interrupt_isr_v9(node, ih_ring_entry,
+ patched_ihre, patched_flag);
+ return false;
+}
+
const struct kfd_event_interrupt_class event_interrupt_class_v9 = {
.interrupt_isr = event_interrupt_isr_v9,
.interrupt_wq = event_interrupt_wq_v9,
};
+
+const struct kfd_event_interrupt_class event_interrupt_class_v9_4_3 = {
+ .interrupt_isr = event_interrupt_isr_v9_4_3,
+ .interrupt_wq = event_interrupt_wq_v9,
+};
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..d4c9ee3f9953 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,8 @@ 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_v9_4_3;
+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 +1459,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 +1475,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 +1517,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 +1534,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..a844e68211ac 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,135 @@ 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];
+ uint8_t node_id = 0;
+ 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;
+
+ /*
+ * For GFX 9.4.3, send the NodeId also in IH cookie DW[3]
+ */
+ if (KFD_GC_VERSION(pdd->dev->kfd) == IP_VERSION(9, 4, 3)) {
+ node_id = ffs(pdd->dev->interrupt_bitmap) - 1;
+ irq_drain_fence[3] |= node_id << 16;
+ }
+
+ /* 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 +2320,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..ba9d69054119 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;
@@ -123,16 +123,24 @@ int pqm_set_gws(struct process_queue_manager *pqm, unsigned int qid,
if (!gws && pdd->qpd.num_gws == 0)
return -EINVAL;
- if (gws)
- ret = amdgpu_amdkfd_add_gws_to_process(pdd->process->kgd_process_info,
- gws, &mem);
- else
- ret = amdgpu_amdkfd_remove_gws_from_process(pdd->process->kgd_process_info,
- pqn->q->gws);
- if (unlikely(ret))
- return ret;
+ if (KFD_GC_VERSION(dev) != IP_VERSION(9, 4, 3)) {
+ if (gws)
+ ret = amdgpu_amdkfd_add_gws_to_process(pdd->process->kgd_process_info,
+ gws, &mem);
+ else
+ ret = amdgpu_amdkfd_remove_gws_from_process(pdd->process->kgd_process_info,
+ pqn->q->gws);
+ if (unlikely(ret))
+ return ret;
+ pqn->q->gws = mem;
+ } else {
+ /*
+ * Intentionally set GWS to a non-NULL value
+ * for GFX 9.4.3.
+ */
+ pqn->q->gws = gws ? ERR_PTR(-ENOMEM) : NULL;
+ }
- pqn->q->gws = mem;
pdd->qpd.num_gws = gws ? dev->adev->gds.gws_size : 0;
return pqn->q->device->dqm->ops.update_queue(pqn->q->device->dqm,
@@ -164,7 +172,8 @@ void pqm_uninit(struct process_queue_manager *pqm)
struct process_queue_node *pqn, *next;
list_for_each_entry_safe(pqn, next, &pqm->queues, process_queue_list) {
- if (pqn->q && pqn->q->gws)
+ if (pqn->q && pqn->q->gws &&
+ KFD_GC_VERSION(pqn->q->device) != IP_VERSION(9, 4, 3))
amdgpu_amdkfd_remove_gws_from_process(pqm->process->kgd_process_info,
pqn->q->gws);
kfd_procfs_del_queue(pqn->q);
@@ -178,7 +187,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 +196,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 +209,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 +234,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 +252,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 +275,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 +347,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 +375,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 +408,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;
@@ -434,12 +455,14 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid)
}
if (pqn->q->gws) {
- amdgpu_amdkfd_remove_gws_from_process(pqm->process->kgd_process_info,
- pqn->q->gws);
+ if (KFD_GC_VERSION(pqn->q->device) != IP_VERSION(9, 4, 3))
+ amdgpu_amdkfd_remove_gws_from_process(
+ pqm->process->kgd_process_info,
+ pqn->q->gws);
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 +500,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 +522,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 +546,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 +596,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 +930,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 +998,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 +1016,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 +1025,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 +1048,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..4a17bb7c7b27 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;
@@ -1875,7 +1965,14 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
const char *asic_name = amdgpu_asic_name[gpu->adev->asic_type];
gpu_id = kfd_generate_gpu_id(gpu);
- pr_debug("Adding new GPU (ID: 0x%x) to topology\n", gpu_id);
+ if (gpu->xcp && !gpu->xcp->ddev) {
+ dev_warn(gpu->adev->dev,
+ "Won't add GPU (ID: 0x%x) to topology since it has no drm node assigned.",
+ gpu_id);
+ return 0;
+ } else {
+ pr_debug("Adding new GPU (ID: 0x%x) to topology\n", gpu_id);
+ }
/* Check to see if this gpu device exists in the topology_device_list.
* If so, assign the gpu to that device,
@@ -1916,28 +2013,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 +2072,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,9 +2111,13 @@ 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;
+ if (dev->gpu->adev->gmc.is_app_apu ||
+ dev->gpu->adev->gmc.xgmi.connected_to_cpu)
+ dev->node_props.capability |= HSA_CAP_FLAGS_COHERENTHOSTACCESS;
+
kfd_debug_print_topology();
kfd_notify_gpu_change(gpu_id, 1);
@@ -2079,7 +2187,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 +2227,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/amdkfd/soc15_int.h b/drivers/gpu/drm/amd/amdkfd/soc15_int.h
index e3f3b0b93a59..10138676f27f 100644
--- a/drivers/gpu/drm/amd/amdkfd/soc15_int.h
+++ b/drivers/gpu/drm/amd/amdkfd/soc15_int.h
@@ -40,6 +40,7 @@
#define SOC15_VMID_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[0]) >> 24 & 0xf)
#define SOC15_VMID_TYPE_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[0]) >> 31 & 0x1)
#define SOC15_PASID_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[3]) & 0xffff)
+#define SOC15_NODEID_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[3]) >> 16 & 0xff)
#define SOC15_CONTEXT_ID0_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[4]))
#define SOC15_CONTEXT_ID1_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[5]))
#define SOC15_CONTEXT_ID2_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[6]))
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..e5554a36e8c8 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,
@@ -416,12 +424,12 @@ static void dm_pflip_high_irq(void *interrupt_params)
spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
- if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){
- DC_LOG_PFLIP("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p] \n",
- amdgpu_crtc->pflip_status,
- AMDGPU_FLIP_SUBMITTED,
- amdgpu_crtc->crtc_id,
- amdgpu_crtc);
+ if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) {
+ DC_LOG_PFLIP("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p]\n",
+ amdgpu_crtc->pflip_status,
+ AMDGPU_FLIP_SUBMITTED,
+ amdgpu_crtc->crtc_id,
+ amdgpu_crtc);
spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
return;
}
@@ -875,7 +883,7 @@ static int dm_set_powergating_state(void *handle,
}
/* Prototypes of private functions */
-static int dm_early_init(void* handle);
+static int dm_early_init(void *handle);
/* Allocate memory for FBC compressed data */
static void amdgpu_dm_fbc_init(struct drm_connector *connector)
@@ -1274,7 +1282,7 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
pa_config->system_aperture.start_addr = (uint64_t)logical_addr_low << 18;
pa_config->system_aperture.end_addr = (uint64_t)logical_addr_high << 18;
- pa_config->system_aperture.agp_base = (uint64_t)agp_base << 24 ;
+ pa_config->system_aperture.agp_base = (uint64_t)agp_base << 24;
pa_config->system_aperture.agp_bot = (uint64_t)agp_bot << 24;
pa_config->system_aperture.agp_top = (uint64_t)agp_top << 24;
@@ -1339,6 +1347,15 @@ static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
if (amdgpu_in_reset(adev))
goto skip;
+ if (offload_work->data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY ||
+ offload_work->data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
+ dm_handle_mst_sideband_msg_ready_event(&aconnector->mst_mgr, DOWN_OR_UP_MSG_RDY_EVENT);
+ spin_lock_irqsave(&offload_work->offload_wq->offload_lock, flags);
+ offload_work->offload_wq->is_handling_mst_msg_rdy_event = false;
+ spin_unlock_irqrestore(&offload_work->offload_wq->offload_lock, flags);
+ goto skip;
+ }
+
mutex_lock(&adev->dm.dc_lock);
if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
dc_link_dp_handle_automated_test(dc_link);
@@ -1357,8 +1374,7 @@ static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
DP_TEST_RESPONSE,
&test_response.raw,
sizeof(test_response));
- }
- else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) &&
+ } else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) &&
dc_link_check_link_loss_status(dc_link, &offload_work->data) &&
dc_link_dp_allow_hpd_rx_irq(dc_link)) {
/* offload_work->data is from handle_hpd_rx_irq->
@@ -1546,7 +1562,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
mutex_init(&adev->dm.dc_lock);
mutex_init(&adev->dm.audio_lock);
- if(amdgpu_dm_irq_init(adev)) {
+ if (amdgpu_dm_irq_init(adev)) {
DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n");
goto error;
}
@@ -1622,9 +1638,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
}
break;
}
- if (init_data.flags.gpu_vm_support &&
- (amdgpu_sg_display == 0))
- init_data.flags.gpu_vm_support = false;
+ if (init_data.flags.gpu_vm_support)
+ init_data.flags.gpu_vm_support = amdgpu_sg_display_supported(adev);
if (init_data.flags.gpu_vm_support)
adev->mode_info.gpu_vm_support = true;
@@ -1646,11 +1661,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 +1682,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;
}
@@ -1691,9 +1703,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
if (amdgpu_dc_debug_mask & DC_DISABLE_STUTTER)
adev->dm.dc->debug.disable_stutter = true;
- if (amdgpu_dc_debug_mask & DC_DISABLE_DSC) {
+ if (amdgpu_dc_debug_mask & DC_DISABLE_DSC)
adev->dm.dc->debug.disable_dsc = true;
- }
if (amdgpu_dc_debug_mask & DC_DISABLE_CLOCK_GATING)
adev->dm.dc->debug.disable_clock_gate = true;
@@ -1776,12 +1787,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 +1845,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");
@@ -1938,8 +1948,6 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
mutex_destroy(&adev->dm.audio_lock);
mutex_destroy(&adev->dm.dc_lock);
mutex_destroy(&adev->dm.dpia_aux_lock);
-
- return;
}
static int load_dmcu_fw(struct amdgpu_device *adev)
@@ -1948,7 +1956,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
int r;
const struct dmcu_firmware_header_v1_0 *hdr;
- switch(adev->asic_type) {
+ switch (adev->asic_type) {
#if defined(CONFIG_DRM_AMD_DC_SI)
case CHIP_TAHITI:
case CHIP_PITCAIRN:
@@ -2705,7 +2713,7 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state,
struct dc_scaling_info scaling_infos[MAX_SURFACES];
struct dc_flip_addrs flip_addrs[MAX_SURFACES];
struct dc_stream_update stream_update;
- } * bundle;
+ } *bundle;
int k, m;
bundle = kzalloc(sizeof(*bundle), GFP_KERNEL);
@@ -2735,8 +2743,6 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state,
cleanup:
kfree(bundle);
-
- return;
}
static int dm_resume(void *handle)
@@ -2950,8 +2956,7 @@ static const struct amd_ip_funcs amdgpu_dm_funcs = {
.set_powergating_state = dm_set_powergating_state,
};
-const struct amdgpu_ip_block_version dm_ip_block =
-{
+const struct amdgpu_ip_block_version dm_ip_block = {
.type = AMD_IP_BLOCK_TYPE_DCE,
.major = 1,
.minor = 0,
@@ -2996,9 +3001,12 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
caps->aux_support = false;
- if (caps->ext_caps->bits.oled == 1 /*||
- caps->ext_caps->bits.sdr_aux_backlight_control == 1 ||
- caps->ext_caps->bits.hdr_aux_backlight_control == 1*/)
+ if (caps->ext_caps->bits.oled == 1
+ /*
+ * ||
+ * caps->ext_caps->bits.sdr_aux_backlight_control == 1 ||
+ * caps->ext_caps->bits.hdr_aux_backlight_control == 1
+ */)
caps->aux_support = true;
if (amdgpu_backlight == 0)
@@ -3232,84 +3240,6 @@ static void handle_hpd_irq(void *param)
}
-static void dm_handle_mst_sideband_msg(struct amdgpu_dm_connector *aconnector)
-{
- u8 esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 };
- u8 dret;
- bool new_irq_handled = false;
- int dpcd_addr;
- int dpcd_bytes_to_read;
-
- const int max_process_count = 30;
- int process_count = 0;
-
- const struct dc_link_status *link_status = dc_link_get_status(aconnector->dc_link);
-
- if (link_status->dpcd_caps->dpcd_rev.raw < 0x12) {
- dpcd_bytes_to_read = DP_LANE0_1_STATUS - DP_SINK_COUNT;
- /* DPCD 0x200 - 0x201 for downstream IRQ */
- dpcd_addr = DP_SINK_COUNT;
- } else {
- dpcd_bytes_to_read = DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI;
- /* DPCD 0x2002 - 0x2005 for downstream IRQ */
- dpcd_addr = DP_SINK_COUNT_ESI;
- }
-
- dret = drm_dp_dpcd_read(
- &aconnector->dm_dp_aux.aux,
- dpcd_addr,
- esi,
- dpcd_bytes_to_read);
-
- while (dret == dpcd_bytes_to_read &&
- process_count < max_process_count) {
- u8 retry;
- dret = 0;
-
- process_count++;
-
- 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);
-
- 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)
- break;
- }
-
- /* check if there is new irq to be handled */
- dret = drm_dp_dpcd_read(
- &aconnector->dm_dp_aux.aux,
- dpcd_addr,
- esi,
- dpcd_bytes_to_read);
-
- new_irq_handled = false;
- } else {
- break;
- }
- }
-
- if (process_count == max_process_count)
- DRM_DEBUG_DRIVER("Loop exceeded max iterations\n");
-}
-
static void schedule_hpd_rx_offload_work(struct hpd_rx_irq_offload_work_queue *offload_wq,
union hpd_irq_data hpd_irq_data)
{
@@ -3371,7 +3301,23 @@ static void handle_hpd_rx_irq(void *param)
if (dc_link_dp_allow_hpd_rx_irq(dc_link)) {
if (hpd_irq_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY ||
hpd_irq_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
- dm_handle_mst_sideband_msg(aconnector);
+ bool skip = false;
+
+ /*
+ * DOWN_REP_MSG_RDY is also handled by polling method
+ * mgr->cbs->poll_hpd_irq()
+ */
+ spin_lock(&offload_wq->offload_lock);
+ skip = offload_wq->is_handling_mst_msg_rdy_event;
+
+ if (!skip)
+ offload_wq->is_handling_mst_msg_rdy_event = true;
+
+ spin_unlock(&offload_wq->offload_lock);
+
+ if (!skip)
+ schedule_hpd_rx_offload_work(offload_wq, hpd_irq_data);
+
goto out;
}
@@ -3462,7 +3408,7 @@ static void register_hpd_handlers(struct amdgpu_device *adev)
aconnector = to_amdgpu_dm_connector(connector);
dc_link = aconnector->dc_link;
- if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd) {
+ if (dc_link->irq_source_hpd != DC_IRQ_SOURCE_INVALID) {
int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
int_params.irq_source = dc_link->irq_source_hpd;
@@ -3471,7 +3417,7 @@ static void register_hpd_handlers(struct amdgpu_device *adev)
(void *) aconnector);
}
- if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) {
+ if (dc_link->irq_source_hpd_rx != DC_IRQ_SOURCE_INVALID) {
/* Also register for DP short pulse (hpd_rx). */
int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
@@ -3480,11 +3426,11 @@ static void register_hpd_handlers(struct amdgpu_device *adev)
amdgpu_dm_irq_register_interrupt(adev, &int_params,
handle_hpd_rx_irq,
(void *) aconnector);
-
- if (adev->dm.hpd_rx_offload_wq)
- adev->dm.hpd_rx_offload_wq[dc_link->link_index].aconnector =
- aconnector;
}
+
+ if (adev->dm.hpd_rx_offload_wq)
+ adev->dm.hpd_rx_offload_wq[connector->index].aconnector =
+ aconnector;
}
}
@@ -3497,7 +3443,7 @@ static int dce60_register_irq_handlers(struct amdgpu_device *adev)
struct dc_interrupt_params int_params = {0};
int r;
int i;
- unsigned client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
+ unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
@@ -3511,11 +3457,12 @@ static int dce60_register_irq_handlers(struct amdgpu_device *adev)
* Base driver will call amdgpu_dm_irq_handler() for ALL interrupts
* coming from DC hardware.
* amdgpu_dm_irq_handler() will re-direct the interrupt to DC
- * for acknowledging and handling. */
+ * for acknowledging and handling.
+ */
/* Use VBLANK interrupt */
for (i = 0; i < adev->mode_info.num_crtc; i++) {
- r = amdgpu_irq_add_id(adev, client_id, i+1 , &adev->crtc_irq);
+ r = amdgpu_irq_add_id(adev, client_id, i + 1, &adev->crtc_irq);
if (r) {
DRM_ERROR("Failed to add crtc irq id!\n");
return r;
@@ -3523,7 +3470,7 @@ static int dce60_register_irq_handlers(struct amdgpu_device *adev)
int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
int_params.irq_source =
- dc_interrupt_to_irq_source(dc, i+1 , 0);
+ dc_interrupt_to_irq_source(dc, i + 1, 0);
c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1];
@@ -3579,7 +3526,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)
struct dc_interrupt_params int_params = {0};
int r;
int i;
- unsigned client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
+ unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
if (adev->family >= AMDGPU_FAMILY_AI)
client_id = SOC15_IH_CLIENTID_DCE;
@@ -3596,7 +3543,8 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)
* Base driver will call amdgpu_dm_irq_handler() for ALL interrupts
* coming from DC hardware.
* amdgpu_dm_irq_handler() will re-direct the interrupt to DC
- * for acknowledging and handling. */
+ * for acknowledging and handling.
+ */
/* Use VBLANK interrupt */
for (i = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0; i <= VISLANDS30_IV_SRCID_D6_VERTICAL_INTERRUPT0; i++) {
@@ -4043,7 +3991,7 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm,
}
static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,
- unsigned *min, unsigned *max)
+ unsigned int *min, unsigned int *max)
{
if (!caps)
return 0;
@@ -4063,7 +4011,7 @@ static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,
static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *caps,
uint32_t brightness)
{
- unsigned min, max;
+ unsigned int min, max;
if (!get_brightness_range(caps, &min, &max))
return brightness;
@@ -4076,7 +4024,7 @@ static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *c
static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *caps,
uint32_t brightness)
{
- unsigned min, max;
+ unsigned int min, max;
if (!get_brightness_range(caps, &min, &max))
return brightness;
@@ -4556,7 +4504,6 @@ fail:
static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm)
{
drm_atomic_private_obj_fini(&dm->atomic_obj);
- return;
}
/******************************************************************************
@@ -5057,11 +5004,7 @@ static inline void fill_dc_dirty_rect(struct drm_plane *plane,
s32 y, s32 width, s32 height,
int *i, bool ffu)
{
- if (*i > DC_MAX_DIRTY_RECTS)
- return;
-
- if (*i == DC_MAX_DIRTY_RECTS)
- goto out;
+ WARN_ON(*i >= DC_MAX_DIRTY_RECTS);
dirty_rect->x = x;
dirty_rect->y = y;
@@ -5077,7 +5020,6 @@ static inline void fill_dc_dirty_rect(struct drm_plane *plane,
"[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)",
plane->base.id, x, y, width, height);
-out:
(*i)++;
}
@@ -5164,6 +5106,9 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
*dirty_regions_changed = bb_changed;
+ if ((num_clips + (bb_changed ? 2 : 0)) > DC_MAX_DIRTY_RECTS)
+ goto ffu;
+
if (bb_changed) {
fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i],
new_plane_state->crtc_x,
@@ -5193,9 +5138,6 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
new_plane_state->crtc_h, &i, false);
}
- if (i > DC_MAX_DIRTY_RECTS)
- goto ffu;
-
flip_addrs->dirty_rect_count = i;
return;
@@ -5331,21 +5273,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 +5323,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;
}
@@ -5379,6 +5335,7 @@ static bool adjust_colour_depth_from_display_info(
{
enum dc_color_depth depth = timing_out->display_color_depth;
int normalized_clk;
+
do {
normalized_clk = timing_out->pix_clk_100hz / 10;
/* YCbCr 4:2:0 requires additional adjustment of 1/2 */
@@ -5505,7 +5462,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,
@@ -5594,6 +5551,7 @@ create_fake_sink(struct amdgpu_dm_connector *aconnector)
{
struct dc_sink_init_data sink_init_data = { 0 };
struct dc_sink *sink = NULL;
+
sink_init_data.link = aconnector->dc_link;
sink_init_data.sink_signal = aconnector->dc_link->connector_signal;
@@ -5717,7 +5675,7 @@ get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector,
return &aconnector->freesync_vid_base;
/* Find the preferred mode */
- list_for_each_entry (m, list_head, head) {
+ list_for_each_entry(m, list_head, head) {
if (m->type & DRM_MODE_TYPE_PREFERRED) {
m_pref = m;
break;
@@ -5741,7 +5699,7 @@ get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector,
* For some monitors, preferred mode is not the mode with highest
* supported refresh rate.
*/
- list_for_each_entry (m, list_head, head) {
+ list_for_each_entry(m, list_head, head) {
current_refresh = drm_mode_vrefresh(m);
if (m->hdisplay == m_pref->hdisplay &&
@@ -5947,15 +5905,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;
@@ -6014,12 +5971,11 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
* This may not be an error, the use case is when we have no
* usermode calls to reset and set mode upon hotplug. In this
* case, we call set mode ourselves to restore the previous mode
- * and the modelist may not be filled in in time.
+ * and the modelist may not be filled in time.
*/
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,13 +5990,13 @@ 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);
/*
- * If scaling is enabled and refresh rate didn't change
- * we copy the vic and polarities of the old timings
- */
+ * If scaling is enabled and refresh rate didn't change
+ * we copy the vic and polarities of the old timings
+ */
if (!scale || mode_refresh != preferred_refresh)
fill_stream_properties_from_drm_display_mode(
stream, &mode, &aconnector->base, con_state, NULL,
@@ -6347,6 +6303,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 +6338,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 +6356,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 +6553,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 +6649,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 +6679,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;
}
@@ -6760,6 +6760,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
if (!state->duplicated) {
int max_bpc = conn_state->max_requested_bpc;
+
is_y420 = drm_mode_is_420_also(&connector->display_info, adjusted_mode) &&
aconnector->force_yuv420_output;
color_depth = convert_color_depth_from_display_info(connector,
@@ -7078,7 +7079,7 @@ static bool is_duplicate_mode(struct amdgpu_dm_connector *aconnector,
{
struct drm_display_mode *m;
- list_for_each_entry (m, &aconnector->base.probed_modes, head) {
+ list_for_each_entry(m, &aconnector->base.probed_modes, head) {
if (drm_mode_equal(m, mode))
return true;
}
@@ -7168,7 +7169,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)
@@ -7196,13 +7197,7 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
drm_add_modes_noedid(connector, 1920, 1080);
} else {
amdgpu_dm_connector_ddc_get_modes(connector, edid);
- /* most eDP supports only timings from its edid,
- * usually only detailed timings are available
- * from eDP edid. timings which are not from edid
- * may damage eDP
- */
- if (connector->connector_type != DRM_MODE_CONNECTOR_eDP)
- amdgpu_dm_connector_add_common_modes(encoder, connector);
+ amdgpu_dm_connector_add_common_modes(encoder, connector);
amdgpu_dm_connector_add_freesync_modes(connector, edid);
}
amdgpu_dm_fbc_init(connector);
@@ -7210,6 +7205,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,
@@ -7238,6 +7239,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
aconnector->as_type = ADAPTIVE_SYNC_TYPE_NONE;
memset(&aconnector->vsdb_info, 0, sizeof(aconnector->vsdb_info));
mutex_init(&aconnector->hpd_lock);
+ mutex_init(&aconnector->handle_mst_msg_ready);
/*
* configure support HPD hot plug connector_>polled default value is 0
@@ -7290,6 +7292,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) {
@@ -7388,7 +7399,6 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
link->priv = aconnector;
- DRM_DEBUG_DRIVER("%s()\n", __func__);
i2c = create_i2c(link->ddc, link->link_index, &res);
if (!i2c) {
@@ -8059,7 +8069,15 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
* Only allow immediate flips for fast updates that don't
* change memory domain, FB pitch, DCC state, rotation or
* mirroring.
+ *
+ * dm_crtc_helper_atomic_check() only accepts async flips with
+ * fast updates.
*/
+ if (crtc->state->async_flip &&
+ acrtc_state->update_type != UPDATE_TYPE_FAST)
+ drm_warn_once(state->dev,
+ "[PLANE:%d:%s] async flip with non-fast update\n",
+ plane->base.id, plane->name);
bundle->flip_addrs[planes_count].flip_immediate =
crtc->state->async_flip &&
acrtc_state->update_type == UPDATE_TYPE_FAST &&
@@ -8102,8 +8120,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
* DRI3/Present extension with defined target_msc.
*/
last_flip_vblank = amdgpu_get_vblank_counter_kms(pcrtc);
- }
- else {
+ } else {
/* For variable refresh rate mode only:
* Get vblank of last completed flip to avoid > 1 vrr
* flips per video frame by use of throttling, but allow
@@ -8436,8 +8453,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
dc_resource_state_copy_construct_current(dm->dc, dc_state);
}
- for_each_oldnew_crtc_in_state (state, crtc, old_crtc_state,
- new_crtc_state, i) {
+ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
+ new_crtc_state, i) {
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
@@ -8460,9 +8477,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
drm_dbg_state(state->dev,
- "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
- "planes_changed:%d, mode_changed:%d,active_changed:%d,"
- "connectors_changed:%d\n",
+ "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, planes_changed:%d, mode_changed:%d,active_changed:%d,connectors_changed:%d\n",
acrtc->crtc_id,
new_crtc_state->enable,
new_crtc_state->active,
@@ -8884,10 +8899,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,
@@ -9031,8 +9053,8 @@ static int do_aquire_global_lock(struct drm_device *dev,
&commit->flip_done, 10*HZ);
if (ret == 0)
- DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done "
- "timed out\n", crtc->base.id, crtc->name);
+ DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done timed out\n",
+ crtc->base.id, crtc->name);
drm_crtc_commit_put(commit);
}
@@ -9117,7 +9139,8 @@ is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
return false;
}
-static void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state) {
+static void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state)
+{
u64 num, den, res;
struct drm_crtc_state *new_crtc_state = &dm_new_crtc_state->base;
@@ -9221,8 +9244,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;
@@ -9240,9 +9262,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
goto skip_modeset;
drm_dbg_state(state->dev,
- "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
- "planes_changed:%d, mode_changed:%d,active_changed:%d,"
- "connectors_changed:%d\n",
+ "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, planes_changed:%d, mode_changed:%d,active_changed:%d,connectors_changed:%d\n",
acrtc->crtc_id,
new_crtc_state->enable,
new_crtc_state->active,
@@ -9264,27 +9284,27 @@ 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;
DRM_DEBUG_DRIVER(
- "Mode change not required for front porch change, "
- "setting mode_changed to %d",
+ "Mode change not required for front porch change, setting mode_changed to %d",
new_crtc_state->mode_changed);
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;
high_mode = get_highest_refresh_rate_mode(aconnector, false);
- if (!drm_mode_equal(&new_crtc_state->mode, high_mode)) {
+ if (!drm_mode_equal(&new_crtc_state->mode, high_mode))
set_freesync_fixed_config(dm_new_crtc_state);
- }
}
ret = dm_atomic_get_state(state, &dm_state);
@@ -9452,6 +9472,7 @@ static bool should_reset_plane(struct drm_atomic_state *state,
*/
for_each_oldnew_plane_in_state(state, other, old_other_state, new_other_state, i) {
struct amdgpu_framebuffer *old_afb, *new_afb;
+
if (other->type == DRM_PLANE_TYPE_CURSOR)
continue;
@@ -9550,11 +9571,12 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc,
}
/* Core DRM takes care of checking FB modifiers, so we only need to
- * check tiling flags when the FB doesn't have a modifier. */
+ * check tiling flags when the FB doesn't have a modifier.
+ */
if (!(fb->flags & DRM_MODE_FB_MODIFIERS)) {
if (adev->family < AMDGPU_FAMILY_AI) {
linear = AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_2D_TILED_THIN1 &&
- AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_1D_TILED_THIN1 &&
+ AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_1D_TILED_THIN1 &&
AMDGPU_TILING_GET(afb->tiling_flags, MICRO_TILE_MODE) == 0;
} else {
linear = AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE) == 0;
@@ -9776,12 +9798,12 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state,
/* On DCE and DCN there is no dedicated hardware cursor plane. We get a
* cursor per pipe but it's going to inherit the scaling and
* positioning from the underlying pipe. Check the cursor plane's
- * blending properties match the underlying planes'. */
+ * blending properties match the underlying planes'.
+ */
new_cursor_state = drm_atomic_get_new_plane_state(state, cursor);
- if (!new_cursor_state || !new_cursor_state->fb) {
+ if (!new_cursor_state || !new_cursor_state->fb)
return 0;
- }
dm_get_oriented_plane_size(new_cursor_state, &cursor_src_w, &cursor_src_h);
cursor_scale_w = new_cursor_state->crtc_w * 1000 / cursor_src_w;
@@ -9826,6 +9848,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
struct drm_connector_state *conn_state, *old_conn_state;
struct amdgpu_dm_connector *aconnector = NULL;
int i;
+
for_each_oldnew_connector_in_state(state, connector, old_conn_state, conn_state, i) {
if (!conn_state->crtc)
conn_state = old_conn_state;
@@ -10260,7 +10283,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
}
/* Store the overall update type for use later in atomic check. */
- for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) {
+ for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
struct dm_crtc_state *dm_new_crtc_state =
to_dm_crtc_state(new_crtc_state);
@@ -10282,7 +10305,7 @@ fail:
else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS)
DRM_DEBUG_DRIVER("Atomic check stopped due to signal.\n");
else
- DRM_DEBUG_DRIVER("Atomic check failed with err: %d \n", ret);
+ DRM_DEBUG_DRIVER("Atomic check failed with err: %d\n", ret);
trace_amdgpu_dm_atomic_check_finish(state, ret);
@@ -10336,7 +10359,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 +10809,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..9fb5bb3a75a7 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -195,6 +195,11 @@ struct hpd_rx_irq_offload_work_queue {
*/
bool is_handling_link_loss;
/**
+ * @is_handling_mst_msg_rdy_event: Used to prevent inserting mst message
+ * ready event when we're already handling mst message ready event
+ */
+ bool is_handling_mst_msg_rdy_event;
+ /**
* @aconnector: The aconnector that this work queue is attached to
*/
struct amdgpu_dm_connector *aconnector;
@@ -638,6 +643,8 @@ struct amdgpu_dm_connector {
struct drm_dp_mst_port *mst_output_port;
struct amdgpu_dm_connector *mst_root;
struct drm_dp_aux *dsc_aux;
+ struct mutex handle_mst_msg_ready;
+
/* TODO see if we can merge with ddc_bus or make a dm_connector */
struct amdgpu_i2c_adapter *i2c;
@@ -661,10 +668,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_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
index 440fc0869a34..30d4c6fd95f5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
@@ -398,6 +398,18 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc,
return -EINVAL;
}
+ /*
+ * Only allow async flips for fast updates that don't change the FB
+ * pitch, the DCC state, rotation, etc.
+ */
+ if (crtc_state->async_flip &&
+ dm_crtc_state->update_type != UPDATE_TYPE_FAST) {
+ drm_dbg_atomic(crtc->dev,
+ "[CRTC:%d:%s] async flips are only supported for fast updates\n",
+ crtc->base.id, crtc->name);
+ return -EINVAL;
+ }
+
/* In some use cases, like reset, no stream is attached */
if (!dm_crtc_state->stream)
return 0;
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..d63ee636483b 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
@@ -336,6 +336,153 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
return size;
}
+static bool dp_mst_is_end_device(struct amdgpu_dm_connector *aconnector)
+{
+ bool is_end_device = false;
+ struct drm_dp_mst_topology_mgr *mgr = NULL;
+ struct drm_dp_mst_port *port = NULL;
+
+ if (aconnector->mst_root && aconnector->mst_root->mst_mgr.mst_state) {
+ mgr = &aconnector->mst_root->mst_mgr;
+ port = aconnector->mst_output_port;
+
+ drm_modeset_lock(&mgr->base.lock, NULL);
+ if (port->pdt == DP_PEER_DEVICE_SST_SINK ||
+ port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV)
+ is_end_device = true;
+ drm_modeset_unlock(&mgr->base.lock);
+ }
+
+ return is_end_device;
+}
+
+/* Change MST link setting
+ *
+ * valid lane count value: 1, 2, 4
+ * valid link rate value:
+ * 06h = 1.62Gbps per lane
+ * 0Ah = 2.7Gbps per lane
+ * 0Ch = 3.24Gbps per lane
+ * 14h = 5.4Gbps per lane
+ * 1Eh = 8.1Gbps per lane
+ * 3E8h = 10.0Gbps per lane
+ * 546h = 13.5Gbps per lane
+ * 7D0h = 20.0Gbps per lane
+ *
+ * debugfs is located at /sys/kernel/debug/dri/0/DP-x/mst_link_settings
+ *
+ * for example, to force to 2 lane, 10.0GHz,
+ * echo 2 0x3e8 > /sys/kernel/debug/dri/0/DP-x/mst_link_settings
+ *
+ * Valid input will trigger hotplug event to get new link setting applied
+ * Invalid input will trigger training setting reset
+ *
+ * The usage can be referred to link_settings entry
+ *
+ */
+static ssize_t dp_mst_link_setting(struct file *f, const char __user *buf,
+ size_t size, loff_t *pos)
+{
+ struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
+ struct dc_link *link = aconnector->dc_link;
+ struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev);
+ struct dc *dc = (struct dc *)link->dc;
+ struct dc_link_settings prefer_link_settings;
+ char *wr_buf = NULL;
+ const uint32_t wr_buf_size = 40;
+ /* 0: lane_count; 1: link_rate */
+ int max_param_num = 2;
+ uint8_t param_nums = 0;
+ long param[2];
+ bool valid_input = true;
+
+ if (!dp_mst_is_end_device(aconnector))
+ return -EINVAL;
+
+ if (size == 0)
+ return -EINVAL;
+
+ wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);
+ if (!wr_buf)
+ return -ENOSPC;
+
+ if (parse_write_buffer_into_params(wr_buf, wr_buf_size,
+ (long *)param, buf,
+ max_param_num,
+ &param_nums)) {
+ kfree(wr_buf);
+ return -EINVAL;
+ }
+
+ if (param_nums <= 0) {
+ kfree(wr_buf);
+ DRM_DEBUG_DRIVER("user data not be read\n");
+ return -EINVAL;
+ }
+
+ switch (param[0]) {
+ case LANE_COUNT_ONE:
+ case LANE_COUNT_TWO:
+ case LANE_COUNT_FOUR:
+ break;
+ default:
+ valid_input = false;
+ break;
+ }
+
+ switch (param[1]) {
+ case LINK_RATE_LOW:
+ case LINK_RATE_HIGH:
+ case LINK_RATE_RBR2:
+ case LINK_RATE_HIGH2:
+ case LINK_RATE_HIGH3:
+ case LINK_RATE_UHBR10:
+ case LINK_RATE_UHBR13_5:
+ case LINK_RATE_UHBR20:
+ break;
+ default:
+ valid_input = false;
+ break;
+ }
+
+ if (!valid_input) {
+ kfree(wr_buf);
+ DRM_DEBUG_DRIVER("Invalid Input value No HW will be programmed\n");
+ mutex_lock(&adev->dm.dc_lock);
+ dc_link_set_preferred_training_settings(dc, NULL, NULL, link, false);
+ mutex_unlock(&adev->dm.dc_lock);
+ return -EINVAL;
+ }
+
+ /* save user force lane_count, link_rate to preferred settings
+ * spread spectrum will not be changed
+ */
+ prefer_link_settings.link_spread = link->cur_link_settings.link_spread;
+ prefer_link_settings.use_link_rate_set = false;
+ prefer_link_settings.lane_count = param[0];
+ prefer_link_settings.link_rate = param[1];
+
+ /* skip immediate retrain, and train to new link setting after hotplug event triggered */
+ mutex_lock(&adev->dm.dc_lock);
+ dc_link_set_preferred_training_settings(dc, &prefer_link_settings, NULL, link, true);
+ mutex_unlock(&adev->dm.dc_lock);
+
+ mutex_lock(&aconnector->base.dev->mode_config.mutex);
+ aconnector->base.force = DRM_FORCE_OFF;
+ mutex_unlock(&aconnector->base.dev->mode_config.mutex);
+ drm_kms_helper_hotplug_event(aconnector->base.dev);
+
+ msleep(100);
+
+ mutex_lock(&aconnector->base.dev->mode_config.mutex);
+ aconnector->base.force = DRM_FORCE_UNSPECIFIED;
+ mutex_unlock(&aconnector->base.dev->mode_config.mutex);
+ drm_kms_helper_hotplug_event(aconnector->base.dev);
+
+ kfree(wr_buf);
+ return size;
+}
+
/* function: get current DP PHY settings: voltage swing, pre-emphasis,
* post-cursor2 (defined by VESA DP specification)
*
@@ -907,6 +1054,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 +1241,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 +2802,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,
@@ -2714,6 +2815,12 @@ static const struct file_operations dp_dsc_disable_passthrough_debugfs_fops = {
.llseek = default_llseek
};
+static const struct file_operations dp_mst_link_settings_debugfs_fops = {
+ .owner = THIS_MODULE,
+ .write = dp_mst_link_setting,
+ .llseek = default_llseek
+};
+
static const struct {
char *name;
const struct file_operations *fops;
@@ -2724,9 +2831,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},
@@ -2740,7 +2844,8 @@ static const struct {
{"dsc_disable_passthrough", &dp_dsc_disable_passthrough_debugfs_fops},
{"is_mst_connector", &dp_is_mst_connector_fops},
{"mst_progress_status", &dp_mst_progress_status_fops},
- {"is_dpia_link", &is_dpia_link_fops}
+ {"is_dpia_link", &is_dpia_link_fops},
+ {"mst_link_settings", &dp_mst_link_settings_debugfs_fops}
};
static const struct {
@@ -2809,6 +2914,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 +2978,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 +3152,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 +3162,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 +3380,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..d9a482908380 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,8 +44,29 @@
#include "dm_helpers.h"
#include "ddc_service_types.h"
-/* MST Dock */
-static const uint8_t SYNAPTICS_DEVICE_ID[] = "SYNA";
+static u32 edid_extract_panel_id(struct edid *edid)
+{
+ return (u32)edid->mfg_id[0] << 24 |
+ (u32)edid->mfg_id[1] << 16 |
+ (u32)EDID_PRODUCT_ID(edid);
+}
+
+static void apply_edid_quirks(struct edid *edid, struct dc_edid_caps *edid_caps)
+{
+ uint32_t panel_id = edid_extract_panel_id(edid);
+
+ switch (panel_id) {
+ /* Workaround for some monitors which does not work well with FAMS */
+ case drm_edid_encode_panel_id('S', 'A', 'M', 0x0E5E):
+ case drm_edid_encode_panel_id('S', 'A', 'M', 0x7053):
+ case drm_edid_encode_panel_id('S', 'A', 'M', 0x71AC):
+ DRM_DEBUG_DRIVER("Disabling FAMS on monitor with panel id %X\n", panel_id);
+ edid_caps->panel_patch.disable_fams = true;
+ break;
+ default:
+ return;
+ }
+}
/* dm_helpers_parse_edid_caps
*
@@ -118,6 +139,8 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
else
edid_caps->speaker_flags = DEFAULT_SPEAKER_LOCATION;
+ apply_edid_quirks(edid_buf, edid_caps);
+
kfree(sads);
kfree(sadb);
@@ -702,6 +725,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 +911,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..b885c39bd16b 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,
@@ -620,8 +619,118 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
return connector;
}
+void dm_handle_mst_sideband_msg_ready_event(
+ struct drm_dp_mst_topology_mgr *mgr,
+ enum mst_msg_ready_type msg_rdy_type)
+{
+ uint8_t esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 };
+ uint8_t dret;
+ bool new_irq_handled = false;
+ int dpcd_addr;
+ uint8_t dpcd_bytes_to_read;
+ const uint8_t max_process_count = 30;
+ uint8_t process_count = 0;
+ u8 retry;
+ struct amdgpu_dm_connector *aconnector =
+ container_of(mgr, struct amdgpu_dm_connector, mst_mgr);
+
+
+ const struct dc_link_status *link_status = dc_link_get_status(aconnector->dc_link);
+
+ if (link_status->dpcd_caps->dpcd_rev.raw < 0x12) {
+ dpcd_bytes_to_read = DP_LANE0_1_STATUS - DP_SINK_COUNT;
+ /* DPCD 0x200 - 0x201 for downstream IRQ */
+ dpcd_addr = DP_SINK_COUNT;
+ } else {
+ dpcd_bytes_to_read = DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI;
+ /* DPCD 0x2002 - 0x2005 for downstream IRQ */
+ dpcd_addr = DP_SINK_COUNT_ESI;
+ }
+
+ mutex_lock(&aconnector->handle_mst_msg_ready);
+
+ while (process_count < max_process_count) {
+ u8 ack[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = {};
+
+ process_count++;
+
+ dret = drm_dp_dpcd_read(
+ &aconnector->dm_dp_aux.aux,
+ dpcd_addr,
+ esi,
+ dpcd_bytes_to_read);
+
+ if (dret != dpcd_bytes_to_read) {
+ DRM_DEBUG_KMS("DPCD read and acked number is not as expected!");
+ break;
+ }
+
+ DRM_DEBUG_DRIVER("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]);
+
+ switch (msg_rdy_type) {
+ case DOWN_REP_MSG_RDY_EVENT:
+ /* Only handle DOWN_REP_MSG_RDY case*/
+ esi[1] &= DP_DOWN_REP_MSG_RDY;
+ break;
+ case UP_REQ_MSG_RDY_EVENT:
+ /* Only handle UP_REQ_MSG_RDY case*/
+ esi[1] &= DP_UP_REQ_MSG_RDY;
+ break;
+ default:
+ /* Handle both cases*/
+ esi[1] &= (DP_DOWN_REP_MSG_RDY | DP_UP_REQ_MSG_RDY);
+ break;
+ }
+
+ if (!esi[1])
+ break;
+
+ /* handle MST irq */
+ if (aconnector->mst_mgr.mst_state)
+ 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 */
+ for (retry = 0; retry < 3; retry++) {
+ 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");
+ break;
+ }
+
+ drm_dp_mst_hpd_irq_send_new_request(&aconnector->mst_mgr);
+
+ new_irq_handled = false;
+ } else {
+ break;
+ }
+ }
+
+ mutex_unlock(&aconnector->handle_mst_msg_ready);
+
+ if (process_count == max_process_count)
+ DRM_DEBUG_DRIVER("Loop exceeded max iterations\n");
+}
+
+static void dm_handle_mst_down_rep_msg_ready(struct drm_dp_mst_topology_mgr *mgr)
+{
+ dm_handle_mst_sideband_msg_ready_event(mgr, DOWN_REP_MSG_RDY_EVENT);
+}
+
static const struct drm_dp_mst_topology_cbs dm_mst_cbs = {
.add_connector = dm_dp_add_mst_connector,
+ .poll_hpd_irq = dm_handle_mst_down_rep_msg_ready,
};
void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
@@ -1211,7 +1320,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
if (computed_streams[i])
continue;
- if (!res_pool->funcs->remove_stream_from_ctx ||
+ if (res_pool->funcs->remove_stream_from_ctx &&
res_pool->funcs->remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
return -EINVAL;
@@ -1422,7 +1531,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/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
index 1e4ede1e57ab..37c820ab0fdb 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
@@ -49,6 +49,13 @@
#define PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B 1031
#define PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B 1000
+enum mst_msg_ready_type {
+ NONE_MSG_RDY_EVENT = 0,
+ DOWN_REP_MSG_RDY_EVENT = 1,
+ UP_REQ_MSG_RDY_EVENT = 2,
+ DOWN_OR_UP_MSG_RDY_EVENT = 3
+};
+
struct amdgpu_display_manager;
struct amdgpu_dm_connector;
@@ -61,6 +68,10 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
void
dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev);
+void dm_handle_mst_sideband_msg_ready_event(
+ struct drm_dp_mst_topology_mgr *mgr,
+ enum mst_msg_ready_type msg_rdy_type);
+
struct dsc_mst_fairness_vars {
int pbn;
bool dsc_enabled;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
index d647f68fd563..4f61d4f257cd 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
@@ -24,6 +24,7 @@
*/
#include "amdgpu_dm_psr.h"
+#include "dc_dmub_srv.h"
#include "dc.h"
#include "dm_helpers.h"
#include "amdgpu_dm.h"
@@ -50,7 +51,7 @@ static bool link_supports_psrsu(struct dc_link *link)
!link->dpcd_caps.psr_info.psr2_su_y_granularity_cap)
return false;
- return true;
+ return dc_dmub_check_min_version(dc->ctx->dmub_srv->dmub);
}
/*
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..3db4ef564b99 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
@@ -87,6 +87,11 @@ static int dcn31_get_active_display_cnt_wa(
stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK)
tmds_present = true;
+
+ /* Checking stream / link detection ensuring that PHY is active*/
+ if (dc_is_dp_signal(stream->signal) && !stream->dpms_off)
+ display_count++;
+
}
for (i = 0; i < dc->link_count; i++) {
@@ -205,10 +210,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 +253,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 +675,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 +715,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..cb992aca760d 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,15 +535,24 @@ 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 */
- if (!clk_mgr_base->clks.p_state_change_support)
- dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
- clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels - 1].memclk_mhz);
+ if (!clk_mgr_base->clks.p_state_change_support) {
+ if (dc->clk_mgr->dc_mode_softmax_enabled) {
+ /* On DCN32x we will never have the functional UCLK min above the softmax
+ * since we calculate mode support based on softmax being the max UCLK
+ * frequency.
+ */
+ dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
+ dc->clk_mgr->bw_params->dc_mode_softmax_memclk);
+ } else {
+ dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, dc->clk_mgr->bw_params->max_memclk_mhz);
+ }
+ }
}
/* Always update saved value, even if new value not set due to P-State switching unsupported. Also check safe_to_lower for FCLK */
@@ -518,20 +560,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 +615,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)) {
@@ -771,8 +817,7 @@ static void dcn32_set_hard_max_memclk(struct clk_mgr *clk_mgr_base)
if (!clk_mgr->smu_present)
return;
- dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK,
- clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels - 1].memclk_mhz);
+ dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK, clk_mgr_base->bw_params->max_memclk_mhz);
}
/* Get current memclk states, update bounding box */
@@ -789,6 +834,8 @@ 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);
+ clk_mgr_base->bw_params->dc_mode_softmax_memclk = clk_mgr_base->bw_params->dc_mode_limit.memclk_mhz;
/* 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,13 +843,15 @@ 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;
} else {
num_levels = num_entries_per_clk->num_fclk_levels;
}
-
+ clk_mgr_base->bw_params->max_memclk_mhz =
+ clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_memclk_levels - 1].memclk_mhz;
clk_mgr_base->bw_params->clk_table.num_entries = num_levels ? num_levels : 1;
if (clk_mgr->dpm_present && !num_levels)
@@ -855,6 +904,25 @@ static bool dcn32_is_smu_present(struct clk_mgr *clk_mgr_base)
return clk_mgr->smu_present;
}
+static void dcn32_set_max_memclk(struct clk_mgr *clk_mgr_base, unsigned int memclk_mhz)
+{
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+ if (!clk_mgr->smu_present)
+ return;
+
+ dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK, memclk_mhz);
+}
+
+static void dcn32_set_min_memclk(struct clk_mgr *clk_mgr_base, unsigned int memclk_mhz)
+{
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+ if (!clk_mgr->smu_present)
+ return;
+
+ dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, memclk_mhz);
+}
static struct clk_mgr_funcs dcn32_funcs = {
.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
@@ -865,6 +933,8 @@ static struct clk_mgr_funcs dcn32_funcs = {
.notify_wm_ranges = dcn32_notify_wm_ranges,
.set_hard_min_memclk = dcn32_set_hard_min_memclk,
.set_hard_max_memclk = dcn32_set_hard_max_memclk,
+ .set_max_memclk = dcn32_set_max_memclk,
+ .set_min_memclk = dcn32_set_min_memclk,
.get_memclk_states_from_smu = dcn32_get_memclk_states_from_smu,
.are_clock_states_equal = dcn32_are_clock_states_equal,
.enable_pme_wa = dcn32_enable_pme_wa,
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 7cde67b7f0c3..d133e4186a52 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);
@@ -1602,6 +1629,9 @@ bool dc_validate_boot_timing(const struct dc *dc,
return false;
}
+ if (dc->debug.force_odm_combine)
+ return false;
+
/* Check for enabled DIG to identify enabled display */
if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
return false;
@@ -2504,9 +2534,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 +2592,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 +2637,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 +2657,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 +3026,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 +3333,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 +3380,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,10 +3420,173 @@ 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);
+ /* Clear update flags so next flip doesn't have redundant programming
+ * (if there's no stream update, the update flags are not cleared).
+ */
+ if (top_pipe_to_program->plane_state)
+ top_pipe_to_program->plane_state->update_flags.raw = 0;
+ if (top_pipe_to_program->stream)
+ top_pipe_to_program->stream->update_flags.raw = 0;
}
static void commit_planes_for_stream(struct dc *dc,
@@ -3414,21 +3626,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 +3667,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 +3758,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 +4208,152 @@ 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;
+ }
+ }
+}
+
+static void populate_fast_updates(struct dc_fast_update *fast_update,
+ struct dc_surface_update *srf_updates,
+ int surface_count,
+ struct dc_stream_update *stream_update)
+{
+ int i = 0;
+
+ if (stream_update) {
+ fast_update[0].out_transfer_func = stream_update->out_transfer_func;
+ fast_update[0].output_csc_transform = stream_update->output_csc_transform;
+ }
+
+ for (i = 0; i < surface_count; i++) {
+ fast_update[i].flip_addr = srf_updates[i].flip_addr;
+ fast_update[i].gamma = srf_updates[i].gamma;
+ fast_update[i].gamut_remap_matrix = srf_updates[i].gamut_remap_matrix;
+ fast_update[i].input_csc_color_matrix = srf_updates[i].input_csc_color_matrix;
+ fast_update[i].coeff_reduction_factor = srf_updates[i].coeff_reduction_factor;
+ }
+}
+
+static bool fast_updates_exist(struct dc_fast_update *fast_update, int surface_count)
+{
+ int i;
+
+ if (fast_update[0].out_transfer_func ||
+ fast_update[0].output_csc_transform)
+ return true;
+
+ for (i = 0; i < surface_count; i++) {
+ if (fast_update[i].flip_addr ||
+ fast_update[i].gamma ||
+ fast_update[i].gamut_remap_matrix ||
+ fast_update[i].input_csc_color_matrix ||
+ fast_update[i].coeff_reduction_factor)
+ return true;
+ }
+
+ return false;
+}
+
+static bool full_update_required(struct dc_surface_update *srf_updates,
+ int surface_count,
+ struct dc_stream_update *stream_update,
+ struct dc_stream_state *stream)
+{
+
+ int i;
+ struct dc_stream_status *stream_status;
+
+ for (i = 0; i < surface_count; i++) {
+ if (srf_updates &&
+ (srf_updates[i].plane_info ||
+ srf_updates[i].scaling_info ||
+ (srf_updates[i].hdr_mult.value &&
+ srf_updates[i].hdr_mult.value != srf_updates->surface->hdr_mult.value) ||
+ srf_updates[i].in_transfer_func ||
+ srf_updates[i].func_shaper ||
+ srf_updates[i].lut3d_func ||
+ srf_updates[i].blend_tf))
+ return true;
+ }
+
+ if (stream_update &&
+ (((stream_update->src.height != 0 && stream_update->src.width != 0) ||
+ (stream_update->dst.height != 0 && stream_update->dst.width != 0) ||
+ stream_update->integer_scaling_update) ||
+ stream_update->hdr_static_metadata ||
+ stream_update->abm_level ||
+ stream_update->periodic_interrupt ||
+ stream_update->vrr_infopacket ||
+ stream_update->vsc_infopacket ||
+ stream_update->vsp_infopacket ||
+ stream_update->hfvsif_infopacket ||
+ stream_update->vtem_infopacket ||
+ stream_update->adaptive_sync_infopacket ||
+ stream_update->dpms_off ||
+ stream_update->allow_freesync ||
+ stream_update->vrr_active_variable ||
+ stream_update->vrr_active_fixed ||
+ stream_update->gamut_remap ||
+ stream_update->output_color_space ||
+ stream_update->dither_option ||
+ stream_update->wb_update ||
+ stream_update->dsc_config ||
+ stream_update->mst_bw_update ||
+ stream_update->func_shaper ||
+ stream_update->lut3d_func ||
+ stream_update->pending_test_pattern ||
+ stream_update->crtc_timing_adjust))
+ return true;
+
+ if (stream) {
+ stream_status = dc_stream_get_status(stream);
+ if (stream_status == NULL || stream_status->plane_count != surface_count)
+ return true;
+ }
+
+ return false;
+}
+
+static bool fast_update_only(struct dc_fast_update *fast_update,
+ struct dc_surface_update *srf_updates,
+ int surface_count,
+ struct dc_stream_update *stream_update,
+ struct dc_stream_state *stream)
+{
+ return fast_updates_exist(fast_update, surface_count)
+ && !full_update_required(srf_updates, surface_count, stream_update, stream);
+}
+
bool dc_update_planes_and_stream(struct dc *dc,
struct dc_surface_update *srf_updates, int surface_count,
struct dc_stream_state *stream,
@@ -4015,6 +4363,7 @@ bool dc_update_planes_and_stream(struct dc *dc,
enum surface_update_type update_type;
int i;
struct mall_temp_config mall_temp_config;
+ struct dc_fast_update fast_update[MAX_SURFACES] = {0};
/* In cases where MPO and split or ODM are used transitions can
* cause underflow. Apply stream configuration with minimal pipe
@@ -4023,6 +4372,7 @@ bool dc_update_planes_and_stream(struct dc *dc,
bool force_minimal_pipe_splitting;
bool is_plane_addition;
+ populate_fast_updates(fast_update, srf_updates, surface_count, stream_update);
force_minimal_pipe_splitting = could_mpcc_tree_change_for_active_pipes(
dc,
stream,
@@ -4072,14 +4422,26 @@ 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 (fast_update_only(fast_update, srf_updates, surface_count, stream_update, stream) &&
+ !dc->debug.enable_legacy_fast_update) {
+ 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) {
@@ -4119,7 +4481,9 @@ void dc_commit_updates_for_stream(struct dc *dc,
struct dc_state *context;
struct dc_context *dc_ctx = dc->ctx;
int i, j;
+ struct dc_fast_update fast_update[MAX_SURFACES] = {0};
+ populate_fast_updates(fast_update, srf_updates, surface_count, stream_update);
stream_status = dc_stream_get_status(stream);
context = dc->current_state;
@@ -4204,7 +4568,18 @@ 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 (fast_update_only(fast_update, srf_updates, surface_count, stream_update, stream) &&
+ !dc->debug.enable_legacy_fast_update) {
+ 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 +4587,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 +4674,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 &&
@@ -4507,15 +4880,17 @@ static void blank_and_force_memclk(struct dc *dc, bool apply, unsigned int memcl
*/
void dc_enable_dcmode_clk_limit(struct dc *dc, bool enable)
{
- uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev;
- unsigned int softMax, maxDPM, funcMin;
+ unsigned int softMax = 0, maxDPM = 0, funcMin = 0, i;
bool p_state_change_support;
- if (!ASICREV_IS_BEIGE_GOBY_P(hw_internal_rev))
+ if (!dc->config.dc_mode_clk_limit_support)
return;
softMax = dc->clk_mgr->bw_params->dc_mode_softmax_memclk;
- maxDPM = dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz;
+ for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries; i++) {
+ if (dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz > maxDPM)
+ maxDPM = dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz;
+ }
funcMin = (dc->clk_mgr->clks.dramclk_khz + 999) / 1000;
p_state_change_support = dc->clk_mgr->clks.p_state_change_support;
@@ -4640,7 +5015,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 +5062,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 +5106,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 +5116,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 +5151,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 +5159,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 +5193,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 +5273,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..cb2bf9a466f5 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 && !current_mpc_pipe->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..63948170fd6d 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.241"
#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;
@@ -406,7 +416,7 @@ struct dc_config {
uint8_t force_bios_fixed_vs;
int sdpif_request_limit_words_per_umc;
bool use_old_fixed_vs_sequence;
- bool disable_subvp_drr;
+ bool dc_mode_clk_limit_support;
};
enum visual_confirm {
@@ -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;
@@ -835,6 +850,7 @@ struct dc_debug_options {
/* Enable dmub aux for legacy ddc */
bool enable_dmub_aux_for_legacy_ddc;
bool disable_fams;
+ bool disable_fams_gaming;
/* FEC/PSR1 sequence enable delay in 100us */
uint8_t fec_enable_delay_in100us;
bool enable_driver_sequence_debug;
@@ -855,7 +871,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 +894,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;
@@ -1242,6 +1265,16 @@ struct dc_scaling_info {
struct scaling_taps scaling_quality;
};
+struct dc_fast_update {
+ const struct dc_flip_addrs *flip_addr;
+ const struct dc_gamma *gamma;
+ const struct colorspace_transform *gamut_remap_matrix;
+ const struct dc_csc_transform *input_csc_color_matrix;
+ const struct fixed31_32 *coeff_reduction_factor;
+ struct dc_transfer_func *out_transfer_func;
+ struct dc_csc_transform *output_csc_transform;
+};
+
struct dc_surface_update {
struct dc_plane_state *surface;
@@ -1502,6 +1535,8 @@ 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;
+ bool read_dpcd204h_on_irq_hpd;
} wa_flags;
struct link_mst_stream_allocation_table mst_stream_alloc_table;
@@ -2126,8 +2161,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 +2253,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..c753c6f30dd7 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,35 @@ 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);
}
}
+
+bool dc_dmub_check_min_version(struct dmub_srv *srv)
+{
+ if (!srv->hw_funcs.is_psrsu_supported)
+ return true;
+ return srv->hw_funcs.is_psrsu_supported(srv);
+}
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..099f94b6107c 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);
@@ -89,4 +86,5 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc, struct dc_state *context, b
void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv);
void dc_send_update_cursor_info_to_dmu(struct pipe_ctx *pCtx, uint8_t pipe_idx);
+bool dc_dmub_check_min_version(struct dmub_srv *srv);
#endif /* _DMUB_DC_SRV_H_ */
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_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h
index e6c06325742a..168cb7094c95 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h
@@ -266,7 +266,24 @@
type MASTER_COMM_INTERRUPT; \
type MASTER_COMM_CMD_REG_BYTE0; \
type MASTER_COMM_CMD_REG_BYTE1; \
- type MASTER_COMM_CMD_REG_BYTE2
+ type MASTER_COMM_CMD_REG_BYTE2; \
+ type ABM1_HG_BIN_33_40_SHIFT_INDEX; \
+ type ABM1_HG_BIN_33_64_SHIFT_FLAG; \
+ type ABM1_HG_BIN_41_48_SHIFT_INDEX; \
+ type ABM1_HG_BIN_49_56_SHIFT_INDEX; \
+ type ABM1_HG_BIN_57_64_SHIFT_INDEX; \
+ type ABM1_HG_RESULT_DATA; \
+ type ABM1_HG_RESULT_INDEX; \
+ type ABM1_ACE_SLOPE_DATA; \
+ type ABM1_ACE_OFFSET_DATA; \
+ type ABM1_ACE_OFFSET_SLOPE_INDEX; \
+ type ABM1_ACE_THRES_INDEX; \
+ type ABM1_ACE_IGNORE_MASTER_LOCK_EN; \
+ type ABM1_ACE_READBACK_DB_REG_VALUE_EN; \
+ type ABM1_ACE_DBUF_REG_UPDATE_PENDING; \
+ type ABM1_ACE_LOCK; \
+ type ABM1_ACE_THRES_DATA_1; \
+ type ABM1_ACE_THRES_DATA_2
struct dce_abm_shift {
ABM_REG_FIELD_LIST(uint8_t);
@@ -288,6 +305,16 @@ struct dce_abm_registers {
uint32_t DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES;
uint32_t DC_ABM1_HGLS_REG_READ_PROGRESS;
uint32_t DC_ABM1_ACE_OFFSET_SLOPE_0;
+ uint32_t DC_ABM1_ACE_OFFSET_SLOPE_DATA;
+ uint32_t DC_ABM1_ACE_PWL_CNTL;
+ uint32_t DC_ABM1_HG_BIN_33_40_SHIFT_INDEX;
+ uint32_t DC_ABM1_HG_BIN_33_64_SHIFT_FLAG;
+ uint32_t DC_ABM1_HG_BIN_41_48_SHIFT_INDEX;
+ uint32_t DC_ABM1_HG_BIN_49_56_SHIFT_INDEX;
+ uint32_t DC_ABM1_HG_BIN_57_64_SHIFT_INDEX;
+ uint32_t DC_ABM1_HG_RESULT_DATA;
+ uint32_t DC_ABM1_HG_RESULT_INDEX;
+ uint32_t DC_ABM1_ACE_THRES_DATA;
uint32_t DC_ABM1_ACE_THRES_12;
uint32_t MASTER_COMM_CNTL_REG;
uint32_t MASTER_COMM_CMD_REG;
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..6966420dfbac 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)
@@ -780,7 +777,8 @@ void dce110_edp_wait_for_hpd_ready(
dal_gpio_destroy_irq(&hpd);
/* ensure that the panel is detected */
- ASSERT(edp_hpd_high);
+ if (!edp_hpd_high)
+ DC_LOG_DC("%s: wait timed out!\n", __func__);
}
void dce110_edp_power_control(
@@ -1219,7 +1217,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);
}
@@ -1794,10 +1793,13 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
hws->funcs.edp_backlight_control(edp_link_with_sink, false);
}
/*resume from S3, no vbios posting, no need to power down again*/
+ clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr);
+
power_down_all_hw_blocks(dc);
disable_vga_and_power_gate_all_controllers(dc);
if (edp_link_with_sink && !keep_edp_vdd_on)
dc->hwss.edp_power_control(edp_link_with_sink, false);
+ clk_mgr_optimize_pwr_state(dc, dc->clk_mgr);
}
bios_set_scratch_acc_mode_change(dc->ctx->dc_bios, 1);
}
@@ -2291,6 +2293,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..e115ff91aaaa 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
@@ -970,10 +974,12 @@ enum dc_status resource_map_phy_clock_resources(
|| dc_is_virtual_signal(pipe_ctx->stream->signal))
pipe_ctx->clock_source =
dc->res_pool->dp_clock_source;
- else
- pipe_ctx->clock_source = find_matching_pll(
- &context->res_ctx, dc->res_pool,
- stream);
+ else {
+ if (stream && stream->link && stream->link->link_enc)
+ pipe_ctx->clock_source = find_matching_pll(
+ &context->res_ctx, dc->res_pool,
+ stream);
+ }
if (pipe_ctx->clock_source == NULL)
return DC_NO_CLOCK_SOURCE_RESOURCE;
@@ -1239,6 +1245,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_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
index 7a00fe525dfb..3538973bd0c6 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
@@ -308,7 +308,10 @@ bool cm_helper_convert_to_custom_float(
#define NUMBER_REGIONS 32
#define NUMBER_SW_SEGMENTS 16
-bool cm_helper_translate_curve_to_hw_format(
+#define DC_LOGGER \
+ ctx->logger
+
+bool cm_helper_translate_curve_to_hw_format(struct dc_context *ctx,
const struct dc_transfer_func *output_tf,
struct pwl_params *lut_params, bool fixpoint)
{
@@ -482,10 +485,18 @@ bool cm_helper_translate_curve_to_hw_format(
rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue);
+
if (fixpoint == true) {
- rgb->delta_red_reg = dc_fixpt_clamp_u0d10(rgb->delta_red);
- rgb->delta_green_reg = dc_fixpt_clamp_u0d10(rgb->delta_green);
- rgb->delta_blue_reg = dc_fixpt_clamp_u0d10(rgb->delta_blue);
+ uint32_t red_clamp = dc_fixpt_clamp_u0d14(rgb->delta_red);
+ uint32_t green_clamp = dc_fixpt_clamp_u0d14(rgb->delta_green);
+ uint32_t blue_clamp = dc_fixpt_clamp_u0d14(rgb->delta_blue);
+
+ if (red_clamp >> 10 || green_clamp >> 10 || blue_clamp >> 10)
+ DC_LOG_WARNING("Losing delta precision while programming shaper LUT.");
+
+ rgb->delta_red_reg = red_clamp & 0x3ff;
+ rgb->delta_green_reg = green_clamp & 0x3ff;
+ rgb->delta_blue_reg = blue_clamp & 0x3ff;
rgb->red_reg = dc_fixpt_clamp_u0d14(rgb->red);
rgb->green_reg = dc_fixpt_clamp_u0d14(rgb->green);
rgb->blue_reg = dc_fixpt_clamp_u0d14(rgb->blue);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h
index 3b8cd7410498..0a68b63d6126 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h
@@ -106,6 +106,7 @@ bool cm_helper_convert_to_custom_float(
bool fixpoint);
bool cm_helper_translate_curve_to_hw_format(
+ struct dc_context *ctx,
const struct dc_transfer_func *output_tf,
struct pwl_params *lut_params, bool fixpoint);
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..9834b75f1837 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);
@@ -1867,7 +1843,7 @@ bool dcn10_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
/* dcn10_translate_regamma_to_hw_format takes 750us, only do it when full
* update.
*/
- else if (cm_helper_translate_curve_to_hw_format(
+ else if (cm_helper_translate_curve_to_hw_format(dc->ctx,
stream->out_transfer_func,
&dpp->regamma_params, false)) {
dpp->funcs->dpp_program_regamma_pwl(
@@ -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,
@@ -3309,7 +3278,8 @@ void dcn10_wait_for_mpcc_disconnect(
if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst]) {
struct hubp *hubp = get_hubp_by_inst(res_pool, mpcc_inst);
- if (pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg))
+ if (pipe_ctx->stream_res.tg &&
+ pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg))
res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst);
pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false;
hubp->funcs->set_blank(hubp, true);
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..4492bc2392b6 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;
@@ -863,7 +867,7 @@ bool dcn20_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
params = &stream->out_transfer_func->pwl;
else if (pipe_ctx->stream->out_transfer_func->type ==
TF_TYPE_DISTRIBUTED_POINTS &&
- cm_helper_translate_curve_to_hw_format(
+ cm_helper_translate_curve_to_hw_format(dc->ctx,
stream->out_transfer_func,
&mpc->blender_params, false))
params = &mpc->blender_params;
@@ -892,7 +896,7 @@ bool dcn20_set_blend_lut(
if (plane_state->blend_tf->type == TF_TYPE_HWPWL)
blend_lut = &plane_state->blend_tf->pwl;
else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) {
- cm_helper_translate_curve_to_hw_format(
+ cm_helper_translate_curve_to_hw_format(plane_state->ctx,
plane_state->blend_tf,
&dpp_base->regamma_params, false);
blend_lut = &dpp_base->regamma_params;
@@ -914,7 +918,7 @@ bool dcn20_set_shaper_3dlut(
if (plane_state->in_shaper_func->type == TF_TYPE_HWPWL)
shaper_lut = &plane_state->in_shaper_func->pwl;
else if (plane_state->in_shaper_func->type == TF_TYPE_DISTRIBUTED_POINTS) {
- cm_helper_translate_curve_to_hw_format(
+ cm_helper_translate_curve_to_hw_format(plane_state->ctx,
plane_state->in_shaper_func,
&dpp_base->shaper_params, true);
shaper_lut = &dpp_base->shaper_params;
@@ -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,
@@ -1755,8 +1764,9 @@ static void dcn20_program_pipe(
hws->funcs.set_hdr_multiplier(pipe_ctx);
if (pipe_ctx->update_flags.bits.enable ||
- pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
- pipe_ctx->plane_state->update_flags.bits.gamma_change)
+ pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
+ pipe_ctx->plane_state->update_flags.bits.gamma_change ||
+ pipe_ctx->plane_state->update_flags.bits.lut_3d)
hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state);
/* dcn10_translate_regamma_to_hw_format takes 750us to finish
@@ -2117,7 +2127,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 +2135,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 +2472,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 +2572,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 +2627,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 +2649,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..9f2e24398cd7 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
@@ -712,7 +712,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.timing_trace = false,
.clock_trace = true,
.disable_pplib_clock_request = true,
- .pipe_split_policy = MPC_SPLIT_DYNAMIC,
+ .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP,
.force_single_disp_pipe_split = false,
.disable_dcc = DCC_ENABLE,
.vsr_support = true,
@@ -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_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c
index e5b7ef7422b8..50dc83404644 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c
@@ -357,8 +357,11 @@ void dpp3_set_cursor_attributes(
int cur_rom_en = 0;
if (color_format == CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA ||
- color_format == CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA)
- cur_rom_en = 1;
+ color_format == CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA) {
+ if (cursor_attributes->attribute_flags.bits.ENABLE_CURSOR_DEGAMMA) {
+ cur_rom_en = 1;
+ }
+ }
REG_UPDATE_3(CURSOR0_CONTROL,
CUR0_MODE, color_format,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c
index 6a3d3a0ec0a3..701c7d8bc038 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c
@@ -280,7 +280,7 @@ bool dwb3_ogam_set_input_transfer_func(
dwb_ogam_lut = kzalloc(sizeof(*dwb_ogam_lut), GFP_KERNEL);
if (dwb_ogam_lut) {
- cm_helper_translate_curve_to_hw_format(
+ cm_helper_translate_curve_to_hw_format(dwbc->ctx,
in_transfer_func_dwb_ogam,
dwb_ogam_lut, false);
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..bf8864bc8a99 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
@@ -106,7 +106,7 @@ static bool dcn30_set_mpc_shaper_3dlut(struct pipe_ctx *pipe_ctx,
if (stream->func_shaper->type == TF_TYPE_HWPWL) {
shaper_lut = &stream->func_shaper->pwl;
} else if (stream->func_shaper->type == TF_TYPE_DISTRIBUTED_POINTS) {
- cm_helper_translate_curve_to_hw_format(stream->func_shaper,
+ cm_helper_translate_curve_to_hw_format(stream->ctx, stream->func_shaper,
&dpp_base->shaper_params, true);
shaper_lut = &dpp_base->shaper_params;
}
@@ -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..5bf4d0aa6230 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);
}
@@ -216,7 +215,7 @@ void optc3_set_odm_bypass(struct timing_generator *optc,
optc1->opp_count = 1;
}
-static void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
+void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
struct dc_crtc_timing *timing)
{
struct optc *optc1 = DCN10TG_FROM_TG(optc);
@@ -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)
@@ -291,7 +293,7 @@ static void optc3_set_timing_double_buffer(struct timing_generator *optc, bool e
OTG_DRR_TIMING_DBUF_UPDATE_MODE, mode);
}
-static void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *optc)
+void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *optc)
{
struct optc *optc1 = DCN10TG_FROM_TG(optc);
@@ -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_optc.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h
index fb06dc9a4893..d3a056c12b0d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h
@@ -351,6 +351,9 @@ void optc3_set_timing_db_mode(struct timing_generator *optc, bool enable);
void optc3_set_odm_bypass(struct timing_generator *optc,
const struct dc_crtc_timing *dc_crtc_timing);
+void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
+ struct dc_crtc_timing *timing);
+void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *optc);
void optc3_tg_init(struct timing_generator *optc);
void optc3_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max);
#endif /* __DC_OPTC_DCN30_H__ */
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..abe4c12a10b5 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
@@ -725,25 +725,8 @@ static const struct dc_debug_options debug_defaults_drv = {
.dwb_fi_phase = -1, // -1 = disable,
.dmub_command_table = true,
.use_max_lb = true,
- .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
+ .exit_idle_opt_for_cursor_updates = true,
+ .enable_legacy_fast_update = false,
};
static const struct dc_panel_config panel_config_defaults = {
@@ -1076,13 +1059,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;
@@ -2011,11 +1987,10 @@ bool dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc,
if (!is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch(context))
return false;
- // check if freesync enabled
if (!context->streams[0]->allow_freesync)
return false;
- if (context->streams[0]->vrr_active_variable)
+ if (context->streams[0]->vrr_active_variable && dc->debug.disable_fams_gaming)
return false;
context->streams[0]->fpo_in_use = true;
@@ -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/Makefile b/drivers/gpu/drm/amd/display/dc/dcn301/Makefile
index 7aa628c21973..9002cb10a6ae 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn301/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn301/Makefile
@@ -11,7 +11,8 @@
# Makefile for dcn30.
DCN301 = dcn301_init.o dcn301_resource.o dcn301_dccg.o \
- dcn301_dio_link_encoder.o dcn301_hwseq.o dcn301_panel_cntl.o dcn301_hubbub.o
+ dcn301_dio_link_encoder.o dcn301_hwseq.o dcn301_panel_cntl.o dcn301_hubbub.o \
+ dcn301_optc.o
AMD_DAL_DCN301 = $(addprefix $(AMDDALPATH)/dc/dcn301/,$(DCN301))
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_optc.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.c
new file mode 100644
index 000000000000..b3cfcb887905
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.c
@@ -0,0 +1,185 @@
+/*
+ * 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
+ * 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 "reg_helper.h"
+#include "dcn301_optc.h"
+#include "dc.h"
+#include "dcn_calc_math.h"
+#include "dc_dmub_srv.h"
+
+#include "dml/dcn30/dcn30_fpu.h"
+#include "dc_trace.h"
+
+#define REG(reg)\
+ optc1->tg_regs->reg
+
+#define CTX \
+ optc1->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+ optc1->tg_shift->field_name, optc1->tg_mask->field_name
+
+
+/**
+ * optc301_set_drr() - Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*.
+ *
+ * @optc: timing_generator instance.
+ * @params: parameters used for Dynamic Refresh Rate.
+ */
+void optc301_set_drr(
+ struct timing_generator *optc,
+ const struct drr_params *params)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+ if (params != NULL &&
+ params->vertical_total_max > 0 &&
+ params->vertical_total_min > 0) {
+
+ if (params->vertical_total_mid != 0) {
+
+ REG_SET(OTG_V_TOTAL_MID, 0,
+ OTG_V_TOTAL_MID, params->vertical_total_mid - 1);
+
+ REG_UPDATE_2(OTG_V_TOTAL_CONTROL,
+ OTG_VTOTAL_MID_REPLACING_MAX_EN, 1,
+ OTG_VTOTAL_MID_FRAME_NUM,
+ (uint8_t)params->vertical_total_mid_frame_num);
+
+ }
+
+ optc->funcs->set_vtotal_min_max(optc, params->vertical_total_min - 1, params->vertical_total_max - 1);
+
+ REG_UPDATE_5(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_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);
+ }
+}
+
+
+void optc301_setup_manual_trigger(struct timing_generator *optc)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+ REG_SET_8(OTG_TRIGA_CNTL, 0,
+ OTG_TRIGA_SOURCE_SELECT, 21,
+ OTG_TRIGA_SOURCE_PIPE_SELECT, optc->inst,
+ OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1,
+ OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 0,
+ OTG_TRIGA_POLARITY_SELECT, 0,
+ OTG_TRIGA_FREQUENCY_SELECT, 0,
+ OTG_TRIGA_DELAY, 0,
+ OTG_TRIGA_CLEAR, 1);
+}
+
+static struct timing_generator_funcs dcn30_tg_funcs = {
+ .validate_timing = optc1_validate_timing,
+ .program_timing = optc1_program_timing,
+ .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0,
+ .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1,
+ .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2,
+ .program_global_sync = optc1_program_global_sync,
+ .enable_crtc = optc2_enable_crtc,
+ .disable_crtc = optc1_disable_crtc,
+ /* used by enable_timing_synchronization. Not need for FPGA */
+ .is_counter_moving = optc1_is_counter_moving,
+ .get_position = optc1_get_position,
+ .get_frame_count = optc1_get_vblank_counter,
+ .get_scanoutpos = optc1_get_crtc_scanoutpos,
+ .get_otg_active_size = optc1_get_otg_active_size,
+ .set_early_control = optc1_set_early_control,
+ /* used by enable_timing_synchronization. Not need for FPGA */
+ .wait_for_state = optc1_wait_for_state,
+ .set_blank_color = optc3_program_blank_color,
+ .did_triggered_reset_occur = optc1_did_triggered_reset_occur,
+ .triplebuffer_lock = optc3_triplebuffer_lock,
+ .triplebuffer_unlock = optc2_triplebuffer_unlock,
+ .enable_reset_trigger = optc1_enable_reset_trigger,
+ .enable_crtc_reset = optc1_enable_crtc_reset,
+ .disable_reset_trigger = optc1_disable_reset_trigger,
+ .lock = optc3_lock,
+ .unlock = optc1_unlock,
+ .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable,
+ .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable,
+ .enable_optc_clock = optc1_enable_optc_clock,
+ .set_drr = optc301_set_drr,
+ .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal,
+ .set_vtotal_min_max = optc3_set_vtotal_min_max,
+ .set_static_screen_control = optc1_set_static_screen_control,
+ .program_stereo = optc1_program_stereo,
+ .is_stereo_left_eye = optc1_is_stereo_left_eye,
+ .tg_init = optc3_tg_init,
+ .is_tg_enabled = optc1_is_tg_enabled,
+ .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred,
+ .clear_optc_underflow = optc1_clear_optc_underflow,
+ .setup_global_swap_lock = NULL,
+ .get_crc = optc1_get_crc,
+ .configure_crc = optc2_configure_crc,
+ .set_dsc_config = optc3_set_dsc_config,
+ .get_dsc_status = optc2_get_dsc_status,
+ .set_dwb_source = NULL,
+ .set_odm_bypass = optc3_set_odm_bypass,
+ .set_odm_combine = optc3_set_odm_combine,
+ .get_optc_source = optc2_get_optc_source,
+ .set_out_mux = optc3_set_out_mux,
+ .set_drr_trigger_window = optc3_set_drr_trigger_window,
+ .set_vtotal_change_limit = optc3_set_vtotal_change_limit,
+ .set_gsl = optc2_set_gsl,
+ .set_gsl_source_select = optc2_set_gsl_source_select,
+ .set_vtg_params = optc1_set_vtg_params,
+ .program_manual_trigger = optc2_program_manual_trigger,
+ .setup_manual_trigger = optc301_setup_manual_trigger,
+ .get_hw_timing = optc1_get_hw_timing,
+ .wait_drr_doublebuffer_pending_clear = optc3_wait_drr_doublebuffer_pending_clear,
+};
+
+void dcn301_timing_generator_init(struct optc *optc1)
+{
+ optc1->base.funcs = &dcn30_tg_funcs;
+
+ optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1;
+ optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1;
+
+ optc1->min_h_blank = 32;
+ optc1->min_v_blank = 3;
+ optc1->min_v_blank_interlace = 5;
+ optc1->min_h_sync_width = 4;
+ optc1->min_v_sync_width = 1;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.h b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.h
new file mode 100644
index 000000000000..b49585682a15
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.h
@@ -0,0 +1,36 @@
+/*
+ * 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
+ * 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 __DC_OPTC_DCN301_H__
+#define __DC_OPTC_DCN301_H__
+
+#include "dcn20/dcn20_optc.h"
+#include "dcn30/dcn30_optc.h"
+
+void dcn301_timing_generator_init(struct optc *optc1);
+void optc301_setup_manual_trigger(struct timing_generator *optc);
+void optc301_set_drr(struct timing_generator *optc, const struct drr_params *params);
+
+#endif /* __DC_OPTC_DCN301_H__ */
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..1bee9a4636e6 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
@@ -42,7 +42,7 @@
#include "dcn30/dcn30_hubp.h"
#include "irq/dcn30/irq_service_dcn30.h"
#include "dcn30/dcn30_dpp.h"
-#include "dcn30/dcn30_optc.h"
+#include "dcn301/dcn301_optc.h"
#include "dcn20/dcn20_hwseq.h"
#include "dcn30/dcn30_hwseq.h"
#include "dce110/dce110_hw_sequencer.h"
@@ -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));
@@ -872,7 +855,7 @@ static struct timing_generator *dcn301_timing_generator_create(
tgn10->tg_shift = &optc_shift;
tgn10->tg_mask = &optc_mask;
- dcn30_timing_generator_init(tgn10);
+ dcn301_timing_generator_init(tgn10);
return &tgn10->base;
}
@@ -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..5ad6a22ee47d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c
@@ -95,25 +95,8 @@ static const struct dc_debug_options debug_defaults_drv = {
.dwb_fi_phase = -1, // -1 = disable,
.dmub_command_table = true,
.use_max_lb = true,
- .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
+ .exit_idle_opt_for_cursor_updates = true,
+ .enable_legacy_fast_update = false,
};
static const struct dc_panel_config panel_config_defaults = {
@@ -954,13 +937,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 +1228,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 +1286,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 +1464,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..131b8b82afc0 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c
@@ -65,7 +65,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.timing_trace = false,
.clock_trace = true,
.disable_pplib_clock_request = true,
- .pipe_split_policy = MPC_SPLIT_DYNAMIC,
+ .pipe_split_policy = MPC_SPLIT_AVOID,
.force_single_disp_pipe_split = false,
.disable_dcc = DCC_ENABLE,
.vsr_support = true,
@@ -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;
@@ -1213,6 +1190,7 @@ static bool dcn303_resource_construct(
dc->caps.dp_hdmi21_pcon_support = true;
+ dc->config.dc_mode_clk_limit_support = true;
/* read VBIOS LTTPR caps */
if (ctx->dc_bios->funcs->get_lttpr_caps) {
enum bp_result bp_query_result;
@@ -1232,8 +1210,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 +1376,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..01cc679ae418 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;
@@ -76,7 +84,8 @@ static enum phyd32clk_clock_source get_phy_mux_symclk(
struct dcn_dccg *dccg_dcn,
enum phyd32clk_clock_source src)
{
- if (dccg_dcn->base.ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) {
+ if (dccg_dcn->base.ctx->asic_id.chip_family == FAMILY_YELLOW_CARP &&
+ dccg_dcn->base.ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) {
if (src == PHYD32CLKC)
src = PHYD32CLKF;
if (src == PHYD32CLKD)
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..0746ed31d1d1 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..4d2820ffe468 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c
@@ -390,6 +390,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)
@@ -400,29 +429,6 @@ void dcn314_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst,
hws->ctx->dc->res_pool->dccg, dpp_inst, clock_on);
}
-void dcn314_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on)
-{
- struct dc_context *ctx = hws->ctx;
- union dmub_rb_cmd cmd;
-
- if (hws->ctx->dc->debug.disable_hubp_power_gate)
- return;
-
- PERF_TRACE();
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.domain_control.header.type = DMUB_CMD__VBIOS;
- cmd.domain_control.header.sub_type = DMUB_CMD__VBIOS_DOMAIN_CONTROL;
- cmd.domain_control.header.payload_bytes = sizeof(cmd.domain_control.data);
- 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);
-
- PERF_TRACE();
-}
static void apply_symclk_on_tx_off_wa(struct dc_link *link)
{
/* There are use cases where SYMCLK is referenced by OTG. For instance
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..eafcc4ea6d24 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h
@@ -41,7 +41,7 @@ unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsig
void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx);
-void dcn314_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on);
+void dcn314_resync_fifo_dccg_dio(struct dce_hwseq *hws, struct dc *dc, struct dc_state *context);
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..ca8fe55c33b8 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 = {
@@ -138,7 +139,7 @@ static const struct hwseq_private_funcs dcn314_private_funcs = {
.plane_atomic_power_down = dcn10_plane_atomic_power_down,
.enable_power_gating_plane = dcn314_enable_power_gating_plane,
.dpp_root_clock_control = dcn314_dpp_root_clock_control,
- .hubp_pg_control = dcn314_hubp_pg_control,
+ .hubp_pg_control = dcn31_hubp_pg_control,
.program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree,
.update_odm = dcn314_update_odm,
.dsc_pg_control = dcn314_dsc_pg_control,
@@ -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..6a9024aa3285 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;
@@ -1920,6 +1903,14 @@ static bool dcn314_resource_construct(
dc->debug = debug_defaults_drv;
else
dc->debug = debug_defaults_diags;
+
+ /* Disable pipe power gating */
+ dc->debug.disable_dpp_power_gate = true;
+ dc->debug.disable_hubp_power_gate = true;
+
+ /* Disable root clock optimization */
+ dc->debug.root_clock_optimization.u32All = 0;
+
// Init the vm_helper
if (dc->vm_helper)
vm_helper_init(dc->vm_helper, 16);
@@ -2101,8 +2092,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..df3a438abda8 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)
+ 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..61ceff6bc0b1 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,17 @@
#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_GET(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_RDIVIDER, &dispclk_rdivider_value);
- REG_WRITE(DENTIST_DISPCLK_CNTL, dentist_dispclk_value);
- REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 2000);
+ /* Not valid for the WDIVIDER to be set to 0 */
+ if (dispclk_rdivider_value != 0)
+ REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, dispclk_rdivider_value);
}
static void dccg32_get_pixel_rate_div(
@@ -124,29 +123,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 +343,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_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.c
index 2d604f7ee782..ca5b4b28a664 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.c
@@ -179,6 +179,7 @@ static struct hubp_funcs dcn32_hubp_funcs = {
.hubp_setup_interdependent = hubp2_setup_interdependent,
.hubp_set_vm_system_aperture_settings = hubp3_set_vm_system_aperture_settings,
.set_blank = hubp2_set_blank,
+ .set_blank_regs = hubp2_set_blank_regs,
.dcc_control = hubp3_dcc_control,
.mem_program_viewport = min_set_viewport,
.set_cursor_attributes = hubp32_cursor_set_attributes,
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..d52d5feeb311 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)
@@ -428,7 +448,7 @@ bool dcn32_set_mpc_shaper_3dlut(
if (stream->func_shaper->type == TF_TYPE_HWPWL)
shaper_lut = &stream->func_shaper->pwl;
else if (stream->func_shaper->type == TF_TYPE_DISTRIBUTED_POINTS) {
- cm_helper_translate_curve_to_hw_format(
+ cm_helper_translate_curve_to_hw_format(stream->ctx,
stream->func_shaper,
&dpp_base->shaper_params, true);
shaper_lut = &dpp_base->shaper_params;
@@ -464,7 +484,7 @@ bool dcn32_set_mcm_luts(
if (plane_state->blend_tf->type == TF_TYPE_HWPWL)
lut_params = &plane_state->blend_tf->pwl;
else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) {
- cm_helper_translate_curve_to_hw_format(
+ cm_helper_translate_curve_to_hw_format(plane_state->ctx,
plane_state->blend_tf,
&dpp_base->regamma_params, false);
lut_params = &dpp_base->regamma_params;
@@ -479,7 +499,7 @@ bool dcn32_set_mcm_luts(
else if (plane_state->in_shaper_func->type == TF_TYPE_DISTRIBUTED_POINTS) {
// TODO: dpp_base replace
ASSERT(false);
- cm_helper_translate_curve_to_hw_format(
+ cm_helper_translate_curve_to_hw_format(plane_state->ctx,
plane_state->in_shaper_func,
&dpp_base->shaper_params, true);
lut_params = &dpp_base->shaper_params;
@@ -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;
}
}
@@ -1125,10 +1147,6 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign
unsigned int odm_combine_factor = 0;
bool two_pix_per_container = false;
- // For phantom pipes, use the same programming as the main pipes
- if (pipe_ctx->stream->mall_stream_config.type == SUBVP_PHANTOM) {
- 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);
@@ -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..2d2628f31bed 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h
@@ -75,6 +75,8 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign
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..777b2fac20c4 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c
@@ -56,6 +56,7 @@ static const struct hw_sequencer_funcs dcn32_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,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 +155,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 +164,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..1cc09799f92d 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,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,
-};
-
-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,
+ .enable_legacy_fast_update = false,
};
static struct dce_aux *dcn32_aux_engine_create(
@@ -1353,15 +1338,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 +1864,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 +2176,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;
@@ -2236,6 +2215,7 @@ static bool dcn32_resource_construct(
/* Use pipe context based otg sync logic */
dc->config.use_pipe_ctx_sync_logic = true;
+ dc->config.dc_mode_clk_limit_support = true;
/* read VBIOS LTTPR caps */
{
if (ctx->dc_bios->funcs->get_lttpr_caps) {
@@ -2254,10 +2234,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 +2290,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 +2427,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..5be242a1b82c 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;
@@ -647,12 +595,128 @@ struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stre
if (!is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch(fpo_candidate_stream, fpo_vactive_margin_us))
return NULL;
- // check if freesync enabled
if (!fpo_candidate_stream->allow_freesync)
return NULL;
- if (fpo_candidate_stream->vrr_active_variable)
+ if (fpo_candidate_stream->vrr_active_variable && dc->debug.disable_fams_gaming)
return NULL;
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..a53478e15ce3 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,15 @@ 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,
+ .enable_legacy_fast_update = false,
+ .disable_dc_mode_overwrite = 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_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 +1324,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 +1710,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 +1720,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;
@@ -1780,6 +1756,7 @@ static bool dcn321_resource_construct(
dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
dc->caps.color.mpc.ocsc = 1;
+ dc->config.dc_mode_clk_limit_support = true;
/* read VBIOS LTTPR caps */
{
if (ctx->dc_bios->funcs->get_lttpr_caps) {
@@ -1798,10 +1775,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 +1831,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 +1963,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/dcn20/display_mode_vba_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c
index 6266b0788387..7bf4bb7ad044 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c
@@ -4356,12 +4356,16 @@ void dml20_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
locals->PSCL_FACTOR[k] / locals->ReturnBWPerState[i][0],
locals->EffectiveLBLatencyHidingSourceLinesLuma),
locals->SwathHeightYPerState[i][j][k]);
-
- locals->EffectiveDETLBLinesChroma = dml_floor(locals->LinesInDETChroma + dml_min(
- locals->LinesInDETChroma * locals->RequiredDISPCLK[i][j] * locals->BytePerPixelInDETC[k] *
- locals->PSCL_FACTOR_CHROMA[k] / locals->ReturnBWPerState[i][0],
- locals->EffectiveLBLatencyHidingSourceLinesChroma),
- locals->SwathHeightCPerState[i][j][k]);
+ if (locals->LinesInDETChroma) {
+ locals->EffectiveDETLBLinesChroma = dml_floor(locals->LinesInDETChroma +
+ dml_min(locals->LinesInDETChroma * locals->RequiredDISPCLK[i][j] *
+ locals->BytePerPixelInDETC[k] *
+ locals->PSCL_FACTOR_CHROMA[k] / locals->ReturnBWPerState[i][0],
+ locals->EffectiveLBLatencyHidingSourceLinesChroma),
+ locals->SwathHeightCPerState[i][j][k]);
+ } else {
+ locals->EffectiveDETLBLinesChroma = 0;
+ }
if (locals->BytePerPixelInDETC[k] == 0) {
locals->UrgentLatencySupportUsPerState[i][j][k] = locals->EffectiveDETLBLinesLuma * (locals->HTotal[k] / locals->PixelClock[k])
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..ed8ddb75b333 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
@@ -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,15 @@ 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)
+ if (pipe->stream->adjust.v_total_min != 0)
pipes[pipe_cnt].pipe.dest.vtotal = pipe->stream->adjust.v_total_min;
+ else
+ pipes[pipe_cnt].pipe.dest.vtotal = timing->v_total;
+
+ 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 +325,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..a95034801712 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,
@@ -476,24 +485,20 @@ static void get_optimal_ntuple(struct _vcs_dpi_voltage_scaling_st *entry)
}
}
-void insert_entry_into_table_sorted(struct _vcs_dpi_voltage_scaling_st *table,
+static void insert_entry_into_table_sorted(struct _vcs_dpi_voltage_scaling_st *table,
unsigned int *num_entries,
struct _vcs_dpi_voltage_scaling_st *entry)
{
int i = 0;
int index = 0;
- float net_bw_of_new_state = 0;
dc_assert_fp_enabled();
- get_optimal_ntuple(entry);
-
if (*num_entries == 0) {
table[0] = *entry;
(*num_entries)++;
} else {
- net_bw_of_new_state = calculate_net_bw_in_kbytes_sec(entry);
- while (net_bw_of_new_state > calculate_net_bw_in_kbytes_sec(&table[index])) {
+ while (entry->net_bw_in_kbytes_sec > table[index].net_bw_in_kbytes_sec) {
index++;
if (index >= *num_entries)
break;
@@ -670,7 +675,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 +696,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 +715,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 +850,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 +863,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 +879,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 +894,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 +992,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 +1022,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 +1086,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 +1099,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 +1119,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 +1150,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 +1180,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 +1239,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 +1253,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 +1344,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 +1426,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 +1467,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 +2041,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 +2099,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 +2126,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 +2228,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 +2345,105 @@ 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,
+static void swap_table_entries(struct _vcs_dpi_voltage_scaling_st *first_entry,
+ struct _vcs_dpi_voltage_scaling_st *second_entry)
+{
+ struct _vcs_dpi_voltage_scaling_st temp_entry = *first_entry;
+ *first_entry = *second_entry;
+ *second_entry = temp_entry;
+}
+
+/*
+ * sort_entries_with_same_bw - Sort entries sharing the same bandwidth by DCFCLK
+ */
+static void sort_entries_with_same_bw(struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries)
+{
+ unsigned int start_index = 0;
+ unsigned int end_index = 0;
+ unsigned int current_bw = 0;
+
+ for (int i = 0; i < (*num_entries - 1); i++) {
+ if (table[i].net_bw_in_kbytes_sec == table[i+1].net_bw_in_kbytes_sec) {
+ current_bw = table[i].net_bw_in_kbytes_sec;
+ start_index = i;
+ end_index = ++i;
+
+ while ((i < (*num_entries - 1)) && (table[i+1].net_bw_in_kbytes_sec == current_bw))
+ end_index = ++i;
+ }
+
+ if (start_index != end_index) {
+ for (int j = start_index; j < end_index; j++) {
+ for (int k = start_index; k < end_index; k++) {
+ if (table[k].dcfclk_mhz > table[k+1].dcfclk_mhz)
+ swap_table_entries(&table[k], &table[k+1]);
+ }
+ }
+ }
+
+ start_index = 0;
+ end_index = 0;
+
+ }
+}
+
+/*
+ * remove_inconsistent_entries - Ensure entries with the same bandwidth have MEMCLK and FCLK monotonically increasing
+ * and remove entries that do not
+ */
+static void remove_inconsistent_entries(struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries)
+{
+ for (int i = 0; i < (*num_entries - 1); i++) {
+ if (table[i].net_bw_in_kbytes_sec == table[i+1].net_bw_in_kbytes_sec) {
+ if ((table[i].dram_speed_mts > table[i+1].dram_speed_mts) ||
+ (table[i].fabricclk_mhz > table[i+1].fabricclk_mhz))
+ remove_entry_from_table_at_index(table, num_entries, i);
+ }
+ }
+}
+
+/*
+ * 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 +2454,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;
@@ -2375,14 +2533,18 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
entry.fabricclk_mhz = 0;
entry.dram_speed_mts = 0;
+ get_optimal_ntuple(&entry);
+ entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry);
insert_entry_into_table_sorted(table, num_entries, &entry);
}
// 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;
+ get_optimal_ntuple(&entry);
+ entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry);
insert_entry_into_table_sorted(table, num_entries, &entry);
// Insert the UCLK DPMS
@@ -2391,6 +2553,8 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
entry.fabricclk_mhz = 0;
entry.dram_speed_mts = bw_params->clk_table.entries[i].memclk_mhz * 16;
+ get_optimal_ntuple(&entry);
+ entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry);
insert_entry_into_table_sorted(table, num_entries, &entry);
}
@@ -2401,15 +2565,19 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
entry.fabricclk_mhz = bw_params->clk_table.entries[i].fclk_mhz;
entry.dram_speed_mts = 0;
+ get_optimal_ntuple(&entry);
+ entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry);
insert_entry_into_table_sorted(table, num_entries, &entry);
}
}
// 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;
+ get_optimal_ntuple(&entry);
+ entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry);
insert_entry_into_table_sorted(table, num_entries, &entry);
}
@@ -2419,12 +2587,27 @@ 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);
}
+ // Insert entry with all max dc limits without bandwidth matching
+ if (!disable_dc_mode_overwrite) {
+ struct _vcs_dpi_voltage_scaling_st max_dc_limits_entry = entry;
+
+ max_dc_limits_entry.dcfclk_mhz = max_clk_data.dcfclk_mhz;
+ max_dc_limits_entry.fabricclk_mhz = max_clk_data.fclk_mhz;
+ max_dc_limits_entry.dram_speed_mts = max_clk_data.memclk_mhz * 16;
+
+ max_dc_limits_entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&max_dc_limits_entry);
+ insert_entry_into_table_sorted(table, num_entries, &max_dc_limits_entry);
+
+ sort_entries_with_same_bw(table, num_entries);
+ remove_inconsistent_entries(table, num_entries);
+ }
+
// At this point, the table only contains supported points of interest
// it could be used as is, but some states may be redundant due to
// coarse grained nature of some clocks, so we want to round up to
@@ -2508,80 +2691,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 +2773,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 +2917,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 +2965,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 +3064,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 +3092,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 +3103,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 +3111,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 +3128,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..defbee866be6 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
@@ -39,10 +39,6 @@ void dcn32_helper_populate_phantom_dlg_params(struct dc *dc,
uint8_t dcn32_predict_pipe_split(struct dc_state *context,
display_e2e_pipe_params_st *pipe_e2e);
-void insert_entry_into_table_sorted(struct _vcs_dpi_voltage_scaling_st *table,
- unsigned int *num_entries,
- struct _vcs_dpi_voltage_scaling_st *entry);
-
void dcn32_set_phantom_stream_timing(struct dc *dc,
struct dc_state *context,
struct pipe_ctx *ref_pipe,
@@ -80,6 +76,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..b26fcf86014c 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
@@ -207,24 +207,20 @@ static float calculate_net_bw_in_kbytes_sec(struct _vcs_dpi_voltage_scaling_st *
return limiting_bw_kbytes_sec;
}
-void dcn321_insert_entry_into_table_sorted(struct _vcs_dpi_voltage_scaling_st *table,
+static void dcn321_insert_entry_into_table_sorted(struct _vcs_dpi_voltage_scaling_st *table,
unsigned int *num_entries,
struct _vcs_dpi_voltage_scaling_st *entry)
{
int i = 0;
int index = 0;
- float net_bw_of_new_state = 0;
dc_assert_fp_enabled();
- get_optimal_ntuple(entry);
-
if (*num_entries == 0) {
table[0] = *entry;
(*num_entries)++;
} else {
- net_bw_of_new_state = calculate_net_bw_in_kbytes_sec(entry);
- while (net_bw_of_new_state > calculate_net_bw_in_kbytes_sec(&table[index])) {
+ while (entry->net_bw_in_kbytes_sec > table[index].net_bw_in_kbytes_sec) {
index++;
if (index >= *num_entries)
break;
@@ -252,14 +248,105 @@ 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,
+static void swap_table_entries(struct _vcs_dpi_voltage_scaling_st *first_entry,
+ struct _vcs_dpi_voltage_scaling_st *second_entry)
+{
+ struct _vcs_dpi_voltage_scaling_st temp_entry = *first_entry;
+ *first_entry = *second_entry;
+ *second_entry = temp_entry;
+}
+
+/*
+ * sort_entries_with_same_bw - Sort entries sharing the same bandwidth by DCFCLK
+ */
+static void sort_entries_with_same_bw(struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries)
+{
+ unsigned int start_index = 0;
+ unsigned int end_index = 0;
+ unsigned int current_bw = 0;
+
+ for (int i = 0; i < (*num_entries - 1); i++) {
+ if (table[i].net_bw_in_kbytes_sec == table[i+1].net_bw_in_kbytes_sec) {
+ current_bw = table[i].net_bw_in_kbytes_sec;
+ start_index = i;
+ end_index = ++i;
+
+ while ((i < (*num_entries - 1)) && (table[i+1].net_bw_in_kbytes_sec == current_bw))
+ end_index = ++i;
+ }
+
+ if (start_index != end_index) {
+ for (int j = start_index; j < end_index; j++) {
+ for (int k = start_index; k < end_index; k++) {
+ if (table[k].dcfclk_mhz > table[k+1].dcfclk_mhz)
+ swap_table_entries(&table[k], &table[k+1]);
+ }
+ }
+ }
+
+ start_index = 0;
+ end_index = 0;
+
+ }
+}
+
+/*
+ * remove_inconsistent_entries - Ensure entries with the same bandwidth have MEMCLK and FCLK monotonically increasing
+ * and remove entries that do not follow this order
+ */
+static void remove_inconsistent_entries(struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries)
+{
+ for (int i = 0; i < (*num_entries - 1); i++) {
+ if (table[i].net_bw_in_kbytes_sec == table[i+1].net_bw_in_kbytes_sec) {
+ if ((table[i].dram_speed_mts > table[i+1].dram_speed_mts) ||
+ (table[i].fabricclk_mhz > table[i+1].fabricclk_mhz))
+ remove_entry_from_table_at_index(table, num_entries, i);
+ }
+ }
+}
+
+/*
+ * 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,51 +357,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;
+ 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_21_soc.pct_ideal_sdp_bw_after_urgent /
+ dcn3_21_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_21_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_21_soc.clock_limits[0].phyclk_d18_mhz;
entry.phyclk_d32_mhz = dcn3_21_soc.clock_limits[0].phyclk_d32_mhz;
@@ -324,14 +436,18 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
entry.fabricclk_mhz = 0;
entry.dram_speed_mts = 0;
+ get_optimal_ntuple(&entry);
+ entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry);
dcn321_insert_entry_into_table_sorted(table, num_entries, &entry);
}
// 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;
+ get_optimal_ntuple(&entry);
+ entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry);
dcn321_insert_entry_into_table_sorted(table, num_entries, &entry);
// Insert the UCLK DPMS
@@ -340,6 +456,8 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
entry.fabricclk_mhz = 0;
entry.dram_speed_mts = bw_params->clk_table.entries[i].memclk_mhz * 16;
+ get_optimal_ntuple(&entry);
+ entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry);
dcn321_insert_entry_into_table_sorted(table, num_entries, &entry);
}
@@ -350,15 +468,19 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
entry.fabricclk_mhz = bw_params->clk_table.entries[i].fclk_mhz;
entry.dram_speed_mts = 0;
+ get_optimal_ntuple(&entry);
+ entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry);
dcn321_insert_entry_into_table_sorted(table, num_entries, &entry);
}
}
// 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;
+ get_optimal_ntuple(&entry);
+ entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry);
dcn321_insert_entry_into_table_sorted(table, num_entries, &entry);
}
@@ -368,12 +490,29 @@ 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);
}
+ // Insert entry with all max dc limits without bandwitch matching
+ if (!disable_dc_mode_overwrite) {
+ struct _vcs_dpi_voltage_scaling_st max_dc_limits_entry = entry;
+
+ max_dc_limits_entry.dcfclk_mhz = max_clk_data.dcfclk_mhz;
+ max_dc_limits_entry.fabricclk_mhz = max_clk_data.fclk_mhz;
+ max_dc_limits_entry.dram_speed_mts = max_clk_data.memclk_mhz * 16;
+
+ max_dc_limits_entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&max_dc_limits_entry);
+ dcn321_insert_entry_into_table_sorted(table, num_entries, &max_dc_limits_entry);
+
+ sort_entries_with_same_bw(table, num_entries);
+ remove_inconsistent_entries(table, num_entries);
+ }
+
+
+
// At this point, the table only contains supported points of interest
// it could be used as is, but some states may be redundant due to
// coarse grained nature of some clocks, so we want to round up to
@@ -471,80 +610,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 +692,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/dcn321/dcn321_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.h
index e8fad9b4be69..c6623b3705ca 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.h
@@ -29,10 +29,6 @@
#include "dml/display_mode_vba.h"
-void dcn321_insert_entry_into_table_sorted(struct _vcs_dpi_voltage_scaling_st *table,
- unsigned int *num_entries,
- struct _vcs_dpi_voltage_scaling_st *entry);
-
void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params);
#endif
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..fb17f8868cb4 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
@@ -167,6 +167,7 @@ struct _vcs_dpi_voltage_scaling_st {
double phyclk_mhz;
double dppclk_mhz;
double dtbclk_mhz;
+ float net_bw_in_kbytes_sec;
};
/**
@@ -619,8 +620,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..ecb7bcc39469 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
@@ -230,9 +230,11 @@ struct clk_bw_params {
unsigned int dram_channel_width_bytes;
unsigned int dispclk_vco_khz;
unsigned int dc_mode_softmax_memclk;
+ unsigned int max_memclk_mhz;
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..4ca4192c1e12 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
@@ -160,6 +160,8 @@ struct hwseq_private_funcs {
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_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
index ba95facc4ee8..ef8739df91bc 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
@@ -82,8 +82,15 @@ bool dp_parse_link_loss_status(
}
/* Check interlane align.*/
- if (sink_status_changed ||
- !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
+ if (link_dp_get_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING &&
+ (!hpd_irq_dpcd_data->bytes.lane_status_updated.bits.EQ_INTERLANE_ALIGN_DONE_128b_132b ||
+ !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.CDS_INTERLANE_ALIGN_DONE_128b_132b)) {
+ sink_status_changed = true;
+ } else if (!hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
+ sink_status_changed = true;
+ }
+
+ if (sink_status_changed) {
DC_LOG_HW_HPD_IRQ("%s: Link Status changed.\n", __func__);
@@ -201,6 +208,25 @@ void dp_handle_link_loss(struct dc_link *link)
}
}
+static void read_dpcd204h_on_irq_hpd(struct dc_link *link, union hpd_irq_data *irq_data)
+{
+ enum dc_status retval;
+ union lane_align_status_updated dpcd_lane_status_updated;
+
+ retval = core_link_read_dpcd(
+ link,
+ DP_LANE_ALIGN_STATUS_UPDATED,
+ &dpcd_lane_status_updated.raw,
+ sizeof(union lane_align_status_updated));
+
+ if (retval == DC_OK) {
+ irq_data->bytes.lane_status_updated.bits.EQ_INTERLANE_ALIGN_DONE_128b_132b =
+ dpcd_lane_status_updated.bits.EQ_INTERLANE_ALIGN_DONE_128b_132b;
+ irq_data->bytes.lane_status_updated.bits.CDS_INTERLANE_ALIGN_DONE_128b_132b =
+ dpcd_lane_status_updated.bits.CDS_INTERLANE_ALIGN_DONE_128b_132b;
+ }
+}
+
enum dc_status dp_read_hpd_rx_irq_data(
struct dc_link *link,
union hpd_irq_data *irq_data)
@@ -242,6 +268,13 @@ enum dc_status dp_read_hpd_rx_irq_data(
irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI - DP_SINK_COUNT_ESI];
irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI - DP_SINK_COUNT_ESI];
irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI];
+
+ /*
+ * This display doesn't have correct values in DPCD200Eh.
+ * Read and check DPCD204h instead.
+ */
+ if (link->wa_flags.read_dpcd204h_on_irq_hpd)
+ read_dpcd204h_on_irq_hpd(link, irq_data);
}
return retval;
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..4585e0419da6 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);
@@ -364,9 +367,10 @@ struct dmub_srv_hw_funcs {
bool (*is_supported)(struct dmub_srv *dmub);
+ bool (*is_psrsu_supported)(struct dmub_srv *dmub);
+
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);
@@ -490,7 +494,7 @@ struct dmub_notification {
* of a firmware to know if feature or functionality is supported or present.
*/
#define DMUB_FW_VERSION(major, minor, revision) \
- ((((major) & 0xFF) << 24) | (((minor) & 0xFF) << 16) | ((revision) & 0xFFFF))
+ ((((major) & 0xFF) << 24) | (((minor) & 0xFF) << 16) | (((revision) & 0xFF) << 8))
/**
* dmub_srv_create() - creates the DMUB service.
@@ -602,6 +606,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..5e952541e72d 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);
@@ -297,6 +302,11 @@ bool dmub_dcn31_is_supported(struct dmub_srv *dmub)
return supported;
}
+bool dmub_dcn31_is_psrsu_supported(struct dmub_srv *dmub)
+{
+ return dmub->fw_version >= DMUB_FW_VERSION(4, 0, 59);
+}
+
void dmub_dcn31_set_gpint(struct dmub_srv *dmub,
union dmub_gpint_data_register reg)
{
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..89c5a948b67d 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);
@@ -219,6 +221,8 @@ bool dmub_dcn31_is_hw_init(struct dmub_srv *dmub);
bool dmub_dcn31_is_supported(struct dmub_srv *dmub);
+bool dmub_dcn31_is_psrsu_supported(struct dmub_srv *dmub);
+
void dmub_dcn31_set_gpint(struct dmub_srv *dmub,
union dmub_gpint_data_register reg);
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..f161aeb7e7c4
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c
@@ -0,0 +1,67 @@
+/*
+ * 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
+};
+
+bool dmub_dcn314_is_psrsu_supported(struct dmub_srv *dmub)
+{
+ return dmub->fw_version >= DMUB_FW_VERSION(8, 0, 16);
+}
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..f213bd82c911
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+bool dmub_dcn314_is_psrsu_supported(struct dmub_srv *dmub);
+
+#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..bdaf43892f47 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,17 +226,23 @@ 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;
+ funcs->is_psrsu_supported = dmub_dcn314_is_psrsu_supported;
+ } else if (asic == DMUB_ASIC_DCN315) {
dmub->regs_dcn31 = &dmub_srv_dcn315_regs;
- else if (asic == DMUB_ASIC_DCN316)
+ } else if (asic == DMUB_ASIC_DCN316) {
dmub->regs_dcn31 = &dmub_srv_dcn316_regs;
- else
+ } else {
dmub->regs_dcn31 = &dmub_srv_dcn31_regs;
+ funcs->is_psrsu_supported = dmub_dcn31_is_psrsu_supported;
+ }
funcs->reset = dmub_dcn31_reset;
funcs->reset_release = dmub_dcn31_reset_release;
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 +281,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 +651,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 +742,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..9ef88a0b1b57 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -35,44 +35,6 @@
#include <linux/pm_runtime.h>
#include <asm/processor.h>
-static const struct cg_flag_name clocks[] = {
- {AMD_CG_SUPPORT_GFX_FGCG, "Graphics Fine Grain Clock Gating"},
- {AMD_CG_SUPPORT_GFX_MGCG, "Graphics Medium Grain Clock Gating"},
- {AMD_CG_SUPPORT_GFX_MGLS, "Graphics Medium Grain memory Light Sleep"},
- {AMD_CG_SUPPORT_GFX_CGCG, "Graphics Coarse Grain Clock Gating"},
- {AMD_CG_SUPPORT_GFX_CGLS, "Graphics Coarse Grain memory Light Sleep"},
- {AMD_CG_SUPPORT_GFX_CGTS, "Graphics Coarse Grain Tree Shader Clock Gating"},
- {AMD_CG_SUPPORT_GFX_CGTS_LS, "Graphics Coarse Grain Tree Shader Light Sleep"},
- {AMD_CG_SUPPORT_GFX_CP_LS, "Graphics Command Processor Light Sleep"},
- {AMD_CG_SUPPORT_GFX_RLC_LS, "Graphics Run List Controller Light Sleep"},
- {AMD_CG_SUPPORT_GFX_3D_CGCG, "Graphics 3D Coarse Grain Clock Gating"},
- {AMD_CG_SUPPORT_GFX_3D_CGLS, "Graphics 3D Coarse Grain memory Light Sleep"},
- {AMD_CG_SUPPORT_MC_LS, "Memory Controller Light Sleep"},
- {AMD_CG_SUPPORT_MC_MGCG, "Memory Controller Medium Grain Clock Gating"},
- {AMD_CG_SUPPORT_SDMA_LS, "System Direct Memory Access Light Sleep"},
- {AMD_CG_SUPPORT_SDMA_MGCG, "System Direct Memory Access Medium Grain Clock Gating"},
- {AMD_CG_SUPPORT_BIF_MGCG, "Bus Interface Medium Grain Clock Gating"},
- {AMD_CG_SUPPORT_BIF_LS, "Bus Interface Light Sleep"},
- {AMD_CG_SUPPORT_UVD_MGCG, "Unified Video Decoder Medium Grain Clock Gating"},
- {AMD_CG_SUPPORT_VCE_MGCG, "Video Compression Engine Medium Grain Clock Gating"},
- {AMD_CG_SUPPORT_HDP_LS, "Host Data Path Light Sleep"},
- {AMD_CG_SUPPORT_HDP_MGCG, "Host Data Path Medium Grain Clock Gating"},
- {AMD_CG_SUPPORT_DRM_MGCG, "Digital Right Management Medium Grain Clock Gating"},
- {AMD_CG_SUPPORT_DRM_LS, "Digital Right Management Light Sleep"},
- {AMD_CG_SUPPORT_ROM_MGCG, "Rom Medium Grain Clock Gating"},
- {AMD_CG_SUPPORT_DF_MGCG, "Data Fabric Medium Grain Clock Gating"},
- {AMD_CG_SUPPORT_VCN_MGCG, "VCN Medium Grain Clock Gating"},
- {AMD_CG_SUPPORT_HDP_DS, "Host Data Path Deep Sleep"},
- {AMD_CG_SUPPORT_HDP_SD, "Host Data Path Shutdown"},
- {AMD_CG_SUPPORT_IH_CG, "Interrupt Handler Clock Gating"},
- {AMD_CG_SUPPORT_JPEG_MGCG, "JPEG Medium Grain Clock Gating"},
- {AMD_CG_SUPPORT_REPEATER_FGCG, "Repeater Fine Grain Clock Gating"},
- {AMD_CG_SUPPORT_GFX_PERF_CLK, "Perfmon Clock Gating"},
- {AMD_CG_SUPPORT_ATHUB_MGCG, "Address Translation Hub Medium Grain Clock Gating"},
- {AMD_CG_SUPPORT_ATHUB_LS, "Address Translation Hub Light Sleep"},
- {0, NULL},
-};
-
static const struct hwmon_temp_label {
enum PP_HWMON_TEMP channel;
const char *label;
@@ -678,7 +640,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 +686,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".
@@ -2098,6 +2072,7 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_
case IP_VERSION(9, 4, 0):
case IP_VERSION(9, 4, 1):
case IP_VERSION(9, 4, 2):
+ case IP_VERSION(9, 4, 3):
case IP_VERSION(10, 3, 0):
case IP_VERSION(11, 0, 0):
case IP_VERSION(11, 0, 1):
@@ -2108,7 +2083,9 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_
*states = ATTR_STATE_UNSUPPORTED;
}
} else if (DEVICE_ATTR_IS(pp_features)) {
- if (adev->flags & AMD_IS_APU || gc_ver < IP_VERSION(9, 0, 0))
+ if ((adev->flags & AMD_IS_APU &&
+ gc_ver != IP_VERSION(9, 4, 3)) ||
+ gc_ver < IP_VERSION(9, 0, 0))
*states = ATTR_STATE_UNSUPPORTED;
} else if (DEVICE_ATTR_IS(gpu_metrics)) {
if (gc_ver < IP_VERSION(9, 1, 0))
@@ -3360,7 +3337,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 +3371,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 +3403,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 */
@@ -3658,6 +3649,44 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a
return 0;
}
+static const struct cg_flag_name clocks[] = {
+ {AMD_CG_SUPPORT_GFX_FGCG, "Graphics Fine Grain Clock Gating"},
+ {AMD_CG_SUPPORT_GFX_MGCG, "Graphics Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_GFX_MGLS, "Graphics Medium Grain memory Light Sleep"},
+ {AMD_CG_SUPPORT_GFX_CGCG, "Graphics Coarse Grain Clock Gating"},
+ {AMD_CG_SUPPORT_GFX_CGLS, "Graphics Coarse Grain memory Light Sleep"},
+ {AMD_CG_SUPPORT_GFX_CGTS, "Graphics Coarse Grain Tree Shader Clock Gating"},
+ {AMD_CG_SUPPORT_GFX_CGTS_LS, "Graphics Coarse Grain Tree Shader Light Sleep"},
+ {AMD_CG_SUPPORT_GFX_CP_LS, "Graphics Command Processor Light Sleep"},
+ {AMD_CG_SUPPORT_GFX_RLC_LS, "Graphics Run List Controller Light Sleep"},
+ {AMD_CG_SUPPORT_GFX_3D_CGCG, "Graphics 3D Coarse Grain Clock Gating"},
+ {AMD_CG_SUPPORT_GFX_3D_CGLS, "Graphics 3D Coarse Grain memory Light Sleep"},
+ {AMD_CG_SUPPORT_MC_LS, "Memory Controller Light Sleep"},
+ {AMD_CG_SUPPORT_MC_MGCG, "Memory Controller Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_SDMA_LS, "System Direct Memory Access Light Sleep"},
+ {AMD_CG_SUPPORT_SDMA_MGCG, "System Direct Memory Access Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_BIF_MGCG, "Bus Interface Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_BIF_LS, "Bus Interface Light Sleep"},
+ {AMD_CG_SUPPORT_UVD_MGCG, "Unified Video Decoder Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_VCE_MGCG, "Video Compression Engine Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_HDP_LS, "Host Data Path Light Sleep"},
+ {AMD_CG_SUPPORT_HDP_MGCG, "Host Data Path Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_DRM_MGCG, "Digital Right Management Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_DRM_LS, "Digital Right Management Light Sleep"},
+ {AMD_CG_SUPPORT_ROM_MGCG, "Rom Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_DF_MGCG, "Data Fabric Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_VCN_MGCG, "VCN Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_HDP_DS, "Host Data Path Deep Sleep"},
+ {AMD_CG_SUPPORT_HDP_SD, "Host Data Path Shutdown"},
+ {AMD_CG_SUPPORT_IH_CG, "Interrupt Handler Clock Gating"},
+ {AMD_CG_SUPPORT_JPEG_MGCG, "JPEG Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_REPEATER_FGCG, "Repeater Fine Grain Clock Gating"},
+ {AMD_CG_SUPPORT_GFX_PERF_CLK, "Perfmon Clock Gating"},
+ {AMD_CG_SUPPORT_ATHUB_MGCG, "Address Translation Hub Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_ATHUB_LS, "Address Translation Hub Light Sleep"},
+ {0, NULL},
+};
+
static void amdgpu_parse_cg_state(struct seq_file *m, u64 flags)
{
int i;
diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
index d178f3f44081..42172b00be66 100644
--- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
+++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
@@ -89,6 +89,8 @@ struct amdgpu_dpm_thermal {
int max_mem_crit_temp;
/* memory max emergency(shutdown) temp */
int max_mem_emergency_temp;
+ /* SWCTF threshold */
+ int sw_ctf_threshold;
/* was last interrupt low to high or high to low */
bool high_to_low;
/* interrupt source */
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/legacy-dpm/legacy_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c
index d3fe149d8476..81fb4e5dd804 100644
--- a/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c
+++ b/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c
@@ -794,7 +794,7 @@ void amdgpu_add_thermal_controller(struct amdgpu_device *adev)
struct i2c_board_info info = { };
const char *name = pp_lib_thermal_controller_names[controller->ucType];
info.addr = controller->ucI2cAddress >> 1;
- strlcpy(info.type, name, sizeof(info.type));
+ strscpy(info.type, name, sizeof(info.type));
i2c_new_client_device(&adev->pm.i2c_bus->adapter, &info);
}
} else {
diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
index 11b7b4cffaae..ff360c699171 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
@@ -26,6 +26,7 @@
#include <linux/gfp.h>
#include <linux/slab.h>
#include <linux/firmware.h>
+#include <linux/reboot.h>
#include "amd_shared.h"
#include "amd_powerplay.h"
#include "power_state.h"
@@ -91,6 +92,45 @@ static int pp_early_init(void *handle)
return 0;
}
+static void pp_swctf_delayed_work_handler(struct work_struct *work)
+{
+ struct pp_hwmgr *hwmgr =
+ container_of(work, struct pp_hwmgr, swctf_delayed_work.work);
+ struct amdgpu_device *adev = hwmgr->adev;
+ struct amdgpu_dpm_thermal *range =
+ &adev->pm.dpm.thermal;
+ uint32_t gpu_temperature, size;
+ int ret;
+
+ /*
+ * If the hotspot/edge temperature is confirmed as below SW CTF setting point
+ * after the delay enforced, nothing will be done.
+ * Otherwise, a graceful shutdown will be performed to prevent further damage.
+ */
+ if (range->sw_ctf_threshold &&
+ hwmgr->hwmgr_func->read_sensor) {
+ ret = hwmgr->hwmgr_func->read_sensor(hwmgr,
+ AMDGPU_PP_SENSOR_HOTSPOT_TEMP,
+ &gpu_temperature,
+ &size);
+ /*
+ * For some legacy ASICs, hotspot temperature retrieving might be not
+ * supported. Check the edge temperature instead then.
+ */
+ if (ret == -EOPNOTSUPP)
+ ret = hwmgr->hwmgr_func->read_sensor(hwmgr,
+ AMDGPU_PP_SENSOR_EDGE_TEMP,
+ &gpu_temperature,
+ &size);
+ if (!ret && gpu_temperature / 1000 < range->sw_ctf_threshold)
+ return;
+ }
+
+ dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");
+ dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");
+ orderly_poweroff(true);
+}
+
static int pp_sw_init(void *handle)
{
struct amdgpu_device *adev = handle;
@@ -101,6 +141,10 @@ static int pp_sw_init(void *handle)
pr_debug("powerplay sw init %s\n", ret ? "failed" : "successfully");
+ if (!ret)
+ INIT_DELAYED_WORK(&hwmgr->swctf_delayed_work,
+ pp_swctf_delayed_work_handler);
+
return ret;
}
@@ -135,6 +179,8 @@ static int pp_hw_fini(void *handle)
struct amdgpu_device *adev = handle;
struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
+ cancel_delayed_work_sync(&hwmgr->swctf_delayed_work);
+
hwmgr_hw_fini(hwmgr);
return 0;
@@ -221,6 +267,8 @@ static int pp_suspend(void *handle)
struct amdgpu_device *adev = handle;
struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
+ cancel_delayed_work_sync(&hwmgr->swctf_delayed_work);
+
return hwmgr_suspend(hwmgr);
}
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c
index 981dc8c7112d..90452b66e107 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c
@@ -241,7 +241,8 @@ int phm_start_thermal_controller(struct pp_hwmgr *hwmgr)
TEMP_RANGE_MAX,
TEMP_RANGE_MIN,
TEMP_RANGE_MAX,
- TEMP_RANGE_MAX};
+ TEMP_RANGE_MAX,
+ 0};
struct amdgpu_device *adev = hwmgr->adev;
if (!hwmgr->not_vf)
@@ -265,6 +266,7 @@ int phm_start_thermal_controller(struct pp_hwmgr *hwmgr)
adev->pm.dpm.thermal.min_mem_temp = range.mem_min;
adev->pm.dpm.thermal.max_mem_crit_temp = range.mem_crit_max;
adev->pm.dpm.thermal.max_mem_emergency_temp = range.mem_emergency_max;
+ adev->pm.dpm.thermal.sw_ctf_threshold = range.sw_ctf_threshold;
return ret;
}
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
index e10cc5e7928e..1cb402264497 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
@@ -1798,17 +1798,6 @@ static int smu7_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
return result;
}
-static bool intel_core_rkl_chk(void)
-{
-#if IS_ENABLED(CONFIG_X86_64)
- struct cpuinfo_x86 *c = &cpu_data(0);
-
- return (c->x86 == 6 && c->x86_model == INTEL_FAM6_ROCKETLAKE);
-#else
- return false;
-#endif
-}
-
static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
@@ -1835,7 +1824,8 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
data->mclk_dpm_key_disabled = hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true;
data->sclk_dpm_key_disabled = hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true;
data->pcie_dpm_key_disabled =
- intel_core_rkl_chk() || !(hwmgr->feature_mask & PP_PCIE_DPM_MASK);
+ !amdgpu_device_pcie_dynamic_switching_supported() ||
+ !(hwmgr->feature_mask & PP_PCIE_DPM_MASK);
/* need to set voltage control types before EVV patching */
data->voltage_control = SMU7_VOLTAGE_CONTROL_NONE;
data->vddci_control = SMU7_VOLTAGE_CONTROL_NONE;
@@ -5432,6 +5422,8 @@ static int smu7_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
thermal_data->max = data->thermal_temp_setting.temperature_shutdown *
PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ thermal_data->sw_ctf_threshold = thermal_data->max;
+
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/smu_helper.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c
index bfe80ac0ad8c..d0b1ab6c4523 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c
@@ -603,21 +603,17 @@ int phm_irq_process(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry)
{
+ struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
uint32_t client_id = entry->client_id;
uint32_t src_id = entry->src_id;
if (client_id == AMDGPU_IRQ_CLIENTID_LEGACY) {
if (src_id == VISLANDS30_IV_SRCID_CG_TSS_THERMAL_LOW_TO_HIGH) {
- dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");
- /*
- * SW CTF just occurred.
- * Try to do a graceful shutdown to prevent further damage.
- */
- dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");
- orderly_poweroff(true);
- } else if (src_id == VISLANDS30_IV_SRCID_CG_TSS_THERMAL_HIGH_TO_LOW)
+ schedule_delayed_work(&hwmgr->swctf_delayed_work,
+ msecs_to_jiffies(AMDGPU_SWCTF_EXTRA_DELAY));
+ } else if (src_id == VISLANDS30_IV_SRCID_CG_TSS_THERMAL_HIGH_TO_LOW) {
dev_emerg(adev->dev, "ERROR: GPU under temperature range detected!\n");
- else if (src_id == VISLANDS30_IV_SRCID_GPIO_19) {
+ } else if (src_id == VISLANDS30_IV_SRCID_GPIO_19) {
dev_emerg(adev->dev, "ERROR: GPU HW Critical Temperature Fault(aka CTF) detected!\n");
/*
* HW CTF just occurred. Shutdown to prevent further damage.
@@ -626,15 +622,10 @@ int phm_irq_process(struct amdgpu_device *adev,
orderly_poweroff(true);
}
} else if (client_id == SOC15_IH_CLIENTID_THM) {
- if (src_id == 0) {
- dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");
- /*
- * SW CTF just occurred.
- * Try to do a graceful shutdown to prevent further damage.
- */
- dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");
- orderly_poweroff(true);
- } else
+ if (src_id == 0)
+ schedule_delayed_work(&hwmgr->swctf_delayed_work,
+ msecs_to_jiffies(AMDGPU_SWCTF_EXTRA_DELAY));
+ else
dev_emerg(adev->dev, "ERROR: GPU under temperature range detected!\n");
} else if (client_id == SOC15_IH_CLIENTID_ROM_SMUIO) {
dev_emerg(adev->dev, "ERROR: GPU HW Critical Temperature Fault(aka CTF) detected!\n");
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
index 99cd2e63afdd..c51dd4c74fe9 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
@@ -5241,6 +5241,9 @@ static int vega10_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
{
struct vega10_hwmgr *data = hwmgr->backend;
PPTable_t *pp_table = &(data->smc_state_table.pp_table);
+ struct phm_ppt_v2_information *pp_table_info =
+ (struct phm_ppt_v2_information *)(hwmgr->pptable);
+ struct phm_tdp_table *tdp_table = pp_table_info->tdp_table;
memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange));
@@ -5257,6 +5260,13 @@ static int vega10_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)*
PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ if (tdp_table->usSoftwareShutdownTemp > pp_table->ThotspotLimit &&
+ tdp_table->usSoftwareShutdownTemp < VEGA10_THERMAL_MAXIMUM_ALERT_TEMP)
+ thermal_data->sw_ctf_threshold = tdp_table->usSoftwareShutdownTemp;
+ else
+ thermal_data->sw_ctf_threshold = VEGA10_THERMAL_MAXIMUM_ALERT_TEMP;
+ thermal_data->sw_ctf_threshold *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
return 0;
}
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/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
index e9db137cd1c6..1937be1cf5b4 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
@@ -2763,6 +2763,8 @@ static int vega12_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
static int vega12_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
struct PP_TemperatureRange *thermal_data)
{
+ struct phm_ppt_v3_information *pptable_information =
+ (struct phm_ppt_v3_information *)hwmgr->pptable;
struct vega12_hwmgr *data =
(struct vega12_hwmgr *)(hwmgr->backend);
PPTable_t *pp_table = &(data->smc_state_table.pp_table);
@@ -2781,6 +2783,8 @@ static int vega12_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)*
PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ thermal_data->sw_ctf_threshold = pptable_information->us_software_shutdown_temp *
+ PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
return 0;
}
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c
index ed3dff0b52d2..ae342c58cd3e 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c
@@ -192,7 +192,9 @@ static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high);
val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low);
- val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
+ val &= ~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK;
+ val &= ~THM_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
+ val &= ~THM_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
index 0d4d4811527c..4e19ccbdb807 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
@@ -4206,6 +4206,8 @@ static int vega20_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
static int vega20_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
struct PP_TemperatureRange *thermal_data)
{
+ struct phm_ppt_v3_information *pptable_information =
+ (struct phm_ppt_v3_information *)hwmgr->pptable;
struct vega20_hwmgr *data =
(struct vega20_hwmgr *)(hwmgr->backend);
PPTable_t *pp_table = &(data->smc_state_table.pp_table);
@@ -4224,6 +4226,8 @@ static int vega20_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)*
PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ thermal_data->sw_ctf_threshold = pptable_information->us_software_shutdown_temp *
+ PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
return 0;
}
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c
index f4f4efdbda79..e9737ca8418a 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c
@@ -263,7 +263,9 @@ static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high);
val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low);
- val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
+ val &= ~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK;
+ val &= ~THM_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
+ val &= ~THM_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
index 5ce433e2c16a..612d66aeaab9 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,
@@ -811,6 +811,8 @@ struct pp_hwmgr {
bool gfxoff_state_changed_by_workload;
uint32_t pstate_sclk_peak;
uint32_t pstate_mclk_peak;
+
+ struct delayed_work swctf_delayed_work;
};
int hwmgr_early_init(struct pp_hwmgr *hwmgr);
diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/power_state.h b/drivers/gpu/drm/amd/pm/powerplay/inc/power_state.h
index a5f2227a3971..0ffc2347829d 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/inc/power_state.h
+++ b/drivers/gpu/drm/amd/pm/powerplay/inc/power_state.h
@@ -131,6 +131,7 @@ struct PP_TemperatureRange {
int mem_min;
int mem_crit_max;
int mem_emergency_max;
+ int sw_ctf_threshold;
};
struct PP_StateValidationBlock {
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 2ddf5198e5c4..222af2fae745 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -24,6 +24,7 @@
#include <linux/firmware.h>
#include <linux/pci.h>
+#include <linux/reboot.h>
#include "amdgpu.h"
#include "amdgpu_smu.h"
@@ -822,11 +823,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 +846,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,
@@ -1070,6 +1079,34 @@ static void smu_interrupt_work_fn(struct work_struct *work)
smu->ppt_funcs->interrupt_work(smu);
}
+static void smu_swctf_delayed_work_handler(struct work_struct *work)
+{
+ struct smu_context *smu =
+ container_of(work, struct smu_context, swctf_delayed_work.work);
+ struct smu_temperature_range *range =
+ &smu->thermal_range;
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t hotspot_tmp, size;
+
+ /*
+ * If the hotspot temperature is confirmed as below SW CTF setting point
+ * after the delay enforced, nothing will be done.
+ * Otherwise, a graceful shutdown will be performed to prevent further damage.
+ */
+ if (range->software_shutdown_temp &&
+ smu->ppt_funcs->read_sensor &&
+ !smu->ppt_funcs->read_sensor(smu,
+ AMDGPU_PP_SENSOR_HOTSPOT_TEMP,
+ &hotspot_tmp,
+ &size) &&
+ hotspot_tmp / 1000 < range->software_shutdown_temp)
+ return;
+
+ dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");
+ dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");
+ orderly_poweroff(true);
+}
+
static int smu_sw_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -1112,6 +1149,9 @@ static int smu_sw_init(void *handle)
smu->smu_dpm.dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
smu->smu_dpm.requested_dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
+ INIT_DELAYED_WORK(&smu->swctf_delayed_work,
+ smu_swctf_delayed_work_handler);
+
ret = smu_smc_table_sw_init(smu);
if (ret) {
dev_err(adev->dev, "Failed to sw init smc table!\n");
@@ -1541,9 +1581,9 @@ static int smu_disable_dpms(struct smu_context *smu)
/*
* For SMU 13.0.4/11, PMFW will handle the features disablement properly
- * for gpu reset case. Driver involvement is unnecessary.
+ * for gpu reset and S0i3 cases. Driver involvement is unnecessary.
*/
- if (amdgpu_in_reset(adev)) {
+ if (amdgpu_in_reset(adev) || adev->in_s0ix) {
switch (adev->ip_versions[MP1_HWIP][0]) {
case IP_VERSION(13, 0, 4):
case IP_VERSION(13, 0, 11):
@@ -1592,6 +1632,8 @@ static int smu_smc_hw_cleanup(struct smu_context *smu)
return ret;
}
+ cancel_delayed_work_sync(&smu->swctf_delayed_work);
+
ret = smu_disable_dpms(smu);
if (ret) {
dev_err(adev->dev, "Fail to disable dpm features!\n");
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
index 09469c750a96..6e2069dcb6b9 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@ -573,6 +573,8 @@ struct smu_context
u32 debug_param_reg;
u32 debug_msg_reg;
u32 debug_resp_reg;
+
+ struct delayed_work swctf_delayed_work;
};
struct i2c_adapter;
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..355c156d871a 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)
@@ -303,5 +295,9 @@ int smu_v13_0_get_pptable_from_firmware(struct smu_context *smu,
uint32_t *size,
uint32_t pptable_id);
+int smu_v13_0_update_pcie_parameters(struct smu_context *smu,
+ uint32_t pcie_gen_cap,
+ uint32_t pcie_width_cap);
+
#endif
#endif
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/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 9cd005131f56..3bb18396d2f9 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -2113,7 +2113,6 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
}
mutex_lock(&adev->pm.mutex);
r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
- mutex_unlock(&adev->pm.mutex);
if (r)
goto fail;
@@ -2130,6 +2129,7 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
}
r = num_msgs;
fail:
+ mutex_unlock(&adev->pm.mutex);
kfree(req);
return r;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index 275f708db636..95f6d821bacb 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -1654,7 +1654,7 @@ static int navi10_force_clk_levels(struct smu_context *smu,
enum smu_clk_type clk_type, uint32_t mask)
{
- int ret = 0, size = 0;
+ int ret = 0;
uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0;
soft_min_level = mask ? (ffs(mask) - 1) : 0;
@@ -1675,15 +1675,15 @@ static int navi10_force_clk_levels(struct smu_context *smu,
ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq);
if (ret)
- return size;
+ return 0;
ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq);
if (ret)
- return size;
+ return 0;
ret = smu_v11_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq);
if (ret)
- return size;
+ return 0;
break;
case SMU_DCEFCLK:
dev_info(smu->adev->dev,"Setting DCEFCLK min/max dpm level is not supported!\n");
@@ -1693,7 +1693,7 @@ static int navi10_force_clk_levels(struct smu_context *smu,
break;
}
- return size;
+ return 0;
}
static int navi10_populate_umd_state_clk(struct smu_context *smu)
@@ -3021,7 +3021,6 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap,
}
mutex_lock(&adev->pm.mutex);
r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
- mutex_unlock(&adev->pm.mutex);
if (r)
goto fail;
@@ -3038,6 +3037,7 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap,
}
r = num_msgs;
fail:
+ mutex_unlock(&adev->pm.mutex);
kfree(req);
return r;
}
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..f0800c0c5168 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;
}
@@ -578,7 +588,9 @@ err0_out:
return -ENOMEM;
}
-static uint32_t sienna_cichlid_get_throttler_status_locked(struct smu_context *smu)
+static uint32_t sienna_cichlid_get_throttler_status_locked(struct smu_context *smu,
+ bool use_metrics_v3,
+ bool use_metrics_v2)
{
struct smu_table_context *smu_table= &smu->smu_table;
SmuMetricsExternal_t *metrics_ext =
@@ -586,13 +598,11 @@ static uint32_t sienna_cichlid_get_throttler_status_locked(struct smu_context *s
uint32_t throttler_status = 0;
int i;
- if ((smu->adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 7)) &&
- (smu->smc_fw_version >= 0x3A4900)) {
+ if (use_metrics_v3) {
for (i = 0; i < THROTTLER_COUNT; i++)
throttler_status |=
(metrics_ext->SmuMetrics_V3.ThrottlingPercentage[i] ? 1U << i : 0);
- } else if ((smu->adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 7)) &&
- (smu->smc_fw_version >= 0x3A4300)) {
+ } else if (use_metrics_v2) {
for (i = 0; i < THROTTLER_COUNT; i++)
throttler_status |=
(metrics_ext->SmuMetrics_V2.ThrottlingPercentage[i] ? 1U << i : 0);
@@ -854,7 +864,7 @@ static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu,
metrics->TemperatureVrSoc) * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
break;
case METRICS_THROTTLER_STATUS:
- *value = sienna_cichlid_get_throttler_status_locked(smu);
+ *value = sienna_cichlid_get_throttler_status_locked(smu, use_metrics_v3, use_metrics_v2);
break;
case METRICS_CURR_FANSPEED:
*value = use_metrics_v3 ? metrics_v3->CurrFanSpeed :
@@ -1917,12 +1927,16 @@ static int sienna_cichlid_read_sensor(struct smu_context *smu,
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_MCLK:
- ret = sienna_cichlid_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data);
+ ret = sienna_cichlid_get_smu_metrics_data(smu,
+ METRICS_CURR_UCLK,
+ (uint32_t *)data);
*(uint32_t *)data *= 100;
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_SCLK:
- ret = sienna_cichlid_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data);
+ ret = sienna_cichlid_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXCLK,
+ (uint32_t *)data);
*(uint32_t *)data *= 100;
*size = 4;
break;
@@ -2067,89 +2081,36 @@ static int sienna_cichlid_display_disable_memory_clock_switch(struct smu_context
return ret;
}
-static void sienna_cichlid_get_override_pcie_settings(struct smu_context *smu,
- uint32_t *gen_speed_override,
- uint32_t *lane_width_override)
-{
- struct amdgpu_device *adev = smu->adev;
-
- *gen_speed_override = 0xff;
- *lane_width_override = 0xff;
-
- switch (adev->pdev->device) {
- case 0x73A0:
- case 0x73A1:
- case 0x73A2:
- case 0x73A3:
- case 0x73AB:
- case 0x73AE:
- /* Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32 */
- *lane_width_override = 6;
- break;
- case 0x73E0:
- case 0x73E1:
- case 0x73E3:
- *lane_width_override = 4;
- break;
- case 0x7420:
- case 0x7421:
- case 0x7422:
- case 0x7423:
- case 0x7424:
- *lane_width_override = 3;
- break;
- default:
- break;
- }
-}
-
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-
static int sienna_cichlid_update_pcie_parameters(struct smu_context *smu,
uint32_t pcie_gen_cap,
uint32_t pcie_width_cap)
{
struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
struct smu_11_0_pcie_table *pcie_table = &dpm_context->dpm_tables.pcie_table;
- uint32_t gen_speed_override, lane_width_override;
- uint8_t *table_member1, *table_member2;
- uint32_t min_gen_speed, max_gen_speed;
- uint32_t min_lane_width, max_lane_width;
- uint32_t smu_pcie_arg;
+ u32 smu_pcie_arg;
int ret, i;
- GET_PPTABLE_MEMBER(PcieGenSpeed, &table_member1);
- GET_PPTABLE_MEMBER(PcieLaneCount, &table_member2);
+ /* PCIE gen speed and lane width override */
+ if (!amdgpu_device_pcie_dynamic_switching_supported()) {
+ if (pcie_table->pcie_gen[NUM_LINK_LEVELS - 1] < pcie_gen_cap)
+ pcie_gen_cap = pcie_table->pcie_gen[NUM_LINK_LEVELS - 1];
- sienna_cichlid_get_override_pcie_settings(smu,
- &gen_speed_override,
- &lane_width_override);
+ if (pcie_table->pcie_lane[NUM_LINK_LEVELS - 1] < pcie_width_cap)
+ pcie_width_cap = pcie_table->pcie_lane[NUM_LINK_LEVELS - 1];
- /* PCIE gen speed override */
- if (gen_speed_override != 0xff) {
- min_gen_speed = MIN(pcie_gen_cap, gen_speed_override);
- max_gen_speed = MIN(pcie_gen_cap, gen_speed_override);
- } else {
- min_gen_speed = MAX(0, table_member1[0]);
- max_gen_speed = MIN(pcie_gen_cap, table_member1[1]);
- min_gen_speed = min_gen_speed > max_gen_speed ?
- max_gen_speed : min_gen_speed;
- }
- pcie_table->pcie_gen[0] = min_gen_speed;
- pcie_table->pcie_gen[1] = max_gen_speed;
-
- /* PCIE lane width override */
- if (lane_width_override != 0xff) {
- min_lane_width = MIN(pcie_width_cap, lane_width_override);
- max_lane_width = MIN(pcie_width_cap, lane_width_override);
+ /* Force all levels to use the same settings */
+ for (i = 0; i < NUM_LINK_LEVELS; i++) {
+ pcie_table->pcie_gen[i] = pcie_gen_cap;
+ pcie_table->pcie_lane[i] = pcie_width_cap;
+ }
} else {
- min_lane_width = MAX(1, table_member2[0]);
- max_lane_width = MIN(pcie_width_cap, table_member2[1]);
- min_lane_width = min_lane_width > max_lane_width ?
- max_lane_width : min_lane_width;
+ for (i = 0; i < NUM_LINK_LEVELS; i++) {
+ if (pcie_table->pcie_gen[i] > pcie_gen_cap)
+ pcie_table->pcie_gen[i] = pcie_gen_cap;
+ if (pcie_table->pcie_lane[i] > pcie_width_cap)
+ pcie_table->pcie_lane[i] = pcie_width_cap;
+ }
}
- pcie_table->pcie_lane[0] = min_lane_width;
- pcie_table->pcie_lane[1] = max_lane_width;
for (i = 0; i < NUM_LINK_LEVELS; i++) {
smu_pcie_arg = (i << 16 |
@@ -3832,7 +3793,6 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap,
}
mutex_lock(&adev->pm.mutex);
r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
- mutex_unlock(&adev->pm.mutex);
if (r)
goto fail;
@@ -3849,6 +3809,7 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap,
}
r = num_msgs;
fail:
+ mutex_unlock(&adev->pm.mutex);
kfree(req);
return r;
}
@@ -4056,7 +4017,7 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu,
gpu_metrics->current_dclk1 = use_metrics_v3 ? metrics_v3->CurrClock[PPCLK_DCLK_1] :
use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_DCLK_1] : metrics->CurrClock[PPCLK_DCLK_1];
- gpu_metrics->throttle_status = sienna_cichlid_get_throttler_status_locked(smu);
+ gpu_metrics->throttle_status = sienna_cichlid_get_throttler_status_locked(smu, use_metrics_v3, use_metrics_v2);
gpu_metrics->indep_throttle_status =
smu_cmn_get_indep_throttler_status(gpu_metrics->throttle_status,
sienna_cichlid_throttler_map);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
index e1ef88ee1ed3..aa4a5498a12f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
@@ -1412,13 +1412,8 @@ static int smu_v11_0_irq_process(struct amdgpu_device *adev,
if (client_id == SOC15_IH_CLIENTID_THM) {
switch (src_id) {
case THM_11_0__SRCID__THM_DIG_THERM_L2H:
- dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");
- /*
- * SW CTF just occurred.
- * Try to do a graceful shutdown to prevent further damage.
- */
- dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");
- orderly_poweroff(true);
+ schedule_delayed_work(&smu->swctf_delayed_work,
+ msecs_to_jiffies(AMDGPU_SWCTF_EXTRA_DELAY));
break;
case THM_11_0__SRCID__THM_DIG_THERM_H2L:
dev_emerg(adev->dev, "ERROR: GPU under temperature range detected\n");
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..ce50ef46e73f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
@@ -1525,7 +1525,6 @@ static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap,
}
mutex_lock(&adev->pm.mutex);
r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
- mutex_unlock(&adev->pm.mutex);
if (r)
goto fail;
@@ -1542,6 +1541,7 @@ static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap,
}
r = num_msgs;
fail:
+ mutex_unlock(&adev->pm.mutex);
kfree(req);
return r;
}
@@ -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..9b62b45ebb7f 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;
@@ -1377,13 +1353,8 @@ static int smu_v13_0_irq_process(struct amdgpu_device *adev,
if (client_id == SOC15_IH_CLIENTID_THM) {
switch (src_id) {
case THM_11_0__SRCID__THM_DIG_THERM_L2H:
- dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");
- /*
- * SW CTF just occurred.
- * Try to do a graceful shutdown to prevent further damage.
- */
- dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");
- orderly_poweroff(true);
+ schedule_delayed_work(&smu->swctf_delayed_work,
+ msecs_to_jiffies(AMDGPU_SWCTF_EXTRA_DELAY));
break;
case THM_11_0__SRCID__THM_DIG_THERM_H2L:
dev_emerg(adev->dev, "ERROR: GPU under temperature range detected\n");
@@ -2453,3 +2424,51 @@ int smu_v13_0_mode1_reset(struct smu_context *smu)
return ret;
}
+
+int smu_v13_0_update_pcie_parameters(struct smu_context *smu,
+ uint32_t pcie_gen_cap,
+ uint32_t pcie_width_cap)
+{
+ struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
+ struct smu_13_0_pcie_table *pcie_table =
+ &dpm_context->dpm_tables.pcie_table;
+ int num_of_levels = pcie_table->num_of_link_levels;
+ uint32_t smu_pcie_arg;
+ int ret, i;
+
+ if (!amdgpu_device_pcie_dynamic_switching_supported()) {
+ if (pcie_table->pcie_gen[num_of_levels - 1] < pcie_gen_cap)
+ pcie_gen_cap = pcie_table->pcie_gen[num_of_levels - 1];
+
+ if (pcie_table->pcie_lane[num_of_levels - 1] < pcie_width_cap)
+ pcie_width_cap = pcie_table->pcie_lane[num_of_levels - 1];
+
+ /* Force all levels to use the same settings */
+ for (i = 0; i < num_of_levels; i++) {
+ pcie_table->pcie_gen[i] = pcie_gen_cap;
+ pcie_table->pcie_lane[i] = pcie_width_cap;
+ }
+ } else {
+ for (i = 0; i < num_of_levels; i++) {
+ if (pcie_table->pcie_gen[i] > pcie_gen_cap)
+ pcie_table->pcie_gen[i] = pcie_gen_cap;
+ if (pcie_table->pcie_lane[i] > pcie_width_cap)
+ pcie_table->pcie_lane[i] = pcie_width_cap;
+ }
+ }
+
+ for (i = 0; i < num_of_levels; i++) {
+ smu_pcie_arg = i << 16;
+ smu_pcie_arg |= pcie_table->pcie_gen[i] << 8;
+ smu_pcie_arg |= pcie_table->pcie_lane[i];
+
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_OverridePcieParameters,
+ smu_pcie_arg,
+ NULL);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
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..0fb6be11a0cc 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,14 @@ 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;
+#if 0
+ 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;
+#endif
if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_HARDWAREDC)
smu->dc_controlled_by_gpio = true;
@@ -342,14 +350,30 @@ 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;
- table_context->thermal_controller_type =
- powerplay_table->thermal_controller_type;
+ /*
+ * We are in the transition to a new OD mechanism.
+ * Disable the OD feature support for SMU13 temporarily.
+ * TODO: get this reverted when new OD mechanism online
+ */
+#if 0
+ if (!overdrive_lowerlimits->FeatureCtrlMask ||
+ !overdrive_upperlimits->FeatureCtrlMask)
+ smu->od_enabled = false;
/*
* Instead of having its own buffer space and get overdrive_table copied,
* smu->od_settings just points to the actual overdrive_table
*/
smu->od_settings = &powerplay_table->overdrive_table;
+#else
+ smu->od_enabled = false;
+#endif
+
+ table_context->thermal_controller_type =
+ powerplay_table->thermal_controller_type;
+
+ smu->adev->pm.no_fan =
+ !(pptable->SkuTable.FeaturesToRun[0] & (1 << FEATURE_FAN_CONTROL_BIT));
return 0;
}
@@ -461,7 +485,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 +1046,118 @@ 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);
@@ -1145,10 +1270,93 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu,
(pcie_table->pcie_lane[i] == 6) ? "x16" : "",
pcie_table->clk_freq[i],
(gen_speed == DECODE_GEN_SPEED(pcie_table->pcie_gen[i])) &&
- (lane_width == DECODE_LANE_WIDTH(link_width[pcie_table->pcie_lane[i]])) ?
+ (lane_width == DECODE_LANE_WIDTH(pcie_table->pcie_lane[i])) ?
"*" : "");
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 +1364,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)
@@ -1235,37 +1659,6 @@ static int smu_v13_0_0_force_clk_levels(struct smu_context *smu,
return ret;
}
-static int smu_v13_0_0_update_pcie_parameters(struct smu_context *smu,
- uint32_t pcie_gen_cap,
- uint32_t pcie_width_cap)
-{
- struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
- struct smu_13_0_pcie_table *pcie_table =
- &dpm_context->dpm_tables.pcie_table;
- uint32_t smu_pcie_arg;
- int ret, i;
-
- for (i = 0; i < pcie_table->num_of_link_levels; i++) {
- if (pcie_table->pcie_gen[i] > pcie_gen_cap)
- pcie_table->pcie_gen[i] = pcie_gen_cap;
- if (pcie_table->pcie_lane[i] > pcie_width_cap)
- pcie_table->pcie_lane[i] = pcie_width_cap;
-
- smu_pcie_arg = i << 16;
- smu_pcie_arg |= pcie_table->pcie_gen[i] << 8;
- smu_pcie_arg |= pcie_table->pcie_lane[i];
-
- ret = smu_cmn_send_smc_msg_with_param(smu,
- SMU_MSG_OverridePcieParameters,
- smu_pcie_arg,
- NULL);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
static const struct smu_temperature_range smu13_thermal_policy[] = {
{-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
{ 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000},
@@ -1300,6 +1693,7 @@ static int smu_v13_0_0_get_thermal_temperature_range(struct smu_context *smu,
range->mem_emergency_max = (pptable->SkuTable.TemperatureLimit[TEMP_MEM] + CTF_OFFSET_MEM)*
SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
range->software_shutdown_temp = powerplay_table->software_shutdown_temp;
+ range->software_shutdown_temp_offset = pptable->SkuTable.FanAbnormalTempLimitOffset;
return 0;
}
@@ -1354,7 +1748,7 @@ static ssize_t smu_v13_0_0_get_gpu_metrics(struct smu_context *smu,
gpu_metrics->average_vclk1_frequency = metrics->AverageVclk1Frequency;
gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency;
- gpu_metrics->current_gfxclk = metrics->CurrClock[PPCLK_GFXCLK];
+ gpu_metrics->current_gfxclk = gpu_metrics->average_gfxclk_frequency;
gpu_metrics->current_socclk = metrics->CurrClock[PPCLK_SOCCLK];
gpu_metrics->current_uclk = metrics->CurrClock[PPCLK_UCLK];
gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0];
@@ -1384,6 +1778,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 =
@@ -1837,7 +2303,6 @@ static int smu_v13_0_0_i2c_xfer(struct i2c_adapter *i2c_adap,
}
mutex_lock(&adev->pm.mutex);
r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
- mutex_unlock(&adev->pm.mutex);
if (r)
goto fail;
@@ -1854,6 +2319,7 @@ static int smu_v13_0_0_i2c_xfer(struct i2c_adapter *i2c_adap,
}
r = num_msgs;
fail:
+ mutex_unlock(&adev->pm.mutex);
kfree(req);
return r;
}
@@ -2126,7 +2592,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;
@@ -2171,7 +2637,7 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = {
.feature_is_enabled = smu_cmn_feature_is_enabled,
.print_clk_levels = smu_v13_0_0_print_clk_levels,
.force_clk_levels = smu_v13_0_0_force_clk_levels,
- .update_pcie_parameters = smu_v13_0_0_update_pcie_parameters,
+ .update_pcie_parameters = smu_v13_0_update_pcie_parameters,
.get_thermal_temperature_range = smu_v13_0_0_get_thermal_temperature_range,
.register_irq_handler = smu_v13_0_register_irq_handler,
.enable_thermal_alert = smu_v13_0_enable_thermal_alert,
@@ -2179,6 +2645,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 +2697,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..dc6104a04dce 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,11 @@
/* possible frequency drift (1Mhz) */
#define EPSILON 1
-#define smnPCIE_ESM_CTRL 0x111003D0
+#define smnPCIE_ESM_CTRL 0x193D0
+#define smnPCIE_LC_LINK_WIDTH_CNTL 0x1a340288
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK 0x00000070L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT 0x4
+#define MAX_LINK_WIDTH 6
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 +126,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 +176,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,6 +196,7 @@ struct PPTable_t {
uint32_t LclkFrequencyTable[4];
uint32_t MaxLclkDpmRange;
uint32_t MinLclkDpmRange;
+ uint64_t PublicSerialNumber_AID;
bool Init;
};
@@ -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:
@@ -697,19 +709,19 @@ static int smu_v13_0_6_get_smu_metrics_data(struct smu_context *smu,
*value = SMUQ10_TO_UINT(metrics->SocketPower) << 8;
break;
case METRICS_TEMPERATURE_HOTSPOT:
- *value = SMUQ10_TO_UINT(metrics->MaxSocketTemperature);
+ *value = SMUQ10_TO_UINT(metrics->MaxSocketTemperature) *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
break;
case METRICS_TEMPERATURE_MEM:
- *value = SMUQ10_TO_UINT(metrics->MaxHbmTemperature);
+ *value = SMUQ10_TO_UINT(metrics->MaxHbmTemperature) *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
break;
/* This is the max of all VRs and not just SOC VR.
* No need to define another data type for the same.
*/
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);
+ *value = SMUQ10_TO_UINT(metrics->MaxVrTemperature) *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
break;
default:
*value = UINT_MAX;
@@ -1246,21 +1258,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 +1284,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);
+
+ 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;
- /* Nothing to be done for APU */
- if (smu->adev->flags & AMD_IS_APU)
+ 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;
- ret = smu_v13_0_system_features_control(smu, enable);
+ 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;
}
@@ -1639,7 +1767,6 @@ static int smu_v13_0_6_i2c_xfer(struct i2c_adapter *i2c_adap,
}
mutex_lock(&adev->pm.mutex);
r = smu_v13_0_6_request_i2c_xfer(smu, req);
- mutex_unlock(&adev->pm.mutex);
if (r)
goto fail;
@@ -1656,6 +1783,7 @@ static int smu_v13_0_6_i2c_xfer(struct i2c_adapter *i2c_adap,
}
r = num_msgs;
fail:
+ mutex_unlock(&adev->pm.mutex);
kfree(req);
return r;
}
@@ -1737,19 +1865,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 +1894,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 +1931,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 +1967,13 @@ 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;
+ u16 link_width_level;
+
+ 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 +1982,63 @@ 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);
+ /* Energy counter reported in 15.259uJ (2^-16) units */
+ gpu_metrics->energy_accumulator = 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;
+ if (!(adev->flags & AMD_IS_APU)) {
+ link_width_level = smu_v13_0_6_get_current_pcie_link_width_level(smu);
+ if (link_width_level > MAX_LINK_WIDTH)
+ link_width_level = 0;
- gpu_metrics->pcie_link_width = 0;
- gpu_metrics->pcie_link_speed = smu_v13_0_6_get_current_pcie_link_speed(smu);
+ gpu_metrics->pcie_link_width =
+ DECODE_LANE_WIDTH(link_width_level);
+ 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 +2048,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 +2077,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 +2173,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 +2204,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..62f2886ab4df 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,12 @@ 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;
+#if 0
+ const OverDriveLimits_t * const overdrive_upperlimits =
+ &smc_pptable->SkuTable.OverDriveLimitsBasicMax;
+ const OverDriveLimits_t * const overdrive_lowerlimits =
+ &smc_pptable->SkuTable.OverDriveLimitsMin;
+#endif
if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_HARDWAREDC)
smu->dc_controlled_by_gpio = true;
@@ -333,14 +340,22 @@ 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;
- table_context->thermal_controller_type =
- powerplay_table->thermal_controller_type;
+#if 0
+ if (!overdrive_lowerlimits->FeatureCtrlMask ||
+ !overdrive_upperlimits->FeatureCtrlMask)
+ smu->od_enabled = false;
/*
* Instead of having its own buffer space and get overdrive_table copied,
* smu->od_settings just points to the actual overdrive_table
*/
smu->od_settings = &powerplay_table->overdrive_table;
+#else
+ smu->od_enabled = false;
+#endif
+
+ table_context->thermal_controller_type =
+ powerplay_table->thermal_controller_type;
return 0;
}
@@ -479,7 +494,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);
@@ -940,7 +955,7 @@ static int smu_v13_0_7_read_sensor(struct smu_context *smu,
break;
case AMDGPU_PP_SENSOR_GFX_MCLK:
ret = smu_v13_0_7_get_smu_metrics_data(smu,
- METRICS_AVERAGE_UCLK,
+ METRICS_CURR_UCLK,
(uint32_t *)data);
*(uint32_t *)data *= 100;
*size = 4;
@@ -1013,16 +1028,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 +1256,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 +1346,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)
@@ -1225,37 +1641,6 @@ static int smu_v13_0_7_force_clk_levels(struct smu_context *smu,
return ret;
}
-static int smu_v13_0_7_update_pcie_parameters(struct smu_context *smu,
- uint32_t pcie_gen_cap,
- uint32_t pcie_width_cap)
-{
- struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
- struct smu_13_0_pcie_table *pcie_table =
- &dpm_context->dpm_tables.pcie_table;
- uint32_t smu_pcie_arg;
- int ret, i;
-
- for (i = 0; i < pcie_table->num_of_link_levels; i++) {
- if (pcie_table->pcie_gen[i] > pcie_gen_cap)
- pcie_table->pcie_gen[i] = pcie_gen_cap;
- if (pcie_table->pcie_lane[i] > pcie_width_cap)
- pcie_table->pcie_lane[i] = pcie_width_cap;
-
- smu_pcie_arg = i << 16;
- smu_pcie_arg |= pcie_table->pcie_gen[i] << 8;
- smu_pcie_arg |= pcie_table->pcie_lane[i];
-
- ret = smu_cmn_send_smc_msg_with_param(smu,
- SMU_MSG_OverridePcieParameters,
- smu_pcie_arg,
- NULL);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
static const struct smu_temperature_range smu13_thermal_policy[] =
{
{-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
@@ -1371,6 +1756,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 =
@@ -1752,7 +2209,7 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {
.feature_is_enabled = smu_cmn_feature_is_enabled,
.print_clk_levels = smu_v13_0_7_print_clk_levels,
.force_clk_levels = smu_v13_0_7_force_clk_levels,
- .update_pcie_parameters = smu_v13_0_7_update_pcie_parameters,
+ .update_pcie_parameters = smu_v13_0_update_pcie_parameters,
.get_thermal_temperature_range = smu_v13_0_7_get_thermal_temperature_range,
.register_irq_handler = smu_v13_0_register_irq_handler,
.enable_thermal_alert = smu_v13_0_enable_thermal_alert,
@@ -1760,6 +2217,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 +2258,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..e40a95e51785 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,91 @@ 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);
+ drm_client_register(&fbh->client);
- drm_fb_helper_unprepare(fbh);
+ return;
- priv->fbdev = NULL;
- }
+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..aadb396508c5 100644
--- a/drivers/gpu/drm/bridge/ite-it6505.c
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -2517,9 +2517,11 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
};
int int_status[3], i;
- if (it6505->enable_drv_hold || pm_runtime_get_if_in_use(dev) <= 0)
+ if (it6505->enable_drv_hold || !it6505->powered)
return IRQ_HANDLED;
+ pm_runtime_get_sync(dev);
+
int_status[0] = it6505_read(it6505, INT_STATUS_01);
int_status[1] = it6505_read(it6505, INT_STATUS_02);
int_status[2] = it6505_read(it6505, INT_STATUS_03);
@@ -3207,7 +3209,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 +3218,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 +3481,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..9663601ce098 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611.c
@@ -1190,7 +1190,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..73ec60757dbc 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) |
@@ -1291,6 +1386,18 @@ static void samsung_dsim_disable_irq(struct samsung_dsim *dsi)
disable_irq(dsi->irq);
}
+static void samsung_dsim_set_stop_state(struct samsung_dsim *dsi, bool enable)
+{
+ u32 reg = samsung_dsim_read(dsi, DSIM_ESCMODE_REG);
+
+ if (enable)
+ reg |= DSIM_FORCE_STOP_STATE;
+ else
+ reg &= ~DSIM_FORCE_STOP_STATE;
+
+ samsung_dsim_write(dsi, DSIM_ESCMODE_REG, reg);
+}
+
static int samsung_dsim_init(struct samsung_dsim *dsi)
{
const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
@@ -1340,6 +1447,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);
}
}
@@ -1348,8 +1458,12 @@ static void samsung_dsim_atomic_enable(struct drm_bridge *bridge,
{
struct samsung_dsim *dsi = bridge_to_dsi(bridge);
- 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 {
+ samsung_dsim_set_stop_state(dsi, false);
+ }
dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
}
@@ -1362,6 +1476,9 @@ static void samsung_dsim_atomic_disable(struct drm_bridge *bridge,
if (!(dsi->state & DSIM_STATE_ENABLED))
return;
+ if (!samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type))
+ samsung_dsim_set_stop_state(dsi, true);
+
dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
}
@@ -1663,6 +1780,8 @@ static ssize_t samsung_dsim_host_transfer(struct mipi_dsi_host *host,
if (ret)
return ret;
+ samsung_dsim_set_stop_state(dsi, false);
+
ret = mipi_dsi_create_packet(&xfer.packet, msg);
if (ret < 0)
return ret;
@@ -1682,11 +1801,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 +1815,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 +2102,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..7b66f362afd8 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);
@@ -1426,9 +1426,9 @@ void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi,
/* Control for TMDS Bit Period/TMDS Clock-Period Ratio */
if (dw_hdmi_support_scdc(hdmi, display)) {
if (mtmdsclock > HDMI14_MAX_TMDSCLK)
- drm_scdc_set_high_tmds_clock_ratio(&hdmi->connector, 1);
+ drm_scdc_set_high_tmds_clock_ratio(hdmi->curr_conn, 1);
else
- drm_scdc_set_high_tmds_clock_ratio(&hdmi->connector, 0);
+ drm_scdc_set_high_tmds_clock_ratio(hdmi->curr_conn, 0);
}
}
EXPORT_SYMBOL_GPL(dw_hdmi_set_high_tmds_clock_ratio);
@@ -2116,7 +2116,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
min_t(u8, bytes, SCDC_MIN_SOURCE_VERSION));
/* Enabled Scrambling in the Sink */
- drm_scdc_set_scrambling(&hdmi->connector, 1);
+ drm_scdc_set_scrambling(hdmi->curr_conn, 1);
/*
* To activate the scrambler feature, you must ensure
@@ -2132,7 +2132,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
hdmi_writeb(hdmi, 0, HDMI_FC_SCRAMBLER_CTRL);
hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ,
HDMI_MC_SWRSTZ);
- drm_scdc_set_scrambling(&hdmi->connector, 0);
+ drm_scdc_set_scrambling(hdmi->curr_conn, 0);
}
}
@@ -3553,6 +3553,7 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID
| DRM_BRIDGE_OP_HPD;
hdmi->bridge.interlace_allowed = true;
+ hdmi->bridge.ddc = hdmi->ddc;
#ifdef CONFIG_OF
hdmi->bridge.of_node = pdev->dev.of_node;
#endif
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..f448b903e190 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -170,10 +170,10 @@
* @pwm_refclk_freq: Cache for the reference clock input to the PWM.
*/
struct ti_sn65dsi86 {
- struct auxiliary_device bridge_aux;
- struct auxiliary_device gpio_aux;
- struct auxiliary_device aux_aux;
- struct auxiliary_device pwm_aux;
+ struct auxiliary_device *bridge_aux;
+ struct auxiliary_device *gpio_aux;
+ struct auxiliary_device *aux_aux;
+ struct auxiliary_device *pwm_aux;
struct device *dev;
struct regmap *regmap;
@@ -468,27 +468,34 @@ static void ti_sn65dsi86_delete_aux(void *data)
auxiliary_device_delete(data);
}
-/*
- * AUX bus docs say that a non-NULL release is mandatory, but it makes no
- * sense for the model used here where all of the aux devices are allocated
- * in the single shared structure. We'll use this noop as a workaround.
- */
-static void ti_sn65dsi86_noop(struct device *dev) {}
+static void ti_sn65dsi86_aux_device_release(struct device *dev)
+{
+ struct auxiliary_device *aux = container_of(dev, struct auxiliary_device, dev);
+
+ kfree(aux);
+}
static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata,
- struct auxiliary_device *aux,
+ struct auxiliary_device **aux_out,
const char *name)
{
struct device *dev = pdata->dev;
+ struct auxiliary_device *aux;
int ret;
+ aux = kzalloc(sizeof(*aux), GFP_KERNEL);
+ if (!aux)
+ return -ENOMEM;
+
aux->name = name;
aux->dev.parent = dev;
- aux->dev.release = ti_sn65dsi86_noop;
+ aux->dev.release = ti_sn65dsi86_aux_device_release;
device_set_of_node_from_dev(&aux->dev, dev);
ret = auxiliary_device_init(aux);
- if (ret)
+ if (ret) {
+ kfree(aux);
return ret;
+ }
ret = devm_add_action_or_reset(dev, ti_sn65dsi86_uninit_aux, aux);
if (ret)
return ret;
@@ -497,6 +504,8 @@ static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata,
if (ret)
return ret;
ret = devm_add_action_or_reset(dev, ti_sn65dsi86_delete_aux, aux);
+ if (!ret)
+ *aux_out = aux;
return ret;
}
@@ -622,6 +631,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 +658,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 +1983,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_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c
index 16565a0a5da6..e6a78fd32380 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -2103,7 +2103,7 @@ int drm_dp_aux_register(struct drm_dp_aux *aux)
aux->ddc.owner = THIS_MODULE;
aux->ddc.dev.parent = aux->dev;
- strlcpy(aux->ddc.name, aux->name ? aux->name : dev_name(aux->dev),
+ strscpy(aux->ddc.name, aux->name ? aux->name : dev_name(aux->dev),
sizeof(aux->ddc.name));
ret = drm_dp_aux_register_devnode(aux);
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index e2e21ce79510..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);
@@ -5702,7 +5773,7 @@ static int drm_dp_mst_register_i2c_bus(struct drm_dp_mst_port *port)
aux->ddc.dev.parent = parent_dev;
aux->ddc.dev.of_node = parent_dev->of_node;
- strlcpy(aux->ddc.name, aux->name ? aux->name : dev_name(parent_dev),
+ strscpy(aux->ddc.name, aux->name ? aux->name : dev_name(parent_dev),
sizeof(aux->ddc.name));
return i2c_add_adapter(&aux->ddc);
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..c277b198fa3f 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -140,6 +140,12 @@ drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)
if (!state->planes)
goto fail;
+ /*
+ * Because drm_atomic_state can be committed asynchronously we need our
+ * own reference and cannot rely on the on implied by drm_file in the
+ * ioctl call.
+ */
+ drm_dev_get(dev);
state->dev = dev;
drm_dbg_atomic(dev, "Allocated atomic state %p\n", state);
@@ -299,7 +305,8 @@ EXPORT_SYMBOL(drm_atomic_state_clear);
void __drm_atomic_state_free(struct kref *ref)
{
struct drm_atomic_state *state = container_of(ref, typeof(*state), ref);
- struct drm_mode_config *config = &state->dev->mode_config;
+ struct drm_device *dev = state->dev;
+ struct drm_mode_config *config = &dev->mode_config;
drm_atomic_state_clear(state);
@@ -311,6 +318,8 @@ void __drm_atomic_state_free(struct kref *ref)
drm_atomic_state_default_release(state);
kfree(state);
}
+
+ drm_dev_put(dev);
}
EXPORT_SYMBOL(__drm_atomic_state_free);
@@ -1131,6 +1140,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_client.c b/drivers/gpu/drm/drm_client.c
index f6292ba0e6fc..037e36f2049c 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -122,13 +122,34 @@ EXPORT_SYMBOL(drm_client_init);
* drm_client_register() it is no longer permissible to call drm_client_release()
* directly (outside the unregister callback), instead cleanup will happen
* automatically on driver unload.
+ *
+ * Registering a client generates a hotplug event that allows the client
+ * to set up its display from pre-existing outputs. The client must have
+ * initialized its state to able to handle the hotplug event successfully.
*/
void drm_client_register(struct drm_client_dev *client)
{
struct drm_device *dev = client->dev;
+ int ret;
mutex_lock(&dev->clientlist_mutex);
list_add(&client->list, &dev->clientlist);
+
+ if (client->funcs && client->funcs->hotplug) {
+ /*
+ * Perform an initial hotplug event to pick up the
+ * display configuration for the client. This step
+ * has to be performed *after* registering the client
+ * in the list of clients, or a concurrent hotplug
+ * event might be lost; leaving the display off.
+ *
+ * Hold the clientlist_mutex as for a regular hotplug
+ * event.
+ */
+ ret = client->funcs->hotplug(client);
+ if (ret)
+ drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
+ }
mutex_unlock(&dev->clientlist_mutex);
}
EXPORT_SYMBOL(drm_client_register);
diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
index 1b12a3c201a3..871e4e2129d6 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -311,6 +311,9 @@ static bool drm_client_target_cloned(struct drm_device *dev,
can_clone = true;
dmt_mode = drm_mode_find_dmt(dev, 1024, 768, 60, false);
+ if (!dmt_mode)
+ goto fail;
+
for (i = 0; i < connector_count; i++) {
if (!enabled[i])
continue;
@@ -326,11 +329,13 @@ static bool drm_client_target_cloned(struct drm_device *dev,
if (!modes[i])
can_clone = false;
}
+ kfree(dmt_mode);
if (can_clone) {
DRM_DEBUG_KMS("can clone using 1024x768\n");
return true;
}
+fail:
DRM_INFO("kms: can't enable cloning when we probably wanted to.\n");
return false;
}
@@ -862,6 +867,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width,
break;
}
+ kfree(modeset->mode);
modeset->mode = drm_mode_duplicate(dev, mode);
drm_connector_get(connector);
modeset->connectors[modeset->num_connectors++] = connector;
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..1f470968ed14 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);
@@ -3424,6 +3456,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
connector->base.id, connector->name);
return NULL;
}
+ if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
+ drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Composite sync not supported\n",
+ connector->base.id, connector->name);
+ }
/* it is incorrect if hsync/vsync width is zero */
if (!hsync_pulse_width || !vsync_pulse_width) {
@@ -3470,27 +3506,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
if (info->quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC;
} else {
- switch (pt->misc & DRM_EDID_PT_SYNC_MASK) {
- case DRM_EDID_PT_ANALOG_CSYNC:
- case DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC:
- drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Analog composite sync!\n",
- connector->base.id, connector->name);
- mode->flags |= DRM_MODE_FLAG_CSYNC | DRM_MODE_FLAG_NCSYNC;
- break;
- case DRM_EDID_PT_DIGITAL_CSYNC:
- drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Digital composite sync!\n",
- connector->base.id, connector->name);
- mode->flags |= DRM_MODE_FLAG_CSYNC;
- mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
- DRM_MODE_FLAG_PCSYNC : DRM_MODE_FLAG_NCSYNC;
- break;
- case DRM_EDID_PT_DIGITAL_SEPARATE_SYNC:
- mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
- DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
- mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
- DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
- break;
- }
+ mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
+ DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
+ mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
+ DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
}
set_size:
@@ -6243,6 +6262,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 +6290,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 +6448,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..f353daff65e1 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,
};
/*
@@ -218,7 +217,7 @@ static const struct drm_client_funcs drm_fbdev_dma_client_funcs = {
* drm_fbdev_dma_setup() - Setup fbdev emulation for GEM DMA helpers
* @dev: DRM device
* @preferred_bpp: Preferred bits per pixel for the device.
- * @dev->mode_config.preferred_depth is used if this is zero.
+ * 32 is used if this is zero.
*
* This function sets up fbdev emulation for GEM DMA drivers that support
* dumb buffers with a virtual address and that can be mmap'ed.
@@ -253,10 +252,6 @@ void drm_fbdev_dma_setup(struct drm_device *dev, unsigned int preferred_bpp)
goto err_drm_client_init;
}
- ret = drm_fbdev_dma_client_hotplug(&fb_helper->client);
- if (ret)
- drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
-
drm_client_register(&fb_helper->client);
return;
diff --git a/drivers/gpu/drm/drm_fbdev_generic.c b/drivers/gpu/drm/drm_fbdev_generic.c
index 8e5148bf40bb..b9343fb6cf13 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,
};
@@ -340,10 +339,6 @@ void drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
goto err_drm_client_init;
}
- ret = drm_fbdev_generic_client_hotplug(&fb_helper->client);
- if (ret)
- drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
-
drm_client_register(&fb_helper->client);
return;
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.c b/drivers/gpu/drm/drm_gem.c
index 1a5a2cd0d4ec..78dcae201cc6 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -496,13 +496,13 @@ int drm_gem_create_mmap_offset(struct drm_gem_object *obj)
EXPORT_SYMBOL(drm_gem_create_mmap_offset);
/*
- * Move pages to appropriate lru and release the pagevec, decrementing the
- * ref count of those pages.
+ * Move folios to appropriate lru and release the folios, decrementing the
+ * ref count of those folios.
*/
-static void drm_gem_check_release_pagevec(struct pagevec *pvec)
+static void drm_gem_check_release_batch(struct folio_batch *fbatch)
{
- check_move_unevictable_pages(pvec);
- __pagevec_release(pvec);
+ check_move_unevictable_folios(fbatch);
+ __folio_batch_release(fbatch);
cond_resched();
}
@@ -534,10 +534,10 @@ static void drm_gem_check_release_pagevec(struct pagevec *pvec)
struct page **drm_gem_get_pages(struct drm_gem_object *obj)
{
struct address_space *mapping;
- struct page *p, **pages;
- struct pagevec pvec;
- int i, npages;
-
+ struct page **pages;
+ struct folio *folio;
+ struct folio_batch fbatch;
+ int i, j, npages;
if (WARN_ON(!obj->filp))
return ERR_PTR(-EINVAL);
@@ -559,11 +559,14 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj)
mapping_set_unevictable(mapping);
- for (i = 0; i < npages; i++) {
- p = shmem_read_mapping_page(mapping, i);
- if (IS_ERR(p))
+ i = 0;
+ while (i < npages) {
+ folio = shmem_read_folio_gfp(mapping, i,
+ mapping_gfp_mask(mapping));
+ if (IS_ERR(folio))
goto fail;
- pages[i] = p;
+ for (j = 0; j < folio_nr_pages(folio); j++, i++)
+ pages[i] = folio_file_page(folio, i);
/* Make sure shmem keeps __GFP_DMA32 allocated pages in the
* correct region during swapin. Note that this requires
@@ -571,23 +574,26 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj)
* so shmem can relocate pages during swapin if required.
*/
BUG_ON(mapping_gfp_constraint(mapping, __GFP_DMA32) &&
- (page_to_pfn(p) >= 0x00100000UL));
+ (folio_pfn(folio) >= 0x00100000UL));
}
return pages;
fail:
mapping_clear_unevictable(mapping);
- pagevec_init(&pvec);
- while (i--) {
- if (!pagevec_add(&pvec, pages[i]))
- drm_gem_check_release_pagevec(&pvec);
+ folio_batch_init(&fbatch);
+ j = 0;
+ while (j < i) {
+ struct folio *f = page_folio(pages[j]);
+ if (!folio_batch_add(&fbatch, f))
+ drm_gem_check_release_batch(&fbatch);
+ j += folio_nr_pages(f);
}
- if (pagevec_count(&pvec))
- drm_gem_check_release_pagevec(&pvec);
+ if (fbatch.nr)
+ drm_gem_check_release_batch(&fbatch);
kvfree(pages);
- return ERR_CAST(p);
+ return ERR_CAST(folio);
}
EXPORT_SYMBOL(drm_gem_get_pages);
@@ -603,7 +609,7 @@ void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
{
int i, npages;
struct address_space *mapping;
- struct pagevec pvec;
+ struct folio_batch fbatch;
mapping = file_inode(obj->filp)->i_mapping;
mapping_clear_unevictable(mapping);
@@ -616,23 +622,27 @@ void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
npages = obj->size >> PAGE_SHIFT;
- pagevec_init(&pvec);
+ folio_batch_init(&fbatch);
for (i = 0; i < npages; i++) {
+ struct folio *folio;
+
if (!pages[i])
continue;
+ folio = page_folio(pages[i]);
if (dirty)
- set_page_dirty(pages[i]);
+ folio_mark_dirty(folio);
if (accessed)
- mark_page_accessed(pages[i]);
+ folio_mark_accessed(folio);
/* Undo the reference we took when populating the table */
- if (!pagevec_add(&pvec, pages[i]))
- drm_gem_check_release_pagevec(&pvec);
+ if (!folio_batch_add(&fbatch, folio))
+ drm_gem_check_release_batch(&fbatch);
+ i += folio_nr_pages(folio) - 1;
}
- if (pagevec_count(&pvec))
- drm_gem_check_release_pagevec(&pvec);
+ if (folio_batch_count(&fbatch))
+ drm_gem_check_release_batch(&fbatch);
kvfree(pages);
}
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_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 4ea6507a77e5..baaf0e0feb06 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -623,7 +623,13 @@ int drm_gem_shmem_mmap(struct drm_gem_shmem_object *shmem, struct vm_area_struct
int ret;
if (obj->import_attach) {
+ /* Reset both vm_ops and vm_private_data, so we don't end up with
+ * vm_ops pointing to our implementation if the dma-buf backend
+ * doesn't set those fields.
+ */
vma->vm_private_data = NULL;
+ vma->vm_ops = NULL;
+
ret = dma_buf_mmap(obj->dma_buf, vma, 0);
/* Drop the reference drm_gem_mmap_obj() acquired.*/
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_managed.c b/drivers/gpu/drm/drm_managed.c
index c21c3f623033..5423ad883729 100644
--- a/drivers/gpu/drm/drm_managed.c
+++ b/drivers/gpu/drm/drm_managed.c
@@ -49,10 +49,10 @@ struct drmres {
* Some archs want to perform DMA into kmalloc caches
* and need a guaranteed alignment larger than
* the alignment of a 64-bit integer.
- * Thus we use ARCH_KMALLOC_MINALIGN here and get exactly the same
- * buffer alignment as if it was allocated by plain kmalloc().
+ * Thus we use ARCH_DMA_MINALIGN for data[] which will force the same
+ * alignment for struct drmres when allocated by kmalloc().
*/
- u8 __aligned(ARCH_KMALLOC_MINALIGN) data[];
+ u8 __aligned(ARCH_DMA_MINALIGN) data[];
};
static void free_dr(struct drmres *dr)
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 3fd6c733ff4e..6252ac01e945 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -223,7 +223,7 @@ mipi_dsi_device_register_full(struct mipi_dsi_host *host,
device_set_node(&dsi->dev, of_fwnode_handle(info->node));
dsi->channel = info->channel;
- strlcpy(dsi->name, info->type, sizeof(dsi->name));
+ strscpy(dsi->name, info->type, sizeof(dsi->name));
ret = mipi_dsi_device_add(dsi);
if (ret) {
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index 2fb9bf901a2c..3f479483d7d8 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -262,6 +262,26 @@ static bool drm_kms_helper_enable_hpd(struct drm_device *dev)
}
#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
+static void reschedule_output_poll_work(struct drm_device *dev)
+{
+ unsigned long delay = DRM_OUTPUT_POLL_PERIOD;
+
+ if (dev->mode_config.delayed_event)
+ /*
+ * FIXME:
+ *
+ * Use short (1s) delay to handle the initial delayed event.
+ * This delay should not be needed, but Optimus/nouveau will
+ * fail in a mysterious way if the delayed event is handled as
+ * soon as possible like it is done in
+ * drm_helper_probe_single_connector_modes() in case the poll
+ * was enabled before.
+ */
+ delay = HZ;
+
+ schedule_delayed_work(&dev->mode_config.output_poll_work, delay);
+}
+
/**
* drm_kms_helper_poll_enable - re-enable output polling.
* @dev: drm_device
@@ -279,37 +299,41 @@ static bool drm_kms_helper_enable_hpd(struct drm_device *dev)
*/
void drm_kms_helper_poll_enable(struct drm_device *dev)
{
- bool poll = false;
- unsigned long delay = DRM_OUTPUT_POLL_PERIOD;
-
if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll ||
dev->mode_config.poll_running)
return;
- poll = drm_kms_helper_enable_hpd(dev);
-
- if (dev->mode_config.delayed_event) {
- /*
- * FIXME:
- *
- * Use short (1s) delay to handle the initial delayed event.
- * This delay should not be needed, but Optimus/nouveau will
- * fail in a mysterious way if the delayed event is handled as
- * soon as possible like it is done in
- * drm_helper_probe_single_connector_modes() in case the poll
- * was enabled before.
- */
- poll = true;
- delay = HZ;
- }
-
- if (poll)
- schedule_delayed_work(&dev->mode_config.output_poll_work, delay);
+ if (drm_kms_helper_enable_hpd(dev) ||
+ dev->mode_config.delayed_event)
+ reschedule_output_poll_work(dev);
dev->mode_config.poll_running = true;
}
EXPORT_SYMBOL(drm_kms_helper_poll_enable);
+/**
+ * drm_kms_helper_poll_reschedule - reschedule the output polling work
+ * @dev: drm_device
+ *
+ * This function reschedules the output polling work, after polling for a
+ * connector has been enabled.
+ *
+ * Drivers must call this helper after enabling polling for a connector by
+ * setting %DRM_CONNECTOR_POLL_CONNECT / %DRM_CONNECTOR_POLL_DISCONNECT flags
+ * in drm_connector::polled. Note that after disabling polling by clearing these
+ * flags for a connector will stop the output polling work automatically if
+ * the polling is disabled for all other connectors as well.
+ *
+ * The function can be called only after polling has been enabled by calling
+ * drm_kms_helper_poll_init() / drm_kms_helper_poll_enable().
+ */
+void drm_kms_helper_poll_reschedule(struct drm_device *dev)
+{
+ if (dev->mode_config.poll_running)
+ reschedule_output_poll_work(dev);
+}
+EXPORT_SYMBOL(drm_kms_helper_poll_reschedule);
+
static enum drm_connector_status
drm_helper_probe_detect_ctx(struct drm_connector *connector, bool force)
{
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index 0c2be8360525..e592c5da70ce 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -353,10 +353,10 @@ EXPORT_SYMBOL(drm_syncobj_replace_fence);
*/
static int drm_syncobj_assign_null_handle(struct drm_syncobj *syncobj)
{
- struct dma_fence *fence = dma_fence_allocate_private_stub();
+ struct dma_fence *fence = dma_fence_allocate_private_stub(ktime_get());
- if (IS_ERR(fence))
- return PTR_ERR(fence);
+ if (!fence)
+ return -ENOMEM;
drm_syncobj_replace_fence(syncobj, fence);
dma_fence_put(fence);
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..226310c765d8 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,
};
@@ -216,10 +215,6 @@ void exynos_drm_fbdev_setup(struct drm_device *dev)
if (ret)
goto err_drm_client_init;
- ret = exynos_drm_fbdev_client_hotplug(&fb_helper->client);
- if (ret)
- drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
-
drm_client_register(&fb_helper->client);
return;
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..054426549fc6 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) */
@@ -330,10 +328,6 @@ void psb_fbdev_setup(struct drm_psb_private *dev_priv)
goto err_drm_fb_helper_unprepare;
}
- ret = psb_fbdev_client_hotplug(&fb_helper->client);
- if (ret)
- drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
-
drm_client_register(&fb_helper->client);
return;
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 db5c9343a3d2..d8d7de18dd65 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -1951,7 +1951,7 @@ static int tda998x_create(struct device *dev)
* offset.
*/
memset(&cec_info, 0, sizeof(cec_info));
- strlcpy(cec_info.type, "tda9950", sizeof(cec_info.type));
+ strscpy(cec_info.type, "tda9950", sizeof(cec_info.type));
cec_info.addr = priv->cec_addr;
cec_info.platform_data = &priv->cec_glue;
cec_info.irq = client->irq;
@@ -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..dcbda9ba32dd 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -19,12 +19,13 @@ 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_display_device.o = $(call cc-disable-warning, override-init)
CFLAGS_display/intel_fbdev.o = $(call cc-disable-warning, override-init)
subdir-ccflags-y += -I$(srctree)/$(src)
@@ -194,6 +195,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 +239,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 +263,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 +307,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 +349,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 +385,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 +400,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..719447ce86e7
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -0,0 +1,3047 @@
+// 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_PLLA |
+ 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..16603d591f56 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)
{
@@ -4968,7 +4564,6 @@ copy_bigjoiner_crtc_state_modeset(struct intel_atomic_state *state,
saved_state->uapi = slave_crtc_state->uapi;
saved_state->scaler_state = slave_crtc_state->scaler_state;
saved_state->shared_dpll = slave_crtc_state->shared_dpll;
- saved_state->dpll_hw_state = slave_crtc_state->dpll_hw_state;
saved_state->crc_enabled = slave_crtc_state->crc_enabled;
intel_crtc_free_hw_state(slave_crtc_state);
@@ -5277,7 +4872,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 +4897,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 +4938,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 +4969,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 +5176,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 +5284,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 +5292,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 +5381,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 +5558,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 +5617,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 +5660,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 +5715,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 +6003,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 +6026,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 +6184,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 +6354,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 +6540,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 +6568,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 +6847,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 +6979,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 +7003,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 +7130,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 +7179,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 +7205,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 +7308,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 +7387,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 +7397,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 +7646,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 +7787,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 +7833,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 +7845,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 +7860,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 +7876,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 +7918,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 +8025,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 +8043,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..b0c6a2a86f2f
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_display_device.c
@@ -0,0 +1,930 @@
+// 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"
+
+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),
+};
+
+/*
+ * Separate detection for no display cases to keep the display id array simple.
+ *
+ * IVB Q requires subvendor and subdevice matching to differentiate from IVB D
+ * GT2 server.
+ */
+static bool has_no_display(struct pci_dev *pdev)
+{
+ static const struct pci_device_id ids[] = {
+ INTEL_IVB_Q_IDS(0),
+ {}
+ };
+
+ return pci_match_id(ids, pdev);
+}
+
+#undef INTEL_VGA_DEVICE
+#define INTEL_VGA_DEVICE(id, info) { id, 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_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);
+
+ if (has_no_display(pdev)) {
+ drm_dbg_kms(&i915->drm, "Device doesn't have display\n");
+ return &no_display;
+ }
+
+ 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..df38632c6237 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.h
+++ b/drivers/gpu/drm/i915/display/intel_display_power.h
@@ -6,6 +6,9 @@
#ifndef __INTEL_DISPLAY_POWER_H__
#define __INTEL_DISPLAY_POWER_H__
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+
#include "intel_wakeref.h"
enum aux_ch;
@@ -16,6 +19,7 @@ enum port;
struct drm_i915_private;
struct i915_power_well;
struct intel_encoder;
+struct seq_file;
/*
* Keep the pipe, transcoder, port (DDI_LANES,DDI_IO,AUX) domain instances
@@ -171,8 +175,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..5ad04cd42c15 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_map.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_map.c
@@ -1251,10 +1251,7 @@ 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, \
+#define XELPD_DC_OFF_PORT_POWER_DOMAINS \
POWER_DOMAIN_PORT_DDI_LANES_C, \
POWER_DOMAIN_PORT_DDI_LANES_D, \
POWER_DOMAIN_PORT_DDI_LANES_E, \
@@ -1279,6 +1276,12 @@ 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, \
+ 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..1015bba4af01 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_well.h
+++ b/drivers/gpu/drm/i915/display/intel_display_power_well.h
@@ -12,6 +12,8 @@
struct drm_i915_private;
struct i915_power_well;
+struct i915_power_well_ops;
+struct intel_encoder;
#define for_each_power_well(__dev_priv, __power_well) \
for ((__power_well) = (__dev_priv)->display.power.domains.power_wells; \
@@ -110,6 +112,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..fbfd8f959f17 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;
@@ -166,6 +166,8 @@ struct i915_vma *intel_dpt_pin(struct i915_address_space *vm)
i915_vma_get(vma);
}
+ dpt->obj->mm.dirty = true;
+
atomic_dec(&i915->gpu_error.pending_fb_pin);
intel_runtime_pm_put(&i915->runtime_pm, wakeref);
@@ -261,7 +263,7 @@ intel_dpt_create(struct intel_framebuffer *fb)
dpt_obj = i915_gem_object_create_stolen(i915, size);
if (IS_ERR(dpt_obj) && !HAS_LMEM(i915)) {
drm_dbg_kms(&i915->drm, "Allocating dpt from smem\n");
- dpt_obj = i915_gem_object_create_internal(i915, size);
+ dpt_obj = i915_gem_object_create_shmem(i915, size);
}
if (IS_ERR(dpt_obj))
return ERR_CAST(dpt_obj);
@@ -300,7 +302,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..80c3f88310db 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,30 @@ 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);
+}
+
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,
};
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 +175,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 +206,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 +691,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..34fabadefaf6 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->hdcp_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..5eac7032bb5a 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
@@ -210,8 +211,9 @@ 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,
+ drm_kms_helper_poll_reschedule(&dev_priv->drm);
+ 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);
}
/**
@@ -644,7 +649,7 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
drm_connector_list_iter_end(&conn_iter);
if (enabled)
- drm_kms_helper_poll_enable(&dev_priv->drm);
+ drm_kms_helper_poll_reschedule(&dev_priv->drm);
mutex_unlock(&dev_priv->drm.mode_config.mutex);
@@ -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..56c17283ba2d 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)
@@ -851,9 +933,9 @@ static bool _compute_psr2_wake_times(struct intel_dp *intel_dp,
}
io_wake_lines = intel_usecs_to_scanlines(
- &crtc_state->uapi.adjusted_mode, io_wake_time);
+ &crtc_state->hw.adjusted_mode, io_wake_time);
fast_wake_lines = intel_usecs_to_scanlines(
- &crtc_state->uapi.adjusted_mode, fast_wake_time);
+ &crtc_state->hw.adjusted_mode, fast_wake_time);
if (io_wake_lines > max_wake_lines ||
fast_wake_lines > max_wake_lines)
@@ -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..8750cb0d8d9d 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
@@ -75,86 +81,95 @@
#define _SRD_AUX_DATA_A 0x60814
#define _SRD_AUX_DATA_EDP 0x6f814
-#define EDP_PSR_AUX_DATA(tran, i) _MMIO_TRANS2(tran, _SRD_AUX_DATA_A + (i) + 4) /* 5 registers */
+#define EDP_PSR_AUX_DATA(tran, i) _MMIO_TRANS2(tran, _SRD_AUX_DATA_A + (i) * 4) /* 5 registers */
#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..67e3aaf9b432 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;
}
@@ -2752,7 +2752,7 @@ static struct intel_sdvo_connector *intel_sdvo_connector_alloc(void)
__drm_atomic_helper_connector_reset(&sdvo_connector->base.base,
&conn_state->base.base);
- INIT_LIST_HEAD(&sdvo_connector->base.panel.fixed_modes);
+ intel_panel_init_alloc(&sdvo_connector->base);
return sdvo_connector;
}
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 37d1efcd3ca6..8f1633c3fb93 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
@@ -19,13 +19,13 @@
#include "i915_trace.h"
/*
- * Move pages to appropriate lru and release the pagevec, decrementing the
- * ref count of those pages.
+ * Move folios to appropriate lru and release the batch, decrementing the
+ * ref count of those folios.
*/
-static void check_release_pagevec(struct pagevec *pvec)
+static void check_release_folio_batch(struct folio_batch *fbatch)
{
- check_move_unevictable_pages(pvec);
- __pagevec_release(pvec);
+ check_move_unevictable_folios(fbatch);
+ __folio_batch_release(fbatch);
cond_resched();
}
@@ -33,24 +33,29 @@ void shmem_sg_free_table(struct sg_table *st, struct address_space *mapping,
bool dirty, bool backup)
{
struct sgt_iter sgt_iter;
- struct pagevec pvec;
+ struct folio_batch fbatch;
+ struct folio *last = NULL;
struct page *page;
mapping_clear_unevictable(mapping);
- pagevec_init(&pvec);
+ folio_batch_init(&fbatch);
for_each_sgt_page(page, sgt_iter, st) {
- if (dirty)
- set_page_dirty(page);
+ struct folio *folio = page_folio(page);
+ if (folio == last)
+ continue;
+ last = folio;
+ if (dirty)
+ folio_mark_dirty(folio);
if (backup)
- mark_page_accessed(page);
+ folio_mark_accessed(folio);
- if (!pagevec_add(&pvec, page))
- check_release_pagevec(&pvec);
+ if (!folio_batch_add(&fbatch, folio))
+ check_release_folio_batch(&fbatch);
}
- if (pagevec_count(&pvec))
- check_release_pagevec(&pvec);
+ if (fbatch.nr)
+ check_release_folio_batch(&fbatch);
sg_free_table(st);
}
@@ -63,8 +68,7 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st,
unsigned int page_count; /* restricted by sg_alloc_table */
unsigned long i;
struct scatterlist *sg;
- struct page *page;
- unsigned long last_pfn = 0; /* suppress gcc warning */
+ unsigned long next_pfn = 0; /* suppress gcc warning */
gfp_t noreclaim;
int ret;
@@ -95,6 +99,7 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st,
sg = st->sgl;
st->nents = 0;
for (i = 0; i < page_count; i++) {
+ struct folio *folio;
const unsigned int shrink[] = {
I915_SHRINK_BOUND | I915_SHRINK_UNBOUND,
0,
@@ -103,12 +108,12 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st,
do {
cond_resched();
- page = shmem_read_mapping_page_gfp(mapping, i, gfp);
- if (!IS_ERR(page))
+ folio = shmem_read_folio_gfp(mapping, i, gfp);
+ if (!IS_ERR(folio))
break;
if (!*s) {
- ret = PTR_ERR(page);
+ ret = PTR_ERR(folio);
goto err_sg;
}
@@ -147,19 +152,21 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st,
if (!i ||
sg->length >= max_segment ||
- page_to_pfn(page) != last_pfn + 1) {
+ folio_pfn(folio) != next_pfn) {
if (i)
sg = sg_next(sg);
st->nents++;
- sg_set_page(sg, page, PAGE_SIZE, 0);
+ sg_set_folio(sg, folio, folio_size(folio), 0);
} else {
- sg->length += PAGE_SIZE;
+ /* XXX: could overflow? */
+ sg->length += folio_size(folio);
}
- last_pfn = page_to_pfn(page);
+ next_pfn = folio_pfn(folio) + folio_nr_pages(folio);
+ i += folio_nr_pages(folio) - 1;
/* Check that the i965g/gm workaround works. */
- GEM_BUG_ON(gfp & __GFP_DMA32 && last_pfn >= 0x00100000UL);
+ GEM_BUG_ON(gfp & __GFP_DMA32 && next_pfn >= 0x00100000UL);
}
if (sg) /* loop terminated early; short sg table */
sg_mark_end(sg);
@@ -455,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)
@@ -601,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..6b9f6cf50bf6 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;
}
@@ -1190,8 +1246,10 @@ static int igt_write_huge(struct drm_i915_private *i915,
* times in succession a possibility by enlarging the permutation array.
*/
order = i915_random_order(count * count, &prng);
- if (!order)
- return -ENOMEM;
+ if (!order) {
+ err = -ENOMEM;
+ goto out;
+ }
max_page_size = rounddown_pow_of_two(obj->mm.page_sizes.sg);
max = div_u64(max - size, max_page_size);
@@ -1910,8 +1968,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 +2018,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 56279908ed30..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);
@@ -1681,7 +1681,9 @@ static int igt_mmap_gpu(void *arg)
static int check_present_pte(pte_t *pte, unsigned long addr, void *data)
{
- if (!pte_present(*pte) || pte_none(*pte)) {
+ pte_t ptent = ptep_get(pte);
+
+ if (!pte_present(ptent) || pte_none(ptent)) {
pr_err("missing PTE:%lx\n",
(addr - (unsigned long)data) >> PAGE_SHIFT);
return -EINVAL;
@@ -1692,7 +1694,9 @@ static int check_present_pte(pte_t *pte, unsigned long addr, void *data)
static int check_absent_pte(pte_t *pte, unsigned long addr, void *data)
{
- if (pte_present(*pte) && !pte_none(*pte)) {
+ pte_t ptent = ptep_get(pte);
+
+ if (pte_present(ptent) && !pte_none(ptent)) {
pr_err("present PTE:%lx; expected to be revoked\n",
(addr - (unsigned long)data) >> PAGE_SHIFT);
return -EINVAL;
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..2702ad4c26c8 100644
--- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c
@@ -165,58 +165,148 @@ static u32 preparser_disable(bool state)
return MI_ARB_CHECK | 1 << 8 | state;
}
-u32 *gen12_emit_aux_table_inv(struct intel_gt *gt, u32 *cs, const i915_reg_t inv_reg)
+static i915_reg_t gen12_get_aux_inv_reg(struct intel_engine_cs *engine)
{
- u32 gsi_offset = gt->uncore->gsi_offset;
+ switch (engine->id) {
+ case RCS0:
+ return GEN12_CCS_AUX_INV;
+ case BCS0:
+ return GEN12_BCS0_AUX_INV;
+ case VCS0:
+ return GEN12_VD0_AUX_INV;
+ case VCS2:
+ return GEN12_VD2_AUX_INV;
+ case VECS0:
+ return GEN12_VE0_AUX_INV;
+ case CCS0:
+ return GEN12_CCS0_AUX_INV;
+ default:
+ return INVALID_MMIO_REG;
+ }
+}
+
+static bool gen12_needs_ccs_aux_inv(struct intel_engine_cs *engine)
+{
+ i915_reg_t reg = gen12_get_aux_inv_reg(engine);
+
+ if (IS_PONTEVECCHIO(engine->i915))
+ return false;
+
+ /*
+ * So far platforms supported by i915 having flat ccs do not require
+ * AUX invalidation. Check also whether the engine requires it.
+ */
+ return i915_mmio_reg_valid(reg) && !HAS_FLAT_CCS(engine->i915);
+}
+
+u32 *gen12_emit_aux_table_inv(struct intel_engine_cs *engine, u32 *cs)
+{
+ i915_reg_t inv_reg = gen12_get_aux_inv_reg(engine);
+ u32 gsi_offset = engine->gt->uncore->gsi_offset;
+
+ if (!gen12_needs_ccs_aux_inv(engine))
+ return cs;
*cs++ = MI_LOAD_REGISTER_IMM(1) | MI_LRI_MMIO_REMAP_EN;
*cs++ = i915_mmio_reg_offset(inv_reg) + gsi_offset;
*cs++ = AUX_INV;
- *cs++ = MI_NOOP;
+
+ *cs++ = MI_SEMAPHORE_WAIT_TOKEN |
+ MI_SEMAPHORE_REGISTER_POLL |
+ MI_SEMAPHORE_POLL |
+ MI_SEMAPHORE_SAD_EQ_SDD;
+ *cs++ = 0;
+ *cs++ = i915_mmio_reg_offset(inv_reg) + gsi_offset;
+ *cs++ = 0;
+ *cs++ = 0;
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;
+ /*
+ * On Aux CCS platforms the invalidation of the Aux
+ * table requires quiescing memory traffic beforehand
+ */
+ if (mode & EMIT_FLUSH || gen12_needs_ccs_aux_inv(engine)) {
+ u32 bit_group_0 = 0;
+ u32 bit_group_1 = 0;
+ int err;
u32 *cs;
- flags |= PIPE_CONTROL_TILE_CACHE_FLUSH;
- flags |= PIPE_CONTROL_FLUSH_L3;
- flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
- flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+ err = mtl_dummy_pipe_control(rq);
+ if (err)
+ return err;
+
+ bit_group_0 |= PIPE_CONTROL0_HDC_PIPELINE_FLUSH;
+
+ /*
+ * When required, in MTL and beyond platforms we
+ * need to set the CCS_FLUSH bit in the pipe control
+ */
+ if (GRAPHICS_VER_FULL(rq->i915) >= IP_VER(12, 70))
+ bit_group_0 |= PIPE_CONTROL_CCS_FLUSH;
+
+ bit_group_1 |= PIPE_CONTROL_TILE_CACHE_FLUSH;
+ bit_group_1 |= PIPE_CONTROL_FLUSH_L3;
+ bit_group_1 |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
+ bit_group_1 |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
/* Wa_1409600907:tgl,adl-p */
- flags |= PIPE_CONTROL_DEPTH_STALL;
- flags |= PIPE_CONTROL_DC_FLUSH_ENABLE;
- flags |= PIPE_CONTROL_FLUSH_ENABLE;
+ bit_group_1 |= PIPE_CONTROL_DEPTH_STALL;
+ bit_group_1 |= PIPE_CONTROL_DC_FLUSH_ENABLE;
+ bit_group_1 |= PIPE_CONTROL_FLUSH_ENABLE;
- flags |= PIPE_CONTROL_STORE_DATA_INDEX;
- flags |= PIPE_CONTROL_QW_WRITE;
+ bit_group_1 |= PIPE_CONTROL_STORE_DATA_INDEX;
+ bit_group_1 |= PIPE_CONTROL_QW_WRITE;
- flags |= PIPE_CONTROL_CS_STALL;
+ bit_group_1 |= PIPE_CONTROL_CS_STALL;
if (!HAS_3D_PIPELINE(engine->i915))
- flags &= ~PIPE_CONTROL_3D_ARCH_FLAGS;
+ bit_group_1 &= ~PIPE_CONTROL_3D_ARCH_FLAGS;
else if (engine->class == COMPUTE_CLASS)
- flags &= ~PIPE_CONTROL_3D_ENGINE_FLAGS;
+ bit_group_1 &= ~PIPE_CONTROL_3D_ENGINE_FLAGS;
cs = intel_ring_begin(rq, 6);
if (IS_ERR(cs))
return PTR_ERR(cs);
- cs = gen12_emit_pipe_control(cs,
- PIPE_CONTROL0_HDC_PIPELINE_FLUSH,
- flags, LRC_PPHWSP_SCRATCH_ADDR);
+ cs = gen12_emit_pipe_control(cs, bit_group_0, bit_group_1,
+ LRC_PPHWSP_SCRATCH_ADDR);
intel_ring_advance(rq, cs);
}
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;
@@ -236,10 +326,9 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode)
else if (engine->class == COMPUTE_CLASS)
flags &= ~PIPE_CONTROL_3D_ENGINE_FLAGS;
- if (!HAS_FLAT_CCS(rq->engine->i915))
- count = 8 + 4;
- else
- count = 8;
+ count = 8;
+ if (gen12_needs_ccs_aux_inv(rq->engine))
+ count += 8;
cs = intel_ring_begin(rq, count);
if (IS_ERR(cs))
@@ -254,11 +343,7 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode)
cs = gen8_emit_pipe_control(cs, flags, LRC_PPHWSP_SCRATCH_ADDR);
- if (!HAS_FLAT_CCS(rq->engine->i915)) {
- /* hsdes: 1809175790 */
- cs = gen12_emit_aux_table_inv(rq->engine->gt,
- cs, GEN12_GFX_CCS_AUX_NV);
- }
+ cs = gen12_emit_aux_table_inv(engine, cs);
*cs++ = preparser_disable(false);
intel_ring_advance(rq, cs);
@@ -269,21 +354,14 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode)
int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode)
{
- intel_engine_mask_t aux_inv = 0;
- u32 cmd, *cs;
+ u32 cmd = 4;
+ u32 *cs;
- cmd = 4;
if (mode & EMIT_INVALIDATE) {
cmd += 2;
- if (!HAS_FLAT_CCS(rq->engine->i915) &&
- (rq->engine->class == VIDEO_DECODE_CLASS ||
- rq->engine->class == VIDEO_ENHANCEMENT_CLASS)) {
- aux_inv = rq->engine->mask &
- ~GENMASK(_BCS(I915_MAX_BCS - 1), BCS0);
- if (aux_inv)
- cmd += 4;
- }
+ if (gen12_needs_ccs_aux_inv(rq->engine))
+ cmd += 8;
}
cs = intel_ring_begin(rq, cmd);
@@ -307,6 +385,10 @@ int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode)
cmd |= MI_INVALIDATE_TLB;
if (rq->engine->class == VIDEO_DECODE_CLASS)
cmd |= MI_INVALIDATE_BSD;
+
+ if (gen12_needs_ccs_aux_inv(rq->engine) &&
+ rq->engine->class == COPY_ENGINE_CLASS)
+ cmd |= MI_FLUSH_DW_CCS;
}
*cs++ = cmd;
@@ -314,14 +396,7 @@ int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode)
*cs++ = 0; /* upper addr */
*cs++ = 0; /* value */
- if (aux_inv) { /* hsdes: 1809175790 */
- if (rq->engine->class == VIDEO_DECODE_CLASS)
- cs = gen12_emit_aux_table_inv(rq->engine->gt,
- cs, GEN12_VD0_AUX_NV);
- else
- cs = gen12_emit_aux_table_inv(rq->engine->gt,
- cs, GEN12_VE0_AUX_NV);
- }
+ cs = gen12_emit_aux_table_inv(rq->engine, cs);
if (mode & EMIT_INVALIDATE)
*cs++ = preparser_disable(false);
@@ -733,6 +808,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_engine_cs.h b/drivers/gpu/drm/i915/gt/gen8_engine_cs.h
index 655e5c00ddc2..867ba697aceb 100644
--- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.h
+++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.h
@@ -13,6 +13,7 @@
#include "intel_gt_regs.h"
#include "intel_gpu_commands.h"
+struct intel_engine_cs;
struct intel_gt;
struct i915_request;
@@ -46,28 +47,32 @@ u32 *gen8_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs);
u32 *gen11_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs);
u32 *gen12_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs);
-u32 *gen12_emit_aux_table_inv(struct intel_gt *gt, u32 *cs, const i915_reg_t inv_reg);
+u32 *gen12_emit_aux_table_inv(struct intel_engine_cs *engine, u32 *cs);
static inline u32 *
-__gen8_emit_pipe_control(u32 *batch, u32 flags0, u32 flags1, u32 offset)
+__gen8_emit_pipe_control(u32 *batch, u32 bit_group_0,
+ u32 bit_group_1, u32 offset)
{
memset(batch, 0, 6 * sizeof(u32));
- batch[0] = GFX_OP_PIPE_CONTROL(6) | flags0;
- batch[1] = flags1;
+ batch[0] = GFX_OP_PIPE_CONTROL(6) | bit_group_0;
+ batch[1] = bit_group_1;
batch[2] = offset;
return batch + 6;
}
-static inline u32 *gen8_emit_pipe_control(u32 *batch, u32 flags, u32 offset)
+static inline u32 *gen8_emit_pipe_control(u32 *batch,
+ u32 bit_group_1, u32 offset)
{
- return __gen8_emit_pipe_control(batch, 0, flags, offset);
+ return __gen8_emit_pipe_control(batch, 0, bit_group_1, offset);
}
-static inline u32 *gen12_emit_pipe_control(u32 *batch, u32 flags0, u32 flags1, u32 offset)
+static inline u32 *gen12_emit_pipe_control(u32 *batch, u32 bit_group_0,
+ u32 bit_group_1, u32 offset)
{
- return __gen8_emit_pipe_control(batch, flags0, flags1, offset);
+ return __gen8_emit_pipe_control(batch, bit_group_0,
+ bit_group_1, offset);
}
static inline u32 *
diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
index 4daaa6f55668..c8568e5d1147 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;
@@ -37,10 +37,12 @@ static u64 gen8_pte_encode(dma_addr_t addr,
if (unlikely(flags & PTE_READ_ONLY))
pte &= ~GEN8_PAGE_RW;
- 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 +57,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 +452,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 +499,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 +599,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 +607,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 +730,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 +749,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 +759,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 +773,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 +803,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 +850,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 +995,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_gpu_commands.h b/drivers/gpu/drm/i915/gt/intel_gpu_commands.h
index 5d143e2a8db0..2bd8d98d2110 100644
--- a/drivers/gpu/drm/i915/gt/intel_gpu_commands.h
+++ b/drivers/gpu/drm/i915/gt/intel_gpu_commands.h
@@ -121,6 +121,7 @@
#define MI_SEMAPHORE_TARGET(engine) ((engine)<<15)
#define MI_SEMAPHORE_WAIT MI_INSTR(0x1c, 2) /* GEN8+ */
#define MI_SEMAPHORE_WAIT_TOKEN MI_INSTR(0x1c, 3) /* GEN12+ */
+#define MI_SEMAPHORE_REGISTER_POLL (1 << 16)
#define MI_SEMAPHORE_POLL (1 << 15)
#define MI_SEMAPHORE_SAD_GT_SDD (0 << 12)
#define MI_SEMAPHORE_SAD_GTE_SDD (1 << 12)
@@ -299,6 +300,7 @@
#define PIPE_CONTROL_QW_WRITE (1<<14)
#define PIPE_CONTROL_POST_SYNC_OP_MASK (3<<14)
#define PIPE_CONTROL_DEPTH_STALL (1<<13)
+#define PIPE_CONTROL_CCS_FLUSH (1<<13) /* MTL+ */
#define PIPE_CONTROL_WRITE_FLUSH (1<<12)
#define PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH (1<<12) /* gen6+ */
#define PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE (1<<11) /* MBZ on ILK */
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..2cdfb2f713d0 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
@@ -331,9 +332,11 @@
#define GEN8_PRIVATE_PAT_HI _MMIO(0x40e0 + 4)
#define GEN10_PAT_INDEX(index) _MMIO(0x40e0 + (index) * 4)
#define BSD_HWS_PGA_GEN7 _MMIO(0x4180)
-#define GEN12_GFX_CCS_AUX_NV _MMIO(0x4208)
-#define GEN12_VD0_AUX_NV _MMIO(0x4218)
-#define GEN12_VD1_AUX_NV _MMIO(0x4228)
+
+#define GEN12_CCS_AUX_INV _MMIO(0x4208)
+#define GEN12_VD0_AUX_INV _MMIO(0x4218)
+#define GEN12_VE0_AUX_INV _MMIO(0x4238)
+#define GEN12_BCS0_AUX_INV _MMIO(0x4248)
#define GEN8_RTCR _MMIO(0x4260)
#define GEN8_M1TCR _MMIO(0x4264)
@@ -341,14 +344,12 @@
#define GEN8_BTCR _MMIO(0x426c)
#define GEN8_VTCR _MMIO(0x4270)
-#define GEN12_VD2_AUX_NV _MMIO(0x4298)
-#define GEN12_VD3_AUX_NV _MMIO(0x42a8)
-#define GEN12_VE0_AUX_NV _MMIO(0x4238)
-
#define BLT_HWS_PGA_GEN7 _MMIO(0x4280)
-#define GEN12_VE1_AUX_NV _MMIO(0x42b8)
+#define GEN12_VD2_AUX_INV _MMIO(0x4298)
+#define GEN12_CCS0_AUX_INV _MMIO(0x42c8)
#define AUX_INV REG_BIT(0)
+
#define VEBOX_HWS_PGA_GEN7 _MMIO(0x4380)
#define GEN12_AUX_ERR_DBG _MMIO(0x43f4)
@@ -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..731d9f2bbc56 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);
@@ -625,7 +670,7 @@ __vm_create_scratch_for_read(struct i915_address_space *vm, unsigned long size)
if (IS_ERR(obj))
return ERR_CAST(obj);
- i915_gem_object_set_cache_coherency(obj, I915_CACHING_CACHED);
+ i915_gem_object_set_cache_coherency(obj, I915_CACHE_LLC);
vma = i915_vma_instance(obj, vm, NULL);
if (IS_ERR(vma)) {
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..9477c2422321 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -1364,13 +1364,12 @@ gen12_emit_indirect_ctx_rcs(const struct intel_context *ce, u32 *cs)
IS_DG2_G11(ce->engine->i915))
cs = gen8_emit_pipe_control(cs, PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE, 0);
- /* hsdes: 1809175790 */
- if (!HAS_FLAT_CCS(ce->engine->i915))
- cs = gen12_emit_aux_table_inv(ce->engine->gt,
- cs, GEN12_GFX_CCS_AUX_NV);
+ cs = gen12_emit_aux_table_inv(ce->engine, cs);
/* 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;
@@ -1390,17 +1389,7 @@ gen12_emit_indirect_ctx_xcs(const struct intel_context *ce, u32 *cs)
PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE,
0);
- /* hsdes: 1809175790 */
- if (!HAS_FLAT_CCS(ce->engine->i915)) {
- if (ce->engine->class == VIDEO_DECODE_CLASS)
- cs = gen12_emit_aux_table_inv(ce->engine->gt,
- cs, GEN12_VD0_AUX_NV);
- else if (ce->engine->class == VIDEO_ENHANCEMENT_CLASS)
- cs = gen12_emit_aux_table_inv(ce->engine->gt,
- cs, GEN12_VE0_AUX_NV);
- }
-
- return cs;
+ return gen12_emit_aux_table_inv(ce->engine, cs);
}
static void
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..477df260ae3a 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,36 @@ 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;
+
+ /* Set min to RPn when we disable efficient freq */
+ if (val)
+ ret = slpc_set_param(slpc,
+ SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
+ slpc->min_freq);
+ }
+
+ 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 +513,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 +520,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);
@@ -589,11 +609,10 @@ static int slpc_set_softlimits(struct intel_guc_slpc *slpc)
return ret;
if (!slpc->min_freq_softlimit) {
- ret = intel_guc_slpc_get_min_freq(slpc, &slpc->min_freq_softlimit);
- if (unlikely(ret))
- return ret;
+ /* Min softlimit is initialized to RPn */
+ slpc->min_freq_softlimit = slpc->min_freq;
slpc_to_gt(slpc)->defaults.min_freq = slpc->min_freq_softlimit;
- } else if (slpc->min_freq_softlimit != slpc->min_freq) {
+ } else {
return intel_guc_slpc_set_min_freq(slpc,
slpc->min_freq_softlimit);
}
@@ -742,6 +761,9 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
return ret;
}
+ /* Set cached value of ignore efficient freq */
+ intel_guc_slpc_set_ignore_eff_freq(slpc, slpc->ignore_eff_freq);
+
/* Revert SLPC min/max to softlimits if necessary */
ret = slpc_set_softlimits(slpc);
if (unlikely(ret)) {
@@ -821,6 +843,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..fa70defcb5b2 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,25 @@
* 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 +118,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 +136,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 +279,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 +296,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 +320,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;
}
- huc_dbg(huc, "loaded by GSC = %s\n", str_yes_no(fw_needs_gsc));
+ /*
+ * 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(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 +419,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 +439,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 +485,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 +494,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.mask) == huc->status.value;
+ 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;
+
+ 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 +569,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 +588,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 +612,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 +648,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..af9afdb53c7f 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, value);
+
// 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.c b/drivers/gpu/drm/i915/i915_active.c
index 8ef93889061a..5ec293011d99 100644
--- a/drivers/gpu/drm/i915/i915_active.c
+++ b/drivers/gpu/drm/i915/i915_active.c
@@ -449,8 +449,11 @@ int i915_active_add_request(struct i915_active *ref, struct i915_request *rq)
}
} while (unlikely(is_barrier(active)));
- if (!__i915_active_fence_set(active, fence))
+ fence = __i915_active_fence_set(active, fence);
+ if (!fence)
__i915_active_acquire(ref);
+ else
+ dma_fence_put(fence);
out:
i915_active_release(ref);
@@ -469,13 +472,9 @@ __i915_active_set_fence(struct i915_active *ref,
return NULL;
}
- rcu_read_lock();
prev = __i915_active_fence_set(active, fence);
- if (prev)
- prev = dma_fence_get_rcu(prev);
- else
+ if (!prev)
__i915_active_acquire(ref);
- rcu_read_unlock();
return prev;
}
@@ -1019,10 +1018,11 @@ void i915_request_add_active_barriers(struct i915_request *rq)
*
* Records the new @fence as the last active fence along its timeline in
* this active tracker, moving the tracking callbacks from the previous
- * fence onto this one. Returns the previous fence (if not already completed),
- * which the caller must ensure is executed before the new fence. To ensure
- * that the order of fences within the timeline of the i915_active_fence is
- * understood, it should be locked by the caller.
+ * fence onto this one. Gets and returns a reference to the previous fence
+ * (if not already completed), which the caller must put after making sure
+ * that it is executed before the new fence. To ensure that the order of
+ * fences within the timeline of the i915_active_fence is understood, it
+ * should be locked by the caller.
*/
struct dma_fence *
__i915_active_fence_set(struct i915_active_fence *active,
@@ -1031,7 +1031,23 @@ __i915_active_fence_set(struct i915_active_fence *active,
struct dma_fence *prev;
unsigned long flags;
- if (fence == rcu_access_pointer(active->fence))
+ /*
+ * In case of fences embedded in i915_requests, their memory is
+ * SLAB_FAILSAFE_BY_RCU, then it can be reused right after release
+ * by new requests. Then, there is a risk of passing back a pointer
+ * to a new, completely unrelated fence that reuses the same memory
+ * while tracked under a different active tracker. Combined with i915
+ * perf open/close operations that build await dependencies between
+ * engine kernel context requests and user requests from different
+ * timelines, this can lead to dependency loops and infinite waits.
+ *
+ * As a countermeasure, we try to get a reference to the active->fence
+ * first, so if we succeed and pass it back to our user then it is not
+ * released and potentially reused by an unrelated request before the
+ * user has a chance to set up an await dependency on it.
+ */
+ prev = i915_active_fence_get(active);
+ if (fence == prev)
return fence;
GEM_BUG_ON(test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags));
@@ -1040,27 +1056,56 @@ __i915_active_fence_set(struct i915_active_fence *active,
* Consider that we have two threads arriving (A and B), with
* C already resident as the active->fence.
*
- * A does the xchg first, and so it sees C or NULL depending
- * on the timing of the interrupt handler. If it is NULL, the
- * previous fence must have been signaled and we know that
- * we are first on the timeline. If it is still present,
- * we acquire the lock on that fence and serialise with the interrupt
- * handler, in the process removing it from any future interrupt
- * callback. A will then wait on C before executing (if present).
- *
- * As B is second, it sees A as the previous fence and so waits for
- * it to complete its transition and takes over the occupancy for
- * itself -- remembering that it needs to wait on A before executing.
+ * Both A and B have got a reference to C or NULL, depending on the
+ * timing of the interrupt handler. Let's assume that if A has got C
+ * then it has locked C first (before B).
*
* Note the strong ordering of the timeline also provides consistent
* nesting rules for the fence->lock; the inner lock is always the
* older lock.
*/
spin_lock_irqsave(fence->lock, flags);
- prev = xchg(__active_fence_slot(active), fence);
- if (prev) {
- GEM_BUG_ON(prev == fence);
+ if (prev)
spin_lock_nested(prev->lock, SINGLE_DEPTH_NESTING);
+
+ /*
+ * A does the cmpxchg first, and so it sees C or NULL, as before, or
+ * something else, depending on the timing of other threads and/or
+ * interrupt handler. If not the same as before then A unlocks C if
+ * applicable and retries, starting from an attempt to get a new
+ * active->fence. Meanwhile, B follows the same path as A.
+ * Once A succeeds with cmpxch, B fails again, retires, gets A from
+ * active->fence, locks it as soon as A completes, and possibly
+ * succeeds with cmpxchg.
+ */
+ while (cmpxchg(__active_fence_slot(active), prev, fence) != prev) {
+ if (prev) {
+ spin_unlock(prev->lock);
+ dma_fence_put(prev);
+ }
+ spin_unlock_irqrestore(fence->lock, flags);
+
+ prev = i915_active_fence_get(active);
+ GEM_BUG_ON(prev == fence);
+
+ spin_lock_irqsave(fence->lock, flags);
+ if (prev)
+ spin_lock_nested(prev->lock, SINGLE_DEPTH_NESTING);
+ }
+
+ /*
+ * If prev is NULL then the previous fence must have been signaled
+ * and we know that we are first on the timeline. If it is still
+ * present then, having the lock on that fence already acquired, we
+ * serialise with the interrupt handler, in the process of removing it
+ * from any future interrupt callback. A will then wait on C before
+ * executing (if present).
+ *
+ * As B is second, it sees A as the previous fence and so waits for
+ * it to complete its transition and takes over the occupancy for
+ * itself -- remembering that it needs to wait on A before executing.
+ */
+ if (prev) {
__list_del_entry(&active->cb.node);
spin_unlock(prev->lock); /* serialise with prev->cb_list */
}
@@ -1077,11 +1122,7 @@ int i915_active_fence_set(struct i915_active_fence *active,
int err = 0;
/* Must maintain timeline ordering wrt previous active requests */
- rcu_read_lock();
fence = __i915_active_fence_set(active, &rq->fence);
- if (fence) /* but the previous fence may not belong to that timeline! */
- fence = dma_fence_get_rcu(fence);
- rcu_read_unlock();
if (fence) {
err = i915_request_await_dma_fence(rq, fence);
dma_fence_put(fence);
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..7d8671fdf447 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);
@@ -433,7 +443,6 @@ static int i915_pcode_init(struct drm_i915_private *i915)
static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
{
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
- struct pci_dev *root_pdev;
int ret;
if (i915_inject_probe_failure(dev_priv))
@@ -547,15 +556,6 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
intel_bw_init_hw(dev_priv);
- /*
- * FIXME: Temporary hammer to avoid freezing the machine on our DGFX
- * This should be totally removed when we handle the pci states properly
- * on runtime PM and on s2idle cases.
- */
- root_pdev = pcie_find_root_port(pdev);
- if (root_pdev)
- pci_d3cold_disable(root_pdev);
-
return 0;
err_opregion:
@@ -581,7 +581,6 @@ err_perf:
static void i915_driver_hw_remove(struct drm_i915_private *dev_priv)
{
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
- struct pci_dev *root_pdev;
i915_perf_fini(dev_priv);
@@ -589,10 +588,6 @@ static void i915_driver_hw_remove(struct drm_i915_private *dev_priv)
if (pdev->msi_enabled)
pci_disable_msi(pdev);
-
- root_pdev = pcie_find_root_port(pdev);
- if (root_pdev)
- pci_d3cold_enable(root_pdev);
}
/**
@@ -720,8 +715,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 +727,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 +739,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 +749,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 +781,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 +789,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 +799,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 +819,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 +842,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 +861,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 +957,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 +979,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 +1058,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 +1082,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 +1113,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 +1120,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 +1131,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 +1227,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 +1237,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))
@@ -1507,6 +1502,8 @@ static int intel_runtime_suspend(struct device *kdev)
{
struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
struct intel_runtime_pm *rpm = &dev_priv->runtime_pm;
+ struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
+ struct pci_dev *root_pdev;
struct intel_gt *gt;
int ret, i;
@@ -1558,6 +1555,15 @@ static int intel_runtime_suspend(struct device *kdev)
drm_err(&dev_priv->drm,
"Unclaimed access detected prior to suspending\n");
+ /*
+ * FIXME: Temporary hammer to avoid freezing the machine on our DGFX
+ * This should be totally removed when we handle the pci states properly
+ * on runtime PM.
+ */
+ root_pdev = pcie_find_root_port(pdev);
+ if (root_pdev)
+ pci_d3cold_disable(root_pdev);
+
rpm->suspended = true;
/*
@@ -1596,6 +1602,8 @@ static int intel_runtime_resume(struct device *kdev)
{
struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
struct intel_runtime_pm *rpm = &dev_priv->runtime_pm;
+ struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
+ struct pci_dev *root_pdev;
struct intel_gt *gt;
int ret, i;
@@ -1609,6 +1617,11 @@ static int intel_runtime_resume(struct device *kdev)
intel_opregion_notify_adapter(dev_priv, PCI_D0);
rpm->suspended = false;
+
+ root_pdev = pcie_find_root_port(pdev);
+ if (root_pdev)
+ pci_d3cold_enable(root_pdev);
+
if (intel_uncore_unclaimed_mmio(&dev_priv->uncore))
drm_dbg(&dev_priv->drm,
"Unclaimed access during suspend, bios?\n");
@@ -1706,7 +1719,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 +1819,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 f020c0086fbc..0c38bfb60c9a 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -187,64 +187,64 @@ i915_error_printer(struct drm_i915_error_state_buf *e)
}
/* single threaded page allocator with a reserved stash for emergencies */
-static void pool_fini(struct pagevec *pv)
+static void pool_fini(struct folio_batch *fbatch)
{
- pagevec_release(pv);
+ folio_batch_release(fbatch);
}
-static int pool_refill(struct pagevec *pv, gfp_t gfp)
+static int pool_refill(struct folio_batch *fbatch, gfp_t gfp)
{
- while (pagevec_space(pv)) {
- struct page *p;
+ while (folio_batch_space(fbatch)) {
+ struct folio *folio;
- p = alloc_page(gfp);
- if (!p)
+ folio = folio_alloc(gfp, 0);
+ if (!folio)
return -ENOMEM;
- pagevec_add(pv, p);
+ folio_batch_add(fbatch, folio);
}
return 0;
}
-static int pool_init(struct pagevec *pv, gfp_t gfp)
+static int pool_init(struct folio_batch *fbatch, gfp_t gfp)
{
int err;
- pagevec_init(pv);
+ folio_batch_init(fbatch);
- err = pool_refill(pv, gfp);
+ err = pool_refill(fbatch, gfp);
if (err)
- pool_fini(pv);
+ pool_fini(fbatch);
return err;
}
-static void *pool_alloc(struct pagevec *pv, gfp_t gfp)
+static void *pool_alloc(struct folio_batch *fbatch, gfp_t gfp)
{
- struct page *p;
+ struct folio *folio;
- p = alloc_page(gfp);
- if (!p && pagevec_count(pv))
- p = pv->pages[--pv->nr];
+ folio = folio_alloc(gfp, 0);
+ if (!folio && folio_batch_count(fbatch))
+ folio = fbatch->folios[--fbatch->nr];
- return p ? page_address(p) : NULL;
+ return folio ? folio_address(folio) : NULL;
}
-static void pool_free(struct pagevec *pv, void *addr)
+static void pool_free(struct folio_batch *fbatch, void *addr)
{
- struct page *p = virt_to_page(addr);
+ struct folio *folio = virt_to_folio(addr);
- if (pagevec_space(pv))
- pagevec_add(pv, p);
+ if (folio_batch_space(fbatch))
+ folio_batch_add(fbatch, folio);
else
- __free_page(p);
+ folio_put(folio);
}
#ifdef CONFIG_DRM_I915_COMPRESS_ERROR
struct i915_vma_compress {
- struct pagevec pool;
+ struct folio_batch pool;
struct z_stream_s zstream;
void *tmp;
};
@@ -381,7 +381,7 @@ static void err_compression_marker(struct drm_i915_error_state_buf *m)
#else
struct i915_vma_compress {
- struct pagevec pool;
+ struct folio_batch pool;
};
static bool compress_init(struct i915_vma_compress *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..928975d5fe2f 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"
@@ -39,128 +41,38 @@
#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 +86,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 +94,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 +109,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 +127,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 +159,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 +166,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 +174,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 +181,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 +194,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 +221,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 +236,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 +249,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 +264,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 +277,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 +316,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 +325,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 +366,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 +374,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 +457,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 +464,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 +484,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 +519,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 +533,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 +612,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 +640,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 +655,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 +672,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 +683,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 +708,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 +727,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 +741,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 +763,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 +771,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 +796,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 +818,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,11 +830,15 @@ 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
@@ -1362,7 +1048,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..49c6f1ff1128 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);
@@ -885,8 +868,17 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
oa_report_id_clear(stream, report32);
oa_timestamp_clear(stream, report32);
} else {
+ u8 *oa_buf_end = stream->oa_buffer.vaddr +
+ OA_BUFFER_SIZE;
+ u32 part = oa_buf_end - (u8 *)report32;
+
/* Zero out the entire report */
- memset(report32, 0, report_size);
+ if (report_size <= part) {
+ memset(report32, 0, report_size);
+ } else {
+ memset(report32, 0, part);
+ memset(oa_buf_base, 0, report_size - part);
+ }
}
}
@@ -1727,7 +1719,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 +1770,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 +1823,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;
/*
@@ -4442,6 +4431,7 @@ static const struct i915_range mtl_oam_b_counters[] = {
static const struct i915_range xehp_oa_b_counters[] = {
{ .start = 0xdc48, .end = 0xdc48 }, /* OAA_ENABLE_REG */
{ .start = 0xdd00, .end = 0xdd48 }, /* OAG_LCE0_0 - OAA_LENABLE_REG */
+ {}
};
static const struct i915_range gen7_oa_mux_regs[] = {
@@ -5305,6 +5295,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..833b73edefdb 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);
}
@@ -1661,6 +1661,11 @@ __i915_request_ensure_parallel_ordering(struct i915_request *rq,
request_to_parent(rq)->parallel.last_rq = i915_request_get(rq);
+ /*
+ * Users have to put a reference potentially got by
+ * __i915_active_fence_set() to the returned request
+ * when no longer needed
+ */
return to_request(__i915_active_fence_set(&timeline->last_request,
&rq->fence));
}
@@ -1707,6 +1712,10 @@ __i915_request_ensure_ordering(struct i915_request *rq,
0);
}
+ /*
+ * Users have to put the reference to prev potentially got
+ * by __i915_active_fence_set() when no longer needed
+ */
return prev;
}
@@ -1760,6 +1769,8 @@ __i915_request_add_to_timeline(struct i915_request *rq)
prev = __i915_request_ensure_ordering(rq, timeline);
else
prev = __i915_request_ensure_parallel_ordering(rq, timeline);
+ if (prev)
+ i915_request_put(prev);
/*
* Make sure that no request gazumped us - if it was allocated after
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..4de6a4e8280d 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);
@@ -117,6 +118,24 @@ static void mock_gt_probe(struct drm_i915_private *i915)
i915->gt[0]->name = "Mock GT";
}
+static const struct intel_device_info mock_info = {
+ .__runtime.graphics.ip.ver = -1,
+ .__runtime.page_sizes = (I915_GTT_PAGE_SIZE_4K |
+ I915_GTT_PAGE_SIZE_64K |
+ I915_GTT_PAGE_SIZE_2M),
+ .__runtime.memory_regions = REGION_SMEM,
+ .__runtime.platform_engine_mask = BIT(0),
+
+ /* simply use legacy cache level for mock device */
+ .max_pat_index = 3,
+ .cachelevel_to_pat = {
+ [I915_CACHE_NONE] = 0,
+ [I915_CACHE_LLC] = 1,
+ [I915_CACHE_L3_LLC] = 2,
+ [I915_CACHE_WT] = 3,
+ },
+};
+
struct drm_i915_private *mock_gem_device(void)
{
#if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU)
@@ -156,15 +175,18 @@ struct drm_i915_private *mock_gem_device(void)
pci_set_drvdata(pdev, i915);
+ /* Device parameters start as a copy of module parameters. */
+ i915_params_copy(&i915->params, &i915_modparams);
+
+ /* Set up device info and initial runtime info. */
+ intel_device_info_driver_create(i915, pdev->device, &mock_info);
+
dev_pm_domain_set(&pdev->dev, &pm_domain);
pm_runtime_enable(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
if (pm_runtime_enabled(&pdev->dev))
WARN_ON(pm_runtime_get_sync(&pdev->dev));
-
- i915_params_copy(&i915->params, &i915_modparams);
-
intel_runtime_pm_init_early(&i915->runtime_pm);
/* wakeref tracking has significant overhead */
i915->runtime_pm.no_wakeref_tracking = true;
@@ -172,14 +194,6 @@ struct drm_i915_private *mock_gem_device(void)
/* Using the global GTT may ask questions about KMS users, so prepare */
drm_mode_config_init(&i915->drm);
- RUNTIME_INFO(i915)->graphics.ip.ver = -1;
-
- RUNTIME_INFO(i915)->page_sizes =
- I915_GTT_PAGE_SIZE_4K |
- I915_GTT_PAGE_SIZE_64K |
- I915_GTT_PAGE_SIZE_2M;
-
- RUNTIME_INFO(i915)->memory_regions = REGION_SMEM;
intel_memory_regions_hw_probe(i915);
spin_lock_init(&i915->gpu_error.lock);
@@ -199,6 +213,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 */
@@ -209,7 +227,6 @@ struct drm_i915_private *mock_gem_device(void)
mock_init_ggtt(to_gt(i915));
to_gt(i915)->vm = i915_vm_get(&to_gt(i915)->ggtt->vm);
- RUNTIME_INFO(i915)->platform_engine_mask = BIT(0);
to_gt(i915)->info.engine_mask = BIT(0);
to_gt(i915)->engine[RCS0] = mock_engine(i915, "mock", RCS0);
@@ -230,6 +247,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/ipuv3/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c
index 5f26090b0c98..89585b31b985 100644
--- a/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c
+++ b/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c
@@ -310,7 +310,7 @@ static void ipu_crtc_mode_set_nofb(struct drm_crtc *crtc)
dev_warn(ipu_crtc->dev, "8-pixel align hactive %d -> %d\n",
sig_cfg.mode.hactive, new_hactive);
- sig_cfg.mode.hfront_porch = new_hactive - sig_cfg.mode.hactive;
+ sig_cfg.mode.hfront_porch -= new_hactive - sig_cfg.mode.hactive;
sig_cfg.mode.hactive = new_hactive;
}
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/mediatek/mtk_hdmi_ddc.c b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c
index 2fc9214ffa82..4d39ea0a05ca 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c
@@ -295,7 +295,7 @@ static int mtk_hdmi_ddc_probe(struct platform_device *pdev)
return ret;
}
- strlcpy(ddc->adap.name, "mediatek-hdmi-ddc", sizeof(ddc->adap.name));
+ strscpy(ddc->adap.name, "mediatek-hdmi-ddc", sizeof(ddc->adap.name));
ddc->adap.owner = THIS_MODULE;
ddc->adap.class = I2C_CLASS_DDC;
ddc->adap.algo = &mtk_hdmi_ddc_algorithm;
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..bbb1bf33f98e 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -89,7 +89,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit
* since we've already mapped it once in
* submit_reloc()
*/
- if (WARN_ON(!ptr))
+ if (WARN_ON(IS_ERR_OR_NULL(ptr)))
return;
for (i = 0; i < dwords; i++) {
@@ -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_gpu_state.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h
index 790f55e24533..e788ed72eb0d 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h
@@ -206,7 +206,7 @@ static const struct a6xx_shader_block {
SHADER(A6XX_SP_LB_3_DATA, 0x800),
SHADER(A6XX_SP_LB_4_DATA, 0x800),
SHADER(A6XX_SP_LB_5_DATA, 0x200),
- SHADER(A6XX_SP_CB_BINDLESS_DATA, 0x2000),
+ SHADER(A6XX_SP_CB_BINDLESS_DATA, 0x800),
SHADER(A6XX_SP_CB_LEGACY_DATA, 0x280),
SHADER(A6XX_SP_UAV_DATA, 0x80),
SHADER(A6XX_SP_INST_TAG, 0x80),
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..ce8d0b2475bf 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,18 @@ 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),
+ .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 +575,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 +586,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..845019891ad1 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,198 @@ 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)
{
+ /* revn can be zero, but if not is set at same time as info */
+ WARN_ON_ONCE(!gpu->info);
+
+ 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)
+{
+ /* revn can be zero, but if not is set at same time as info */
+ WARN_ON_ONCE(!gpu->info);
+
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)
{
+ /* revn can be zero, but if not is set at same time as info */
+ WARN_ON_ONCE(!gpu->info);
+
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)
+{
+ /* The order of args is important here to handle ANY_ID correctly */
+ return adreno_cmp_rev(ADRENO_REV(6, 9, 0, ANY_ID), gpu->rev);
+};
+
/* 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_core_perf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
index e3795995e145..29bb8ee2bc26 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
@@ -15,19 +15,6 @@
#define DPU_PERF_DEFAULT_MAX_CORE_CLK_RATE 412500000
/**
- * enum dpu_core_perf_data_bus_id - data bus identifier
- * @DPU_CORE_PERF_DATA_BUS_ID_MNOC: DPU/MNOC data bus
- * @DPU_CORE_PERF_DATA_BUS_ID_LLCC: MNOC/LLCC data bus
- * @DPU_CORE_PERF_DATA_BUS_ID_EBI: LLCC/EBI data bus
- */
-enum dpu_core_perf_data_bus_id {
- DPU_CORE_PERF_DATA_BUS_ID_MNOC,
- DPU_CORE_PERF_DATA_BUS_ID_LLCC,
- DPU_CORE_PERF_DATA_BUS_ID_EBI,
- DPU_CORE_PERF_DATA_BUS_ID_MAX,
-};
-
-/**
* struct dpu_core_perf_params - definition of performance parameters
* @max_per_pipe_ib: maximum instantaneous bandwidth request
* @bw_ctl: arbitrated bandwidth request
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..86182c734606 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -51,24 +51,7 @@
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);
-}
+ 1, 2, 3, 4, 5};
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);
}
@@ -206,6 +198,12 @@ static void dpu_hw_ctl_update_pending_flush_sspp(struct dpu_hw_ctl *ctx,
case SSPP_DMA3:
ctx->pending_flush_mask |= BIT(25);
break;
+ case SSPP_DMA4:
+ ctx->pending_flush_mask |= BIT(13);
+ break;
+ case SSPP_DMA5:
+ ctx->pending_flush_mask |= BIT(14);
+ break;
case SSPP_CURSOR0:
ctx->pending_flush_mask |= BIT(22);
break;
@@ -302,6 +300,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 +335,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 +518,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 +537,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 +582,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 +612,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 +649,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 +680,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..31deda1c664a 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);
@@ -1084,8 +1087,6 @@ const struct msm_dsi_phy_cfg dsi_phy_14nm_8953_cfgs = {
const struct msm_dsi_phy_cfg dsi_phy_14nm_2290_cfgs = {
.has_phy_lane = true,
- .regulator_data = dsi_phy_14nm_17mA_regulators,
- .num_regulators = ARRAY_SIZE(dsi_phy_14nm_17mA_regulators),
.ops = {
.enable = dsi_14nm_phy_enable,
.disable = dsi_14nm_phy_disable,
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..bf1e17dc4550 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,
};
/*
@@ -227,10 +246,6 @@ void msm_fbdev_setup(struct drm_device *dev)
goto err_drm_fb_helper_unprepare;
}
- ret = msm_fbdev_client_hotplug(&helper->client);
- if (ret)
- drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
-
drm_client_register(&helper->client);
return;
diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c
index 96599ec3eb78..1a5d4f1c8b42 100644
--- a/drivers/gpu/drm/msm/msm_fence.c
+++ b/drivers/gpu/drm/msm/msm_fence.c
@@ -191,6 +191,12 @@ msm_fence_init(struct dma_fence *fence, struct msm_fence_context *fctx)
f->fctx = fctx;
+ /*
+ * Until this point, the fence was just some pre-allocated memory,
+ * no-one should have taken a reference to it yet.
+ */
+ WARN_ON(kref_read(&fence->refcount));
+
dma_fence_init(&f->base, &msm_fence_ops, &fctx->spinlock,
fctx->context, ++fctx->last_fence);
}
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..63c96416e183 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -86,7 +86,19 @@ void __msm_gem_submit_destroy(struct kref *kref)
}
dma_fence_put(submit->user_fence);
- dma_fence_put(submit->hw_fence);
+
+ /*
+ * If the submit is freed before msm_job_run(), then hw_fence is
+ * just some pre-allocated memory, not a reference counted fence.
+ * Once the job runs and the hw_fence is initialized, it will
+ * have a refcount of at least one, since the submit holds a ref
+ * to the hw_fence.
+ */
+ if (kref_read(&submit->hw_fence->refcount) == 0) {
+ kfree(submit->hw_fence);
+ } else {
+ dma_fence_put(submit->hw_fence);
+ }
put_pid(submit->pid);
msm_submitqueue_put(submit->queue);
@@ -558,8 +570,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 +819,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;
@@ -890,7 +901,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
* after the job is armed
*/
if ((args->flags & MSM_SUBMIT_FENCE_SN_IN) &&
- idr_find(&queue->fence_idr, args->fence)) {
+ (!args->fence || idr_find(&queue->fence_idr, args->fence))) {
spin_unlock(&queue->idr_lock);
idr_preload_end();
ret = -EINVAL;
@@ -949,6 +960,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..798bd4f3b662 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -189,6 +189,7 @@ static int _msm_mdss_irq_domain_add(struct msm_mdss *msm_mdss)
#define UBWC_2_0 0x20000000
#define UBWC_3_0 0x30000000
#define UBWC_4_0 0x40000000
+#define UBWC_4_3 0x40030000
static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss)
{
@@ -227,7 +228,10 @@ static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss)
writel_relaxed(1, msm_mdss->mmio + UBWC_CTRL_2);
writel_relaxed(0, msm_mdss->mmio + UBWC_PREDICTION_MODE);
} else {
- writel_relaxed(2, msm_mdss->mmio + UBWC_CTRL_2);
+ if (data->ubwc_dec_version == UBWC_4_3)
+ writel_relaxed(3, msm_mdss->mmio + UBWC_CTRL_2);
+ else
+ writel_relaxed(2, msm_mdss->mmio + UBWC_CTRL_2);
writel_relaxed(1, msm_mdss->mmio + UBWC_PREDICTION_MODE);
}
}
@@ -271,6 +275,7 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss)
msm_mdss_setup_ubwc_dec_30(msm_mdss);
break;
case UBWC_4_0:
+ case UBWC_4_3:
msm_mdss_setup_ubwc_dec_40(msm_mdss);
break;
default:
@@ -538,6 +543,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,
@@ -561,6 +574,16 @@ static const struct msm_mdss_data sm8250_data = {
.macrotile_mode = 1,
};
+static const struct msm_mdss_data sm8550_data = {
+ .ubwc_version = UBWC_4_0,
+ .ubwc_dec_version = UBWC_4_3,
+ .ubwc_swizzle = 6,
+ .ubwc_static = 1,
+ /* TODO: highest_bank_bit = 2 for LP_DDR4 */
+ .highest_bank_bit = 3,
+ .macrotile_mode = 1,
+};
+
static const struct of_device_id mdss_dt_match[] = {
{ .compatible = "qcom,mdss" },
{ .compatible = "qcom,msm8998-mdss" },
@@ -571,11 +594,13 @@ 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 },
{ .compatible = "qcom,sm8450-mdss", .data = &sm8250_data },
- { .compatible = "qcom,sm8550-mdss", .data = &sm8250_data },
+ { .compatible = "qcom,sm8550-mdss", .data = &sm8550_data },
{}
};
MODULE_DEVICE_TABLE(of, mdss_dt_match);
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..1bec819da876 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>
@@ -909,15 +910,19 @@ nv50_msto_prepare(struct drm_atomic_state *state,
struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev);
struct nv50_mstc *mstc = msto->mstc;
struct nv50_mstm *mstm = mstc->mstm;
- struct drm_dp_mst_atomic_payload *payload;
+ struct drm_dp_mst_topology_state *old_mst_state;
+ struct drm_dp_mst_atomic_payload *payload, *old_payload;
NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name);
+ old_mst_state = drm_atomic_get_old_mst_topology_state(state, mgr);
+
payload = drm_atomic_get_mst_payload_state(mst_state, mstc->port);
+ old_payload = drm_atomic_get_mst_payload_state(old_mst_state, mstc->port);
// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
if (msto->disabled) {
- drm_dp_remove_payload(mgr, mst_state, payload, payload);
+ drm_dp_remove_payload(mgr, mst_state, old_payload, payload);
nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
} else {
@@ -1358,22 +1363,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)
@@ -1868,6 +1877,8 @@ nv50_pior_destroy(struct drm_encoder *encoder)
nvif_outp_dtor(&nv_encoder->outp);
drm_encoder_cleanup(encoder);
+
+ mutex_destroy(&nv_encoder->dp.hpd_irq_lock);
kfree(encoder);
}
@@ -1912,6 +1923,8 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
nv_encoder->i2c = ddc;
nv_encoder->aux = aux;
+ mutex_init(&nv_encoder->dp.hpd_irq_lock);
+
encoder = to_drm_encoder(nv_encoder);
encoder->possible_crtcs = dcbe->heads;
encoder->possible_clones = 0;
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h
index 40a1065ae626..ef441dfdea09 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h
@@ -16,7 +16,7 @@ struct nvkm_i2c_bus {
const struct nvkm_i2c_bus_func *func;
struct nvkm_i2c_pad *pad;
#define NVKM_I2C_BUS_CCB(n) /* 'n' is ccb index */ (n)
-#define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100)
+#define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x10)
#define NVKM_I2C_BUS_PRI /* ccb primary comm. port */ -1
#define NVKM_I2C_BUS_SEC /* ccb secondary comm. port */ -2
int id;
@@ -38,7 +38,7 @@ struct nvkm_i2c_aux {
const struct nvkm_i2c_aux_func *func;
struct nvkm_i2c_pad *pad;
#define NVKM_I2C_AUX_CCB(n) /* 'n' is ccb index */ (n)
-#define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100)
+#define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x10)
int id;
struct mutex mutex;
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c
index e648ecd0c1a0..3dfbc374478e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.c
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.c
@@ -90,6 +90,7 @@ nouveau_channel_del(struct nouveau_channel **pchan)
if (cli)
nouveau_svmm_part(chan->vmm->svmm, chan->inst);
+ nvif_object_dtor(&chan->blit);
nvif_object_dtor(&chan->nvsw);
nvif_object_dtor(&chan->gart);
nvif_object_dtor(&chan->vram);
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h
index e06a8ffed31a..bad7466bd0d5 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.h
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.h
@@ -53,6 +53,7 @@ struct nouveau_channel {
u32 user_put;
struct nvif_object user;
+ struct nvif_object blit;
struct nvif_event kill;
atomic_t killed;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index f75c6f09dd2a..622f6eb9a8bf 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -967,7 +967,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
/* Determine display colour depth for everything except LVDS now,
* DP requires this before mode_valid() is called.
*/
- if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && nv_connector->native_mode)
+ if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS)
nouveau_connector_detect_depth(connector);
/* Find the native mode if this is a digital panel, if we didn't
@@ -1408,8 +1408,7 @@ nouveau_connector_create(struct drm_device *dev,
ret = nvif_conn_ctor(&disp->disp, nv_connector->base.name, nv_connector->index,
&nv_connector->conn);
if (ret) {
- kfree(nv_connector);
- return ERR_PTR(ret);
+ goto drm_conn_err;
}
ret = nvif_conn_event_ctor(&nv_connector->conn, "kmsHotplug",
@@ -1426,8 +1425,7 @@ nouveau_connector_create(struct drm_device *dev,
if (ret) {
nvif_event_dtor(&nv_connector->hpd);
nvif_conn_dtor(&nv_connector->conn);
- kfree(nv_connector);
- return ERR_PTR(ret);
+ goto drm_conn_err;
}
}
}
@@ -1475,4 +1473,9 @@ nouveau_connector_create(struct drm_device *dev,
drm_connector_register(connector);
return connector;
+
+drm_conn_err:
+ drm_connector_cleanup(connector);
+ kfree(nv_connector);
+ return ERR_PTR(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_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 7aac9384600e..40fb9a834918 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -375,15 +375,29 @@ nouveau_accel_gr_init(struct nouveau_drm *drm)
ret = nvif_object_ctor(&drm->channel->user, "drmNvsw",
NVDRM_NVSW, nouveau_abi16_swclass(drm),
NULL, 0, &drm->channel->nvsw);
+
+ if (ret == 0 && device->info.chipset >= 0x11) {
+ ret = nvif_object_ctor(&drm->channel->user, "drmBlit",
+ 0x005f, 0x009f,
+ NULL, 0, &drm->channel->blit);
+ }
+
if (ret == 0) {
struct nvif_push *push = drm->channel->chan.push;
- ret = PUSH_WAIT(push, 2);
- if (ret == 0)
+ ret = PUSH_WAIT(push, 8);
+ if (ret == 0) {
+ if (device->info.chipset >= 0x11) {
+ PUSH_NVSQ(push, NV05F, 0x0000, drm->channel->blit.handle);
+ PUSH_NVSQ(push, NV09F, 0x0120, 0,
+ 0x0124, 1,
+ 0x0128, 2);
+ }
PUSH_NVSQ(push, NV_SW, 0x0000, drm->channel->nvsw.handle);
+ }
}
if (ret) {
- NV_ERROR(drm, "failed to allocate sw class, %d\n", ret);
+ NV_ERROR(drm, "failed to allocate sw or blit class, %d\n", ret);
nouveau_accel_gr_fini(drm);
return;
}
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/engine/disp/dp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
index 40c8ea43c42f..b8ac66b4a2c4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
@@ -26,6 +26,8 @@
#include "head.h"
#include "ior.h"
+#include <drm/display/drm_dp.h>
+
#include <subdev/bios.h>
#include <subdev/bios/init.h>
#include <subdev/gpio.h>
@@ -634,6 +636,50 @@ nvkm_dp_enable_supported_link_rates(struct nvkm_outp *outp)
return outp->dp.rates != 0;
}
+/* XXX: This is a big fat hack, and this is just drm_dp_read_dpcd_caps()
+ * converted to work inside nvkm. This is a temporary holdover until we start
+ * passing the drm_dp_aux device through NVKM
+ */
+static int
+nvkm_dp_read_dpcd_caps(struct nvkm_outp *outp)
+{
+ struct nvkm_i2c_aux *aux = outp->dp.aux;
+ u8 dpcd_ext[DP_RECEIVER_CAP_SIZE];
+ int ret;
+
+ ret = nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, DP_RECEIVER_CAP_SIZE);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Prior to DP1.3 the bit represented by
+ * DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved.
+ * If it is set DP_DPCD_REV at 0000h could be at a value less than
+ * the true capability of the panel. The only way to check is to
+ * then compare 0000h and 2200h.
+ */
+ if (!(outp->dp.dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
+ DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT))
+ return 0;
+
+ ret = nvkm_rdaux(aux, DP_DP13_DPCD_REV, dpcd_ext, sizeof(dpcd_ext));
+ if (ret < 0)
+ return ret;
+
+ if (outp->dp.dpcd[DP_DPCD_REV] > dpcd_ext[DP_DPCD_REV]) {
+ OUTP_DBG(outp, "Extended DPCD rev less than base DPCD rev (%d > %d)\n",
+ outp->dp.dpcd[DP_DPCD_REV], dpcd_ext[DP_DPCD_REV]);
+ return 0;
+ }
+
+ if (!memcmp(outp->dp.dpcd, dpcd_ext, sizeof(dpcd_ext)))
+ return 0;
+
+ memcpy(outp->dp.dpcd, dpcd_ext, sizeof(dpcd_ext));
+
+ return 0;
+}
+
void
nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr)
{
@@ -689,7 +735,7 @@ nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr)
memset(outp->dp.lttpr, 0x00, sizeof(outp->dp.lttpr));
}
- if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, sizeof(outp->dp.dpcd))) {
+ if (!nvkm_dp_read_dpcd_caps(outp)) {
const u8 rates[] = { 0x1e, 0x14, 0x0a, 0x06, 0 };
const u8 *rate;
int rate_max;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
index a4853c4e5ee3..67ef889a0c5f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
@@ -295,6 +295,7 @@ g94_sor = {
.clock = nv50_sor_clock,
.war_2 = g94_sor_war_2,
.war_3 = g94_sor_war_3,
+ .hdmi = &g84_sor_hdmi,
.dp = &g94_sor_dp,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c
index a2c7c6f83dcd..506ffbe7b842 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c
@@ -125,7 +125,7 @@ gt215_sor_hdmi_infoframe_avi(struct nvkm_ior *ior, int head, void *data, u32 siz
pack_hdmi_infoframe(&avi, data, size);
nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000);
- if (size)
+ if (!size)
return;
nvkm_wr32(device, 0x61c528 + soff, avi.header);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
index dad942be6679..46b057fe1412 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
@@ -81,20 +81,29 @@ nvkm_uconn_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_
return -ENOSYS;
list_for_each_entry(outp, &conn->disp->outps, head) {
- if (outp->info.connector == conn->index && outp->dp.aux) {
- if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_I2C_PLUG;
- if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_I2C_UNPLUG;
- if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ ) bits |= NVKM_I2C_IRQ;
+ if (outp->info.connector == conn->index)
+ break;
+ }
- return nvkm_uevent_add(uevent, &device->i2c->event, outp->dp.aux->id, bits,
- nvkm_uconn_uevent_aux);
- }
+ if (&outp->head == &conn->disp->outps)
+ return -EINVAL;
+
+ if (outp->dp.aux && !outp->info.location) {
+ if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_I2C_PLUG;
+ if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_I2C_UNPLUG;
+ if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ ) bits |= NVKM_I2C_IRQ;
+
+ return nvkm_uevent_add(uevent, &device->i2c->event, outp->dp.aux->id, bits,
+ nvkm_uconn_uevent_aux);
}
if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_GPIO_HI;
if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_GPIO_LO;
- if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ)
- return -EINVAL;
+ if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ) {
+ /* TODO: support DP IRQ on ANX9805 and remove this hack. */
+ if (!outp->info.location)
+ return -EINVAL;
+ }
return nvkm_uevent_add(uevent, &device->gpio->event, conn->info.hpd, bits,
nvkm_uconn_uevent_gpio);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
index 00dbeda7e346..de161e7a04aa 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
@@ -117,6 +117,7 @@ void gk104_grctx_generate_r418800(struct gf100_gr *);
extern const struct gf100_grctx_func gk110_grctx;
void gk110_grctx_generate_r419eb0(struct gf100_gr *);
+void gk110_grctx_generate_r419f78(struct gf100_gr *);
extern const struct gf100_grctx_func gk110b_grctx;
extern const struct gf100_grctx_func gk208_grctx;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
index 94233d0119df..52a234b1ef01 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
@@ -906,7 +906,9 @@ static void
gk104_grctx_generate_r419f78(struct gf100_gr *gr)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
- nvkm_mask(device, 0x419f78, 0x00000001, 0x00000000);
+
+ /* bit 3 set disables loads in fp helper invocations, we need it enabled */
+ nvkm_mask(device, 0x419f78, 0x00000009, 0x00000000);
}
void
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c
index 4391458e1fb2..3acdd9eeb74a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c
@@ -820,6 +820,15 @@ gk110_grctx_generate_r419eb0(struct gf100_gr *gr)
nvkm_mask(device, 0x419eb0, 0x00001000, 0x00001000);
}
+void
+gk110_grctx_generate_r419f78(struct gf100_gr *gr)
+{
+ struct nvkm_device *device = gr->base.engine.subdev.device;
+
+ /* bit 3 set disables loads in fp helper invocations, we need it enabled */
+ nvkm_mask(device, 0x419f78, 0x00000008, 0x00000000);
+}
+
const struct gf100_grctx_func
gk110_grctx = {
.main = gf100_grctx_generate_main,
@@ -854,4 +863,5 @@ gk110_grctx = {
.gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr,
.r418800 = gk104_grctx_generate_r418800,
.r419eb0 = gk110_grctx_generate_r419eb0,
+ .r419f78 = gk110_grctx_generate_r419f78,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c
index 7b9a34f9ec3c..5597e87624ac 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c
@@ -103,4 +103,5 @@ gk110b_grctx = {
.gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr,
.r418800 = gk104_grctx_generate_r418800,
.r419eb0 = gk110_grctx_generate_r419eb0,
+ .r419f78 = gk110_grctx_generate_r419f78,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c
index c78d07a8bb7d..612656496541 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c
@@ -568,4 +568,5 @@ gk208_grctx = {
.dist_skip_table = gf117_grctx_generate_dist_skip_table,
.gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr,
.r418800 = gk104_grctx_generate_r418800,
+ .r419f78 = gk110_grctx_generate_r419f78,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
index beac66eb2a80..9906974ac3f0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
@@ -988,4 +988,5 @@ gm107_grctx = {
.r406500 = gm107_grctx_generate_r406500,
.gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr,
.r419e00 = gm107_grctx_generate_r419e00,
+ .r419f78 = gk110_grctx_generate_r419f78,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c
index 3b6c8100a242..a7775aa18541 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c
@@ -206,19 +206,6 @@ tu102_gr_av_to_init_veid(struct nvkm_blob *blob, struct gf100_gr_pack **ppack)
return gk20a_gr_av_to_init_(blob, 64, 0x00100000, ppack);
}
-int
-tu102_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif)
-{
- int ret;
-
- ret = gm200_gr_load(gr, ver, fwif);
- if (ret)
- return ret;
-
- return gk20a_gr_load_net(gr, "gr/", "sw_veid_bundle_init", ver, tu102_gr_av_to_init_veid,
- &gr->bundle_veid);
-}
-
static const struct gf100_gr_fwif
tu102_gr_fwif[] = {
{ 0, gm200_gr_load, &tu102_gr, &gp108_gr_fecs_acr, &gp108_gr_gpccs_acr },
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
index 795f3a649b12..9b8ca4e898f9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
@@ -224,7 +224,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
u64 falcons;
int ret, i;
- if (list_empty(&acr->hsfw)) {
+ if (list_empty(&acr->hsfw) || !acr->func || !acr->func->wpr_layout) {
nvkm_debug(subdev, "No HSFW(s)\n");
nvkm_acr_cleanup(acr);
return 0;
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/i2c/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
index 976539de4220..731b2f68d3db 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
@@ -260,10 +260,11 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device,
{
struct nvkm_bios *bios = device->bios;
struct nvkm_i2c *i2c;
+ struct nvkm_i2c_aux *aux;
struct dcb_i2c_entry ccbE;
struct dcb_output dcbE;
u8 ver, hdr;
- int ret, i;
+ int ret, i, ids;
if (!(i2c = *pi2c = kzalloc(sizeof(*i2c), GFP_KERNEL)))
return -ENOMEM;
@@ -406,5 +407,11 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device,
}
}
- return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, i, &i2c->event);
+ ids = 0;
+ list_for_each_entry(aux, &i2c->aux, head)
+ ids = max(ids, aux->id + 1);
+ if (!ids)
+ return 0;
+
+ return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, ids, &i2c->event);
}
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..fe6639c1cdf3 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,
};
@@ -323,10 +318,6 @@ void omap_fbdev_setup(struct drm_device *dev)
INIT_WORK(&fbdev->work, pan_worker);
- ret = omap_fbdev_client_hotplug(&helper->client);
- if (ret)
- drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
-
drm_client_register(&helper->client);
return;
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..dc276c346fd1 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 + 72,
+ .hsync_end = 1200 + 72 + 30,
+ .htotal = 1200 + 72 + 30 + 72,
+ .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-jdi-lt070me05000.c b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
index 8f4f137a2af6..213008499caa 100644
--- a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
+++ b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
@@ -404,38 +404,30 @@ static int jdi_panel_add(struct jdi_panel *jdi)
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(jdi->supplies),
jdi->supplies);
- if (ret < 0) {
- dev_err(dev, "failed to init regulator, ret=%d\n", ret);
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "failed to init regulator, ret=%d\n", ret);
jdi->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
if (IS_ERR(jdi->enable_gpio)) {
- ret = PTR_ERR(jdi->enable_gpio);
- dev_err(dev, "cannot get enable-gpio %d\n", ret);
- return ret;
+ return dev_err_probe(dev, PTR_ERR(jdi->enable_gpio),
+ "cannot get enable-gpio %d\n", ret);
}
jdi->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
- if (IS_ERR(jdi->reset_gpio)) {
- ret = PTR_ERR(jdi->reset_gpio);
- dev_err(dev, "cannot get reset-gpios %d\n", ret);
- return ret;
- }
+ if (IS_ERR(jdi->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(jdi->reset_gpio),
+ "cannot get reset-gpios %d\n", ret);
jdi->dcdc_en_gpio = devm_gpiod_get(dev, "dcdc-en", GPIOD_OUT_LOW);
- if (IS_ERR(jdi->dcdc_en_gpio)) {
- ret = PTR_ERR(jdi->dcdc_en_gpio);
- dev_err(dev, "cannot get dcdc-en-gpio %d\n", ret);
- return ret;
- }
+ if (IS_ERR(jdi->dcdc_en_gpio))
+ return dev_err_probe(dev, PTR_ERR(jdi->dcdc_en_gpio),
+ "cannot get dcdc-en-gpio %d\n", ret);
jdi->backlight = drm_panel_create_dsi_backlight(jdi->dsi);
- if (IS_ERR(jdi->backlight)) {
- ret = PTR_ERR(jdi->backlight);
- dev_err(dev, "failed to register backlight %d\n", ret);
- return ret;
- }
+ if (IS_ERR(jdi->backlight))
+ return dev_err_probe(dev, PTR_ERR(jdi->backlight),
+ "failed to register backlight %d\n", ret);
drm_panel_init(&jdi->base, &jdi->dsi->dev, &jdi_panel_funcs,
DRM_MODE_CONNECTOR_DSI);
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..be4ec5bb5223
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c
@@ -0,0 +1,586 @@
+// 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 */ }
+};
+MODULE_DEVICE_TABLE(of, s6d7aa0_of_match);
+
+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..b38d0e95cd54 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,
@@ -969,21 +999,21 @@ static const struct panel_desc auo_g104sn02 = {
.connector_type = DRM_MODE_CONNECTOR_LVDS,
};
-static const struct drm_display_mode auo_g121ean01_mode = {
- .clock = 66700,
- .hdisplay = 1280,
- .hsync_start = 1280 + 58,
- .hsync_end = 1280 + 58 + 8,
- .htotal = 1280 + 58 + 8 + 70,
- .vdisplay = 800,
- .vsync_start = 800 + 6,
- .vsync_end = 800 + 6 + 4,
- .vtotal = 800 + 6 + 4 + 10,
+static const struct display_timing auo_g121ean01_timing = {
+ .pixelclock = { 60000000, 74400000, 90000000 },
+ .hactive = { 1280, 1280, 1280 },
+ .hfront_porch = { 20, 50, 100 },
+ .hback_porch = { 20, 50, 100 },
+ .hsync_len = { 30, 100, 200 },
+ .vactive = { 800, 800, 800 },
+ .vfront_porch = { 2, 10, 25 },
+ .vback_porch = { 2, 10, 25 },
+ .vsync_len = { 4, 18, 50 },
};
static const struct panel_desc auo_g121ean01 = {
- .modes = &auo_g121ean01_mode,
- .num_modes = 1,
+ .timings = &auo_g121ean01_timing,
+ .num_timings = 1,
.bpc = 8,
.size = {
.width = 261,
@@ -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,
@@ -2117,6 +2178,7 @@ static const struct panel_desc innolux_at043tn24 = {
.height = 54,
},
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+ .connector_type = DRM_MODE_CONNECTOR_DPI,
.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
};
@@ -2142,6 +2204,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 },
@@ -3109,6 +3203,7 @@ static const struct drm_display_mode powertip_ph800480t013_idf02_mode = {
.vsync_start = 480 + 49,
.vsync_end = 480 + 49 + 2,
.vtotal = 480 + 49 + 2 + 22,
+ .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
};
static const struct panel_desc powertip_ph800480t013_idf02 = {
@@ -3188,6 +3283,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 +4052,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 +4109,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 +4226,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 +4349,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/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c
index 58dfb15a8757..e78de99e9933 100644
--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c
+++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c
@@ -96,7 +96,7 @@ static int panfrost_read_speedbin(struct device *dev)
* keep going without it; any other error means that we are
* supposed to read the bin value, but we failed doing so.
*/
- if (ret != -ENOENT) {
+ if (ret != -ENOENT && ret != -EOPNOTSUPP) {
DRM_DEV_ERROR(dev, "Cannot read speed-bin (%d).", ret);
return ret;
}
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index ea993d7162e8..307a890fde13 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -310,7 +310,7 @@ int qxl_gem_object_create_with_handle(struct qxl_device *qdev,
u32 domain,
size_t size,
struct qxl_surface *surf,
- struct qxl_bo **qobj,
+ struct drm_gem_object **gobj,
uint32_t *handle);
void qxl_gem_object_free(struct drm_gem_object *gobj);
int qxl_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_priv);
diff --git a/drivers/gpu/drm/qxl/qxl_dumb.c b/drivers/gpu/drm/qxl/qxl_dumb.c
index d636ba685451..17df5c7ccf69 100644
--- a/drivers/gpu/drm/qxl/qxl_dumb.c
+++ b/drivers/gpu/drm/qxl/qxl_dumb.c
@@ -34,6 +34,7 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
{
struct qxl_device *qdev = to_qxl(dev);
struct qxl_bo *qobj;
+ struct drm_gem_object *gobj;
uint32_t handle;
int r;
struct qxl_surface surf;
@@ -62,11 +63,13 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
r = qxl_gem_object_create_with_handle(qdev, file_priv,
QXL_GEM_DOMAIN_CPU,
- args->size, &surf, &qobj,
+ args->size, &surf, &gobj,
&handle);
if (r)
return r;
+ qobj = gem_to_qxl_bo(gobj);
qobj->is_dumb = true;
+ drm_gem_object_put(gobj);
args->pitch = pitch;
args->handle = handle;
return 0;
diff --git a/drivers/gpu/drm/qxl/qxl_gem.c b/drivers/gpu/drm/qxl/qxl_gem.c
index a08da0bd9098..fc5e3763c359 100644
--- a/drivers/gpu/drm/qxl/qxl_gem.c
+++ b/drivers/gpu/drm/qxl/qxl_gem.c
@@ -72,32 +72,41 @@ int qxl_gem_object_create(struct qxl_device *qdev, int size,
return 0;
}
+/*
+ * If the caller passed a valid gobj pointer, it is responsible to call
+ * drm_gem_object_put() when it no longer needs to acess the object.
+ *
+ * If gobj is NULL, it is handled internally.
+ */
int qxl_gem_object_create_with_handle(struct qxl_device *qdev,
struct drm_file *file_priv,
u32 domain,
size_t size,
struct qxl_surface *surf,
- struct qxl_bo **qobj,
+ struct drm_gem_object **gobj,
uint32_t *handle)
{
- struct drm_gem_object *gobj;
int r;
+ struct drm_gem_object *local_gobj;
- BUG_ON(!qobj);
BUG_ON(!handle);
r = qxl_gem_object_create(qdev, size, 0,
domain,
false, false, surf,
- &gobj);
+ &local_gobj);
if (r)
return -ENOMEM;
- r = drm_gem_handle_create(file_priv, gobj, handle);
+ r = drm_gem_handle_create(file_priv, local_gobj, handle);
if (r)
return r;
- /* drop reference from allocate - handle holds it now */
- *qobj = gem_to_qxl_bo(gobj);
- drm_gem_object_put(gobj);
+
+ if (gobj)
+ *gobj = local_gobj;
+ else
+ /* drop reference from allocate - handle holds it now */
+ drm_gem_object_put(local_gobj);
+
return 0;
}
diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c
index 30f58b21372a..dd0f834d881c 100644
--- a/drivers/gpu/drm/qxl/qxl_ioctl.c
+++ b/drivers/gpu/drm/qxl/qxl_ioctl.c
@@ -38,7 +38,6 @@ int qxl_alloc_ioctl(struct drm_device *dev, void *data, struct drm_file *file_pr
struct qxl_device *qdev = to_qxl(dev);
struct drm_qxl_alloc *qxl_alloc = data;
int ret;
- struct qxl_bo *qobj;
uint32_t handle;
u32 domain = QXL_GEM_DOMAIN_VRAM;
@@ -50,7 +49,7 @@ int qxl_alloc_ioctl(struct drm_device *dev, void *data, struct drm_file *file_pr
domain,
qxl_alloc->size,
NULL,
- &qobj, &handle);
+ NULL, &handle);
if (ret) {
DRM_ERROR("%s: failed to create gem ret=%d\n",
__func__, ret);
@@ -386,7 +385,6 @@ int qxl_alloc_surf_ioctl(struct drm_device *dev, void *data, struct drm_file *fi
{
struct qxl_device *qdev = to_qxl(dev);
struct drm_qxl_alloc_surf *param = data;
- struct qxl_bo *qobj;
int handle;
int ret;
int size, actual_stride;
@@ -406,7 +404,7 @@ int qxl_alloc_surf_ioctl(struct drm_device *dev, void *data, struct drm_file *fi
QXL_GEM_DOMAIN_SURFACE,
size,
&surf,
- &qobj, &handle);
+ NULL, &handle);
if (ret) {
DRM_ERROR("%s: failed to create gem ret=%d\n",
__func__, ret);
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_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 4ad5a328d920..bf3c411a55c5 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -2105,7 +2105,7 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
const char *name = thermal_controller_names[power_info->info.
ucOverdriveThermalController];
info.addr = power_info->info.ucOverdriveControllerAddress >> 1;
- strlcpy(info.type, name, sizeof(info.type));
+ strscpy(info.type, name, sizeof(info.type));
i2c_new_client_device(&rdev->pm.i2c_bus->adapter, &info);
}
}
@@ -2355,7 +2355,7 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r
struct i2c_board_info info = { };
const char *name = pp_lib_thermal_controller_names[controller->ucType];
info.addr = controller->ucI2cAddress >> 1;
- strlcpy(info.type, name, sizeof(info.type));
+ strscpy(info.type, name, sizeof(info.type));
i2c_new_client_device(&rdev->pm.i2c_bus->adapter, &info);
}
} else {
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_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index 783a6b8802d5..795c3667f6d6 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -2702,7 +2702,7 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev)
struct i2c_board_info info = { };
const char *name = thermal_controller_names[thermal_controller];
info.addr = i2c_addr >> 1;
- strlcpy(info.type, name, sizeof(info.type));
+ strscpy(info.type, name, sizeof(info.type));
i2c_new_client_device(&rdev->pm.i2c_bus->adapter, &info);
}
}
@@ -2719,7 +2719,7 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev)
struct i2c_board_info info = { };
const char *name = "f75375";
info.addr = 0x28;
- strlcpy(info.type, name, sizeof(info.type));
+ strscpy(info.type, name, sizeof(info.type));
i2c_new_client_device(&rdev->pm.i2c_bus->adapter, &info);
DRM_INFO("Possible %s thermal controller at 0x%02x\n",
name, info.addr);
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..f941e2e7cae6 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,
};
@@ -386,10 +383,6 @@ void radeon_fbdev_setup(struct radeon_device *rdev)
goto err_drm_client_init;
}
- ret = radeon_fbdev_client_hotplug(&fb_helper->client);
- if (ret)
- drm_dbg_kms(rdev->ddev, "client hotplug ret=%d\n", ret);
-
drm_client_register(&fb_helper->client);
return;
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 2220cdf6a3f6..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>
@@ -359,7 +358,7 @@ static int radeon_ttm_tt_pin_userptr(struct ttm_device *bdev, struct ttm_tt *ttm
struct page **pages = ttm->pages + pinned;
r = get_user_pages(userptr, num_pages, write ? FOLL_WRITE : 0,
- pages, NULL);
+ pages);
if (r < 0)
goto release_pages;
@@ -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/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c
index f51774866f41..9afb889963c1 100644
--- a/drivers/gpu/drm/rockchip/inno_hdmi.c
+++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
@@ -797,7 +797,7 @@ static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
adap->dev.parent = hdmi->dev;
adap->dev.of_node = hdmi->dev->of_node;
adap->algo = &inno_hdmi_algorithm;
- strlcpy(adap->name, "Inno HDMI", sizeof(adap->name));
+ strscpy(adap->name, "Inno HDMI", sizeof(adap->name));
i2c_set_adapdata(adap, hdmi);
ret = i2c_add_adapter(adap);
diff --git a/drivers/gpu/drm/rockchip/rk3066_hdmi.c b/drivers/gpu/drm/rockchip/rk3066_hdmi.c
index 90145ad96984..b5d042ee052f 100644
--- a/drivers/gpu/drm/rockchip/rk3066_hdmi.c
+++ b/drivers/gpu/drm/rockchip/rk3066_hdmi.c
@@ -730,7 +730,7 @@ static struct i2c_adapter *rk3066_hdmi_i2c_adapter(struct rk3066_hdmi *hdmi)
adap->dev.parent = hdmi->dev;
adap->dev.of_node = hdmi->dev->of_node;
adap->algo = &rk3066_hdmi_algorithm;
- strlcpy(adap->name, "RK3066 HDMI", sizeof(adap->name));
+ strscpy(adap->name, "RK3066 HDMI", sizeof(adap->name));
i2c_set_adapdata(adap, hdmi);
ret = i2c_add_adapter(adap);
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..bf34498c1b6d 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);
@@ -833,12 +833,12 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
* need align with 2 pixel.
*/
if (fb->format->is_yuv && ((new_plane_state->src.x1 >> 16) % 2)) {
- DRM_ERROR("Invalid Source: Yuv format not support odd xpos\n");
+ DRM_DEBUG_KMS("Invalid Source: Yuv format not support odd xpos\n");
return -EINVAL;
}
if (fb->format->is_yuv && new_plane_state->rotation & DRM_MODE_REFLECT_Y) {
- DRM_ERROR("Invalid Source: Yuv format does not support this rotation\n");
+ DRM_DEBUG_KMS("Invalid Source: Yuv format does not support this rotation\n");
return -EINVAL;
}
@@ -846,7 +846,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
struct vop *vop = to_vop(crtc);
if (!vop->data->afbc) {
- DRM_ERROR("vop does not support AFBC\n");
+ DRM_DEBUG_KMS("vop does not support AFBC\n");
return -EINVAL;
}
@@ -855,15 +855,16 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
return ret;
if (new_plane_state->src.x1 || new_plane_state->src.y1) {
- DRM_ERROR("AFBC does not support offset display, xpos=%d, ypos=%d, offset=%d\n",
- new_plane_state->src.x1,
- new_plane_state->src.y1, fb->offsets[0]);
+ DRM_DEBUG_KMS("AFBC does not support offset display, " \
+ "xpos=%d, ypos=%d, offset=%d\n",
+ new_plane_state->src.x1, new_plane_state->src.y1,
+ fb->offsets[0]);
return -EINVAL;
}
if (new_plane_state->rotation && new_plane_state->rotation != DRM_MODE_ROTATE_0) {
- DRM_ERROR("No rotation support in AFBC, rotation=%d\n",
- new_plane_state->rotation);
+ DRM_DEBUG_KMS("No rotation support in AFBC, rotation=%d\n",
+ new_plane_state->rotation);
return -EINVAL;
}
}
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
index e0a8890a62e2..a42763e1429d 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);
}
@@ -155,16 +176,32 @@ static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f,
{
struct drm_sched_job *job = container_of(cb, struct drm_sched_job,
finish_cb);
- int r;
+ unsigned long index;
dma_fence_put(f);
/* Wait for all dependencies to avoid data corruptions */
- while (!xa_empty(&job->dependencies)) {
- f = xa_erase(&job->dependencies, job->last_dependency++);
- r = dma_fence_add_callback(f, &job->finish_cb,
- drm_sched_entity_kill_jobs_cb);
- if (!r)
+ xa_for_each(&job->dependencies, index, f) {
+ struct drm_sched_fence *s_fence = to_drm_sched_fence(f);
+
+ if (s_fence && f == &s_fence->scheduled) {
+ /* The dependencies array had a reference on the scheduled
+ * fence, and the finished fence refcount might have
+ * dropped to zero. Use dma_fence_get_rcu() so we get
+ * a NULL fence in that case.
+ */
+ f = dma_fence_get_rcu(&s_fence->finished);
+
+ /* Now that we have a reference on the finished fence,
+ * we can release the reference the dependencies array
+ * had on the scheduled fence.
+ */
+ dma_fence_put(&s_fence->scheduled);
+ }
+
+ xa_erase(&job->dependencies, index);
+ if (f && !dma_fence_add_callback(f, &job->finish_cb,
+ drm_sched_entity_kill_jobs_cb))
return;
dma_fence_put(f);
@@ -191,12 +228,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 +317,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 +358,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 +400,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)) {
/*
@@ -394,8 +431,17 @@ static struct dma_fence *
drm_sched_job_dependency(struct drm_sched_job *job,
struct drm_sched_entity *entity)
{
- if (!xa_empty(&job->dependencies))
- return xa_erase(&job->dependencies, job->last_dependency++);
+ struct dma_fence *f;
+
+ /* We keep the fence around, so we can iterate over all dependencies
+ * in drm_sched_entity_kill_jobs_cb() to ensure all deps are signaled
+ * before killing the job.
+ */
+ f = xa_load(&job->dependencies, job->last_dependency);
+ if (f) {
+ job->last_dependency++;
+ return dma_fence_get(f);
+ }
if (job->sched->ops->prepare_job)
return job->sched->ops->prepare_job(job, entity);
@@ -423,9 +469,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 +494,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 +525,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 +590,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..06cedfe4b486 100644
--- a/drivers/gpu/drm/scheduler/sched_fence.c
+++ b/drivers/gpu/drm/scheduler/sched_fence.c
@@ -48,13 +48,39 @@ static void __exit drm_sched_fence_slab_fini(void)
kmem_cache_destroy(sched_fence_slab);
}
-void drm_sched_fence_scheduled(struct drm_sched_fence *fence)
+static void drm_sched_fence_set_parent(struct drm_sched_fence *s_fence,
+ struct dma_fence *fence)
{
+ /*
+ * smp_store_release() to ensure another thread racing us
+ * in drm_sched_fence_set_deadline_finished() sees the
+ * fence's parent set before test_bit()
+ */
+ smp_store_release(&s_fence->parent, dma_fence_get(fence));
+ if (test_bit(DRM_SCHED_FENCE_FLAG_HAS_DEADLINE_BIT,
+ &s_fence->finished.flags))
+ dma_fence_set_deadline(fence, s_fence->deadline);
+}
+
+void drm_sched_fence_scheduled(struct drm_sched_fence *fence,
+ struct dma_fence *parent)
+{
+ /* Set the parent before signaling the scheduled fence, such that,
+ * any waiter expecting the parent to be filled after the job has
+ * been scheduled (which is the case for drivers delegating waits
+ * to some firmware) doesn't have to busy wait for parent to show
+ * up.
+ */
+ if (!IS_ERR_OR_NULL(parent))
+ drm_sched_fence_set_parent(fence, parent);
+
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);
}
@@ -179,20 +205,6 @@ struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f)
}
EXPORT_SYMBOL(to_drm_sched_fence);
-void drm_sched_fence_set_parent(struct drm_sched_fence *s_fence,
- struct dma_fence *fence)
-{
- /*
- * smp_store_release() to ensure another thread racing us
- * in drm_sched_fence_set_deadline_finished() sees the
- * fence's parent set before test_bit()
- */
- smp_store_release(&s_fence->parent, dma_fence_get(fence));
- if (test_bit(DRM_SCHED_FENCE_FLAG_HAS_DEADLINE_BIT,
- &s_fence->finished.flags))
- dma_fence_set_deadline(fence, s_fence->deadline);
-}
-
struct drm_sched_fence *drm_sched_fence_alloc(struct drm_sched_entity *entity,
void *owner)
{
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index aea5a90ff98b..506371c42745 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*/
@@ -1040,25 +1043,22 @@ static int drm_sched_main(void *param)
trace_drm_run_job(sched_job, entity);
fence = sched->ops->run_job(sched_job);
complete_all(&entity->entity_idle);
- drm_sched_fence_scheduled(s_fence);
+ drm_sched_fence_scheduled(s_fence, fence);
if (!IS_ERR_OR_NULL(fence)) {
- drm_sched_fence_set_parent(s_fence, fence);
/* Drop for original kref_init of the fence */
dma_fence_put(fence);
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_hdmi_i2c.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c
index c7d7e9fff91c..d1a65a921f5a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c
@@ -304,7 +304,7 @@ int sun4i_hdmi_i2c_create(struct device *dev, struct sun4i_hdmi *hdmi)
adap->owner = THIS_MODULE;
adap->class = I2C_CLASS_DDC;
adap->algo = &sun4i_hdmi_i2c_algorithm;
- strlcpy(adap->name, "sun4i_hdmi_i2c adapter", sizeof(adap->name));
+ strscpy(adap->name, "sun4i_hdmi_i2c adapter", sizeof(adap->name));
i2c_set_adapdata(adap, hdmi);
ret = i2c_add_adapter(adap);
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..d042234e1807 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,
};
@@ -227,10 +225,6 @@ void tegra_fbdev_setup(struct drm_device *dev)
if (ret)
goto err_drm_client_init;
- ret = tegra_fbdev_client_hotplug(&helper->client);
- if (ret)
- drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
-
drm_client_register(&helper->client);
return;
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_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index bd5dae4d1624..54e3083076b7 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -458,18 +458,18 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo,
goto out;
}
-bounce:
- ret = ttm_bo_handle_move_mem(bo, evict_mem, true, ctx, &hop);
- if (ret == -EMULTIHOP) {
+ do {
+ ret = ttm_bo_handle_move_mem(bo, evict_mem, true, ctx, &hop);
+ if (ret != -EMULTIHOP)
+ break;
+
ret = ttm_bo_bounce_temp_buffer(bo, &evict_mem, ctx, &hop);
- if (ret) {
- if (ret != -ERESTARTSYS && ret != -EINTR)
- pr_err("Buffer eviction failed\n");
- ttm_resource_free(bo, &evict_mem);
- goto out;
- }
- /* try and move to final place now. */
- goto bounce;
+ } while (!ret);
+
+ if (ret) {
+ ttm_resource_free(bo, &evict_mem);
+ if (ret != -ERESTARTSYS && ret != -EINTR)
+ pr_err("Buffer eviction failed\n");
}
out:
return ret;
@@ -517,6 +517,13 @@ static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo,
{
bool ret = false;
+ if (bo->pin_count) {
+ *locked = false;
+ if (busy)
+ *busy = false;
+ return false;
+ }
+
if (bo->base.resv == ctx->resv) {
dma_resv_assert_held(bo->base.resv);
if (ctx->allow_res_evict)
@@ -1167,6 +1174,7 @@ int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx,
ret = ttm_bo_handle_move_mem(bo, evict_mem, true, &ctx, &hop);
if (unlikely(ret != 0)) {
WARN(ret == -EMULTIHOP, "Unexpected multihop in swaput - likely driver bug.\n");
+ ttm_resource_free(bo, &evict_mem);
goto out;
}
}
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_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c
index 7333f7a87a2f..46ff9c75bb12 100644
--- a/drivers/gpu/drm/ttm/ttm_resource.c
+++ b/drivers/gpu/drm/ttm/ttm_resource.c
@@ -86,6 +86,8 @@ static void ttm_lru_bulk_move_pos_tail(struct ttm_lru_bulk_move_pos *pos,
struct ttm_resource *res)
{
if (pos->last != res) {
+ if (pos->first == res)
+ pos->first = list_next_entry(res, lru);
list_move(&res->lru, &pos->last->lru);
pos->last = res;
}
@@ -111,7 +113,8 @@ static void ttm_lru_bulk_move_del(struct ttm_lru_bulk_move *bulk,
{
struct ttm_lru_bulk_move_pos *pos = ttm_lru_bulk_move_pos(bulk, res);
- if (unlikely(pos->first == res && pos->last == res)) {
+ if (unlikely(WARN_ON(!pos->first || !pos->last) ||
+ (pos->first == res && pos->last == res))) {
pos->first = NULL;
pos->last = NULL;
} else if (pos->first == res) {
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/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
index 82094c137855..c43853597776 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
@@ -497,10 +497,9 @@ static int vmw_user_bo_synccpu_release(struct drm_file *filp,
if (!(flags & drm_vmw_synccpu_allow_cs)) {
atomic_dec(&vmw_bo->cpu_writers);
}
- ttm_bo_put(&vmw_bo->tbo);
+ vmw_user_bo_unref(vmw_bo);
}
- drm_gem_object_put(&vmw_bo->tbo.base);
return ret;
}
@@ -540,8 +539,7 @@ int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data,
return ret;
ret = vmw_user_bo_synccpu_grab(vbo, arg->flags);
- vmw_bo_unreference(&vbo);
- drm_gem_object_put(&vbo->tbo.base);
+ vmw_user_bo_unref(vbo);
if (unlikely(ret != 0)) {
if (ret == -ERESTARTSYS || ret == -EBUSY)
return -EBUSY;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h
index 50a836e70994..1d433fceed3d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h
@@ -195,6 +195,14 @@ static inline struct vmw_bo *vmw_bo_reference(struct vmw_bo *buf)
return buf;
}
+static inline void vmw_user_bo_unref(struct vmw_bo *vbo)
+{
+ if (vbo) {
+ ttm_bo_put(&vbo->tbo);
+ drm_gem_object_put(&vbo->tbo.base);
+ }
+}
+
static inline struct vmw_bo *to_vmw_bo(struct drm_gem_object *gobj)
{
return container_of((gobj), struct vmw_bo, tbo.base);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 3810a9984a7f..58bfdf203eca 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -1513,4 +1513,16 @@ static inline bool vmw_has_fences(struct vmw_private *vmw)
return (vmw_fifo_caps(vmw) & SVGA_FIFO_CAP_FENCE) != 0;
}
+static inline bool vmw_shadertype_is_valid(enum vmw_sm_type shader_model,
+ u32 shader_type)
+{
+ SVGA3dShaderType max_allowed = SVGA3D_SHADERTYPE_PREDX_MAX;
+
+ if (shader_model >= VMW_SM_5)
+ max_allowed = SVGA3D_SHADERTYPE_MAX;
+ else if (shader_model >= VMW_SM_4)
+ max_allowed = SVGA3D_SHADERTYPE_DX10_MAX;
+ return shader_type >= SVGA3D_SHADERTYPE_MIN && shader_type < max_allowed;
+}
+
#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 6b9aa2b4ef54..98e0723ca6f5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -1164,8 +1164,7 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
}
vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB);
ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo);
- ttm_bo_put(&vmw_bo->tbo);
- drm_gem_object_put(&vmw_bo->tbo.base);
+ vmw_user_bo_unref(vmw_bo);
if (unlikely(ret != 0))
return ret;
@@ -1221,8 +1220,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM,
VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM);
ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo);
- ttm_bo_put(&vmw_bo->tbo);
- drm_gem_object_put(&vmw_bo->tbo.base);
+ vmw_user_bo_unref(vmw_bo);
if (unlikely(ret != 0))
return ret;
@@ -1992,7 +1990,7 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
cmd = container_of(header, typeof(*cmd), header);
- if (cmd->body.type >= SVGA3D_SHADERTYPE_PREDX_MAX) {
+ if (!vmw_shadertype_is_valid(VMW_SM_LEGACY, cmd->body.type)) {
VMW_DEBUG_USER("Illegal shader type %u.\n",
(unsigned int) cmd->body.type);
return -EINVAL;
@@ -2115,8 +2113,6 @@ vmw_cmd_dx_set_single_constant_buffer(struct vmw_private *dev_priv,
SVGA3dCmdHeader *header)
{
VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetSingleConstantBuffer);
- SVGA3dShaderType max_shader_num = has_sm5_context(dev_priv) ?
- SVGA3D_NUM_SHADERTYPE : SVGA3D_NUM_SHADERTYPE_DX10;
struct vmw_resource *res = NULL;
struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context);
@@ -2133,6 +2129,14 @@ vmw_cmd_dx_set_single_constant_buffer(struct vmw_private *dev_priv,
if (unlikely(ret != 0))
return ret;
+ if (!vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type) ||
+ cmd->body.slot >= SVGA3D_DX_MAX_CONSTBUFFERS) {
+ VMW_DEBUG_USER("Illegal const buffer shader %u slot %u.\n",
+ (unsigned int) cmd->body.type,
+ (unsigned int) cmd->body.slot);
+ return -EINVAL;
+ }
+
binding.bi.ctx = ctx_node->ctx;
binding.bi.res = res;
binding.bi.bt = vmw_ctx_binding_cb;
@@ -2141,14 +2145,6 @@ vmw_cmd_dx_set_single_constant_buffer(struct vmw_private *dev_priv,
binding.size = cmd->body.sizeInBytes;
binding.slot = cmd->body.slot;
- if (binding.shader_slot >= max_shader_num ||
- binding.slot >= SVGA3D_DX_MAX_CONSTBUFFERS) {
- VMW_DEBUG_USER("Illegal const buffer shader %u slot %u.\n",
- (unsigned int) cmd->body.type,
- (unsigned int) binding.slot);
- return -EINVAL;
- }
-
vmw_binding_add(ctx_node->staged, &binding.bi, binding.shader_slot,
binding.slot);
@@ -2207,15 +2203,13 @@ static int vmw_cmd_dx_set_shader_res(struct vmw_private *dev_priv,
{
VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetShaderResources) =
container_of(header, typeof(*cmd), header);
- SVGA3dShaderType max_allowed = has_sm5_context(dev_priv) ?
- SVGA3D_SHADERTYPE_MAX : SVGA3D_SHADERTYPE_DX10_MAX;
u32 num_sr_view = (cmd->header.size - sizeof(cmd->body)) /
sizeof(SVGA3dShaderResourceViewId);
if ((u64) cmd->body.startView + (u64) num_sr_view >
(u64) SVGA3D_DX_MAX_SRVIEWS ||
- cmd->body.type >= max_allowed) {
+ !vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type)) {
VMW_DEBUG_USER("Invalid shader binding.\n");
return -EINVAL;
}
@@ -2239,8 +2233,6 @@ static int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv,
SVGA3dCmdHeader *header)
{
VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetShader);
- SVGA3dShaderType max_allowed = has_sm5_context(dev_priv) ?
- SVGA3D_SHADERTYPE_MAX : SVGA3D_SHADERTYPE_DX10_MAX;
struct vmw_resource *res = NULL;
struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context);
struct vmw_ctx_bindinfo_shader binding;
@@ -2251,8 +2243,7 @@ static int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv,
cmd = container_of(header, typeof(*cmd), header);
- if (cmd->body.type >= max_allowed ||
- cmd->body.type < SVGA3D_SHADERTYPE_MIN) {
+ if (!vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type)) {
VMW_DEBUG_USER("Illegal shader type %u.\n",
(unsigned int) cmd->body.type);
return -EINVAL;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index b62207be3363..1489ad73c103 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1665,10 +1665,8 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
err_out:
/* vmw_user_lookup_handle takes one ref so does new_fb */
- if (bo) {
- vmw_bo_unreference(&bo);
- drm_gem_object_put(&bo->tbo.base);
- }
+ if (bo)
+ vmw_user_bo_unref(bo);
if (surface)
vmw_surface_unreference(&surface);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h
index 0b74ca2dfb7b..23899d743a90 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h
@@ -105,10 +105,14 @@
flags, magic, bp, \
eax, ebx, ecx, edx, si, di) \
({ \
- asm volatile ("push %%rbp;" \
+ asm volatile ( \
+ UNWIND_HINT_SAVE \
+ "push %%rbp;" \
+ UNWIND_HINT_UNDEFINED \
"mov %12, %%rbp;" \
VMWARE_HYPERCALL_HB_OUT \
- "pop %%rbp;" : \
+ "pop %%rbp;" \
+ UNWIND_HINT_RESTORE : \
"=a"(eax), \
"=b"(ebx), \
"=c"(ecx), \
@@ -130,10 +134,14 @@
flags, magic, bp, \
eax, ebx, ecx, edx, si, di) \
({ \
- asm volatile ("push %%rbp;" \
+ asm volatile ( \
+ UNWIND_HINT_SAVE \
+ "push %%rbp;" \
+ UNWIND_HINT_UNDEFINED \
"mov %12, %%rbp;" \
VMWARE_HYPERCALL_HB_IN \
- "pop %%rbp" : \
+ "pop %%rbp;" \
+ UNWIND_HINT_RESTORE : \
"=a"(eax), \
"=b"(ebx), \
"=c"(ecx), \
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
index 7e112319a23c..fb85f244c3d0 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
@@ -451,8 +451,7 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data,
ret = vmw_overlay_update_stream(dev_priv, buf, arg, true);
- vmw_bo_unreference(&buf);
- drm_gem_object_put(&buf->tbo.base);
+ vmw_user_bo_unref(buf);
out_unlock:
mutex_unlock(&overlay->mutex);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
index e7226db8b242..1e81ff2422cf 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
@@ -809,8 +809,7 @@ static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv,
shader_type, num_input_sig,
num_output_sig, tfile, shader_handle);
out_bad_arg:
- vmw_bo_unreference(&buffer);
- drm_gem_object_put(&buffer->tbo.base);
+ vmw_user_bo_unref(buffer);
return ret;
}
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/greybus/connection.c b/drivers/greybus/connection.c
index e3799a53a193..9c88861986c8 100644
--- a/drivers/greybus/connection.c
+++ b/drivers/greybus/connection.c
@@ -187,8 +187,8 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id,
spin_lock_init(&connection->lock);
INIT_LIST_HEAD(&connection->operations);
- connection->wq = alloc_workqueue("%s:%d", WQ_UNBOUND, 1,
- dev_name(&hd->dev), hd_cport_id);
+ connection->wq = alloc_ordered_workqueue("%s:%d", 0, dev_name(&hd->dev),
+ hd_cport_id);
if (!connection->wq) {
ret = -ENOMEM;
goto err_free_connection;
diff --git a/drivers/greybus/svc.c b/drivers/greybus/svc.c
index 16cced80867a..0d7e749174a4 100644
--- a/drivers/greybus/svc.c
+++ b/drivers/greybus/svc.c
@@ -1318,7 +1318,7 @@ struct gb_svc *gb_svc_create(struct gb_host_device *hd)
if (!svc)
return NULL;
- svc->wq = alloc_workqueue("%s:svc", WQ_UNBOUND, 1, dev_name(&hd->dev));
+ svc->wq = alloc_ordered_workqueue("%s:svc", 0, dev_name(&hd->dev));
if (!svc->wq) {
kfree(svc);
return NULL;
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_desc.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
index 6f0d332ccf51..06bdcf072d10 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
@@ -132,29 +132,45 @@ static void get_common_inputs(struct common_input_property *common, int report_i
common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;
}
-static int float_to_int(u32 float32)
+static int float_to_int(u32 flt32_val)
{
int fraction, shift, mantissa, sign, exp, zeropre;
- mantissa = float32 & GENMASK(22, 0);
- sign = (float32 & BIT(31)) ? -1 : 1;
- exp = (float32 & ~BIT(31)) >> 23;
+ mantissa = flt32_val & GENMASK(22, 0);
+ sign = (flt32_val & BIT(31)) ? -1 : 1;
+ exp = (flt32_val & ~BIT(31)) >> 23;
if (!exp && !mantissa)
return 0;
+ /*
+ * Calculate the exponent and fraction part of floating
+ * point representation.
+ */
exp -= 127;
if (exp < 0) {
exp = -exp;
+ if (exp >= BITS_PER_TYPE(u32))
+ return 0;
zeropre = (((BIT(23) + mantissa) * 100) >> 23) >> exp;
return zeropre >= 50 ? sign : 0;
}
shift = 23 - exp;
- float32 = BIT(exp) + (mantissa >> shift);
- fraction = mantissa & GENMASK(shift - 1, 0);
+ if (abs(shift) >= BITS_PER_TYPE(u32))
+ return 0;
+
+ if (shift < 0) {
+ shift = -shift;
+ flt32_val = BIT(exp) + (mantissa << shift);
+ shift = 0;
+ } else {
+ flt32_val = BIT(exp) + (mantissa >> shift);
+ }
+
+ fraction = (shift == 0) ? 0 : mantissa & GENMASK(shift - 1, 0);
- return (((fraction * 100) >> shift) >= 50) ? sign * (float32 + 1) : sign * float32;
+ return (((fraction * 100) >> shift) >= 50) ? sign * (flt32_val + 1) : sign * flt32_val;
}
static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,
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-hyperv.c b/drivers/hid/hid-hyperv.c
index 49d4a26895e7..f33485d83d24 100644
--- a/drivers/hid/hid-hyperv.c
+++ b/drivers/hid/hid-hyperv.c
@@ -258,19 +258,17 @@ static void mousevsc_on_receive(struct hv_device *device,
switch (hid_msg_hdr->type) {
case SYNTH_HID_PROTOCOL_RESPONSE:
+ len = struct_size(pipe_msg, data, pipe_msg->size);
+
/*
* While it will be impossible for us to protect against
* malicious/buggy hypervisor/host, add a check here to
* ensure we don't corrupt memory.
*/
- if (struct_size(pipe_msg, data, pipe_msg->size)
- > sizeof(struct mousevsc_prt_msg)) {
- WARN_ON(1);
+ if (WARN_ON(len > sizeof(struct mousevsc_prt_msg)))
break;
- }
- memcpy(&input_dev->protocol_resp, pipe_msg,
- struct_size(pipe_msg, data, pipe_msg->size));
+ memcpy(&input_dev->protocol_resp, pipe_msg, len);
complete(&input_dev->wait_event);
break;
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-input.c b/drivers/hid/hid-input.c
index a1d2690a1a0d..851ee86eff32 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1093,6 +1093,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x074: map_key_clear(KEY_BRIGHTNESS_MAX); break;
case 0x075: map_key_clear(KEY_BRIGHTNESS_AUTO); break;
+ case 0x076: map_key_clear(KEY_CAMERA_ACCESS_ENABLE); break;
+ case 0x077: map_key_clear(KEY_CAMERA_ACCESS_DISABLE); break;
+ case 0x078: map_key_clear(KEY_CAMERA_ACCESS_TOGGLE); break;
+
case 0x079: map_key_clear(KEY_KBDILLUMUP); break;
case 0x07a: map_key_clear(KEY_KBDILLUMDOWN); break;
case 0x07c: map_key_clear(KEY_KBDILLUMTOGGLE); break;
@@ -1139,9 +1143,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break;
case 0x0cf: map_key_clear(KEY_VOICECOMMAND); break;
- case 0x0d5: map_key_clear(KEY_CAMERA_ACCESS_ENABLE); break;
- case 0x0d6: map_key_clear(KEY_CAMERA_ACCESS_DISABLE); break;
- case 0x0d7: map_key_clear(KEY_CAMERA_ACCESS_TOGGLE); break;
case 0x0d8: map_key_clear(KEY_DICTATE); break;
case 0x0d9: map_key_clear(KEY_EMOJI_PICKER); break;
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 5e1a412fd28f..129b01be488d 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 */
@@ -4598,6 +4598,8 @@ static const struct hid_device_id hidpp_devices[] = {
{ /* Logitech G403 Wireless Gaming Mouse over USB */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC082) },
+ { /* Logitech G502 Lightspeed Wireless Gaming Mouse over USB */
+ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC08D) },
{ /* Logitech G703 Gaming Mouse over USB */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC087) },
{ /* Logitech G703 Hero Gaming Mouse over USB */
@@ -4608,6 +4610,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 +4634,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..a928ad2be62d
--- /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];
+} __packed;
+
+struct thunderstrike_hostcmd_haptics {
+ u8 motor_left;
+ u8 motor_right;
+} __packed;
+
+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;
+} __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 __packed {
+ u8 update;
+ enum thunderstrike_led_state state;
+ } led;
+ struct __packed {
+ u8 update;
+ struct thunderstrike_hostcmd_haptics motors;
+ } haptics;
+ } __packed;
+ 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/hv/connection.c b/drivers/hv/connection.c
index 5978e9dbc286..ebf15f31d97e 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -209,8 +209,7 @@ int vmbus_connect(void)
* Setup the vmbus event connection for channel interrupt
* abstraction stuff
*/
- vmbus_connection.int_page =
- (void *)hv_alloc_hyperv_zeroed_page();
+ vmbus_connection.int_page = hv_alloc_hyperv_zeroed_page();
if (vmbus_connection.int_page == NULL) {
ret = -ENOMEM;
goto cleanup;
@@ -225,8 +224,8 @@ int vmbus_connect(void)
* Setup the monitor notification facility. The 1st page for
* parent->child and the 2nd page for child->parent
*/
- vmbus_connection.monitor_pages[0] = (void *)hv_alloc_hyperv_page();
- vmbus_connection.monitor_pages[1] = (void *)hv_alloc_hyperv_page();
+ vmbus_connection.monitor_pages[0] = hv_alloc_hyperv_page();
+ vmbus_connection.monitor_pages[1] = hv_alloc_hyperv_page();
if ((vmbus_connection.monitor_pages[0] == NULL) ||
(vmbus_connection.monitor_pages[1] == NULL)) {
ret = -ENOMEM;
@@ -333,15 +332,15 @@ void vmbus_disconnect(void)
destroy_workqueue(vmbus_connection.work_queue);
if (vmbus_connection.int_page) {
- hv_free_hyperv_page((unsigned long)vmbus_connection.int_page);
+ hv_free_hyperv_page(vmbus_connection.int_page);
vmbus_connection.int_page = NULL;
}
set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[0], 1);
set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[1], 1);
- hv_free_hyperv_page((unsigned long)vmbus_connection.monitor_pages[0]);
- hv_free_hyperv_page((unsigned long)vmbus_connection.monitor_pages[1]);
+ hv_free_hyperv_page(vmbus_connection.monitor_pages[0]);
+ hv_free_hyperv_page(vmbus_connection.monitor_pages[1]);
vmbus_connection.monitor_pages[0] = NULL;
vmbus_connection.monitor_pages[1] = NULL;
}
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
index dffcc894f117..0d7a3ba66396 100644
--- a/drivers/hv/hv_balloon.c
+++ b/drivers/hv/hv_balloon.c
@@ -1628,7 +1628,7 @@ static int hv_free_page_report(struct page_reporting_dev_info *pr_dev_info,
WARN_ON_ONCE(nents > HV_MEMORY_HINT_MAX_GPA_PAGE_RANGES);
WARN_ON_ONCE(sgl->length < (HV_HYP_PAGE_SIZE << page_reporting_order));
local_irq_save(flags);
- hint = *(struct hv_memory_hint **)this_cpu_ptr(hyperv_pcpu_input_arg);
+ hint = *this_cpu_ptr(hyperv_pcpu_input_arg);
if (!hint) {
local_irq_restore(flags);
return -ENOSPC;
diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
index 542a1d53b303..6a2258fef1fe 100644
--- a/drivers/hv/hv_common.c
+++ b/drivers/hv/hv_common.c
@@ -115,12 +115,12 @@ void *hv_alloc_hyperv_zeroed_page(void)
}
EXPORT_SYMBOL_GPL(hv_alloc_hyperv_zeroed_page);
-void hv_free_hyperv_page(unsigned long addr)
+void hv_free_hyperv_page(void *addr)
{
if (PAGE_SIZE == HV_HYP_PAGE_SIZE)
- free_page(addr);
+ free_page((unsigned long)addr);
else
- kfree((void *)addr);
+ kfree(addr);
}
EXPORT_SYMBOL_GPL(hv_free_hyperv_page);
@@ -253,7 +253,7 @@ static void hv_kmsg_dump_unregister(void)
atomic_notifier_chain_unregister(&panic_notifier_list,
&hyperv_panic_report_block);
- hv_free_hyperv_page((unsigned long)hv_panic_page);
+ hv_free_hyperv_page(hv_panic_page);
hv_panic_page = NULL;
}
@@ -270,7 +270,7 @@ static void hv_kmsg_dump_register(void)
ret = kmsg_dump_register(&hv_kmsg_dumper);
if (ret) {
pr_err("Hyper-V: kmsg dump register error 0x%x\n", ret);
- hv_free_hyperv_page((unsigned long)hv_panic_page);
+ hv_free_hyperv_page(hv_panic_page);
hv_panic_page = NULL;
}
}
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..023807859be7 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
@@ -13,9 +13,11 @@
#include <linux/crc16.h>
#include <linux/debugfs.h>
+#include <linux/delay.h>
#include <linux/hid.h>
#include <linux/hwmon.h>
#include <linux/jiffies.h>
+#include <linux/ktime.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/seq_file.h>
@@ -29,6 +31,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 +39,7 @@
enum kinds {
d5next, farbwerk, farbwerk360, octo, quadro,
highflownext, aquaero, poweradjust3, aquastreamult,
- aquastreamxt
+ aquastreamxt, leakshield
};
static const char *const aqc_device_names[] = {
@@ -46,6 +49,7 @@ static const char *const aqc_device_names[] = {
[octo] = "octo",
[quadro] = "quadro",
[highflownext] = "highflownext",
+ [leakshield] = "leakshield",
[aquastreamxt] = "aquastreamxt",
[aquaero] = "aquaero",
[aquastreamult] = "aquastreamultimate",
@@ -61,6 +65,8 @@ static const char *const aqc_device_names[] = {
#define CTRL_REPORT_ID 0x03
#define AQUAERO_CTRL_REPORT_ID 0x0b
+#define CTRL_REPORT_DELAY 200 /* ms */
+
/* The HID report that the official software always sends
* after writing values, currently same for all devices
*/
@@ -93,7 +99,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 +242,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 +432,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",
@@ -496,6 +531,9 @@ struct aqc_data {
int secondary_ctrl_report_size;
u8 *secondary_ctrl_report;
+ ktime_t last_ctrl_report_op;
+ int ctrl_report_delay; /* Delay between two ctrl report operations, in ms */
+
int buffer_size;
u8 *buffer;
int checksum_start;
@@ -529,7 +567,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];
@@ -577,17 +618,35 @@ static int aqc_aquastreamxt_convert_fan_rpm(u16 val)
return 0;
}
+static void aqc_delay_ctrl_report(struct aqc_data *priv)
+{
+ /*
+ * If previous read or write is too close to this one, delay the current operation
+ * to give the device enough time to process the previous one.
+ */
+ if (priv->ctrl_report_delay) {
+ s64 delta = ktime_ms_delta(ktime_get(), priv->last_ctrl_report_op);
+
+ if (delta < priv->ctrl_report_delay)
+ msleep(priv->ctrl_report_delay - delta);
+ }
+}
+
/* Expects the mutex to be locked */
static int aqc_get_ctrl_data(struct aqc_data *priv)
{
int ret;
+ aqc_delay_ctrl_report(priv);
+
memset(priv->buffer, 0x00, priv->buffer_size);
ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
if (ret < 0)
ret = -ENODATA;
+ priv->last_ctrl_report_op = ktime_get();
+
return ret;
}
@@ -597,6 +656,8 @@ static int aqc_send_ctrl_data(struct aqc_data *priv)
int ret;
u16 checksum;
+ aqc_delay_ctrl_report(priv);
+
/* Checksum is not needed for Aquaero */
if (priv->kind != aquaero) {
/* Init and xorout value for CRC-16/USB is 0xffff */
@@ -612,12 +673,16 @@ static int aqc_send_ctrl_data(struct aqc_data *priv)
ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size,
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
if (ret < 0)
- return ret;
+ goto record_access_and_ret;
/* The official software sends this report after every change, so do it here as well */
ret = hid_hw_raw_request(priv->hdev, priv->secondary_ctrl_report_id,
priv->secondary_ctrl_report, priv->secondary_ctrl_report_size,
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+
+record_access_and_ret:
+ priv->last_ctrl_report_op = ktime_get();
+
return ret;
}
@@ -747,6 +812,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 +834,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 +1015,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);
@@ -969,7 +1058,7 @@ static int aqc_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
if (ret < 0)
return ret;
- *val = aqc_percent_to_pwm(ret);
+ *val = aqc_percent_to_pwm(*val);
break;
}
break;
@@ -1151,7 +1240,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 +1314,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 +1325,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 +1367,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 +1404,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;
}
@@ -1443,6 +1555,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->buffer_size = AQUAERO_CTRL_REPORT_SIZE;
priv->temp_ctrl_offset = AQUAERO_TEMP_CTRL_OFFSET;
+ priv->ctrl_report_delay = CTRL_REPORT_DELAY;
priv->temp_label = label_temp_sensors;
priv->virtual_temp_label = label_virtual_temp_sensors;
@@ -1466,6 +1579,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->temp_ctrl_offset = D5NEXT_TEMP_CTRL_OFFSET;
priv->buffer_size = D5NEXT_CTRL_REPORT_SIZE;
+ priv->ctrl_report_delay = CTRL_REPORT_DELAY;
priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES;
@@ -1516,6 +1630,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->temp_ctrl_offset = OCTO_TEMP_CTRL_OFFSET;
priv->buffer_size = OCTO_CTRL_REPORT_SIZE;
+ priv->ctrl_report_delay = CTRL_REPORT_DELAY;
priv->power_cycle_count_offset = OCTO_POWER_CYCLES;
@@ -1543,6 +1658,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->temp_ctrl_offset = QUADRO_TEMP_CTRL_OFFSET;
priv->buffer_size = QUADRO_CTRL_REPORT_SIZE;
+ priv->ctrl_report_delay = CTRL_REPORT_DELAY;
priv->flow_pulses_ctrl_offset = QUADRO_FLOW_PULSES_CTRL_OFFSET;
priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;
@@ -1571,6 +1687,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 +1842,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/k10temp.c b/drivers/hwmon/k10temp.c
index 7b177b9fbb09..a267b11731a8 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -77,6 +77,13 @@ static DEFINE_MUTEX(nb_smu_ind_mutex);
#define ZEN_CUR_TEMP_RANGE_SEL_MASK BIT(19)
#define ZEN_CUR_TEMP_TJ_SEL_MASK GENMASK(17, 16)
+/*
+ * AMD's Industrial processor 3255 supports temperature from -40 deg to 105 deg Celsius.
+ * Use the model name to identify 3255 CPUs and set a flag to display negative temperature.
+ * Do not round off to zero for negative Tctl or Tdie values if the flag is set
+ */
+#define AMD_I3255_STR "3255"
+
struct k10temp_data {
struct pci_dev *pdev;
void (*read_htcreg)(struct pci_dev *pdev, u32 *regval);
@@ -86,6 +93,7 @@ struct k10temp_data {
u32 show_temp;
bool is_zen;
u32 ccd_offset;
+ bool disp_negative;
};
#define TCTL_BIT 0
@@ -204,12 +212,12 @@ static int k10temp_read_temp(struct device *dev, u32 attr, int channel,
switch (channel) {
case 0: /* Tctl */
*val = get_raw_temp(data);
- if (*val < 0)
+ if (*val < 0 && !data->disp_negative)
*val = 0;
break;
case 1: /* Tdie */
*val = get_raw_temp(data) - data->temp_offset;
- if (*val < 0)
+ if (*val < 0 && !data->disp_negative)
*val = 0;
break;
case 2 ... 13: /* Tccd{1-12} */
@@ -405,6 +413,11 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
data->pdev = pdev;
data->show_temp |= BIT(TCTL_BIT); /* Always show Tctl */
+ if (boot_cpu_data.x86 == 0x17 &&
+ strstr(boot_cpu_data.x86_model_id, AMD_I3255_STR)) {
+ data->disp_negative = true;
+ }
+
if (boot_cpu_data.x86 == 0x15 &&
((boot_cpu_data.x86_model & 0xf0) == 0x60 ||
(boot_cpu_data.x86_model & 0xf0) == 0x70)) {
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..08ce4984151d 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
@@ -915,14 +955,25 @@ static const u16 scale_in[15] = {
800, 800
};
-static inline long in_from_reg(u8 reg, u8 nr)
+/*
+ * NCT6798 scaling:
+ * CPUVC, IN1, AVSB, 3VCC, IN0, IN8, IN4, 3VSB, VBAT, VTT, IN5, IN6, IN2,
+ * IN3, IN7
+ * Additional scales to be added later: IN9 (800), VHIF (1600)
+ */
+static const u16 scale_in_6798[15] = {
+ 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 1600, 1600, 1600, 800,
+ 800, 800
+};
+
+static inline long in_from_reg(u8 reg, u8 nr, const u16 *scales)
{
- return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
+ return DIV_ROUND_CLOSEST(reg * scales[nr], 100);
}
-static inline u8 in_to_reg(u32 val, u8 nr)
+static inline u8 in_to_reg(u32 val, u8 nr, const u16 *scales)
{
- return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
+ return clamp_val(DIV_ROUND_CLOSEST(val * 100, scales[nr]), 0, 255);
}
/* TSI temperatures are in 8.3 format */
@@ -1109,6 +1160,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 +1514,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;
@@ -1631,7 +1684,8 @@ show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
if (IS_ERR(data))
return PTR_ERR(data);
- return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
+ return sprintf(buf, "%ld\n",
+ in_from_reg(data->in[nr][index], nr, data->scale_in));
}
static ssize_t
@@ -1649,7 +1703,7 @@ store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
if (err < 0)
return err;
mutex_lock(&data->update_lock);
- data->in[nr][index] = in_to_reg(val, nr);
+ data->in[nr][index] = in_to_reg(val, nr, data->scale_in);
err = nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr], data->in[nr][index]);
mutex_unlock(&data->update_lock);
return err ? : count;
@@ -3109,6 +3163,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;
@@ -3419,6 +3474,7 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
mutex_init(&data->update_lock);
data->name = nct6775_device_names[data->kind];
data->bank = 0xff; /* Force initial bank selection */
+ data->scale_in = scale_in;
switch (data->kind) {
case nct6106:
@@ -3807,10 +3863,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 +3917,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 +3981,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;
@@ -3926,6 +3990,9 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
break;
}
+ if (data->kind == nct6798 || data->kind == nct6799)
+ data->scale_in = scale_in_6798;
+
reg_temp = NCT6779_REG_TEMP;
num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
if (data->kind == nct6791) {
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..a409d7a0b813 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, 0xe6);
+
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..a84c6ce7275d 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*/
@@ -98,6 +98,7 @@ struct nct6775_data {
u8 bank; /* current register bank */
u8 in_num; /* number of in inputs we have */
u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */
+ const u16 *scale_in; /* internal scaling factors */
unsigned int rpm[NUM_FAN];
u16 fan_min[NUM_FAN];
u8 fan_pulses[NUM_FAN];
diff --git a/drivers/hwmon/nct7802.c b/drivers/hwmon/nct7802.c
index a175f8283695..024cff151c36 100644
--- a/drivers/hwmon/nct7802.c
+++ b/drivers/hwmon/nct7802.c
@@ -725,7 +725,7 @@ static umode_t nct7802_temp_is_visible(struct kobject *kobj,
if (index >= 38 && index < 46 && !(reg & 0x01)) /* PECI 0 */
return 0;
- if (index >= 0x46 && (!(reg & 0x02))) /* PECI 1 */
+ if (index >= 46 && !(reg & 0x02)) /* PECI 1 */
return 0;
return attr->mode;
@@ -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..1e1cc67bcdea 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,123 @@ 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 umode_t tt_toggle_is_visible(struct kobject *kobj,
+ struct attribute *attr, int n)
{
- return write_to_ec(dev, OXP_SENSOR_PWM_ENABLE_REG, 0x01);
+ switch (board) {
+ case aok_zoe_a1:
+ case oxp_mini_amd_a07:
+ case oxp_mini_amd_pro:
+ return attr->mode;
+ default:
+ break;
+ }
+ return 0;
}
-static int oxp_pwm_disable(const struct device *dev)
+static ssize_t tt_toggle_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
- return write_to_ec(dev, OXP_SENSOR_PWM_ENABLE_REG, 0x00);
+ 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(OXP_SENSOR_PWM_ENABLE_REG, 0x01);
+}
+
+static int oxp_pwm_disable(void)
+{
+ return write_to_ec(OXP_SENSOR_PWM_ENABLE_REG, 0x00);
}
/* Callbacks for hwmon interface */
@@ -178,9 +330,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 +364,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 +385,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 +405,21 @@ static const struct hwmon_channel_info * const oxp_platform_sensors[] = {
NULL,
};
+static struct attribute *oxp_ec_attrs[] = {
+ &dev_attr_tt_toggle.attr,
+ NULL
+};
+
+static struct attribute_group oxp_ec_attribute_group = {
+ .is_visible = tt_toggle_is_visible,
+ .attrs = oxp_ec_attrs,
+};
+
+static const struct attribute_group *oxp_ec_groups[] = {
+ &oxp_ec_attribute_group,
+ NULL
+};
+
static const struct hwmon_ops oxp_ec_hwmon_ops = {
.is_visible = oxp_ec_hwmon_is_visible,
.read = oxp_platform_read,
@@ -276,7 +449,7 @@ 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;
hwdev = devm_hwmon_device_register_with_info(dev, "oxpec", NULL,
&oxp_ec_chip_info, NULL);
@@ -287,6 +460,7 @@ static int oxp_platform_probe(struct platform_device *pdev)
static struct platform_driver oxp_platform_driver = {
.driver = {
.name = "oxp-platform",
+ .dev_groups = oxp_ec_groups,
},
.probe = oxp_platform_probe,
};
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..7c5f4b10a7c1 100644
--- a/drivers/hwmon/pmbus/bel-pfe.c
+++ b/drivers/hwmon/pmbus/bel-pfe.c
@@ -17,12 +17,13 @@
enum chips {pfe1100, pfe3000};
/*
- * Disable status check for pfe3000 devices, because some devices report
- * communication error (invalid command) for VOUT_MODE command (0x20)
- * although correct VOUT_MODE (0x16) is returned: it leads to incorrect
- * exponent in linear mode.
+ * Disable status check because some devices report communication error
+ * (invalid command) for VOUT_MODE command (0x20) although the correct
+ * VOUT_MODE (0x16) is returned: it leads to incorrect exponent in linear
+ * mode.
+ * This affects both pfe3000 and pfe1100.
*/
-static struct pmbus_platform_data pfe3000_plat_data = {
+static struct pmbus_platform_data pfe_plat_data = {
.flags = PMBUS_SKIP_STATUS_CHECK,
};
@@ -94,16 +95,15 @@ static int pfe_pmbus_probe(struct i2c_client *client)
int model;
model = (int)i2c_match_id(pfe_device_id, client)->driver_data;
+ client->dev.platform_data = &pfe_plat_data;
/*
* PFE3000-12-069RA devices may not stay in page 0 during device
* probe which leads to probe failure (read status word failed).
* So let's set the device to page 0 at the beginning.
*/
- if (model == pfe3000) {
- client->dev.platform_data = &pfe3000_plat_data;
+ if (model == pfe3000)
i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
- }
return pmbus_do_probe(client, &pfe_driver_info[model]);
}
@@ -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..69a4e62b6c8d 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;
@@ -2745,9 +2745,8 @@ static const struct pmbus_status_category __maybe_unused pmbus_status_flag_map[]
},
};
-static int _pmbus_is_enabled(struct device *dev, u8 page)
+static int _pmbus_is_enabled(struct i2c_client *client, u8 page)
{
- struct i2c_client *client = to_i2c_client(dev->parent);
int ret;
ret = _pmbus_read_byte_data(client, page, PMBUS_OPERATION);
@@ -2758,17 +2757,16 @@ static int _pmbus_is_enabled(struct device *dev, u8 page)
return !!(ret & PB_OPERATION_CONTROL_ON);
}
-static int __maybe_unused pmbus_is_enabled(struct device *dev, u8 page)
+static int __maybe_unused pmbus_is_enabled(struct i2c_client *client, u8 page)
{
- struct i2c_client *client = to_i2c_client(dev->parent);
struct pmbus_data *data = i2c_get_clientdata(client);
int ret;
mutex_lock(&data->update_lock);
- ret = _pmbus_is_enabled(dev, page);
+ ret = _pmbus_is_enabled(client, page);
mutex_unlock(&data->update_lock);
- return !!(ret & PB_OPERATION_CONTROL_ON);
+ return ret;
}
#define to_dev_attr(_dev_attr) \
@@ -2844,7 +2842,7 @@ static int _pmbus_get_flags(struct pmbus_data *data, u8 page, unsigned int *flag
if (status < 0)
return status;
- if (_pmbus_is_enabled(dev, page)) {
+ if (_pmbus_is_enabled(client, page)) {
if (status & PB_STATUS_OFF) {
*flags |= REGULATOR_ERROR_FAIL;
*event |= REGULATOR_EVENT_FAIL;
@@ -2898,7 +2896,10 @@ static int __maybe_unused pmbus_get_flags(struct pmbus_data *data, u8 page, unsi
#if IS_ENABLED(CONFIG_REGULATOR)
static int pmbus_regulator_is_enabled(struct regulator_dev *rdev)
{
- return pmbus_is_enabled(rdev_get_dev(rdev), rdev_get_id(rdev));
+ struct device *dev = rdev_get_dev(rdev);
+ struct i2c_client *client = to_i2c_client(dev->parent);
+
+ return pmbus_is_enabled(client, rdev_get_id(rdev));
}
static int _pmbus_regulator_on_off(struct regulator_dev *rdev, bool enable)
@@ -2945,6 +2946,7 @@ static int pmbus_regulator_get_status(struct regulator_dev *rdev)
struct pmbus_data *data = i2c_get_clientdata(client);
u8 page = rdev_get_id(rdev);
int status, ret;
+ int event;
mutex_lock(&data->update_lock);
status = pmbus_get_status(client, page, PMBUS_STATUS_WORD);
@@ -2964,7 +2966,7 @@ static int pmbus_regulator_get_status(struct regulator_dev *rdev)
goto unlock;
}
- ret = pmbus_regulator_get_error_flags(rdev, &status);
+ ret = _pmbus_get_flags(data, rdev_get_id(rdev), &status, &event, false);
if (ret)
goto unlock;
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 1fc4fd79a1c6..7720619909d6 100644
--- a/drivers/hwtracing/coresight/coresight-trbe.c
+++ b/drivers/hwtracing/coresight/coresight-trbe.c
@@ -218,7 +218,7 @@ static inline void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr)
* Enable the TRBE without clearing LIMITPTR which
* might be required for fetching the buffer limits.
*/
- trblimitr |= TRBLIMITR_ENABLE;
+ trblimitr |= TRBLIMITR_EL1_E;
write_sysreg_s(trblimitr, SYS_TRBLIMITR_EL1);
/* Synchronize the TRBE enable event */
@@ -236,7 +236,7 @@ static inline void set_trbe_disabled(struct trbe_cpudata *cpudata)
* Disable the TRBE without clearing LIMITPTR which
* might be required for fetching the buffer limits.
*/
- trblimitr &= ~TRBLIMITR_ENABLE;
+ trblimitr &= ~TRBLIMITR_EL1_E;
write_sysreg_s(trblimitr, SYS_TRBLIMITR_EL1);
if (trbe_needs_drain_after_disable(cpudata))
@@ -582,12 +582,12 @@ static void clr_trbe_status(void)
u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1);
WARN_ON(is_trbe_enabled());
- trbsr &= ~TRBSR_IRQ;
- trbsr &= ~TRBSR_TRG;
- trbsr &= ~TRBSR_WRAP;
- trbsr &= ~(TRBSR_EC_MASK << TRBSR_EC_SHIFT);
- trbsr &= ~(TRBSR_BSC_MASK << TRBSR_BSC_SHIFT);
- trbsr &= ~TRBSR_STOP;
+ trbsr &= ~TRBSR_EL1_IRQ;
+ trbsr &= ~TRBSR_EL1_TRG;
+ trbsr &= ~TRBSR_EL1_WRAP;
+ trbsr &= ~TRBSR_EL1_EC_MASK;
+ trbsr &= ~TRBSR_EL1_BSC_MASK;
+ trbsr &= ~TRBSR_EL1_S;
write_sysreg_s(trbsr, SYS_TRBSR_EL1);
}
@@ -596,13 +596,13 @@ static void set_trbe_limit_pointer_enabled(struct trbe_buf *buf)
u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1);
unsigned long addr = buf->trbe_limit;
- WARN_ON(!IS_ALIGNED(addr, (1UL << TRBLIMITR_LIMIT_SHIFT)));
+ WARN_ON(!IS_ALIGNED(addr, (1UL << TRBLIMITR_EL1_LIMIT_SHIFT)));
WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE));
- trblimitr &= ~TRBLIMITR_NVM;
- trblimitr &= ~(TRBLIMITR_FILL_MODE_MASK << TRBLIMITR_FILL_MODE_SHIFT);
- trblimitr &= ~(TRBLIMITR_TRIG_MODE_MASK << TRBLIMITR_TRIG_MODE_SHIFT);
- trblimitr &= ~(TRBLIMITR_LIMIT_MASK << TRBLIMITR_LIMIT_SHIFT);
+ trblimitr &= ~TRBLIMITR_EL1_nVM;
+ trblimitr &= ~TRBLIMITR_EL1_FM_MASK;
+ trblimitr &= ~TRBLIMITR_EL1_TM_MASK;
+ trblimitr &= ~TRBLIMITR_EL1_LIMIT_MASK;
/*
* Fill trace buffer mode is used here while configuring the
@@ -613,14 +613,15 @@ static void set_trbe_limit_pointer_enabled(struct trbe_buf *buf)
* trace data in the interrupt handler, before reconfiguring
* the TRBE.
*/
- trblimitr |= (TRBE_FILL_MODE_FILL & TRBLIMITR_FILL_MODE_MASK) << TRBLIMITR_FILL_MODE_SHIFT;
+ trblimitr |= (TRBLIMITR_EL1_FM_FILL << TRBLIMITR_EL1_FM_SHIFT) &
+ TRBLIMITR_EL1_FM_MASK;
/*
* Trigger mode is not used here while configuring the TRBE for
* the trace capture. Hence just keep this in the ignore mode.
*/
- trblimitr |= (TRBE_TRIG_MODE_IGNORE & TRBLIMITR_TRIG_MODE_MASK) <<
- TRBLIMITR_TRIG_MODE_SHIFT;
+ trblimitr |= (TRBLIMITR_EL1_TM_IGNR << TRBLIMITR_EL1_TM_SHIFT) &
+ TRBLIMITR_EL1_TM_MASK;
trblimitr |= (addr & PAGE_MASK);
set_trbe_enabled(buf->cpudata, trblimitr);
}
@@ -1005,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/coresight-trbe.h b/drivers/hwtracing/coresight/coresight-trbe.h
index 98ff1b17ad07..77cbb5c63878 100644
--- a/drivers/hwtracing/coresight/coresight-trbe.h
+++ b/drivers/hwtracing/coresight/coresight-trbe.h
@@ -30,7 +30,7 @@ static inline bool is_trbe_enabled(void)
{
u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1);
- return trblimitr & TRBLIMITR_ENABLE;
+ return trblimitr & TRBLIMITR_EL1_E;
}
#define TRBE_EC_OTHERS 0
@@ -39,7 +39,7 @@ static inline bool is_trbe_enabled(void)
static inline int get_trbe_ec(u64 trbsr)
{
- return (trbsr >> TRBSR_EC_SHIFT) & TRBSR_EC_MASK;
+ return (trbsr & TRBSR_EL1_EC_MASK) >> TRBSR_EL1_EC_SHIFT;
}
#define TRBE_BSC_NOT_STOPPED 0
@@ -48,63 +48,55 @@ static inline int get_trbe_ec(u64 trbsr)
static inline int get_trbe_bsc(u64 trbsr)
{
- return (trbsr >> TRBSR_BSC_SHIFT) & TRBSR_BSC_MASK;
+ return (trbsr & TRBSR_EL1_BSC_MASK) >> TRBSR_EL1_BSC_SHIFT;
}
static inline void clr_trbe_irq(void)
{
u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1);
- trbsr &= ~TRBSR_IRQ;
+ trbsr &= ~TRBSR_EL1_IRQ;
write_sysreg_s(trbsr, SYS_TRBSR_EL1);
}
static inline bool is_trbe_irq(u64 trbsr)
{
- return trbsr & TRBSR_IRQ;
+ return trbsr & TRBSR_EL1_IRQ;
}
static inline bool is_trbe_trg(u64 trbsr)
{
- return trbsr & TRBSR_TRG;
+ return trbsr & TRBSR_EL1_TRG;
}
static inline bool is_trbe_wrap(u64 trbsr)
{
- return trbsr & TRBSR_WRAP;
+ return trbsr & TRBSR_EL1_WRAP;
}
static inline bool is_trbe_abort(u64 trbsr)
{
- return trbsr & TRBSR_ABORT;
+ return trbsr & TRBSR_EL1_EA;
}
static inline bool is_trbe_running(u64 trbsr)
{
- return !(trbsr & TRBSR_STOP);
+ return !(trbsr & TRBSR_EL1_S);
}
-#define TRBE_TRIG_MODE_STOP 0
-#define TRBE_TRIG_MODE_IRQ 1
-#define TRBE_TRIG_MODE_IGNORE 3
-
-#define TRBE_FILL_MODE_FILL 0
-#define TRBE_FILL_MODE_WRAP 1
-#define TRBE_FILL_MODE_CIRCULAR_BUFFER 3
-
static inline bool get_trbe_flag_update(u64 trbidr)
{
- return trbidr & TRBIDR_FLAG;
+ return trbidr & TRBIDR_EL1_F;
}
static inline bool is_trbe_programmable(u64 trbidr)
{
- return !(trbidr & TRBIDR_PROG);
+ return !(trbidr & TRBIDR_EL1_P);
}
static inline int get_trbe_address_align(u64 trbidr)
{
- return (trbidr >> TRBIDR_ALIGN_SHIFT) & TRBIDR_ALIGN_MASK;
+ return (trbidr & TRBIDR_EL1_Align_MASK) >> TRBIDR_EL1_Align_SHIFT;
}
static inline unsigned long get_trbe_write_pointer(void)
@@ -121,7 +113,7 @@ static inline void set_trbe_write_pointer(unsigned long addr)
static inline unsigned long get_trbe_limit_pointer(void)
{
u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1);
- unsigned long addr = trblimitr & (TRBLIMITR_LIMIT_MASK << TRBLIMITR_LIMIT_SHIFT);
+ unsigned long addr = trblimitr & TRBLIMITR_EL1_LIMIT_MASK;
WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE));
return addr;
@@ -130,7 +122,7 @@ static inline unsigned long get_trbe_limit_pointer(void)
static inline unsigned long get_trbe_base_pointer(void)
{
u64 trbbaser = read_sysreg_s(SYS_TRBBASER_EL1);
- unsigned long addr = trbbaser & (TRBBASER_BASE_MASK << TRBBASER_BASE_SHIFT);
+ unsigned long addr = trbbaser & TRBBASER_EL1_BASE_MASK;
WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE));
return addr;
@@ -139,7 +131,7 @@ static inline unsigned long get_trbe_base_pointer(void)
static inline void set_trbe_base_pointer(unsigned long addr)
{
WARN_ON(is_trbe_enabled());
- WARN_ON(!IS_ALIGNED(addr, (1UL << TRBBASER_BASE_SHIFT)));
+ WARN_ON(!IS_ALIGNED(addr, (1UL << TRBBASER_EL1_BASE_SHIFT)));
WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE));
write_sysreg_s(addr, SYS_TRBBASER_EL1);
}
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..05c80680dff4 100644
--- a/drivers/i2c/busses/i2c-bcm-iproc.c
+++ b/drivers/i2c/busses/i2c-bcm-iproc.c
@@ -233,13 +233,14 @@ static inline u32 iproc_i2c_rd_reg(struct bcm_iproc_i2c_dev *iproc_i2c,
u32 offset)
{
u32 val;
+ unsigned long flags;
if (iproc_i2c->idm_base) {
- spin_lock(&iproc_i2c->idm_lock);
+ spin_lock_irqsave(&iproc_i2c->idm_lock, flags);
writel(iproc_i2c->ape_addr_mask,
iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET);
val = readl(iproc_i2c->base + offset);
- spin_unlock(&iproc_i2c->idm_lock);
+ spin_unlock_irqrestore(&iproc_i2c->idm_lock, flags);
} else {
val = readl(iproc_i2c->base + offset);
}
@@ -250,12 +251,14 @@ static inline u32 iproc_i2c_rd_reg(struct bcm_iproc_i2c_dev *iproc_i2c,
static inline void iproc_i2c_wr_reg(struct bcm_iproc_i2c_dev *iproc_i2c,
u32 offset, u32 val)
{
+ unsigned long flags;
+
if (iproc_i2c->idm_base) {
- spin_lock(&iproc_i2c->idm_lock);
+ spin_lock_irqsave(&iproc_i2c->idm_lock, flags);
writel(iproc_i2c->ape_addr_mask,
iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET);
writel(val, iproc_i2c->base + offset);
- spin_unlock(&iproc_i2c->idm_lock);
+ spin_unlock_irqrestore(&iproc_i2c->idm_lock, flags);
} else {
writel(val, iproc_i2c->base + offset);
}
@@ -1107,7 +1110,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 +1126,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 +1261,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..24bef0025c98 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
@@ -526,9 +588,21 @@ i2c_dw_read(struct dw_i2c_dev *dev)
u32 flags = msgs[dev->msg_read_idx].flags;
regmap_read(dev->map, DW_IC_DATA_CMD, &tmp);
+ tmp &= DW_IC_DATA_CMD_DAT;
/* Ensure length byte is a valid value */
- if (flags & I2C_M_RECV_LEN &&
- (tmp & DW_IC_DATA_CMD_DAT) <= I2C_SMBUS_BLOCK_MAX && tmp > 0) {
+ if (flags & I2C_M_RECV_LEN) {
+ /*
+ * if IC_EMPTYFIFO_HOLD_MASTER_EN is set, which cannot be
+ * detected from the registers, the controller can be
+ * disabled if the STOP bit is set. But it is only set
+ * after receiving block data response length in
+ * I2C_FUNC_SMBUS_BLOCK_DATA case. That needs to read
+ * another byte with STOP bit set when the block data
+ * response length is invalid to complete the transaction.
+ */
+ if (!tmp || tmp > I2C_SMBUS_BLOCK_MAX)
+ tmp = 1;
+
len = i2c_dw_recv_len(dev, tmp);
}
*buf++ = tmp;
@@ -559,13 +633,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 +928,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 +942,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 +1008,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-hisi.c b/drivers/i2c/busses/i2c-hisi.c
index e067671b3ce2..0980c773cb5b 100644
--- a/drivers/i2c/busses/i2c-hisi.c
+++ b/drivers/i2c/busses/i2c-hisi.c
@@ -330,6 +330,14 @@ static irqreturn_t hisi_i2c_irq(int irq, void *context)
struct hisi_i2c_controller *ctlr = context;
u32 int_stat;
+ /*
+ * Don't handle the interrupt if cltr->completion is NULL. We may
+ * reach here because the interrupt is spurious or the transfer is
+ * started by another port (e.g. firmware) rather than us.
+ */
+ if (!ctlr->completion)
+ return IRQ_NONE;
+
int_stat = readl(ctlr->iobase + HISI_I2C_INT_MSTAT);
hisi_i2c_clear_int(ctlr, int_stat);
if (!(int_stat & HISI_I2C_INT_ALL))
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..150d923ca7f1 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -209,6 +209,9 @@ static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx)
lpi2c_imx_set_mode(lpi2c_imx);
clk_rate = clk_get_rate(lpi2c_imx->clks[0].clk);
+ if (!clk_rate)
+ return -EINVAL;
+
if (lpi2c_imx->mode == HS || lpi2c_imx->mode == ULTRA_FAST)
filt = 0;
else
@@ -217,7 +220,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 +626,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 +634,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 +670,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..f460a7fb4eae 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -307,7 +307,6 @@ static void mpc_i2c_setup_512x(struct device_node *node,
{
struct device_node *node_ctrl;
void __iomem *ctrl;
- const u32 *pval;
u32 idx;
/* Enable I2C interrupts for mpc5121 */
@@ -316,9 +315,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 +890,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 +957,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..212f412f1c74 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,22 +1029,15 @@ 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)
{
- struct resource *res = &adev->res;
struct nmk_i2c_dev *dev = amba_get_drvdata(adev);
i2c_del_adapter(&dev->adap);
@@ -1066,8 +1046,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));
}
static struct i2c_vendor_data vendor_stn8815 = {
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..421735acfa14 100644
--- a/drivers/i2c/busses/i2c-scmi.c
+++ b/drivers/i2c/busses/i2c-scmi.c
@@ -13,9 +13,6 @@
#include <linux/i2c.h>
#include <linux/acpi.h>
-/* SMBUS HID definition as supported by Microsoft Windows */
-#define ACPI_SMBUS_MS_HID "SMB0001"
-
struct smbus_methods_t {
char *mt_info;
char *mt_sbr;
@@ -404,19 +401,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..fa6020dced59 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,15 @@ 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;
+ dev_err(dev, "failed to retrieve reset controller: %pe\n",
+ p2wi->rstc);
+ 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 +301,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..03fc10b45bd6 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,28 +427,22 @@ 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) {
+ if (i2c_dev->hw->has_apb_dma) {
if (!IS_ENABLED(CONFIG_TEGRA20_APB_DMA)) {
dev_dbg(i2c_dev->dev, "APB DMA support not enabled\n");
return 0;
@@ -459,25 +452,19 @@ 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);
+ i2c_dev->dma_chan = NULL;
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 +626,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 +638,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 +690,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 +833,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 +920,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 +959,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 +977,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 +993,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 +1004,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 +1017,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 +1327,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 +1629,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 +1654,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 +1688,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 +1806,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 +1849,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 +1858,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 +1878,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 +1966,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..b3bb97762c85 100644
--- a/drivers/i2c/busses/i2c-xiic.c
+++ b/drivers/i2c/busses/i2c-xiic.c
@@ -721,6 +721,8 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
wakeup_req = 1;
wakeup_code = STATE_ERROR;
}
+ /* don't try to handle other events */
+ goto out;
}
if (pend & XIIC_INTR_RX_FULL_MASK) {
/* Receive register/FIFO is full */
@@ -1256,16 +1258,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 +1283,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 +1304,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 +1325,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 +1349,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 +1384,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 aa2d19db2b1d..256c2d42e350 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1839,6 +1839,41 @@ static bool __init intel_idle_verify_cstate(unsigned int mwait_hint)
return true;
}
+static void state_update_enter_method(struct cpuidle_state *state, int cstate)
+{
+ if (state->flags & CPUIDLE_FLAG_INIT_XSTATE) {
+ /*
+ * Combining with XSTATE with IBRS or IRQ_ENABLE flags
+ * is not currently supported but this driver.
+ */
+ WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IBRS);
+ WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE);
+ state->enter = intel_idle_xstate;
+ return;
+ }
+
+ if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) &&
+ state->flags & CPUIDLE_FLAG_IBRS) {
+ /*
+ * IBRS mitigation requires that C-states are entered
+ * with interrupts disabled.
+ */
+ WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE);
+ state->enter = intel_idle_ibrs;
+ return;
+ }
+
+ if (state->flags & CPUIDLE_FLAG_IRQ_ENABLE) {
+ state->enter = intel_idle_irq;
+ return;
+ }
+
+ if (force_irq_on) {
+ pr_info("forced intel_idle_irq for state %d\n", cstate);
+ state->enter = intel_idle_irq;
+ }
+}
+
static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
{
int cstate;
@@ -1894,28 +1929,8 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
drv->states[drv->state_count] = cpuidle_state_table[cstate];
state = &drv->states[drv->state_count];
- if (state->flags & CPUIDLE_FLAG_INIT_XSTATE) {
- /*
- * Combining with XSTATE with IBRS or IRQ_ENABLE flags
- * is not currently supported but this driver.
- */
- WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IBRS);
- WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE);
- state->enter = intel_idle_xstate;
- } else if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) &&
- state->flags & CPUIDLE_FLAG_IBRS) {
- /*
- * IBRS mitigation requires that C-states are entered
- * with interrupts disabled.
- */
- WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE);
- state->enter = intel_idle_ibrs;
- } else if (state->flags & CPUIDLE_FLAG_IRQ_ENABLE) {
- state->enter = intel_idle_irq;
- } else if (force_irq_on) {
- pr_info("forced intel_idle_irq for state %d\n", cstate);
- state->enter = intel_idle_irq;
- }
+ state_update_enter_method(state, cstate);
+
if ((disabled_states_mask & BIT(drv->state_count)) ||
((icpu->use_acpi || force_use_acpi) &&
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..7bc3ebfe8081 100644
--- a/drivers/iio/adc/ad7192.c
+++ b/drivers/iio/adc/ad7192.c
@@ -62,7 +62,6 @@
#define AD7192_MODE_STA_MASK BIT(20) /* Status Register transmission Mask */
#define AD7192_MODE_CLKSRC(x) (((x) & 0x3) << 18) /* Clock Source Select */
#define AD7192_MODE_SINC3 BIT(15) /* SINC3 Filter Select */
-#define AD7192_MODE_ACX BIT(14) /* AC excitation enable(AD7195 only)*/
#define AD7192_MODE_ENPAR BIT(13) /* Parity Enable */
#define AD7192_MODE_CLKDIV BIT(12) /* Clock divide by 2 (AD7190/2 only)*/
#define AD7192_MODE_SCYCLE BIT(11) /* Single cycle conversion */
@@ -91,6 +90,7 @@
/* Configuration Register Bit Designations (AD7192_REG_CONF) */
#define AD7192_CONF_CHOP BIT(23) /* CHOP enable */
+#define AD7192_CONF_ACX BIT(22) /* AC excitation enable(AD7195 only) */
#define AD7192_CONF_REFSEL BIT(20) /* REFIN1/REFIN2 Reference Select */
#define AD7192_CONF_CHAN(x) ((x) << 8) /* Channel select */
#define AD7192_CONF_CHAN_MASK (0x7FF << 8) /* Channel select mask */
@@ -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;
@@ -472,7 +472,7 @@ static ssize_t ad7192_show_ac_excitation(struct device *dev,
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7192_state *st = iio_priv(indio_dev);
- return sysfs_emit(buf, "%d\n", !!(st->mode & AD7192_MODE_ACX));
+ return sysfs_emit(buf, "%d\n", !!(st->conf & AD7192_CONF_ACX));
}
static ssize_t ad7192_show_bridge_switch(struct device *dev,
@@ -513,13 +513,13 @@ static ssize_t ad7192_set(struct device *dev,
ad_sd_write_reg(&st->sd, AD7192_REG_GPOCON, 1, st->gpocon);
break;
- case AD7192_REG_MODE:
+ case AD7192_REG_CONF:
if (val)
- st->mode |= AD7192_MODE_ACX;
+ st->conf |= AD7192_CONF_ACX;
else
- st->mode &= ~AD7192_MODE_ACX;
+ st->conf &= ~AD7192_CONF_ACX;
- ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
+ ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf);
break;
default:
ret = -EINVAL;
@@ -579,12 +579,11 @@ static IIO_DEVICE_ATTR(bridge_switch_en, 0644,
static IIO_DEVICE_ATTR(ac_excitation_en, 0644,
ad7192_show_ac_excitation, ad7192_set,
- AD7192_REG_MODE);
+ AD7192_REG_CONF);
static struct attribute *ad7192_attributes[] = {
&iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr,
&iio_dev_attr_bridge_switch_en.dev_attr.attr,
- &iio_dev_attr_ac_excitation_en.dev_attr.attr,
NULL
};
@@ -595,6 +594,7 @@ static const struct attribute_group ad7192_attribute_group = {
static struct attribute *ad7195_attributes[] = {
&iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr,
&iio_dev_attr_bridge_switch_en.dev_attr.attr,
+ &iio_dev_attr_ac_excitation_en.dev_attr.attr,
NULL
};
@@ -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..aea83f369437 100644
--- a/drivers/iio/adc/ina2xx-adc.c
+++ b/drivers/iio/adc/ina2xx-adc.c
@@ -124,6 +124,7 @@ static const struct regmap_config ina2xx_regmap_config = {
enum ina2xx_ids { ina219, ina226 };
struct ina2xx_config {
+ const char *name;
u16 config_default;
int calibration_value;
int shunt_voltage_lsb; /* nV */
@@ -155,6 +156,7 @@ struct ina2xx_chip_info {
static const struct ina2xx_config ina2xx_config[] = {
[ina219] = {
+ .name = "ina219",
.config_default = INA219_CONFIG_DEFAULT,
.calibration_value = 4096,
.shunt_voltage_lsb = 10000,
@@ -164,6 +166,7 @@ static const struct ina2xx_config ina2xx_config[] = {
.chip_id = ina219,
},
[ina226] = {
+ .name = "ina226",
.config_default = INA226_CONFIG_DEFAULT,
.calibration_value = 2048,
.shunt_voltage_lsb = 2500,
@@ -996,7 +999,7 @@ static int ina2xx_probe(struct i2c_client *client)
/* Patch the current config register with default. */
val = chip->config->config_default;
- if (id->driver_data == ina226) {
+ if (type == ina226) {
ina226_set_average(chip, INA226_DEFAULT_AVG, &val);
ina226_set_int_time_vbus(chip, INA226_DEFAULT_IT, &val);
ina226_set_int_time_vshunt(chip, INA226_DEFAULT_IT, &val);
@@ -1015,7 +1018,7 @@ static int ina2xx_probe(struct i2c_client *client)
}
indio_dev->modes = INDIO_DIRECT_MODE;
- if (id->driver_data == ina226) {
+ if (type == ina226) {
indio_dev->channels = ina226_channels;
indio_dev->num_channels = ARRAY_SIZE(ina226_channels);
indio_dev->info = &ina226_info;
@@ -1024,7 +1027,7 @@ static int ina2xx_probe(struct i2c_client *client)
indio_dev->num_channels = ARRAY_SIZE(ina219_channels);
indio_dev->info = &ina219_info;
}
- indio_dev->name = id->name;
+ indio_dev->name = id ? id->name : chip->config->name;
ret = devm_iio_kfifo_buffer_setup(&client->dev, indio_dev,
&ina2xx_setup_ops);
@@ -1090,7 +1093,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..eb78a6f17fd0 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)
@@ -916,12 +916,6 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
goto err_vref;
}
- ret = clk_prepare_enable(priv->core_clk);
- if (ret) {
- dev_err(dev, "failed to enable core clk\n");
- goto err_core_clk;
- }
-
regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
@@ -948,8 +942,6 @@ err_adc_clk:
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
MESON_SAR_ADC_REG3_ADC_EN, 0);
meson_sar_adc_set_bandgap(indio_dev, false);
- clk_disable_unprepare(priv->core_clk);
-err_core_clk:
regulator_disable(priv->vref);
err_vref:
meson_sar_adc_unlock(indio_dev);
@@ -977,8 +969,6 @@ static void meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
meson_sar_adc_set_bandgap(indio_dev, false);
- clk_disable_unprepare(priv->core_clk);
-
regulator_disable(priv->vref);
if (!ret)
@@ -1211,7 +1201,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
if (IS_ERR(priv->clkin))
return dev_err_probe(dev, PTR_ERR(priv->clkin), "failed to get clkin\n");
- priv->core_clk = devm_clk_get(dev, "core");
+ priv->core_clk = devm_clk_get_enabled(dev, "core");
if (IS_ERR(priv->core_clk))
return dev_err_probe(dev, PTR_ERR(priv->core_clk), "failed to get core clk\n");
@@ -1294,15 +1284,26 @@ static int meson_sar_adc_remove(struct platform_device *pdev)
static int meson_sar_adc_suspend(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
meson_sar_adc_hw_disable(indio_dev);
+ clk_disable_unprepare(priv->core_clk);
+
return 0;
}
static int meson_sar_adc_resume(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
+ int ret;
+
+ ret = clk_prepare_enable(priv->core_clk);
+ if (ret) {
+ dev_err(dev, "failed to enable core clk\n");
+ return ret;
+ }
return meson_sar_adc_hw_enable(indio_dev);
}
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/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
index 943e9e14d1e9..b72d39fc2434 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -253,7 +253,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
platform_set_drvdata(pdev, indio_dev);
state->ec = ec->ec_dev;
- state->msg = devm_kzalloc(&pdev->dev,
+ state->msg = devm_kzalloc(&pdev->dev, sizeof(*state->msg) +
max((u16)sizeof(struct ec_params_motion_sense),
state->ec->max_response), GFP_KERNEL);
if (!state->msg)
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/frequency/admv1013.c b/drivers/iio/frequency/admv1013.c
index 9bf8337806fc..8c8e0bbfc99f 100644
--- a/drivers/iio/frequency/admv1013.c
+++ b/drivers/iio/frequency/admv1013.c
@@ -344,9 +344,12 @@ static int admv1013_update_quad_filters(struct admv1013_state *st)
static int admv1013_update_mixer_vgate(struct admv1013_state *st)
{
- unsigned int vcm, mixer_vgate;
+ unsigned int mixer_vgate;
+ int vcm;
vcm = regulator_get_voltage(st->reg);
+ if (vcm < 0)
+ return vcm;
if (vcm < 1800000)
mixer_vgate = (2389 * vcm / 1000000 + 8100) / 100;
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_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
index 6a18b363cf73..b6e6b1df8a61 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
@@ -2687,7 +2687,7 @@ unknown_format:
static int lsm6dsx_get_acpi_mount_matrix(struct device *dev,
struct iio_mount_matrix *orientation)
{
- return false;
+ return -EOPNOTSUPP;
}
#endif
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-core.c b/drivers/iio/industrialio-core.c
index c117f50d0cf3..adcba832e6fa 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -1888,7 +1888,7 @@ static const struct iio_buffer_setup_ops noop_ring_setup_ops;
int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
{
struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
- struct fwnode_handle *fwnode;
+ struct fwnode_handle *fwnode = NULL;
int ret;
if (!indio_dev->info)
@@ -1899,7 +1899,8 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
/* If the calling driver did not initialize firmware node, do it here */
if (dev_fwnode(&indio_dev->dev))
fwnode = dev_fwnode(&indio_dev->dev);
- else
+ /* The default dummy IIO device has no parent */
+ else if (indio_dev->dev.parent)
fwnode = dev_fwnode(indio_dev->dev.parent);
device_set_node(&indio_dev->dev, fwnode);
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..b50bf8973d9a
--- /dev/null
+++ b/drivers/iio/light/rohm-bu27008.c
@@ -0,0 +1,1042 @@
+// 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 = 'u', \
+ .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, 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, &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_get_fmt(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ long mask)
+{
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ return IIO_VAL_INT_PLUS_NANO;
+ case IIO_CHAN_INFO_INT_TIME:
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+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,
+ .write_raw_get_fmt = &bu27008_write_raw_get_fmt,
+ .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..bf3de853a811 100644
--- a/drivers/iio/light/rohm-bu27034.c
+++ b/drivers/iio/light/rohm-bu27034.c
@@ -575,7 +575,7 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan,
return -EINVAL;
if (chan == BU27034_CHAN_ALS) {
- if (val == 0 && val2 == 1000)
+ if (val == 0 && val2 == 1000000)
return 0;
return -EINVAL;
@@ -587,7 +587,7 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan,
goto unlock_out;
ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, time_sel,
- val, val2 * 1000, &gain_sel);
+ val, val2, &gain_sel);
if (ret) {
/*
* Could not support scale with given time. Need to change time.
@@ -624,7 +624,7 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan,
/* Can we provide requested scale with this time? */
ret = iio_gts_find_gain_sel_for_scale_using_time(
- &data->gts, new_time_sel, val, val2 * 1000,
+ &data->gts, new_time_sel, val, val2,
&gain_sel);
if (ret)
continue;
@@ -1217,6 +1217,21 @@ static int bu27034_read_raw(struct iio_dev *idev,
}
}
+static int bu27034_write_raw_get_fmt(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ long mask)
+{
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ return IIO_VAL_INT_PLUS_NANO;
+ case IIO_CHAN_INFO_INT_TIME:
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
static int bu27034_write_raw(struct iio_dev *idev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
@@ -1267,6 +1282,7 @@ static int bu27034_read_avail(struct iio_dev *idev,
static const struct iio_info bu27034_info = {
.read_raw = &bu27034_read_raw,
.write_raw = &bu27034_write_raw,
+ .write_raw_get_fmt = &bu27034_write_raw_get_fmt,
.read_avail = &bu27034_read_avail,
};
@@ -1500,8 +1516,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..9891c7dc2af5 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -4062,6 +4062,8 @@ static int resolve_prepare_src(struct rdma_id_private *id_priv,
RDMA_CM_ADDR_QUERY)))
return -EINVAL;
+ } else {
+ memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr));
}
if (cma_family(id_priv) != dst_addr->sa_family) {
@@ -4805,8 +4807,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/core/umem.c b/drivers/infiniband/core/umem.c
index 755a9c57db6f..f9ab671c8eda 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -85,6 +85,8 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
dma_addr_t mask;
int i;
+ umem->iova = va = virt;
+
if (umem->is_odp) {
unsigned int page_size = BIT(to_ib_umem_odp(umem)->page_shift);
@@ -100,7 +102,6 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
*/
pgsz_bitmap &= GENMASK(BITS_PER_LONG - 1, PAGE_SHIFT);
- umem->iova = va = virt;
/* The best result is the smallest page size that results in the minimum
* number of required pages. Compute the largest page size that could
* work based on VA address bits that don't change.
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..03cc45a5458d 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)
@@ -797,7 +869,10 @@ fail:
int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
{
struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
+ struct bnxt_qplib_qp *qplib_qp = &qp->qplib_qp;
struct bnxt_re_dev *rdev = qp->rdev;
+ struct bnxt_qplib_nq *scq_nq = NULL;
+ struct bnxt_qplib_nq *rcq_nq = NULL;
unsigned int flags;
int rc;
@@ -831,6 +906,15 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
ib_umem_release(qp->rumem);
ib_umem_release(qp->sumem);
+ /* Flush all the entries of notification queue associated with
+ * given qp.
+ */
+ scq_nq = qplib_qp->scq->nq;
+ rcq_nq = qplib_qp->rcq->nq;
+ bnxt_re_synchronize_nq(scq_nq);
+ if (scq_nq != rcq_nq)
+ bnxt_re_synchronize_nq(rcq_nq);
+
return 0;
}
@@ -3955,6 +4039,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 +4078,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 +4111,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 +4120,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 +4131,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..63e98e2d3596 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)
@@ -1152,6 +1253,8 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode)
rc = bnxt_re_setup_chip_ctx(rdev, wqe_mode);
if (rc) {
+ bnxt_unregister_dev(rdev->en_dev);
+ clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
ibdev_err(&rdev->ibdev, "Failed to get chip context\n");
return -EINVAL;
}
@@ -1200,7 +1303,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",
@@ -1425,8 +1528,8 @@ static void bnxt_re_remove(struct auxiliary_device *adev)
}
bnxt_re_setup_cc(rdev, false);
ib_unregister_device(&rdev->ibdev);
- ib_dealloc_device(&rdev->ibdev);
bnxt_re_dev_uninit(rdev);
+ ib_dealloc_device(&rdev->ibdev);
skip_remove:
mutex_unlock(&bnxt_re_mutex);
}
@@ -1497,6 +1600,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..a42555623aed 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
@@ -381,6 +381,24 @@ static void bnxt_qplib_service_nq(struct tasklet_struct *t)
spin_unlock_bh(&hwq->lock);
}
+/* bnxt_re_synchronize_nq - self polling notification queue.
+ * @nq - notification queue pointer
+ *
+ * This function will start polling entries of a given notification queue
+ * for all pending entries.
+ * This function is useful to synchronize notification entries while resources
+ * are going away.
+ */
+
+void bnxt_re_synchronize_nq(struct bnxt_qplib_nq *nq)
+{
+ int budget = nq->budget;
+
+ nq->budget = nq->hwq.max_elements;
+ bnxt_qplib_service_nq(&nq->nq_tasklet);
+ nq->budget = budget;
+}
+
static irqreturn_t bnxt_qplib_nq_irq(int irq, void *dev_instance)
{
struct bnxt_qplib_nq *nq = dev_instance;
@@ -399,18 +417,22 @@ 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)
{
- tasklet_disable(&nq->nq_tasklet);
+ if (!nq->requested)
+ return;
+
+ nq->requested = false;
/* Mask h/w interrupt */
bnxt_qplib_ring_nq_db(&nq->nq_db.dbinfo, nq->res->cctx, false);
/* Sync with last running IRQ handler */
synchronize_irq(nq->msix_vec);
+ irq_set_affinity_hint(nq->msix_vec, NULL);
+ free_irq(nq->msix_vec, nq);
+ kfree(nq->name);
+ nq->name = NULL;
+
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;
- }
+ tasklet_disable(&nq->nq_tasklet);
}
void bnxt_qplib_disable_nq(struct bnxt_qplib_nq *nq)
@@ -436,6 +458,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 +470,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 +491,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 +501,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 +510,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 +520,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 +641,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 +686,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 +695,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 +759,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 +807,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 +827,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 +862,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 +950,6 @@ sq_swq:
kfree(sq->swq);
fail_sq:
bnxt_qplib_free_hwq(res, &sq->hwq);
-exit:
return rc;
}
@@ -992,7 +1014,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 +1162,6 @@ sq_swq:
kfree(sq->swq);
fail_sq:
bnxt_qplib_free_hwq(res, &sq->hwq);
-exit:
return rc;
}
@@ -1614,7 +1635,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 +1659,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 +2088,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 +2123,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 +2131,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 +2523,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 +2533,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 +2589,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 +2602,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 +2612,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 +2674,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 +2702,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 +2712,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 +2781,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 +2803,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..404b851091ca 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;
@@ -553,6 +553,7 @@ int bnxt_qplib_process_flush_list(struct bnxt_qplib_cq *cq,
struct bnxt_qplib_cqe *cqe,
int num_cqes);
void bnxt_qplib_flush_cqn_wq(struct bnxt_qplib_qp *qp);
+void bnxt_re_synchronize_nq(struct bnxt_qplib_nq *nq);
static inline void *bnxt_qplib_get_swqe(struct bnxt_qplib_q *que, u32 *swq_idx)
{
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
index de9069103177..bc3aea4592b9 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 (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++;
}
- 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;
+
+ 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,25 +985,28 @@ void bnxt_qplib_rcfw_stop_irq(struct bnxt_qplib_rcfw *rcfw, bool kill)
struct bnxt_qplib_creq_ctx *creq;
creq = &rcfw->creq;
- tasklet_disable(&creq->creq_tasklet);
+
+ if (!creq->requested)
+ return;
+
+ creq->requested = false;
/* Mask h/w interrupts */
bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo, rcfw->res->cctx, false);
/* Sync with last running IRQ-handler */
synchronize_irq(creq->msix_vec);
+ free_irq(creq->msix_vec, rcfw);
+ kfree(creq->irq_name);
+ creq->irq_name = NULL;
+ atomic_set(&rcfw->rcfw_intr_enabled, 0);
if (kill)
tasklet_kill(&creq->creq_tasklet);
-
- if (creq->requested) {
- free_irq(creq->msix_vec, rcfw);
- creq->requested = false;
- }
+ tasklet_disable(&creq->creq_tasklet);
}
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 +1016,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 +1026,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 +1040,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 +1090,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 +1154,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 +1174,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 +1190,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..739d942761d1 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,15 @@ 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);
+ mutex_init(&res->dpi_tbl_lock);
+ 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 +890,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 +900,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/chip.c b/drivers/infiniband/hw/hfi1/chip.c
index 9dbb89e9f4af..baaa4406d5e6 100644
--- a/drivers/infiniband/hw/hfi1/chip.c
+++ b/drivers/infiniband/hw/hfi1/chip.c
@@ -12307,6 +12307,7 @@ static void free_cntrs(struct hfi1_devdata *dd)
if (dd->synth_stats_timer.function)
del_timer_sync(&dd->synth_stats_timer);
+ cancel_work_sync(&dd->update_cntr_work);
ppd = (struct hfi1_pportdata *)(dd + 1);
for (i = 0; i < dd->num_pports; i++, ppd++) {
kfree(ppd->cntrs);
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/ctrl.c b/drivers/infiniband/hw/irdma/ctrl.c
index d88c9184007e..45e3344daa04 100644
--- a/drivers/infiniband/hw/irdma/ctrl.c
+++ b/drivers/infiniband/hw/irdma/ctrl.c
@@ -2712,13 +2712,13 @@ static int irdma_sc_cq_modify(struct irdma_sc_cq *cq,
*/
void irdma_check_cqp_progress(struct irdma_cqp_timeout *timeout, struct irdma_sc_dev *dev)
{
- if (timeout->compl_cqp_cmds != dev->cqp_cmd_stats[IRDMA_OP_CMPL_CMDS]) {
- timeout->compl_cqp_cmds = dev->cqp_cmd_stats[IRDMA_OP_CMPL_CMDS];
+ u64 completed_ops = atomic64_read(&dev->cqp->completed_ops);
+
+ if (timeout->compl_cqp_cmds != completed_ops) {
+ timeout->compl_cqp_cmds = completed_ops;
timeout->count = 0;
- } else {
- if (dev->cqp_cmd_stats[IRDMA_OP_REQ_CMDS] !=
- timeout->compl_cqp_cmds)
- timeout->count++;
+ } else if (timeout->compl_cqp_cmds != dev->cqp->requested_ops) {
+ timeout->count++;
}
}
@@ -2761,7 +2761,7 @@ static int irdma_cqp_poll_registers(struct irdma_sc_cqp *cqp, u32 tail,
if (newtail != tail) {
/* SUCCESS */
IRDMA_RING_MOVE_TAIL(cqp->sq_ring);
- cqp->dev->cqp_cmd_stats[IRDMA_OP_CMPL_CMDS]++;
+ atomic64_inc(&cqp->completed_ops);
return 0;
}
udelay(cqp->dev->hw_attrs.max_sleep_count);
@@ -3121,8 +3121,8 @@ int irdma_sc_cqp_init(struct irdma_sc_cqp *cqp,
info->dev->cqp = cqp;
IRDMA_RING_INIT(cqp->sq_ring, cqp->sq_size);
- cqp->dev->cqp_cmd_stats[IRDMA_OP_REQ_CMDS] = 0;
- cqp->dev->cqp_cmd_stats[IRDMA_OP_CMPL_CMDS] = 0;
+ cqp->requested_ops = 0;
+ atomic64_set(&cqp->completed_ops, 0);
/* for the cqp commands backlog. */
INIT_LIST_HEAD(&cqp->dev->cqp_cmd_head);
@@ -3274,7 +3274,7 @@ __le64 *irdma_sc_cqp_get_next_send_wqe_idx(struct irdma_sc_cqp *cqp, u64 scratch
if (ret_code)
return NULL;
- cqp->dev->cqp_cmd_stats[IRDMA_OP_REQ_CMDS]++;
+ cqp->requested_ops++;
if (!*wqe_idx)
cqp->polarity = !cqp->polarity;
wqe = cqp->sq_base[*wqe_idx].elem;
@@ -3363,6 +3363,9 @@ int irdma_sc_ccq_get_cqe_info(struct irdma_sc_cq *ccq,
if (polarity != ccq->cq_uk.polarity)
return -ENOENT;
+ /* Ensure CEQE contents are read after valid bit is checked */
+ dma_rmb();
+
get_64bit_val(cqe, 8, &qp_ctx);
cqp = (struct irdma_sc_cqp *)(unsigned long)qp_ctx;
info->error = (bool)FIELD_GET(IRDMA_CQ_ERROR, temp);
@@ -3397,7 +3400,7 @@ int irdma_sc_ccq_get_cqe_info(struct irdma_sc_cq *ccq,
dma_wmb(); /* make sure shadow area is updated before moving tail */
IRDMA_RING_MOVE_TAIL(cqp->sq_ring);
- ccq->dev->cqp_cmd_stats[IRDMA_OP_CMPL_CMDS]++;
+ atomic64_inc(&cqp->completed_ops);
return ret_code;
}
@@ -4009,13 +4012,17 @@ int irdma_sc_get_next_aeqe(struct irdma_sc_aeq *aeq,
u8 polarity;
aeqe = IRDMA_GET_CURRENT_AEQ_ELEM(aeq);
- get_64bit_val(aeqe, 0, &compl_ctx);
get_64bit_val(aeqe, 8, &temp);
polarity = (u8)FIELD_GET(IRDMA_AEQE_VALID, temp);
if (aeq->polarity != polarity)
return -ENOENT;
+ /* Ensure AEQE contents are read after valid bit is checked */
+ dma_rmb();
+
+ get_64bit_val(aeqe, 0, &compl_ctx);
+
print_hex_dump_debug("WQE: AEQ_ENTRY WQE", DUMP_PREFIX_OFFSET, 16, 8,
aeqe, 16, false);
diff --git a/drivers/infiniband/hw/irdma/defs.h b/drivers/infiniband/hw/irdma/defs.h
index 6014b9d06a9b..d06e45d2c23f 100644
--- a/drivers/infiniband/hw/irdma/defs.h
+++ b/drivers/infiniband/hw/irdma/defs.h
@@ -191,32 +191,30 @@ enum irdma_cqp_op_type {
IRDMA_OP_MANAGE_VF_PBLE_BP = 25,
IRDMA_OP_QUERY_FPM_VAL = 26,
IRDMA_OP_COMMIT_FPM_VAL = 27,
- IRDMA_OP_REQ_CMDS = 28,
- IRDMA_OP_CMPL_CMDS = 29,
- IRDMA_OP_AH_CREATE = 30,
- IRDMA_OP_AH_MODIFY = 31,
- IRDMA_OP_AH_DESTROY = 32,
- IRDMA_OP_MC_CREATE = 33,
- IRDMA_OP_MC_DESTROY = 34,
- IRDMA_OP_MC_MODIFY = 35,
- IRDMA_OP_STATS_ALLOCATE = 36,
- IRDMA_OP_STATS_FREE = 37,
- IRDMA_OP_STATS_GATHER = 38,
- IRDMA_OP_WS_ADD_NODE = 39,
- IRDMA_OP_WS_MODIFY_NODE = 40,
- IRDMA_OP_WS_DELETE_NODE = 41,
- IRDMA_OP_WS_FAILOVER_START = 42,
- IRDMA_OP_WS_FAILOVER_COMPLETE = 43,
- IRDMA_OP_SET_UP_MAP = 44,
- IRDMA_OP_GEN_AE = 45,
- IRDMA_OP_QUERY_RDMA_FEATURES = 46,
- IRDMA_OP_ALLOC_LOCAL_MAC_ENTRY = 47,
- IRDMA_OP_ADD_LOCAL_MAC_ENTRY = 48,
- IRDMA_OP_DELETE_LOCAL_MAC_ENTRY = 49,
- IRDMA_OP_CQ_MODIFY = 50,
+ IRDMA_OP_AH_CREATE = 28,
+ IRDMA_OP_AH_MODIFY = 29,
+ IRDMA_OP_AH_DESTROY = 30,
+ IRDMA_OP_MC_CREATE = 31,
+ IRDMA_OP_MC_DESTROY = 32,
+ IRDMA_OP_MC_MODIFY = 33,
+ IRDMA_OP_STATS_ALLOCATE = 34,
+ IRDMA_OP_STATS_FREE = 35,
+ IRDMA_OP_STATS_GATHER = 36,
+ IRDMA_OP_WS_ADD_NODE = 37,
+ IRDMA_OP_WS_MODIFY_NODE = 38,
+ IRDMA_OP_WS_DELETE_NODE = 39,
+ IRDMA_OP_WS_FAILOVER_START = 40,
+ IRDMA_OP_WS_FAILOVER_COMPLETE = 41,
+ IRDMA_OP_SET_UP_MAP = 42,
+ IRDMA_OP_GEN_AE = 43,
+ IRDMA_OP_QUERY_RDMA_FEATURES = 44,
+ IRDMA_OP_ALLOC_LOCAL_MAC_ENTRY = 45,
+ IRDMA_OP_ADD_LOCAL_MAC_ENTRY = 46,
+ IRDMA_OP_DELETE_LOCAL_MAC_ENTRY = 47,
+ IRDMA_OP_CQ_MODIFY = 48,
/* Must be last entry*/
- IRDMA_MAX_CQP_OPS = 51,
+ IRDMA_MAX_CQP_OPS = 49,
};
/* CQP SQ WQES */
diff --git a/drivers/infiniband/hw/irdma/hw.c b/drivers/infiniband/hw/irdma/hw.c
index 795f7fd4f257..457368e324e1 100644
--- a/drivers/infiniband/hw/irdma/hw.c
+++ b/drivers/infiniband/hw/irdma/hw.c
@@ -191,6 +191,7 @@ static void irdma_set_flush_fields(struct irdma_sc_qp *qp,
case IRDMA_AE_AMP_MWBIND_INVALID_RIGHTS:
case IRDMA_AE_AMP_MWBIND_BIND_DISABLED:
case IRDMA_AE_AMP_MWBIND_INVALID_BOUNDS:
+ case IRDMA_AE_AMP_MWBIND_VALID_STAG:
qp->flush_code = FLUSH_MW_BIND_ERR;
qp->event_type = IRDMA_QP_EVENT_ACCESS_ERR;
break;
@@ -2075,7 +2076,7 @@ void irdma_cqp_ce_handler(struct irdma_pci_f *rf, struct irdma_sc_cq *cq)
cqp_request->compl_info.error = info.error;
if (cqp_request->waiting) {
- cqp_request->request_done = true;
+ WRITE_ONCE(cqp_request->request_done, true);
wake_up(&cqp_request->waitq);
irdma_put_cqp_request(&rf->cqp, cqp_request);
} else {
diff --git a/drivers/infiniband/hw/irdma/main.h b/drivers/infiniband/hw/irdma/main.h
index def6dd58dcd4..2323962cdeac 100644
--- a/drivers/infiniband/hw/irdma/main.h
+++ b/drivers/infiniband/hw/irdma/main.h
@@ -161,8 +161,8 @@ struct irdma_cqp_request {
void (*callback_fcn)(struct irdma_cqp_request *cqp_request);
void *param;
struct irdma_cqp_compl_info compl_info;
+ bool request_done; /* READ/WRITE_ONCE macros operate on it */
bool waiting:1;
- bool request_done:1;
bool dynamic:1;
};
diff --git a/drivers/infiniband/hw/irdma/puda.c b/drivers/infiniband/hw/irdma/puda.c
index 4ec9639f1bdb..562531712ea4 100644
--- a/drivers/infiniband/hw/irdma/puda.c
+++ b/drivers/infiniband/hw/irdma/puda.c
@@ -230,6 +230,9 @@ static int irdma_puda_poll_info(struct irdma_sc_cq *cq,
if (valid_bit != cq_uk->polarity)
return -ENOENT;
+ /* Ensure CQE contents are read after valid bit is checked */
+ dma_rmb();
+
if (cq->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2)
ext_valid = (bool)FIELD_GET(IRDMA_CQ_EXTCQE, qword3);
@@ -243,6 +246,9 @@ static int irdma_puda_poll_info(struct irdma_sc_cq *cq,
if (polarity != cq_uk->polarity)
return -ENOENT;
+ /* Ensure ext CQE contents are read after ext valid bit is checked */
+ dma_rmb();
+
IRDMA_RING_MOVE_HEAD_NOCHECK(cq_uk->cq_ring);
if (!IRDMA_RING_CURRENT_HEAD(cq_uk->cq_ring))
cq_uk->polarity = !cq_uk->polarity;
diff --git a/drivers/infiniband/hw/irdma/type.h b/drivers/infiniband/hw/irdma/type.h
index 5ee68604e59f..a20709577ab0 100644
--- a/drivers/infiniband/hw/irdma/type.h
+++ b/drivers/infiniband/hw/irdma/type.h
@@ -365,6 +365,8 @@ struct irdma_sc_cqp {
struct irdma_dcqcn_cc_params dcqcn_params;
__le64 *host_ctx;
u64 *scratch_array;
+ u64 requested_ops;
+ atomic64_t completed_ops;
u32 cqp_id;
u32 sq_size;
u32 hw_sq_size;
diff --git a/drivers/infiniband/hw/irdma/uk.c b/drivers/infiniband/hw/irdma/uk.c
index 16183e894da7..280d633d4ec4 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));
}
}
@@ -1159,7 +1161,7 @@ int irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq,
}
wqe_idx = (u32)FIELD_GET(IRDMA_CQ_WQEIDX, qword3);
info->qp_handle = (irdma_qp_handle)(unsigned long)qp;
- info->op_type = (u8)FIELD_GET(IRDMA_CQ_SQ, qword3);
+ info->op_type = (u8)FIELD_GET(IRDMACQ_OP, qword3);
if (info->q_type == IRDMA_CQE_QTYPE_RQ) {
u32 array_idx;
@@ -1525,6 +1527,9 @@ void irdma_uk_clean_cq(void *q, struct irdma_cq_uk *cq)
if (polarity != temp)
break;
+ /* Ensure CQE contents are read after valid bit is checked */
+ dma_rmb();
+
get_64bit_val(cqe, 8, &comp_ctx);
if ((void *)(unsigned long)comp_ctx == q)
set_64bit_val(cqe, 8, 0);
diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c
index 71e1c5d34709..eb083f70b09f 100644
--- a/drivers/infiniband/hw/irdma/utils.c
+++ b/drivers/infiniband/hw/irdma/utils.c
@@ -481,7 +481,7 @@ void irdma_free_cqp_request(struct irdma_cqp *cqp,
if (cqp_request->dynamic) {
kfree(cqp_request);
} else {
- cqp_request->request_done = false;
+ WRITE_ONCE(cqp_request->request_done, false);
cqp_request->callback_fcn = NULL;
cqp_request->waiting = false;
@@ -515,7 +515,7 @@ irdma_free_pending_cqp_request(struct irdma_cqp *cqp,
{
if (cqp_request->waiting) {
cqp_request->compl_info.error = true;
- cqp_request->request_done = true;
+ WRITE_ONCE(cqp_request->request_done, true);
wake_up(&cqp_request->waitq);
}
wait_event_timeout(cqp->remove_wq,
@@ -567,11 +567,11 @@ static int irdma_wait_event(struct irdma_pci_f *rf,
bool cqp_error = false;
int err_code = 0;
- cqp_timeout.compl_cqp_cmds = rf->sc_dev.cqp_cmd_stats[IRDMA_OP_CMPL_CMDS];
+ cqp_timeout.compl_cqp_cmds = atomic64_read(&rf->sc_dev.cqp->completed_ops);
do {
irdma_cqp_ce_handler(rf, &rf->ccq.sc_cq);
if (wait_event_timeout(cqp_request->waitq,
- cqp_request->request_done,
+ READ_ONCE(cqp_request->request_done),
msecs_to_jiffies(CQP_COMPL_WAIT_TIME_MS)))
break;
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/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 456656617c33..9d08aa99f3cb 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -565,15 +565,15 @@ static int set_qp_rss(struct mlx4_ib_dev *dev, struct mlx4_ib_rss *rss_ctx,
return (-EOPNOTSUPP);
}
- if (ucmd->rx_hash_fields_mask & ~(MLX4_IB_RX_HASH_SRC_IPV4 |
- MLX4_IB_RX_HASH_DST_IPV4 |
- MLX4_IB_RX_HASH_SRC_IPV6 |
- MLX4_IB_RX_HASH_DST_IPV6 |
- MLX4_IB_RX_HASH_SRC_PORT_TCP |
- MLX4_IB_RX_HASH_DST_PORT_TCP |
- MLX4_IB_RX_HASH_SRC_PORT_UDP |
- MLX4_IB_RX_HASH_DST_PORT_UDP |
- MLX4_IB_RX_HASH_INNER)) {
+ if (ucmd->rx_hash_fields_mask & ~(u64)(MLX4_IB_RX_HASH_SRC_IPV4 |
+ MLX4_IB_RX_HASH_DST_IPV4 |
+ MLX4_IB_RX_HASH_SRC_IPV6 |
+ MLX4_IB_RX_HASH_DST_IPV6 |
+ MLX4_IB_RX_HASH_SRC_PORT_TCP |
+ MLX4_IB_RX_HASH_DST_PORT_TCP |
+ MLX4_IB_RX_HASH_SRC_PORT_UDP |
+ MLX4_IB_RX_HASH_DST_PORT_UDP |
+ MLX4_IB_RX_HASH_INNER)) {
pr_debug("RX Hash fields_mask has unsupported mask (0x%llx)\n",
ucmd->rx_hash_fields_mask);
return (-EOPNOTSUPP);
diff --git a/drivers/infiniband/hw/mlx5/ib_rep.c b/drivers/infiniband/hw/mlx5/ib_rep.c
index ddcfc116b19a..c7a4ee896121 100644
--- a/drivers/infiniband/hw/mlx5/ib_rep.c
+++ b/drivers/infiniband/hw/mlx5/ib_rep.c
@@ -30,45 +30,65 @@ mlx5_ib_set_vport_rep(struct mlx5_core_dev *dev,
static void mlx5_ib_register_peer_vport_reps(struct mlx5_core_dev *mdev);
+static void mlx5_ib_num_ports_update(struct mlx5_core_dev *dev, u32 *num_ports)
+{
+ struct mlx5_core_dev *peer_dev;
+ int i;
+
+ mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) {
+ u32 peer_num_ports = mlx5_eswitch_get_total_vports(peer_dev);
+
+ if (mlx5_lag_is_mpesw(peer_dev))
+ *num_ports += peer_num_ports;
+ else
+ /* Only 1 ib port is the representor for all uplinks */
+ *num_ports += peer_num_ports - 1;
+ }
+}
+
static int
mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
{
u32 num_ports = mlx5_eswitch_get_total_vports(dev);
+ struct mlx5_core_dev *lag_master = dev;
const struct mlx5_ib_profile *profile;
struct mlx5_core_dev *peer_dev;
struct mlx5_ib_dev *ibdev;
- int second_uplink = false;
- u32 peer_num_ports;
+ int new_uplink = false;
int vport_index;
int ret;
+ int i;
vport_index = rep->vport_index;
if (mlx5_lag_is_shared_fdb(dev)) {
- peer_dev = mlx5_lag_get_peer_mdev(dev);
- peer_num_ports = mlx5_eswitch_get_total_vports(peer_dev);
if (mlx5_lag_is_master(dev)) {
- if (mlx5_lag_is_mpesw(dev))
- num_ports += peer_num_ports;
- else
- num_ports += peer_num_ports - 1;
-
+ mlx5_ib_num_ports_update(dev, &num_ports);
} else {
if (rep->vport == MLX5_VPORT_UPLINK) {
if (!mlx5_lag_is_mpesw(dev))
return 0;
- second_uplink = true;
+ new_uplink = true;
}
+ mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) {
+ u32 peer_n_ports = mlx5_eswitch_get_total_vports(peer_dev);
+
+ if (mlx5_lag_is_master(peer_dev))
+ lag_master = peer_dev;
+ else if (!mlx5_lag_is_mpesw(dev))
+ /* Only 1 ib port is the representor for all uplinks */
+ peer_n_ports--;
- vport_index += peer_num_ports;
- dev = peer_dev;
+ if (mlx5_get_dev_index(peer_dev) < mlx5_get_dev_index(dev))
+ vport_index += peer_n_ports;
+ }
}
}
- if (rep->vport == MLX5_VPORT_UPLINK && !second_uplink)
+ if (rep->vport == MLX5_VPORT_UPLINK && !new_uplink)
profile = &raw_eth_profile;
else
- return mlx5_ib_set_vport_rep(dev, rep, vport_index);
+ return mlx5_ib_set_vport_rep(lag_master, rep, vport_index);
ibdev = ib_alloc_device(mlx5_ib_dev, ib_dev);
if (!ibdev)
@@ -85,8 +105,8 @@ mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
vport_index = rep->vport_index;
ibdev->port[vport_index].rep = rep;
ibdev->port[vport_index].roce.netdev =
- mlx5_ib_get_rep_netdev(dev->priv.eswitch, rep->vport);
- ibdev->mdev = dev;
+ mlx5_ib_get_rep_netdev(lag_master->priv.eswitch, rep->vport);
+ ibdev->mdev = lag_master;
ibdev->num_ports = num_ports;
ret = __mlx5_ib_add(ibdev, profile);
@@ -94,8 +114,8 @@ mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
goto fail_add;
rep->rep_data[REP_IB].priv = ibdev;
- if (mlx5_lag_is_shared_fdb(dev))
- mlx5_ib_register_peer_vport_reps(dev);
+ if (mlx5_lag_is_shared_fdb(lag_master))
+ mlx5_ib_register_peer_vport_reps(lag_master);
return 0;
@@ -118,23 +138,27 @@ mlx5_ib_vport_rep_unload(struct mlx5_eswitch_rep *rep)
struct mlx5_ib_dev *dev = mlx5_ib_rep_to_dev(rep);
int vport_index = rep->vport_index;
struct mlx5_ib_port *port;
+ int i;
if (WARN_ON(!mdev))
return;
+ if (!dev)
+ return;
+
if (mlx5_lag_is_shared_fdb(mdev) &&
!mlx5_lag_is_master(mdev)) {
- struct mlx5_core_dev *peer_mdev;
-
- if (rep->vport == MLX5_VPORT_UPLINK)
+ if (rep->vport == MLX5_VPORT_UPLINK && !mlx5_lag_is_mpesw(mdev))
return;
- peer_mdev = mlx5_lag_get_peer_mdev(mdev);
- vport_index += mlx5_eswitch_get_total_vports(peer_mdev);
+ for (i = 0; i < dev->num_ports; i++) {
+ if (dev->port[i].rep == rep)
+ break;
+ }
+ if (WARN_ON(i == dev->num_ports))
+ return;
+ vport_index = i;
}
- if (!dev)
- return;
-
port = &dev->port[vport_index];
write_lock(&port->roce.netdev_lock);
port->roce.netdev = NULL;
@@ -143,13 +167,18 @@ mlx5_ib_vport_rep_unload(struct mlx5_eswitch_rep *rep)
port->rep = NULL;
if (rep->vport == MLX5_VPORT_UPLINK) {
- struct mlx5_core_dev *peer_mdev;
- struct mlx5_eswitch *esw;
+
+ if (mlx5_lag_is_shared_fdb(mdev) && !mlx5_lag_is_master(mdev))
+ return;
if (mlx5_lag_is_shared_fdb(mdev)) {
- peer_mdev = mlx5_lag_get_peer_mdev(mdev);
- esw = peer_mdev->priv.eswitch;
- mlx5_eswitch_unregister_vport_reps(esw, REP_IB);
+ struct mlx5_core_dev *peer_mdev;
+ struct mlx5_eswitch *esw;
+
+ mlx5_lag_for_each_peer_mdev(mdev, peer_mdev, i) {
+ esw = peer_mdev->priv.eswitch;
+ mlx5_eswitch_unregister_vport_reps(esw, REP_IB);
+ }
}
__mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX);
}
@@ -163,14 +192,14 @@ static const struct mlx5_eswitch_rep_ops rep_ops = {
static void mlx5_ib_register_peer_vport_reps(struct mlx5_core_dev *mdev)
{
- struct mlx5_core_dev *peer_mdev = mlx5_lag_get_peer_mdev(mdev);
+ struct mlx5_core_dev *peer_mdev;
struct mlx5_eswitch *esw;
+ int i;
- if (!peer_mdev)
- return;
-
- esw = peer_mdev->priv.eswitch;
- mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_IB);
+ mlx5_lag_for_each_peer_mdev(mdev, peer_mdev, i) {
+ esw = peer_mdev->priv.eswitch;
+ mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_IB);
+ }
}
struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw,
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/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 69bba0ef4a5d..53f43649f7d0 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -1393,7 +1393,7 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
if (mthca_array_get(&dev->qp_table.qp, mqpn))
err = -EBUSY;
else
- mthca_array_set(&dev->qp_table.qp, mqpn, qp->sqp);
+ mthca_array_set(&dev->qp_table.qp, mqpn, qp);
spin_unlock_irq(&dev->qp_table.lock);
if (err)
diff --git a/drivers/infiniband/hw/qib/qib_user_pages.c b/drivers/infiniband/hw/qib/qib_user_pages.c
index f693bc753b6b..1bb7507325bc 100644
--- a/drivers/infiniband/hw/qib/qib_user_pages.c
+++ b/drivers/infiniband/hw/qib/qib_user_pages.c
@@ -111,7 +111,7 @@ int qib_get_user_pages(unsigned long start_page, size_t num_pages,
ret = pin_user_pages(start_page + got * PAGE_SIZE,
num_pages - got,
FOLL_LONGTERM | FOLL_WRITE,
- p + got, NULL);
+ p + got);
if (ret < 0) {
mmap_read_unlock(current->mm);
goto bail_release;
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom.c b/drivers/infiniband/hw/usnic/usnic_uiom.c
index 2a5cac2658ec..84e0f41e7dfa 100644
--- a/drivers/infiniband/hw/usnic/usnic_uiom.c
+++ b/drivers/infiniband/hw/usnic/usnic_uiom.c
@@ -140,7 +140,7 @@ static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable,
ret = pin_user_pages(cur_base,
min_t(unsigned long, npages,
PAGE_SIZE / sizeof(struct page *)),
- gup_flags, page_list, NULL);
+ gup_flags, page_list);
if (ret < 0)
goto out;
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..d9312b5c9d20 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,19 @@ 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);
+ ret = -EOPNOTSUPP;
+ goto err_drop_mr;
+ }
+
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 4d8f6b8051ff..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)
{
@@ -1357,7 +1395,7 @@ static int rxe_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
if (cleanup_err)
rxe_err_mr(mr, "cleanup failed, err = %d", cleanup_err);
- kfree_rcu(mr);
+ kfree_rcu_mightsleep(mr);
return 0;
err_out:
@@ -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/sw/siw/siw_mem.c b/drivers/infiniband/sw/siw/siw_mem.c
index f51ab2ccf151..e6e25f15567d 100644
--- a/drivers/infiniband/sw/siw/siw_mem.c
+++ b/drivers/infiniband/sw/siw/siw_mem.c
@@ -422,7 +422,7 @@ struct siw_umem *siw_umem_get(u64 start, u64 len, bool writable)
umem->page_chunk[i].plist = plist;
while (nents) {
rv = pin_user_pages(first_page_va, nents, foll_flags,
- plist, NULL);
+ plist);
if (rv < 0)
goto out_sem_up;
diff --git a/drivers/infiniband/sw/siw/siw_qp_tx.c b/drivers/infiniband/sw/siw/siw_qp_tx.c
index 4b292e0504f1..7c7a51d36d0c 100644
--- a/drivers/infiniband/sw/siw/siw_qp_tx.c
+++ b/drivers/infiniband/sw/siw/siw_qp_tx.c
@@ -312,7 +312,7 @@ static int siw_tx_ctrl(struct siw_iwarp_tx *c_tx, struct socket *s,
}
/*
- * 0copy TCP transmit interface: Use do_tcp_sendpages.
+ * 0copy TCP transmit interface: Use MSG_SPLICE_PAGES.
*
* Using sendpage to push page by page appears to be less efficient
* than using sendmsg, even if data are copied.
@@ -323,20 +323,26 @@ static int siw_tx_ctrl(struct siw_iwarp_tx *c_tx, struct socket *s,
static int siw_tcp_sendpages(struct socket *s, struct page **page, int offset,
size_t size)
{
+ struct bio_vec bvec;
+ struct msghdr msg = {
+ .msg_flags = (MSG_MORE | MSG_DONTWAIT | MSG_SPLICE_PAGES),
+ };
struct sock *sk = s->sk;
- int i = 0, rv = 0, sent = 0,
- flags = MSG_MORE | MSG_DONTWAIT | MSG_SENDPAGE_NOTLAST;
+ int i = 0, rv = 0, sent = 0;
while (size) {
size_t bytes = min_t(size_t, PAGE_SIZE - offset, size);
if (size + offset <= PAGE_SIZE)
- flags = MSG_MORE | MSG_DONTWAIT;
+ msg.msg_flags &= ~MSG_MORE;
tcp_rate_check_app_limited(sk);
+ bvec_set_page(&bvec, page[i], bytes, offset);
+ iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, size);
+
try_page_again:
lock_sock(sk);
- rv = do_tcp_sendpages(sk, page[i], offset, bytes, flags);
+ rv = tcp_sendmsg_locked(sk, &msg, size);
release_sock(sk);
if (rv > 0) {
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/evdev.c b/drivers/input/evdev.c
index 95f90699d2b1..51e0c4954600 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -50,7 +50,7 @@ struct evdev_client {
bool revoked;
unsigned long *evmasks[EV_CNT];
unsigned int bufsize;
- struct input_event buffer[];
+ struct input_event buffer[] __counted_by(bufsize);
};
static size_t evdev_get_mask_cnt(unsigned int type)
diff --git a/drivers/input/input-leds.c b/drivers/input/input-leds.c
index 0b11990ade46..0e935914bc3a 100644
--- a/drivers/input/input-leds.c
+++ b/drivers/input/input-leds.c
@@ -44,7 +44,7 @@ struct input_led {
struct input_leds {
struct input_handle handle;
unsigned int num_leds;
- struct input_led leds[];
+ struct input_led leds[] __counted_by(num_leds);
};
static enum led_brightness input_leds_brightness_get(struct led_classdev *cdev)
diff --git a/drivers/input/joystick/walkera0701.c b/drivers/input/joystick/walkera0701.c
index 56abc8c6c763..27d95d6cf56e 100644
--- a/drivers/input/joystick/walkera0701.c
+++ b/drivers/input/joystick/walkera0701.c
@@ -296,15 +296,4 @@ static struct parport_driver walkera0701_parport_driver = {
.devmodel = true,
};
-static int __init walkera0701_init(void)
-{
- return parport_register_driver(&walkera0701_parport_driver);
-}
-
-static void __exit walkera0701_exit(void)
-{
- parport_unregister_driver(&walkera0701_parport_driver);
-}
-
-module_init(walkera0701_init);
-module_exit(walkera0701_exit);
+module_parport_driver(walkera0701_parport_driver);
diff --git a/drivers/input/keyboard/adp5520-keys.c b/drivers/input/keyboard/adp5520-keys.c
index 7851ffd678a8..10c248f0c1fc 100644
--- a/drivers/input/keyboard/adp5520-keys.c
+++ b/drivers/input/keyboard/adp5520-keys.c
@@ -168,14 +168,12 @@ static int adp5520_keys_probe(struct platform_device *pdev)
return 0;
}
-static int adp5520_keys_remove(struct platform_device *pdev)
+static void adp5520_keys_remove(struct platform_device *pdev)
{
struct adp5520_keys *dev = platform_get_drvdata(pdev);
adp5520_unregister_notifier(dev->master, &dev->notifier,
ADP5520_KP_IEN | ADP5520_KR_IEN);
-
- return 0;
}
static struct platform_driver adp5520_keys_driver = {
@@ -183,7 +181,7 @@ static struct platform_driver adp5520_keys_driver = {
.name = "adp5520-keys",
},
.probe = adp5520_keys_probe,
- .remove = adp5520_keys_remove,
+ .remove_new = adp5520_keys_remove,
};
module_platform_driver(adp5520_keys_driver);
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index e7ecfca838df..30678a34cf64 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -686,10 +686,11 @@ static umode_t cros_ec_keyb_attr_is_visible(struct kobject *kobj,
return attr->mode;
}
-static const struct attribute_group cros_ec_keyb_attr_group = {
+static const struct attribute_group cros_ec_keyb_group = {
.is_visible = cros_ec_keyb_attr_is_visible,
.attrs = cros_ec_keyb_attrs,
};
+__ATTRIBUTE_GROUPS(cros_ec_keyb);
static int cros_ec_keyb_probe(struct platform_device *pdev)
{
@@ -730,12 +731,6 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
return err;
}
- err = devm_device_add_group(dev, &cros_ec_keyb_attr_group);
- if (err) {
- dev_err(dev, "failed to create attributes: %d\n", err);
- return err;
- }
-
ckdev->notifier.notifier_call = cros_ec_keyb_work;
err = blocking_notifier_chain_register(&ckdev->ec->event_notifier,
&ckdev->notifier);
@@ -748,14 +743,12 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
return 0;
}
-static int cros_ec_keyb_remove(struct platform_device *pdev)
+static void cros_ec_keyb_remove(struct platform_device *pdev)
{
struct cros_ec_keyb *ckdev = dev_get_drvdata(&pdev->dev);
blocking_notifier_chain_unregister(&ckdev->ec->event_notifier,
&ckdev->notifier);
-
- return 0;
}
#ifdef CONFIG_ACPI
@@ -779,9 +772,10 @@ static DEFINE_SIMPLE_DEV_PM_OPS(cros_ec_keyb_pm_ops, NULL, cros_ec_keyb_resume);
static struct platform_driver cros_ec_keyb_driver = {
.probe = cros_ec_keyb_probe,
- .remove = cros_ec_keyb_remove,
+ .remove_new = cros_ec_keyb_remove,
.driver = {
.name = "cros-ec-keyb",
+ .dev_groups = cros_ec_keyb_groups,
.of_match_table = of_match_ptr(cros_ec_keyb_of_match),
.acpi_match_table = ACPI_PTR(cros_ec_keyb_acpi_match),
.pm = pm_sleep_ptr(&cros_ec_keyb_pm_ops),
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c
index 55075addcac2..6b811d6bf625 100644
--- a/drivers/input/keyboard/ep93xx_keypad.c
+++ b/drivers/input/keyboard/ep93xx_keypad.c
@@ -308,11 +308,9 @@ static int ep93xx_keypad_probe(struct platform_device *pdev)
return 0;
}
-static int ep93xx_keypad_remove(struct platform_device *pdev)
+static void ep93xx_keypad_remove(struct platform_device *pdev)
{
dev_pm_clear_wake_irq(&pdev->dev);
-
- return 0;
}
static struct platform_driver ep93xx_keypad_driver = {
@@ -321,7 +319,7 @@ static struct platform_driver ep93xx_keypad_driver = {
.pm = pm_sleep_ptr(&ep93xx_keypad_pm_ops),
},
.probe = ep93xx_keypad_probe,
- .remove = ep93xx_keypad_remove,
+ .remove_new = ep93xx_keypad_remove,
};
module_platform_driver(ep93xx_keypad_driver);
diff --git a/drivers/input/keyboard/iqs62x-keys.c b/drivers/input/keyboard/iqs62x-keys.c
index 02ceebad7bda..688d61244b5f 100644
--- a/drivers/input/keyboard/iqs62x-keys.c
+++ b/drivers/input/keyboard/iqs62x-keys.c
@@ -310,7 +310,7 @@ static int iqs62x_keys_probe(struct platform_device *pdev)
return ret;
}
-static int iqs62x_keys_remove(struct platform_device *pdev)
+static void iqs62x_keys_remove(struct platform_device *pdev)
{
struct iqs62x_keys_private *iqs62x_keys = platform_get_drvdata(pdev);
int ret;
@@ -319,8 +319,6 @@ static int iqs62x_keys_remove(struct platform_device *pdev)
&iqs62x_keys->notifier);
if (ret)
dev_err(&pdev->dev, "Failed to unregister notifier: %d\n", ret);
-
- return 0;
}
static struct platform_driver iqs62x_keys_platform_driver = {
@@ -328,7 +326,7 @@ static struct platform_driver iqs62x_keys_platform_driver = {
.name = "iqs62x-keys",
},
.probe = iqs62x_keys_probe,
- .remove = iqs62x_keys_remove,
+ .remove_new = iqs62x_keys_remove,
};
module_platform_driver(iqs62x_keys_platform_driver);
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
index a1b037891af2..50fa764c82d2 100644
--- a/drivers/input/keyboard/matrix_keypad.c
+++ b/drivers/input/keyboard/matrix_keypad.c
@@ -549,15 +549,13 @@ err_free_mem:
return err;
}
-static int matrix_keypad_remove(struct platform_device *pdev)
+static void matrix_keypad_remove(struct platform_device *pdev)
{
struct matrix_keypad *keypad = platform_get_drvdata(pdev);
matrix_keypad_free_gpio(keypad);
input_unregister_device(keypad->input_dev);
kfree(keypad);
-
- return 0;
}
#ifdef CONFIG_OF
@@ -570,7 +568,7 @@ MODULE_DEVICE_TABLE(of, matrix_keypad_dt_match);
static struct platform_driver matrix_keypad_driver = {
.probe = matrix_keypad_probe,
- .remove = matrix_keypad_remove,
+ .remove_new = matrix_keypad_remove,
.driver = {
.name = "matrix-keypad",
.pm = pm_sleep_ptr(&matrix_keypad_pm_ops),
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
index 24440b498645..454fb8675657 100644
--- a/drivers/input/keyboard/omap-keypad.c
+++ b/drivers/input/keyboard/omap-keypad.c
@@ -287,7 +287,7 @@ err2:
return -EINVAL;
}
-static int omap_kp_remove(struct platform_device *pdev)
+static void omap_kp_remove(struct platform_device *pdev)
{
struct omap_kp *omap_kp = platform_get_drvdata(pdev);
@@ -303,13 +303,11 @@ static int omap_kp_remove(struct platform_device *pdev)
input_unregister_device(omap_kp->input);
kfree(omap_kp);
-
- return 0;
}
static struct platform_driver omap_kp_driver = {
.probe = omap_kp_probe,
- .remove = omap_kp_remove,
+ .remove_new = omap_kp_remove,
.driver = {
.name = "omap-keypad",
},
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
index 773e55eed88b..d3f8688fdd9c 100644
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -461,11 +461,9 @@ static int omap4_keypad_probe(struct platform_device *pdev)
return 0;
}
-static int omap4_keypad_remove(struct platform_device *pdev)
+static void omap4_keypad_remove(struct platform_device *pdev)
{
dev_pm_clear_wake_irq(&pdev->dev);
-
- return 0;
}
static const struct of_device_id omap_keypad_dt_match[] = {
@@ -476,7 +474,7 @@ MODULE_DEVICE_TABLE(of, omap_keypad_dt_match);
static struct platform_driver omap4_keypad_driver = {
.probe = omap4_keypad_probe,
- .remove = omap4_keypad_remove,
+ .remove_new = omap4_keypad_remove,
.driver = {
.name = "omap4-keypad",
.of_match_table = omap_keypad_dt_match,
diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c
index d85dd2489293..e212eff7687c 100644
--- a/drivers/input/keyboard/samsung-keypad.c
+++ b/drivers/input/keyboard/samsung-keypad.c
@@ -444,7 +444,7 @@ err_unprepare_clk:
return error;
}
-static int samsung_keypad_remove(struct platform_device *pdev)
+static void samsung_keypad_remove(struct platform_device *pdev)
{
struct samsung_keypad *keypad = platform_get_drvdata(pdev);
@@ -453,8 +453,6 @@ static int samsung_keypad_remove(struct platform_device *pdev)
input_unregister_device(keypad->input_dev);
clk_unprepare(keypad->clk);
-
- return 0;
}
static int samsung_keypad_runtime_suspend(struct device *dev)
@@ -589,7 +587,7 @@ MODULE_DEVICE_TABLE(platform, samsung_keypad_driver_ids);
static struct platform_driver samsung_keypad_driver = {
.probe = samsung_keypad_probe,
- .remove = samsung_keypad_remove,
+ .remove_new = samsung_keypad_remove,
.driver = {
.name = "samsung-keypad",
.of_match_table = of_match_ptr(samsung_keypad_dt_match),
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c
index 2c00320f739f..4ea4fd25c5d2 100644
--- a/drivers/input/keyboard/sh_keysc.c
+++ b/drivers/input/keyboard/sh_keysc.c
@@ -265,7 +265,7 @@ static int sh_keysc_probe(struct platform_device *pdev)
return error;
}
-static int sh_keysc_remove(struct platform_device *pdev)
+static void sh_keysc_remove(struct platform_device *pdev)
{
struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
@@ -279,8 +279,6 @@ static int sh_keysc_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
kfree(priv);
-
- return 0;
}
static int sh_keysc_suspend(struct device *dev)
@@ -321,7 +319,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(sh_keysc_dev_pm_ops,
static struct platform_driver sh_keysc_device_driver = {
.probe = sh_keysc_probe,
- .remove = sh_keysc_remove,
+ .remove_new = sh_keysc_remove,
.driver = {
.name = "sh_keysc",
.pm = pm_sleep_ptr(&sh_keysc_dev_pm_ops),
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c
index a50fa9915381..557d00a667ce 100644
--- a/drivers/input/keyboard/spear-keyboard.c
+++ b/drivers/input/keyboard/spear-keyboard.c
@@ -272,14 +272,12 @@ static int spear_kbd_probe(struct platform_device *pdev)
return 0;
}
-static int spear_kbd_remove(struct platform_device *pdev)
+static void spear_kbd_remove(struct platform_device *pdev)
{
struct spear_kbd *kbd = platform_get_drvdata(pdev);
input_unregister_device(kbd->input);
clk_unprepare(kbd->clk);
-
- return 0;
}
static int spear_kbd_suspend(struct device *dev)
@@ -375,7 +373,7 @@ MODULE_DEVICE_TABLE(of, spear_kbd_id_table);
static struct platform_driver spear_kbd_driver = {
.probe = spear_kbd_probe,
- .remove = spear_kbd_remove,
+ .remove_new = spear_kbd_remove,
.driver = {
.name = "keyboard",
.pm = pm_sleep_ptr(&spear_kbd_pm_ops),
diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c
index 2c6c53290cc0..2013c0afd0c3 100644
--- a/drivers/input/keyboard/stmpe-keypad.c
+++ b/drivers/input/keyboard/stmpe-keypad.c
@@ -404,20 +404,18 @@ static int stmpe_keypad_probe(struct platform_device *pdev)
return 0;
}
-static int stmpe_keypad_remove(struct platform_device *pdev)
+static void stmpe_keypad_remove(struct platform_device *pdev)
{
struct stmpe_keypad *keypad = platform_get_drvdata(pdev);
stmpe_disable(keypad->stmpe, STMPE_BLOCK_KEYPAD);
-
- return 0;
}
static struct platform_driver stmpe_keypad_driver = {
.driver.name = "stmpe-keypad",
.driver.owner = THIS_MODULE,
.probe = stmpe_keypad_probe,
- .remove = stmpe_keypad_remove,
+ .remove_new = stmpe_keypad_remove,
};
module_platform_driver(stmpe_keypad_driver);
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index c9a823ea45d0..a1765ed8c825 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -14,7 +14,7 @@
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/of.h>
-#include <linux/of_device.h>
+#include <linux/property.h>
#include <linux/clk.h>
#include <linux/slab.h>
#include <linux/input/matrix_keypad.h>
@@ -602,9 +602,6 @@ static int tegra_kbc_probe(struct platform_device *pdev)
unsigned int debounce_cnt;
unsigned int scan_time_rows;
unsigned int keymap_rows;
- const struct of_device_id *match;
-
- match = of_match_device(tegra_kbc_of_match, &pdev->dev);
kbc = devm_kzalloc(&pdev->dev, sizeof(*kbc), GFP_KERNEL);
if (!kbc) {
@@ -613,7 +610,7 @@ static int tegra_kbc_probe(struct platform_device *pdev)
}
kbc->dev = &pdev->dev;
- kbc->hw_support = match->data;
+ kbc->hw_support = device_get_match_data(&pdev->dev);
kbc->max_keys = kbc->hw_support->max_rows *
kbc->hw_support->max_columns;
kbc->num_rows_and_columns = kbc->hw_support->max_rows +
diff --git a/drivers/input/misc/88pm80x_onkey.c b/drivers/input/misc/88pm80x_onkey.c
index 51c8a326fd06..31f0702c3d01 100644
--- a/drivers/input/misc/88pm80x_onkey.c
+++ b/drivers/input/misc/88pm80x_onkey.c
@@ -138,14 +138,13 @@ out:
return err;
}
-static int pm80x_onkey_remove(struct platform_device *pdev)
+static void pm80x_onkey_remove(struct platform_device *pdev)
{
struct pm80x_onkey_info *info = platform_get_drvdata(pdev);
pm80x_free_irq(info->pm80x, info->irq, info);
input_unregister_device(info->idev);
kfree(info);
- return 0;
}
static struct platform_driver pm80x_onkey_driver = {
@@ -154,7 +153,7 @@ static struct platform_driver pm80x_onkey_driver = {
.pm = &pm80x_onkey_pm_ops,
},
.probe = pm80x_onkey_probe,
- .remove = pm80x_onkey_remove,
+ .remove_new = pm80x_onkey_remove,
};
module_platform_driver(pm80x_onkey_driver);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index c47eecc6f83b..6ba984d7f0b1 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -609,7 +609,7 @@ config INPUT_PWM_VIBRA
config INPUT_RK805_PWRKEY
tristate "Rockchip RK805 PMIC power key support"
- depends on MFD_RK808
+ depends on MFD_RK8XX
help
Select this option to enable power key driver for RK805.
diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c
index 4581606a28d6..24f9e9d893de 100644
--- a/drivers/input/misc/axp20x-pek.c
+++ b/drivers/input/misc/axp20x-pek.c
@@ -133,20 +133,11 @@ static ssize_t axp20x_store_attr(struct device *dev,
size_t count)
{
struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
- char val_str[20];
- size_t len;
int ret, i;
unsigned int val, idx = 0;
unsigned int best_err = UINT_MAX;
- val_str[sizeof(val_str) - 1] = '\0';
- strncpy(val_str, buf, sizeof(val_str) - 1);
- len = strlen(val_str);
-
- if (len && val_str[len - 1] == '\n')
- val_str[len - 1] = '\0';
-
- ret = kstrtouint(val_str, 10, &val);
+ ret = kstrtouint(buf, 10, &val);
if (ret)
return ret;
diff --git a/drivers/input/misc/da9052_onkey.c b/drivers/input/misc/da9052_onkey.c
index 6d1152850a6d..7a1122e1efb9 100644
--- a/drivers/input/misc/da9052_onkey.c
+++ b/drivers/input/misc/da9052_onkey.c
@@ -127,7 +127,7 @@ err_free_mem:
return error;
}
-static int da9052_onkey_remove(struct platform_device *pdev)
+static void da9052_onkey_remove(struct platform_device *pdev)
{
struct da9052_onkey *onkey = platform_get_drvdata(pdev);
@@ -136,13 +136,11 @@ static int da9052_onkey_remove(struct platform_device *pdev)
input_unregister_device(onkey->input);
kfree(onkey);
-
- return 0;
}
static struct platform_driver da9052_onkey_driver = {
.probe = da9052_onkey_probe,
- .remove = da9052_onkey_remove,
+ .remove_new = da9052_onkey_remove,
.driver = {
.name = "da9052-onkey",
},
diff --git a/drivers/input/misc/da9055_onkey.c b/drivers/input/misc/da9055_onkey.c
index 7a0d3a1d503c..871812f1b398 100644
--- a/drivers/input/misc/da9055_onkey.c
+++ b/drivers/input/misc/da9055_onkey.c
@@ -132,7 +132,7 @@ err_free_input:
return err;
}
-static int da9055_onkey_remove(struct platform_device *pdev)
+static void da9055_onkey_remove(struct platform_device *pdev)
{
struct da9055_onkey *onkey = platform_get_drvdata(pdev);
int irq = platform_get_irq_byname(pdev, "ONKEY");
@@ -141,13 +141,11 @@ static int da9055_onkey_remove(struct platform_device *pdev)
free_irq(irq, onkey);
cancel_delayed_work_sync(&onkey->work);
input_unregister_device(onkey->input);
-
- return 0;
}
static struct platform_driver da9055_onkey_driver = {
.probe = da9055_onkey_probe,
- .remove = da9055_onkey_remove,
+ .remove_new = da9055_onkey_remove,
.driver = {
.name = "da9055-onkey",
},
diff --git a/drivers/input/misc/ideapad_slidebar.c b/drivers/input/misc/ideapad_slidebar.c
index 68f1c584da05..fa4e7f67d713 100644
--- a/drivers/input/misc/ideapad_slidebar.c
+++ b/drivers/input/misc/ideapad_slidebar.c
@@ -256,20 +256,18 @@ err_release_ports:
return err;
}
-static int ideapad_remove(struct platform_device *pdev)
+static void ideapad_remove(struct platform_device *pdev)
{
i8042_remove_filter(slidebar_i8042_filter);
input_unregister_device(slidebar_input_dev);
release_region(IDEAPAD_BASE, 3);
-
- return 0;
}
static struct platform_driver slidebar_drv = {
.driver = {
.name = "ideapad_slidebar",
},
- .remove = ideapad_remove,
+ .remove_new = ideapad_remove,
};
static int __init ideapad_dmi_check(const struct dmi_system_id *id)
diff --git a/drivers/input/misc/iqs269a.c b/drivers/input/misc/iqs269a.c
index c0a085639870..3c636c75e8a1 100644
--- a/drivers/input/misc/iqs269a.c
+++ b/drivers/input/misc/iqs269a.c
@@ -1586,10 +1586,7 @@ static struct attribute *iqs269_attrs[] = {
&dev_attr_ati_trigger.attr,
NULL,
};
-
-static const struct attribute_group iqs269_attr_group = {
- .attrs = iqs269_attrs,
-};
+ATTRIBUTE_GROUPS(iqs269);
static const struct regmap_config iqs269_regmap_config = {
.reg_bits = 8,
@@ -1671,10 +1668,6 @@ static int iqs269_probe(struct i2c_client *client)
return error;
}
- error = devm_device_add_group(&client->dev, &iqs269_attr_group);
- if (error)
- dev_err(&client->dev, "Failed to add attributes: %d\n", error);
-
return error;
}
@@ -1743,6 +1736,7 @@ MODULE_DEVICE_TABLE(of, iqs269_of_match);
static struct i2c_driver iqs269_i2c_driver = {
.driver = {
.name = "iqs269a",
+ .dev_groups = iqs269_groups,
.of_match_table = iqs269_of_match,
.pm = pm_sleep_ptr(&iqs269_pm),
},
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index 912e614d039d..d47269b10e9a 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -334,14 +334,25 @@ static ssize_t kxtj9_set_poll(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(poll, S_IRUGO|S_IWUSR, kxtj9_get_poll, kxtj9_set_poll);
-static struct attribute *kxtj9_attributes[] = {
+static struct attribute *kxtj9_attrs[] = {
&dev_attr_poll.attr,
NULL
};
-static struct attribute_group kxtj9_attribute_group = {
- .attrs = kxtj9_attributes
+static umode_t kxtj9_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr, int n)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct i2c_client *client = to_i2c_client(dev);
+
+ return client->irq ? attr->mode : 0;
+}
+
+static struct attribute_group kxtj9_group = {
+ .attrs = kxtj9_attrs,
+ .is_visible = kxtj9_attr_is_visible,
};
+__ATTRIBUTE_GROUPS(kxtj9);
static void kxtj9_poll(struct input_dev *input)
{
@@ -482,13 +493,6 @@ static int kxtj9_probe(struct i2c_client *client)
dev_err(&client->dev, "request irq failed: %d\n", err);
return err;
}
-
- err = devm_device_add_group(&client->dev,
- &kxtj9_attribute_group);
- if (err) {
- dev_err(&client->dev, "sysfs create failed: %d\n", err);
- return err;
- }
}
return 0;
@@ -535,8 +539,9 @@ MODULE_DEVICE_TABLE(i2c, kxtj9_id);
static struct i2c_driver kxtj9_driver = {
.driver = {
- .name = NAME,
- .pm = pm_sleep_ptr(&kxtj9_pm_ops),
+ .name = NAME,
+ .dev_groups = kxtj9_groups,
+ .pm = pm_sleep_ptr(&kxtj9_pm_ops),
},
.probe = kxtj9_probe,
.id_table = kxtj9_id,
diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c
index 25fcf1467151..3fe0a85c45e0 100644
--- a/drivers/input/misc/m68kspkr.c
+++ b/drivers/input/misc/m68kspkr.c
@@ -75,15 +75,13 @@ static int m68kspkr_probe(struct platform_device *dev)
return 0;
}
-static int m68kspkr_remove(struct platform_device *dev)
+static void m68kspkr_remove(struct platform_device *dev)
{
struct input_dev *input_dev = platform_get_drvdata(dev);
input_unregister_device(input_dev);
/* turn off the speaker */
m68kspkr_event(NULL, EV_SND, SND_BELL, 0);
-
- return 0;
}
static void m68kspkr_shutdown(struct platform_device *dev)
@@ -97,7 +95,7 @@ static struct platform_driver m68kspkr_platform_driver = {
.name = "m68kspkr",
},
.probe = m68kspkr_probe,
- .remove = m68kspkr_remove,
+ .remove_new = m68kspkr_remove,
.shutdown = m68kspkr_shutdown,
};
diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
index c4dff476d479..8861a67be575 100644
--- a/drivers/input/misc/max8997_haptic.c
+++ b/drivers/input/misc/max8997_haptic.c
@@ -351,7 +351,7 @@ err_free_mem:
return error;
}
-static int max8997_haptic_remove(struct platform_device *pdev)
+static void max8997_haptic_remove(struct platform_device *pdev)
{
struct max8997_haptic *chip = platform_get_drvdata(pdev);
@@ -362,8 +362,6 @@ static int max8997_haptic_remove(struct platform_device *pdev)
pwm_put(chip->pwm);
kfree(chip);
-
- return 0;
}
static int max8997_haptic_suspend(struct device *dev)
@@ -391,7 +389,7 @@ static struct platform_driver max8997_haptic_driver = {
.pm = pm_sleep_ptr(&max8997_haptic_pm_ops),
},
.probe = max8997_haptic_probe,
- .remove = max8997_haptic_remove,
+ .remove_new = max8997_haptic_remove,
.id_table = max8997_haptic_id,
};
module_platform_driver(max8997_haptic_driver);
diff --git a/drivers/input/misc/mc13783-pwrbutton.c b/drivers/input/misc/mc13783-pwrbutton.c
index 0636eee4bb6c..1c8c939638f6 100644
--- a/drivers/input/misc/mc13783-pwrbutton.c
+++ b/drivers/input/misc/mc13783-pwrbutton.c
@@ -229,7 +229,7 @@ free_input_dev:
return err;
}
-static int mc13783_pwrbutton_remove(struct platform_device *pdev)
+static void mc13783_pwrbutton_remove(struct platform_device *pdev)
{
struct mc13783_pwrb *priv = platform_get_drvdata(pdev);
const struct mc13xxx_buttons_platform_data *pdata;
@@ -249,13 +249,11 @@ static int mc13783_pwrbutton_remove(struct platform_device *pdev)
input_unregister_device(priv->pwr);
kfree(priv);
-
- return 0;
}
static struct platform_driver mc13783_pwrbutton_driver = {
.probe = mc13783_pwrbutton_probe,
- .remove = mc13783_pwrbutton_remove,
+ .remove_new = mc13783_pwrbutton_remove,
.driver = {
.name = "mc13783-pwrbutton",
},
diff --git a/drivers/input/misc/palmas-pwrbutton.c b/drivers/input/misc/palmas-pwrbutton.c
index 7e361727b0d9..06d5972e8e84 100644
--- a/drivers/input/misc/palmas-pwrbutton.c
+++ b/drivers/input/misc/palmas-pwrbutton.c
@@ -245,7 +245,7 @@ err_free_mem:
*
* Return: 0
*/
-static int palmas_pwron_remove(struct platform_device *pdev)
+static void palmas_pwron_remove(struct platform_device *pdev)
{
struct palmas_pwron *pwron = platform_get_drvdata(pdev);
@@ -254,8 +254,6 @@ static int palmas_pwron_remove(struct platform_device *pdev)
input_unregister_device(pwron->input_dev);
kfree(pwron);
-
- return 0;
}
/**
@@ -312,7 +310,7 @@ MODULE_DEVICE_TABLE(of, of_palmas_pwr_match);
static struct platform_driver palmas_pwron_driver = {
.probe = palmas_pwron_probe,
- .remove = palmas_pwron_remove,
+ .remove_new = palmas_pwron_remove,
.driver = {
.name = "palmas_pwrbutton",
.of_match_table = of_match_ptr(of_palmas_pwr_match),
diff --git a/drivers/input/misc/pcap_keys.c b/drivers/input/misc/pcap_keys.c
index b5a53636d7e2..8a7e9ada5952 100644
--- a/drivers/input/misc/pcap_keys.c
+++ b/drivers/input/misc/pcap_keys.c
@@ -99,7 +99,7 @@ fail:
return err;
}
-static int pcap_keys_remove(struct platform_device *pdev)
+static void pcap_keys_remove(struct platform_device *pdev)
{
struct pcap_keys *pcap_keys = platform_get_drvdata(pdev);
@@ -108,13 +108,11 @@ static int pcap_keys_remove(struct platform_device *pdev)
input_unregister_device(pcap_keys->input);
kfree(pcap_keys);
-
- return 0;
}
static struct platform_driver pcap_keys_device_driver = {
.probe = pcap_keys_probe,
- .remove = pcap_keys_remove,
+ .remove_new = pcap_keys_remove,
.driver = {
.name = "pcap-keys",
}
diff --git a/drivers/input/misc/pcf50633-input.c b/drivers/input/misc/pcf50633-input.c
index 4c60c70c4c10..c5c5fe236c18 100644
--- a/drivers/input/misc/pcf50633-input.c
+++ b/drivers/input/misc/pcf50633-input.c
@@ -87,7 +87,7 @@ static int pcf50633_input_probe(struct platform_device *pdev)
return 0;
}
-static int pcf50633_input_remove(struct platform_device *pdev)
+static void pcf50633_input_remove(struct platform_device *pdev)
{
struct pcf50633_input *input = platform_get_drvdata(pdev);
@@ -96,8 +96,6 @@ static int pcf50633_input_remove(struct platform_device *pdev)
input_unregister_device(input->input_dev);
kfree(input);
-
- return 0;
}
static struct platform_driver pcf50633_input_driver = {
@@ -105,7 +103,7 @@ static struct platform_driver pcf50633_input_driver = {
.name = "pcf50633-input",
},
.probe = pcf50633_input_probe,
- .remove = pcf50633_input_remove,
+ .remove_new = pcf50633_input_remove,
};
module_platform_driver(pcf50633_input_driver);
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index 9c666b2f14fe..897854fd245f 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -95,15 +95,13 @@ static int pcspkr_probe(struct platform_device *dev)
return 0;
}
-static int pcspkr_remove(struct platform_device *dev)
+static void pcspkr_remove(struct platform_device *dev)
{
struct input_dev *pcspkr_dev = platform_get_drvdata(dev);
input_unregister_device(pcspkr_dev);
/* turn off the speaker */
pcspkr_event(NULL, EV_SND, SND_BELL, 0);
-
- return 0;
}
static int pcspkr_suspend(struct device *dev)
@@ -129,7 +127,7 @@ static struct platform_driver pcspkr_platform_driver = {
.pm = &pcspkr_pm_ops,
},
.probe = pcspkr_probe,
- .remove = pcspkr_remove,
+ .remove_new = pcspkr_remove,
.shutdown = pcspkr_shutdown,
};
module_platform_driver(pcspkr_platform_driver);
diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c
index ba747c5b2b5f..bab710023d8f 100644
--- a/drivers/input/misc/pm8941-pwrkey.c
+++ b/drivers/input/misc/pm8941-pwrkey.c
@@ -408,14 +408,12 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
return 0;
}
-static int pm8941_pwrkey_remove(struct platform_device *pdev)
+static void pm8941_pwrkey_remove(struct platform_device *pdev)
{
struct pm8941_pwrkey *pwrkey = platform_get_drvdata(pdev);
if (pwrkey->data->supports_ps_hold_poff_config)
unregister_reboot_notifier(&pwrkey->reboot_notifier);
-
- return 0;
}
static const struct pm8941_data pwrkey_data = {
@@ -467,7 +465,7 @@ MODULE_DEVICE_TABLE(of, pm8941_pwr_key_id_table);
static struct platform_driver pm8941_pwrkey_driver = {
.probe = pm8941_pwrkey_probe,
- .remove = pm8941_pwrkey_remove,
+ .remove_new = pm8941_pwrkey_remove,
.driver = {
.name = "pm8941-pwrkey",
.pm = pm_sleep_ptr(&pm8941_pwr_key_pm_ops),
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
index e79f5497948b..08bcee3d6bcc 100644
--- a/drivers/input/misc/soc_button_array.c
+++ b/drivers/input/misc/soc_button_array.c
@@ -411,7 +411,7 @@ out:
return button_info;
}
-static int soc_button_remove(struct platform_device *pdev)
+static void soc_button_remove(struct platform_device *pdev)
{
struct soc_button_data *priv = platform_get_drvdata(pdev);
@@ -420,8 +420,6 @@ static int soc_button_remove(struct platform_device *pdev)
for (i = 0; i < BUTTON_TYPES; i++)
if (priv->children[i])
platform_device_unregister(priv->children[i]);
-
- return 0;
}
static int soc_button_probe(struct platform_device *pdev)
@@ -609,7 +607,7 @@ MODULE_DEVICE_TABLE(acpi, soc_button_acpi_match);
static struct platform_driver soc_button_driver = {
.probe = soc_button_probe,
- .remove = soc_button_remove,
+ .remove_new = soc_button_remove,
.driver = {
.name = KBUILD_MODNAME,
.acpi_match_table = ACPI_PTR(soc_button_acpi_match),
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index e5dd84725c6e..20020cbc0752 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -231,7 +231,7 @@ out_err:
return err;
}
-static int bbc_remove(struct platform_device *op)
+static void bbc_remove(struct platform_device *op)
{
struct sparcspkr_state *state = platform_get_drvdata(op);
struct input_dev *input_dev = state->input_dev;
@@ -245,8 +245,6 @@ static int bbc_remove(struct platform_device *op)
of_iounmap(&op->resource[0], info->regs, 6);
kfree(state);
-
- return 0;
}
static const struct of_device_id bbc_beep_match[] = {
@@ -264,7 +262,7 @@ static struct platform_driver bbc_beep_driver = {
.of_match_table = bbc_beep_match,
},
.probe = bbc_beep_probe,
- .remove = bbc_remove,
+ .remove_new = bbc_remove,
.shutdown = sparcspkr_shutdown,
};
@@ -310,7 +308,7 @@ out_err:
return err;
}
-static int grover_remove(struct platform_device *op)
+static void grover_remove(struct platform_device *op)
{
struct sparcspkr_state *state = platform_get_drvdata(op);
struct grover_beep_info *info = &state->u.grover;
@@ -325,8 +323,6 @@ static int grover_remove(struct platform_device *op)
of_iounmap(&op->resource[2], info->freq_regs, 2);
kfree(state);
-
- return 0;
}
static const struct of_device_id grover_beep_match[] = {
@@ -344,7 +340,7 @@ static struct platform_driver grover_beep_driver = {
.of_match_table = grover_beep_match,
},
.probe = grover_beep_probe,
- .remove = grover_remove,
+ .remove_new = grover_remove,
.shutdown = sparcspkr_shutdown,
};
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index 111cb70cde46..5c4956678cd0 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -1286,13 +1286,11 @@ static int wistron_probe(struct platform_device *dev)
return 0;
}
-static int wistron_remove(struct platform_device *dev)
+static void wistron_remove(struct platform_device *dev)
{
wistron_led_remove();
input_unregister_device(wistron_idev);
bios_detach();
-
- return 0;
}
static int wistron_suspend(struct device *dev)
@@ -1336,7 +1334,7 @@ static struct platform_driver wistron_driver = {
.pm = pm_sleep_ptr(&wistron_pm_ops),
},
.probe = wistron_probe,
- .remove = wistron_remove,
+ .remove_new = wistron_remove,
};
static int __init wb_module_init(void)
diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c
index a42fe041b73c..e4a06c73b72d 100644
--- a/drivers/input/misc/wm831x-on.c
+++ b/drivers/input/misc/wm831x-on.c
@@ -123,20 +123,18 @@ err:
return ret;
}
-static int wm831x_on_remove(struct platform_device *pdev)
+static void wm831x_on_remove(struct platform_device *pdev)
{
struct wm831x_on *wm831x_on = platform_get_drvdata(pdev);
int irq = platform_get_irq(pdev, 0);
free_irq(irq, wm831x_on);
cancel_delayed_work_sync(&wm831x_on->work);
-
- return 0;
}
static struct platform_driver wm831x_on_driver = {
.probe = wm831x_on_probe,
- .remove = wm831x_on_remove,
+ .remove_new = wm831x_on_remove,
.driver = {
.name = "wm831x-on",
},
diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c
index 05851bc32541..a84098448f5b 100644
--- a/drivers/input/mouse/cyapa.c
+++ b/drivers/input/mouse/cyapa.c
@@ -1223,7 +1223,7 @@ static DEVICE_ATTR(baseline, S_IRUGO, cyapa_show_baseline, NULL);
static DEVICE_ATTR(calibrate, S_IWUSR, NULL, cyapa_calibrate_store);
static DEVICE_ATTR(mode, S_IRUGO, cyapa_show_mode, NULL);
-static struct attribute *cyapa_sysfs_entries[] = {
+static struct attribute *cyapa_attrs[] = {
&dev_attr_firmware_version.attr,
&dev_attr_product_id.attr,
&dev_attr_update_fw.attr,
@@ -1232,10 +1232,7 @@ static struct attribute *cyapa_sysfs_entries[] = {
&dev_attr_mode.attr,
NULL,
};
-
-static const struct attribute_group cyapa_sysfs_group = {
- .attrs = cyapa_sysfs_entries,
-};
+ATTRIBUTE_GROUPS(cyapa);
static void cyapa_disable_regulator(void *data)
{
@@ -1302,12 +1299,6 @@ static int cyapa_probe(struct i2c_client *client)
return error;
}
- error = devm_device_add_group(dev, &cyapa_sysfs_group);
- if (error) {
- dev_err(dev, "failed to create sysfs entries: %d\n", error);
- return error;
- }
-
error = cyapa_prepare_wakeup_controls(cyapa);
if (error) {
dev_err(dev, "failed to prepare wakeup controls: %d\n", error);
@@ -1484,6 +1475,7 @@ MODULE_DEVICE_TABLE(of, cyapa_of_match);
static struct i2c_driver cyapa_driver = {
.driver = {
.name = "cyapa",
+ .dev_groups = cyapa_groups,
.pm = pm_ptr(&cyapa_pm_ops),
.acpi_match_table = ACPI_PTR(cyapa_acpi_id),
.of_match_table = of_match_ptr(cyapa_of_match),
diff --git a/drivers/input/mouse/navpoint.c b/drivers/input/mouse/navpoint.c
index 2b7b86eef280..c00dc1275da2 100644
--- a/drivers/input/mouse/navpoint.c
+++ b/drivers/input/mouse/navpoint.c
@@ -295,7 +295,7 @@ err_free_gpio:
return error;
}
-static int navpoint_remove(struct platform_device *pdev)
+static void navpoint_remove(struct platform_device *pdev)
{
const struct navpoint_platform_data *pdata =
dev_get_platdata(&pdev->dev);
@@ -311,8 +311,6 @@ static int navpoint_remove(struct platform_device *pdev)
if (gpio_is_valid(pdata->gpio))
gpio_free(pdata->gpio);
-
- return 0;
}
static int navpoint_suspend(struct device *dev)
@@ -348,7 +346,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(navpoint_pm_ops,
static struct platform_driver navpoint_driver = {
.probe = navpoint_probe,
- .remove = navpoint_remove,
+ .remove_new = navpoint_remove,
.driver = {
.name = "navpoint",
.pm = pm_sleep_ptr(&navpoint_pm_ops),
diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c
index f2e093b0b998..1b45b1d3077d 100644
--- a/drivers/input/rmi4/rmi_bus.c
+++ b/drivers/input/rmi4/rmi_bus.c
@@ -277,11 +277,11 @@ void rmi_unregister_function(struct rmi_function *fn)
device_del(&fn->dev);
of_node_put(fn->dev.of_node);
- put_device(&fn->dev);
for (i = 0; i < fn->num_of_irqs; i++)
irq_dispose_mapping(fn->irq[i]);
+ put_device(&fn->dev);
}
/**
diff --git a/drivers/input/rmi4/rmi_f34.c b/drivers/input/rmi4/rmi_f34.c
index 0d9a5756e3f5..3b3ac71e53dc 100644
--- a/drivers/input/rmi4/rmi_f34.c
+++ b/drivers/input/rmi4/rmi_f34.c
@@ -471,7 +471,7 @@ static ssize_t rmi_driver_update_fw_store(struct device *dev,
if (buf[count - 1] == '\0' || buf[count - 1] == '\n')
copy_count -= 1;
- strncpy(fw_name, buf, copy_count);
+ memcpy(fw_name, buf, copy_count);
fw_name[copy_count] = '\0';
ret = request_firmware(&fw, fw_name, dev);
diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c
index 9f8d7b332d1b..c5b634940cfc 100644
--- a/drivers/input/serio/altera_ps2.c
+++ b/drivers/input/serio/altera_ps2.c
@@ -125,13 +125,11 @@ static int altera_ps2_probe(struct platform_device *pdev)
/*
* Remove one device from this driver.
*/
-static int altera_ps2_remove(struct platform_device *pdev)
+static void altera_ps2_remove(struct platform_device *pdev)
{
struct ps2if *ps2if = platform_get_drvdata(pdev);
serio_unregister_port(ps2if->io);
-
- return 0;
}
#ifdef CONFIG_OF
@@ -148,7 +146,7 @@ MODULE_DEVICE_TABLE(of, altera_ps2_match);
*/
static struct platform_driver altera_ps2_driver = {
.probe = altera_ps2_probe,
- .remove = altera_ps2_remove,
+ .remove_new = altera_ps2_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(altera_ps2_match),
diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c
index ec93cb4573c3..0bd6ae106809 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -173,18 +173,16 @@ static int ams_delta_serio_init(struct platform_device *pdev)
return 0;
}
-static int ams_delta_serio_exit(struct platform_device *pdev)
+static void ams_delta_serio_exit(struct platform_device *pdev)
{
struct ams_delta_serio *priv = platform_get_drvdata(pdev);
serio_unregister_port(priv->serio);
-
- return 0;
}
static struct platform_driver ams_delta_serio_driver = {
.probe = ams_delta_serio_init,
- .remove = ams_delta_serio_exit,
+ .remove_new = ams_delta_serio_exit,
.driver = {
.name = DRIVER_NAME
},
diff --git a/drivers/input/serio/apbps2.c b/drivers/input/serio/apbps2.c
index 3f6866d39b86..dbbb10251520 100644
--- a/drivers/input/serio/apbps2.c
+++ b/drivers/input/serio/apbps2.c
@@ -187,13 +187,11 @@ static int apbps2_of_probe(struct platform_device *ofdev)
return 0;
}
-static int apbps2_of_remove(struct platform_device *of_dev)
+static void apbps2_of_remove(struct platform_device *of_dev)
{
struct apbps2_priv *priv = platform_get_drvdata(of_dev);
serio_unregister_port(priv->io);
-
- return 0;
}
static const struct of_device_id apbps2_of_match[] = {
@@ -210,7 +208,7 @@ static struct platform_driver apbps2_of_driver = {
.of_match_table = apbps2_of_match,
},
.probe = apbps2_of_probe,
- .remove = apbps2_of_remove,
+ .remove_new = apbps2_of_remove,
};
module_platform_driver(apbps2_of_driver);
diff --git a/drivers/input/serio/arc_ps2.c b/drivers/input/serio/arc_ps2.c
index a6debb13d527..9d8726830140 100644
--- a/drivers/input/serio/arc_ps2.c
+++ b/drivers/input/serio/arc_ps2.c
@@ -232,7 +232,7 @@ static int arc_ps2_probe(struct platform_device *pdev)
return 0;
}
-static int arc_ps2_remove(struct platform_device *pdev)
+static void arc_ps2_remove(struct platform_device *pdev)
{
struct arc_ps2_data *arc_ps2 = platform_get_drvdata(pdev);
int i;
@@ -244,8 +244,6 @@ static int arc_ps2_remove(struct platform_device *pdev)
dev_dbg(&pdev->dev, "frame error count = %i\n", arc_ps2->frame_error);
dev_dbg(&pdev->dev, "buffer overflow count = %i\n",
arc_ps2->buf_overflow);
-
- return 0;
}
#ifdef CONFIG_OF
@@ -262,7 +260,7 @@ static struct platform_driver arc_ps2_driver = {
.of_match_table = of_match_ptr(arc_ps2_match),
},
.probe = arc_ps2_probe,
- .remove = arc_ps2_remove,
+ .remove_new = arc_ps2_remove,
};
module_platform_driver(arc_ps2_driver);
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
index 3da751f4a6bf..d5c9bb3d0103 100644
--- a/drivers/input/serio/ct82c710.c
+++ b/drivers/input/serio/ct82c710.c
@@ -180,11 +180,9 @@ static int ct82c710_probe(struct platform_device *dev)
return 0;
}
-static int ct82c710_remove(struct platform_device *dev)
+static void ct82c710_remove(struct platform_device *dev)
{
serio_unregister_port(ct82c710_port);
-
- return 0;
}
static struct platform_driver ct82c710_driver = {
@@ -192,7 +190,7 @@ static struct platform_driver ct82c710_driver = {
.name = "ct82c710",
},
.probe = ct82c710_probe,
- .remove = ct82c710_remove,
+ .remove_new = ct82c710_remove,
};
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
index b68793bf05c8..c2fda54dc384 100644
--- a/drivers/input/serio/i8042-sparcio.h
+++ b/drivers/input/serio/i8042-sparcio.h
@@ -82,11 +82,9 @@ static int sparc_i8042_probe(struct platform_device *op)
return 0;
}
-static int sparc_i8042_remove(struct platform_device *op)
+static void sparc_i8042_remove(struct platform_device *op)
{
of_iounmap(kbd_res, kbd_iobase, 8);
-
- return 0;
}
static const struct of_device_id sparc_i8042_match[] = {
@@ -103,7 +101,7 @@ static struct platform_driver sparc_i8042_driver = {
.of_match_table = sparc_i8042_match,
},
.probe = sparc_i8042_probe,
- .remove = sparc_i8042_remove,
+ .remove_new = sparc_i8042_remove,
};
static bool i8042_is_mr_coffee(void)
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 6dac7c1853a5..9fbb8d31575a 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -1584,13 +1584,11 @@ static int i8042_probe(struct platform_device *dev)
return error;
}
-static int i8042_remove(struct platform_device *dev)
+static void i8042_remove(struct platform_device *dev)
{
i8042_unregister_ports();
i8042_free_irqs();
i8042_controller_reset(false);
-
- return 0;
}
static struct platform_driver i8042_driver = {
@@ -1601,7 +1599,7 @@ static struct platform_driver i8042_driver = {
#endif
},
.probe = i8042_probe,
- .remove = i8042_remove,
+ .remove_new = i8042_remove,
.shutdown = i8042_shutdown,
};
diff --git a/drivers/input/serio/ioc3kbd.c b/drivers/input/serio/ioc3kbd.c
index d51bfe912db5..50552dc7b4f5 100644
--- a/drivers/input/serio/ioc3kbd.c
+++ b/drivers/input/serio/ioc3kbd.c
@@ -190,7 +190,7 @@ static int ioc3kbd_probe(struct platform_device *pdev)
return 0;
}
-static int ioc3kbd_remove(struct platform_device *pdev)
+static void ioc3kbd_remove(struct platform_device *pdev)
{
struct ioc3kbd_data *d = platform_get_drvdata(pdev);
@@ -198,13 +198,11 @@ static int ioc3kbd_remove(struct platform_device *pdev)
serio_unregister_port(d->kbd);
serio_unregister_port(d->aux);
-
- return 0;
}
static struct platform_driver ioc3kbd_driver = {
.probe = ioc3kbd_probe,
- .remove = ioc3kbd_remove,
+ .remove_new = ioc3kbd_remove,
.driver = {
.name = "ioc3-kbd",
},
diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
index 629e15089c21..5ccfb82759b3 100644
--- a/drivers/input/serio/maceps2.c
+++ b/drivers/input/serio/maceps2.c
@@ -148,12 +148,10 @@ static int maceps2_probe(struct platform_device *dev)
return 0;
}
-static int maceps2_remove(struct platform_device *dev)
+static void maceps2_remove(struct platform_device *dev)
{
serio_unregister_port(maceps2_port[0]);
serio_unregister_port(maceps2_port[1]);
-
- return 0;
}
static struct platform_driver maceps2_driver = {
@@ -161,7 +159,7 @@ static struct platform_driver maceps2_driver = {
.name = "maceps2",
},
.probe = maceps2_probe,
- .remove = maceps2_remove,
+ .remove_new = maceps2_remove,
};
static int __init maceps2_init(void)
diff --git a/drivers/input/serio/olpc_apsp.c b/drivers/input/serio/olpc_apsp.c
index 33a8e5889bd8..240a714f7081 100644
--- a/drivers/input/serio/olpc_apsp.c
+++ b/drivers/input/serio/olpc_apsp.c
@@ -238,7 +238,7 @@ err_pad:
return error;
}
-static int olpc_apsp_remove(struct platform_device *pdev)
+static void olpc_apsp_remove(struct platform_device *pdev)
{
struct olpc_apsp *priv = platform_get_drvdata(pdev);
@@ -246,8 +246,6 @@ static int olpc_apsp_remove(struct platform_device *pdev)
serio_unregister_port(priv->kbio);
serio_unregister_port(priv->padio);
-
- return 0;
}
static const struct of_device_id olpc_apsp_dt_ids[] = {
@@ -258,7 +256,7 @@ MODULE_DEVICE_TABLE(of, olpc_apsp_dt_ids);
static struct platform_driver olpc_apsp_driver = {
.probe = olpc_apsp_probe,
- .remove = olpc_apsp_remove,
+ .remove_new = olpc_apsp_remove,
.driver = {
.name = "olpc-apsp",
.of_match_table = olpc_apsp_dt_ids,
diff --git a/drivers/input/serio/ps2-gpio.c b/drivers/input/serio/ps2-gpio.c
index bc1dc484389b..c3ff60859a03 100644
--- a/drivers/input/serio/ps2-gpio.c
+++ b/drivers/input/serio/ps2-gpio.c
@@ -476,12 +476,11 @@ err_free_serio:
return error;
}
-static int ps2_gpio_remove(struct platform_device *pdev)
+static void ps2_gpio_remove(struct platform_device *pdev)
{
struct ps2_gpio_data *drvdata = platform_get_drvdata(pdev);
serio_unregister_port(drvdata->serio);
- return 0;
}
#if defined(CONFIG_OF)
@@ -494,7 +493,7 @@ MODULE_DEVICE_TABLE(of, ps2_gpio_match);
static struct platform_driver ps2_gpio_driver = {
.probe = ps2_gpio_probe,
- .remove = ps2_gpio_remove,
+ .remove_new = ps2_gpio_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(ps2_gpio_match),
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
index ba04058fc3cb..3f81f8749cd5 100644
--- a/drivers/input/serio/q40kbd.c
+++ b/drivers/input/serio/q40kbd.c
@@ -148,7 +148,7 @@ err_free_mem:
return error;
}
-static int q40kbd_remove(struct platform_device *pdev)
+static void q40kbd_remove(struct platform_device *pdev)
{
struct q40kbd *q40kbd = platform_get_drvdata(pdev);
@@ -160,15 +160,13 @@ static int q40kbd_remove(struct platform_device *pdev)
serio_unregister_port(q40kbd->port);
free_irq(Q40_IRQ_KEYBOARD, q40kbd);
kfree(q40kbd);
-
- return 0;
}
static struct platform_driver q40kbd_driver = {
.driver = {
.name = "q40kbd",
},
- .remove = q40kbd_remove,
+ .remove_new = q40kbd_remove,
};
module_platform_driver_probe(q40kbd_driver, q40kbd_probe);
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
index e8a9709f32eb..9bbfefd092c0 100644
--- a/drivers/input/serio/rpckbd.c
+++ b/drivers/input/serio/rpckbd.c
@@ -133,20 +133,18 @@ static int rpckbd_probe(struct platform_device *dev)
return 0;
}
-static int rpckbd_remove(struct platform_device *dev)
+static void rpckbd_remove(struct platform_device *dev)
{
struct serio *serio = platform_get_drvdata(dev);
struct rpckbd_data *rpckbd = serio->port_data;
serio_unregister_port(serio);
kfree(rpckbd);
-
- return 0;
}
static struct platform_driver rpckbd_driver = {
.probe = rpckbd_probe,
- .remove = rpckbd_remove,
+ .remove_new = rpckbd_remove,
.driver = {
.name = "kart",
},
diff --git a/drivers/input/serio/sun4i-ps2.c b/drivers/input/serio/sun4i-ps2.c
index eb262640192e..aec66d9f5176 100644
--- a/drivers/input/serio/sun4i-ps2.c
+++ b/drivers/input/serio/sun4i-ps2.c
@@ -297,7 +297,7 @@ err_free_mem:
return error;
}
-static int sun4i_ps2_remove(struct platform_device *pdev)
+static void sun4i_ps2_remove(struct platform_device *pdev)
{
struct sun4i_ps2data *drvdata = platform_get_drvdata(pdev);
@@ -311,8 +311,6 @@ static int sun4i_ps2_remove(struct platform_device *pdev)
iounmap(drvdata->reg_base);
kfree(drvdata);
-
- return 0;
}
static const struct of_device_id sun4i_ps2_match[] = {
@@ -324,7 +322,7 @@ MODULE_DEVICE_TABLE(of, sun4i_ps2_match);
static struct platform_driver sun4i_ps2_driver = {
.probe = sun4i_ps2_probe,
- .remove = sun4i_ps2_remove,
+ .remove_new = sun4i_ps2_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = sun4i_ps2_match,
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
index f3d28da70b75..d8f9faf2b529 100644
--- a/drivers/input/serio/xilinx_ps2.c
+++ b/drivers/input/serio/xilinx_ps2.c
@@ -329,7 +329,7 @@ failed1:
* if the driver module is being unloaded. It frees any resources allocated to
* the device.
*/
-static int xps2_of_remove(struct platform_device *of_dev)
+static void xps2_of_remove(struct platform_device *of_dev)
{
struct xps2data *drvdata = platform_get_drvdata(of_dev);
struct resource r_mem; /* IO mem resources */
@@ -344,8 +344,6 @@ static int xps2_of_remove(struct platform_device *of_dev)
release_mem_region(r_mem.start, resource_size(&r_mem));
kfree(drvdata);
-
- return 0;
}
/* Match table for of_platform binding */
@@ -361,7 +359,7 @@ static struct platform_driver xps2_of_driver = {
.of_match_table = xps2_of_match,
},
.probe = xps2_of_probe,
- .remove = xps2_of_remove,
+ .remove_new = xps2_of_remove,
};
module_platform_driver(xps2_of_driver);
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
index edb36d663f22..a0598e9c7aff 100644
--- a/drivers/input/touchscreen/ad7877.c
+++ b/drivers/input/touchscreen/ad7877.c
@@ -612,10 +612,11 @@ static umode_t ad7877_attr_is_visible(struct kobject *kobj,
return mode;
}
-static const struct attribute_group ad7877_attr_group = {
+static const struct attribute_group ad7877_group = {
.is_visible = ad7877_attr_is_visible,
.attrs = ad7877_attributes,
};
+__ATTRIBUTE_GROUPS(ad7877);
static void ad7877_setup_ts_def_msg(struct spi_device *spi, struct ad7877 *ts)
{
@@ -777,10 +778,6 @@ static int ad7877_probe(struct spi_device *spi)
return err;
}
- err = devm_device_add_group(&spi->dev, &ad7877_attr_group);
- if (err)
- return err;
-
err = input_register_device(input_dev);
if (err)
return err;
@@ -810,8 +807,9 @@ static DEFINE_SIMPLE_DEV_PM_OPS(ad7877_pm, ad7877_suspend, ad7877_resume);
static struct spi_driver ad7877_driver = {
.driver = {
- .name = "ad7877",
- .pm = pm_sleep_ptr(&ad7877_pm),
+ .name = "ad7877",
+ .dev_groups = ad7877_groups,
+ .pm = pm_sleep_ptr(&ad7877_pm),
},
.probe = ad7877_probe,
};
diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c
index feaa6f8b01ed..5c094ab74698 100644
--- a/drivers/input/touchscreen/ad7879-i2c.c
+++ b/drivers/input/touchscreen/ad7879-i2c.c
@@ -58,9 +58,10 @@ MODULE_DEVICE_TABLE(of, ad7879_i2c_dt_ids);
static struct i2c_driver ad7879_i2c_driver = {
.driver = {
- .name = "ad7879",
- .pm = &ad7879_pm_ops,
- .of_match_table = of_match_ptr(ad7879_i2c_dt_ids),
+ .name = "ad7879",
+ .dev_groups = ad7879_groups,
+ .pm = &ad7879_pm_ops,
+ .of_match_table = of_match_ptr(ad7879_i2c_dt_ids),
},
.probe = ad7879_i2c_probe,
.id_table = ad7879_id,
diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c
index 50e889846800..064968fe57cf 100644
--- a/drivers/input/touchscreen/ad7879-spi.c
+++ b/drivers/input/touchscreen/ad7879-spi.c
@@ -56,9 +56,10 @@ MODULE_DEVICE_TABLE(of, ad7879_spi_dt_ids);
static struct spi_driver ad7879_spi_driver = {
.driver = {
- .name = "ad7879",
- .pm = &ad7879_pm_ops,
- .of_match_table = of_match_ptr(ad7879_spi_dt_ids),
+ .name = "ad7879",
+ .dev_groups = ad7879_groups,
+ .pm = &ad7879_pm_ops,
+ .of_match_table = of_match_ptr(ad7879_spi_dt_ids),
},
.probe = ad7879_spi_probe,
};
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c
index e850853328f1..e5d69bf2276e 100644
--- a/drivers/input/touchscreen/ad7879.c
+++ b/drivers/input/touchscreen/ad7879.c
@@ -391,6 +391,12 @@ static const struct attribute_group ad7879_attr_group = {
.attrs = ad7879_attributes,
};
+const struct attribute_group *ad7879_groups[] = {
+ &ad7879_attr_group,
+ NULL
+};
+EXPORT_SYMBOL_GPL(ad7879_groups);
+
#ifdef CONFIG_GPIOLIB
static int ad7879_gpio_direction_input(struct gpio_chip *chip,
unsigned gpio)
@@ -612,10 +618,6 @@ int ad7879_probe(struct device *dev, struct regmap *regmap,
__ad7879_disable(ts);
- err = devm_device_add_group(dev, &ad7879_attr_group);
- if (err)
- return err;
-
err = ad7879_gpio_add(ts);
if (err)
return err;
diff --git a/drivers/input/touchscreen/ad7879.h b/drivers/input/touchscreen/ad7879.h
index ae8aa1428e56..d71a8e787290 100644
--- a/drivers/input/touchscreen/ad7879.h
+++ b/drivers/input/touchscreen/ad7879.h
@@ -8,11 +8,14 @@
#ifndef _AD7879_H_
#define _AD7879_H_
+#include <linux/pm.h>
#include <linux/types.h>
+struct attribute_group;
struct device;
struct regmap;
+extern const struct attribute_group *ad7879_groups[];
extern const struct dev_pm_ops ad7879_pm_ops;
int ad7879_probe(struct device *dev, struct regmap *regmap,
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index bb1058b1e7fd..d2bbb436a77d 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)
@@ -628,15 +625,12 @@ static ssize_t ads7846_disable_store(struct device *dev,
static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store);
-static struct attribute *ads784x_attributes[] = {
+static struct attribute *ads784x_attrs[] = {
&dev_attr_pen_down.attr,
&dev_attr_disable.attr,
NULL,
};
-
-static const struct attribute_group ads784x_attr_group = {
- .attrs = ads784x_attributes,
-};
+ATTRIBUTE_GROUPS(ads784x);
/*--------------------------------------------------------------------------*/
@@ -989,8 +983,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 +991,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 +1101,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 +1111,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 +1228,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);
}
@@ -1395,10 +1354,6 @@ static int ads7846_probe(struct spi_device *spi)
else
(void) ads7846_read12_ser(dev, READ_12BIT_SER(vaux));
- err = devm_device_add_group(dev, &ads784x_attr_group);
- if (err)
- return err;
-
err = input_register_device(input_dev);
if (err)
return err;
@@ -1424,9 +1379,10 @@ static void ads7846_remove(struct spi_device *spi)
static struct spi_driver ads7846_driver = {
.driver = {
- .name = "ads7846",
- .pm = pm_sleep_ptr(&ads7846_pm),
- .of_match_table = of_match_ptr(ads7846_dt_ids),
+ .name = "ads7846",
+ .dev_groups = ads784x_groups,
+ .pm = pm_sleep_ptr(&ads7846_pm),
+ .of_match_table = ads7846_dt_ids,
},
.probe = ads7846_probe,
.remove = ads7846_remove,
diff --git a/drivers/input/touchscreen/cyttsp5.c b/drivers/input/touchscreen/cyttsp5.c
index db5a885ecd72..68527ede5c0e 100644
--- a/drivers/input/touchscreen/cyttsp5.c
+++ b/drivers/input/touchscreen/cyttsp5.c
@@ -207,7 +207,7 @@ struct cyttsp5 {
int num_prv_rec;
struct regmap *regmap;
struct touchscreen_properties prop;
- struct regulator *vdd;
+ struct regulator_bulk_data supplies[2];
};
/*
@@ -817,7 +817,7 @@ static void cyttsp5_cleanup(void *data)
{
struct cyttsp5 *ts = data;
- regulator_disable(ts->vdd);
+ regulator_bulk_disable(ARRAY_SIZE(ts->supplies), ts->supplies);
}
static int cyttsp5_probe(struct device *dev, struct regmap *regmap, int irq,
@@ -840,9 +840,12 @@ static int cyttsp5_probe(struct device *dev, struct regmap *regmap, int irq,
init_completion(&ts->cmd_done);
/* Power up the device */
- ts->vdd = devm_regulator_get(dev, "vdd");
- if (IS_ERR(ts->vdd)) {
- error = PTR_ERR(ts->vdd);
+ ts->supplies[0].supply = "vdd";
+ ts->supplies[1].supply = "vddio";
+ error = devm_regulator_bulk_get(dev, ARRAY_SIZE(ts->supplies),
+ ts->supplies);
+ if (error) {
+ dev_err(ts->dev, "Failed to get regulators, error %d\n", error);
return error;
}
@@ -850,9 +853,11 @@ static int cyttsp5_probe(struct device *dev, struct regmap *regmap, int irq,
if (error)
return error;
- error = regulator_enable(ts->vdd);
- if (error)
+ error = regulator_bulk_enable(ARRAY_SIZE(ts->supplies), ts->supplies);
+ if (error) {
+ dev_err(ts->dev, "Failed to enable regulators, error %d\n", error);
return error;
+ }
ts->input = devm_input_allocate_device(dev);
if (!ts->input) {
diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c
index f91d0e02ddae..d71690ce6463 100644
--- a/drivers/input/touchscreen/da9052_tsi.c
+++ b/drivers/input/touchscreen/da9052_tsi.c
@@ -311,7 +311,7 @@ err_free_mem:
return error;
}
-static int da9052_ts_remove(struct platform_device *pdev)
+static void da9052_ts_remove(struct platform_device *pdev)
{
struct da9052_tsi *tsi = platform_get_drvdata(pdev);
@@ -322,13 +322,11 @@ static int da9052_ts_remove(struct platform_device *pdev)
input_unregister_device(tsi->dev);
kfree(tsi);
-
- return 0;
}
static struct platform_driver da9052_tsi_driver = {
.probe = da9052_ts_probe,
- .remove = da9052_ts_remove,
+ .remove_new = da9052_ts_remove,
.driver = {
.name = "da9052-tsi",
},
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 457d53337fbb..3e102bcc4a1c 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -580,10 +580,7 @@ static struct attribute *edt_ft5x06_attrs[] = {
&dev_attr_crc_errors.attr,
NULL
};
-
-static const struct attribute_group edt_ft5x06_attr_group = {
- .attrs = edt_ft5x06_attrs,
-};
+ATTRIBUTE_GROUPS(edt_ft5x06);
static void edt_ft5x06_restore_reg_parameters(struct edt_ft5x06_ts_data *tsdata)
{
@@ -1330,10 +1327,6 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
return error;
}
- error = devm_device_add_group(&client->dev, &edt_ft5x06_attr_group);
- if (error)
- return error;
-
error = input_register_device(input);
if (error)
return error;
@@ -1502,6 +1495,7 @@ MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match);
static struct i2c_driver edt_ft5x06_ts_driver = {
.driver = {
.name = "edt_ft5x06",
+ .dev_groups = edt_ft5x06_groups,
.of_match_table = edt_ft5x06_of_match,
.pm = pm_sleep_ptr(&edt_ft5x06_ts_pm_ops),
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c
index a1af3de9f310..365765d40e62 100644
--- a/drivers/input/touchscreen/elants_i2c.c
+++ b/drivers/input/touchscreen/elants_i2c.c
@@ -1299,7 +1299,7 @@ static ELANTS_VERSION_ATTR(solution_version);
static ELANTS_VERSION_ATTR(bc_version);
static ELANTS_VERSION_ATTR(iap_version);
-static struct attribute *elants_attributes[] = {
+static struct attribute *elants_i2c_attrs[] = {
&dev_attr_calibrate.attr,
&dev_attr_update_fw.attr,
&dev_attr_iap_mode.attr,
@@ -1313,10 +1313,7 @@ static struct attribute *elants_attributes[] = {
&elants_ver_attr_iap_version.dattr.attr,
NULL
};
-
-static const struct attribute_group elants_attribute_group = {
- .attrs = elants_attributes,
-};
+ATTRIBUTE_GROUPS(elants_i2c);
static int elants_i2c_power_on(struct elants_data *ts)
{
@@ -1552,13 +1549,6 @@ static int elants_i2c_probe(struct i2c_client *client)
return error;
}
- error = devm_device_add_group(&client->dev, &elants_attribute_group);
- if (error) {
- dev_err(&client->dev, "failed to create sysfs attributes: %d\n",
- error);
- return error;
- }
-
return 0;
}
@@ -1667,6 +1657,7 @@ static struct i2c_driver elants_i2c_driver = {
.id_table = elants_i2c_id,
.driver = {
.name = DEVICE_NAME,
+ .dev_groups = elants_i2c_groups,
.pm = pm_sleep_ptr(&elants_i2c_pm_ops),
.acpi_match_table = ACPI_PTR(elants_acpi_id),
.of_match_table = of_match_ptr(elants_of_match),
diff --git a/drivers/input/touchscreen/exc3000.c b/drivers/input/touchscreen/exc3000.c
index 4c0d99aae9e0..a4030cc9ff60 100644
--- a/drivers/input/touchscreen/exc3000.c
+++ b/drivers/input/touchscreen/exc3000.c
@@ -325,16 +325,13 @@ static ssize_t type_show(struct device *dev,
}
static DEVICE_ATTR_RO(type);
-static struct attribute *sysfs_attrs[] = {
+static struct attribute *exc3000_attrs[] = {
&dev_attr_fw_version.attr,
&dev_attr_model.attr,
&dev_attr_type.attr,
NULL
};
-
-static struct attribute_group exc3000_attribute_group = {
- .attrs = sysfs_attrs
-};
+ATTRIBUTE_GROUPS(exc3000);
static int exc3000_probe(struct i2c_client *client)
{
@@ -437,10 +434,6 @@ static int exc3000_probe(struct i2c_client *client)
i2c_set_clientdata(client, data);
- error = devm_device_add_group(&client->dev, &exc3000_attribute_group);
- if (error)
- return error;
-
return 0;
}
@@ -473,6 +466,7 @@ MODULE_DEVICE_TABLE(acpi, exc3000_acpi_match);
static struct i2c_driver exc3000_driver = {
.driver = {
.name = "exc3000",
+ .dev_groups = exc3000_groups,
.of_match_table = of_match_ptr(exc3000_of_match),
.acpi_match_table = ACPI_PTR(exc3000_acpi_match),
},
diff --git a/drivers/input/touchscreen/hideep.c b/drivers/input/touchscreen/hideep.c
index 404153338df7..0f58258306bf 100644
--- a/drivers/input/touchscreen/hideep.c
+++ b/drivers/input/touchscreen/hideep.c
@@ -954,16 +954,13 @@ static DEVICE_ATTR(version, 0664, hideep_fw_version_show, NULL);
static DEVICE_ATTR(product_id, 0664, hideep_product_id_show, NULL);
static DEVICE_ATTR(update_fw, 0664, NULL, hideep_update_fw);
-static struct attribute *hideep_ts_sysfs_entries[] = {
+static struct attribute *hideep_ts_attrs[] = {
&dev_attr_version.attr,
&dev_attr_product_id.attr,
&dev_attr_update_fw.attr,
NULL,
};
-
-static const struct attribute_group hideep_ts_attr_group = {
- .attrs = hideep_ts_sysfs_entries,
-};
+ATTRIBUTE_GROUPS(hideep_ts);
static void hideep_set_work_mode(struct hideep_ts *ts)
{
@@ -1096,13 +1093,6 @@ static int hideep_probe(struct i2c_client *client)
return error;
}
- error = devm_device_add_group(&client->dev, &hideep_ts_attr_group);
- if (error) {
- dev_err(&client->dev,
- "failed to add sysfs attributes: %d\n", error);
- return error;
- }
-
return 0;
}
@@ -1131,6 +1121,7 @@ MODULE_DEVICE_TABLE(of, hideep_match_table);
static struct i2c_driver hideep_driver = {
.driver = {
.name = HIDEEP_I2C_NAME,
+ .dev_groups = hideep_ts_groups,
.of_match_table = of_match_ptr(hideep_match_table),
.acpi_match_table = ACPI_PTR(hideep_acpi_id),
.pm = pm_sleep_ptr(&hideep_pm_ops),
diff --git a/drivers/input/touchscreen/hycon-hy46xx.c b/drivers/input/touchscreen/hycon-hy46xx.c
index 2450cfa14de9..d0f257989fd6 100644
--- a/drivers/input/touchscreen/hycon-hy46xx.c
+++ b/drivers/input/touchscreen/hycon-hy46xx.c
@@ -274,10 +274,7 @@ static struct attribute *hycon_hy46xx_attrs[] = {
&hycon_hy46xx_attr_bootloader_version.dattr.attr,
NULL
};
-
-static const struct attribute_group hycon_hy46xx_attr_group = {
- .attrs = hycon_hy46xx_attrs,
-};
+ATTRIBUTE_GROUPS(hycon_hy46xx);
static void hycon_hy46xx_get_defaults(struct device *dev, struct hycon_hy46xx_data *tsdata)
{
@@ -535,10 +532,6 @@ static int hycon_hy46xx_probe(struct i2c_client *client)
return error;
}
- error = devm_device_add_group(&client->dev, &hycon_hy46xx_attr_group);
- if (error)
- return error;
-
error = input_register_device(input);
if (error)
return error;
@@ -576,6 +569,7 @@ MODULE_DEVICE_TABLE(of, hycon_hy46xx_of_match);
static struct i2c_driver hycon_hy46xx_driver = {
.driver = {
.name = "hycon_hy46xx",
+ .dev_groups = hycon_hy46xx_groups,
.of_match_table = hycon_hy46xx_of_match,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
index ad6828e4f2e2..31ffdc2a93f3 100644
--- a/drivers/input/touchscreen/ili210x.c
+++ b/drivers/input/touchscreen/ili210x.c
@@ -876,7 +876,7 @@ exit:
static DEVICE_ATTR(firmware_update, 0200, NULL, ili210x_firmware_update_store);
-static struct attribute *ili210x_attributes[] = {
+static struct attribute *ili210x_attrs[] = {
&dev_attr_calibrate.attr,
&dev_attr_firmware_update.attr,
&dev_attr_firmware_version.attr,
@@ -904,10 +904,11 @@ static umode_t ili210x_attributes_visible(struct kobject *kobj,
return attr->mode;
}
-static const struct attribute_group ili210x_attr_group = {
- .attrs = ili210x_attributes,
+static const struct attribute_group ili210x_group = {
+ .attrs = ili210x_attrs,
.is_visible = ili210x_attributes_visible,
};
+__ATTRIBUTE_GROUPS(ili210x);
static void ili210x_power_down(void *data)
{
@@ -1013,13 +1014,6 @@ static int ili210x_i2c_probe(struct i2c_client *client)
if (error)
return error;
- error = devm_device_add_group(dev, &ili210x_attr_group);
- if (error) {
- dev_err(dev, "Unable to create sysfs attributes, err: %d\n",
- error);
- return error;
- }
-
error = input_register_device(priv->input);
if (error) {
dev_err(dev, "Cannot register input device, err: %d\n", error);
@@ -1050,6 +1044,7 @@ MODULE_DEVICE_TABLE(of, ili210x_dt_ids);
static struct i2c_driver ili210x_ts_driver = {
.driver = {
.name = "ili210x_i2c",
+ .dev_groups = ili210x_groups,
.of_match_table = ili210x_dt_ids,
},
.id_table = ili210x_i2c_id,
diff --git a/drivers/input/touchscreen/ilitek_ts_i2c.c b/drivers/input/touchscreen/ilitek_ts_i2c.c
index 2f872e95fbba..90c4934e750a 100644
--- a/drivers/input/touchscreen/ilitek_ts_i2c.c
+++ b/drivers/input/touchscreen/ilitek_ts_i2c.c
@@ -537,10 +537,7 @@ static struct attribute *ilitek_sysfs_attrs[] = {
&dev_attr_product_id.attr,
NULL
};
-
-static struct attribute_group ilitek_attrs_group = {
- .attrs = ilitek_sysfs_attrs,
-};
+ATTRIBUTE_GROUPS(ilitek_sysfs);
static int ilitek_ts_i2c_probe(struct i2c_client *client)
{
@@ -595,12 +592,6 @@ static int ilitek_ts_i2c_probe(struct i2c_client *client)
return error;
}
- error = devm_device_add_group(dev, &ilitek_attrs_group);
- if (error) {
- dev_err(dev, "sysfs create group failed: %d\n", error);
- return error;
- }
-
return 0;
}
@@ -675,6 +666,7 @@ MODULE_DEVICE_TABLE(of, ilitek_ts_i2c_match);
static struct i2c_driver ilitek_ts_i2c_driver = {
.driver = {
.name = ILITEK_TS_NAME,
+ .dev_groups = ilitek_sysfs_groups,
.pm = pm_sleep_ptr(&ilitek_pm_ops),
.of_match_table = of_match_ptr(ilitek_ts_i2c_match),
.acpi_match_table = ACPI_PTR(ilitekts_acpi_id),
diff --git a/drivers/input/touchscreen/iqs5xx.c b/drivers/input/touchscreen/iqs5xx.c
index b4768b66eb10..a3f4fb85bee5 100644
--- a/drivers/input/touchscreen/iqs5xx.c
+++ b/drivers/input/touchscreen/iqs5xx.c
@@ -974,10 +974,11 @@ static umode_t iqs5xx_attr_is_visible(struct kobject *kobj,
return attr->mode;
}
-static const struct attribute_group iqs5xx_attr_group = {
+static const struct attribute_group iqs5xx_group = {
.is_visible = iqs5xx_attr_is_visible,
.attrs = iqs5xx_attrs,
};
+__ATTRIBUTE_GROUPS(iqs5xx);
static int iqs5xx_suspend(struct device *dev)
{
@@ -1053,12 +1054,6 @@ static int iqs5xx_probe(struct i2c_client *client)
return error;
}
- error = devm_device_add_group(&client->dev, &iqs5xx_attr_group);
- if (error) {
- dev_err(&client->dev, "Failed to add attributes: %d\n", error);
- return error;
- }
-
if (iqs5xx->input) {
error = input_register_device(iqs5xx->input);
if (error)
@@ -1089,6 +1084,7 @@ MODULE_DEVICE_TABLE(of, iqs5xx_of_match);
static struct i2c_driver iqs5xx_i2c_driver = {
.driver = {
.name = "iqs5xx",
+ .dev_groups = iqs5xx_groups,
.of_match_table = iqs5xx_of_match,
.pm = pm_sleep_ptr(&iqs5xx_pm),
},
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c
index 85b95ed461e7..bfbebe245040 100644
--- a/drivers/input/touchscreen/mainstone-wm97xx.c
+++ b/drivers/input/touchscreen/mainstone-wm97xx.c
@@ -252,18 +252,16 @@ static int mainstone_wm97xx_probe(struct platform_device *pdev)
return wm97xx_register_mach_ops(wm, &mainstone_mach_ops);
}
-static int mainstone_wm97xx_remove(struct platform_device *pdev)
+static void mainstone_wm97xx_remove(struct platform_device *pdev)
{
struct wm97xx *wm = platform_get_drvdata(pdev);
wm97xx_unregister_mach_ops(wm);
-
- return 0;
}
static struct platform_driver mainstone_wm97xx_driver = {
.probe = mainstone_wm97xx_probe,
- .remove = mainstone_wm97xx_remove,
+ .remove_new = mainstone_wm97xx_remove,
.driver = {
.name = "wm97xx-touch",
},
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
index ae0d978c83bf..cbcd6e34efb7 100644
--- a/drivers/input/touchscreen/mc13783_ts.c
+++ b/drivers/input/touchscreen/mc13783_ts.c
@@ -217,18 +217,16 @@ err_free_mem:
return ret;
}
-static int mc13783_ts_remove(struct platform_device *pdev)
+static void mc13783_ts_remove(struct platform_device *pdev)
{
struct mc13783_ts_priv *priv = platform_get_drvdata(pdev);
input_unregister_device(priv->idev);
kfree(priv);
-
- return 0;
}
static struct platform_driver mc13783_ts_driver = {
- .remove = mc13783_ts_remove,
+ .remove_new = mc13783_ts_remove,
.driver = {
.name = MC13783_TS_NAME,
},
diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c
index 2ac4483fbc25..aa325486f618 100644
--- a/drivers/input/touchscreen/melfas_mip4.c
+++ b/drivers/input/touchscreen/melfas_mip4.c
@@ -1419,10 +1419,7 @@ static struct attribute *mip4_attrs[] = {
&dev_attr_update_fw.attr,
NULL,
};
-
-static const struct attribute_group mip4_attr_group = {
- .attrs = mip4_attrs,
-};
+ATTRIBUTE_GROUPS(mip4);
static int mip4_probe(struct i2c_client *client)
{
@@ -1514,13 +1511,6 @@ static int mip4_probe(struct i2c_client *client)
return error;
}
- error = devm_device_add_group(&client->dev, &mip4_attr_group);
- if (error) {
- dev_err(&client->dev,
- "Failed to create sysfs attribute group: %d\n", error);
- return error;
- }
-
return 0;
}
@@ -1589,6 +1579,7 @@ static struct i2c_driver mip4_driver = {
.probe = mip4_probe,
.driver = {
.name = MIP4_DEVICE_NAME,
+ .dev_groups = mip4_groups,
.of_match_table = of_match_ptr(mip4_of_match),
.acpi_match_table = ACPI_PTR(mip4_acpi_match),
.pm = pm_sleep_ptr(&mip4_pm_ops),
diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c
index b2da0194e02a..821245019fea 100644
--- a/drivers/input/touchscreen/pcap_ts.c
+++ b/drivers/input/touchscreen/pcap_ts.c
@@ -197,7 +197,7 @@ fail:
return err;
}
-static int pcap_ts_remove(struct platform_device *pdev)
+static void pcap_ts_remove(struct platform_device *pdev)
{
struct pcap_ts *pcap_ts = platform_get_drvdata(pdev);
@@ -207,8 +207,6 @@ static int pcap_ts_remove(struct platform_device *pdev)
input_unregister_device(pcap_ts->input);
kfree(pcap_ts);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -240,7 +238,7 @@ static const struct dev_pm_ops pcap_ts_pm_ops = {
static struct platform_driver pcap_ts_driver = {
.probe = pcap_ts_probe,
- .remove = pcap_ts_remove,
+ .remove_new = pcap_ts_remove,
.driver = {
.name = "pcap-ts",
.pm = PCAP_TS_PM_OPS,
diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c
index 78dd3059d585..13c500e776f6 100644
--- a/drivers/input/touchscreen/raydium_i2c_ts.c
+++ b/drivers/input/touchscreen/raydium_i2c_ts.c
@@ -1004,7 +1004,7 @@ static DEVICE_ATTR(boot_mode, S_IRUGO, raydium_i2c_boot_mode_show, NULL);
static DEVICE_ATTR(update_fw, S_IWUSR, NULL, raydium_i2c_update_fw_store);
static DEVICE_ATTR(calibrate, S_IWUSR, NULL, raydium_i2c_calibrate_store);
-static struct attribute *raydium_i2c_attributes[] = {
+static struct attribute *raydium_i2c_attrs[] = {
&dev_attr_update_fw.attr,
&dev_attr_boot_mode.attr,
&dev_attr_fw_version.attr,
@@ -1012,10 +1012,7 @@ static struct attribute *raydium_i2c_attributes[] = {
&dev_attr_calibrate.attr,
NULL
};
-
-static const struct attribute_group raydium_i2c_attribute_group = {
- .attrs = raydium_i2c_attributes,
-};
+ATTRIBUTE_GROUPS(raydium_i2c);
static int raydium_i2c_power_on(struct raydium_data *ts)
{
@@ -1174,14 +1171,6 @@ static int raydium_i2c_probe(struct i2c_client *client)
return error;
}
- error = devm_device_add_group(&client->dev,
- &raydium_i2c_attribute_group);
- if (error) {
- dev_err(&client->dev, "failed to create sysfs attributes: %d\n",
- error);
- return error;
- }
-
return 0;
}
@@ -1265,6 +1254,7 @@ static struct i2c_driver raydium_i2c_driver = {
.id_table = raydium_i2c_id,
.driver = {
.name = "raydium_ts",
+ .dev_groups = raydium_i2c_groups,
.pm = pm_sleep_ptr(&raydium_i2c_pm_ops),
.acpi_match_table = ACPI_PTR(raydium_acpi_id),
.of_match_table = of_match_ptr(raydium_of_match),
diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c
index 240424f06b98..4493ad0c9322 100644
--- a/drivers/input/touchscreen/rohm_bu21023.c
+++ b/drivers/input/touchscreen/rohm_bu21023.c
@@ -854,10 +854,7 @@ static struct attribute *rohm_ts_attrs[] = {
&dev_attr_inv_y.attr,
NULL,
};
-
-static const struct attribute_group rohm_ts_attr_group = {
- .attrs = rohm_ts_attrs,
-};
+ATTRIBUTE_GROUPS(rohm_ts);
static int rohm_ts_device_init(struct i2c_client *client, u8 setup2)
{
@@ -1164,12 +1161,6 @@ static int rohm_bu21023_i2c_probe(struct i2c_client *client)
return error;
}
- error = devm_device_add_group(dev, &rohm_ts_attr_group);
- if (error) {
- dev_err(dev, "failed to create sysfs group: %d\n", error);
- return error;
- }
-
return error;
}
@@ -1182,6 +1173,7 @@ MODULE_DEVICE_TABLE(i2c, rohm_bu21023_i2c_id);
static struct i2c_driver rohm_bu21023_i2c_driver = {
.driver = {
.name = BU21023_NAME,
+ .dev_groups = rohm_ts_groups,
},
.probe = rohm_bu21023_i2c_probe,
.id_table = rohm_bu21023_i2c_id,
diff --git a/drivers/input/touchscreen/s6sy761.c b/drivers/input/touchscreen/s6sy761.c
index 998d99d18911..149cc2c4925e 100644
--- a/drivers/input/touchscreen/s6sy761.c
+++ b/drivers/input/touchscreen/s6sy761.c
@@ -286,10 +286,7 @@ static struct attribute *s6sy761_sysfs_attrs[] = {
&dev_attr_devid.attr,
NULL
};
-
-static struct attribute_group s6sy761_attribute_group = {
- .attrs = s6sy761_sysfs_attrs
-};
+ATTRIBUTE_GROUPS(s6sy761_sysfs);
static int s6sy761_power_on(struct s6sy761_data *sdata)
{
@@ -465,10 +462,6 @@ static int s6sy761_probe(struct i2c_client *client)
if (err)
return err;
- err = devm_device_add_group(&client->dev, &s6sy761_attribute_group);
- if (err)
- return err;
-
pm_runtime_enable(&client->dev);
return 0;
@@ -535,6 +528,7 @@ MODULE_DEVICE_TABLE(i2c, s6sy761_id);
static struct i2c_driver s6sy761_driver = {
.driver = {
.name = S6SY761_DEV_NAME,
+ .dev_groups = s6sy761_sysfs_groups,
.of_match_table = of_match_ptr(s6sy761_of_match),
.pm = pm_ptr(&s6sy761_pm_ops),
},
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index 56e371fd88fa..85010fa07908 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -517,10 +517,7 @@ static struct attribute *stmfts_sysfs_attrs[] = {
&dev_attr_hover_enable.attr,
NULL
};
-
-static struct attribute_group stmfts_attribute_group = {
- .attrs = stmfts_sysfs_attrs
-};
+ATTRIBUTE_GROUPS(stmfts_sysfs);
static int stmfts_power_on(struct stmfts_data *sdata)
{
@@ -727,10 +724,6 @@ static int stmfts_probe(struct i2c_client *client)
}
}
- err = devm_device_add_group(&client->dev, &stmfts_attribute_group);
- if (err)
- return err;
-
pm_runtime_enable(&client->dev);
device_enable_async_suspend(&client->dev);
@@ -804,6 +797,7 @@ MODULE_DEVICE_TABLE(i2c, stmfts_id);
static struct i2c_driver stmfts_driver = {
.driver = {
.name = STMFTS_DEV_NAME,
+ .dev_groups = stmfts_sysfs_groups,
.of_match_table = of_match_ptr(stmfts_of_match),
.pm = pm_ptr(&stmfts_pm_ops),
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c
index 25c45c3a3561..b204fdb2d22c 100644
--- a/drivers/input/touchscreen/stmpe-ts.c
+++ b/drivers/input/touchscreen/stmpe-ts.c
@@ -350,13 +350,11 @@ static int stmpe_input_probe(struct platform_device *pdev)
return 0;
}
-static int stmpe_ts_remove(struct platform_device *pdev)
+static void stmpe_ts_remove(struct platform_device *pdev)
{
struct stmpe_touch *ts = platform_get_drvdata(pdev);
stmpe_disable(ts->stmpe, STMPE_BLOCK_TOUCHSCREEN);
-
- return 0;
}
static struct platform_driver stmpe_ts_driver = {
@@ -364,7 +362,7 @@ static struct platform_driver stmpe_ts_driver = {
.name = STMPE_TS_NAME,
},
.probe = stmpe_input_probe,
- .remove = stmpe_ts_remove,
+ .remove_new = stmpe_ts_remove,
};
module_platform_driver(stmpe_ts_driver);
diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c
index 577c75c83e25..92b2b840b4b7 100644
--- a/drivers/input/touchscreen/sun4i-ts.c
+++ b/drivers/input/touchscreen/sun4i-ts.c
@@ -22,7 +22,7 @@
* in the kernel). So this driver offers straight forward, reliable single
* touch functionality only.
*
- * s.a. A20 User Manual "1.15 TP" (Documentation/arm/sunxi.rst)
+ * s.a. A20 User Manual "1.15 TP" (Documentation/arch/arm/sunxi.rst)
* (looks like the description in the A20 User Manual v1.3 is better
* than the one in the A10 User Manual v.1.5)
*/
@@ -375,7 +375,7 @@ static int sun4i_ts_probe(struct platform_device *pdev)
return 0;
}
-static int sun4i_ts_remove(struct platform_device *pdev)
+static void sun4i_ts_remove(struct platform_device *pdev)
{
struct sun4i_ts_data *ts = platform_get_drvdata(pdev);
@@ -385,8 +385,6 @@ static int sun4i_ts_remove(struct platform_device *pdev)
/* Deactivate all IRQs */
writel(0, ts->base + TP_INT_FIFOC);
-
- return 0;
}
static const struct of_device_id sun4i_ts_of_match[] = {
@@ -403,7 +401,7 @@ static struct platform_driver sun4i_ts_driver = {
.of_match_table = sun4i_ts_of_match,
},
.probe = sun4i_ts_probe,
- .remove = sun4i_ts_remove,
+ .remove_new = sun4i_ts_remove,
};
module_platform_driver(sun4i_ts_driver);
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index 9aa4e35fb4f5..34324f8512ac 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -491,7 +491,7 @@ err_free_mem:
return err;
}
-static int titsc_remove(struct platform_device *pdev)
+static void titsc_remove(struct platform_device *pdev)
{
struct titsc *ts_dev = platform_get_drvdata(pdev);
u32 steps;
@@ -508,7 +508,6 @@ static int titsc_remove(struct platform_device *pdev)
input_unregister_device(ts_dev->input);
kfree(ts_dev);
- return 0;
}
static int titsc_suspend(struct device *dev)
@@ -552,7 +551,7 @@ MODULE_DEVICE_TABLE(of, ti_tsc_dt_ids);
static struct platform_driver ti_tsc_driver = {
.probe = titsc_probe,
- .remove = titsc_remove,
+ .remove_new = titsc_remove,
.driver = {
.name = "TI-am335x-tsc",
.pm = pm_sleep_ptr(&titsc_pm_ops),
diff --git a/drivers/input/touchscreen/tsc2004.c b/drivers/input/touchscreen/tsc2004.c
index b5e904c5b7c4..89c5248f66f6 100644
--- a/drivers/input/touchscreen/tsc2004.c
+++ b/drivers/input/touchscreen/tsc2004.c
@@ -63,9 +63,10 @@ MODULE_DEVICE_TABLE(of, tsc2004_of_match);
static struct i2c_driver tsc2004_driver = {
.driver = {
- .name = "tsc2004",
- .of_match_table = of_match_ptr(tsc2004_of_match),
- .pm = pm_sleep_ptr(&tsc200x_pm_ops),
+ .name = "tsc2004",
+ .dev_groups = tsc200x_groups,
+ .of_match_table = of_match_ptr(tsc2004_of_match),
+ .pm = pm_sleep_ptr(&tsc200x_pm_ops),
},
.id_table = tsc2004_idtable,
.probe = tsc2004_probe,
diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c
index b6dfbcfc8c19..1b40ce0ca1b9 100644
--- a/drivers/input/touchscreen/tsc2005.c
+++ b/drivers/input/touchscreen/tsc2005.c
@@ -79,9 +79,10 @@ MODULE_DEVICE_TABLE(of, tsc2005_of_match);
static struct spi_driver tsc2005_driver = {
.driver = {
- .name = "tsc2005",
- .of_match_table = of_match_ptr(tsc2005_of_match),
- .pm = pm_sleep_ptr(&tsc200x_pm_ops),
+ .name = "tsc2005",
+ .dev_groups = tsc200x_groups,
+ .of_match_table = of_match_ptr(tsc2005_of_match),
+ .pm = pm_sleep_ptr(&tsc200x_pm_ops),
},
.probe = tsc2005_probe,
.remove = tsc2005_remove,
diff --git a/drivers/input/touchscreen/tsc200x-core.c b/drivers/input/touchscreen/tsc200x-core.c
index b799f26fcf8f..a4c0e9db9bb9 100644
--- a/drivers/input/touchscreen/tsc200x-core.c
+++ b/drivers/input/touchscreen/tsc200x-core.c
@@ -356,6 +356,12 @@ static const struct attribute_group tsc200x_attr_group = {
.attrs = tsc200x_attrs,
};
+const struct attribute_group *tsc200x_groups[] = {
+ &tsc200x_attr_group,
+ NULL
+};
+EXPORT_SYMBOL_GPL(tsc200x_groups);
+
static void tsc200x_esd_work(struct work_struct *work)
{
struct tsc200x *ts = container_of(work, struct tsc200x, esd_work.work);
@@ -553,25 +559,17 @@ int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id,
return error;
dev_set_drvdata(dev, ts);
- error = sysfs_create_group(&dev->kobj, &tsc200x_attr_group);
- if (error) {
- dev_err(dev,
- "Failed to create sysfs attributes, err: %d\n", error);
- goto disable_regulator;
- }
error = input_register_device(ts->idev);
if (error) {
dev_err(dev,
"Failed to register input device, err: %d\n", error);
- goto err_remove_sysfs;
+ goto disable_regulator;
}
irq_set_irq_wake(irq, 1);
return 0;
-err_remove_sysfs:
- sysfs_remove_group(&dev->kobj, &tsc200x_attr_group);
disable_regulator:
regulator_disable(ts->vio);
return error;
@@ -582,8 +580,6 @@ void tsc200x_remove(struct device *dev)
{
struct tsc200x *ts = dev_get_drvdata(dev);
- sysfs_remove_group(&dev->kobj, &tsc200x_attr_group);
-
regulator_disable(ts->vio);
}
EXPORT_SYMBOL_GPL(tsc200x_remove);
diff --git a/drivers/input/touchscreen/tsc200x-core.h b/drivers/input/touchscreen/tsc200x-core.h
index 4ded34425b21..37de91efd78e 100644
--- a/drivers/input/touchscreen/tsc200x-core.h
+++ b/drivers/input/touchscreen/tsc200x-core.h
@@ -70,6 +70,7 @@
extern const struct regmap_config tsc200x_regmap_config;
extern const struct dev_pm_ops tsc200x_pm_ops;
+extern const struct attribute_group *tsc200x_groups[];
int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id,
struct regmap *regmap,
diff --git a/drivers/input/touchscreen/wdt87xx_i2c.c b/drivers/input/touchscreen/wdt87xx_i2c.c
index cbc4750c53f9..128341a6696b 100644
--- a/drivers/input/touchscreen/wdt87xx_i2c.c
+++ b/drivers/input/touchscreen/wdt87xx_i2c.c
@@ -944,10 +944,7 @@ static struct attribute *wdt87xx_attrs[] = {
&dev_attr_update_fw.attr,
NULL
};
-
-static const struct attribute_group wdt87xx_attr_group = {
- .attrs = wdt87xx_attrs,
-};
+ATTRIBUTE_GROUPS(wdt87xx);
static void wdt87xx_report_contact(struct input_dev *input,
struct wdt87xx_sys_param *param,
@@ -1104,12 +1101,6 @@ static int wdt87xx_ts_probe(struct i2c_client *client)
return error;
}
- error = devm_device_add_group(&client->dev, &wdt87xx_attr_group);
- if (error) {
- dev_err(&client->dev, "create sysfs failed: %d\n", error);
- return error;
- }
-
return 0;
}
@@ -1172,8 +1163,9 @@ static struct i2c_driver wdt87xx_driver = {
.probe = wdt87xx_ts_probe,
.id_table = wdt87xx_dev_id,
.driver = {
- .name = WDT87XX_NAME,
- .pm = pm_sleep_ptr(&wdt87xx_pm_ops),
+ .name = WDT87XX_NAME,
+ .dev_groups = wdt87xx_groups,
+ .pm = pm_sleep_ptr(&wdt87xx_pm_ops),
.acpi_match_table = ACPI_PTR(wdt87xx_acpi_id),
},
};
diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c
index 319f57fb9af5..9cee26b63341 100644
--- a/drivers/input/touchscreen/wm831x-ts.c
+++ b/drivers/input/touchscreen/wm831x-ts.c
@@ -374,14 +374,12 @@ err_alloc:
return error;
}
-static int wm831x_ts_remove(struct platform_device *pdev)
+static void wm831x_ts_remove(struct platform_device *pdev)
{
struct wm831x_ts *wm831x_ts = platform_get_drvdata(pdev);
free_irq(wm831x_ts->pd_irq, wm831x_ts);
free_irq(wm831x_ts->data_irq, wm831x_ts);
-
- return 0;
}
static struct platform_driver wm831x_ts_driver = {
@@ -389,7 +387,7 @@ static struct platform_driver wm831x_ts_driver = {
.name = "wm831x-touch",
},
.probe = wm831x_ts_probe,
- .remove = wm831x_ts_remove,
+ .remove_new = wm831x_ts_remove,
};
module_platform_driver(wm831x_ts_driver);
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
index ac3b3dd59488..f01f6cc9b59f 100644
--- a/drivers/input/touchscreen/wm97xx-core.c
+++ b/drivers/input/touchscreen/wm97xx-core.c
@@ -756,11 +756,9 @@ batt_err:
return ret;
}
-static int wm97xx_mfd_remove(struct platform_device *pdev)
+static void wm97xx_mfd_remove(struct platform_device *pdev)
{
wm97xx_remove(&pdev->dev);
-
- return 0;
}
static int wm97xx_suspend(struct device *dev)
@@ -878,7 +876,7 @@ static struct platform_driver wm97xx_mfd_driver = {
.pm = pm_sleep_ptr(&wm97xx_pm_ops),
},
.probe = wm97xx_mfd_probe,
- .remove = wm97xx_mfd_remove,
+ .remove_new = wm97xx_mfd_remove,
};
static int __init wm97xx_init(void)
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/bcm-voter.c b/drivers/interconnect/qcom/bcm-voter.c
index 8f385f9c2dd3..d5f2a6b5376b 100644
--- a/drivers/interconnect/qcom/bcm-voter.c
+++ b/drivers/interconnect/qcom/bcm-voter.c
@@ -83,6 +83,11 @@ static void bcm_aggregate(struct qcom_icc_bcm *bcm)
temp = agg_peak[bucket] * bcm->vote_scale;
bcm->vote_y[bucket] = bcm_div(temp, bcm->aux_data.unit);
+
+ if (bcm->enable_mask && (bcm->vote_x[bucket] || bcm->vote_y[bucket])) {
+ bcm->vote_x[bucket] = 0;
+ bcm->vote_y[bucket] = bcm->enable_mask;
+ }
}
if (bcm->keepalive && bcm->vote_x[QCOM_ICC_BUCKET_AMC] == 0 &&
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/icc-rpmh.h b/drivers/interconnect/qcom/icc-rpmh.h
index 04391c1ba465..7843d8864d6b 100644
--- a/drivers/interconnect/qcom/icc-rpmh.h
+++ b/drivers/interconnect/qcom/icc-rpmh.h
@@ -81,6 +81,7 @@ struct qcom_icc_node {
* @vote_x: aggregated threshold values, represents sum_bw when @type is bw bcm
* @vote_y: aggregated threshold values, represents peak_bw when @type is bw bcm
* @vote_scale: scaling factor for vote_x and vote_y
+ * @enable_mask: optional mask to send as vote instead of vote_x/vote_y
* @dirty: flag used to indicate whether the bcm needs to be committed
* @keepalive: flag used to indicate whether a keepalive is required
* @aux_data: auxiliary data used when calculating threshold values and
@@ -97,6 +98,7 @@ struct qcom_icc_bcm {
u64 vote_x[QCOM_ICC_NUM_BUCKETS];
u64 vote_y[QCOM_ICC_NUM_BUCKETS];
u64 vote_scale;
+ u32 enable_mask;
bool dirty;
bool keepalive;
struct bcm_db aux_data;
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/sa8775p.c b/drivers/interconnect/qcom/sa8775p.c
index da21cc31a580..f56538669de0 100644
--- a/drivers/interconnect/qcom/sa8775p.c
+++ b/drivers/interconnect/qcom/sa8775p.c
@@ -1873,6 +1873,7 @@ static struct qcom_icc_node srvc_snoc = {
static struct qcom_icc_bcm bcm_acv = {
.name = "ACV",
+ .enable_mask = 0x8,
.num_nodes = 1,
.nodes = { &ebi },
};
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/interconnect/qcom/sm8450.c b/drivers/interconnect/qcom/sm8450.c
index 2d7a8e7b85ec..e64c214b4020 100644
--- a/drivers/interconnect/qcom/sm8450.c
+++ b/drivers/interconnect/qcom/sm8450.c
@@ -1337,6 +1337,7 @@ static struct qcom_icc_node qns_mem_noc_sf_disp = {
static struct qcom_icc_bcm bcm_acv = {
.name = "ACV",
+ .enable_mask = 0x8,
.num_nodes = 1,
.nodes = { &ebi },
};
@@ -1349,6 +1350,7 @@ static struct qcom_icc_bcm bcm_ce0 = {
static struct qcom_icc_bcm bcm_cn0 = {
.name = "CN0",
+ .enable_mask = 0x1,
.keepalive = true,
.num_nodes = 55,
.nodes = { &qnm_gemnoc_cnoc, &qnm_gemnoc_pcie,
@@ -1383,6 +1385,7 @@ static struct qcom_icc_bcm bcm_cn0 = {
static struct qcom_icc_bcm bcm_co0 = {
.name = "CO0",
+ .enable_mask = 0x1,
.num_nodes = 2,
.nodes = { &qxm_nsp, &qns_nsp_gemnoc },
};
@@ -1403,6 +1406,7 @@ static struct qcom_icc_bcm bcm_mm0 = {
static struct qcom_icc_bcm bcm_mm1 = {
.name = "MM1",
+ .enable_mask = 0x1,
.num_nodes = 12,
.nodes = { &qnm_camnoc_hf, &qnm_camnoc_icp,
&qnm_camnoc_sf, &qnm_mdp,
@@ -1445,6 +1449,7 @@ static struct qcom_icc_bcm bcm_sh0 = {
static struct qcom_icc_bcm bcm_sh1 = {
.name = "SH1",
+ .enable_mask = 0x1,
.num_nodes = 7,
.nodes = { &alm_gpu_tcu, &alm_sys_tcu,
&qnm_nsp_gemnoc, &qnm_pcie,
@@ -1461,6 +1466,7 @@ static struct qcom_icc_bcm bcm_sn0 = {
static struct qcom_icc_bcm bcm_sn1 = {
.name = "SN1",
+ .enable_mask = 0x1,
.num_nodes = 4,
.nodes = { &qhm_gic, &qxm_pimem,
&xm_gic, &qns_gemnoc_gc },
@@ -1492,6 +1498,7 @@ static struct qcom_icc_bcm bcm_sn7 = {
static struct qcom_icc_bcm bcm_acv_disp = {
.name = "ACV",
+ .enable_mask = 0x1,
.num_nodes = 1,
.nodes = { &ebi_disp },
};
@@ -1510,6 +1517,7 @@ static struct qcom_icc_bcm bcm_mm0_disp = {
static struct qcom_icc_bcm bcm_mm1_disp = {
.name = "MM1",
+ .enable_mask = 0x1,
.num_nodes = 3,
.nodes = { &qnm_mdp_disp, &qnm_rot_disp,
&qns_mem_noc_sf_disp },
@@ -1523,6 +1531,7 @@ static struct qcom_icc_bcm bcm_sh0_disp = {
static struct qcom_icc_bcm bcm_sh1_disp = {
.name = "SH1",
+ .enable_mask = 0x1,
.num_nodes = 1,
.nodes = { &qnm_pcie_disp },
};
diff --git a/drivers/interconnect/qcom/sm8550.c b/drivers/interconnect/qcom/sm8550.c
index d823ba988ef6..0864ed285375 100644
--- a/drivers/interconnect/qcom/sm8550.c
+++ b/drivers/interconnect/qcom/sm8550.c
@@ -1473,6 +1473,7 @@ static struct qcom_icc_node qns_mem_noc_sf_cam_ife_2 = {
static struct qcom_icc_bcm bcm_acv = {
.name = "ACV",
+ .enable_mask = 0x8,
.num_nodes = 1,
.nodes = { &ebi },
};
@@ -1485,6 +1486,7 @@ static struct qcom_icc_bcm bcm_ce0 = {
static struct qcom_icc_bcm bcm_cn0 = {
.name = "CN0",
+ .enable_mask = 0x1,
.keepalive = true,
.num_nodes = 54,
.nodes = { &qsm_cfg, &qhs_ahb2phy0,
@@ -1524,6 +1526,7 @@ static struct qcom_icc_bcm bcm_cn1 = {
static struct qcom_icc_bcm bcm_co0 = {
.name = "CO0",
+ .enable_mask = 0x1,
.num_nodes = 2,
.nodes = { &qxm_nsp, &qns_nsp_gemnoc },
};
@@ -1549,6 +1552,7 @@ static struct qcom_icc_bcm bcm_mm0 = {
static struct qcom_icc_bcm bcm_mm1 = {
.name = "MM1",
+ .enable_mask = 0x1,
.num_nodes = 8,
.nodes = { &qnm_camnoc_hf, &qnm_camnoc_icp,
&qnm_camnoc_sf, &qnm_vapss_hcp,
@@ -1589,6 +1593,7 @@ static struct qcom_icc_bcm bcm_sh0 = {
static struct qcom_icc_bcm bcm_sh1 = {
.name = "SH1",
+ .enable_mask = 0x1,
.num_nodes = 13,
.nodes = { &alm_gpu_tcu, &alm_sys_tcu,
&chm_apps, &qnm_gpu,
@@ -1608,6 +1613,7 @@ static struct qcom_icc_bcm bcm_sn0 = {
static struct qcom_icc_bcm bcm_sn1 = {
.name = "SN1",
+ .enable_mask = 0x1,
.num_nodes = 3,
.nodes = { &qhm_gic, &xm_gic,
&qns_gemnoc_gc },
@@ -1633,6 +1639,7 @@ static struct qcom_icc_bcm bcm_sn7 = {
static struct qcom_icc_bcm bcm_acv_disp = {
.name = "ACV",
+ .enable_mask = 0x1,
.num_nodes = 1,
.nodes = { &ebi_disp },
};
@@ -1657,12 +1664,14 @@ static struct qcom_icc_bcm bcm_sh0_disp = {
static struct qcom_icc_bcm bcm_sh1_disp = {
.name = "SH1",
+ .enable_mask = 0x1,
.num_nodes = 2,
.nodes = { &qnm_mnoc_hf_disp, &qnm_pcie_disp },
};
static struct qcom_icc_bcm bcm_acv_cam_ife_0 = {
.name = "ACV",
+ .enable_mask = 0x0,
.num_nodes = 1,
.nodes = { &ebi_cam_ife_0 },
};
@@ -1681,6 +1690,7 @@ static struct qcom_icc_bcm bcm_mm0_cam_ife_0 = {
static struct qcom_icc_bcm bcm_mm1_cam_ife_0 = {
.name = "MM1",
+ .enable_mask = 0x1,
.num_nodes = 4,
.nodes = { &qnm_camnoc_hf_cam_ife_0, &qnm_camnoc_icp_cam_ife_0,
&qnm_camnoc_sf_cam_ife_0, &qns_mem_noc_sf_cam_ife_0 },
@@ -1694,6 +1704,7 @@ static struct qcom_icc_bcm bcm_sh0_cam_ife_0 = {
static struct qcom_icc_bcm bcm_sh1_cam_ife_0 = {
.name = "SH1",
+ .enable_mask = 0x1,
.num_nodes = 3,
.nodes = { &qnm_mnoc_hf_cam_ife_0, &qnm_mnoc_sf_cam_ife_0,
&qnm_pcie_cam_ife_0 },
@@ -1701,6 +1712,7 @@ static struct qcom_icc_bcm bcm_sh1_cam_ife_0 = {
static struct qcom_icc_bcm bcm_acv_cam_ife_1 = {
.name = "ACV",
+ .enable_mask = 0x0,
.num_nodes = 1,
.nodes = { &ebi_cam_ife_1 },
};
@@ -1719,6 +1731,7 @@ static struct qcom_icc_bcm bcm_mm0_cam_ife_1 = {
static struct qcom_icc_bcm bcm_mm1_cam_ife_1 = {
.name = "MM1",
+ .enable_mask = 0x1,
.num_nodes = 4,
.nodes = { &qnm_camnoc_hf_cam_ife_1, &qnm_camnoc_icp_cam_ife_1,
&qnm_camnoc_sf_cam_ife_1, &qns_mem_noc_sf_cam_ife_1 },
@@ -1732,6 +1745,7 @@ static struct qcom_icc_bcm bcm_sh0_cam_ife_1 = {
static struct qcom_icc_bcm bcm_sh1_cam_ife_1 = {
.name = "SH1",
+ .enable_mask = 0x1,
.num_nodes = 3,
.nodes = { &qnm_mnoc_hf_cam_ife_1, &qnm_mnoc_sf_cam_ife_1,
&qnm_pcie_cam_ife_1 },
@@ -1739,6 +1753,7 @@ static struct qcom_icc_bcm bcm_sh1_cam_ife_1 = {
static struct qcom_icc_bcm bcm_acv_cam_ife_2 = {
.name = "ACV",
+ .enable_mask = 0x0,
.num_nodes = 1,
.nodes = { &ebi_cam_ife_2 },
};
@@ -1757,6 +1772,7 @@ static struct qcom_icc_bcm bcm_mm0_cam_ife_2 = {
static struct qcom_icc_bcm bcm_mm1_cam_ife_2 = {
.name = "MM1",
+ .enable_mask = 0x1,
.num_nodes = 4,
.nodes = { &qnm_camnoc_hf_cam_ife_2, &qnm_camnoc_icp_cam_ife_2,
&qnm_camnoc_sf_cam_ife_2, &qns_mem_noc_sf_cam_ife_2 },
@@ -1770,6 +1786,7 @@ static struct qcom_icc_bcm bcm_sh0_cam_ife_2 = {
static struct qcom_icc_bcm bcm_sh1_cam_ife_2 = {
.name = "SH1",
+ .enable_mask = 0x1,
.num_nodes = 3,
.nodes = { &qnm_mnoc_hf_cam_ife_2, &qnm_mnoc_sf_cam_ife_2,
&qnm_pcie_cam_ife_2 },
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 4d800601e8ec..2b12b583ef4b 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -152,6 +152,7 @@ config IOMMU_DMA
select IOMMU_IOVA
select IRQ_MSI_IOMMU
select NEED_SG_DMA_LENGTH
+ select NEED_SG_DMA_FLAGS if SWIOTLB
# Shared Virtual Addressing
config IOMMU_SVA
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 2ddbda3a4374..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)
{
@@ -986,8 +990,13 @@ union irte_ga_hi {
};
struct irte_ga {
- union irte_ga_lo lo;
- union irte_ga_hi hi;
+ union {
+ struct {
+ union irte_ga_lo lo;
+ union irte_ga_hi hi;
+ };
+ u128 irte;
+ };
};
struct irq_2_irte {
@@ -1001,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 e8a2e5984acb..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,12 +3052,12 @@ 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)
{
- bool ret;
struct irq_remap_table *table;
- unsigned long flags;
struct irte_ga *entry;
+ unsigned long flags;
+ u128 old;
table = get_irq_table(iommu, devid);
if (!table)
@@ -3037,24 +3068,18 @@ static int modify_irte_ga(struct amd_iommu *iommu, u16 devid, int index,
entry = (struct irte_ga *)table->table;
entry = &entry[index];
- ret = cmpxchg_double(&entry->lo.val, &entry->hi.val,
- entry->lo.val, entry->hi.val,
- irte->lo.val, irte->hi.val);
/*
* We use cmpxchg16 to atomically update the 128-bit IRTE,
* and it cannot be updated by the hardware or other processors
* behind us, so the return value of cmpxchg16 should be the
* same as the old value.
*/
- WARN_ON(!ret);
-
- if (data)
- data->ref = entry;
+ old = entry->irte;
+ WARN_ON(!try_cmpxchg128(&entry->irte, &old, irte->irte));
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;
}
@@ -3073,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;
}
@@ -3092,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,
@@ -3139,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)
@@ -3155,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,
@@ -3179,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);
}
}
@@ -3529,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);
@@ -3559,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);
@@ -3721,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)
- return -ENODEV;
-
- table = get_irq_table(iommu, devid);
- if (!table)
+ if (!ir_data->iommu)
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 7a9f0b0bddbd..e57724163835 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -520,9 +520,38 @@ static bool dev_is_untrusted(struct device *dev)
return dev_is_pci(dev) && to_pci_dev(dev)->untrusted;
}
-static bool dev_use_swiotlb(struct device *dev)
+static bool dev_use_swiotlb(struct device *dev, size_t size,
+ enum dma_data_direction dir)
{
- return IS_ENABLED(CONFIG_SWIOTLB) && dev_is_untrusted(dev);
+ return IS_ENABLED(CONFIG_SWIOTLB) &&
+ (dev_is_untrusted(dev) ||
+ dma_kmalloc_needs_bounce(dev, size, dir));
+}
+
+static bool dev_use_sg_swiotlb(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir)
+{
+ struct scatterlist *s;
+ int i;
+
+ if (!IS_ENABLED(CONFIG_SWIOTLB))
+ return false;
+
+ if (dev_is_untrusted(dev))
+ return true;
+
+ /*
+ * If kmalloc() buffers are not DMA-safe for this device and
+ * direction, check the individual lengths in the sg list. If any
+ * element is deemed unsafe, use the swiotlb for bouncing.
+ */
+ if (!dma_kmalloc_safe(dev, dir)) {
+ for_each_sg(sg, s, nents, i)
+ if (!dma_kmalloc_size_aligned(s->length))
+ return true;
+ }
+
+ return false;
}
/**
@@ -586,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);
@@ -922,7 +952,7 @@ static void iommu_dma_sync_single_for_cpu(struct device *dev,
{
phys_addr_t phys;
- if (dev_is_dma_coherent(dev) && !dev_use_swiotlb(dev))
+ if (dev_is_dma_coherent(dev) && !dev_use_swiotlb(dev, size, dir))
return;
phys = iommu_iova_to_phys(iommu_get_dma_domain(dev), dma_handle);
@@ -938,7 +968,7 @@ static void iommu_dma_sync_single_for_device(struct device *dev,
{
phys_addr_t phys;
- if (dev_is_dma_coherent(dev) && !dev_use_swiotlb(dev))
+ if (dev_is_dma_coherent(dev) && !dev_use_swiotlb(dev, size, dir))
return;
phys = iommu_iova_to_phys(iommu_get_dma_domain(dev), dma_handle);
@@ -956,7 +986,7 @@ static void iommu_dma_sync_sg_for_cpu(struct device *dev,
struct scatterlist *sg;
int i;
- if (dev_use_swiotlb(dev))
+ if (sg_dma_is_swiotlb(sgl))
for_each_sg(sgl, sg, nelems, i)
iommu_dma_sync_single_for_cpu(dev, sg_dma_address(sg),
sg->length, dir);
@@ -972,7 +1002,7 @@ static void iommu_dma_sync_sg_for_device(struct device *dev,
struct scatterlist *sg;
int i;
- if (dev_use_swiotlb(dev))
+ if (sg_dma_is_swiotlb(sgl))
for_each_sg(sgl, sg, nelems, i)
iommu_dma_sync_single_for_device(dev,
sg_dma_address(sg),
@@ -998,7 +1028,8 @@ static dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
* If both the physical buffer start address and size are
* page aligned, we don't need to use a bounce page.
*/
- if (dev_use_swiotlb(dev) && iova_offset(iovad, phys | size)) {
+ if (dev_use_swiotlb(dev, size, dir) &&
+ iova_offset(iovad, phys | size)) {
void *padding_start;
size_t padding_size, aligned_size;
@@ -1080,7 +1111,7 @@ static int __finalise_sg(struct device *dev, struct scatterlist *sg, int nents,
sg_dma_address(s) = DMA_MAPPING_ERROR;
sg_dma_len(s) = 0;
- if (sg_is_dma_bus_address(s)) {
+ if (sg_dma_is_bus_address(s)) {
if (i > 0)
cur = sg_next(cur);
@@ -1136,7 +1167,7 @@ static void __invalidate_sg(struct scatterlist *sg, int nents)
int i;
for_each_sg(sg, s, nents, i) {
- if (sg_is_dma_bus_address(s)) {
+ if (sg_dma_is_bus_address(s)) {
sg_dma_unmark_bus_address(s);
} else {
if (sg_dma_address(s) != DMA_MAPPING_ERROR)
@@ -1166,6 +1197,8 @@ static int iommu_dma_map_sg_swiotlb(struct device *dev, struct scatterlist *sg,
struct scatterlist *s;
int i;
+ sg_dma_mark_swiotlb(sg);
+
for_each_sg(sg, s, nents, i) {
sg_dma_address(s) = iommu_dma_map_page(dev, sg_page(s),
s->offset, s->length, dir, attrs);
@@ -1210,7 +1243,7 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
goto out;
}
- if (dev_use_swiotlb(dev))
+ if (dev_use_sg_swiotlb(dev, sg, nents, dir))
return iommu_dma_map_sg_swiotlb(dev, sg, nents, dir, attrs);
if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
@@ -1315,7 +1348,7 @@ static void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
struct scatterlist *tmp;
int i;
- if (dev_use_swiotlb(dev)) {
+ if (sg_dma_is_swiotlb(sg)) {
iommu_dma_unmap_sg_swiotlb(dev, sg, nents, dir, attrs);
return;
}
@@ -1329,7 +1362,7 @@ static void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
* just have to be determined.
*/
for_each_sg(sg, tmp, nents, i) {
- if (sg_is_dma_bus_address(tmp)) {
+ if (sg_dma_is_bus_address(tmp)) {
sg_dma_unmark_bus_address(tmp);
continue;
}
@@ -1343,7 +1376,7 @@ static void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
nents -= i;
for_each_sg(tmp, tmp, nents, i) {
- if (sg_is_dma_bus_address(tmp)) {
+ if (sg_dma_is_bus_address(tmp)) {
sg_dma_unmark_bus_address(tmp);
continue;
}
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/intel/irq_remapping.c b/drivers/iommu/intel/irq_remapping.c
index a1b987335b31..08f56326e2f8 100644
--- a/drivers/iommu/intel/irq_remapping.c
+++ b/drivers/iommu/intel/irq_remapping.c
@@ -175,18 +175,14 @@ static int modify_irte(struct irq_2_iommu *irq_iommu,
irte = &iommu->ir_table->base[index];
if ((irte->pst == 1) || (irte_modified->pst == 1)) {
- bool ret;
-
- ret = cmpxchg_double(&irte->low, &irte->high,
- irte->low, irte->high,
- irte_modified->low, irte_modified->high);
/*
* We use cmpxchg16 to atomically update the 128-bit IRTE,
* and it cannot be updated by the hardware or other processors
* behind us, so the return value of cmpxchg16 should be the
* same as the old value.
*/
- WARN_ON(!ret);
+ u128 old = irte->irte;
+ WARN_ON(!try_cmpxchg128(&irte->irte, &old, irte_modified->irte));
} else {
WRITE_ONCE(irte->low, irte_modified->low);
WRITE_ONCE(irte->high, irte_modified->high);
diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c
index 9821bc44f5ac..05c0fb2acbc4 100644
--- a/drivers/iommu/iommu-sva.c
+++ b/drivers/iommu/iommu-sva.c
@@ -34,8 +34,9 @@ static int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t ma
}
ret = ida_alloc_range(&iommu_global_pasid_ida, min, max, GFP_KERNEL);
- if (ret < min)
+ if (ret < 0)
goto out;
+
mm->pasid = ret;
ret = 0;
out:
@@ -175,7 +176,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 f1dcfa3f1a1b..caaf563d38ae 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);
+
+ /* 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;
- type = iommu_get_def_domain_type(dev) ? : iommu_def_domain_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;
- return iommu_group_alloc_default_domain(dev->bus, group, type);
+ 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;
-
- memset(&gtype, 0, sizeof(gtype));
+ int best_type = target_type;
+ struct group_device *gdev;
+ struct device *last_dev;
- /* 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)
@@ -2567,7 +2540,7 @@ ssize_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
len = 0;
}
- if (sg_is_dma_bus_address(sg))
+ if (sg_dma_is_bus_address(sg))
goto next;
if (len) {
@@ -2846,78 +2819,113 @@ 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;
+ if (group->default_domain == dom)
+ return 0;
- ret = __iommu_attach_group(group->default_domain, group);
- if (ret)
- goto free_new_domain;
+ /*
+ * 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.");
+ }
+ }
- iommu_domain_free(prev_dom);
+ /* 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_old;
+ } else {
+ ret = __iommu_group_set_domain(group, dom);
+ if (ret)
+ goto err_restore_def_domain;
+ }
- return 0;
+ /*
+ * 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_domain;
+ }
+ }
-free_new_domain:
- iommu_domain_free(group->default_domain);
-restore_old_domain:
- group->default_domain = prev_dom;
- group->domain = prev_dom;
+out_free_old:
+ if (old_dom)
+ iommu_domain_free(old_dom);
+ return ret;
+err_restore_domain:
+ if (old_dom)
+ __iommu_group_set_domain_internal(
+ group, old_dom, IOMMU_SET_DOMAIN_MUST_SUCCEED);
+err_restore_def_domain:
+ if (old_dom) {
+ iommu_domain_free(dom);
+ group->default_domain = old_dom;
+ }
return ret;
}
@@ -2933,8 +2941,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 +2966,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 +2993,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 +3192,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 +3260,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 +3275,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..ed2937a4e196 100644
--- a/drivers/iommu/iommufd/device.c
+++ b/drivers/iommu/iommufd/device.c
@@ -109,10 +109,7 @@ EXPORT_SYMBOL_NS_GPL(iommufd_device_bind, IOMMUFD);
*/
void iommufd_device_unbind(struct iommufd_device *idev)
{
- bool was_destroyed;
-
- was_destroyed = iommufd_object_destroy_user(idev->ictx, &idev->obj);
- WARN_ON(!was_destroyed);
+ iommufd_object_destroy_user(idev->ictx, &idev->obj);
}
EXPORT_SYMBOL_NS_GPL(iommufd_device_unbind, IOMMUFD);
@@ -382,7 +379,7 @@ void iommufd_device_detach(struct iommufd_device *idev)
mutex_unlock(&hwpt->devices_lock);
if (hwpt->auto_domain)
- iommufd_object_destroy_user(idev->ictx, &hwpt->obj);
+ iommufd_object_deref_user(idev->ictx, &hwpt->obj);
else
refcount_dec(&hwpt->obj.users);
@@ -456,10 +453,7 @@ EXPORT_SYMBOL_NS_GPL(iommufd_access_create, IOMMUFD);
*/
void iommufd_access_destroy(struct iommufd_access *access)
{
- bool was_destroyed;
-
- was_destroyed = iommufd_object_destroy_user(access->ictx, &access->obj);
- WARN_ON(!was_destroyed);
+ iommufd_object_destroy_user(access->ictx, &access->obj);
}
EXPORT_SYMBOL_NS_GPL(iommufd_access_destroy, IOMMUFD);
@@ -553,8 +547,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/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h
index b38e67d1988b..f9790983699c 100644
--- a/drivers/iommu/iommufd/iommufd_private.h
+++ b/drivers/iommu/iommufd/iommufd_private.h
@@ -176,8 +176,19 @@ void iommufd_object_abort_and_destroy(struct iommufd_ctx *ictx,
struct iommufd_object *obj);
void iommufd_object_finalize(struct iommufd_ctx *ictx,
struct iommufd_object *obj);
-bool iommufd_object_destroy_user(struct iommufd_ctx *ictx,
- struct iommufd_object *obj);
+void __iommufd_object_destroy_user(struct iommufd_ctx *ictx,
+ struct iommufd_object *obj, bool allow_fail);
+static inline void iommufd_object_destroy_user(struct iommufd_ctx *ictx,
+ struct iommufd_object *obj)
+{
+ __iommufd_object_destroy_user(ictx, obj, false);
+}
+static inline void iommufd_object_deref_user(struct iommufd_ctx *ictx,
+ struct iommufd_object *obj)
+{
+ __iommufd_object_destroy_user(ictx, obj, true);
+}
+
struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
size_t size,
enum iommufd_object_type type);
diff --git a/drivers/iommu/iommufd/main.c b/drivers/iommu/iommufd/main.c
index 3fbe636c3d8a..4cf5f73f2708 100644
--- a/drivers/iommu/iommufd/main.c
+++ b/drivers/iommu/iommufd/main.c
@@ -117,13 +117,55 @@ struct iommufd_object *iommufd_get_object(struct iommufd_ctx *ictx, u32 id,
}
/*
+ * Remove the given object id from the xarray if the only reference to the
+ * object is held by the xarray. The caller must call ops destroy().
+ */
+static struct iommufd_object *iommufd_object_remove(struct iommufd_ctx *ictx,
+ u32 id, bool extra_put)
+{
+ struct iommufd_object *obj;
+ XA_STATE(xas, &ictx->objects, id);
+
+ xa_lock(&ictx->objects);
+ obj = xas_load(&xas);
+ if (xa_is_zero(obj) || !obj) {
+ obj = ERR_PTR(-ENOENT);
+ goto out_xa;
+ }
+
+ /*
+ * If the caller is holding a ref on obj we put it here under the
+ * spinlock.
+ */
+ if (extra_put)
+ refcount_dec(&obj->users);
+
+ if (!refcount_dec_if_one(&obj->users)) {
+ obj = ERR_PTR(-EBUSY);
+ goto out_xa;
+ }
+
+ xas_store(&xas, NULL);
+ if (ictx->vfio_ioas == container_of(obj, struct iommufd_ioas, obj))
+ ictx->vfio_ioas = NULL;
+
+out_xa:
+ xa_unlock(&ictx->objects);
+
+ /* The returned object reference count is zero */
+ return obj;
+}
+
+/*
* The caller holds a users refcount and wants to destroy the object. Returns
* true if the object was destroyed. In all cases the caller no longer has a
* reference on obj.
*/
-bool iommufd_object_destroy_user(struct iommufd_ctx *ictx,
- struct iommufd_object *obj)
+void __iommufd_object_destroy_user(struct iommufd_ctx *ictx,
+ struct iommufd_object *obj, bool allow_fail)
{
+ struct iommufd_object *ret;
+
/*
* The purpose of the destroy_rwsem is to ensure deterministic
* destruction of objects used by external drivers and destroyed by this
@@ -131,22 +173,22 @@ bool iommufd_object_destroy_user(struct iommufd_ctx *ictx,
* side of this, such as during ioctl execution.
*/
down_write(&obj->destroy_rwsem);
- xa_lock(&ictx->objects);
- refcount_dec(&obj->users);
- if (!refcount_dec_if_one(&obj->users)) {
- xa_unlock(&ictx->objects);
- up_write(&obj->destroy_rwsem);
- return false;
- }
- __xa_erase(&ictx->objects, obj->id);
- if (ictx->vfio_ioas && &ictx->vfio_ioas->obj == obj)
- ictx->vfio_ioas = NULL;
- xa_unlock(&ictx->objects);
+ ret = iommufd_object_remove(ictx, obj->id, true);
up_write(&obj->destroy_rwsem);
+ if (allow_fail && IS_ERR(ret))
+ return;
+
+ /*
+ * If there is a bug and we couldn't destroy the object then we did put
+ * back the caller's refcount and will eventually try to free it again
+ * during close.
+ */
+ if (WARN_ON(IS_ERR(ret)))
+ return;
+
iommufd_object_ops[obj->type].destroy(obj);
kfree(obj);
- return true;
}
static int iommufd_destroy(struct iommufd_ucmd *ucmd)
@@ -154,13 +196,11 @@ static int iommufd_destroy(struct iommufd_ucmd *ucmd)
struct iommu_destroy *cmd = ucmd->cmd;
struct iommufd_object *obj;
- obj = iommufd_get_object(ucmd->ictx, cmd->id, IOMMUFD_OBJ_ANY);
+ obj = iommufd_object_remove(ucmd->ictx, cmd->id, false);
if (IS_ERR(obj))
return PTR_ERR(obj);
- iommufd_ref_to_users(obj);
- /* See iommufd_ref_to_users() */
- if (!iommufd_object_destroy_user(ucmd->ictx, obj))
- return -EBUSY;
+ iommufd_object_ops[obj->type].destroy(obj);
+ kfree(obj);
return 0;
}
diff --git a/drivers/iommu/iommufd/pages.c b/drivers/iommu/iommufd/pages.c
index 3c47846cc5ef..8d9aa297c117 100644
--- a/drivers/iommu/iommufd/pages.c
+++ b/drivers/iommu/iommufd/pages.c
@@ -297,7 +297,7 @@ static void batch_clear_carry(struct pfn_batch *batch, unsigned int keep_pfns)
batch->pfns[0] = batch->pfns[batch->end - 1] +
(batch->npfns[batch->end - 1] - keep_pfns);
batch->npfns[0] = keep_pfns;
- batch->end = 0;
+ batch->end = 1;
}
static void batch_skip_carry(struct pfn_batch *batch, unsigned int skip_pfns)
@@ -786,7 +786,7 @@ static int pfn_reader_user_pin(struct pfn_reader_user *user,
user->locked = 1;
}
rc = pin_user_pages_remote(pages->source_mm, uptr, npages,
- user->gup_flags, user->upages, NULL,
+ user->gup_flags, user->upages,
&user->locked);
}
if (rc <= 0) {
@@ -1799,7 +1799,7 @@ static int iopt_pages_rw_page(struct iopt_pages *pages, unsigned long index,
rc = pin_user_pages_remote(
pages->source_mm, (uintptr_t)(pages->uptr + index * PAGE_SIZE),
1, (flags & IOMMUFD_ACCESS_RW_WRITE) ? FOLL_WRITE : 0, &page,
- NULL, NULL);
+ NULL);
mmap_read_unlock(pages->source_mm);
if (rc != 1) {
if (WARN_ON(rc >= 0))
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-bcm6345-l1.c b/drivers/irqchip/irq-bcm6345-l1.c
index fa113cb2529a..6341c0167c4a 100644
--- a/drivers/irqchip/irq-bcm6345-l1.c
+++ b/drivers/irqchip/irq-bcm6345-l1.c
@@ -82,6 +82,7 @@ struct bcm6345_l1_chip {
};
struct bcm6345_l1_cpu {
+ struct bcm6345_l1_chip *intc;
void __iomem *map_base;
unsigned int parent_irq;
u32 enable_cache[];
@@ -115,17 +116,11 @@ static inline unsigned int cpu_for_irq(struct bcm6345_l1_chip *intc,
static void bcm6345_l1_irq_handle(struct irq_desc *desc)
{
- struct bcm6345_l1_chip *intc = irq_desc_get_handler_data(desc);
- struct bcm6345_l1_cpu *cpu;
+ struct bcm6345_l1_cpu *cpu = irq_desc_get_handler_data(desc);
+ struct bcm6345_l1_chip *intc = cpu->intc;
struct irq_chip *chip = irq_desc_get_chip(desc);
unsigned int idx;
-#ifdef CONFIG_SMP
- cpu = intc->cpus[cpu_logical_map(smp_processor_id())];
-#else
- cpu = intc->cpus[0];
-#endif
-
chained_irq_enter(chip, desc);
for (idx = 0; idx < intc->n_words; idx++) {
@@ -253,6 +248,7 @@ static int __init bcm6345_l1_init_one(struct device_node *dn,
if (!cpu)
return -ENOMEM;
+ cpu->intc = intc;
cpu->map_base = ioremap(res.start, sz);
if (!cpu->map_base)
return -ENOMEM;
@@ -271,7 +267,7 @@ static int __init bcm6345_l1_init_one(struct device_node *dn,
return -EINVAL;
}
irq_set_chained_handler_and_data(cpu->parent_irq,
- bcm6345_l1_irq_handle, intc);
+ bcm6345_l1_irq_handle, cpu);
return 0;
}
diff --git a/drivers/irqchip/irq-clps711x.c b/drivers/irqchip/irq-clps711x.c
index 77ebe7e47e0e..e731e0784f7e 100644
--- a/drivers/irqchip/irq-clps711x.c
+++ b/drivers/irqchip/irq-clps711x.c
@@ -212,12 +212,6 @@ out_kfree:
return err;
}
-void __init clps711x_intc_init(phys_addr_t base, resource_size_t size)
-{
- BUG_ON(_clps711x_intc_init(NULL, base, size));
-}
-
-#ifdef CONFIG_IRQCHIP
static int __init clps711x_intc_init_dt(struct device_node *np,
struct device_node *parent)
{
@@ -231,4 +225,3 @@ static int __init clps711x_intc_init_dt(struct device_node *np,
return _clps711x_intc_init(np, res.start, resource_size(&res));
}
IRQCHIP_DECLARE(clps711x, "cirrus,ep7209-intc", clps711x_intc_init_dt);
-#endif
diff --git a/drivers/irqchip/irq-ftintc010.c b/drivers/irqchip/irq-ftintc010.c
index 46a3aa60e50e..359efc1d1be7 100644
--- a/drivers/irqchip/irq-ftintc010.c
+++ b/drivers/irqchip/irq-ftintc010.c
@@ -125,7 +125,7 @@ static struct irq_chip ft010_irq_chip = {
/* Local static for the IRQ entry call */
static struct ft010_irq_data firq;
-asmlinkage void __exception_irq_entry ft010_irqchip_handle_irq(struct pt_regs *regs)
+static asmlinkage void __exception_irq_entry ft010_irqchip_handle_irq(struct pt_regs *regs)
{
struct ft010_irq_data *f = &firq;
int irq;
@@ -162,7 +162,7 @@ static const struct irq_domain_ops ft010_irqdomain_ops = {
.xlate = irq_domain_xlate_onetwocell,
};
-int __init ft010_of_init_irq(struct device_node *node,
+static int __init ft010_of_init_irq(struct device_node *node,
struct device_node *parent)
{
struct ft010_irq_data *f = &firq;
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 0ec2b1e1df75..e0c2b10d154d 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -273,13 +273,23 @@ static void vpe_to_cpuid_unlock(struct its_vpe *vpe, unsigned long flags)
raw_spin_unlock_irqrestore(&vpe->vpe_lock, flags);
}
+static struct irq_chip its_vpe_irq_chip;
+
static int irq_to_cpuid_lock(struct irq_data *d, unsigned long *flags)
{
- struct its_vlpi_map *map = get_vlpi_map(d);
+ struct its_vpe *vpe = NULL;
int cpu;
- if (map) {
- cpu = vpe_to_cpuid_lock(map->vpe, flags);
+ if (d->chip == &its_vpe_irq_chip) {
+ vpe = irq_data_get_irq_chip_data(d);
+ } else {
+ struct its_vlpi_map *map = get_vlpi_map(d);
+ if (map)
+ vpe = map->vpe;
+ }
+
+ if (vpe) {
+ cpu = vpe_to_cpuid_lock(vpe, flags);
} else {
/* Physical LPIs are already locked via the irq_desc lock */
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
@@ -293,10 +303,18 @@ static int irq_to_cpuid_lock(struct irq_data *d, unsigned long *flags)
static void irq_to_cpuid_unlock(struct irq_data *d, unsigned long flags)
{
- struct its_vlpi_map *map = get_vlpi_map(d);
+ struct its_vpe *vpe = NULL;
+
+ if (d->chip == &its_vpe_irq_chip) {
+ vpe = irq_data_get_irq_chip_data(d);
+ } else {
+ struct its_vlpi_map *map = get_vlpi_map(d);
+ if (map)
+ vpe = map->vpe;
+ }
- if (map)
- vpe_to_cpuid_unlock(map->vpe, flags);
+ if (vpe)
+ vpe_to_cpuid_unlock(vpe, flags);
}
static struct its_collection *valid_col(struct its_collection *col)
@@ -1433,14 +1451,29 @@ static void wait_for_syncr(void __iomem *rdbase)
cpu_relax();
}
-static void direct_lpi_inv(struct irq_data *d)
+static void __direct_lpi_inv(struct irq_data *d, u64 val)
{
- struct its_vlpi_map *map = get_vlpi_map(d);
void __iomem *rdbase;
unsigned long flags;
- u64 val;
int cpu;
+ /* Target the redistributor this LPI is currently routed to */
+ cpu = irq_to_cpuid_lock(d, &flags);
+ raw_spin_lock(&gic_data_rdist_cpu(cpu)->rd_lock);
+
+ rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base;
+ gic_write_lpir(val, rdbase + GICR_INVLPIR);
+ wait_for_syncr(rdbase);
+
+ raw_spin_unlock(&gic_data_rdist_cpu(cpu)->rd_lock);
+ irq_to_cpuid_unlock(d, flags);
+}
+
+static void direct_lpi_inv(struct irq_data *d)
+{
+ struct its_vlpi_map *map = get_vlpi_map(d);
+ u64 val;
+
if (map) {
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
@@ -1453,15 +1486,7 @@ static void direct_lpi_inv(struct irq_data *d)
val = d->hwirq;
}
- /* Target the redistributor this LPI is currently routed to */
- cpu = irq_to_cpuid_lock(d, &flags);
- raw_spin_lock(&gic_data_rdist_cpu(cpu)->rd_lock);
- rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base;
- gic_write_lpir(val, rdbase + GICR_INVLPIR);
-
- wait_for_syncr(rdbase);
- raw_spin_unlock(&gic_data_rdist_cpu(cpu)->rd_lock);
- irq_to_cpuid_unlock(d, flags);
+ __direct_lpi_inv(d, val);
}
static void lpi_update_config(struct irq_data *d, u8 clr, u8 set)
@@ -3585,6 +3610,7 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
irqd = irq_get_irq_data(virq + i);
irqd_set_single_target(irqd);
irqd_set_affinity_on_activate(irqd);
+ irqd_set_resend_when_in_progress(irqd);
pr_debug("ID:%d pID:%d vID:%d\n",
(int)(hwirq + i - its_dev->event_map.lpi_base),
(int)(hwirq + i), virq + i);
@@ -3952,18 +3978,10 @@ static void its_vpe_send_inv(struct irq_data *d)
{
struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
- if (gic_rdists->has_direct_lpi) {
- void __iomem *rdbase;
-
- /* Target the redistributor this VPE is currently known on */
- raw_spin_lock(&gic_data_rdist_cpu(vpe->col_idx)->rd_lock);
- rdbase = per_cpu_ptr(gic_rdists->rdist, vpe->col_idx)->rd_base;
- gic_write_lpir(d->parent_data->hwirq, rdbase + GICR_INVLPIR);
- wait_for_syncr(rdbase);
- raw_spin_unlock(&gic_data_rdist_cpu(vpe->col_idx)->rd_lock);
- } else {
+ if (gic_rdists->has_direct_lpi)
+ __direct_lpi_inv(d, d->parent_data->hwirq);
+ else
its_vpe_send_cmd(vpe, its_send_inv);
- }
}
static void its_vpe_mask_irq(struct irq_data *d)
@@ -4523,6 +4541,7 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq
irq_domain_set_hwirq_and_chip(domain, virq + i, i,
irqchip, vm->vpes[i]);
set_bit(i, bitmap);
+ irqd_set_resend_when_in_progress(irq_get_irq_data(virq + i));
}
if (err) {
@@ -4725,7 +4744,8 @@ static bool __maybe_unused its_enable_rk3588001(void *data)
{
struct its_node *its = data;
- if (!of_machine_is_compatible("rockchip,rk3588"))
+ if (!of_machine_is_compatible("rockchip,rk3588") &&
+ !of_machine_is_compatible("rockchip,rk3588s"))
return false;
its->flags |= ITS_FLAGS_FORCE_NON_SHAREABLE;
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index a605aa79435a..eedfa8e9f077 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -40,6 +40,7 @@
#define FLAGS_WORKAROUND_GICR_WAKER_MSM8996 (1ULL << 0)
#define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539 (1ULL << 1)
#define FLAGS_WORKAROUND_MTK_GICR_SAVE (1ULL << 2)
+#define FLAGS_WORKAROUND_ASR_ERRATUM_8601001 (1ULL << 3)
#define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1)
@@ -68,6 +69,8 @@ struct gic_chip_data {
static void __iomem *t241_dist_base_alias[T241_CHIPS_MAX] __read_mostly;
static DEFINE_STATIC_KEY_FALSE(gic_nvidia_t241_erratum);
+static DEFINE_STATIC_KEY_FALSE(gic_arm64_2941627_erratum);
+
static struct gic_chip_data gic_data __read_mostly;
static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
@@ -591,10 +594,39 @@ static void gic_irq_nmi_teardown(struct irq_data *d)
gic_irq_set_prio(d, GICD_INT_DEF_PRI);
}
+static bool gic_arm64_erratum_2941627_needed(struct irq_data *d)
+{
+ enum gic_intid_range range;
+
+ if (!static_branch_unlikely(&gic_arm64_2941627_erratum))
+ return false;
+
+ range = get_intid_range(d);
+
+ /*
+ * The workaround is needed if the IRQ is an SPI and
+ * the target cpu is different from the one we are
+ * executing on.
+ */
+ return (range == SPI_RANGE || range == ESPI_RANGE) &&
+ !cpumask_test_cpu(raw_smp_processor_id(),
+ irq_data_get_effective_affinity_mask(d));
+}
+
static void gic_eoi_irq(struct irq_data *d)
{
write_gicreg(gic_irq(d), ICC_EOIR1_EL1);
isb();
+
+ if (gic_arm64_erratum_2941627_needed(d)) {
+ /*
+ * Make sure the GIC stream deactivate packet
+ * issued by ICC_EOIR1_EL1 has completed before
+ * deactivating through GICD_IACTIVER.
+ */
+ dsb(sy);
+ gic_poke_irq(d, GICD_ICACTIVER);
+ }
}
static void gic_eoimode1_eoi_irq(struct irq_data *d)
@@ -605,7 +637,11 @@ static void gic_eoimode1_eoi_irq(struct irq_data *d)
*/
if (gic_irq(d) >= 8192 || irqd_is_forwarded_to_vcpu(d))
return;
- gic_write_dir(gic_irq(d));
+
+ if (!gic_arm64_erratum_2941627_needed(d))
+ gic_write_dir(gic_irq(d));
+ else
+ gic_poke_irq(d, GICD_ICACTIVER);
}
static int gic_set_type(struct irq_data *d, unsigned int type)
@@ -656,10 +692,16 @@ static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
return 0;
}
-static u64 gic_mpidr_to_affinity(unsigned long mpidr)
+static u64 gic_cpu_to_affinity(int cpu)
{
+ u64 mpidr = cpu_logical_map(cpu);
u64 aff;
+ /* ASR8601 needs to have its affinities shifted down... */
+ if (unlikely(gic_data.flags & FLAGS_WORKAROUND_ASR_ERRATUM_8601001))
+ mpidr = (MPIDR_AFFINITY_LEVEL(mpidr, 1) |
+ (MPIDR_AFFINITY_LEVEL(mpidr, 2) << 8));
+
aff = ((u64)MPIDR_AFFINITY_LEVEL(mpidr, 3) << 32 |
MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
@@ -914,7 +956,7 @@ static void __init gic_dist_init(void)
* Set all global interrupts to the boot CPU only. ARE must be
* enabled.
*/
- affinity = gic_mpidr_to_affinity(cpu_logical_map(smp_processor_id()));
+ affinity = gic_cpu_to_affinity(smp_processor_id());
for (i = 32; i < GIC_LINE_NR; i++)
gic_write_irouter(affinity, base + GICD_IROUTER + i * 8);
@@ -963,7 +1005,7 @@ static int gic_iterate_rdists(int (*fn)(struct redist_region *, void __iomem *))
static int __gic_populate_rdist(struct redist_region *region, void __iomem *ptr)
{
- unsigned long mpidr = cpu_logical_map(smp_processor_id());
+ unsigned long mpidr;
u64 typer;
u32 aff;
@@ -971,6 +1013,8 @@ static int __gic_populate_rdist(struct redist_region *region, void __iomem *ptr)
* Convert affinity to a 32bit value that can be matched to
* GICR_TYPER bits [63:32].
*/
+ mpidr = gic_cpu_to_affinity(smp_processor_id());
+
aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24 |
MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
@@ -1084,7 +1128,7 @@ static inline bool gic_dist_security_disabled(void)
static void gic_cpu_sys_reg_init(void)
{
int i, cpu = smp_processor_id();
- u64 mpidr = cpu_logical_map(cpu);
+ u64 mpidr = gic_cpu_to_affinity(cpu);
u64 need_rss = MPIDR_RS(mpidr);
bool group0;
u32 pribits;
@@ -1183,11 +1227,11 @@ static void gic_cpu_sys_reg_init(void)
for_each_online_cpu(i) {
bool have_rss = per_cpu(has_rss, i) && per_cpu(has_rss, cpu);
- need_rss |= MPIDR_RS(cpu_logical_map(i));
+ need_rss |= MPIDR_RS(gic_cpu_to_affinity(i));
if (need_rss && (!have_rss))
pr_crit("CPU%d (%lx) can't SGI CPU%d (%lx), no RSS\n",
cpu, (unsigned long)mpidr,
- i, (unsigned long)cpu_logical_map(i));
+ i, (unsigned long)gic_cpu_to_affinity(i));
}
/**
@@ -1263,9 +1307,11 @@ static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
unsigned long cluster_id)
{
int next_cpu, cpu = *base_cpu;
- unsigned long mpidr = cpu_logical_map(cpu);
+ unsigned long mpidr;
u16 tlist = 0;
+ mpidr = gic_cpu_to_affinity(cpu);
+
while (cpu < nr_cpu_ids) {
tlist |= 1 << (mpidr & 0xf);
@@ -1274,7 +1320,7 @@ static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
goto out;
cpu = next_cpu;
- mpidr = cpu_logical_map(cpu);
+ mpidr = gic_cpu_to_affinity(cpu);
if (cluster_id != MPIDR_TO_SGI_CLUSTER_ID(mpidr)) {
cpu--;
@@ -1319,7 +1365,7 @@ static void gic_ipi_send_mask(struct irq_data *d, const struct cpumask *mask)
dsb(ishst);
for_each_cpu(cpu, mask) {
- u64 cluster_id = MPIDR_TO_SGI_CLUSTER_ID(cpu_logical_map(cpu));
+ u64 cluster_id = MPIDR_TO_SGI_CLUSTER_ID(gic_cpu_to_affinity(cpu));
u16 tlist;
tlist = gic_compute_target_list(&cpu, mask, cluster_id);
@@ -1377,7 +1423,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
offset = convert_offset_index(d, GICD_IROUTER, &index);
reg = gic_dist_base(d) + offset + (index * 8);
- val = gic_mpidr_to_affinity(cpu_logical_map(cpu));
+ val = gic_cpu_to_affinity(cpu);
gic_write_irouter(val, reg);
@@ -1796,6 +1842,21 @@ static bool gic_enable_quirk_nvidia_t241(void *data)
return true;
}
+static bool gic_enable_quirk_asr8601(void *data)
+{
+ struct gic_chip_data *d = data;
+
+ d->flags |= FLAGS_WORKAROUND_ASR_ERRATUM_8601001;
+
+ return true;
+}
+
+static bool gic_enable_quirk_arm64_2941627(void *data)
+{
+ static_branch_enable(&gic_arm64_2941627_erratum);
+ return true;
+}
+
static const struct gic_quirk gic_quirks[] = {
{
.desc = "GICv3: Qualcomm MSM8996 broken firmware",
@@ -1803,6 +1864,11 @@ static const struct gic_quirk gic_quirks[] = {
.init = gic_enable_quirk_msm8996,
},
{
+ .desc = "GICv3: ASR erratum 8601001",
+ .compatible = "asr,asr8601-gic-v3",
+ .init = gic_enable_quirk_asr8601,
+ },
+ {
.desc = "GICv3: Mediatek Chromebook GICR save problem",
.property = "mediatek,broken-save-restore-fw",
.init = gic_enable_quirk_mtk_gicr,
@@ -1839,6 +1905,25 @@ static const struct gic_quirk gic_quirks[] = {
.init = gic_enable_quirk_nvidia_t241,
},
{
+ /*
+ * GIC-700: 2941627 workaround - IP variant [0,1]
+ *
+ */
+ .desc = "GICv3: ARM64 erratum 2941627",
+ .iidr = 0x0400043b,
+ .mask = 0xff0e0fff,
+ .init = gic_enable_quirk_arm64_2941627,
+ },
+ {
+ /*
+ * GIC-700: 2941627 workaround - IP variant [2]
+ */
+ .desc = "GICv3: ARM64 erratum 2941627",
+ .iidr = 0x0402043b,
+ .mask = 0xff0f0fff,
+ .init = gic_enable_quirk_arm64_2941627,
+ },
+ {
}
};
diff --git a/drivers/irqchip/irq-jcore-aic.c b/drivers/irqchip/irq-jcore-aic.c
index 5f47d8ee4ae3..b9dcc8e78c75 100644
--- a/drivers/irqchip/irq-jcore-aic.c
+++ b/drivers/irqchip/irq-jcore-aic.c
@@ -68,6 +68,7 @@ static int __init aic_irq_of_init(struct device_node *node,
unsigned min_irq = JCORE_AIC2_MIN_HWIRQ;
unsigned dom_sz = JCORE_AIC_MAX_HWIRQ+1;
struct irq_domain *domain;
+ int ret;
pr_info("Initializing J-Core AIC\n");
@@ -100,6 +101,12 @@ static int __init aic_irq_of_init(struct device_node *node,
jcore_aic.irq_unmask = noop;
jcore_aic.name = "AIC";
+ ret = irq_alloc_descs(-1, min_irq, dom_sz - min_irq,
+ of_node_to_nid(node));
+
+ if (ret < 0)
+ return ret;
+
domain = irq_domain_add_legacy(node, dom_sz - min_irq, min_irq, min_irq,
&jcore_aic_irqdomain_ops,
&jcore_aic);
diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c
index 71ef19f77a5a..92d8aa28bdf5 100644
--- a/drivers/irqchip/irq-loongson-eiointc.c
+++ b/drivers/irqchip/irq-loongson-eiointc.c
@@ -36,6 +36,7 @@ static int nr_pics;
struct eiointc_priv {
u32 node;
+ u32 vec_count;
nodemask_t node_map;
cpumask_t cpuspan_map;
struct fwnode_handle *domain_handle;
@@ -153,18 +154,18 @@ static int eiointc_router_init(unsigned int cpu)
if ((cpu_logical_map(cpu) % CORES_PER_EIO_NODE) == 0) {
eiointc_enable();
- for (i = 0; i < VEC_COUNT / 32; i++) {
+ for (i = 0; i < eiointc_priv[0]->vec_count / 32; i++) {
data = (((1 << (i * 2 + 1)) << 16) | (1 << (i * 2)));
iocsr_write32(data, EIOINTC_REG_NODEMAP + i * 4);
}
- for (i = 0; i < VEC_COUNT / 32 / 4; i++) {
+ for (i = 0; i < eiointc_priv[0]->vec_count / 32 / 4; i++) {
bit = BIT(1 + index); /* Route to IP[1 + index] */
data = bit | (bit << 8) | (bit << 16) | (bit << 24);
iocsr_write32(data, EIOINTC_REG_IPMAP + i * 4);
}
- for (i = 0; i < VEC_COUNT / 4; i++) {
+ for (i = 0; i < eiointc_priv[0]->vec_count / 4; i++) {
/* Route to Node-0 Core-0 */
if (index == 0)
bit = BIT(cpu_logical_map(0));
@@ -175,7 +176,7 @@ static int eiointc_router_init(unsigned int cpu)
iocsr_write32(data, EIOINTC_REG_ROUTE + i * 4);
}
- for (i = 0; i < VEC_COUNT / 32; i++) {
+ for (i = 0; i < eiointc_priv[0]->vec_count / 32; i++) {
data = 0xffffffff;
iocsr_write32(data, EIOINTC_REG_ENABLE + i * 4);
iocsr_write32(data, EIOINTC_REG_BOUNCE + i * 4);
@@ -195,7 +196,7 @@ static void eiointc_irq_dispatch(struct irq_desc *desc)
chained_irq_enter(chip, desc);
- for (i = 0; i < VEC_REG_COUNT; i++) {
+ for (i = 0; i < eiointc_priv[0]->vec_count / VEC_COUNT_PER_REG; i++) {
pending = iocsr_read64(EIOINTC_REG_ISR + (i << 3));
iocsr_write64(pending, EIOINTC_REG_ISR + (i << 3));
while (pending) {
@@ -310,11 +311,11 @@ static void eiointc_resume(void)
eiointc_router_init(0);
for (i = 0; i < nr_pics; i++) {
- for (j = 0; j < VEC_COUNT; j++) {
+ for (j = 0; j < eiointc_priv[0]->vec_count; j++) {
desc = irq_resolve_mapping(eiointc_priv[i]->eiointc_domain, j);
if (desc && desc->handle_irq && desc->handle_irq != handle_bad_irq) {
raw_spin_lock(&desc->lock);
- irq_data = &desc->irq_data;
+ irq_data = irq_domain_get_irq_data(eiointc_priv[i]->eiointc_domain, irq_desc_get_irq(desc));
eiointc_set_irq_affinity(irq_data, irq_data->common->affinity, 0);
raw_spin_unlock(&desc->lock);
}
@@ -375,11 +376,47 @@ static int __init acpi_cascade_irqdomain_init(void)
return 0;
}
+static int __init eiointc_init(struct eiointc_priv *priv, int parent_irq,
+ u64 node_map)
+{
+ int i;
+
+ node_map = node_map ? node_map : -1ULL;
+ for_each_possible_cpu(i) {
+ if (node_map & (1ULL << (cpu_to_eio_node(i)))) {
+ node_set(cpu_to_eio_node(i), priv->node_map);
+ cpumask_or(&priv->cpuspan_map, &priv->cpuspan_map,
+ cpumask_of(i));
+ }
+ }
+
+ priv->eiointc_domain = irq_domain_create_linear(priv->domain_handle,
+ priv->vec_count,
+ &eiointc_domain_ops,
+ priv);
+ if (!priv->eiointc_domain) {
+ pr_err("loongson-extioi: cannot add IRQ domain\n");
+ return -ENOMEM;
+ }
+
+ eiointc_priv[nr_pics++] = priv;
+ eiointc_router_init(0);
+ irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv);
+
+ if (nr_pics == 1) {
+ register_syscore_ops(&eiointc_syscore_ops);
+ cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING,
+ "irqchip/loongarch/intc:starting",
+ eiointc_router_init, NULL);
+ }
+
+ return 0;
+}
+
int __init eiointc_acpi_init(struct irq_domain *parent,
struct acpi_madt_eio_pic *acpi_eiointc)
{
- int i, ret, parent_irq;
- unsigned long node_map;
+ int parent_irq, ret;
struct eiointc_priv *priv;
int node;
@@ -394,37 +431,14 @@ int __init eiointc_acpi_init(struct irq_domain *parent,
goto out_free_priv;
}
+ priv->vec_count = VEC_COUNT;
priv->node = acpi_eiointc->node;
- node_map = acpi_eiointc->node_map ? : -1ULL;
-
- for_each_possible_cpu(i) {
- if (node_map & (1ULL << cpu_to_eio_node(i))) {
- node_set(cpu_to_eio_node(i), priv->node_map);
- cpumask_or(&priv->cpuspan_map, &priv->cpuspan_map, cpumask_of(i));
- }
- }
-
- /* Setup IRQ domain */
- priv->eiointc_domain = irq_domain_create_linear(priv->domain_handle, VEC_COUNT,
- &eiointc_domain_ops, priv);
- if (!priv->eiointc_domain) {
- pr_err("loongson-eiointc: cannot add IRQ domain\n");
- goto out_free_handle;
- }
-
- eiointc_priv[nr_pics++] = priv;
-
- eiointc_router_init(0);
parent_irq = irq_create_mapping(parent, acpi_eiointc->cascade);
- irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv);
- if (nr_pics == 1) {
- register_syscore_ops(&eiointc_syscore_ops);
- cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING,
- "irqchip/loongarch/intc:starting",
- eiointc_router_init, NULL);
- }
+ ret = eiointc_init(priv, parent_irq, acpi_eiointc->node_map);
+ if (ret < 0)
+ goto out_free_handle;
if (cpu_has_flatmode)
node = cpu_to_node(acpi_eiointc->node * CORES_PER_EIO_NODE);
@@ -432,7 +446,10 @@ int __init eiointc_acpi_init(struct irq_domain *parent,
node = acpi_eiointc->node;
acpi_set_vec_parent(node, priv->eiointc_domain, pch_group);
acpi_set_vec_parent(node, priv->eiointc_domain, msi_group);
+
ret = acpi_cascade_irqdomain_init();
+ if (ret < 0)
+ goto out_free_handle;
return ret;
@@ -444,3 +461,49 @@ out_free_priv:
return -ENOMEM;
}
+
+static int __init eiointc_of_init(struct device_node *of_node,
+ struct device_node *parent)
+{
+ int parent_irq, ret;
+ struct eiointc_priv *priv;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ parent_irq = irq_of_parse_and_map(of_node, 0);
+ if (parent_irq <= 0) {
+ ret = -ENODEV;
+ goto out_free_priv;
+ }
+
+ ret = irq_set_handler_data(parent_irq, priv);
+ if (ret < 0)
+ goto out_free_priv;
+
+ /*
+ * In particular, the number of devices supported by the LS2K0500
+ * extended I/O interrupt vector is 128.
+ */
+ if (of_device_is_compatible(of_node, "loongson,ls2k0500-eiointc"))
+ priv->vec_count = 128;
+ else
+ priv->vec_count = VEC_COUNT;
+
+ priv->node = 0;
+ priv->domain_handle = of_node_to_fwnode(of_node);
+
+ ret = eiointc_init(priv, parent_irq, 0);
+ if (ret < 0)
+ goto out_free_priv;
+
+ return 0;
+
+out_free_priv:
+ kfree(priv);
+ return ret;
+}
+
+IRQCHIP_DECLARE(loongson_ls2k0500_eiointc, "loongson,ls2k0500-eiointc", eiointc_of_init);
+IRQCHIP_DECLARE(loongson_ls2k2000_eiointc, "loongson,ls2k2000-eiointc", eiointc_of_init);
diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-loongson-liointc.c
index 8d00a9ad5b00..e4b33aed1c97 100644
--- a/drivers/irqchip/irq-loongson-liointc.c
+++ b/drivers/irqchip/irq-loongson-liointc.c
@@ -32,6 +32,10 @@
#define LIOINTC_REG_INTC_EN_STATUS (LIOINTC_INTC_CHIP_START + 0x04)
#define LIOINTC_REG_INTC_ENABLE (LIOINTC_INTC_CHIP_START + 0x08)
#define LIOINTC_REG_INTC_DISABLE (LIOINTC_INTC_CHIP_START + 0x0c)
+/*
+ * LIOINTC_REG_INTC_POL register is only valid for Loongson-2K series, and
+ * Loongson-3 series behave as noops.
+ */
#define LIOINTC_REG_INTC_POL (LIOINTC_INTC_CHIP_START + 0x10)
#define LIOINTC_REG_INTC_EDGE (LIOINTC_INTC_CHIP_START + 0x14)
@@ -116,19 +120,19 @@ static int liointc_set_type(struct irq_data *data, unsigned int type)
switch (type) {
case IRQ_TYPE_LEVEL_HIGH:
liointc_set_bit(gc, LIOINTC_REG_INTC_EDGE, mask, false);
- liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, true);
+ liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, false);
break;
case IRQ_TYPE_LEVEL_LOW:
liointc_set_bit(gc, LIOINTC_REG_INTC_EDGE, mask, false);
- liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, false);
+ liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, true);
break;
case IRQ_TYPE_EDGE_RISING:
liointc_set_bit(gc, LIOINTC_REG_INTC_EDGE, mask, true);
- liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, true);
+ liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, false);
break;
case IRQ_TYPE_EDGE_FALLING:
liointc_set_bit(gc, LIOINTC_REG_INTC_EDGE, mask, true);
- liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, false);
+ liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, true);
break;
default:
irq_gc_unlock_irqrestore(gc, flags);
@@ -291,6 +295,7 @@ static int liointc_init(phys_addr_t addr, unsigned long size, int revision,
ct->chip.irq_mask = irq_gc_mask_disable_reg;
ct->chip.irq_mask_ack = irq_gc_mask_disable_reg;
ct->chip.irq_set_type = liointc_set_type;
+ ct->chip.flags = IRQCHIP_SKIP_SET_WAKE;
gc->mask_cache = 0;
priv->gc = gc;
diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c
index e5fe4d50be05..93a71f66efeb 100644
--- a/drivers/irqchip/irq-loongson-pch-pic.c
+++ b/drivers/irqchip/irq-loongson-pch-pic.c
@@ -164,7 +164,7 @@ static int pch_pic_domain_translate(struct irq_domain *d,
if (fwspec->param_count < 2)
return -EINVAL;
- *hwirq = fwspec->param[0] + priv->ht_vec_base;
+ *hwirq = fwspec->param[0];
*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
} else {
if (fwspec->param_count < 1)
@@ -196,7 +196,7 @@ static int pch_pic_alloc(struct irq_domain *domain, unsigned int virq,
parent_fwspec.fwnode = domain->parent->fwnode;
parent_fwspec.param_count = 1;
- parent_fwspec.param[0] = hwirq;
+ parent_fwspec.param[0] = hwirq + priv->ht_vec_base;
err = irq_domain_alloc_irqs_parent(domain, virq, 1, &parent_fwspec);
if (err)
@@ -401,14 +401,12 @@ static int __init acpi_cascade_irqdomain_init(void)
int __init pch_pic_acpi_init(struct irq_domain *parent,
struct acpi_madt_bio_pic *acpi_pchpic)
{
- int ret, vec_base;
+ int ret;
struct fwnode_handle *domain_handle;
if (find_pch_pic(acpi_pchpic->gsi_base) >= 0)
return 0;
- vec_base = acpi_pchpic->gsi_base - GSI_MIN_PCH_IRQ;
-
domain_handle = irq_domain_alloc_fwnode(&acpi_pchpic->address);
if (!domain_handle) {
pr_err("Unable to allocate domain handle\n");
@@ -416,7 +414,7 @@ int __init pch_pic_acpi_init(struct irq_domain *parent,
}
ret = pch_pic_init(acpi_pchpic->address, acpi_pchpic->size,
- vec_base, parent, domain_handle, acpi_pchpic->gsi_base);
+ 0, parent, domain_handle, acpi_pchpic->gsi_base);
if (ret < 0) {
irq_domain_free_fwnode(domain_handle);
diff --git a/drivers/irqchip/irq-mmp.c b/drivers/irqchip/irq-mmp.c
index 83455ca72439..25cf4f80e767 100644
--- a/drivers/irqchip/irq-mmp.c
+++ b/drivers/irqchip/irq-mmp.c
@@ -244,132 +244,6 @@ static void __exception_irq_entry mmp2_handle_irq(struct pt_regs *regs)
generic_handle_domain_irq(icu_data[0].domain, hwirq);
}
-/* MMP (ARMv5) */
-void __init icu_init_irq(void)
-{
- int irq;
-
- max_icu_nr = 1;
- mmp_icu_base = ioremap(0xd4282000, 0x1000);
- icu_data[0].conf_enable = mmp_conf.conf_enable;
- icu_data[0].conf_disable = mmp_conf.conf_disable;
- icu_data[0].conf_mask = mmp_conf.conf_mask;
- icu_data[0].nr_irqs = 64;
- icu_data[0].virq_base = 0;
- icu_data[0].domain = irq_domain_add_legacy(NULL, 64, 0, 0,
- &irq_domain_simple_ops,
- &icu_data[0]);
- for (irq = 0; irq < 64; irq++) {
- icu_mask_irq(irq_get_irq_data(irq));
- irq_set_chip_and_handler(irq, &icu_irq_chip, handle_level_irq);
- }
- irq_set_default_host(icu_data[0].domain);
- set_handle_irq(mmp_handle_irq);
-}
-
-/* MMP2 (ARMv7) */
-void __init mmp2_init_icu(void)
-{
- int irq, end;
-
- max_icu_nr = 8;
- mmp_icu_base = ioremap(0xd4282000, 0x1000);
- icu_data[0].conf_enable = mmp2_conf.conf_enable;
- icu_data[0].conf_disable = mmp2_conf.conf_disable;
- icu_data[0].conf_mask = mmp2_conf.conf_mask;
- icu_data[0].nr_irqs = 64;
- icu_data[0].virq_base = 0;
- icu_data[0].domain = irq_domain_add_legacy(NULL, 64, 0, 0,
- &irq_domain_simple_ops,
- &icu_data[0]);
- icu_data[1].reg_status = mmp_icu_base + 0x150;
- icu_data[1].reg_mask = mmp_icu_base + 0x168;
- icu_data[1].clr_mfp_irq_base = icu_data[0].virq_base +
- icu_data[0].nr_irqs;
- icu_data[1].clr_mfp_hwirq = 1; /* offset to IRQ_MMP2_PMIC_BASE */
- icu_data[1].nr_irqs = 2;
- icu_data[1].cascade_irq = 4;
- icu_data[1].virq_base = icu_data[0].virq_base + icu_data[0].nr_irqs;
- icu_data[1].domain = irq_domain_add_legacy(NULL, icu_data[1].nr_irqs,
- icu_data[1].virq_base, 0,
- &irq_domain_simple_ops,
- &icu_data[1]);
- icu_data[2].reg_status = mmp_icu_base + 0x154;
- icu_data[2].reg_mask = mmp_icu_base + 0x16c;
- icu_data[2].nr_irqs = 2;
- icu_data[2].cascade_irq = 5;
- icu_data[2].virq_base = icu_data[1].virq_base + icu_data[1].nr_irqs;
- icu_data[2].domain = irq_domain_add_legacy(NULL, icu_data[2].nr_irqs,
- icu_data[2].virq_base, 0,
- &irq_domain_simple_ops,
- &icu_data[2]);
- icu_data[3].reg_status = mmp_icu_base + 0x180;
- icu_data[3].reg_mask = mmp_icu_base + 0x17c;
- icu_data[3].nr_irqs = 3;
- icu_data[3].cascade_irq = 9;
- icu_data[3].virq_base = icu_data[2].virq_base + icu_data[2].nr_irqs;
- icu_data[3].domain = irq_domain_add_legacy(NULL, icu_data[3].nr_irqs,
- icu_data[3].virq_base, 0,
- &irq_domain_simple_ops,
- &icu_data[3]);
- icu_data[4].reg_status = mmp_icu_base + 0x158;
- icu_data[4].reg_mask = mmp_icu_base + 0x170;
- icu_data[4].nr_irqs = 5;
- icu_data[4].cascade_irq = 17;
- icu_data[4].virq_base = icu_data[3].virq_base + icu_data[3].nr_irqs;
- icu_data[4].domain = irq_domain_add_legacy(NULL, icu_data[4].nr_irqs,
- icu_data[4].virq_base, 0,
- &irq_domain_simple_ops,
- &icu_data[4]);
- icu_data[5].reg_status = mmp_icu_base + 0x15c;
- icu_data[5].reg_mask = mmp_icu_base + 0x174;
- icu_data[5].nr_irqs = 15;
- icu_data[5].cascade_irq = 35;
- icu_data[5].virq_base = icu_data[4].virq_base + icu_data[4].nr_irqs;
- icu_data[5].domain = irq_domain_add_legacy(NULL, icu_data[5].nr_irqs,
- icu_data[5].virq_base, 0,
- &irq_domain_simple_ops,
- &icu_data[5]);
- icu_data[6].reg_status = mmp_icu_base + 0x160;
- icu_data[6].reg_mask = mmp_icu_base + 0x178;
- icu_data[6].nr_irqs = 2;
- icu_data[6].cascade_irq = 51;
- icu_data[6].virq_base = icu_data[5].virq_base + icu_data[5].nr_irqs;
- icu_data[6].domain = irq_domain_add_legacy(NULL, icu_data[6].nr_irqs,
- icu_data[6].virq_base, 0,
- &irq_domain_simple_ops,
- &icu_data[6]);
- icu_data[7].reg_status = mmp_icu_base + 0x188;
- icu_data[7].reg_mask = mmp_icu_base + 0x184;
- icu_data[7].nr_irqs = 2;
- icu_data[7].cascade_irq = 55;
- icu_data[7].virq_base = icu_data[6].virq_base + icu_data[6].nr_irqs;
- icu_data[7].domain = irq_domain_add_legacy(NULL, icu_data[7].nr_irqs,
- icu_data[7].virq_base, 0,
- &irq_domain_simple_ops,
- &icu_data[7]);
- end = icu_data[7].virq_base + icu_data[7].nr_irqs;
- for (irq = 0; irq < end; irq++) {
- icu_mask_irq(irq_get_irq_data(irq));
- if (irq == icu_data[1].cascade_irq ||
- irq == icu_data[2].cascade_irq ||
- irq == icu_data[3].cascade_irq ||
- irq == icu_data[4].cascade_irq ||
- irq == icu_data[5].cascade_irq ||
- irq == icu_data[6].cascade_irq ||
- irq == icu_data[7].cascade_irq) {
- irq_set_chip(irq, &icu_irq_chip);
- irq_set_chained_handler(irq, icu_mux_irq_demux);
- } else {
- irq_set_chip_and_handler(irq, &icu_irq_chip,
- handle_level_irq);
- }
- }
- irq_set_default_host(icu_data[0].domain);
- set_handle_irq(mmp2_handle_irq);
-}
-
-#ifdef CONFIG_OF
static int __init mmp_init_bases(struct device_node *node)
{
int ret, nr_irqs, irq, i = 0;
@@ -548,4 +422,3 @@ err:
return -EINVAL;
}
IRQCHIP_DECLARE(mmp2_mux_intc, "mrvl,mmp2-mux-intc", mmp2_mux_of_init);
-#endif
diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c
index 55cb6b5a686e..be9680645545 100644
--- a/drivers/irqchip/irq-mxs.c
+++ b/drivers/irqchip/irq-mxs.c
@@ -201,6 +201,7 @@ static int __init icoll_of_init(struct device_node *np,
stmp_reset_block(icoll_priv.ctrl);
icoll_add_domain(np, ICOLL_NUM_IRQS);
+ set_handle_irq(icoll_handle_irq);
return 0;
}
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/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
index 6a3f7498ea8e..b5fa76ce5046 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -173,6 +173,16 @@ static struct irq_chip stm32_exti_h_chip_direct;
#define EXTI_INVALID_IRQ U8_MAX
#define STM32MP1_DESC_IRQ_SIZE (ARRAY_SIZE(stm32mp1_exti_banks) * IRQS_PER_BANK)
+/*
+ * Use some intentionally tricky logic here to initialize the whole array to
+ * EXTI_INVALID_IRQ, but then override certain fields, requiring us to indicate
+ * that we "know" that there are overrides in this structure, and we'll need to
+ * disable that warning from W=1 builds.
+ */
+__diag_push();
+__diag_ignore_all("-Woverride-init",
+ "logic to initialize all and then override some is OK");
+
static const u8 stm32mp1_desc_irq[] = {
/* default value */
[0 ... (STM32MP1_DESC_IRQ_SIZE - 1)] = EXTI_INVALID_IRQ,
@@ -208,6 +218,7 @@ static const u8 stm32mp1_desc_irq[] = {
[31] = 53,
[32] = 82,
[33] = 83,
+ [46] = 151,
[47] = 93,
[48] = 138,
[50] = 139,
@@ -266,6 +277,8 @@ static const u8 stm32mp13_desc_irq[] = {
[70] = 98,
};
+__diag_pop();
+
static const struct stm32_exti_drv_data stm32mp1_drv_data = {
.exti_banks = stm32mp1_exti_banks,
.bank_nr = ARRAY_SIZE(stm32mp1_exti_banks),
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/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index c0331b268010..fe391de1aba3 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -839,7 +839,7 @@ hfcpci_fill_fifo(struct bchannel *bch)
*z1t = cpu_to_le16(new_z1); /* now send data */
if (bch->tx_idx < bch->tx_skb->len)
return;
- dev_kfree_skb(bch->tx_skb);
+ dev_kfree_skb_any(bch->tx_skb);
if (get_next_bframe(bch))
goto next_t_frame;
return;
@@ -895,7 +895,7 @@ hfcpci_fill_fifo(struct bchannel *bch)
}
bz->za[new_f1].z1 = cpu_to_le16(new_z1); /* for next buffer */
bz->f1 = new_f1; /* next frame */
- dev_kfree_skb(bch->tx_skb);
+ dev_kfree_skb_any(bch->tx_skb);
get_next_bframe(bch);
}
@@ -1119,7 +1119,7 @@ tx_birq(struct bchannel *bch)
if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len)
hfcpci_fill_fifo(bch);
else {
- dev_kfree_skb(bch->tx_skb);
+ dev_kfree_skb_any(bch->tx_skb);
if (get_next_bframe(bch))
hfcpci_fill_fifo(bch);
}
@@ -2277,7 +2277,7 @@ _hfcpci_softirq(struct device *dev, void *unused)
return 0;
if (hc->hw.int_m2 & HFCPCI_IRQ_ENABLE) {
- spin_lock(&hc->lock);
+ spin_lock_irq(&hc->lock);
bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1);
if (bch && bch->state == ISDN_P_B_RAW) { /* B1 rx&tx */
main_rec_hfcpci(bch);
@@ -2288,7 +2288,7 @@ _hfcpci_softirq(struct device *dev, void *unused)
main_rec_hfcpci(bch);
tx_birq(bch);
}
- spin_unlock(&hc->lock);
+ spin_unlock_irq(&hc->lock);
}
return 0;
}
diff --git a/drivers/isdn/mISDN/dsp.h b/drivers/isdn/mISDN/dsp.h
index fa09d511a8ed..baf31258f5c9 100644
--- a/drivers/isdn/mISDN/dsp.h
+++ b/drivers/isdn/mISDN/dsp.h
@@ -247,7 +247,7 @@ extern void dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp);
extern int dsp_cmx_conf(struct dsp *dsp, u32 conf_id);
extern void dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb);
extern void dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb);
-extern void dsp_cmx_send(void *arg);
+extern void dsp_cmx_send(struct timer_list *arg);
extern void dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb);
extern int dsp_cmx_del_conf_member(struct dsp *dsp);
extern int dsp_cmx_del_conf(struct dsp_conf *conf);
diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c
index 357b87592eb4..61cb45c5d0d8 100644
--- a/drivers/isdn/mISDN/dsp_cmx.c
+++ b/drivers/isdn/mISDN/dsp_cmx.c
@@ -1614,7 +1614,7 @@ static u16 dsp_count; /* last sample count */
static int dsp_count_valid; /* if we have last sample count */
void
-dsp_cmx_send(void *arg)
+dsp_cmx_send(struct timer_list *arg)
{
struct dsp_conf *conf;
struct dsp_conf_member *member;
diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c
index 386084530c2f..fae95f166688 100644
--- a/drivers/isdn/mISDN/dsp_core.c
+++ b/drivers/isdn/mISDN/dsp_core.c
@@ -1195,7 +1195,7 @@ static int __init dsp_init(void)
}
/* set sample timer */
- timer_setup(&dsp_spl_tl, (void *)dsp_cmx_send, 0);
+ timer_setup(&dsp_spl_tl, dsp_cmx_send, 0);
dsp_spl_tl.expires = jiffies + dsp_tics;
dsp_spl_jiffies = dsp_spl_tl.expires;
add_timer(&dsp_spl_tl);
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 d5e774d83021..03c58e50cc44 100644
--- a/drivers/leds/trigger/ledtrig-netdev.c
+++ b/drivers/leds/trigger/ledtrig-netdev.c
@@ -13,6 +13,7 @@
#include <linux/atomic.h>
#include <linux/ctype.h>
#include <linux/device.h>
+#include <linux/ethtool.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
@@ -20,10 +21,13 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/netdevice.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/rtnetlink.h>
#include <linux/timer.h>
#include "../leds.h"
+#define NETDEV_LED_DEFAULT_INTERVAL 50
+
/*
* Configurable sysfs attributes:
*
@@ -37,7 +41,7 @@
*/
struct led_netdev_data {
- spinlock_t lock;
+ struct mutex lock;
struct delayed_work work;
struct notifier_block notifier;
@@ -50,16 +54,11 @@ struct led_netdev_data {
unsigned int last_activity;
unsigned long mode;
-#define NETDEV_LED_LINK 0
-#define NETDEV_LED_TX 1
-#define NETDEV_LED_RX 2
-#define NETDEV_LED_MODE_LINKUP 3
-};
+ int link_speed;
+ u8 duplex;
-enum netdev_led_attr {
- NETDEV_ATTR_LINK,
- NETDEV_ATTR_TX,
- NETDEV_ATTR_RX
+ bool carrier_link_up;
+ bool hw_control;
};
static void set_baseline_state(struct led_netdev_data *trigger_data)
@@ -67,16 +66,48 @@ static void set_baseline_state(struct led_netdev_data *trigger_data)
int current_brightness;
struct led_classdev *led_cdev = trigger_data->led_cdev;
+ /* Already validated, hw control is possible with the requested mode */
+ if (trigger_data->hw_control) {
+ led_cdev->hw_control_set(led_cdev, trigger_data->mode);
+
+ return;
+ }
+
current_brightness = led_cdev->brightness;
if (current_brightness)
led_cdev->blink_brightness = current_brightness;
if (!led_cdev->blink_brightness)
led_cdev->blink_brightness = led_cdev->max_brightness;
- if (!test_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode))
+ if (!trigger_data->carrier_link_up) {
led_set_brightness(led_cdev, LED_OFF);
- else {
- if (test_bit(NETDEV_LED_LINK, &trigger_data->mode))
+ } else {
+ bool blink_on = false;
+
+ if (test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode))
+ blink_on = true;
+
+ if (test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) &&
+ trigger_data->link_speed == SPEED_10)
+ blink_on = true;
+
+ if (test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) &&
+ trigger_data->link_speed == SPEED_100)
+ blink_on = true;
+
+ if (test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) &&
+ trigger_data->link_speed == SPEED_1000)
+ blink_on = true;
+
+ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) &&
+ trigger_data->duplex == DUPLEX_HALF)
+ blink_on = true;
+
+ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode) &&
+ trigger_data->duplex == DUPLEX_FULL)
+ blink_on = true;
+
+ if (blink_on)
led_set_brightness(led_cdev,
led_cdev->blink_brightness);
else
@@ -85,44 +116,121 @@ static void set_baseline_state(struct led_netdev_data *trigger_data)
/* If we are looking for RX/TX start periodically
* checking stats
*/
- if (test_bit(NETDEV_LED_TX, &trigger_data->mode) ||
- test_bit(NETDEV_LED_RX, &trigger_data->mode))
+ if (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) ||
+ test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode))
schedule_delayed_work(&trigger_data->work, 0);
}
}
+static bool supports_hw_control(struct led_classdev *led_cdev)
+{
+ if (!led_cdev->hw_control_get || !led_cdev->hw_control_set ||
+ !led_cdev->hw_control_is_supported)
+ return false;
+
+ return !strcmp(led_cdev->hw_control_trigger, led_cdev->trigger->name);
+}
+
+/*
+ * Validate the configured netdev is the same as the one associated with
+ * the LED driver in hw control.
+ */
+static bool validate_net_dev(struct led_classdev *led_cdev,
+ struct net_device *net_dev)
+{
+ struct device *dev = led_cdev->hw_control_get_device(led_cdev);
+ struct net_device *ndev;
+
+ if (!dev)
+ return false;
+
+ ndev = to_net_dev(dev);
+
+ return ndev == net_dev;
+}
+
+static bool can_hw_control(struct led_netdev_data *trigger_data)
+{
+ unsigned long default_interval = msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL);
+ unsigned int interval = atomic_read(&trigger_data->interval);
+ struct led_classdev *led_cdev = trigger_data->led_cdev;
+ int ret;
+
+ if (!supports_hw_control(led_cdev))
+ return false;
+
+ /*
+ * Interval must be set to the default
+ * value. Any different value is rejected if in hw
+ * control.
+ */
+ if (interval != default_interval)
+ return false;
+
+ /*
+ * net_dev must be set with hw control, otherwise no
+ * blinking can be happening and there is nothing to
+ * offloaded. Additionally, for hw control to be
+ * valid, the configured netdev must be the same as
+ * netdev associated to the LED.
+ */
+ if (!validate_net_dev(led_cdev, trigger_data->net_dev))
+ return false;
+
+ /* Check if the requested mode is supported */
+ ret = led_cdev->hw_control_is_supported(led_cdev, trigger_data->mode);
+ /* Fall back to software blinking if not supported */
+ if (ret == -EOPNOTSUPP)
+ return false;
+ if (ret) {
+ dev_warn(led_cdev->dev,
+ "Current mode check failed with error %d\n", ret);
+ return false;
+ }
+
+ return true;
+}
+
+static void get_device_state(struct led_netdev_data *trigger_data)
+{
+ struct ethtool_link_ksettings cmd;
+
+ trigger_data->carrier_link_up = netif_carrier_ok(trigger_data->net_dev);
+ if (!trigger_data->carrier_link_up)
+ return;
+
+ if (!__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) {
+ trigger_data->link_speed = cmd.base.speed;
+ trigger_data->duplex = cmd.base.duplex;
+ }
+}
+
static ssize_t device_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
ssize_t len;
- spin_lock_bh(&trigger_data->lock);
+ mutex_lock(&trigger_data->lock);
len = sprintf(buf, "%s\n", trigger_data->device_name);
- spin_unlock_bh(&trigger_data->lock);
+ mutex_unlock(&trigger_data->lock);
return len;
}
-static ssize_t device_name_store(struct device *dev,
- struct device_attribute *attr, const char *buf,
- size_t size)
+static int set_device_name(struct led_netdev_data *trigger_data,
+ const char *name, size_t size)
{
- struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
-
- if (size >= IFNAMSIZ)
- return -EINVAL;
-
cancel_delayed_work_sync(&trigger_data->work);
- spin_lock_bh(&trigger_data->lock);
+ mutex_lock(&trigger_data->lock);
if (trigger_data->net_dev) {
dev_put(trigger_data->net_dev);
trigger_data->net_dev = NULL;
}
- memcpy(trigger_data->device_name, buf, size);
+ memcpy(trigger_data->device_name, name, size);
trigger_data->device_name[size] = 0;
if (size > 0 && trigger_data->device_name[size - 1] == '\n')
trigger_data->device_name[size - 1] = 0;
@@ -131,36 +239,58 @@ static ssize_t device_name_store(struct device *dev,
trigger_data->net_dev =
dev_get_by_name(&init_net, trigger_data->device_name);
- clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
- if (trigger_data->net_dev != NULL)
- if (netif_carrier_ok(trigger_data->net_dev))
- set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
+ trigger_data->carrier_link_up = false;
+ trigger_data->link_speed = SPEED_UNKNOWN;
+ trigger_data->duplex = DUPLEX_UNKNOWN;
+ if (trigger_data->net_dev != NULL) {
+ rtnl_lock();
+ get_device_state(trigger_data);
+ rtnl_unlock();
+ }
trigger_data->last_activity = 0;
set_baseline_state(trigger_data);
- spin_unlock_bh(&trigger_data->lock);
+ mutex_unlock(&trigger_data->lock);
+
+ return 0;
+}
+
+static ssize_t device_name_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
+ int ret;
+ if (size >= IFNAMSIZ)
+ return -EINVAL;
+
+ ret = set_device_name(trigger_data, buf, size);
+
+ if (ret < 0)
+ return ret;
return size;
}
static DEVICE_ATTR_RW(device_name);
static ssize_t netdev_led_attr_show(struct device *dev, char *buf,
- enum netdev_led_attr attr)
+ enum led_trigger_netdev_modes attr)
{
struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
int bit;
switch (attr) {
- case NETDEV_ATTR_LINK:
- bit = NETDEV_LED_LINK;
- break;
- case NETDEV_ATTR_TX:
- bit = NETDEV_LED_TX;
- break;
- case NETDEV_ATTR_RX:
- bit = NETDEV_LED_RX;
+ case TRIGGER_NETDEV_LINK:
+ case TRIGGER_NETDEV_LINK_10:
+ case TRIGGER_NETDEV_LINK_100:
+ case TRIGGER_NETDEV_LINK_1000:
+ case TRIGGER_NETDEV_HALF_DUPLEX:
+ case TRIGGER_NETDEV_FULL_DUPLEX:
+ case TRIGGER_NETDEV_TX:
+ case TRIGGER_NETDEV_RX:
+ bit = attr;
break;
default:
return -EINVAL;
@@ -170,10 +300,10 @@ static ssize_t netdev_led_attr_show(struct device *dev, char *buf,
}
static ssize_t netdev_led_attr_store(struct device *dev, const char *buf,
- size_t size, enum netdev_led_attr attr)
+ size_t size, enum led_trigger_netdev_modes attr)
{
struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
- unsigned long state;
+ unsigned long state, mode = trigger_data->mode;
int ret;
int bit;
@@ -182,72 +312,62 @@ static ssize_t netdev_led_attr_store(struct device *dev, const char *buf,
return ret;
switch (attr) {
- case NETDEV_ATTR_LINK:
- bit = NETDEV_LED_LINK;
- break;
- case NETDEV_ATTR_TX:
- bit = NETDEV_LED_TX;
- break;
- case NETDEV_ATTR_RX:
- bit = NETDEV_LED_RX;
+ case TRIGGER_NETDEV_LINK:
+ case TRIGGER_NETDEV_LINK_10:
+ case TRIGGER_NETDEV_LINK_100:
+ case TRIGGER_NETDEV_LINK_1000:
+ case TRIGGER_NETDEV_HALF_DUPLEX:
+ case TRIGGER_NETDEV_FULL_DUPLEX:
+ case TRIGGER_NETDEV_TX:
+ case TRIGGER_NETDEV_RX:
+ bit = attr;
break;
default:
return -EINVAL;
}
- cancel_delayed_work_sync(&trigger_data->work);
-
if (state)
- set_bit(bit, &trigger_data->mode);
+ set_bit(bit, &mode);
else
- clear_bit(bit, &trigger_data->mode);
-
- set_baseline_state(trigger_data);
-
- return size;
-}
-
-static ssize_t link_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return netdev_led_attr_show(dev, buf, NETDEV_ATTR_LINK);
-}
-
-static ssize_t link_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_LINK);
-}
+ clear_bit(bit, &mode);
-static DEVICE_ATTR_RW(link);
-
-static ssize_t tx_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return netdev_led_attr_show(dev, buf, NETDEV_ATTR_TX);
-}
+ if (test_bit(TRIGGER_NETDEV_LINK, &mode) &&
+ (test_bit(TRIGGER_NETDEV_LINK_10, &mode) ||
+ test_bit(TRIGGER_NETDEV_LINK_100, &mode) ||
+ test_bit(TRIGGER_NETDEV_LINK_1000, &mode)))
+ return -EINVAL;
-static ssize_t tx_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_TX);
-}
+ cancel_delayed_work_sync(&trigger_data->work);
-static DEVICE_ATTR_RW(tx);
+ trigger_data->mode = mode;
+ trigger_data->hw_control = can_hw_control(trigger_data);
-static ssize_t rx_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return netdev_led_attr_show(dev, buf, NETDEV_ATTR_RX);
-}
+ set_baseline_state(trigger_data);
-static ssize_t rx_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_RX);
+ return size;
}
-static DEVICE_ATTR_RW(rx);
+#define DEFINE_NETDEV_TRIGGER(trigger_name, trigger) \
+ static ssize_t trigger_name##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+ { \
+ return netdev_led_attr_show(dev, buf, trigger); \
+ } \
+ static ssize_t trigger_name##_store(struct device *dev, \
+ struct device_attribute *attr, const char *buf, size_t size) \
+ { \
+ return netdev_led_attr_store(dev, buf, size, trigger); \
+ } \
+ static DEVICE_ATTR_RW(trigger_name)
+
+DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETDEV_LINK);
+DEFINE_NETDEV_TRIGGER(link_10, TRIGGER_NETDEV_LINK_10);
+DEFINE_NETDEV_TRIGGER(link_100, TRIGGER_NETDEV_LINK_100);
+DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1000);
+DEFINE_NETDEV_TRIGGER(half_duplex, TRIGGER_NETDEV_HALF_DUPLEX);
+DEFINE_NETDEV_TRIGGER(full_duplex, TRIGGER_NETDEV_FULL_DUPLEX);
+DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX);
+DEFINE_NETDEV_TRIGGER(rx, TRIGGER_NETDEV_RX);
static ssize_t interval_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -266,6 +386,9 @@ static ssize_t interval_store(struct device *dev,
unsigned long value;
int ret;
+ if (trigger_data->hw_control)
+ return -EINVAL;
+
ret = kstrtoul(buf, 0, &value);
if (ret)
return ret;
@@ -283,12 +406,28 @@ static ssize_t interval_store(struct device *dev,
static DEVICE_ATTR_RW(interval);
+static ssize_t offloaded_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", trigger_data->hw_control);
+}
+
+static DEVICE_ATTR_RO(offloaded);
+
static struct attribute *netdev_trig_attrs[] = {
&dev_attr_device_name.attr,
&dev_attr_link.attr,
+ &dev_attr_link_10.attr,
+ &dev_attr_link_100.attr,
+ &dev_attr_link_1000.attr,
+ &dev_attr_full_duplex.attr,
+ &dev_attr_half_duplex.attr,
&dev_attr_rx.attr,
&dev_attr_tx.attr,
&dev_attr_interval.attr,
+ &dev_attr_offloaded.attr,
NULL
};
ATTRIBUTE_GROUPS(netdev_trig);
@@ -313,14 +452,17 @@ static int netdev_trig_notify(struct notifier_block *nb,
cancel_delayed_work_sync(&trigger_data->work);
- spin_lock_bh(&trigger_data->lock);
+ mutex_lock(&trigger_data->lock);
- clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
+ trigger_data->carrier_link_up = false;
+ trigger_data->link_speed = SPEED_UNKNOWN;
+ trigger_data->duplex = DUPLEX_UNKNOWN;
switch (evt) {
case NETDEV_CHANGENAME:
+ 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;
@@ -330,14 +472,13 @@ static int netdev_trig_notify(struct notifier_block *nb,
break;
case NETDEV_UP:
case NETDEV_CHANGE:
- if (netif_carrier_ok(dev))
- set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
+ get_device_state(trigger_data);
break;
}
set_baseline_state(trigger_data);
- spin_unlock_bh(&trigger_data->lock);
+ mutex_unlock(&trigger_data->lock);
return NOTIFY_DONE;
}
@@ -360,21 +501,26 @@ static void netdev_trig_work(struct work_struct *work)
}
/* If we are not looking for RX/TX then return */
- if (!test_bit(NETDEV_LED_TX, &trigger_data->mode) &&
- !test_bit(NETDEV_LED_RX, &trigger_data->mode))
+ if (!test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) &&
+ !test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode))
return;
dev_stats = dev_get_stats(trigger_data->net_dev, &temp);
new_activity =
- (test_bit(NETDEV_LED_TX, &trigger_data->mode) ?
+ (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) ?
dev_stats->tx_packets : 0) +
- (test_bit(NETDEV_LED_RX, &trigger_data->mode) ?
+ (test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode) ?
dev_stats->rx_packets : 0);
if (trigger_data->last_activity != new_activity) {
led_stop_software_blink(trigger_data->led_cdev);
- invert = test_bit(NETDEV_LED_LINK, &trigger_data->mode);
+ invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode) ||
+ test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) ||
+ test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) ||
+ test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) ||
+ test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) ||
+ test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode);
interval = jiffies_to_msecs(
atomic_read(&trigger_data->interval));
/* base state is ON (link present) */
@@ -392,13 +538,15 @@ static void netdev_trig_work(struct work_struct *work)
static int netdev_trig_activate(struct led_classdev *led_cdev)
{
struct led_netdev_data *trigger_data;
+ unsigned long mode = 0;
+ struct device *dev;
int rc;
trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL);
if (!trigger_data)
return -ENOMEM;
- spin_lock_init(&trigger_data->lock);
+ mutex_init(&trigger_data->lock);
trigger_data->notifier.notifier_call = netdev_trig_notify;
trigger_data->notifier.priority = 10;
@@ -410,9 +558,24 @@ static int netdev_trig_activate(struct led_classdev *led_cdev)
trigger_data->device_name[0] = 0;
trigger_data->mode = 0;
- atomic_set(&trigger_data->interval, msecs_to_jiffies(50));
+ atomic_set(&trigger_data->interval, msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL));
trigger_data->last_activity = 0;
+ /* Check if hw control is active by default on the LED.
+ * Init already enabled mode in hw control.
+ */
+ if (supports_hw_control(led_cdev) &&
+ !led_cdev->hw_control_get(led_cdev, &mode)) {
+ dev = led_cdev->hw_control_get_device(led_cdev);
+ if (dev) {
+ const char *name = dev_name(dev);
+
+ set_device_name(trigger_data, name, strlen(name));
+ trigger_data->hw_control = true;
+ trigger_data->mode = mode;
+ }
+ }
+
led_set_trigger_data(led_cdev, trigger_data);
rc = register_netdevice_notifier(&trigger_data->notifier);
@@ -430,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/bcache.h b/drivers/md/bcache/bcache.h
index aebb7ef10e63..5a79bb3c272f 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -275,7 +275,7 @@ struct bcache_device {
int (*cache_miss)(struct btree *b, struct search *s,
struct bio *bio, unsigned int sectors);
- int (*ioctl)(struct bcache_device *d, fmode_t mode,
+ int (*ioctl)(struct bcache_device *d, blk_mode_t mode,
unsigned int cmd, unsigned long arg);
};
@@ -1004,11 +1004,11 @@ extern struct workqueue_struct *bch_flush_wq;
extern struct mutex bch_register_lock;
extern struct list_head bch_cache_sets;
-extern struct kobj_type bch_cached_dev_ktype;
-extern struct kobj_type bch_flash_dev_ktype;
-extern struct kobj_type bch_cache_set_ktype;
-extern struct kobj_type bch_cache_set_internal_ktype;
-extern struct kobj_type bch_cache_ktype;
+extern const struct kobj_type bch_cached_dev_ktype;
+extern const struct kobj_type bch_flash_dev_ktype;
+extern const struct kobj_type bch_cache_set_ktype;
+extern const struct kobj_type bch_cache_set_internal_ktype;
+extern const struct kobj_type bch_cache_ktype;
void bch_cached_dev_release(struct kobject *kobj);
void bch_flash_dev_release(struct kobject *kobj);
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
index 147c493a989a..fd121a61f17c 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -559,6 +559,27 @@ static void mca_data_alloc(struct btree *b, struct bkey *k, gfp_t gfp)
}
}
+#define cmp_int(l, r) ((l > r) - (l < r))
+
+#ifdef CONFIG_PROVE_LOCKING
+static int btree_lock_cmp_fn(const struct lockdep_map *_a,
+ const struct lockdep_map *_b)
+{
+ const struct btree *a = container_of(_a, struct btree, lock.dep_map);
+ const struct btree *b = container_of(_b, struct btree, lock.dep_map);
+
+ return -cmp_int(a->level, b->level) ?: bkey_cmp(&a->key, &b->key);
+}
+
+static void btree_lock_print_fn(const struct lockdep_map *map)
+{
+ const struct btree *b = container_of(map, struct btree, lock.dep_map);
+
+ printk(KERN_CONT " l=%u %llu:%llu", b->level,
+ KEY_INODE(&b->key), KEY_OFFSET(&b->key));
+}
+#endif
+
static struct btree *mca_bucket_alloc(struct cache_set *c,
struct bkey *k, gfp_t gfp)
{
@@ -572,7 +593,7 @@ static struct btree *mca_bucket_alloc(struct cache_set *c,
return NULL;
init_rwsem(&b->lock);
- lockdep_set_novalidate_class(&b->lock);
+ lock_set_cmp_fn(&b->lock, btree_lock_cmp_fn, btree_lock_print_fn);
mutex_init(&b->write_lock);
lockdep_set_novalidate_class(&b->write_lock);
INIT_LIST_HEAD(&b->list);
@@ -885,7 +906,7 @@ static struct btree *mca_cannibalize(struct cache_set *c, struct btree_op *op,
* cannibalize_bucket() will take. This means every time we unlock the root of
* the btree, we need to release this lock if we have it held.
*/
-static void bch_cannibalize_unlock(struct cache_set *c)
+void bch_cannibalize_unlock(struct cache_set *c)
{
spin_lock(&c->btree_cannibalize_lock);
if (c->btree_cache_alloc_lock == current) {
@@ -1090,10 +1111,12 @@ struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op,
struct btree *parent)
{
BKEY_PADDED(key) k;
- struct btree *b = ERR_PTR(-EAGAIN);
+ struct btree *b;
mutex_lock(&c->bucket_lock);
retry:
+ /* return ERR_PTR(-EAGAIN) when it fails */
+ b = ERR_PTR(-EAGAIN);
if (__bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, wait))
goto err;
@@ -1138,7 +1161,7 @@ static struct btree *btree_node_alloc_replacement(struct btree *b,
{
struct btree *n = bch_btree_node_alloc(b->c, op, b->level, b->parent);
- if (!IS_ERR_OR_NULL(n)) {
+ if (!IS_ERR(n)) {
mutex_lock(&n->write_lock);
bch_btree_sort_into(&b->keys, &n->keys, &b->c->sort);
bkey_copy_key(&n->key, &b->key);
@@ -1340,7 +1363,7 @@ static int btree_gc_coalesce(struct btree *b, struct btree_op *op,
memset(new_nodes, 0, sizeof(new_nodes));
closure_init_stack(&cl);
- while (nodes < GC_MERGE_NODES && !IS_ERR_OR_NULL(r[nodes].b))
+ while (nodes < GC_MERGE_NODES && !IS_ERR(r[nodes].b))
keys += r[nodes++].keys;
blocks = btree_default_blocks(b->c) * 2 / 3;
@@ -1352,7 +1375,7 @@ static int btree_gc_coalesce(struct btree *b, struct btree_op *op,
for (i = 0; i < nodes; i++) {
new_nodes[i] = btree_node_alloc_replacement(r[i].b, NULL);
- if (IS_ERR_OR_NULL(new_nodes[i]))
+ if (IS_ERR(new_nodes[i]))
goto out_nocoalesce;
}
@@ -1487,7 +1510,7 @@ out_nocoalesce:
bch_keylist_free(&keylist);
for (i = 0; i < nodes; i++)
- if (!IS_ERR_OR_NULL(new_nodes[i])) {
+ if (!IS_ERR(new_nodes[i])) {
btree_node_free(new_nodes[i]);
rw_unlock(true, new_nodes[i]);
}
@@ -1669,7 +1692,7 @@ static int bch_btree_gc_root(struct btree *b, struct btree_op *op,
if (should_rewrite) {
n = btree_node_alloc_replacement(b, NULL);
- if (!IS_ERR_OR_NULL(n)) {
+ if (!IS_ERR(n)) {
bch_btree_node_write_sync(n);
bch_btree_set_root(n);
@@ -1968,6 +1991,15 @@ static int bch_btree_check_thread(void *arg)
c->gc_stats.nodes++;
bch_btree_op_init(&op, 0);
ret = bcache_btree(check_recurse, p, c->root, &op);
+ /*
+ * The op may be added to cache_set's btree_cache_wait
+ * in mca_cannibalize(), must ensure it is removed from
+ * the list and release btree_cache_alloc_lock before
+ * free op memory.
+ * Otherwise, the btree_cache_wait will be damaged.
+ */
+ bch_cannibalize_unlock(c);
+ finish_wait(&c->btree_cache_wait, &(&op)->wait);
if (ret)
goto out;
}
diff --git a/drivers/md/bcache/btree.h b/drivers/md/bcache/btree.h
index 1b5fdbc0d83e..45d64b54115a 100644
--- a/drivers/md/bcache/btree.h
+++ b/drivers/md/bcache/btree.h
@@ -247,8 +247,8 @@ static inline void bch_btree_op_init(struct btree_op *op, int write_lock_level)
static inline void rw_lock(bool w, struct btree *b, int level)
{
- w ? down_write_nested(&b->lock, level + 1)
- : down_read_nested(&b->lock, level + 1);
+ w ? down_write(&b->lock)
+ : down_read(&b->lock);
if (w)
b->seq++;
}
@@ -282,6 +282,7 @@ void bch_initial_gc_finish(struct cache_set *c);
void bch_moving_gc(struct cache_set *c);
int bch_btree_check(struct cache_set *c);
void bch_initial_mark_key(struct cache_set *c, int level, struct bkey *k);
+void bch_cannibalize_unlock(struct cache_set *c);
static inline void wake_up_gc(struct cache_set *c)
{
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index 67a2e29e0b40..a9b1f3896249 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -1228,7 +1228,7 @@ void cached_dev_submit_bio(struct bio *bio)
detached_dev_do_request(d, bio, orig_bdev, start_time);
}
-static int cached_dev_ioctl(struct bcache_device *d, fmode_t mode,
+static int cached_dev_ioctl(struct bcache_device *d, blk_mode_t mode,
unsigned int cmd, unsigned long arg)
{
struct cached_dev *dc = container_of(d, struct cached_dev, disk);
@@ -1318,7 +1318,7 @@ void flash_dev_submit_bio(struct bio *bio)
continue_at(cl, search_free, NULL);
}
-static int flash_dev_ioctl(struct bcache_device *d, fmode_t mode,
+static int flash_dev_ioctl(struct bcache_device *d, blk_mode_t mode,
unsigned int cmd, unsigned long arg)
{
return -ENOTTY;
diff --git a/drivers/md/bcache/stats.h b/drivers/md/bcache/stats.h
index bd3afc856d53..21b445f8af15 100644
--- a/drivers/md/bcache/stats.h
+++ b/drivers/md/bcache/stats.h
@@ -18,7 +18,6 @@ struct cache_stats {
unsigned long cache_misses;
unsigned long cache_bypass_hits;
unsigned long cache_bypass_misses;
- unsigned long cache_readaheads;
unsigned long cache_miss_collisions;
unsigned long sectors_bypassed;
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 7e9d19fd21dd..0ae2b3676293 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -732,9 +732,9 @@ out:
/* Bcache device */
-static int open_dev(struct block_device *b, fmode_t mode)
+static int open_dev(struct gendisk *disk, blk_mode_t mode)
{
- struct bcache_device *d = b->bd_disk->private_data;
+ struct bcache_device *d = disk->private_data;
if (test_bit(BCACHE_DEV_CLOSING, &d->flags))
return -ENXIO;
@@ -743,14 +743,14 @@ static int open_dev(struct block_device *b, fmode_t mode)
return 0;
}
-static void release_dev(struct gendisk *b, fmode_t mode)
+static void release_dev(struct gendisk *b)
{
struct bcache_device *d = b->private_data;
closure_put(&d->cl);
}
-static int ioctl_dev(struct block_device *b, fmode_t mode,
+static int ioctl_dev(struct block_device *b, blk_mode_t mode,
unsigned int cmd, unsigned long arg)
{
struct bcache_device *d = b->bd_disk->private_data;
@@ -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, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+ 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))
@@ -1723,7 +1722,7 @@ static void cache_set_flush(struct closure *cl)
if (!IS_ERR_OR_NULL(c->gc_thread))
kthread_stop(c->gc_thread);
- if (!IS_ERR_OR_NULL(c->root))
+ if (!IS_ERR(c->root))
list_add(&c->root->list, &c->btree_cache);
/*
@@ -2087,7 +2086,7 @@ static int run_cache_set(struct cache_set *c)
err = "cannot allocate new btree root";
c->root = __bch_btree_node_alloc(c, NULL, 0, true, NULL);
- if (IS_ERR_OR_NULL(c->root))
+ if (IS_ERR(c->root))
goto err;
mutex_lock(&c->root->write_lock);
@@ -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, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+ 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, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+ 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, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
- 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, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
- 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,11 +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),
- FMODE_READ|FMODE_WRITE|FMODE_EXCL,
- sb);
+ 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);
@@ -2572,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) {
@@ -2596,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, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+ if (bdev)
+ blkdev_put(bdev, holder);
out_free_sb:
kfree(sb);
out_free_path:
@@ -2657,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/bcache/sysfs.c b/drivers/md/bcache/sysfs.c
index c6f677059214..0e2c1880f60b 100644
--- a/drivers/md/bcache/sysfs.c
+++ b/drivers/md/bcache/sysfs.c
@@ -1111,26 +1111,25 @@ SHOW(__bch_cache)
vfree(p);
- ret = scnprintf(buf, PAGE_SIZE,
- "Unused: %zu%%\n"
- "Clean: %zu%%\n"
- "Dirty: %zu%%\n"
- "Metadata: %zu%%\n"
- "Average: %llu\n"
- "Sectors per Q: %zu\n"
- "Quantiles: [",
- unused * 100 / (size_t) ca->sb.nbuckets,
- available * 100 / (size_t) ca->sb.nbuckets,
- dirty * 100 / (size_t) ca->sb.nbuckets,
- meta * 100 / (size_t) ca->sb.nbuckets, sum,
- n * ca->sb.bucket_size / (ARRAY_SIZE(q) + 1));
+ ret = sysfs_emit(buf,
+ "Unused: %zu%%\n"
+ "Clean: %zu%%\n"
+ "Dirty: %zu%%\n"
+ "Metadata: %zu%%\n"
+ "Average: %llu\n"
+ "Sectors per Q: %zu\n"
+ "Quantiles: [",
+ unused * 100 / (size_t) ca->sb.nbuckets,
+ available * 100 / (size_t) ca->sb.nbuckets,
+ dirty * 100 / (size_t) ca->sb.nbuckets,
+ meta * 100 / (size_t) ca->sb.nbuckets, sum,
+ n * ca->sb.bucket_size / (ARRAY_SIZE(q) + 1));
for (i = 0; i < ARRAY_SIZE(q); i++)
- ret += scnprintf(buf + ret, PAGE_SIZE - ret,
- "%u ", q[i]);
+ ret += sysfs_emit_at(buf, ret, "%u ", q[i]);
ret--;
- ret += scnprintf(buf + ret, PAGE_SIZE - ret, "]\n");
+ ret += sysfs_emit_at(buf, ret, "]\n");
return ret;
}
diff --git a/drivers/md/bcache/sysfs.h b/drivers/md/bcache/sysfs.h
index a2ff6447b699..65b8bd975ab1 100644
--- a/drivers/md/bcache/sysfs.h
+++ b/drivers/md/bcache/sysfs.h
@@ -3,7 +3,7 @@
#define _BCACHE_SYSFS_H_
#define KTYPE(type) \
-struct kobj_type type ## _ktype = { \
+const struct kobj_type type ## _ktype = { \
.release = type ## _release, \
.sysfs_ops = &((const struct sysfs_ops) { \
.show = type ## _show, \
diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
index d4a5fc0650bb..24c049067f61 100644
--- a/drivers/md/bcache/writeback.c
+++ b/drivers/md/bcache/writeback.c
@@ -890,6 +890,16 @@ static int bch_root_node_dirty_init(struct cache_set *c,
if (ret < 0)
pr_warn("sectors dirty init failed, ret=%d!\n", ret);
+ /*
+ * The op may be added to cache_set's btree_cache_wait
+ * in mca_cannibalize(), must ensure it is removed from
+ * the list and release btree_cache_alloc_lock before
+ * free op memory.
+ * Otherwise, the btree_cache_wait will be damaged.
+ */
+ bch_cannibalize_unlock(c);
+ finish_wait(&c->btree_cache_wait, &(&op.op)->wait);
+
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-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c
index 493a8715dc8f..8bd2ad743d9a 100644
--- a/drivers/md/dm-cache-policy-smq.c
+++ b/drivers/md/dm-cache-policy-smq.c
@@ -857,7 +857,13 @@ struct smq_policy {
struct background_tracker *bg_work;
- bool migrations_allowed;
+ bool migrations_allowed:1;
+
+ /*
+ * If this is set the policy will try and clean the whole cache
+ * even if the device is not idle.
+ */
+ bool cleaner:1;
};
/*----------------------------------------------------------------*/
@@ -1138,7 +1144,7 @@ static bool clean_target_met(struct smq_policy *mq, bool idle)
* Cache entries may not be populated. So we cannot rely on the
* size of the clean queue.
*/
- if (idle) {
+ if (idle || mq->cleaner) {
/*
* We'd like to clean everything.
*/
@@ -1722,11 +1728,9 @@ static void calc_hotspot_params(sector_t origin_size,
*hotspot_block_size /= 2u;
}
-static struct dm_cache_policy *__smq_create(dm_cblock_t cache_size,
- sector_t origin_size,
- sector_t cache_block_size,
- bool mimic_mq,
- bool migrations_allowed)
+static struct dm_cache_policy *
+__smq_create(dm_cblock_t cache_size, sector_t origin_size, sector_t cache_block_size,
+ bool mimic_mq, bool migrations_allowed, bool cleaner)
{
unsigned int i;
unsigned int nr_sentinels_per_queue = 2u * NR_CACHE_LEVELS;
@@ -1813,6 +1817,7 @@ static struct dm_cache_policy *__smq_create(dm_cblock_t cache_size,
goto bad_btracker;
mq->migrations_allowed = migrations_allowed;
+ mq->cleaner = cleaner;
return &mq->policy;
@@ -1836,21 +1841,24 @@ static struct dm_cache_policy *smq_create(dm_cblock_t cache_size,
sector_t origin_size,
sector_t cache_block_size)
{
- return __smq_create(cache_size, origin_size, cache_block_size, false, true);
+ return __smq_create(cache_size, origin_size, cache_block_size,
+ false, true, false);
}
static struct dm_cache_policy *mq_create(dm_cblock_t cache_size,
sector_t origin_size,
sector_t cache_block_size)
{
- return __smq_create(cache_size, origin_size, cache_block_size, true, true);
+ return __smq_create(cache_size, origin_size, cache_block_size,
+ true, true, false);
}
static struct dm_cache_policy *cleaner_create(dm_cblock_t cache_size,
sector_t origin_size,
sector_t cache_block_size)
{
- return __smq_create(cache_size, origin_size, cache_block_size, false, false);
+ return __smq_create(cache_size, origin_size, cache_block_size,
+ false, false, true);
}
/*----------------------------------------------------------------*/
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index 872896218550..911f73f7ebba 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -2051,8 +2051,8 @@ static int parse_metadata_dev(struct cache_args *ca, struct dm_arg_set *as,
if (!at_least_one_arg(as, error))
return -EINVAL;
- r = dm_get_device(ca->ti, dm_shift_arg(as), FMODE_READ | FMODE_WRITE,
- &ca->metadata_dev);
+ r = dm_get_device(ca->ti, dm_shift_arg(as),
+ BLK_OPEN_READ | BLK_OPEN_WRITE, &ca->metadata_dev);
if (r) {
*error = "Error opening metadata device";
return r;
@@ -2074,8 +2074,8 @@ static int parse_cache_dev(struct cache_args *ca, struct dm_arg_set *as,
if (!at_least_one_arg(as, error))
return -EINVAL;
- r = dm_get_device(ca->ti, dm_shift_arg(as), FMODE_READ | FMODE_WRITE,
- &ca->cache_dev);
+ r = dm_get_device(ca->ti, dm_shift_arg(as),
+ BLK_OPEN_READ | BLK_OPEN_WRITE, &ca->cache_dev);
if (r) {
*error = "Error opening cache device";
return r;
@@ -2093,8 +2093,8 @@ static int parse_origin_dev(struct cache_args *ca, struct dm_arg_set *as,
if (!at_least_one_arg(as, error))
return -EINVAL;
- r = dm_get_device(ca->ti, dm_shift_arg(as), FMODE_READ | FMODE_WRITE,
- &ca->origin_dev);
+ r = dm_get_device(ca->ti, dm_shift_arg(as),
+ BLK_OPEN_READ | BLK_OPEN_WRITE, &ca->origin_dev);
if (r) {
*error = "Error opening origin device";
return r;
diff --git a/drivers/md/dm-clone-target.c b/drivers/md/dm-clone-target.c
index f467cdb5a022..94b2fc33f64b 100644
--- a/drivers/md/dm-clone-target.c
+++ b/drivers/md/dm-clone-target.c
@@ -1683,8 +1683,8 @@ static int parse_metadata_dev(struct clone *clone, struct dm_arg_set *as, char *
int r;
sector_t metadata_dev_size;
- r = dm_get_device(clone->ti, dm_shift_arg(as), FMODE_READ | FMODE_WRITE,
- &clone->metadata_dev);
+ r = dm_get_device(clone->ti, dm_shift_arg(as),
+ BLK_OPEN_READ | BLK_OPEN_WRITE, &clone->metadata_dev);
if (r) {
*error = "Error opening metadata device";
return r;
@@ -1703,8 +1703,8 @@ static int parse_dest_dev(struct clone *clone, struct dm_arg_set *as, char **err
int r;
sector_t dest_dev_size;
- r = dm_get_device(clone->ti, dm_shift_arg(as), FMODE_READ | FMODE_WRITE,
- &clone->dest_dev);
+ r = dm_get_device(clone->ti, dm_shift_arg(as),
+ BLK_OPEN_READ | BLK_OPEN_WRITE, &clone->dest_dev);
if (r) {
*error = "Error opening destination device";
return r;
@@ -1725,7 +1725,7 @@ static int parse_source_dev(struct clone *clone, struct dm_arg_set *as, char **e
int r;
sector_t source_dev_size;
- r = dm_get_device(clone->ti, dm_shift_arg(as), FMODE_READ,
+ r = dm_get_device(clone->ti, dm_shift_arg(as), BLK_OPEN_READ,
&clone->source_dev);
if (r) {
*error = "Error opening source device";
diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h
index aecab0c0720f..0d93661f88d3 100644
--- a/drivers/md/dm-core.h
+++ b/drivers/md/dm-core.h
@@ -207,11 +207,10 @@ struct dm_table {
unsigned integrity_added:1;
/*
- * Indicates the rw permissions for the new logical
- * device. This should be a combination of FMODE_READ
- * and FMODE_WRITE.
+ * Indicates the rw permissions for the new logical device. This
+ * should be a combination of BLK_OPEN_READ and BLK_OPEN_WRITE.
*/
- fmode_t mode;
+ blk_mode_t mode;
/* a list of devices used by this table */
struct list_head devices;
@@ -307,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 8b47b913ee83..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,20 +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 */
@@ -1713,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);
+ }
}
}
@@ -2888,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;
}
}
@@ -3256,7 +3283,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
cc->per_bio_data_size = ti->per_io_data_size =
ALIGN(sizeof(struct dm_crypt_io) + cc->dmreq_start + additional_req_size,
- ARCH_KMALLOC_MINALIGN);
+ ARCH_DMA_MINALIGN);
ret = mempool_init(&cc->page_pool, BIO_MAX_VECS, crypt_page_alloc, crypt_page_free, cc);
if (ret) {
diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c
index 0d70914217ee..6acfa5bf97a4 100644
--- a/drivers/md/dm-era-target.c
+++ b/drivers/md/dm-era-target.c
@@ -1482,14 +1482,16 @@ static int era_ctr(struct dm_target *ti, unsigned int argc, char **argv)
era->ti = ti;
- r = dm_get_device(ti, argv[0], FMODE_READ | FMODE_WRITE, &era->metadata_dev);
+ r = dm_get_device(ti, argv[0], BLK_OPEN_READ | BLK_OPEN_WRITE,
+ &era->metadata_dev);
if (r) {
ti->error = "Error opening metadata device";
era_destroy(era);
return -EINVAL;
}
- r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &era->origin_dev);
+ r = dm_get_device(ti, argv[1], BLK_OPEN_READ | BLK_OPEN_WRITE,
+ &era->origin_dev);
if (r) {
ti->error = "Error opening data device";
era_destroy(era);
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-init.c b/drivers/md/dm-init.c
index d369457dbed0..2a71bcdba92d 100644
--- a/drivers/md/dm-init.c
+++ b/drivers/md/dm-init.c
@@ -293,8 +293,10 @@ static int __init dm_init_init(void)
for (i = 0; i < ARRAY_SIZE(waitfor); i++) {
if (waitfor[i]) {
+ dev_t dev;
+
DMINFO("waiting for device %s ...", waitfor[i]);
- while (!dm_get_dev_t(waitfor[i]))
+ while (early_lookup_bdev(waitfor[i], &dev))
fsleep(5000);
}
}
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index 31838b13ea54..97a8d5fc9ebb 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,27 @@ 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);
+ recalc_buffer = NULL;
+ goto oom;
+ }
DEBUG_print("start recalculation... (position %llx)\n", le64_to_cpu(ic->sb->recalc_sector));
@@ -2693,7 +2700,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 +2742,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 +2755,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 +2791,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)
@@ -4268,10 +4279,10 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned int argc, char **argv
}
/*
- * If this workqueue were percpu, it would cause bio reordering
+ * If this workqueue weren't ordered, it would cause bio reordering
* and reduced performance.
*/
- ic->wait_wq = alloc_workqueue("dm-integrity-wait", WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+ ic->wait_wq = alloc_ordered_workqueue("dm-integrity-wait", WQ_MEM_RECLAIM);
if (!ic->wait_wq) {
ti->error = "Cannot allocate workqueue";
r = -ENOMEM;
@@ -4454,8 +4465,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 +4472,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 +4615,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 7d5c9c582ed2..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;
}
@@ -861,7 +868,7 @@ static void __dev_status(struct mapped_device *md, struct dm_ioctl *param)
table = dm_get_inactive_table(md, &srcu_idx);
if (table) {
- if (!(dm_table_get_mode(table) & FMODE_WRITE))
+ if (!(dm_table_get_mode(table) & BLK_OPEN_WRITE))
param->flags |= DM_READONLY_FLAG;
param->target_count = table->num_targets;
}
@@ -1189,7 +1196,7 @@ static int do_resume(struct dm_ioctl *param)
if (old_size && new_size && old_size != new_size)
need_resize_uevent = true;
- if (dm_table_get_mode(new_map) & FMODE_WRITE)
+ if (dm_table_get_mode(new_map) & BLK_OPEN_WRITE)
set_disk_ro(dm_disk(md), 0);
else
set_disk_ro(dm_disk(md), 1);
@@ -1378,26 +1385,48 @@ static int dev_arm_poll(struct file *filp, struct dm_ioctl *param, size_t param_
return 0;
}
-static inline fmode_t get_mode(struct dm_ioctl *param)
+static inline blk_mode_t get_mode(struct dm_ioctl *param)
{
- fmode_t mode = FMODE_READ | FMODE_WRITE;
+ blk_mode_t mode = BLK_OPEN_READ | BLK_OPEN_WRITE;
if (param->flags & DM_READONLY_FLAG)
- mode = FMODE_READ;
+ mode = BLK_OPEN_READ;
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-raid.c b/drivers/md/dm-raid.c
index c8821fcb8299..becdb689190e 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -3251,8 +3251,7 @@ size_check:
r = md_start(&rs->md);
if (r) {
ti->error = "Failed to start raid array";
- mddev_unlock(&rs->md);
- goto bad_md_start;
+ goto bad_unlock;
}
/* If raid4/5/6 journal mode explicitly requested (only possible with journal dev) -> set it */
@@ -3260,8 +3259,7 @@ size_check:
r = r5c_journal_mode_set(&rs->md, rs->journal_dev.mode);
if (r) {
ti->error = "Failed to set raid4/5/6 journal mode";
- mddev_unlock(&rs->md);
- goto bad_journal_mode_set;
+ goto bad_unlock;
}
}
@@ -3272,14 +3270,14 @@ size_check:
if (rs_is_raid456(rs)) {
r = rs_set_raid456_stripe_cache(rs);
if (r)
- goto bad_stripe_cache;
+ goto bad_unlock;
}
/* Now do an early reshape check */
if (test_bit(RT_FLAG_RESHAPE_RS, &rs->runtime_flags)) {
r = rs_check_reshape(rs);
if (r)
- goto bad_check_reshape;
+ goto bad_unlock;
/* Restore new, ctr requested layout to perform check */
rs_config_restore(rs, &rs_layout);
@@ -3288,7 +3286,7 @@ size_check:
r = rs->md.pers->check_reshape(&rs->md);
if (r) {
ti->error = "Reshape check failed";
- goto bad_check_reshape;
+ goto bad_unlock;
}
}
}
@@ -3299,11 +3297,9 @@ size_check:
mddev_unlock(&rs->md);
return 0;
-bad_md_start:
-bad_journal_mode_set:
-bad_stripe_cache:
-bad_check_reshape:
+bad_unlock:
md_stop(&rs->md);
+ mddev_unlock(&rs->md);
bad:
raid_set_free(rs);
@@ -3314,7 +3310,9 @@ static void raid_dtr(struct dm_target *ti)
{
struct raid_set *rs = ti->private;
+ mddev_lock_nointr(&rs->md);
md_stop(&rs->md);
+ mddev_unlock(&rs->md);
raid_set_free(rs);
}
@@ -3750,11 +3748,11 @@ static int raid_message(struct dm_target *ti, unsigned int argc, char **argv,
* canceling read-auto mode
*/
mddev->ro = 0;
- if (!mddev->suspended && mddev->sync_thread)
+ if (!mddev->suspended)
md_wakeup_thread(mddev->sync_thread);
}
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
- if (!mddev->suspended && mddev->thread)
+ if (!mddev->suspended)
md_wakeup_thread(mddev->thread);
return 0;
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 9c49f53760d0..bf7a574499a3 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -1241,9 +1241,8 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
int i;
int r = -EINVAL;
char *origin_path, *cow_path;
- dev_t origin_dev, cow_dev;
unsigned int args_used, num_flush_bios = 1;
- fmode_t origin_mode = FMODE_READ;
+ blk_mode_t origin_mode = BLK_OPEN_READ;
if (argc < 4) {
ti->error = "requires 4 or more arguments";
@@ -1253,7 +1252,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
if (dm_target_is_snapshot_merge(ti)) {
num_flush_bios = 2;
- origin_mode = FMODE_WRITE;
+ origin_mode = BLK_OPEN_WRITE;
}
s = kzalloc(sizeof(*s), GFP_KERNEL);
@@ -1279,24 +1278,21 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
ti->error = "Cannot get origin device";
goto bad_origin;
}
- origin_dev = s->origin->bdev->bd_dev;
cow_path = argv[0];
argv++;
argc--;
- cow_dev = dm_get_dev_t(cow_path);
- if (cow_dev && cow_dev == origin_dev) {
- ti->error = "COW device cannot be the same as origin device";
- r = -EINVAL;
- goto bad_cow;
- }
-
r = dm_get_device(ti, cow_path, dm_table_get_mode(ti->table), &s->cow);
if (r) {
ti->error = "Cannot get COW device";
goto bad_cow;
}
+ if (s->cow->bdev && s->cow->bdev == s->origin->bdev) {
+ ti->error = "COW device cannot be the same as origin device";
+ r = -EINVAL;
+ goto bad_store;
+ }
r = dm_exception_store_create(ti, argc, argv, s, &args_used, &s->store);
if (r) {
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 1398f1d6e83e..7d208b2b1a19 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -126,7 +126,7 @@ static int alloc_targets(struct dm_table *t, unsigned int num)
return 0;
}
-int dm_table_create(struct dm_table **result, fmode_t mode,
+int dm_table_create(struct dm_table **result, blk_mode_t mode,
unsigned int num_targets, struct mapped_device *md)
{
struct dm_table *t = kzalloc(sizeof(*t), GFP_KERNEL);
@@ -304,7 +304,7 @@ static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev,
* device and not to touch the existing bdev field in case
* it is accessed concurrently.
*/
-static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode,
+static int upgrade_mode(struct dm_dev_internal *dd, blk_mode_t new_mode,
struct mapped_device *md)
{
int r;
@@ -324,23 +324,13 @@ static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode,
}
/*
- * Convert the path to a device
- */
-dev_t dm_get_dev_t(const char *path)
-{
- dev_t dev;
-
- if (lookup_bdev(path, &dev))
- dev = name_to_dev_t(path);
- return dev;
-}
-EXPORT_SYMBOL_GPL(dm_get_dev_t);
-
-/*
* Add a device to the list, or just increment the usage count if
* it's already present.
+ *
+ * Note: the __ref annotation is because this function can call the __init
+ * marked early_lookup_bdev when called during early boot code from dm-init.c.
*/
-int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
+int __ref dm_get_device(struct dm_target *ti, const char *path, blk_mode_t mode,
struct dm_dev **result)
{
int r;
@@ -358,9 +348,13 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
if (MAJOR(dev) != major || MINOR(dev) != minor)
return -EOVERFLOW;
} else {
- dev = dm_get_dev_t(path);
- if (!dev)
- return -ENODEV;
+ r = lookup_bdev(path, &dev);
+#ifndef MODULE
+ if (r && system_state < SYSTEM_RUNNING)
+ r = early_lookup_bdev(path, &dev);
+#endif
+ if (r)
+ return r;
}
if (dev == disk_devt(t->md->disk))
return -EINVAL;
@@ -668,7 +662,8 @@ int dm_table_add_target(struct dm_table *t, const char *type,
t->singleton = true;
}
- if (dm_target_always_writeable(ti->type) && !(t->mode & FMODE_WRITE)) {
+ if (dm_target_always_writeable(ti->type) &&
+ !(t->mode & BLK_OPEN_WRITE)) {
ti->error = "target type may not be included in a read-only table";
goto bad;
}
@@ -2039,7 +2034,7 @@ struct list_head *dm_table_get_devices(struct dm_table *t)
return &t->devices;
}
-fmode_t dm_table_get_mode(struct dm_table *t)
+blk_mode_t dm_table_get_mode(struct dm_table *t)
{
return t->mode;
}
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 39410bf186cf..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;
@@ -3300,7 +3295,7 @@ static int pool_ctr(struct dm_target *ti, unsigned int argc, char **argv)
unsigned long block_size;
dm_block_t low_water_blocks;
struct dm_dev *metadata_dev;
- fmode_t metadata_mode;
+ blk_mode_t metadata_mode;
/*
* FIXME Remove validation from scope of lock.
@@ -3333,7 +3328,8 @@ static int pool_ctr(struct dm_target *ti, unsigned int argc, char **argv)
if (r)
goto out_unlock;
- metadata_mode = FMODE_READ | ((pf.mode == PM_READ_ONLY) ? 0 : FMODE_WRITE);
+ metadata_mode = BLK_OPEN_READ |
+ ((pf.mode == PM_READ_ONLY) ? 0 : BLK_OPEN_WRITE);
r = dm_get_device(ti, argv[0], metadata_mode, &metadata_dev);
if (r) {
ti->error = "Error opening metadata block device";
@@ -3341,7 +3337,7 @@ static int pool_ctr(struct dm_target *ti, unsigned int argc, char **argv)
}
warn_if_metadata_device_too_big(metadata_dev->bdev);
- r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev);
+ r = dm_get_device(ti, argv[1], BLK_OPEN_READ | BLK_OPEN_WRITE, &data_dev);
if (r) {
ti->error = "Error getting data device";
goto out_metadata;
@@ -3445,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;
@@ -3454,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)
@@ -4098,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 = {
@@ -4222,7 +4217,7 @@ static int thin_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad_origin_dev;
}
- r = dm_get_device(ti, argv[2], FMODE_READ, &origin_dev);
+ r = dm_get_device(ti, argv[2], BLK_OPEN_READ, &origin_dev);
if (r) {
ti->error = "Error opening origin device";
goto bad_origin_dev;
@@ -4496,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-verity-fec.c b/drivers/md/dm-verity-fec.c
index a9ee2faa75a2..3ef9f018da60 100644
--- a/drivers/md/dm-verity-fec.c
+++ b/drivers/md/dm-verity-fec.c
@@ -607,7 +607,7 @@ int verity_fec_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
(*argc)--;
if (!strcasecmp(arg_name, DM_VERITY_OPT_FEC_DEV)) {
- r = dm_get_device(ti, arg_value, FMODE_READ, &v->fec->dev);
+ r = dm_get_device(ti, arg_value, BLK_OPEN_READ, &v->fec->dev);
if (r) {
ti->error = "FEC device lookup failed";
return r;
diff --git a/drivers/md/dm-verity-loadpin.c b/drivers/md/dm-verity-loadpin.c
index 4f78cc55c251..0666699b6858 100644
--- a/drivers/md/dm-verity-loadpin.c
+++ b/drivers/md/dm-verity-loadpin.c
@@ -58,6 +58,9 @@ bool dm_verity_loadpin_is_bdev_trusted(struct block_device *bdev)
int srcu_idx;
bool trusted = false;
+ if (bdev == NULL)
+ return false;
+
if (list_empty(&dm_verity_loadpin_trusted_root_digests))
return false;
diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
index e35c16e06d06..26adcfea0302 100644
--- a/drivers/md/dm-verity-target.c
+++ b/drivers/md/dm-verity-target.c
@@ -1196,7 +1196,7 @@ static int verity_ctr(struct dm_target *ti, unsigned int argc, char **argv)
if (r)
goto bad;
- if ((dm_table_get_mode(ti->table) & ~FMODE_READ)) {
+ if ((dm_table_get_mode(ti->table) & ~BLK_OPEN_READ)) {
ti->error = "Device must be readonly";
r = -EINVAL;
goto bad;
@@ -1225,13 +1225,13 @@ static int verity_ctr(struct dm_target *ti, unsigned int argc, char **argv)
}
v->version = num;
- r = dm_get_device(ti, argv[1], FMODE_READ, &v->data_dev);
+ r = dm_get_device(ti, argv[1], BLK_OPEN_READ, &v->data_dev);
if (r) {
ti->error = "Data device lookup failed";
goto bad;
}
- r = dm_get_device(ti, argv[2], FMODE_READ, &v->hash_dev);
+ r = dm_get_device(ti, argv[2], BLK_OPEN_READ, &v->hash_dev);
if (r) {
ti->error = "Hash device lookup failed";
goto bad;
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-zoned-metadata.c b/drivers/md/dm-zoned-metadata.c
index 8f0896a6990b..9d3cca8e3dc9 100644
--- a/drivers/md/dm-zoned-metadata.c
+++ b/drivers/md/dm-zoned-metadata.c
@@ -577,7 +577,7 @@ static struct dmz_mblock *dmz_get_mblock_slow(struct dmz_metadata *zmd,
bio->bi_iter.bi_sector = dmz_blk2sect(block);
bio->bi_private = mblk;
bio->bi_end_io = dmz_mblock_bio_end_io;
- bio_add_page(bio, mblk->page, DMZ_BLOCK_SIZE, 0);
+ __bio_add_page(bio, mblk->page, DMZ_BLOCK_SIZE, 0);
submit_bio(bio);
return mblk;
@@ -728,7 +728,7 @@ static int dmz_write_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk,
bio->bi_iter.bi_sector = dmz_blk2sect(block);
bio->bi_private = mblk;
bio->bi_end_io = dmz_mblock_bio_end_io;
- bio_add_page(bio, mblk->page, DMZ_BLOCK_SIZE, 0);
+ __bio_add_page(bio, mblk->page, DMZ_BLOCK_SIZE, 0);
submit_bio(bio);
return 0;
@@ -752,7 +752,7 @@ static int dmz_rdwr_block(struct dmz_dev *dev, enum req_op op,
bio = bio_alloc(dev->bdev, 1, op | REQ_SYNC | REQ_META | REQ_PRIO,
GFP_NOIO);
bio->bi_iter.bi_sector = dmz_blk2sect(block);
- bio_add_page(bio, page, DMZ_BLOCK_SIZE, 0);
+ __bio_add_page(bio, page, DMZ_BLOCK_SIZE, 0);
ret = submit_bio_wait(bio);
bio_put(bio);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index fffb0cbe2ac8..f0f118ab20fa 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -207,7 +207,7 @@ static int __init local_init(void)
if (r)
return r;
- deferred_remove_workqueue = alloc_workqueue("kdmremove", WQ_UNBOUND, 1);
+ deferred_remove_workqueue = alloc_ordered_workqueue("kdmremove", 0);
if (!deferred_remove_workqueue) {
r = -ENOMEM;
goto out_uevent_exit;
@@ -310,13 +310,13 @@ int dm_deleting_md(struct mapped_device *md)
return test_bit(DMF_DELETING, &md->flags);
}
-static int dm_blk_open(struct block_device *bdev, fmode_t mode)
+static int dm_blk_open(struct gendisk *disk, blk_mode_t mode)
{
struct mapped_device *md;
spin_lock(&_minor_lock);
- md = bdev->bd_disk->private_data;
+ md = disk->private_data;
if (!md)
goto out;
@@ -334,7 +334,7 @@ out:
return md ? 0 : -ENXIO;
}
-static void dm_blk_close(struct gendisk *disk, fmode_t mode)
+static void dm_blk_close(struct gendisk *disk)
{
struct mapped_device *md;
@@ -448,7 +448,7 @@ static void dm_unprepare_ioctl(struct mapped_device *md, int srcu_idx)
dm_put_live_table(md, srcu_idx);
}
-static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
+static int dm_blk_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long arg)
{
struct mapped_device *md = bdev->bd_disk->private_data;
@@ -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;
@@ -734,7 +739,7 @@ static char *_dm_claim_ptr = "I belong to device-mapper";
* Open a table device so we can use it as a map destination.
*/
static struct table_device *open_table_device(struct mapped_device *md,
- dev_t dev, fmode_t mode)
+ dev_t dev, blk_mode_t mode)
{
struct table_device *td;
struct block_device *bdev;
@@ -746,7 +751,7 @@ static struct table_device *open_table_device(struct mapped_device *md,
return ERR_PTR(-ENOMEM);
refcount_set(&td->count, 1);
- bdev = blkdev_get_by_dev(dev, mode | FMODE_EXCL, _dm_claim_ptr);
+ bdev = blkdev_get_by_dev(dev, mode, _dm_claim_ptr, NULL);
if (IS_ERR(bdev)) {
r = PTR_ERR(bdev);
goto out_free_td;
@@ -771,7 +776,7 @@ static struct table_device *open_table_device(struct mapped_device *md,
return td;
out_blkdev_put:
- blkdev_put(bdev, mode | FMODE_EXCL);
+ blkdev_put(bdev, _dm_claim_ptr);
out_free_td:
kfree(td);
return ERR_PTR(r);
@@ -784,14 +789,14 @@ static void close_table_device(struct table_device *td, struct mapped_device *md
{
if (md->disk->slave_dir)
bd_unlink_disk_holder(td->dm_dev.bdev, md->disk);
- blkdev_put(td->dm_dev.bdev, td->dm_dev.mode | FMODE_EXCL);
+ blkdev_put(td->dm_dev.bdev, _dm_claim_ptr);
put_dax(td->dm_dev.dax_dev);
list_del(&td->list);
kfree(td);
}
static struct table_device *find_table_device(struct list_head *l, dev_t dev,
- fmode_t mode)
+ blk_mode_t mode)
{
struct table_device *td;
@@ -802,7 +807,7 @@ static struct table_device *find_table_device(struct list_head *l, dev_t dev,
return NULL;
}
-int dm_get_table_device(struct mapped_device *md, dev_t dev, fmode_t mode,
+int dm_get_table_device(struct mapped_device *md, dev_t dev, blk_mode_t mode,
struct dm_dev **result)
{
struct table_device *td;
@@ -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 a856e0aee73b..f682295af91f 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -203,16 +203,13 @@ int dm_open_count(struct mapped_device *md);
int dm_lock_for_deletion(struct mapped_device *md, bool mark_deferred, bool only_deferred);
int dm_cancel_deferred_remove(struct mapped_device *md);
int dm_request_based(struct mapped_device *md);
-int dm_get_table_device(struct mapped_device *md, dev_t dev, fmode_t mode,
+int dm_get_table_device(struct mapped_device *md, dev_t dev, blk_mode_t mode,
struct dm_dev **result);
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-autodetect.c b/drivers/md/md-autodetect.c
index 91836e6de326..6eaa0eab40f9 100644
--- a/drivers/md/md-autodetect.c
+++ b/drivers/md/md-autodetect.c
@@ -147,7 +147,8 @@ static void __init md_setup_drive(struct md_setup_args *args)
if (p)
*p++ = 0;
- dev = name_to_dev_t(devname);
+ if (early_lookup_bdev(devname, &dev))
+ dev = 0;
if (strncmp(devname, "/dev/", 5) == 0)
devname += 5;
snprintf(comp_name, 63, "/dev/%s", devname);
diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
index bc8d7565171d..1ff712889a3b 100644
--- a/drivers/md/md-bitmap.c
+++ b/drivers/md/md-bitmap.c
@@ -54,14 +54,7 @@ __acquires(bitmap->lock)
{
unsigned char *mappage;
- if (page >= bitmap->pages) {
- /* This can happen if bitmap_start_sync goes beyond
- * End-of-device while looking for a whole page.
- * It is harmless.
- */
- return -EINVAL;
- }
-
+ WARN_ON_ONCE(page >= bitmap->pages);
if (bitmap->bp[page].hijacked) /* it's hijacked, don't try to alloc */
return 0;
@@ -1023,7 +1016,6 @@ static int md_bitmap_file_test_bit(struct bitmap *bitmap, sector_t block)
return set;
}
-
/* this gets called when the md device is ready to unplug its underlying
* (slave) device queues -- before we let any writes go down, we need to
* sync the dirty pages of the bitmap file to disk */
@@ -1033,8 +1025,7 @@ void md_bitmap_unplug(struct bitmap *bitmap)
int dirty, need_write;
int writing = 0;
- if (!bitmap || !bitmap->storage.filemap ||
- test_bit(BITMAP_STALE, &bitmap->flags))
+ if (!md_bitmap_enabled(bitmap))
return;
/* look at each page to see if there are any set bits that need to be
@@ -1063,6 +1054,35 @@ void md_bitmap_unplug(struct bitmap *bitmap)
}
EXPORT_SYMBOL(md_bitmap_unplug);
+struct bitmap_unplug_work {
+ struct work_struct work;
+ struct bitmap *bitmap;
+ struct completion *done;
+};
+
+static void md_bitmap_unplug_fn(struct work_struct *work)
+{
+ struct bitmap_unplug_work *unplug_work =
+ container_of(work, struct bitmap_unplug_work, work);
+
+ md_bitmap_unplug(unplug_work->bitmap);
+ complete(unplug_work->done);
+}
+
+void md_bitmap_unplug_async(struct bitmap *bitmap)
+{
+ DECLARE_COMPLETION_ONSTACK(done);
+ struct bitmap_unplug_work unplug_work;
+
+ INIT_WORK_ONSTACK(&unplug_work.work, md_bitmap_unplug_fn);
+ unplug_work.bitmap = bitmap;
+ unplug_work.done = &done;
+
+ queue_work(md_bitmap_wq, &unplug_work.work);
+ wait_for_completion(&done);
+}
+EXPORT_SYMBOL(md_bitmap_unplug_async);
+
static void md_bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed);
/* * bitmap_init_from_disk -- called at bitmap_create time to initialize
* the in-memory bitmap from the on-disk bitmap -- also, sets up the
@@ -1241,11 +1261,28 @@ static bitmap_counter_t *md_bitmap_get_counter(struct bitmap_counts *bitmap,
sector_t offset, sector_t *blocks,
int create);
+static void mddev_set_timeout(struct mddev *mddev, unsigned long timeout,
+ bool force)
+{
+ struct md_thread *thread;
+
+ rcu_read_lock();
+ thread = rcu_dereference(mddev->thread);
+
+ if (!thread)
+ goto out;
+
+ if (force || thread->timeout < MAX_SCHEDULE_TIMEOUT)
+ thread->timeout = timeout;
+
+out:
+ rcu_read_unlock();
+}
+
/*
* bitmap daemon -- periodically wakes up to clean bits and flush pages
* out to disk
*/
-
void md_bitmap_daemon_work(struct mddev *mddev)
{
struct bitmap *bitmap;
@@ -1269,7 +1306,7 @@ void md_bitmap_daemon_work(struct mddev *mddev)
bitmap->daemon_lastrun = jiffies;
if (bitmap->allclean) {
- mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
+ mddev_set_timeout(mddev, MAX_SCHEDULE_TIMEOUT, true);
goto done;
}
bitmap->allclean = 1;
@@ -1366,8 +1403,7 @@ void md_bitmap_daemon_work(struct mddev *mddev)
done:
if (bitmap->allclean == 0)
- mddev->thread->timeout =
- mddev->bitmap_info.daemon_sleep;
+ mddev_set_timeout(mddev, mddev->bitmap_info.daemon_sleep, true);
mutex_unlock(&mddev->bitmap_info.mutex);
}
@@ -1387,6 +1423,14 @@ __acquires(bitmap->lock)
sector_t csize;
int err;
+ if (page >= bitmap->pages) {
+ /*
+ * This can happen if bitmap_start_sync goes beyond
+ * End-of-device while looking for a whole page or
+ * user set a huge number to sysfs bitmap_set_bits.
+ */
+ return NULL;
+ }
err = md_bitmap_checkpage(bitmap, page, create, 0);
if (bitmap->bp[page].hijacked ||
@@ -1820,8 +1864,7 @@ void md_bitmap_destroy(struct mddev *mddev)
mddev->bitmap = NULL; /* disconnect from the md device */
spin_unlock(&mddev->lock);
mutex_unlock(&mddev->bitmap_info.mutex);
- if (mddev->thread)
- mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
+ mddev_set_timeout(mddev, MAX_SCHEDULE_TIMEOUT, true);
md_bitmap_free(bitmap);
}
@@ -1964,7 +2007,7 @@ int md_bitmap_load(struct mddev *mddev)
/* Kick recovery in case any bits were set */
set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery);
- mddev->thread->timeout = mddev->bitmap_info.daemon_sleep;
+ mddev_set_timeout(mddev, mddev->bitmap_info.daemon_sleep, true);
md_wakeup_thread(mddev->thread);
md_bitmap_update_sb(bitmap);
@@ -2469,17 +2512,11 @@ timeout_store(struct mddev *mddev, const char *buf, size_t len)
timeout = MAX_SCHEDULE_TIMEOUT-1;
if (timeout < 1)
timeout = 1;
+
mddev->bitmap_info.daemon_sleep = timeout;
- if (mddev->thread) {
- /* if thread->timeout is MAX_SCHEDULE_TIMEOUT, then
- * the bitmap is all clean and we don't need to
- * adjust the timeout right now
- */
- if (mddev->thread->timeout < MAX_SCHEDULE_TIMEOUT) {
- mddev->thread->timeout = timeout;
- md_wakeup_thread(mddev->thread);
- }
- }
+ mddev_set_timeout(mddev, timeout, false);
+ md_wakeup_thread(mddev->thread);
+
return len;
}
diff --git a/drivers/md/md-bitmap.h b/drivers/md/md-bitmap.h
index cfd7395de8fd..8a3788c9bfef 100644
--- a/drivers/md/md-bitmap.h
+++ b/drivers/md/md-bitmap.h
@@ -264,6 +264,7 @@ void md_bitmap_sync_with_cluster(struct mddev *mddev,
sector_t new_lo, sector_t new_hi);
void md_bitmap_unplug(struct bitmap *bitmap);
+void md_bitmap_unplug_async(struct bitmap *bitmap);
void md_bitmap_daemon_work(struct mddev *mddev);
int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks,
@@ -273,6 +274,13 @@ int md_bitmap_copy_from_slot(struct mddev *mddev, int slot,
sector_t *lo, sector_t *hi, bool clear_bits);
void md_bitmap_free(struct bitmap *bitmap);
void md_bitmap_wait_behind_writes(struct mddev *mddev);
+
+static inline bool md_bitmap_enabled(struct bitmap *bitmap)
+{
+ return bitmap && bitmap->storage.filemap &&
+ !test_bit(BITMAP_STALE, &bitmap->flags);
+}
+
#endif
#endif
diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c
index 10e0c5381d01..3d9fd74233df 100644
--- a/drivers/md/md-cluster.c
+++ b/drivers/md/md-cluster.c
@@ -75,14 +75,14 @@ struct md_cluster_info {
sector_t suspend_hi;
int suspend_from; /* the slot which broadcast suspend_lo/hi */
- struct md_thread *recovery_thread;
+ struct md_thread __rcu *recovery_thread;
unsigned long recovery_map;
/* communication loc resources */
struct dlm_lock_resource *ack_lockres;
struct dlm_lock_resource *message_lockres;
struct dlm_lock_resource *token_lockres;
struct dlm_lock_resource *no_new_dev_lockres;
- struct md_thread *recv_thread;
+ struct md_thread __rcu *recv_thread;
struct completion newdisk_completion;
wait_queue_head_t wait;
unsigned long state;
@@ -362,8 +362,8 @@ static void __recover_slot(struct mddev *mddev, int slot)
set_bit(slot, &cinfo->recovery_map);
if (!cinfo->recovery_thread) {
- cinfo->recovery_thread = md_register_thread(recover_bitmaps,
- mddev, "recover");
+ rcu_assign_pointer(cinfo->recovery_thread,
+ md_register_thread(recover_bitmaps, mddev, "recover"));
if (!cinfo->recovery_thread) {
pr_warn("md-cluster: Could not create recovery thread\n");
return;
@@ -526,11 +526,15 @@ static void process_add_new_disk(struct mddev *mddev, struct cluster_msg *cmsg)
static void process_metadata_update(struct mddev *mddev, struct cluster_msg *msg)
{
int got_lock = 0;
+ struct md_thread *thread;
struct md_cluster_info *cinfo = mddev->cluster_info;
mddev->good_device_nr = le32_to_cpu(msg->raid_slot);
dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_CR);
- wait_event(mddev->thread->wqueue,
+
+ /* daemaon thread must exist */
+ thread = rcu_dereference_protected(mddev->thread, true);
+ wait_event(thread->wqueue,
(got_lock = mddev_trylock(mddev)) ||
test_bit(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state));
md_reload_sb(mddev, mddev->good_device_nr);
@@ -889,7 +893,8 @@ static int join(struct mddev *mddev, int nodes)
}
/* Initiate the communication resources */
ret = -ENOMEM;
- cinfo->recv_thread = md_register_thread(recv_daemon, mddev, "cluster_recv");
+ rcu_assign_pointer(cinfo->recv_thread,
+ md_register_thread(recv_daemon, mddev, "cluster_recv"));
if (!cinfo->recv_thread) {
pr_err("md-cluster: cannot allocate memory for recv_thread!\n");
goto err;
diff --git a/drivers/md/md-multipath.c b/drivers/md/md-multipath.c
index 66edf5e72bd6..92c45be203d7 100644
--- a/drivers/md/md-multipath.c
+++ b/drivers/md/md-multipath.c
@@ -400,8 +400,8 @@ static int multipath_run (struct mddev *mddev)
if (ret)
goto out_free_conf;
- mddev->thread = md_register_thread(multipathd, mddev,
- "multipath");
+ rcu_assign_pointer(mddev->thread,
+ md_register_thread(multipathd, mddev, "multipath"));
if (!mddev->thread)
goto out_free_conf;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 8e344b4b3444..78be7811a89f 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -70,11 +70,7 @@
#include "md-bitmap.h"
#include "md-cluster.h"
-/* pers_list is a list of registered personalities protected
- * by pers_lock.
- * pers_lock does extra service to protect accesses to
- * mddev->thread when the mutex cannot be held.
- */
+/* pers_list is a list of registered personalities protected by pers_lock. */
static LIST_HEAD(pers_list);
static DEFINE_SPINLOCK(pers_lock);
@@ -87,23 +83,13 @@ static struct module *md_cluster_mod;
static DECLARE_WAIT_QUEUE_HEAD(resync_wait);
static struct workqueue_struct *md_wq;
static struct workqueue_struct *md_misc_wq;
-static struct workqueue_struct *md_rdev_misc_wq;
+struct workqueue_struct *md_bitmap_wq;
static int remove_and_add_spares(struct mddev *mddev,
struct md_rdev *this);
static void mddev_detach(struct mddev *mddev);
-
-enum md_ro_state {
- MD_RDWR,
- MD_RDONLY,
- MD_AUTO_READ,
- MD_MAX_STATE
-};
-
-static bool md_is_rdwr(struct mddev *mddev)
-{
- return (mddev->ro == MD_RDWR);
-}
+static void export_rdev(struct md_rdev *rdev, struct mddev *mddev);
+static void md_wakeup_thread_directly(struct md_thread __rcu *thread);
/*
* Default number of read corrections we'll attempt on an rdev
@@ -360,10 +346,6 @@ EXPORT_SYMBOL_GPL(md_new_event);
static LIST_HEAD(all_mddevs);
static DEFINE_SPINLOCK(all_mddevs_lock);
-static bool is_md_suspended(struct mddev *mddev)
-{
- return percpu_ref_is_dying(&mddev->active_io);
-}
/* Rather than calling directly into the personality make_request function,
* IO requests come here first so that we can check if the device is
* being suspended pending a reconfiguration.
@@ -457,13 +439,19 @@ static void md_submit_bio(struct bio *bio)
*/
void mddev_suspend(struct mddev *mddev)
{
- WARN_ON_ONCE(mddev->thread && current == mddev->thread->tsk);
- lockdep_assert_held(&mddev->reconfig_mutex);
+ struct md_thread *thread = rcu_dereference_protected(mddev->thread,
+ lockdep_is_held(&mddev->reconfig_mutex));
+
+ WARN_ON_ONCE(thread && current == thread->tsk);
if (mddev->suspended++)
return;
wake_up(&mddev->sb_wait);
set_bit(MD_ALLOW_SB_UPDATE, &mddev->flags);
percpu_ref_kill(&mddev->active_io);
+
+ if (mddev->pers->prepare_suspend)
+ mddev->pers->prepare_suspend(mddev);
+
wait_event(mddev->sb_wait, percpu_ref_is_zero(&mddev->active_io));
mddev->pers->quiesce(mddev, 1);
clear_bit_unlock(MD_ALLOW_SB_UPDATE, &mddev->flags);
@@ -658,6 +646,7 @@ void mddev_init(struct mddev *mddev)
mutex_init(&mddev->bitmap_info.mutex);
INIT_LIST_HEAD(&mddev->disks);
INIT_LIST_HEAD(&mddev->all_mddevs);
+ INIT_LIST_HEAD(&mddev->deleting);
timer_setup(&mddev->safemode_timer, md_safemode_timeout, 0);
atomic_set(&mddev->active, 1);
atomic_set(&mddev->openers, 0);
@@ -761,6 +750,13 @@ static const struct attribute_group md_redundancy_group;
void mddev_unlock(struct mddev *mddev)
{
+ struct md_rdev *rdev;
+ struct md_rdev *tmp;
+ LIST_HEAD(delete);
+
+ if (!list_empty(&mddev->deleting))
+ list_splice_init(&mddev->deleting, &delete);
+
if (mddev->to_remove) {
/* These cannot be removed under reconfig_mutex as
* an access to the files will try to take reconfig_mutex
@@ -800,13 +796,14 @@ void mddev_unlock(struct mddev *mddev)
} else
mutex_unlock(&mddev->reconfig_mutex);
- /* As we've dropped the mutex we need a spinlock to
- * make sure the thread doesn't disappear
- */
- spin_lock(&pers_lock);
+ 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);
- spin_unlock(&pers_lock);
}
EXPORT_SYMBOL_GPL(mddev_unlock);
@@ -938,7 +935,7 @@ void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
atomic_inc(&rdev->nr_pending);
bio->bi_iter.bi_sector = sector;
- bio_add_page(bio, page, size, 0);
+ __bio_add_page(bio, page, size, 0);
bio->bi_private = rdev;
bio->bi_end_io = super_written;
@@ -979,7 +976,7 @@ int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
bio.bi_iter.bi_sector = sector + rdev->new_data_offset;
else
bio.bi_iter.bi_sector = sector + rdev->data_offset;
- bio_add_page(&bio, page, size, 0);
+ __bio_add_page(&bio, page, size, 0);
submit_bio_wait(&bio);
@@ -2440,16 +2437,12 @@ static int bind_rdev_to_array(struct md_rdev *rdev, struct mddev *mddev)
return err;
}
-static void rdev_delayed_delete(struct work_struct *ws)
-{
- struct md_rdev *rdev = container_of(ws, struct md_rdev, del_work);
- kobject_del(&rdev->kobj);
- kobject_put(&rdev->kobj);
-}
-
void md_autodetect_dev(dev_t dev);
-static void export_rdev(struct md_rdev *rdev)
+/* just for claiming the bdev */
+static struct md_rdev claim_rdev;
+
+static void export_rdev(struct md_rdev *rdev, struct mddev *mddev)
{
pr_debug("md: export_rdev(%pg)\n", rdev->bdev);
md_rdev_clear(rdev);
@@ -2457,13 +2450,15 @@ static void export_rdev(struct md_rdev *rdev)
if (test_bit(AutoDetected, &rdev->flags))
md_autodetect_dev(rdev->bdev->bd_dev);
#endif
- blkdev_put(rdev->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+ blkdev_put(rdev->bdev, mddev->external ? &claim_rdev : rdev);
rdev->bdev = NULL;
kobject_put(&rdev->kobj);
}
static void md_kick_rdev_from_array(struct md_rdev *rdev)
{
+ struct mddev *mddev = rdev->mddev;
+
bd_unlink_disk_holder(rdev->bdev, rdev->mddev->gendisk);
list_del_rcu(&rdev->same_set);
pr_debug("md: unbind<%pg>\n", rdev->bdev);
@@ -2477,15 +2472,15 @@ static void md_kick_rdev_from_array(struct md_rdev *rdev)
rdev->sysfs_unack_badblocks = NULL;
rdev->sysfs_badblocks = NULL;
rdev->badblocks.count = 0;
- /* We need to delay this, otherwise we can deadlock when
- * writing to 'remove' to "dev/state". We also need
- * to delay it due to rcu usage.
- */
+
synchronize_rcu();
- INIT_WORK(&rdev->del_work, rdev_delayed_delete);
- kobject_get(&rdev->kobj);
- queue_work(md_rdev_misc_wq, &rdev->del_work);
- export_rdev(rdev);
+
+ /*
+ * kobject_del() will wait for all in progress writers to be done, where
+ * reconfig_mutex is held, hence it can't be called under
+ * reconfig_mutex and it's delayed to mddev_unlock().
+ */
+ list_add(&rdev->same_set, &mddev->deleting);
}
static void export_array(struct mddev *mddev)
@@ -3553,6 +3548,7 @@ rdev_attr_store(struct kobject *kobj, struct attribute *attr,
{
struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr);
struct md_rdev *rdev = container_of(kobj, struct md_rdev, kobj);
+ struct kernfs_node *kn = NULL;
ssize_t rv;
struct mddev *mddev = rdev->mddev;
@@ -3560,6 +3556,10 @@ rdev_attr_store(struct kobject *kobj, struct attribute *attr,
return -EIO;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
+
+ if (entry->store == state_store && cmd_match(page, "remove"))
+ kn = sysfs_break_active_protection(kobj, attr);
+
rv = mddev ? mddev_lock(mddev) : -ENODEV;
if (!rv) {
if (rdev->mddev == NULL)
@@ -3568,6 +3568,10 @@ rdev_attr_store(struct kobject *kobj, struct attribute *attr,
rv = entry->store(rdev, page, length);
mddev_unlock(mddev);
}
+
+ if (kn)
+ sysfs_unbreak_active_protection(kn);
+
return rv;
}
@@ -3612,6 +3616,7 @@ int md_rdev_init(struct md_rdev *rdev)
return badblocks_init(&rdev->badblocks, 0);
}
EXPORT_SYMBOL_GPL(md_rdev_init);
+
/*
* Import a device. If 'super_format' >= 0, then sanity check the superblock
*
@@ -3624,7 +3629,6 @@ EXPORT_SYMBOL_GPL(md_rdev_init);
*/
static struct md_rdev *md_import_device(dev_t newdev, int super_format, int super_minor)
{
- static struct md_rdev claim_rdev; /* just for claiming the bdev */
struct md_rdev *rdev;
sector_t size;
int err;
@@ -3640,9 +3644,8 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe
if (err)
goto out_clear_rdev;
- rdev->bdev = blkdev_get_by_dev(newdev,
- FMODE_READ | FMODE_WRITE | FMODE_EXCL,
- super_format == -2 ? &claim_rdev : rdev);
+ rdev->bdev = blkdev_get_by_dev(newdev, BLK_OPEN_READ | BLK_OPEN_WRITE,
+ super_format == -2 ? &claim_rdev : rdev, NULL);
if (IS_ERR(rdev->bdev)) {
pr_warn("md: could not open device unknown-block(%u,%u).\n",
MAJOR(newdev), MINOR(newdev));
@@ -3679,7 +3682,7 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe
return rdev;
out_blkdev_put:
- blkdev_put(rdev->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+ blkdev_put(rdev->bdev, super_format == -2 ? &claim_rdev : rdev);
out_clear_rdev:
md_rdev_clear(rdev);
out_free_rdev:
@@ -3794,8 +3797,9 @@ int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale)
static ssize_t
safe_delay_show(struct mddev *mddev, char *page)
{
- int msec = (mddev->safemode_delay*1000)/HZ;
- return sprintf(page, "%d.%03d\n", msec/1000, msec%1000);
+ unsigned int msec = ((unsigned long)mddev->safemode_delay*1000)/HZ;
+
+ return sprintf(page, "%u.%03u\n", msec/1000, msec%1000);
}
static ssize_t
safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len)
@@ -3807,7 +3811,7 @@ safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len)
return -EINVAL;
}
- if (strict_strtoul_scaled(cbuf, &msec, 3) < 0)
+ if (strict_strtoul_scaled(cbuf, &msec, 3) < 0 || msec > UINT_MAX / HZ)
return -EINVAL;
if (msec == 0)
mddev->safemode_delay = 0;
@@ -4477,6 +4481,8 @@ max_corrected_read_errors_store(struct mddev *mddev, const char *buf, size_t len
rv = kstrtouint(buf, 10, &n);
if (rv < 0)
return rv;
+ if (n > INT_MAX)
+ return -EINVAL;
atomic_set(&mddev->max_corr_read_errors, n);
return len;
}
@@ -4491,20 +4497,6 @@ null_show(struct mddev *mddev, char *page)
return -EINVAL;
}
-/* need to ensure rdev_delayed_delete() has completed */
-static void flush_rdev_wq(struct mddev *mddev)
-{
- struct md_rdev *rdev;
-
- rcu_read_lock();
- rdev_for_each_rcu(rdev, mddev)
- if (work_pending(&rdev->del_work)) {
- flush_workqueue(md_rdev_misc_wq);
- break;
- }
- rcu_read_unlock();
-}
-
static ssize_t
new_dev_store(struct mddev *mddev, const char *buf, size_t len)
{
@@ -4532,7 +4524,6 @@ new_dev_store(struct mddev *mddev, const char *buf, size_t len)
minor != MINOR(dev))
return -EOVERFLOW;
- flush_rdev_wq(mddev);
err = mddev_lock(mddev);
if (err)
return err;
@@ -4560,7 +4551,7 @@ new_dev_store(struct mddev *mddev, const char *buf, size_t len)
err = bind_rdev_to_array(rdev, mddev);
out:
if (err)
- export_rdev(rdev);
+ export_rdev(rdev, mddev);
mddev_unlock(mddev);
if (!err)
md_new_event();
@@ -4804,11 +4795,21 @@ action_store(struct mddev *mddev, const char *page, size_t len)
return -EINVAL;
err = mddev_lock(mddev);
if (!err) {
- if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
+ if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) {
err = -EBUSY;
- else {
+ } else if (mddev->reshape_position == MaxSector ||
+ mddev->pers->check_reshape == NULL ||
+ mddev->pers->check_reshape(mddev)) {
clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
err = mddev->pers->start_reshape(mddev);
+ } else {
+ /*
+ * If reshape is still in progress, and
+ * md_check_recovery() can continue to reshape,
+ * don't restart reshape because data can be
+ * corrupted for raid456.
+ */
+ clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
}
mddev_unlock(mddev);
}
@@ -5592,7 +5593,6 @@ struct mddev *md_alloc(dev_t dev, char *name)
* removed (mddev_delayed_delete).
*/
flush_workqueue(md_misc_wq);
- flush_workqueue(md_rdev_misc_wq);
mutex_lock(&disks_mutex);
mddev = mddev_alloc(dev);
@@ -6130,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;
@@ -6247,6 +6247,8 @@ static void __md_stop(struct mddev *mddev)
void md_stop(struct mddev *mddev)
{
+ lockdep_assert_held(&mddev->reconfig_mutex);
+
/* stop the array and free an attached data structures.
* This is called from dm-raid
*/
@@ -6269,10 +6271,12 @@ static int md_set_readonly(struct mddev *mddev, struct block_device *bdev)
}
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
- if (mddev->sync_thread)
- /* Thread might be blocked waiting for metadata update
- * which will now never happen */
- wake_up_process(mddev->sync_thread->tsk);
+
+ /*
+ * Thread might be blocked waiting for metadata update which will now
+ * never happen
+ */
+ md_wakeup_thread_directly(mddev->sync_thread);
if (mddev->external && test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags))
return -EBUSY;
@@ -6333,10 +6337,12 @@ static int do_md_stop(struct mddev *mddev, int mode,
}
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
- if (mddev->sync_thread)
- /* Thread might be blocked waiting for metadata update
- * which will now never happen */
- wake_up_process(mddev->sync_thread->tsk);
+
+ /*
+ * Thread might be blocked waiting for metadata update which will now
+ * never happen
+ */
+ md_wakeup_thread_directly(mddev->sync_thread);
mddev_unlock(mddev);
wait_event(resync_wait, (mddev->sync_thread == NULL &&
@@ -6498,7 +6504,7 @@ static void autorun_devices(int part)
rdev_for_each_list(rdev, tmp, &candidates) {
list_del_init(&rdev->same_set);
if (bind_rdev_to_array(rdev, mddev))
- export_rdev(rdev);
+ export_rdev(rdev, mddev);
}
autorun_array(mddev);
mddev_unlock(mddev);
@@ -6508,7 +6514,7 @@ static void autorun_devices(int part)
*/
rdev_for_each_list(rdev, tmp, &candidates) {
list_del_init(&rdev->same_set);
- export_rdev(rdev);
+ export_rdev(rdev, mddev);
}
mddev_put(mddev);
}
@@ -6696,13 +6702,13 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
pr_warn("md: %pg has different UUID to %pg\n",
rdev->bdev,
rdev0->bdev);
- export_rdev(rdev);
+ export_rdev(rdev, mddev);
return -EINVAL;
}
}
err = bind_rdev_to_array(rdev, mddev);
if (err)
- export_rdev(rdev);
+ export_rdev(rdev, mddev);
return err;
}
@@ -6733,7 +6739,6 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
if (info->state & (1<<MD_DISK_SYNC) &&
info->raid_disk < mddev->raid_disks) {
rdev->raid_disk = info->raid_disk;
- set_bit(In_sync, &rdev->flags);
clear_bit(Bitmap_sync, &rdev->flags);
} else
rdev->raid_disk = -1;
@@ -6746,7 +6751,7 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
/* This was a hot-add request, but events doesn't
* match, so reject it.
*/
- export_rdev(rdev);
+ export_rdev(rdev, mddev);
return -EINVAL;
}
@@ -6772,7 +6777,7 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
}
}
if (has_journal || mddev->bitmap) {
- export_rdev(rdev);
+ export_rdev(rdev, mddev);
return -EBUSY;
}
set_bit(Journal, &rdev->flags);
@@ -6787,7 +6792,7 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
/* --add initiated by this node */
err = md_cluster_ops->add_new_disk(mddev, rdev);
if (err) {
- export_rdev(rdev);
+ export_rdev(rdev, mddev);
return err;
}
}
@@ -6797,7 +6802,7 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
err = bind_rdev_to_array(rdev, mddev);
if (err)
- export_rdev(rdev);
+ export_rdev(rdev, mddev);
if (mddev_is_clustered(mddev)) {
if (info->state & (1 << MD_DISK_CANDIDATE)) {
@@ -6860,7 +6865,7 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
err = bind_rdev_to_array(rdev, mddev);
if (err) {
- export_rdev(rdev);
+ export_rdev(rdev, mddev);
return err;
}
}
@@ -6985,7 +6990,7 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)
return 0;
abort_export:
- export_rdev(rdev);
+ export_rdev(rdev, mddev);
return err;
}
@@ -7486,7 +7491,7 @@ static int __md_set_array_info(struct mddev *mddev, void __user *argp)
return err;
}
-static int md_ioctl(struct block_device *bdev, fmode_t mode,
+static int md_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long arg)
{
int err = 0;
@@ -7555,9 +7560,6 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
}
- if (cmd == ADD_NEW_DISK || cmd == HOT_ADD_DISK)
- flush_rdev_wq(mddev);
-
if (cmd == HOT_REMOVE_DISK)
/* need to ensure recovery thread has run */
wait_event_interruptible_timeout(mddev->sb_wait,
@@ -7718,7 +7720,7 @@ out:
return err;
}
#ifdef CONFIG_COMPAT
-static int md_compat_ioctl(struct block_device *bdev, fmode_t mode,
+static int md_compat_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long arg)
{
switch (cmd) {
@@ -7767,13 +7769,13 @@ out_unlock:
return err;
}
-static int md_open(struct block_device *bdev, fmode_t mode)
+static int md_open(struct gendisk *disk, blk_mode_t mode)
{
struct mddev *mddev;
int err;
spin_lock(&all_mddevs_lock);
- mddev = mddev_get(bdev->bd_disk->private_data);
+ mddev = mddev_get(disk->private_data);
spin_unlock(&all_mddevs_lock);
if (!mddev)
return -ENODEV;
@@ -7789,7 +7791,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
atomic_inc(&mddev->openers);
mutex_unlock(&mddev->open_mutex);
- bdev_check_media_change(bdev);
+ disk_check_media_change(disk);
return 0;
out_unlock:
@@ -7799,7 +7801,7 @@ out:
return err;
}
-static void md_release(struct gendisk *disk, fmode_t mode)
+static void md_release(struct gendisk *disk)
{
struct mddev *mddev = disk->private_data;
@@ -7886,13 +7888,29 @@ static int md_thread(void *arg)
return 0;
}
-void md_wakeup_thread(struct md_thread *thread)
+static void md_wakeup_thread_directly(struct md_thread __rcu *thread)
{
- if (thread) {
- pr_debug("md: waking up MD thread %s.\n", thread->tsk->comm);
- set_bit(THREAD_WAKEUP, &thread->flags);
- wake_up(&thread->wqueue);
+ struct md_thread *t;
+
+ rcu_read_lock();
+ t = rcu_dereference(thread);
+ if (t)
+ wake_up_process(t->tsk);
+ rcu_read_unlock();
+}
+
+void md_wakeup_thread(struct md_thread __rcu *thread)
+{
+ struct md_thread *t;
+
+ rcu_read_lock();
+ t = rcu_dereference(thread);
+ if (t) {
+ pr_debug("md: waking up MD thread %s.\n", t->tsk->comm);
+ set_bit(THREAD_WAKEUP, &t->flags);
+ wake_up(&t->wqueue);
}
+ rcu_read_unlock();
}
EXPORT_SYMBOL(md_wakeup_thread);
@@ -7922,22 +7940,15 @@ struct md_thread *md_register_thread(void (*run) (struct md_thread *),
}
EXPORT_SYMBOL(md_register_thread);
-void md_unregister_thread(struct md_thread **threadp)
+void md_unregister_thread(struct md_thread __rcu **threadp)
{
- struct md_thread *thread;
+ struct md_thread *thread = rcu_dereference_protected(*threadp, true);
- /*
- * Locking ensures that mddev_unlock does not wake_up a
- * non-existent thread
- */
- spin_lock(&pers_lock);
- thread = *threadp;
- if (!thread) {
- spin_unlock(&pers_lock);
+ if (!thread)
return;
- }
- *threadp = NULL;
- spin_unlock(&pers_lock);
+
+ rcu_assign_pointer(*threadp, NULL);
+ synchronize_rcu();
pr_debug("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk));
kthread_stop(thread->tsk);
@@ -9100,6 +9111,7 @@ void md_do_sync(struct md_thread *thread)
spin_unlock(&mddev->lock);
wake_up(&resync_wait);
+ wake_up(&mddev->sb_wait);
md_wakeup_thread(mddev->thread);
return;
}
@@ -9202,9 +9214,8 @@ static void md_start_sync(struct work_struct *ws)
{
struct mddev *mddev = container_of(ws, struct mddev, del_work);
- mddev->sync_thread = md_register_thread(md_do_sync,
- mddev,
- "resync");
+ rcu_assign_pointer(mddev->sync_thread,
+ md_register_thread(md_do_sync, mddev, "resync"));
if (!mddev->sync_thread) {
pr_warn("%s: could not start resync thread...\n",
mdname(mddev));
@@ -9619,9 +9630,10 @@ static int __init md_init(void)
if (!md_misc_wq)
goto err_misc_wq;
- md_rdev_misc_wq = alloc_workqueue("md_rdev_misc", 0, 0);
- if (!md_rdev_misc_wq)
- goto err_rdev_misc_wq;
+ md_bitmap_wq = alloc_workqueue("md_bitmap", WQ_MEM_RECLAIM | WQ_UNBOUND,
+ 0);
+ if (!md_bitmap_wq)
+ goto err_bitmap_wq;
ret = __register_blkdev(MD_MAJOR, "md", md_probe);
if (ret < 0)
@@ -9641,8 +9653,8 @@ static int __init md_init(void)
err_mdp:
unregister_blkdev(MD_MAJOR, "md");
err_md:
- destroy_workqueue(md_rdev_misc_wq);
-err_rdev_misc_wq:
+ destroy_workqueue(md_bitmap_wq);
+err_bitmap_wq:
destroy_workqueue(md_misc_wq);
err_misc_wq:
destroy_workqueue(md_wq);
@@ -9938,8 +9950,8 @@ static __exit void md_exit(void)
}
spin_unlock(&all_mddevs_lock);
- destroy_workqueue(md_rdev_misc_wq);
destroy_workqueue(md_misc_wq);
+ destroy_workqueue(md_bitmap_wq);
destroy_workqueue(md_wq);
}
diff --git a/drivers/md/md.h b/drivers/md/md.h
index fd8f260ed5f8..1aef86bf3fc3 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -122,8 +122,6 @@ struct md_rdev {
struct serial_in_rdev *serial; /* used for raid1 io serialization */
- struct work_struct del_work; /* used for delayed sysfs removal */
-
struct kernfs_node *sysfs_state; /* handle for 'state'
* sysfs entry */
/* handle for 'unacknowledged_bad_blocks' sysfs dentry */
@@ -367,8 +365,8 @@ struct mddev {
int new_chunk_sectors;
int reshape_backwards;
- struct md_thread *thread; /* management thread */
- struct md_thread *sync_thread; /* doing resync or reconstruct */
+ struct md_thread __rcu *thread; /* management thread */
+ struct md_thread __rcu *sync_thread; /* doing resync or reconstruct */
/* 'last_sync_action' is initialized to "none". It is set when a
* sync operation (i.e "data-check", "requested-resync", "resync",
@@ -531,6 +529,12 @@ struct mddev {
unsigned int good_device_nr; /* good device num within cluster raid */
unsigned int noio_flag; /* for memalloc scope API */
+ /*
+ * Temporarily store rdev that will be finally removed when
+ * reconfig_mutex is unlocked, protected by reconfig_mutex.
+ */
+ struct list_head deleting;
+
bool has_superblocks:1;
bool fail_last_dev:1;
bool serialize_policy:1;
@@ -555,6 +559,23 @@ enum recovery_flags {
MD_RESYNCING_REMOTE, /* remote node is running resync thread */
};
+enum md_ro_state {
+ MD_RDWR,
+ MD_RDONLY,
+ MD_AUTO_READ,
+ MD_MAX_STATE
+};
+
+static inline bool md_is_rdwr(struct mddev *mddev)
+{
+ return (mddev->ro == MD_RDWR);
+}
+
+static inline bool is_md_suspended(struct mddev *mddev)
+{
+ return percpu_ref_is_dying(&mddev->active_io);
+}
+
static inline int __must_check mddev_lock(struct mddev *mddev)
{
return mutex_lock_interruptible(&mddev->reconfig_mutex);
@@ -614,6 +635,7 @@ struct md_personality
int (*start_reshape) (struct mddev *mddev);
void (*finish_reshape) (struct mddev *mddev);
void (*update_reshape_pos) (struct mddev *mddev);
+ void (*prepare_suspend) (struct mddev *mddev);
/* quiesce suspends or resumes internal processing.
* 1 - stop new actions and wait for action io to complete
* 0 - return to normal behaviour
@@ -734,8 +756,8 @@ extern struct md_thread *md_register_thread(
void (*run)(struct md_thread *thread),
struct mddev *mddev,
const char *name);
-extern void md_unregister_thread(struct md_thread **threadp);
-extern void md_wakeup_thread(struct md_thread *thread);
+extern void md_unregister_thread(struct md_thread __rcu **threadp);
+extern void md_wakeup_thread(struct md_thread __rcu *thread);
extern void md_check_recovery(struct mddev *mddev);
extern void md_reap_sync_thread(struct mddev *mddev);
extern int mddev_init_writes_pending(struct mddev *mddev);
@@ -828,6 +850,7 @@ struct mdu_array_info_s;
struct mdu_disk_info_s;
extern int mdp_major;
+extern struct workqueue_struct *md_bitmap_wq;
void md_autostart_arrays(int part);
int md_set_array_info(struct mddev *mddev, struct mdu_array_info_s *info);
int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info);
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 e61f6cad4e08..3f22edec70e7 100644
--- a/drivers/md/raid1-10.c
+++ b/drivers/md/raid1-10.c
@@ -21,6 +21,7 @@
#define IO_MADE_GOOD ((struct bio *)2)
#define BIO_SPECIAL(bio) ((unsigned long)bio <= 2)
+#define MAX_PLUG_BIO 32
/* for managing resync I/O pages */
struct resync_pages {
@@ -31,6 +32,7 @@ struct resync_pages {
struct raid1_plug_cb {
struct blk_plug_cb cb;
struct bio_list pending;
+ unsigned int count;
};
static void rbio_pool_free(void *rbio, void *data)
@@ -101,11 +103,73 @@ static void md_bio_reset_resync_pages(struct bio *bio, struct resync_pages *rp,
struct page *page = resync_fetch_page(rp, idx);
int len = min_t(int, size, PAGE_SIZE);
- /*
- * won't fail because the vec table is big
- * enough to hold all these pages
- */
- bio_add_page(bio, page, len, 0);
+ if (WARN_ON(!bio_add_page(bio, page, len, 0))) {
+ bio->bi_status = BLK_STS_RESOURCE;
+ bio_endio(bio);
+ return;
+ }
+
size -= len;
} while (idx++ < RESYNC_PAGES && size > 0);
}
+
+
+static inline void raid1_submit_write(struct bio *bio)
+{
+ struct md_rdev *rdev = (void *)bio->bi_bdev;
+
+ bio->bi_next = NULL;
+ bio_set_dev(bio, rdev->bdev);
+ if (test_bit(Faulty, &rdev->flags))
+ bio_io_error(bio);
+ else if (unlikely(bio_op(bio) == REQ_OP_DISCARD &&
+ !bdev_max_discard_sectors(bio->bi_bdev)))
+ /* Just ignore it */
+ bio_endio(bio);
+ else
+ submit_bio_noacct(bio);
+}
+
+static inline bool raid1_add_bio_to_plug(struct mddev *mddev, struct bio *bio,
+ blk_plug_cb_fn unplug, int copies)
+{
+ struct raid1_plug_cb *plug = NULL;
+ struct blk_plug_cb *cb;
+
+ /*
+ * If bitmap is not enabled, it's safe to submit the io directly, and
+ * this can get optimal performance.
+ */
+ if (!md_bitmap_enabled(mddev->bitmap)) {
+ raid1_submit_write(bio);
+ return true;
+ }
+
+ cb = blk_check_plugged(unplug, mddev, sizeof(*plug));
+ if (!cb)
+ return false;
+
+ plug = container_of(cb, struct raid1_plug_cb, cb);
+ bio_list_add(&plug->pending, bio);
+ if (++plug->count / MAX_PLUG_BIO >= copies) {
+ list_del(&cb->list);
+ cb->callback(cb, false);
+ }
+
+
+ return true;
+}
+
+/*
+ * current->bio_list will be set under submit_bio() context, in this case bitmap
+ * io will be added to the list and wait for current io submission to finish,
+ * while current io submission must wait for bitmap io to be done. In order to
+ * avoid such deadlock, submit bitmap io asynchronously.
+ */
+static inline void raid1_prepare_flush_writes(struct bitmap *bitmap)
+{
+ if (current->bio_list)
+ md_bitmap_unplug_async(bitmap);
+ else
+ md_bitmap_unplug(bitmap);
+}
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 68a9e2d9985b..dd25832eb045 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -794,22 +794,13 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
static void flush_bio_list(struct r1conf *conf, struct bio *bio)
{
/* flush any pending bitmap writes to disk before proceeding w/ I/O */
- md_bitmap_unplug(conf->mddev->bitmap);
+ raid1_prepare_flush_writes(conf->mddev->bitmap);
wake_up(&conf->wait_barrier);
while (bio) { /* submit pending writes */
struct bio *next = bio->bi_next;
- struct md_rdev *rdev = (void *)bio->bi_bdev;
- bio->bi_next = NULL;
- bio_set_dev(bio, rdev->bdev);
- if (test_bit(Faulty, &rdev->flags)) {
- bio_io_error(bio);
- } else if (unlikely((bio_op(bio) == REQ_OP_DISCARD) &&
- !bdev_max_discard_sectors(bio->bi_bdev)))
- /* Just ignore it */
- bio_endio(bio);
- else
- submit_bio_noacct(bio);
+
+ raid1_submit_write(bio);
bio = next;
cond_resched();
}
@@ -1147,7 +1138,10 @@ static void alloc_behind_master_bio(struct r1bio *r1_bio,
if (unlikely(!page))
goto free_pages;
- bio_add_page(behind_bio, page, len, 0);
+ if (!bio_add_page(behind_bio, page, len, 0)) {
+ put_page(page);
+ goto free_pages;
+ }
size -= len;
i++;
@@ -1175,7 +1169,7 @@ static void raid1_unplug(struct blk_plug_cb *cb, bool from_schedule)
struct r1conf *conf = mddev->private;
struct bio *bio;
- if (from_schedule || current->bio_list) {
+ if (from_schedule) {
spin_lock_irq(&conf->device_lock);
bio_list_merge(&conf->pending_bio_list, &plug->pending);
spin_unlock_irq(&conf->device_lock);
@@ -1343,8 +1337,6 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
struct bitmap *bitmap = mddev->bitmap;
unsigned long flags;
struct md_rdev *blocked_rdev;
- struct blk_plug_cb *cb;
- struct raid1_plug_cb *plug = NULL;
int first_clone;
int max_sectors;
bool write_behind = false;
@@ -1573,15 +1565,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
r1_bio->sector);
/* flush_pending_writes() needs access to the rdev so...*/
mbio->bi_bdev = (void *)rdev;
-
- cb = blk_check_plugged(raid1_unplug, mddev, sizeof(*plug));
- if (cb)
- plug = container_of(cb, struct raid1_plug_cb, cb);
- else
- plug = NULL;
- if (plug) {
- bio_list_add(&plug->pending, mbio);
- } else {
+ if (!raid1_add_bio_to_plug(mddev, mbio, raid1_unplug, disks)) {
spin_lock_irqsave(&conf->device_lock, flags);
bio_list_add(&conf->pending_bio_list, mbio);
spin_unlock_irqrestore(&conf->device_lock, flags);
@@ -2914,7 +2898,7 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr,
* won't fail because the vec table is big
* enough to hold all these pages
*/
- bio_add_page(bio, page, len, 0);
+ __bio_add_page(bio, page, len, 0);
}
}
nr_sectors += len>>9;
@@ -3084,7 +3068,8 @@ static struct r1conf *setup_conf(struct mddev *mddev)
}
err = -ENOMEM;
- conf->thread = md_register_thread(raid1d, mddev, "raid1");
+ rcu_assign_pointer(conf->thread,
+ md_register_thread(raid1d, mddev, "raid1"));
if (!conf->thread)
goto abort;
@@ -3177,8 +3162,8 @@ static int raid1_run(struct mddev *mddev)
/*
* Ok, everything is just fine now
*/
- mddev->thread = conf->thread;
- conf->thread = NULL;
+ rcu_assign_pointer(mddev->thread, conf->thread);
+ rcu_assign_pointer(conf->thread, NULL);
mddev->private = conf;
set_bit(MD_FAILFAST_SUPPORTED, &mddev->flags);
diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h
index ebb6788820e7..468f189da7a0 100644
--- a/drivers/md/raid1.h
+++ b/drivers/md/raid1.h
@@ -130,7 +130,7 @@ struct r1conf {
/* When taking over an array from a different personality, we store
* the new thread here until we fully activate the array.
*/
- struct md_thread *thread;
+ struct md_thread __rcu *thread;
/* Keep track of cluster resync window to send to other
* nodes.
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 4fcfcb350d2b..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);
/*
@@ -779,8 +779,16 @@ static struct md_rdev *read_balance(struct r10conf *conf,
disk = r10_bio->devs[slot].devnum;
rdev = rcu_dereference(conf->mirrors[disk].replacement);
if (rdev == NULL || test_bit(Faulty, &rdev->flags) ||
- r10_bio->devs[slot].addr + sectors > rdev->recovery_offset)
+ r10_bio->devs[slot].addr + sectors >
+ rdev->recovery_offset) {
+ /*
+ * Read replacement first to prevent reading both rdev
+ * and replacement as NULL during replacement replace
+ * rdev.
+ */
+ smp_mb();
rdev = rcu_dereference(conf->mirrors[disk].rdev);
+ }
if (rdev == NULL ||
test_bit(Faulty, &rdev->flags))
continue;
@@ -902,25 +910,15 @@ static void flush_pending_writes(struct r10conf *conf)
__set_current_state(TASK_RUNNING);
blk_start_plug(&plug);
- /* flush any pending bitmap writes to disk
- * before proceeding w/ I/O */
- md_bitmap_unplug(conf->mddev->bitmap);
+ raid1_prepare_flush_writes(conf->mddev->bitmap);
wake_up(&conf->wait_barrier);
while (bio) { /* submit pending writes */
struct bio *next = bio->bi_next;
- struct md_rdev *rdev = (void*)bio->bi_bdev;
- bio->bi_next = NULL;
- bio_set_dev(bio, rdev->bdev);
- if (test_bit(Faulty, &rdev->flags)) {
- bio_io_error(bio);
- } else if (unlikely((bio_op(bio) == REQ_OP_DISCARD) &&
- !bdev_max_discard_sectors(bio->bi_bdev)))
- /* Just ignore it */
- bio_endio(bio);
- else
- submit_bio_noacct(bio);
+
+ raid1_submit_write(bio);
bio = next;
+ cond_resched();
}
blk_finish_plug(&plug);
} else
@@ -982,6 +980,7 @@ static void lower_barrier(struct r10conf *conf)
static bool stop_waiting_barrier(struct r10conf *conf)
{
struct bio_list *bio_list = current->bio_list;
+ struct md_thread *thread;
/* barrier is dropped */
if (!conf->barrier)
@@ -997,12 +996,14 @@ static bool stop_waiting_barrier(struct r10conf *conf)
(!bio_list_empty(&bio_list[0]) || !bio_list_empty(&bio_list[1])))
return true;
+ /* daemon thread must exist while handling io */
+ thread = rcu_dereference_protected(conf->mddev->thread, true);
/*
* move on if io is issued from raid10d(), nr_pending is not released
* from original io(see handle_read_error()). All raise barrier is
* blocked until this io is done.
*/
- if (conf->mddev->thread->tsk == current) {
+ if (thread->tsk == current) {
WARN_ON_ONCE(atomic_read(&conf->nr_pending) == 0);
return true;
}
@@ -1113,11 +1114,11 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule)
struct r10conf *conf = mddev->private;
struct bio *bio;
- if (from_schedule || current->bio_list) {
+ if (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;
@@ -1125,23 +1126,15 @@ 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);
- md_bitmap_unplug(mddev->bitmap);
- wake_up(&conf->wait_barrier);
+ raid1_prepare_flush_writes(mddev->bitmap);
+ wake_up_barrier(conf);
while (bio) { /* submit pending writes */
struct bio *next = bio->bi_next;
- struct md_rdev *rdev = (void*)bio->bi_bdev;
- bio->bi_next = NULL;
- bio_set_dev(bio, rdev->bdev);
- if (test_bit(Faulty, &rdev->flags)) {
- bio_io_error(bio);
- } else if (unlikely((bio_op(bio) == REQ_OP_DISCARD) &&
- !bdev_max_discard_sectors(bio->bi_bdev)))
- /* Just ignore it */
- bio_endio(bio);
- else
- submit_bio_noacct(bio);
+
+ raid1_submit_write(bio);
bio = next;
+ cond_resched();
}
kfree(plug);
}
@@ -1282,8 +1275,6 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio,
const blk_opf_t do_sync = bio->bi_opf & REQ_SYNC;
const blk_opf_t do_fua = bio->bi_opf & REQ_FUA;
unsigned long flags;
- struct blk_plug_cb *cb;
- struct raid1_plug_cb *plug = NULL;
struct r10conf *conf = mddev->private;
struct md_rdev *rdev;
int devnum = r10_bio->devs[n_copy].devnum;
@@ -1323,14 +1314,7 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio,
atomic_inc(&r10_bio->remaining);
- cb = blk_check_plugged(raid10_unplug, mddev, sizeof(*plug));
- if (cb)
- plug = container_of(cb, struct raid1_plug_cb, cb);
- else
- plug = NULL;
- if (plug) {
- bio_list_add(&plug->pending, mbio);
- } else {
+ if (!raid1_add_bio_to_plug(mddev, mbio, raid10_unplug, conf->copies)) {
spin_lock_irqsave(&conf->device_lock, flags);
bio_list_add(&conf->pending_bio_list, mbio);
spin_unlock_irqrestore(&conf->device_lock, flags);
@@ -1479,9 +1463,15 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio,
for (i = 0; i < conf->copies; i++) {
int d = r10_bio->devs[i].devnum;
- struct md_rdev *rdev = rcu_dereference(conf->mirrors[d].rdev);
- struct md_rdev *rrdev = rcu_dereference(
- conf->mirrors[d].replacement);
+ struct md_rdev *rdev, *rrdev;
+
+ rrdev = rcu_dereference(conf->mirrors[d].replacement);
+ /*
+ * Read replacement first to prevent reading both rdev and
+ * replacement as NULL during replacement replace rdev.
+ */
+ smp_mb();
+ rdev = rcu_dereference(conf->mirrors[d].rdev);
if (rdev == rrdev)
rrdev = NULL;
if (rdev && (test_bit(Faulty, &rdev->flags)))
@@ -2148,9 +2138,10 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
{
struct r10conf *conf = mddev->private;
int err = -EEXIST;
- int mirror;
+ int mirror, repl_slot = -1;
int first = 0;
int last = conf->geo.raid_disks - 1;
+ struct raid10_info *p;
if (mddev->recovery_cp < MaxSector)
/* only hot-add to in-sync arrays, as recovery is
@@ -2173,23 +2164,14 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
else
mirror = first;
for ( ; mirror <= last ; mirror++) {
- struct raid10_info *p = &conf->mirrors[mirror];
+ p = &conf->mirrors[mirror];
if (p->recovery_disabled == mddev->recovery_disabled)
continue;
if (p->rdev) {
- if (!test_bit(WantReplacement, &p->rdev->flags) ||
- p->replacement != NULL)
- continue;
- clear_bit(In_sync, &rdev->flags);
- set_bit(Replacement, &rdev->flags);
- rdev->raid_disk = mirror;
- err = 0;
- if (mddev->gendisk)
- disk_stack_limits(mddev->gendisk, rdev->bdev,
- rdev->data_offset << 9);
- conf->fullsync = 1;
- rcu_assign_pointer(p->replacement, rdev);
- break;
+ if (test_bit(WantReplacement, &p->rdev->flags) &&
+ p->replacement == NULL && repl_slot < 0)
+ repl_slot = mirror;
+ continue;
}
if (mddev->gendisk)
@@ -2206,6 +2188,19 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
break;
}
+ if (err && repl_slot >= 0) {
+ p = &conf->mirrors[repl_slot];
+ clear_bit(In_sync, &rdev->flags);
+ set_bit(Replacement, &rdev->flags);
+ rdev->raid_disk = repl_slot;
+ err = 0;
+ if (mddev->gendisk)
+ disk_stack_limits(mddev->gendisk, rdev->bdev,
+ rdev->data_offset << 9);
+ conf->fullsync = 1;
+ rcu_assign_pointer(p->replacement, rdev);
+ }
+
print_conf(conf);
return err;
}
@@ -3303,6 +3298,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
int chunks_skipped = 0;
sector_t chunk_mask = conf->geo.chunk_mask;
int page_idx = 0;
+ int error_disk = -1;
/*
* Allow skipping a full rebuild for incremental assembly
@@ -3386,8 +3382,21 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
return reshape_request(mddev, sector_nr, skipped);
if (chunks_skipped >= conf->geo.raid_disks) {
- /* if there has been nothing to do on any drive,
- * then there is nothing to do at all..
+ pr_err("md/raid10:%s: %s fails\n", mdname(mddev),
+ test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ? "resync" : "recovery");
+ if (error_disk >= 0 &&
+ !test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
+ /*
+ * recovery fails, set mirrors.recovery_disabled,
+ * device shouldn't be added to there.
+ */
+ conf->mirrors[error_disk].recovery_disabled =
+ mddev->recovery_disabled;
+ return 0;
+ }
+ /*
+ * if there has been nothing to do on any drive,
+ * then there is nothing to do at all.
*/
*skipped = 1;
return (max_sector - sector_nr) + sectors_skipped;
@@ -3437,8 +3446,6 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
sector_t sect;
int must_sync;
int any_working;
- int need_recover = 0;
- int need_replace = 0;
struct raid10_info *mirror = &conf->mirrors[i];
struct md_rdev *mrdev, *mreplace;
@@ -3446,15 +3453,13 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
mrdev = rcu_dereference(mirror->rdev);
mreplace = rcu_dereference(mirror->replacement);
- if (mrdev != NULL &&
- !test_bit(Faulty, &mrdev->flags) &&
- !test_bit(In_sync, &mrdev->flags))
- need_recover = 1;
- if (mreplace != NULL &&
- !test_bit(Faulty, &mreplace->flags))
- need_replace = 1;
+ if (mrdev && (test_bit(Faulty, &mrdev->flags) ||
+ test_bit(In_sync, &mrdev->flags)))
+ mrdev = NULL;
+ if (mreplace && test_bit(Faulty, &mreplace->flags))
+ mreplace = NULL;
- if (!need_recover && !need_replace) {
+ if (!mrdev && !mreplace) {
rcu_read_unlock();
continue;
}
@@ -3470,8 +3475,6 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
rcu_read_unlock();
continue;
}
- if (mreplace && test_bit(Faulty, &mreplace->flags))
- mreplace = NULL;
/* Unless we are doing a full sync, or a replacement
* we only need to recover the block if it is set in
* the bitmap
@@ -3490,7 +3493,8 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
rcu_read_unlock();
continue;
}
- atomic_inc(&mrdev->nr_pending);
+ if (mrdev)
+ atomic_inc(&mrdev->nr_pending);
if (mreplace)
atomic_inc(&mreplace->nr_pending);
rcu_read_unlock();
@@ -3577,7 +3581,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
r10_bio->devs[1].devnum = i;
r10_bio->devs[1].addr = to_addr;
- if (need_recover) {
+ if (mrdev) {
bio = r10_bio->devs[1].bio;
bio->bi_next = biolist;
biolist = bio;
@@ -3594,11 +3598,11 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
bio = r10_bio->devs[1].repl_bio;
if (bio)
bio->bi_end_io = NULL;
- /* Note: if need_replace, then bio
+ /* Note: if replace is not NULL, then bio
* cannot be NULL as r10buf_pool_alloc will
* have allocated it.
*/
- if (!need_replace)
+ if (!mreplace)
break;
bio->bi_next = biolist;
biolist = bio;
@@ -3622,7 +3626,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
for (k = 0; k < conf->copies; k++)
if (r10_bio->devs[k].devnum == i)
break;
- if (!test_bit(In_sync,
+ if (mrdev && !test_bit(In_sync,
&mrdev->flags)
&& !rdev_set_badblocks(
mrdev,
@@ -3643,17 +3647,21 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
mdname(mddev));
mirror->recovery_disabled
= mddev->recovery_disabled;
+ } else {
+ error_disk = i;
}
put_buf(r10_bio);
if (rb2)
atomic_dec(&rb2->remaining);
r10_bio = rb2;
- rdev_dec_pending(mrdev, mddev);
+ if (mrdev)
+ rdev_dec_pending(mrdev, mddev);
if (mreplace)
rdev_dec_pending(mreplace, mddev);
break;
}
- rdev_dec_pending(mrdev, mddev);
+ if (mrdev)
+ rdev_dec_pending(mrdev, mddev);
if (mreplace)
rdev_dec_pending(mreplace, mddev);
if (r10_bio->devs[0].bio->bi_opf & MD_FAILFAST) {
@@ -3819,11 +3827,11 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
for (bio= biolist ; bio ; bio=bio->bi_next) {
struct resync_pages *rp = get_resync_pages(bio);
page = resync_fetch_page(rp, page_idx);
- /*
- * won't fail because the vec table is big enough
- * to hold all these pages
- */
- bio_add_page(bio, page, len, 0);
+ if (WARN_ON(!bio_add_page(bio, page, len, 0))) {
+ bio->bi_status = BLK_STS_RESOURCE;
+ bio_endio(bio);
+ goto giveup;
+ }
}
nr_sectors += len>>9;
sector_nr += len>>9;
@@ -4107,7 +4115,8 @@ static struct r10conf *setup_conf(struct mddev *mddev)
atomic_set(&conf->nr_pending, 0);
err = -ENOMEM;
- conf->thread = md_register_thread(raid10d, mddev, "raid10");
+ rcu_assign_pointer(conf->thread,
+ md_register_thread(raid10d, mddev, "raid10"));
if (!conf->thread)
goto out;
@@ -4152,8 +4161,8 @@ static int raid10_run(struct mddev *mddev)
if (!conf)
goto out;
- mddev->thread = conf->thread;
- conf->thread = NULL;
+ rcu_assign_pointer(mddev->thread, conf->thread);
+ rcu_assign_pointer(conf->thread, NULL);
if (mddev_is_clustered(conf->mddev)) {
int fc, fo;
@@ -4296,8 +4305,8 @@ static int raid10_run(struct mddev *mddev)
clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
- mddev->sync_thread = md_register_thread(md_do_sync, mddev,
- "reshape");
+ rcu_assign_pointer(mddev->sync_thread,
+ md_register_thread(md_do_sync, mddev, "reshape"));
if (!mddev->sync_thread)
goto out_free_conf;
}
@@ -4698,8 +4707,8 @@ out:
set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
- mddev->sync_thread = md_register_thread(md_do_sync, mddev,
- "reshape");
+ rcu_assign_pointer(mddev->sync_thread,
+ md_register_thread(md_do_sync, mddev, "reshape"));
if (!mddev->sync_thread) {
ret = -EAGAIN;
goto abort;
@@ -4997,11 +5006,11 @@ read_more:
if (len > PAGE_SIZE)
len = PAGE_SIZE;
for (bio = blist; bio ; bio = bio->bi_next) {
- /*
- * won't fail because the vec table is big enough
- * to hold all these pages
- */
- bio_add_page(bio, page, len, 0);
+ if (WARN_ON(!bio_add_page(bio, page, len, 0))) {
+ bio->bi_status = BLK_STS_RESOURCE;
+ bio_endio(bio);
+ return sectors_done;
+ }
}
sector_nr += len >> 9;
nr_sectors += len >> 9;
diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h
index 8c072ce0bc54..63e48b11b552 100644
--- a/drivers/md/raid10.h
+++ b/drivers/md/raid10.h
@@ -100,7 +100,7 @@ struct r10conf {
/* When taking over an array from a different personality, we store
* the new thread here until we fully activate the array.
*/
- struct md_thread *thread;
+ struct md_thread __rcu *thread;
/*
* Keep track of cluster resync window to send to other nodes.
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c
index 46182b955aef..47ba7d9e81e1 100644
--- a/drivers/md/raid5-cache.c
+++ b/drivers/md/raid5-cache.c
@@ -120,7 +120,7 @@ struct r5l_log {
struct bio_set bs;
mempool_t meta_pool;
- struct md_thread *reclaim_thread;
+ struct md_thread __rcu *reclaim_thread;
unsigned long reclaim_target; /* number of space that need to be
* reclaimed. if it's 0, reclaim spaces
* used by io_units which are in
@@ -792,7 +792,7 @@ static struct r5l_io_unit *r5l_new_meta(struct r5l_log *log)
io->current_bio = r5l_bio_alloc(log);
io->current_bio->bi_end_io = r5l_log_endio;
io->current_bio->bi_private = io;
- bio_add_page(io->current_bio, io->meta_page, PAGE_SIZE, 0);
+ __bio_add_page(io->current_bio, io->meta_page, PAGE_SIZE, 0);
r5_reserve_log_entry(log, io);
@@ -1576,17 +1576,18 @@ void r5l_wake_reclaim(struct r5l_log *log, sector_t space)
void r5l_quiesce(struct r5l_log *log, int quiesce)
{
- struct mddev *mddev;
+ struct mddev *mddev = log->rdev->mddev;
+ struct md_thread *thread = rcu_dereference_protected(
+ log->reclaim_thread, lockdep_is_held(&mddev->reconfig_mutex));
if (quiesce) {
/* make sure r5l_write_super_and_discard_space exits */
- mddev = log->rdev->mddev;
wake_up(&mddev->sb_wait);
- kthread_park(log->reclaim_thread->tsk);
+ kthread_park(thread->tsk);
r5l_wake_reclaim(log, MaxSector);
r5l_do_reclaim(log);
} else
- kthread_unpark(log->reclaim_thread->tsk);
+ kthread_unpark(thread->tsk);
}
bool r5l_log_disk_error(struct r5conf *conf)
@@ -3063,6 +3064,7 @@ void r5c_update_on_rdev_error(struct mddev *mddev, struct md_rdev *rdev)
int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)
{
struct r5l_log *log;
+ struct md_thread *thread;
int ret;
pr_debug("md/raid:%s: using device %pg as journal\n",
@@ -3121,11 +3123,13 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)
spin_lock_init(&log->tree_lock);
INIT_RADIX_TREE(&log->big_stripe_tree, GFP_NOWAIT | __GFP_NOWARN);
- log->reclaim_thread = md_register_thread(r5l_reclaim_thread,
- log->rdev->mddev, "reclaim");
- if (!log->reclaim_thread)
+ thread = md_register_thread(r5l_reclaim_thread, log->rdev->mddev,
+ "reclaim");
+ if (!thread)
goto reclaim_thread;
- log->reclaim_thread->timeout = R5C_RECLAIM_WAKEUP_INTERVAL;
+
+ thread->timeout = R5C_RECLAIM_WAKEUP_INTERVAL;
+ rcu_assign_pointer(log->reclaim_thread, thread);
init_waitqueue_head(&log->iounit_wait);
diff --git a/drivers/md/raid5-ppl.c b/drivers/md/raid5-ppl.c
index e495939bb3e0..eaea57aee602 100644
--- a/drivers/md/raid5-ppl.c
+++ b/drivers/md/raid5-ppl.c
@@ -465,7 +465,7 @@ static void ppl_submit_iounit(struct ppl_io_unit *io)
bio->bi_end_io = ppl_log_endio;
bio->bi_iter.bi_sector = log->next_io_sector;
- bio_add_page(bio, io->header_page, PAGE_SIZE, 0);
+ __bio_add_page(bio, io->header_page, PAGE_SIZE, 0);
pr_debug("%s: log->current_io_sector: %llu\n", __func__,
(unsigned long long)log->next_io_sector);
@@ -496,7 +496,7 @@ static void ppl_submit_iounit(struct ppl_io_unit *io)
prev->bi_opf, GFP_NOIO,
&ppl_conf->bs);
bio->bi_iter.bi_sector = bio_end_sector(prev);
- bio_add_page(bio, sh->ppl_page, PAGE_SIZE, 0);
+ __bio_add_page(bio, sh->ppl_page, PAGE_SIZE, 0);
bio_chain(bio, prev);
ppl_submit_iounit_bio(io, prev);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 9ea285fbc4a6..85b3004594e0 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2433,7 +2433,7 @@ static int grow_stripes(struct r5conf *conf, int num)
conf->active_name = 0;
sc = kmem_cache_create(conf->cache_name[conf->active_name],
- sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
+ struct_size_t(struct stripe_head, dev, devs),
0, 0, NULL);
if (!sc)
return 1;
@@ -2559,7 +2559,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
/* Step 1 */
sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
- sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev),
+ struct_size_t(struct stripe_head, dev, newsize),
0, 0, NULL);
if (!sc)
return -ENOMEM;
@@ -5966,6 +5966,19 @@ out:
return ret;
}
+static bool reshape_inprogress(struct mddev *mddev)
+{
+ return test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
+ test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
+ !test_bit(MD_RECOVERY_DONE, &mddev->recovery) &&
+ !test_bit(MD_RECOVERY_INTR, &mddev->recovery);
+}
+
+static bool reshape_disabled(struct mddev *mddev)
+{
+ return is_md_suspended(mddev) || !md_is_rdwr(mddev);
+}
+
static enum stripe_result make_stripe_request(struct mddev *mddev,
struct r5conf *conf, struct stripe_request_ctx *ctx,
sector_t logical_sector, struct bio *bi)
@@ -5997,7 +6010,8 @@ static enum stripe_result make_stripe_request(struct mddev *mddev,
if (ahead_of_reshape(mddev, logical_sector,
conf->reshape_safe)) {
spin_unlock_irq(&conf->device_lock);
- return STRIPE_SCHEDULE_AND_RETRY;
+ ret = STRIPE_SCHEDULE_AND_RETRY;
+ goto out;
}
}
spin_unlock_irq(&conf->device_lock);
@@ -6076,6 +6090,15 @@ static enum stripe_result make_stripe_request(struct mddev *mddev,
out_release:
raid5_release_stripe(sh);
+out:
+ if (ret == STRIPE_SCHEDULE_AND_RETRY && !reshape_inprogress(mddev) &&
+ reshape_disabled(mddev)) {
+ bi->bi_status = BLK_STS_IOERR;
+ ret = STRIPE_FAIL;
+ pr_err("md/raid456:%s: io failed across reshape position while reshape can't make progress.\n",
+ mdname(mddev));
+ }
+
return ret;
}
@@ -7708,7 +7731,8 @@ static struct r5conf *setup_conf(struct mddev *mddev)
}
sprintf(pers_name, "raid%d", mddev->new_level);
- conf->thread = md_register_thread(raid5d, mddev, pers_name);
+ rcu_assign_pointer(conf->thread,
+ md_register_thread(raid5d, mddev, pers_name));
if (!conf->thread) {
pr_warn("md/raid:%s: couldn't allocate thread.\n",
mdname(mddev));
@@ -7931,8 +7955,8 @@ static int raid5_run(struct mddev *mddev)
}
conf->min_offset_diff = min_offset_diff;
- mddev->thread = conf->thread;
- conf->thread = NULL;
+ rcu_assign_pointer(mddev->thread, conf->thread);
+ rcu_assign_pointer(conf->thread, NULL);
mddev->private = conf;
for (i = 0; i < conf->raid_disks && conf->previous_raid_disks;
@@ -8029,8 +8053,8 @@ static int raid5_run(struct mddev *mddev)
clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
- mddev->sync_thread = md_register_thread(md_do_sync, mddev,
- "reshape");
+ rcu_assign_pointer(mddev->sync_thread,
+ md_register_thread(md_do_sync, mddev, "reshape"));
if (!mddev->sync_thread)
goto abort;
}
@@ -8377,6 +8401,7 @@ static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev)
p = conf->disks + disk;
tmp = rdev_mdlock_deref(mddev, p->rdev);
if (test_bit(WantReplacement, &tmp->flags) &&
+ mddev->reshape_position == MaxSector &&
p->replacement == NULL) {
clear_bit(In_sync, &rdev->flags);
set_bit(Replacement, &rdev->flags);
@@ -8500,6 +8525,7 @@ static int raid5_start_reshape(struct mddev *mddev)
struct r5conf *conf = mddev->private;
struct md_rdev *rdev;
int spares = 0;
+ int i;
unsigned long flags;
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
@@ -8511,6 +8537,13 @@ static int raid5_start_reshape(struct mddev *mddev)
if (has_failed(conf))
return -EINVAL;
+ /* raid5 can't handle concurrent reshape and recovery */
+ if (mddev->recovery_cp < MaxSector)
+ return -EBUSY;
+ for (i = 0; i < conf->raid_disks; i++)
+ if (rdev_mdlock_deref(mddev, conf->disks[i].replacement))
+ return -EBUSY;
+
rdev_for_each(rdev, mddev) {
if (!test_bit(In_sync, &rdev->flags)
&& !test_bit(Faulty, &rdev->flags))
@@ -8607,8 +8640,8 @@ static int raid5_start_reshape(struct mddev *mddev)
clear_bit(MD_RECOVERY_DONE, &mddev->recovery);
set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
- mddev->sync_thread = md_register_thread(md_do_sync, mddev,
- "reshape");
+ rcu_assign_pointer(mddev->sync_thread,
+ md_register_thread(md_do_sync, mddev, "reshape"));
if (!mddev->sync_thread) {
mddev->recovery = 0;
spin_lock_irq(&conf->device_lock);
@@ -9043,6 +9076,22 @@ static int raid5_start(struct mddev *mddev)
return r5l_start(conf->log);
}
+static void raid5_prepare_suspend(struct mddev *mddev)
+{
+ struct r5conf *conf = mddev->private;
+
+ wait_event(mddev->sb_wait, !reshape_inprogress(mddev) ||
+ percpu_ref_is_zero(&mddev->active_io));
+ if (percpu_ref_is_zero(&mddev->active_io))
+ return;
+
+ /*
+ * Reshape is not in progress, and array is suspended, io that is
+ * waiting for reshpape can never be done.
+ */
+ wake_up(&conf->wait_for_overlap);
+}
+
static struct md_personality raid6_personality =
{
.name = "raid6",
@@ -9063,6 +9112,7 @@ static struct md_personality raid6_personality =
.check_reshape = raid6_check_reshape,
.start_reshape = raid5_start_reshape,
.finish_reshape = raid5_finish_reshape,
+ .prepare_suspend = raid5_prepare_suspend,
.quiesce = raid5_quiesce,
.takeover = raid6_takeover,
.change_consistency_policy = raid5_change_consistency_policy,
@@ -9087,6 +9137,7 @@ static struct md_personality raid5_personality =
.check_reshape = raid5_check_reshape,
.start_reshape = raid5_start_reshape,
.finish_reshape = raid5_finish_reshape,
+ .prepare_suspend = raid5_prepare_suspend,
.quiesce = raid5_quiesce,
.takeover = raid5_takeover,
.change_consistency_policy = raid5_change_consistency_policy,
@@ -9112,6 +9163,7 @@ static struct md_personality raid4_personality =
.check_reshape = raid5_check_reshape,
.start_reshape = raid5_start_reshape,
.finish_reshape = raid5_finish_reshape,
+ .prepare_suspend = raid5_prepare_suspend,
.quiesce = raid5_quiesce,
.takeover = raid4_takeover,
.change_consistency_policy = raid5_change_consistency_policy,
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index e873938a6125..97a795979a35 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -268,7 +268,7 @@ struct stripe_head {
unsigned long flags;
u32 log_checksum;
unsigned short write_hint;
- } dev[1]; /* allocated with extra space depending of RAID geometry */
+ } dev[]; /* allocated depending of RAID geometry ("disks" member) */
};
/* stripe_head_state - collects and tracks the dynamic state of a stripe_head
@@ -679,7 +679,7 @@ struct r5conf {
/* When taking over an array from a different personality, we store
* the new thread here until we fully activate the array.
*/
- struct md_thread *thread;
+ struct md_thread __rcu *thread;
struct list_head temp_inactive_list[NR_STRIPE_HASH_LOCKS];
struct r5worker_group *worker_groups;
int group_cnt;
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/cec/usb/pulse8/pulse8-cec.c b/drivers/media/cec/usb/pulse8/pulse8-cec.c
index 04b13cdc38d2..ba67587bd43e 100644
--- a/drivers/media/cec/usb/pulse8/pulse8-cec.c
+++ b/drivers/media/cec/usb/pulse8/pulse8-cec.c
@@ -809,8 +809,11 @@ static void pulse8_ping_eeprom_work_handler(struct work_struct *work)
mutex_lock(&pulse8->lock);
cmd = MSGCODE_PING;
- pulse8_send_and_wait(pulse8, &cmd, 1,
- MSGCODE_COMMAND_ACCEPTED, 0);
+ if (pulse8_send_and_wait(pulse8, &cmd, 1,
+ MSGCODE_COMMAND_ACCEPTED, 0)) {
+ dev_warn(pulse8->dev, "failed to ping EEPROM\n");
+ goto unlock;
+ }
if (pulse8->vers < 2)
goto unlock;
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..3f7e147ef594 100644
--- a/drivers/media/i2c/tc358746.c
+++ b/drivers/media/i2c/tc358746.c
@@ -813,8 +813,8 @@ static unsigned long tc358746_find_pll_settings(struct tc358746 *tc358746,
u32 min_delta = 0xffffffff;
u16 prediv_max = 17;
u16 prediv_min = 1;
- u16 m_best, mul;
- u16 p_best, p;
+ u16 m_best = 0, mul;
+ u16 p_best = 1, p;
u8 postdiv;
if (fout > 1000 * HZ_PER_MHZ) {
@@ -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/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index 8fd5b6ef2428..7551ca4a322a 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -2459,16 +2459,10 @@ static int dvb_register(struct cx23885_tsport *port)
request_module("%s", info.type);
client_tuner = i2c_new_client_device(&dev->i2c_bus[1].i2c_adap, &info);
if (!i2c_client_has_driver(client_tuner)) {
- module_put(client_demod->dev.driver->owner);
- i2c_unregister_device(client_demod);
- port->i2c_client_demod = NULL;
goto frontend_detach;
}
if (!try_module_get(client_tuner->dev.driver->owner)) {
i2c_unregister_device(client_tuner);
- module_put(client_demod->dev.driver->owner);
- i2c_unregister_device(client_demod);
- port->i2c_client_demod = NULL;
goto frontend_detach;
}
port->i2c_client_tuner = client_tuner;
@@ -2505,16 +2499,10 @@ static int dvb_register(struct cx23885_tsport *port)
request_module("%s", info.type);
client_tuner = i2c_new_client_device(&dev->i2c_bus[1].i2c_adap, &info);
if (!i2c_client_has_driver(client_tuner)) {
- module_put(client_demod->dev.driver->owner);
- i2c_unregister_device(client_demod);
- port->i2c_client_demod = NULL;
goto frontend_detach;
}
if (!try_module_get(client_tuner->dev.driver->owner)) {
i2c_unregister_device(client_tuner);
- module_put(client_demod->dev.driver->owner);
- i2c_unregister_device(client_demod);
- port->i2c_client_demod = NULL;
goto frontend_detach;
}
port->i2c_client_tuner = client_tuner;
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_core.c b/drivers/media/platform/amphion/vpu_core.c
index de23627a119a..7863b7b53494 100644
--- a/drivers/media/platform/amphion/vpu_core.c
+++ b/drivers/media/platform/amphion/vpu_core.c
@@ -254,7 +254,7 @@ static int vpu_core_register(struct device *dev, struct vpu_core *core)
if (vpu_core_is_exist(vpu, core))
return 0;
- core->workqueue = alloc_workqueue("vpu", WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+ core->workqueue = alloc_ordered_workqueue("vpu", WQ_MEM_RECLAIM);
if (!core->workqueue) {
dev_err(core->dev, "fail to alloc workqueue\n");
return -ENOMEM;
@@ -826,7 +826,7 @@ static const struct dev_pm_ops vpu_core_pm_ops = {
static struct vpu_core_resources imx8q_enc = {
.type = VPU_CORE_TYPE_ENC,
- .fwname = "vpu/vpu_fw_imx8_enc.bin",
+ .fwname = "amphion/vpu/vpu_fw_imx8_enc.bin",
.stride = 16,
.max_width = 1920,
.max_height = 1920,
@@ -841,7 +841,7 @@ static struct vpu_core_resources imx8q_enc = {
static struct vpu_core_resources imx8q_dec = {
.type = VPU_CORE_TYPE_DEC,
- .fwname = "vpu/vpu_fw_imx8_dec.bin",
+ .fwname = "amphion/vpu/vpu_fw_imx8_dec.bin",
.stride = 256,
.max_width = 8188,
.max_height = 8188,
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_mbox.c b/drivers/media/platform/amphion/vpu_mbox.c
index bf759eb2fd46..b6d5b4844f67 100644
--- a/drivers/media/platform/amphion/vpu_mbox.c
+++ b/drivers/media/platform/amphion/vpu_mbox.c
@@ -46,11 +46,10 @@ static int vpu_mbox_request_channel(struct device *dev, struct vpu_mbox *mbox)
cl->rx_callback = vpu_mbox_rx_callback;
ch = mbox_request_channel_byname(cl, mbox->name);
- if (IS_ERR(ch)) {
- dev_err(dev, "Failed to request mbox chan %s, ret : %ld\n",
- mbox->name, PTR_ERR(ch));
- return PTR_ERR(ch);
- }
+ if (IS_ERR(ch))
+ return dev_err_probe(dev, PTR_ERR(ch),
+ "Failed to request mbox chan %s\n",
+ mbox->name);
mbox->ch = ch;
return 0;
diff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c
index 6773b885597c..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;
}
@@ -740,7 +741,7 @@ int vpu_v4l2_open(struct file *file, struct vpu_inst *inst)
inst->fh.ctrl_handler = &inst->ctrl_handler;
file->private_data = &inst->fh;
inst->state = VPU_CODEC_STATE_DEINIT;
- inst->workqueue = alloc_workqueue("vpu_inst", WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+ inst->workqueue = alloc_ordered_workqueue("vpu_inst", WQ_MEM_RECLAIM);
if (inst->workqueue) {
INIT_WORK(&inst->msg_work, vpu_inst_run_work);
ret = kfifo_init(&inst->msg_fifo,
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/chips-media/coda-common.c b/drivers/media/platform/chips-media/coda-common.c
index d013ea5d9d3d..ac9a642ae76f 100644
--- a/drivers/media/platform/chips-media/coda-common.c
+++ b/drivers/media/platform/chips-media/coda-common.c
@@ -3268,7 +3268,7 @@ static int coda_probe(struct platform_device *pdev)
&dev->iram.blob);
}
- dev->workqueue = alloc_workqueue("coda", WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+ dev->workqueue = alloc_ordered_workqueue("coda", WQ_MEM_RECLAIM);
if (!dev->workqueue) {
dev_err(&pdev->dev, "unable to alloc workqueue\n");
ret = -ENOMEM;
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
index 0051f372a66c..60425c99a2b8 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
@@ -936,148 +936,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 +986,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 +1121,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 +1233,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,
@@ -1723,6 +1310,8 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
jpeg->dev = &pdev->dev;
jpeg->variant = of_device_get_match_data(jpeg->dev);
+ platform_set_drvdata(pdev, jpeg);
+
ret = devm_of_platform_populate(&pdev->dev);
if (ret) {
v4l2_err(&jpeg->v4l2_dev, "Master of platform populate failed.");
@@ -1794,8 +1383,6 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
jpeg->variant->dev_name, jpeg->vdev->num,
VIDEO_MAJOR, jpeg->vdev->minor);
- platform_set_drvdata(pdev, jpeg);
-
pm_runtime_enable(&pdev->dev);
return 0;
@@ -1866,7 +1453,419 @@ static const struct dev_pm_ops mtk_jpeg_pm_ops = {
SET_RUNTIME_PM_OPS(mtk_jpeg_pm_suspend, mtk_jpeg_pm_resume, NULL)
};
-#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),
@@ -1949,14 +1948,13 @@ static const struct of_device_id mtk_jpeg_match[] = {
};
MODULE_DEVICE_TABLE(of, mtk_jpeg_match);
-#endif
static struct platform_driver mtk_jpeg_driver = {
.probe = mtk_jpeg_probe,
.remove_new = mtk_jpeg_remove,
.driver = {
.name = MTK_JPEG_NAME,
- .of_match_table = of_match_ptr(mtk_jpeg_match),
+ .of_match_table = mtk_jpeg_match,
.pm = &mtk_jpeg_pm_ops,
},
};
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
index 869068fac5e2..baa7be58ce69 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
@@ -39,7 +39,6 @@ enum mtk_jpeg_color {
MTK_JPEG_COLOR_400 = 0x00110000
};
-#if defined(CONFIG_OF)
static const struct of_device_id mtk_jpegdec_hw_ids[] = {
{
.compatible = "mediatek,mt8195-jpgdec-hw",
@@ -47,7 +46,6 @@ static const struct of_device_id mtk_jpegdec_hw_ids[] = {
{},
};
MODULE_DEVICE_TABLE(of, mtk_jpegdec_hw_ids);
-#endif
static inline int mtk_jpeg_verify_align(u32 val, int align, u32 reg)
{
@@ -653,7 +651,7 @@ static struct platform_driver mtk_jpegdec_hw_driver = {
.probe = mtk_jpegdec_hw_probe,
.driver = {
.name = "mtk-jpegdec-hw",
- .of_match_table = of_match_ptr(mtk_jpegdec_hw_ids),
+ .of_match_table = mtk_jpegdec_hw_ids,
},
};
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/jpeg/mtk_jpeg_enc_hw.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
index 71e85b4bbf12..244018365b6f 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
@@ -46,7 +46,6 @@ static const struct mtk_jpeg_enc_qlt mtk_jpeg_enc_quality[] = {
{.quality_param = 97, .hardware_value = JPEG_ENC_QUALITY_Q97},
};
-#if defined(CONFIG_OF)
static const struct of_device_id mtk_jpegenc_drv_ids[] = {
{
.compatible = "mediatek,mt8195-jpgenc-hw",
@@ -54,7 +53,6 @@ static const struct of_device_id mtk_jpegenc_drv_ids[] = {
{},
};
MODULE_DEVICE_TABLE(of, mtk_jpegenc_drv_ids);
-#endif
void mtk_jpeg_enc_reset(void __iomem *base)
{
@@ -377,7 +375,7 @@ static struct platform_driver mtk_jpegenc_hw_driver = {
.probe = mtk_jpegenc_hw_probe,
.driver = {
.name = "mtk-jpegenc-hw",
- .of_match_table = of_match_ptr(mtk_jpegenc_drv_ids),
+ .of_match_table = mtk_jpegenc_drv_ids,
},
};
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..315e97a2450e 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;
@@ -821,6 +821,8 @@ static int vb2ops_venc_queue_setup(struct vb2_queue *vq,
return -EINVAL;
if (*nplanes) {
+ if (*nplanes != q_data->fmt->num_planes)
+ return -EINVAL;
for (i = 0; i < *nplanes; i++)
if (sizes[i] < q_data->sizeimage[i])
return -EINVAL;
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..04e6dc6cfa1d 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,19 @@ 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);
}
+
+ if (msg_queue->wdma_addr.size)
+ cancel_work_sync(&msg_queue->core_work);
}
static void vdec_msg_queue_core_work(struct work_struct *work)
@@ -261,12 +245,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 +272,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 +292,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 +312,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 +333,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 +357,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/imx-jpeg/mxc-jpeg-hw.h b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.h
index ed15ea348f97..a2b4fb9e29e7 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.h
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.h
@@ -58,7 +58,6 @@
#define CAST_OFBSIZE_LO CAST_STATUS18
#define CAST_OFBSIZE_HI CAST_STATUS19
-#define MXC_MAX_SLOTS 1 /* TODO use all 4 slots*/
/* JPEG-Decoder Wrapper Slot Registers 0..3 */
#define SLOT_BASE 0x10000
#define SLOT_STATUS 0x0
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index c0e49be42450..9512c0a61966 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -745,87 +745,77 @@ static void notify_src_chg(struct mxc_jpeg_ctx *ctx)
v4l2_event_queue_fh(&ctx->fh, &ev);
}
-static int mxc_get_free_slot(struct mxc_jpeg_slot_data slot_data[], int n)
+static int mxc_get_free_slot(struct mxc_jpeg_slot_data *slot_data)
{
- int free_slot = 0;
-
- while (slot_data[free_slot].used && free_slot < n)
- free_slot++;
-
- return free_slot; /* >=n when there are no more free slots */
+ if (!slot_data->used)
+ return slot_data->slot;
+ return -1;
}
-static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg,
- unsigned int slot)
+static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg)
{
struct mxc_jpeg_desc *desc;
struct mxc_jpeg_desc *cfg_desc;
void *cfg_stm;
- if (jpeg->slot_data[slot].desc)
+ if (jpeg->slot_data.desc)
goto skip_alloc; /* already allocated, reuse it */
/* allocate descriptor for decoding/encoding phase */
desc = dma_alloc_coherent(jpeg->dev,
sizeof(struct mxc_jpeg_desc),
- &jpeg->slot_data[slot].desc_handle,
+ &jpeg->slot_data.desc_handle,
GFP_ATOMIC);
if (!desc)
goto err;
- jpeg->slot_data[slot].desc = desc;
+ jpeg->slot_data.desc = desc;
/* allocate descriptor for configuration phase (encoder only) */
cfg_desc = dma_alloc_coherent(jpeg->dev,
sizeof(struct mxc_jpeg_desc),
- &jpeg->slot_data[slot].cfg_desc_handle,
+ &jpeg->slot_data.cfg_desc_handle,
GFP_ATOMIC);
if (!cfg_desc)
goto err;
- jpeg->slot_data[slot].cfg_desc = cfg_desc;
+ jpeg->slot_data.cfg_desc = cfg_desc;
/* allocate configuration stream */
cfg_stm = dma_alloc_coherent(jpeg->dev,
MXC_JPEG_MAX_CFG_STREAM,
- &jpeg->slot_data[slot].cfg_stream_handle,
+ &jpeg->slot_data.cfg_stream_handle,
GFP_ATOMIC);
if (!cfg_stm)
goto err;
- jpeg->slot_data[slot].cfg_stream_vaddr = cfg_stm;
+ jpeg->slot_data.cfg_stream_vaddr = cfg_stm;
skip_alloc:
- jpeg->slot_data[slot].used = true;
+ jpeg->slot_data.used = true;
return true;
err:
- dev_err(jpeg->dev, "Could not allocate descriptors for slot %d", slot);
+ dev_err(jpeg->dev, "Could not allocate descriptors for slot %d", jpeg->slot_data.slot);
return false;
}
-static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg,
- unsigned int slot)
+static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg)
{
- if (slot >= MXC_MAX_SLOTS) {
- dev_err(jpeg->dev, "Invalid slot %d, nothing to free.", slot);
- return;
- }
-
/* free descriptor for decoding/encoding phase */
dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
- jpeg->slot_data[slot].desc,
- jpeg->slot_data[slot].desc_handle);
+ jpeg->slot_data.desc,
+ jpeg->slot_data.desc_handle);
/* free descriptor for encoder configuration phase / decoder DHT */
dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
- jpeg->slot_data[slot].cfg_desc,
- jpeg->slot_data[slot].cfg_desc_handle);
+ jpeg->slot_data.cfg_desc,
+ jpeg->slot_data.cfg_desc_handle);
/* free configuration stream */
dma_free_coherent(jpeg->dev, MXC_JPEG_MAX_CFG_STREAM,
- jpeg->slot_data[slot].cfg_stream_vaddr,
- jpeg->slot_data[slot].cfg_stream_handle);
+ jpeg->slot_data.cfg_stream_vaddr,
+ jpeg->slot_data.cfg_stream_handle);
- jpeg->slot_data[slot].used = false;
+ jpeg->slot_data.used = false;
}
static void mxc_jpeg_check_and_set_last_buffer(struct mxc_jpeg_ctx *ctx,
@@ -855,7 +845,7 @@ static void mxc_jpeg_job_finish(struct mxc_jpeg_ctx *ctx, enum vb2_buffer_state
v4l2_m2m_buf_done(dst_buf, state);
mxc_jpeg_disable_irq(reg, ctx->slot);
- ctx->mxc_jpeg->slot_data[ctx->slot].used = false;
+ jpeg->slot_data.used = false;
if (reset)
mxc_jpeg_sw_reset(reg);
}
@@ -919,7 +909,7 @@ static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv)
goto job_unlock;
}
- if (!jpeg->slot_data[slot].used)
+ if (!jpeg->slot_data.used)
goto job_unlock;
dec_ret = readl(reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS));
@@ -1179,13 +1169,13 @@ static void mxc_jpeg_config_dec_desc(struct vb2_buffer *out_buf,
struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
void __iomem *reg = jpeg->base_reg;
unsigned int slot = ctx->slot;
- struct mxc_jpeg_desc *desc = jpeg->slot_data[slot].desc;
- struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data[slot].cfg_desc;
- dma_addr_t desc_handle = jpeg->slot_data[slot].desc_handle;
- dma_addr_t cfg_desc_handle = jpeg->slot_data[slot].cfg_desc_handle;
- dma_addr_t cfg_stream_handle = jpeg->slot_data[slot].cfg_stream_handle;
- unsigned int *cfg_size = &jpeg->slot_data[slot].cfg_stream_size;
- void *cfg_stream_vaddr = jpeg->slot_data[slot].cfg_stream_vaddr;
+ struct mxc_jpeg_desc *desc = jpeg->slot_data.desc;
+ struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data.cfg_desc;
+ dma_addr_t desc_handle = jpeg->slot_data.desc_handle;
+ dma_addr_t cfg_desc_handle = jpeg->slot_data.cfg_desc_handle;
+ dma_addr_t cfg_stream_handle = jpeg->slot_data.cfg_stream_handle;
+ unsigned int *cfg_size = &jpeg->slot_data.cfg_stream_size;
+ void *cfg_stream_vaddr = jpeg->slot_data.cfg_stream_vaddr;
struct mxc_jpeg_src_buf *jpeg_src_buf;
jpeg_src_buf = vb2_to_mxc_buf(src_buf);
@@ -1245,18 +1235,18 @@ static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf,
struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
void __iomem *reg = jpeg->base_reg;
unsigned int slot = ctx->slot;
- struct mxc_jpeg_desc *desc = jpeg->slot_data[slot].desc;
- struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data[slot].cfg_desc;
- dma_addr_t desc_handle = jpeg->slot_data[slot].desc_handle;
- dma_addr_t cfg_desc_handle = jpeg->slot_data[slot].cfg_desc_handle;
- void *cfg_stream_vaddr = jpeg->slot_data[slot].cfg_stream_vaddr;
+ struct mxc_jpeg_desc *desc = jpeg->slot_data.desc;
+ struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data.cfg_desc;
+ dma_addr_t desc_handle = jpeg->slot_data.desc_handle;
+ dma_addr_t cfg_desc_handle = jpeg->slot_data.cfg_desc_handle;
+ void *cfg_stream_vaddr = jpeg->slot_data.cfg_stream_vaddr;
struct mxc_jpeg_q_data *q_data;
enum mxc_jpeg_image_format img_fmt;
int w, h;
q_data = mxc_jpeg_get_q_data(ctx, src_buf->vb2_queue->type);
- jpeg->slot_data[slot].cfg_stream_size =
+ jpeg->slot_data.cfg_stream_size =
mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr,
q_data->fmt->fourcc,
q_data->crop.width,
@@ -1265,7 +1255,7 @@ static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf,
/* chain the config descriptor with the encoding descriptor */
cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN;
- cfg_desc->buf_base0 = jpeg->slot_data[slot].cfg_stream_handle;
+ cfg_desc->buf_base0 = jpeg->slot_data.cfg_stream_handle;
cfg_desc->buf_base1 = 0;
cfg_desc->line_pitch = 0;
cfg_desc->stm_bufbase = 0; /* no output expected */
@@ -1408,7 +1398,7 @@ static void mxc_jpeg_device_run_timeout(struct work_struct *work)
unsigned long flags;
spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags);
- if (ctx->slot < MXC_MAX_SLOTS && ctx->mxc_jpeg->slot_data[ctx->slot].used) {
+ if (ctx->mxc_jpeg->slot_data.used) {
dev_warn(jpeg->dev, "%s timeout, cancel it\n",
ctx->mxc_jpeg->mode == MXC_JPEG_DECODE ? "decode" : "encode");
mxc_jpeg_job_finish(ctx, VB2_BUF_STATE_ERROR, true);
@@ -1476,12 +1466,12 @@ static void mxc_jpeg_device_run(void *priv)
mxc_jpeg_enable(reg);
mxc_jpeg_set_l_endian(reg, 1);
- ctx->slot = mxc_get_free_slot(jpeg->slot_data, MXC_MAX_SLOTS);
- if (ctx->slot >= MXC_MAX_SLOTS) {
+ ctx->slot = mxc_get_free_slot(&jpeg->slot_data);
+ if (ctx->slot < 0) {
dev_err(dev, "No more free slots\n");
goto end;
}
- if (!mxc_jpeg_alloc_slot_data(jpeg, ctx->slot)) {
+ if (!mxc_jpeg_alloc_slot_data(jpeg)) {
dev_err(dev, "Cannot allocate slot data\n");
goto end;
}
@@ -2101,7 +2091,7 @@ static int mxc_jpeg_open(struct file *file)
}
ctx->fh.ctrl_handler = &ctx->ctrl_handler;
mxc_jpeg_set_default_params(ctx);
- ctx->slot = MXC_MAX_SLOTS; /* slot not allocated yet */
+ ctx->slot = -1; /* slot not allocated yet */
INIT_DELAYED_WORK(&ctx->task_timer, mxc_jpeg_device_run_timeout);
if (mxc_jpeg->mode == MXC_JPEG_DECODE)
@@ -2677,6 +2667,11 @@ static int mxc_jpeg_attach_pm_domains(struct mxc_jpeg_dev *jpeg)
dev_err(dev, "No power domains defined for jpeg node\n");
return jpeg->num_domains;
}
+ if (jpeg->num_domains == 1) {
+ /* genpd_dev_pm_attach() attach automatically if power domains count is 1 */
+ jpeg->num_domains = 0;
+ return 0;
+ }
jpeg->pd_dev = devm_kmalloc_array(dev, jpeg->num_domains,
sizeof(*jpeg->pd_dev), GFP_KERNEL);
@@ -2718,7 +2713,6 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
int ret;
int mode;
const struct of_device_id *of_id;
- unsigned int slot;
of_id = of_match_node(mxc_jpeg_match, dev->of_node);
if (!of_id)
@@ -2742,19 +2736,22 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
if (IS_ERR(jpeg->base_reg))
return PTR_ERR(jpeg->base_reg);
- for (slot = 0; slot < MXC_MAX_SLOTS; slot++) {
- dec_irq = platform_get_irq(pdev, slot);
- if (dec_irq < 0) {
- ret = dec_irq;
- goto err_irq;
- }
- ret = devm_request_irq(&pdev->dev, dec_irq, mxc_jpeg_dec_irq,
- 0, pdev->name, jpeg);
- if (ret) {
- dev_err(&pdev->dev, "Failed to request irq %d (%d)\n",
- dec_irq, ret);
- goto err_irq;
- }
+ ret = of_property_read_u32_index(pdev->dev.of_node, "slot", 0, &jpeg->slot_data.slot);
+ if (ret)
+ jpeg->slot_data.slot = 0;
+ dev_info(&pdev->dev, "choose slot %d\n", jpeg->slot_data.slot);
+ dec_irq = platform_get_irq(pdev, 0);
+ if (dec_irq < 0) {
+ dev_err(&pdev->dev, "Failed to get irq %d\n", dec_irq);
+ ret = dec_irq;
+ goto err_irq;
+ }
+ ret = devm_request_irq(&pdev->dev, dec_irq, mxc_jpeg_dec_irq,
+ 0, pdev->name, jpeg);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request irq %d (%d)\n",
+ dec_irq, ret);
+ goto err_irq;
}
jpeg->pdev = pdev;
@@ -2914,11 +2911,9 @@ static const struct dev_pm_ops mxc_jpeg_pm_ops = {
static void mxc_jpeg_remove(struct platform_device *pdev)
{
- unsigned int slot;
struct mxc_jpeg_dev *jpeg = platform_get_drvdata(pdev);
- for (slot = 0; slot < MXC_MAX_SLOTS; slot++)
- mxc_jpeg_free_slot_data(jpeg, slot);
+ mxc_jpeg_free_slot_data(jpeg);
pm_runtime_disable(&pdev->dev);
video_unregister_device(jpeg->dec_vdev);
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
index 87157db78082..d80e94cc9d99 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
@@ -97,7 +97,7 @@ struct mxc_jpeg_ctx {
struct mxc_jpeg_q_data cap_q;
struct v4l2_fh fh;
enum mxc_jpeg_enc_state enc_state;
- unsigned int slot;
+ int slot;
unsigned int source_change;
bool header_parsed;
struct v4l2_ctrl_handler ctrl_handler;
@@ -106,6 +106,7 @@ struct mxc_jpeg_ctx {
};
struct mxc_jpeg_slot_data {
+ int slot;
bool used;
struct mxc_jpeg_desc *desc; // enc/dec descriptor
struct mxc_jpeg_desc *cfg_desc; // configuration descriptor
@@ -128,7 +129,7 @@ struct mxc_jpeg_dev {
struct v4l2_device v4l2_dev;
struct v4l2_m2m_dev *m2m_dev;
struct video_device *dec_vdev;
- struct mxc_jpeg_slot_data slot_data[MXC_MAX_SLOTS];
+ struct mxc_jpeg_slot_data slot_data;
int num_domains;
struct device **pd_dev;
struct device_link **pd_link;
diff --git a/drivers/media/platform/nxp/imx7-media-csi.c b/drivers/media/platform/nxp/imx7-media-csi.c
index b701e823436a..791bde67f439 100644
--- a/drivers/media/platform/nxp/imx7-media-csi.c
+++ b/drivers/media/platform/nxp/imx7-media-csi.c
@@ -9,7 +9,9 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/math.h>
#include <linux/mfd/syscon.h>
+#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_graph.h>
@@ -1014,39 +1016,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 +1114,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 +1132,20 @@ __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;
+ pixfmt->width = clamp(round_up(pixfmt->width, walign), walign,
+ round_down(65535U, walign));
+ pixfmt->height = clamp(pixfmt->height, 1U, 65535U);
- 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 +1573,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 +1593,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..3418d2dd9371 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_t(struct hfi_session_set_buffers_pkt,
+ 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..77aee9489516 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;
};
};
@@ -362,26 +370,26 @@ extern int hantro_debug;
pr_err("%s:%d: " fmt, __func__, __LINE__, ##args)
/* Structure access helpers. */
-static inline struct hantro_ctx *fh_to_ctx(struct v4l2_fh *fh)
+static __always_inline struct hantro_ctx *fh_to_ctx(struct v4l2_fh *fh)
{
return container_of(fh, struct hantro_ctx, fh);
}
/* Register accessors. */
-static inline void vepu_write_relaxed(struct hantro_dev *vpu,
- u32 val, u32 reg)
+static __always_inline void vepu_write_relaxed(struct hantro_dev *vpu,
+ u32 val, u32 reg)
{
vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
writel_relaxed(val, vpu->enc_base + reg);
}
-static inline void vepu_write(struct hantro_dev *vpu, u32 val, u32 reg)
+static __always_inline void vepu_write(struct hantro_dev *vpu, u32 val, u32 reg)
{
vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
writel(val, vpu->enc_base + reg);
}
-static inline u32 vepu_read(struct hantro_dev *vpu, u32 reg)
+static __always_inline u32 vepu_read(struct hantro_dev *vpu, u32 reg)
{
u32 val = readl(vpu->enc_base + reg);
@@ -389,27 +397,27 @@ static inline u32 vepu_read(struct hantro_dev *vpu, u32 reg)
return val;
}
-static inline void vdpu_write_relaxed(struct hantro_dev *vpu,
- u32 val, u32 reg)
+static __always_inline void vdpu_write_relaxed(struct hantro_dev *vpu,
+ u32 val, u32 reg)
{
vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
writel_relaxed(val, vpu->dec_base + reg);
}
-static inline void vdpu_write(struct hantro_dev *vpu, u32 val, u32 reg)
+static __always_inline void vdpu_write(struct hantro_dev *vpu, u32 val, u32 reg)
{
vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
writel(val, vpu->dec_base + reg);
}
-static inline void hantro_write_addr(struct hantro_dev *vpu,
- unsigned long offset,
- dma_addr_t addr)
+static __always_inline void hantro_write_addr(struct hantro_dev *vpu,
+ unsigned long offset,
+ dma_addr_t addr)
{
vdpu_write(vpu, addr & 0xffffffff, offset);
}
-static inline u32 vdpu_read(struct hantro_dev *vpu, u32 reg)
+static __always_inline u32 vdpu_read(struct hantro_dev *vpu, u32 reg)
{
u32 val = readl(vpu->dec_base + reg);
@@ -417,9 +425,9 @@ static inline u32 vdpu_read(struct hantro_dev *vpu, u32 reg)
return val;
}
-static inline u32 vdpu_read_mask(struct hantro_dev *vpu,
- const struct hantro_reg *reg,
- u32 val)
+static __always_inline u32 vdpu_read_mask(struct hantro_dev *vpu,
+ const struct hantro_reg *reg,
+ u32 val)
{
u32 v;
@@ -429,18 +437,18 @@ static inline u32 vdpu_read_mask(struct hantro_dev *vpu,
return v;
}
-static inline void hantro_reg_write(struct hantro_dev *vpu,
- const struct hantro_reg *reg,
- u32 val)
+static __always_inline void hantro_reg_write(struct hantro_dev *vpu,
+ const struct hantro_reg *reg,
+ u32 val)
{
- vdpu_write_relaxed(vpu, vdpu_read_mask(vpu, reg, val), reg->base);
+ vdpu_write(vpu, vdpu_read_mask(vpu, reg, val), reg->base);
}
-static inline void hantro_reg_write_s(struct hantro_dev *vpu,
- const struct hantro_reg *reg,
- u32 val)
+static __always_inline void hantro_reg_write_relaxed(struct hantro_dev *vpu,
+ const struct hantro_reg *reg,
+ u32 val)
{
- vdpu_write(vpu, vdpu_read_mask(vpu, reg, val), reg->base);
+ vdpu_write_relaxed(vpu, vdpu_read_mask(vpu, reg, val), reg->base);
}
void *hantro_get_ctrl(struct hantro_ctx *ctx, u32 id);
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..0224ff68ab3f 100644
--- a/drivers/media/platform/verisilicon/hantro_postproc.c
+++ b/drivers/media/platform/verisilicon/hantro_postproc.c
@@ -21,11 +21,11 @@
val); \
}
-#define HANTRO_PP_REG_WRITE_S(vpu, reg_name, val) \
+#define HANTRO_PP_REG_WRITE_RELAXED(vpu, reg_name, val) \
{ \
- hantro_reg_write_s(vpu, \
- &hantro_g1_postproc_regs.reg_name, \
- val); \
+ hantro_reg_write_relaxed(vpu, \
+ &hantro_g1_postproc_regs.reg_name, \
+ val); \
}
#define VPU_PP_IN_YUYV 0x0
@@ -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;
}
@@ -68,7 +72,7 @@ static void hantro_postproc_g1_enable(struct hantro_ctx *ctx)
dma_addr_t dst_dma;
/* Turn on pipeline mode. Must be done first. */
- HANTRO_PP_REG_WRITE_S(vpu, pipeline_en, 0x1);
+ HANTRO_PP_REG_WRITE(vpu, pipeline_en, 0x1);
src_pp_fmt = VPU_PP_IN_NV12;
@@ -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];
@@ -235,7 +242,7 @@ static void hantro_postproc_g1_disable(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
- HANTRO_PP_REG_WRITE_S(vpu, pipeline_en, 0x0);
+ HANTRO_PP_REG_WRITE(vpu, pipeline_en, 0x0);
}
static void hantro_postproc_g2_disable(struct hantro_ctx *ctx)
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..f4988f03640a 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -45,7 +45,7 @@ static int uvc_control_add_xu_mapping(struct uvc_video_chain *chain,
map->menu_names = NULL;
map->menu_mapping = NULL;
- map->menu_mask = BIT_MASK(xmap->menu_count);
+ map->menu_mask = GENMASK(xmap->menu_count - 1, 0);
size = xmap->menu_count * sizeof(*map->menu_mapping);
map->menu_mapping = kzalloc(size, GFP_KERNEL);
@@ -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/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c
index 53001532e8e3..405b89ea1054 100644
--- a/drivers/media/v4l2-core/videobuf-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf-dma-sg.c
@@ -180,7 +180,7 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
data, size, dma->nr_pages);
err = pin_user_pages(data & PAGE_MASK, dma->nr_pages, gup_flags,
- dma->pages, NULL);
+ dma->pages);
if (err != dma->nr_pages) {
dma->nr_pages = (err >= 0) ? err : 0;
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..deb6e65b59af 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>
@@ -754,6 +755,43 @@ const char *const tegra_mc_error_names[8] = {
[6] = "SMMU translation error",
};
+struct icc_node *tegra_mc_icc_xlate(struct of_phandle_args *spec, void *data)
+{
+ struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
+ struct icc_node *node;
+
+ list_for_each_entry(node, &mc->provider.nodes, node_list) {
+ if (node->id == spec->args[0])
+ 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 tegra_mc_icc_get(struct icc_node *node, u32 *average, u32 *peak)
+{
+ *average = 0;
+ *peak = 0;
+
+ return 0;
+}
+
+static int tegra_mc_icc_set(struct icc_node *src, struct icc_node *dst)
+{
+ return 0;
+}
+
+const struct tegra_mc_icc_ops tegra_mc_icc_ops = {
+ .xlate = tegra_mc_icc_xlate,
+ .aggregate = icc_std_aggregate,
+ .get_bw = tegra_mc_icc_get,
+ .set = tegra_mc_icc_set,
+};
+
/*
* Memory Controller (MC) has few Memory Clients that are issuing memory
* bandwidth allocation requests to the MC interconnect provider. The MC
@@ -792,6 +830,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 +864,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 +880,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 +935,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/tegra194.c b/drivers/memory/tegra/tegra194.c
index b2416ee3ac26..26035ac3a1eb 100644
--- a/drivers/memory/tegra/tegra194.c
+++ b/drivers/memory/tegra/tegra194.c
@@ -1355,6 +1355,7 @@ const struct tegra_mc_soc tegra194_mc_soc = {
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
.has_addr_hi_reg = true,
.ops = &tegra186_mc_ops,
+ .icc_ops = &tegra_mc_icc_ops,
.ch_intmask = 0x00000f00,
.global_intstatus_channel_shift = 8,
};
diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c
index 02dcc5748bba..8fb83b39f5f5 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,445 @@ 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 0;
+
+ 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 0;
+
+ 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 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 = tegra_mc_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 +916,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/memory/ti-emif-sram-pm.S b/drivers/memory/ti-emif-sram-pm.S
index d60a8cfd63f3..7756b3971244 100644
--- a/drivers/memory/ti-emif-sram-pm.S
+++ b/drivers/memory/ti-emif-sram-pm.S
@@ -8,7 +8,7 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
-#include <asm/memory.h>
+#include <asm/page.h>
#include "emif.h"
#include "ti-emif-asm-offsets.h"
diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c
index 42bfc46842b8..461f5ffd02bc 100644
--- a/drivers/memstick/host/r592.c
+++ b/drivers/memstick/host/r592.c
@@ -44,12 +44,10 @@ static const char *tpc_names[] = {
* memstick_debug_get_tpc_name - debug helper that returns string for
* a TPC number
*/
-const char *memstick_debug_get_tpc_name(int tpc)
+static __maybe_unused const char *memstick_debug_get_tpc_name(int tpc)
{
return tpc_names[tpc-1];
}
-EXPORT_SYMBOL(memstick_debug_get_tpc_name);
-
/* Read a register*/
static inline u32 r592_read_reg(struct r592_device *dev, int address)
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 e90463c4441c..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
@@ -1183,12 +1196,17 @@ config MFD_RC5T583
Additional drivers must be enabled in order to use the
different functionality of the device.
-config MFD_RK808
+config MFD_RK8XX
+ bool
+ select MFD_CORE
+
+config MFD_RK8XX_I2C
tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power Management Chip"
depends on I2C && OF
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
+ select MFD_RK8XX
help
If you say yes here you get support for the RK805, RK808, RK809,
RK817 and RK818 Power Management chips.
@@ -1196,6 +1214,20 @@ config MFD_RK808
through I2C interface. The device supports multiple sub-devices
including interrupts, RTC, LDO & DCDC regulators, and onkey.
+config MFD_RK8XX_SPI
+ tristate "Rockchip RK806 Power Management Chip"
+ depends on SPI && OF
+ select MFD_CORE
+ select REGMAP_SPI
+ select REGMAP_IRQ
+ select MFD_RK8XX
+ help
+ If you say yes here you get support for the RK806 Power Management
+ chip.
+ This driver provides common support for accessing the device
+ through an SPI interface. The device supports multiple sub-devices
+ including interrupts, LDO & DCDC regulators, and power on-key.
+
config MFD_RN5T618
tristate "Ricoh RN5T567/618 PMIC"
depends on I2C
@@ -1679,6 +1711,38 @@ config MFD_TPS65912_SPI
If you say yes here you get support for the TPS65912 series of
PM chips with SPI interface.
+config MFD_TPS6594
+ tristate
+ select MFD_CORE
+ select REGMAP
+ select REGMAP_IRQ
+
+config MFD_TPS6594_I2C
+ tristate "TI TPS6594 Power Management chip with I2C"
+ select MFD_TPS6594
+ select REGMAP_I2C
+ select CRC8
+ depends on I2C
+ help
+ If you say yes here you get support for the TPS6594 series of
+ PM chips with I2C interface.
+
+ This driver can also be built as a module. If so, the module
+ will be called tps6594-i2c.
+
+config MFD_TPS6594_SPI
+ tristate "TI TPS6594 Power Management chip with SPI"
+ select MFD_TPS6594
+ select REGMAP_SPI
+ select CRC8
+ depends on SPI_MASTER
+ help
+ If you say yes here you get support for the TPS6594 series of
+ PM chips with SPI interface.
+
+ This driver can also be built as a module. If so, the module
+ will be called tps6594-spi.
+
config TWL4030_CORE
bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 Support"
depends on I2C=y
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 1d2392f06f78..f3d1f1dc73b5 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -96,6 +96,9 @@ obj-$(CONFIG_MFD_TPS65910) += tps65910.o
obj-$(CONFIG_MFD_TPS65912) += tps65912-core.o
obj-$(CONFIG_MFD_TPS65912_I2C) += tps65912-i2c.o
obj-$(CONFIG_MFD_TPS65912_SPI) += tps65912-spi.o
+obj-$(CONFIG_MFD_TPS6594) += tps6594-core.o
+obj-$(CONFIG_MFD_TPS6594_I2C) += tps6594-i2c.o
+obj-$(CONFIG_MFD_TPS6594_SPI) += tps6594-spi.o
obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o
@@ -151,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
@@ -214,7 +218,9 @@ obj-$(CONFIG_MFD_PALMAS) += palmas.o
obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o
obj-$(CONFIG_MFD_NTXEC) += ntxec.o
obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o
-obj-$(CONFIG_MFD_RK808) += rk808.o
+obj-$(CONFIG_MFD_RK8XX) += rk8xx-core.o
+obj-$(CONFIG_MFD_RK8XX_I2C) += rk8xx-i2c.o
+obj-$(CONFIG_MFD_RK8XX_SPI) += rk8xx-spi.o
obj-$(CONFIG_MFD_RN5T618) += rn5t618.o
obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o
obj-$(CONFIG_MFD_SYSCON) += syscon.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 b4f5cb457117..68d3560cfe4a 100644
--- a/drivers/mfd/axp20x-i2c.c
+++ b/drivers/mfd/axp20x-i2c.c
@@ -59,10 +59,12 @@ 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 },
{ .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
+ { .compatible = "x-powers,axp313a", .data = (void *)AXP313A_ID },
{ .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
{ .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
{ .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID },
@@ -73,10 +75,12 @@ 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 },
{ "axp223", 0 },
+ { "axp313a", 0 },
{ "axp803", 0 },
{ "axp806", 0 },
{ "axp15060", 0 },
@@ -101,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 72b87aae60cc..c03bc5cda080 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -34,11 +34,13 @@
static const char * const axp20x_model_names[] = {
"AXP152",
+ "AXP192",
"AXP202",
"AXP209",
"AXP221",
"AXP223",
"AXP288",
+ "AXP313a",
"AXP803",
"AXP806",
"AXP809",
@@ -93,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),
@@ -156,6 +187,25 @@ static const struct regmap_range axp806_writeable_ranges[] = {
regmap_reg_range(AXP806_REG_ADDR_EXT, AXP806_REG_ADDR_EXT),
};
+static const struct regmap_range axp313a_writeable_ranges[] = {
+ regmap_reg_range(AXP313A_ON_INDICATE, AXP313A_IRQ_STATE),
+};
+
+static const struct regmap_range axp313a_volatile_ranges[] = {
+ regmap_reg_range(AXP313A_SHUTDOWN_CTRL, AXP313A_SHUTDOWN_CTRL),
+ regmap_reg_range(AXP313A_IRQ_STATE, AXP313A_IRQ_STATE),
+};
+
+static const struct regmap_access_table axp313a_writeable_table = {
+ .yes_ranges = axp313a_writeable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(axp313a_writeable_ranges),
+};
+
+static const struct regmap_access_table axp313a_volatile_table = {
+ .yes_ranges = axp313a_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(axp313a_volatile_ranges),
+};
+
static const struct regmap_range axp806_volatile_ranges[] = {
regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE),
};
@@ -200,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"),
@@ -248,6 +311,11 @@ static const struct resource axp288_fuel_gauge_resources[] = {
DEFINE_RES_IRQ(AXP288_IRQ_WL1),
};
+static const struct resource axp313a_pek_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
+ DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
+};
+
static const struct resource axp803_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
@@ -277,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,
@@ -304,6 +381,15 @@ static const struct regmap_config axp288_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
+static const struct regmap_config axp313a_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .wr_table = &axp313a_writeable_table,
+ .volatile_table = &axp313a_volatile_table,
+ .max_register = AXP313A_IRQ_STATE,
+ .cache_type = REGCACHE_RBTREE,
+};
+
static const struct regmap_config axp806_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -345,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),
@@ -456,6 +578,16 @@ static const struct regmap_irq axp288_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1),
};
+static const struct regmap_irq axp313a_regmap_irqs[] = {
+ INIT_REGMAP_IRQ(AXP313A, PEK_RIS_EDGE, 0, 7),
+ INIT_REGMAP_IRQ(AXP313A, PEK_FAL_EDGE, 0, 6),
+ INIT_REGMAP_IRQ(AXP313A, PEK_SHORT, 0, 5),
+ INIT_REGMAP_IRQ(AXP313A, PEK_LONG, 0, 4),
+ INIT_REGMAP_IRQ(AXP313A, DCDC3_V_LOW, 0, 3),
+ INIT_REGMAP_IRQ(AXP313A, DCDC2_V_LOW, 0, 2),
+ INIT_REGMAP_IRQ(AXP313A, DIE_TEMP_HIGH, 0, 0),
+};
+
static const struct regmap_irq axp803_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP803, ACIN_OVER_V, 0, 7),
INIT_REGMAP_IRQ(AXP803, ACIN_PLUGIN, 0, 6),
@@ -571,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,
@@ -606,6 +764,17 @@ static const struct regmap_irq_chip axp288_regmap_irq_chip = {
};
+static const struct regmap_irq_chip axp313a_regmap_irq_chip = {
+ .name = "axp313a_irq_chip",
+ .status_base = AXP313A_IRQ_STATE,
+ .ack_base = AXP313A_IRQ_STATE,
+ .unmask_base = AXP313A_IRQ_EN,
+ .init_ack_masked = true,
+ .irqs = axp313a_regmap_irqs,
+ .num_irqs = ARRAY_SIZE(axp313a_regmap_irqs),
+ .num_regs = 1,
+};
+
static const struct regmap_irq_chip axp803_regmap_irq_chip = {
.name = "axp803",
.status_base = AXP20X_IRQ1_STATE,
@@ -650,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",
@@ -745,6 +935,11 @@ static const struct mfd_cell axp152_cells[] = {
},
};
+static struct mfd_cell axp313a_cells[] = {
+ MFD_CELL_NAME("axp20x-regulator"),
+ MFD_CELL_RES("axp313a-pek", axp313a_pek_resources),
+};
+
static const struct resource axp288_adc_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC"),
};
@@ -914,8 +1109,18 @@ static const struct mfd_cell axp_regulator_only_cells[] = {
static int axp20x_power_off(struct sys_off_data *data)
{
struct axp20x_dev *axp20x = data->cb_data;
+ unsigned int shutdown_reg;
- regmap_write(axp20x->regmap, AXP20X_OFF_CTRL, AXP20X_OFF);
+ switch (axp20x->variant) {
+ case AXP313A_ID:
+ shutdown_reg = AXP313A_SHUTDOWN_CTRL;
+ break;
+ default:
+ shutdown_reg = AXP20X_OFF_CTRL;
+ break;
+ }
+
+ regmap_write(axp20x->regmap, shutdown_reg, AXP20X_OFF);
/* Give capacitors etc. time to drain to avoid kernel panic msg. */
mdelay(500);
@@ -952,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);
@@ -978,6 +1189,12 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
axp20x->irq_flags = IRQF_TRIGGER_LOW;
break;
+ case AXP313A_ID:
+ axp20x->nr_cells = ARRAY_SIZE(axp313a_cells);
+ axp20x->cells = axp313a_cells;
+ axp20x->regmap_cfg = &axp313a_regmap_config;
+ axp20x->regmap_irq_chip = &axp313a_regmap_irq_chip;
+ break;
case AXP803_ID:
axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
axp20x->cells = axp803_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/rk808.c b/drivers/mfd/rk8xx-core.c
index 0f22ef61e817..e8fc9e2ab1d0 100644
--- a/drivers/mfd/rk808.c
+++ b/drivers/mfd/rk8xx-core.c
@@ -1,18 +1,15 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * MFD core driver for Rockchip RK808/RK818
+ * MFD core driver for Rockchip RK8XX
*
* Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ * Copyright (C) 2016 PHYTEC Messtechnik GmbH
*
* Author: Chris Zhong <zyw@rock-chips.com>
* Author: Zhang Qing <zhangqing@rock-chips.com>
- *
- * Copyright (C) 2016 PHYTEC Messtechnik GmbH
- *
* Author: Wadim Egorov <w.egorov@phytec.de>
*/
-#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/mfd/rk808.h>
#include <linux/mfd/core.h>
@@ -27,92 +24,6 @@ struct rk808_reg_data {
int value;
};
-static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
-{
- /*
- * Notes:
- * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
- * we don't use that feature. It's better to cache.
- * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since
- * bits are cleared in case when we shutoff anyway, but better safe.
- */
-
- switch (reg) {
- case RK808_SECONDS_REG ... RK808_WEEKS_REG:
- case RK808_RTC_STATUS_REG:
- case RK808_VB_MON_REG:
- case RK808_THERMAL_REG:
- case RK808_DCDC_UV_STS_REG:
- case RK808_LDO_UV_STS_REG:
- case RK808_DCDC_PG_REG:
- case RK808_LDO_PG_REG:
- case RK808_DEVCTRL_REG:
- case RK808_INT_STS_REG1:
- case RK808_INT_STS_REG2:
- return true;
- }
-
- return false;
-}
-
-static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
-{
- /*
- * Notes:
- * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
- * we don't use that feature. It's better to cache.
- */
-
- switch (reg) {
- case RK817_SECONDS_REG ... RK817_WEEKS_REG:
- case RK817_RTC_STATUS_REG:
- case RK817_CODEC_DTOP_LPT_SRST:
- case RK817_GAS_GAUGE_ADC_CONFIG0 ... RK817_GAS_GAUGE_CUR_ADC_K0:
- case RK817_PMIC_CHRG_STS:
- case RK817_PMIC_CHRG_OUT:
- case RK817_PMIC_CHRG_IN:
- case RK817_INT_STS_REG0:
- case RK817_INT_STS_REG1:
- case RK817_INT_STS_REG2:
- case RK817_SYS_STS:
- return true;
- }
-
- return false;
-}
-
-static const struct regmap_config rk818_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
- .max_register = RK818_USB_CTRL_REG,
- .cache_type = REGCACHE_RBTREE,
- .volatile_reg = rk808_is_volatile_reg,
-};
-
-static const struct regmap_config rk805_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
- .max_register = RK805_OFF_SOURCE_REG,
- .cache_type = REGCACHE_RBTREE,
- .volatile_reg = rk808_is_volatile_reg,
-};
-
-static const struct regmap_config rk808_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
- .max_register = RK808_IO_POL_REG,
- .cache_type = REGCACHE_RBTREE,
- .volatile_reg = rk808_is_volatile_reg,
-};
-
-static const struct regmap_config rk817_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
- .max_register = RK817_GPIO_INT_CFG,
- .cache_type = REGCACHE_NONE,
- .volatile_reg = rk817_is_volatile_reg,
-};
-
static const struct resource rtc_resources[] = {
DEFINE_RES_IRQ(RK808_IRQ_RTC_ALARM),
};
@@ -126,6 +37,11 @@ static const struct resource rk805_key_resources[] = {
DEFINE_RES_IRQ(RK805_IRQ_PWRON_FALL),
};
+static struct resource rk806_pwrkey_resources[] = {
+ DEFINE_RES_IRQ(RK806_IRQ_PWRON_FALL),
+ DEFINE_RES_IRQ(RK806_IRQ_PWRON_RISE),
+};
+
static const struct resource rk817_pwrkey_resources[] = {
DEFINE_RES_IRQ(RK817_IRQ_PWRON_RISE),
DEFINE_RES_IRQ(RK817_IRQ_PWRON_FALL),
@@ -153,6 +69,17 @@ static const struct mfd_cell rk805s[] = {
},
};
+static const struct mfd_cell rk806s[] = {
+ { .name = "rk805-pinctrl", .id = PLATFORM_DEVID_AUTO, },
+ { .name = "rk808-regulator", .id = PLATFORM_DEVID_AUTO, },
+ {
+ .name = "rk805-pwrkey",
+ .resources = rk806_pwrkey_resources,
+ .num_resources = ARRAY_SIZE(rk806_pwrkey_resources),
+ .id = PLATFORM_DEVID_AUTO,
+ },
+};
+
static const struct mfd_cell rk808s[] = {
{ .name = "rk808-clkout", .id = PLATFORM_DEVID_NONE, },
{ .name = "rk808-regulator", .id = PLATFORM_DEVID_NONE, },
@@ -212,6 +139,12 @@ static const struct rk808_reg_data rk805_pre_init_reg[] = {
{RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C},
};
+static const struct rk808_reg_data rk806_pre_init_reg[] = {
+ { RK806_GPIO_INT_CONFIG, RK806_INT_POL_MSK, RK806_INT_POL_L },
+ { RK806_SYS_CFG3, RK806_SLAVE_RESTART_FUN_MSK, RK806_SLAVE_RESTART_FUN_EN },
+ { RK806_SYS_OPTION, RK806_SYS_ENB2_2M_MSK, RK806_SYS_ENB2_2M_EN },
+};
+
static const struct rk808_reg_data rk808_pre_init_reg[] = {
{ RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA },
{ RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA },
@@ -362,6 +295,27 @@ static const struct regmap_irq rk805_irqs[] = {
},
};
+static const struct regmap_irq rk806_irqs[] = {
+ /* INT_STS0 IRQs */
+ REGMAP_IRQ_REG(RK806_IRQ_PWRON_FALL, 0, RK806_INT_STS_PWRON_FALL),
+ REGMAP_IRQ_REG(RK806_IRQ_PWRON_RISE, 0, RK806_INT_STS_PWRON_RISE),
+ REGMAP_IRQ_REG(RK806_IRQ_PWRON, 0, RK806_INT_STS_PWRON),
+ REGMAP_IRQ_REG(RK806_IRQ_PWRON_LP, 0, RK806_INT_STS_PWRON_LP),
+ REGMAP_IRQ_REG(RK806_IRQ_HOTDIE, 0, RK806_INT_STS_HOTDIE),
+ REGMAP_IRQ_REG(RK806_IRQ_VDC_RISE, 0, RK806_INT_STS_VDC_RISE),
+ REGMAP_IRQ_REG(RK806_IRQ_VDC_FALL, 0, RK806_INT_STS_VDC_FALL),
+ REGMAP_IRQ_REG(RK806_IRQ_VB_LO, 0, RK806_INT_STS_VB_LO),
+ /* INT_STS1 IRQs */
+ REGMAP_IRQ_REG(RK806_IRQ_REV0, 1, RK806_INT_STS_REV0),
+ REGMAP_IRQ_REG(RK806_IRQ_REV1, 1, RK806_INT_STS_REV1),
+ REGMAP_IRQ_REG(RK806_IRQ_REV2, 1, RK806_INT_STS_REV2),
+ REGMAP_IRQ_REG(RK806_IRQ_CRC_ERROR, 1, RK806_INT_STS_CRC_ERROR),
+ REGMAP_IRQ_REG(RK806_IRQ_SLP3_GPIO, 1, RK806_INT_STS_SLP3_GPIO),
+ REGMAP_IRQ_REG(RK806_IRQ_SLP2_GPIO, 1, RK806_INT_STS_SLP2_GPIO),
+ REGMAP_IRQ_REG(RK806_IRQ_SLP1_GPIO, 1, RK806_INT_STS_SLP1_GPIO),
+ REGMAP_IRQ_REG(RK806_IRQ_WDT, 1, RK806_INT_STS_WDT),
+};
+
static const struct regmap_irq rk808_irqs[] = {
/* INT_STS */
[RK808_IRQ_VOUT_LO] = {
@@ -512,6 +466,18 @@ static struct regmap_irq_chip rk805_irq_chip = {
.init_ack_masked = true,
};
+static struct regmap_irq_chip rk806_irq_chip = {
+ .name = "rk806",
+ .irqs = rk806_irqs,
+ .num_irqs = ARRAY_SIZE(rk806_irqs),
+ .num_regs = 2,
+ .irq_reg_stride = 2,
+ .mask_base = RK806_INT_MSK0,
+ .status_base = RK806_INT_STS0,
+ .ack_base = RK806_INT_STS0,
+ .init_ack_masked = true,
+};
+
static const struct regmap_irq_chip rk808_irq_chip = {
.name = "rk808",
.irqs = rk808_irqs,
@@ -548,13 +514,11 @@ static const struct regmap_irq_chip rk818_irq_chip = {
.init_ack_masked = true,
};
-static struct i2c_client *rk808_i2c_client;
-
-static void rk808_pm_power_off(void)
+static int rk808_power_off(struct sys_off_data *data)
{
+ struct rk808 *rk808 = data->cb_data;
int ret;
unsigned int reg, bit;
- struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
switch (rk808->variant) {
case RK805_ID:
@@ -575,16 +539,18 @@ static void rk808_pm_power_off(void)
bit = DEV_OFF;
break;
default:
- return;
+ return NOTIFY_DONE;
}
ret = regmap_update_bits(rk808->regmap, reg, bit, bit);
if (ret)
- dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n");
+ dev_err(rk808->dev, "Failed to shutdown device!\n");
+
+ return NOTIFY_DONE;
}
-static int rk808_restart_notify(struct notifier_block *this, unsigned long mode, void *cmd)
+static int rk808_restart(struct sys_off_data *data)
{
- struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
+ struct rk808 *rk808 = data->cb_data;
unsigned int reg, bit;
int ret;
@@ -600,19 +566,14 @@ static int rk808_restart_notify(struct notifier_block *this, unsigned long mode,
}
ret = regmap_update_bits(rk808->regmap, reg, bit, bit);
if (ret)
- dev_err(&rk808_i2c_client->dev, "Failed to restart device!\n");
+ dev_err(rk808->dev, "Failed to restart device!\n");
return NOTIFY_DONE;
}
-static struct notifier_block rk808_restart_handler = {
- .notifier_call = rk808_restart_notify,
- .priority = 192,
-};
-
-static void rk8xx_shutdown(struct i2c_client *client)
+void rk8xx_shutdown(struct device *dev)
{
- struct rk808 *rk808 = i2c_get_clientdata(client);
+ struct rk808 *rk808 = dev_get_drvdata(dev);
int ret;
switch (rk808->variant) {
@@ -633,75 +594,47 @@ static void rk8xx_shutdown(struct i2c_client *client)
return;
}
if (ret)
- dev_warn(&client->dev,
+ dev_warn(dev,
"Cannot switch to power down function\n");
}
+EXPORT_SYMBOL_GPL(rk8xx_shutdown);
-static const struct of_device_id rk808_of_match[] = {
- { .compatible = "rockchip,rk805" },
- { .compatible = "rockchip,rk808" },
- { .compatible = "rockchip,rk809" },
- { .compatible = "rockchip,rk817" },
- { .compatible = "rockchip,rk818" },
- { },
-};
-MODULE_DEVICE_TABLE(of, rk808_of_match);
-
-static int rk808_probe(struct i2c_client *client)
+int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap *regmap)
{
- struct device_node *np = client->dev.of_node;
struct rk808 *rk808;
const struct rk808_reg_data *pre_init_reg;
const struct mfd_cell *cells;
+ int dual_support = 0;
int nr_pre_init_regs;
int nr_cells;
- int msb, lsb;
- unsigned char pmic_id_msb, pmic_id_lsb;
int ret;
int i;
- rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL);
+ rk808 = devm_kzalloc(dev, sizeof(*rk808), GFP_KERNEL);
if (!rk808)
return -ENOMEM;
-
- if (of_device_is_compatible(np, "rockchip,rk817") ||
- of_device_is_compatible(np, "rockchip,rk809")) {
- pmic_id_msb = RK817_ID_MSB;
- pmic_id_lsb = RK817_ID_LSB;
- } else {
- pmic_id_msb = RK808_ID_MSB;
- pmic_id_lsb = RK808_ID_LSB;
- }
-
- /* Read chip variant */
- msb = i2c_smbus_read_byte_data(client, pmic_id_msb);
- if (msb < 0) {
- dev_err(&client->dev, "failed to read the chip id at 0x%x\n",
- RK808_ID_MSB);
- return msb;
- }
-
- lsb = i2c_smbus_read_byte_data(client, pmic_id_lsb);
- if (lsb < 0) {
- dev_err(&client->dev, "failed to read the chip id at 0x%x\n",
- RK808_ID_LSB);
- return lsb;
- }
-
- rk808->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
- dev_info(&client->dev, "chip id: 0x%x\n", (unsigned int)rk808->variant);
+ rk808->dev = dev;
+ rk808->variant = variant;
+ rk808->regmap = regmap;
+ dev_set_drvdata(dev, rk808);
switch (rk808->variant) {
case RK805_ID:
- rk808->regmap_cfg = &rk805_regmap_config;
rk808->regmap_irq_chip = &rk805_irq_chip;
pre_init_reg = rk805_pre_init_reg;
nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg);
cells = rk805s;
nr_cells = ARRAY_SIZE(rk805s);
break;
+ case RK806_ID:
+ rk808->regmap_irq_chip = &rk806_irq_chip;
+ pre_init_reg = rk806_pre_init_reg;
+ nr_pre_init_regs = ARRAY_SIZE(rk806_pre_init_reg);
+ cells = rk806s;
+ nr_cells = ARRAY_SIZE(rk806s);
+ dual_support = IRQF_SHARED;
+ break;
case RK808_ID:
- rk808->regmap_cfg = &rk808_regmap_config;
rk808->regmap_irq_chip = &rk808_irq_chip;
pre_init_reg = rk808_pre_init_reg;
nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg);
@@ -709,7 +642,6 @@ static int rk808_probe(struct i2c_client *client)
nr_cells = ARRAY_SIZE(rk808s);
break;
case RK818_ID:
- rk808->regmap_cfg = &rk818_regmap_config;
rk808->regmap_irq_chip = &rk818_irq_chip;
pre_init_reg = rk818_pre_init_reg;
nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg);
@@ -718,7 +650,6 @@ static int rk808_probe(struct i2c_client *client)
break;
case RK809_ID:
case RK817_ID:
- rk808->regmap_cfg = &rk817_regmap_config;
rk808->regmap_irq_chip = &rk817_irq_chip;
pre_init_reg = rk817_pre_init_reg;
nr_pre_init_regs = ARRAY_SIZE(rk817_pre_init_reg);
@@ -726,97 +657,64 @@ static int rk808_probe(struct i2c_client *client)
nr_cells = ARRAY_SIZE(rk817s);
break;
default:
- dev_err(&client->dev, "Unsupported RK8XX ID %lu\n",
- rk808->variant);
+ dev_err(dev, "Unsupported RK8XX ID %lu\n", rk808->variant);
return -EINVAL;
}
- rk808->i2c = client;
- i2c_set_clientdata(client, rk808);
-
- rk808->regmap = devm_regmap_init_i2c(client, rk808->regmap_cfg);
- if (IS_ERR(rk808->regmap)) {
- dev_err(&client->dev, "regmap initialization failed\n");
- return PTR_ERR(rk808->regmap);
- }
-
- if (!client->irq) {
- dev_err(&client->dev, "No interrupt support, no core IRQ\n");
- return -EINVAL;
- }
+ if (!irq)
+ return dev_err_probe(dev, -EINVAL, "No interrupt support, no core IRQ\n");
- ret = regmap_add_irq_chip(rk808->regmap, client->irq,
- IRQF_ONESHOT, -1,
- rk808->regmap_irq_chip, &rk808->irq_data);
- if (ret) {
- dev_err(&client->dev, "Failed to add irq_chip %d\n", ret);
- return ret;
- }
+ ret = devm_regmap_add_irq_chip(dev, rk808->regmap, irq,
+ IRQF_ONESHOT | dual_support, -1,
+ rk808->regmap_irq_chip, &rk808->irq_data);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to add irq_chip\n");
for (i = 0; i < nr_pre_init_regs; i++) {
ret = regmap_update_bits(rk808->regmap,
pre_init_reg[i].addr,
pre_init_reg[i].mask,
pre_init_reg[i].value);
- if (ret) {
- dev_err(&client->dev,
- "0x%x write err\n",
- pre_init_reg[i].addr);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "0x%x write err\n",
+ pre_init_reg[i].addr);
}
- ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
- cells, nr_cells, NULL, 0,
+ ret = devm_mfd_add_devices(dev, 0, cells, nr_cells, NULL, 0,
regmap_irq_get_domain(rk808->irq_data));
- if (ret) {
- dev_err(&client->dev, "failed to add MFD devices %d\n", ret);
- goto err_irq;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to add MFD devices\n");
- if (of_property_read_bool(np, "rockchip,system-power-controller")) {
- rk808_i2c_client = client;
- pm_power_off = rk808_pm_power_off;
+ if (device_property_read_bool(dev, "rockchip,system-power-controller")) {
+ ret = devm_register_sys_off_handler(dev,
+ SYS_OFF_MODE_POWER_OFF_PREPARE, SYS_OFF_PRIO_HIGH,
+ &rk808_power_off, rk808);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to register poweroff handler\n");
switch (rk808->variant) {
case RK809_ID:
case RK817_ID:
- ret = register_restart_handler(&rk808_restart_handler);
+ ret = devm_register_sys_off_handler(dev,
+ SYS_OFF_MODE_RESTART, SYS_OFF_PRIO_HIGH,
+ &rk808_restart, rk808);
if (ret)
- dev_warn(&client->dev, "failed to register rst handler, %d\n", ret);
+ dev_warn(dev, "failed to register rst handler, %d\n", ret);
break;
default:
- dev_dbg(&client->dev, "pmic controlled board reset not supported\n");
+ dev_dbg(dev, "pmic controlled board reset not supported\n");
break;
}
}
return 0;
-
-err_irq:
- regmap_del_irq_chip(client->irq, rk808->irq_data);
- return ret;
}
+EXPORT_SYMBOL_GPL(rk8xx_probe);
-static void rk808_remove(struct i2c_client *client)
+int rk8xx_suspend(struct device *dev)
{
- struct rk808 *rk808 = i2c_get_clientdata(client);
-
- regmap_del_irq_chip(client->irq, rk808->irq_data);
-
- /**
- * pm_power_off may points to a function from another module.
- * Check if the pointer is set by us and only then overwrite it.
- */
- if (pm_power_off == rk808_pm_power_off)
- pm_power_off = NULL;
-
- unregister_restart_handler(&rk808_restart_handler);
-}
-
-static int __maybe_unused rk8xx_suspend(struct device *dev)
-{
- struct rk808 *rk808 = i2c_get_clientdata(to_i2c_client(dev));
+ struct rk808 *rk808 = dev_get_drvdata(dev);
int ret = 0;
switch (rk808->variant) {
@@ -839,10 +737,11 @@ static int __maybe_unused rk8xx_suspend(struct device *dev)
return ret;
}
+EXPORT_SYMBOL_GPL(rk8xx_suspend);
-static int __maybe_unused rk8xx_resume(struct device *dev)
+int rk8xx_resume(struct device *dev)
{
- struct rk808 *rk808 = i2c_get_clientdata(to_i2c_client(dev));
+ struct rk808 *rk808 = dev_get_drvdata(dev);
int ret = 0;
switch (rk808->variant) {
@@ -859,23 +758,10 @@ static int __maybe_unused rk8xx_resume(struct device *dev)
return ret;
}
-static SIMPLE_DEV_PM_OPS(rk8xx_pm_ops, rk8xx_suspend, rk8xx_resume);
-
-static struct i2c_driver rk808_i2c_driver = {
- .driver = {
- .name = "rk808",
- .of_match_table = rk808_of_match,
- .pm = &rk8xx_pm_ops,
- },
- .probe_new = rk808_probe,
- .remove = rk808_remove,
- .shutdown = rk8xx_shutdown,
-};
-
-module_i2c_driver(rk808_i2c_driver);
+EXPORT_SYMBOL_GPL(rk8xx_resume);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
-MODULE_DESCRIPTION("RK808/RK818 PMIC driver");
+MODULE_DESCRIPTION("RK8xx PMIC core");
diff --git a/drivers/mfd/rk8xx-i2c.c b/drivers/mfd/rk8xx-i2c.c
new file mode 100644
index 000000000000..1a98feea97e2
--- /dev/null
+++ b/drivers/mfd/rk8xx-i2c.c
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Rockchip RK808/RK818 Core (I2C) driver
+ *
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ * Copyright (C) 2016 PHYTEC Messtechnik GmbH
+ *
+ * Author: Chris Zhong <zyw@rock-chips.com>
+ * Author: Zhang Qing <zhangqing@rock-chips.com>
+ * Author: Wadim Egorov <w.egorov@phytec.de>
+ */
+
+#include <linux/i2c.h>
+#include <linux/mfd/rk808.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+
+struct rk8xx_i2c_platform_data {
+ const struct regmap_config *regmap_cfg;
+ int variant;
+};
+
+static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ /*
+ * Notes:
+ * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
+ * we don't use that feature. It's better to cache.
+ * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since
+ * bits are cleared in case when we shutoff anyway, but better safe.
+ */
+
+ switch (reg) {
+ case RK808_SECONDS_REG ... RK808_WEEKS_REG:
+ case RK808_RTC_STATUS_REG:
+ case RK808_VB_MON_REG:
+ case RK808_THERMAL_REG:
+ case RK808_DCDC_UV_STS_REG:
+ case RK808_LDO_UV_STS_REG:
+ case RK808_DCDC_PG_REG:
+ case RK808_LDO_PG_REG:
+ case RK808_DEVCTRL_REG:
+ case RK808_INT_STS_REG1:
+ case RK808_INT_STS_REG2:
+ return true;
+ }
+
+ return false;
+}
+
+static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ /*
+ * Notes:
+ * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
+ * we don't use that feature. It's better to cache.
+ */
+
+ switch (reg) {
+ case RK817_SECONDS_REG ... RK817_WEEKS_REG:
+ case RK817_RTC_STATUS_REG:
+ case RK817_CODEC_DTOP_LPT_SRST:
+ case RK817_GAS_GAUGE_ADC_CONFIG0 ... RK817_GAS_GAUGE_CUR_ADC_K0:
+ case RK817_PMIC_CHRG_STS:
+ case RK817_PMIC_CHRG_OUT:
+ case RK817_PMIC_CHRG_IN:
+ case RK817_INT_STS_REG0:
+ case RK817_INT_STS_REG1:
+ case RK817_INT_STS_REG2:
+ case RK817_SYS_STS:
+ return true;
+ }
+
+ return false;
+}
+
+
+static const struct regmap_config rk818_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = RK818_USB_CTRL_REG,
+ .cache_type = REGCACHE_RBTREE,
+ .volatile_reg = rk808_is_volatile_reg,
+};
+
+static const struct regmap_config rk805_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = RK805_OFF_SOURCE_REG,
+ .cache_type = REGCACHE_RBTREE,
+ .volatile_reg = rk808_is_volatile_reg,
+};
+
+static const struct regmap_config rk808_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = RK808_IO_POL_REG,
+ .cache_type = REGCACHE_RBTREE,
+ .volatile_reg = rk808_is_volatile_reg,
+};
+
+static const struct regmap_config rk817_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = RK817_GPIO_INT_CFG,
+ .cache_type = REGCACHE_NONE,
+ .volatile_reg = rk817_is_volatile_reg,
+};
+
+static const struct rk8xx_i2c_platform_data rk805_data = {
+ .regmap_cfg = &rk805_regmap_config,
+ .variant = RK805_ID,
+};
+
+static const struct rk8xx_i2c_platform_data rk808_data = {
+ .regmap_cfg = &rk808_regmap_config,
+ .variant = RK808_ID,
+};
+
+static const struct rk8xx_i2c_platform_data rk809_data = {
+ .regmap_cfg = &rk817_regmap_config,
+ .variant = RK809_ID,
+};
+
+static const struct rk8xx_i2c_platform_data rk817_data = {
+ .regmap_cfg = &rk817_regmap_config,
+ .variant = RK817_ID,
+};
+
+static const struct rk8xx_i2c_platform_data rk818_data = {
+ .regmap_cfg = &rk818_regmap_config,
+ .variant = RK818_ID,
+};
+
+static int rk8xx_i2c_probe(struct i2c_client *client)
+{
+ const struct rk8xx_i2c_platform_data *data;
+ struct regmap *regmap;
+
+ data = device_get_match_data(&client->dev);
+ if (!data)
+ return -ENODEV;
+
+ regmap = devm_regmap_init_i2c(client, data->regmap_cfg);
+ if (IS_ERR(regmap))
+ return dev_err_probe(&client->dev, PTR_ERR(regmap),
+ "regmap initialization failed\n");
+
+ return rk8xx_probe(&client->dev, data->variant, client->irq, regmap);
+}
+
+static void rk8xx_i2c_shutdown(struct i2c_client *client)
+{
+ rk8xx_shutdown(&client->dev);
+}
+
+static SIMPLE_DEV_PM_OPS(rk8xx_i2c_pm_ops, rk8xx_suspend, rk8xx_resume);
+
+static const struct of_device_id rk8xx_i2c_of_match[] = {
+ { .compatible = "rockchip,rk805", .data = &rk805_data },
+ { .compatible = "rockchip,rk808", .data = &rk808_data },
+ { .compatible = "rockchip,rk809", .data = &rk809_data },
+ { .compatible = "rockchip,rk817", .data = &rk817_data },
+ { .compatible = "rockchip,rk818", .data = &rk818_data },
+ { },
+};
+MODULE_DEVICE_TABLE(of, rk8xx_i2c_of_match);
+
+static struct i2c_driver rk8xx_i2c_driver = {
+ .driver = {
+ .name = "rk8xx-i2c",
+ .of_match_table = rk8xx_i2c_of_match,
+ .pm = &rk8xx_i2c_pm_ops,
+ },
+ .probe = rk8xx_i2c_probe,
+ .shutdown = rk8xx_i2c_shutdown,
+};
+module_i2c_driver(rk8xx_i2c_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
+MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
+MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
+MODULE_DESCRIPTION("RK8xx I2C PMIC driver");
diff --git a/drivers/mfd/rk8xx-spi.c b/drivers/mfd/rk8xx-spi.c
new file mode 100644
index 000000000000..fd137f38c2c4
--- /dev/null
+++ b/drivers/mfd/rk8xx-spi.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Rockchip RK806 Core (SPI) driver
+ *
+ * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2023 Collabora Ltd.
+ *
+ * Author: Xu Shengfei <xsf@rock-chips.com>
+ * Author: Sebastian Reichel <sebastian.reichel@collabora.com>
+ */
+
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/rk808.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#define RK806_ADDR_SIZE 2
+#define RK806_CMD_WITH_SIZE(CMD, VALUE_BYTES) \
+ (RK806_CMD_##CMD | RK806_CMD_CRC_DIS | (VALUE_BYTES - 1))
+
+static const struct regmap_range rk806_volatile_ranges[] = {
+ regmap_reg_range(RK806_POWER_EN0, RK806_POWER_EN5),
+ regmap_reg_range(RK806_DVS_START_CTRL, RK806_INT_MSK1),
+};
+
+static const struct regmap_access_table rk806_volatile_table = {
+ .yes_ranges = rk806_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(rk806_volatile_ranges),
+};
+
+static const struct regmap_config rk806_regmap_config_spi = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .max_register = RK806_BUCK_RSERVE_REG5,
+ .cache_type = REGCACHE_RBTREE,
+ .volatile_table = &rk806_volatile_table,
+};
+
+static int rk806_spi_bus_write(void *context, const void *vdata, size_t count)
+{
+ struct device *dev = context;
+ struct spi_device *spi = to_spi_device(dev);
+ struct spi_transfer xfer[2] = { 0 };
+ /* data and thus count includes the register address */
+ size_t val_size = count - RK806_ADDR_SIZE;
+ char cmd;
+
+ if (val_size < 1 || val_size > (RK806_CMD_LEN_MSK + 1))
+ return -EINVAL;
+
+ cmd = RK806_CMD_WITH_SIZE(WRITE, val_size);
+
+ xfer[0].tx_buf = &cmd;
+ xfer[0].len = sizeof(cmd);
+ xfer[1].tx_buf = vdata;
+ xfer[1].len = count;
+
+ return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
+}
+
+static int rk806_spi_bus_read(void *context, const void *vreg, size_t reg_size,
+ void *val, size_t val_size)
+{
+ struct device *dev = context;
+ struct spi_device *spi = to_spi_device(dev);
+ char txbuf[3] = { 0 };
+
+ if (reg_size != RK806_ADDR_SIZE ||
+ val_size < 1 || val_size > (RK806_CMD_LEN_MSK + 1))
+ return -EINVAL;
+
+ /* TX buffer contains command byte followed by two address bytes */
+ txbuf[0] = RK806_CMD_WITH_SIZE(READ, val_size);
+ memcpy(txbuf+1, vreg, reg_size);
+
+ return spi_write_then_read(spi, txbuf, sizeof(txbuf), val, val_size);
+}
+
+static const struct regmap_bus rk806_regmap_bus_spi = {
+ .write = rk806_spi_bus_write,
+ .read = rk806_spi_bus_read,
+ .reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
+};
+
+static int rk8xx_spi_probe(struct spi_device *spi)
+{
+ struct regmap *regmap;
+
+ regmap = devm_regmap_init(&spi->dev, &rk806_regmap_bus_spi,
+ &spi->dev, &rk806_regmap_config_spi);
+ if (IS_ERR(regmap))
+ return dev_err_probe(&spi->dev, PTR_ERR(regmap),
+ "Failed to init regmap\n");
+
+ return rk8xx_probe(&spi->dev, RK806_ID, spi->irq, regmap);
+}
+
+static const struct of_device_id rk8xx_spi_of_match[] = {
+ { .compatible = "rockchip,rk806", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, rk8xx_spi_of_match);
+
+static const struct spi_device_id rk8xx_spi_id_table[] = {
+ { "rk806", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, rk8xx_spi_id_table);
+
+static struct spi_driver rk8xx_spi_driver = {
+ .driver = {
+ .name = "rk8xx-spi",
+ .of_match_table = rk8xx_spi_of_match,
+ },
+ .probe = rk8xx_spi_probe,
+ .id_table = rk8xx_spi_id_table,
+};
+module_spi_driver(rk8xx_spi_driver);
+
+MODULE_AUTHOR("Xu Shengfei <xsf@rock-chips.com>");
+MODULE_DESCRIPTION("RK8xx SPI PMIC driver");
+MODULE_LICENSE("GPL");
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-core.c b/drivers/mfd/tps6594-core.c
new file mode 100644
index 000000000000..15f314833207
--- /dev/null
+++ b/drivers/mfd/tps6594-core.c
@@ -0,0 +1,462 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Core functions for TI TPS6594/TPS6593/LP8764 PMICs
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps6594.h>
+
+#define TPS6594_CRC_SYNC_TIMEOUT_MS 150
+
+/* Completion to synchronize CRC feature enabling on all PMICs */
+static DECLARE_COMPLETION(tps6594_crc_comp);
+
+static const struct resource tps6594_regulator_resources[] = {
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK1_OV, TPS6594_IRQ_NAME_BUCK1_OV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK1_UV, TPS6594_IRQ_NAME_BUCK1_UV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK1_SC, TPS6594_IRQ_NAME_BUCK1_SC),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK1_ILIM, TPS6594_IRQ_NAME_BUCK1_ILIM),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK2_OV, TPS6594_IRQ_NAME_BUCK2_OV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK2_UV, TPS6594_IRQ_NAME_BUCK2_UV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK2_SC, TPS6594_IRQ_NAME_BUCK2_SC),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK2_ILIM, TPS6594_IRQ_NAME_BUCK2_ILIM),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK3_OV, TPS6594_IRQ_NAME_BUCK3_OV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK3_UV, TPS6594_IRQ_NAME_BUCK3_UV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK3_SC, TPS6594_IRQ_NAME_BUCK3_SC),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK3_ILIM, TPS6594_IRQ_NAME_BUCK3_ILIM),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK4_OV, TPS6594_IRQ_NAME_BUCK4_OV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK4_UV, TPS6594_IRQ_NAME_BUCK4_UV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK4_SC, TPS6594_IRQ_NAME_BUCK4_SC),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK4_ILIM, TPS6594_IRQ_NAME_BUCK4_ILIM),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK5_OV, TPS6594_IRQ_NAME_BUCK5_OV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK5_UV, TPS6594_IRQ_NAME_BUCK5_UV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK5_SC, TPS6594_IRQ_NAME_BUCK5_SC),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK5_ILIM, TPS6594_IRQ_NAME_BUCK5_ILIM),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO1_OV, TPS6594_IRQ_NAME_LDO1_OV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO1_UV, TPS6594_IRQ_NAME_LDO1_UV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO1_SC, TPS6594_IRQ_NAME_LDO1_SC),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO1_ILIM, TPS6594_IRQ_NAME_LDO1_ILIM),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO2_OV, TPS6594_IRQ_NAME_LDO2_OV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO2_UV, TPS6594_IRQ_NAME_LDO2_UV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO2_SC, TPS6594_IRQ_NAME_LDO2_SC),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO2_ILIM, TPS6594_IRQ_NAME_LDO2_ILIM),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO3_OV, TPS6594_IRQ_NAME_LDO3_OV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO3_UV, TPS6594_IRQ_NAME_LDO3_UV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO3_SC, TPS6594_IRQ_NAME_LDO3_SC),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO3_ILIM, TPS6594_IRQ_NAME_LDO3_ILIM),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO4_OV, TPS6594_IRQ_NAME_LDO4_OV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO4_UV, TPS6594_IRQ_NAME_LDO4_UV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO4_SC, TPS6594_IRQ_NAME_LDO4_SC),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO4_ILIM, TPS6594_IRQ_NAME_LDO4_ILIM),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VCCA_OV, TPS6594_IRQ_NAME_VCCA_OV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VCCA_UV, TPS6594_IRQ_NAME_VCCA_UV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON1_OV, TPS6594_IRQ_NAME_VMON1_OV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON1_UV, TPS6594_IRQ_NAME_VMON1_UV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON1_RV, TPS6594_IRQ_NAME_VMON1_RV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON2_OV, TPS6594_IRQ_NAME_VMON2_OV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON2_UV, TPS6594_IRQ_NAME_VMON2_UV),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON2_RV, TPS6594_IRQ_NAME_VMON2_RV),
+};
+
+static const struct resource tps6594_pinctrl_resources[] = {
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO9, TPS6594_IRQ_NAME_GPIO9),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO10, TPS6594_IRQ_NAME_GPIO10),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO11, TPS6594_IRQ_NAME_GPIO11),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO1, TPS6594_IRQ_NAME_GPIO1),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO2, TPS6594_IRQ_NAME_GPIO2),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO3, TPS6594_IRQ_NAME_GPIO3),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO4, TPS6594_IRQ_NAME_GPIO4),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO5, TPS6594_IRQ_NAME_GPIO5),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO6, TPS6594_IRQ_NAME_GPIO6),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO7, TPS6594_IRQ_NAME_GPIO7),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO8, TPS6594_IRQ_NAME_GPIO8),
+};
+
+static const struct resource tps6594_pfsm_resources[] = {
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NPWRON_START, TPS6594_IRQ_NAME_NPWRON_START),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ENABLE, TPS6594_IRQ_NAME_ENABLE),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_FSD, TPS6594_IRQ_NAME_FSD),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_SOFT_REBOOT, TPS6594_IRQ_NAME_SOFT_REBOOT),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BIST_PASS, TPS6594_IRQ_NAME_BIST_PASS),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_EXT_CLK, TPS6594_IRQ_NAME_EXT_CLK),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_TWARN, TPS6594_IRQ_NAME_TWARN),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_TSD_ORD, TPS6594_IRQ_NAME_TSD_ORD),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BIST_FAIL, TPS6594_IRQ_NAME_BIST_FAIL),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_REG_CRC_ERR, TPS6594_IRQ_NAME_REG_CRC_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_RECOV_CNT, TPS6594_IRQ_NAME_RECOV_CNT),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_SPMI_ERR, TPS6594_IRQ_NAME_SPMI_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NPWRON_LONG, TPS6594_IRQ_NAME_NPWRON_LONG),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NINT_READBACK, TPS6594_IRQ_NAME_NINT_READBACK),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NRSTOUT_READBACK, TPS6594_IRQ_NAME_NRSTOUT_READBACK),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_TSD_IMM, TPS6594_IRQ_NAME_TSD_IMM),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VCCA_OVP, TPS6594_IRQ_NAME_VCCA_OVP),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_PFSM_ERR, TPS6594_IRQ_NAME_PFSM_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_IMM_SHUTDOWN, TPS6594_IRQ_NAME_IMM_SHUTDOWN),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ORD_SHUTDOWN, TPS6594_IRQ_NAME_ORD_SHUTDOWN),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_MCU_PWR_ERR, TPS6594_IRQ_NAME_MCU_PWR_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_SOC_PWR_ERR, TPS6594_IRQ_NAME_SOC_PWR_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_COMM_FRM_ERR, TPS6594_IRQ_NAME_COMM_FRM_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_COMM_CRC_ERR, TPS6594_IRQ_NAME_COMM_CRC_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_COMM_ADR_ERR, TPS6594_IRQ_NAME_COMM_ADR_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_EN_DRV_READBACK, TPS6594_IRQ_NAME_EN_DRV_READBACK),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NRSTOUT_SOC_READBACK,
+ TPS6594_IRQ_NAME_NRSTOUT_SOC_READBACK),
+};
+
+static const struct resource tps6594_esm_resources[] = {
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ESM_SOC_PIN, TPS6594_IRQ_NAME_ESM_SOC_PIN),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ESM_SOC_FAIL, TPS6594_IRQ_NAME_ESM_SOC_FAIL),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ESM_SOC_RST, TPS6594_IRQ_NAME_ESM_SOC_RST),
+};
+
+static const struct resource tps6594_rtc_resources[] = {
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_TIMER, TPS6594_IRQ_NAME_TIMER),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ALARM, TPS6594_IRQ_NAME_ALARM),
+ DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_POWER_UP, TPS6594_IRQ_NAME_POWERUP),
+};
+
+static const struct mfd_cell tps6594_common_cells[] = {
+ MFD_CELL_RES("tps6594-regulator", tps6594_regulator_resources),
+ MFD_CELL_RES("tps6594-pinctrl", tps6594_pinctrl_resources),
+ MFD_CELL_RES("tps6594-pfsm", tps6594_pfsm_resources),
+ MFD_CELL_RES("tps6594-esm", tps6594_esm_resources),
+};
+
+static const struct mfd_cell tps6594_rtc_cells[] = {
+ MFD_CELL_RES("tps6594-rtc", tps6594_rtc_resources),
+};
+
+static const struct regmap_irq tps6594_irqs[] = {
+ /* INT_BUCK1_2 register */
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK1_OV, 0, TPS6594_BIT_BUCKX_OV_INT(0)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK1_UV, 0, TPS6594_BIT_BUCKX_UV_INT(0)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK1_SC, 0, TPS6594_BIT_BUCKX_SC_INT(0)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK1_ILIM, 0, TPS6594_BIT_BUCKX_ILIM_INT(0)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK2_OV, 0, TPS6594_BIT_BUCKX_OV_INT(1)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK2_UV, 0, TPS6594_BIT_BUCKX_UV_INT(1)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK2_SC, 0, TPS6594_BIT_BUCKX_SC_INT(1)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK2_ILIM, 0, TPS6594_BIT_BUCKX_ILIM_INT(1)),
+
+ /* INT_BUCK3_4 register */
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK3_OV, 1, TPS6594_BIT_BUCKX_OV_INT(2)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK3_UV, 1, TPS6594_BIT_BUCKX_UV_INT(2)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK3_SC, 1, TPS6594_BIT_BUCKX_SC_INT(2)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK3_ILIM, 1, TPS6594_BIT_BUCKX_ILIM_INT(2)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK4_OV, 1, TPS6594_BIT_BUCKX_OV_INT(3)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK4_UV, 1, TPS6594_BIT_BUCKX_UV_INT(3)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK4_SC, 1, TPS6594_BIT_BUCKX_SC_INT(3)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK4_ILIM, 1, TPS6594_BIT_BUCKX_ILIM_INT(3)),
+
+ /* INT_BUCK5 register */
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK5_OV, 2, TPS6594_BIT_BUCKX_OV_INT(4)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK5_UV, 2, TPS6594_BIT_BUCKX_UV_INT(4)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK5_SC, 2, TPS6594_BIT_BUCKX_SC_INT(4)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BUCK5_ILIM, 2, TPS6594_BIT_BUCKX_ILIM_INT(4)),
+
+ /* INT_LDO1_2 register */
+ REGMAP_IRQ_REG(TPS6594_IRQ_LDO1_OV, 3, TPS6594_BIT_LDOX_OV_INT(0)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_LDO1_UV, 3, TPS6594_BIT_LDOX_UV_INT(0)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_LDO1_SC, 3, TPS6594_BIT_LDOX_SC_INT(0)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_LDO1_ILIM, 3, TPS6594_BIT_LDOX_ILIM_INT(0)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_LDO2_OV, 3, TPS6594_BIT_LDOX_OV_INT(1)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_LDO2_UV, 3, TPS6594_BIT_LDOX_UV_INT(1)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_LDO2_SC, 3, TPS6594_BIT_LDOX_SC_INT(1)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_LDO2_ILIM, 3, TPS6594_BIT_LDOX_ILIM_INT(1)),
+
+ /* INT_LDO3_4 register */
+ REGMAP_IRQ_REG(TPS6594_IRQ_LDO3_OV, 4, TPS6594_BIT_LDOX_OV_INT(2)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_LDO3_UV, 4, TPS6594_BIT_LDOX_UV_INT(2)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_LDO3_SC, 4, TPS6594_BIT_LDOX_SC_INT(2)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_LDO3_ILIM, 4, TPS6594_BIT_LDOX_ILIM_INT(2)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_LDO4_OV, 4, TPS6594_BIT_LDOX_OV_INT(3)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_LDO4_UV, 4, TPS6594_BIT_LDOX_UV_INT(3)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_LDO4_SC, 4, TPS6594_BIT_LDOX_SC_INT(3)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_LDO4_ILIM, 4, TPS6594_BIT_LDOX_ILIM_INT(3)),
+
+ /* INT_VMON register */
+ REGMAP_IRQ_REG(TPS6594_IRQ_VCCA_OV, 5, TPS6594_BIT_VCCA_OV_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_VCCA_UV, 5, TPS6594_BIT_VCCA_UV_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_VMON1_OV, 5, TPS6594_BIT_VMON1_OV_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_VMON1_UV, 5, TPS6594_BIT_VMON1_UV_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_VMON1_RV, 5, TPS6594_BIT_VMON1_RV_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_VMON2_OV, 5, TPS6594_BIT_VMON2_OV_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_VMON2_UV, 5, TPS6594_BIT_VMON2_UV_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_VMON2_RV, 5, TPS6594_BIT_VMON2_RV_INT),
+
+ /* INT_GPIO register */
+ REGMAP_IRQ_REG(TPS6594_IRQ_GPIO9, 6, TPS6594_BIT_GPIO9_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_GPIO10, 6, TPS6594_BIT_GPIO10_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_GPIO11, 6, TPS6594_BIT_GPIO11_INT),
+
+ /* INT_GPIO1_8 register */
+ REGMAP_IRQ_REG(TPS6594_IRQ_GPIO1, 7, TPS6594_BIT_GPIOX_INT(0)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_GPIO2, 7, TPS6594_BIT_GPIOX_INT(1)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_GPIO3, 7, TPS6594_BIT_GPIOX_INT(2)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_GPIO4, 7, TPS6594_BIT_GPIOX_INT(3)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_GPIO5, 7, TPS6594_BIT_GPIOX_INT(4)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_GPIO6, 7, TPS6594_BIT_GPIOX_INT(5)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_GPIO7, 7, TPS6594_BIT_GPIOX_INT(6)),
+ REGMAP_IRQ_REG(TPS6594_IRQ_GPIO8, 7, TPS6594_BIT_GPIOX_INT(7)),
+
+ /* INT_STARTUP register */
+ REGMAP_IRQ_REG(TPS6594_IRQ_NPWRON_START, 8, TPS6594_BIT_NPWRON_START_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_ENABLE, 8, TPS6594_BIT_ENABLE_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_FSD, 8, TPS6594_BIT_FSD_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_SOFT_REBOOT, 8, TPS6594_BIT_SOFT_REBOOT_INT),
+
+ /* INT_MISC register */
+ REGMAP_IRQ_REG(TPS6594_IRQ_BIST_PASS, 9, TPS6594_BIT_BIST_PASS_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_EXT_CLK, 9, TPS6594_BIT_EXT_CLK_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_TWARN, 9, TPS6594_BIT_TWARN_INT),
+
+ /* INT_MODERATE_ERR register */
+ REGMAP_IRQ_REG(TPS6594_IRQ_TSD_ORD, 10, TPS6594_BIT_TSD_ORD_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_BIST_FAIL, 10, TPS6594_BIT_BIST_FAIL_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_REG_CRC_ERR, 10, TPS6594_BIT_REG_CRC_ERR_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_RECOV_CNT, 10, TPS6594_BIT_RECOV_CNT_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_SPMI_ERR, 10, TPS6594_BIT_SPMI_ERR_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_NPWRON_LONG, 10, TPS6594_BIT_NPWRON_LONG_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_NINT_READBACK, 10, TPS6594_BIT_NINT_READBACK_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_NRSTOUT_READBACK, 10, TPS6594_BIT_NRSTOUT_READBACK_INT),
+
+ /* INT_SEVERE_ERR register */
+ REGMAP_IRQ_REG(TPS6594_IRQ_TSD_IMM, 11, TPS6594_BIT_TSD_IMM_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_VCCA_OVP, 11, TPS6594_BIT_VCCA_OVP_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_PFSM_ERR, 11, TPS6594_BIT_PFSM_ERR_INT),
+
+ /* INT_FSM_ERR register */
+ REGMAP_IRQ_REG(TPS6594_IRQ_IMM_SHUTDOWN, 12, TPS6594_BIT_IMM_SHUTDOWN_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_ORD_SHUTDOWN, 12, TPS6594_BIT_ORD_SHUTDOWN_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_MCU_PWR_ERR, 12, TPS6594_BIT_MCU_PWR_ERR_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_SOC_PWR_ERR, 12, TPS6594_BIT_SOC_PWR_ERR_INT),
+
+ /* INT_COMM_ERR register */
+ REGMAP_IRQ_REG(TPS6594_IRQ_COMM_FRM_ERR, 13, TPS6594_BIT_COMM_FRM_ERR_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_COMM_CRC_ERR, 13, TPS6594_BIT_COMM_CRC_ERR_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_COMM_ADR_ERR, 13, TPS6594_BIT_COMM_ADR_ERR_INT),
+
+ /* INT_READBACK_ERR register */
+ REGMAP_IRQ_REG(TPS6594_IRQ_EN_DRV_READBACK, 14, TPS6594_BIT_EN_DRV_READBACK_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_NRSTOUT_SOC_READBACK, 14, TPS6594_BIT_NRSTOUT_SOC_READBACK_INT),
+
+ /* INT_ESM register */
+ REGMAP_IRQ_REG(TPS6594_IRQ_ESM_SOC_PIN, 15, TPS6594_BIT_ESM_SOC_PIN_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_ESM_SOC_FAIL, 15, TPS6594_BIT_ESM_SOC_FAIL_INT),
+ REGMAP_IRQ_REG(TPS6594_IRQ_ESM_SOC_RST, 15, TPS6594_BIT_ESM_SOC_RST_INT),
+
+ /* RTC_STATUS register */
+ REGMAP_IRQ_REG(TPS6594_IRQ_TIMER, 16, TPS6594_BIT_TIMER),
+ REGMAP_IRQ_REG(TPS6594_IRQ_ALARM, 16, TPS6594_BIT_ALARM),
+ REGMAP_IRQ_REG(TPS6594_IRQ_POWER_UP, 16, TPS6594_BIT_POWER_UP),
+};
+
+static const unsigned int tps6594_irq_reg[] = {
+ TPS6594_REG_INT_BUCK1_2,
+ TPS6594_REG_INT_BUCK3_4,
+ TPS6594_REG_INT_BUCK5,
+ TPS6594_REG_INT_LDO1_2,
+ TPS6594_REG_INT_LDO3_4,
+ TPS6594_REG_INT_VMON,
+ TPS6594_REG_INT_GPIO,
+ TPS6594_REG_INT_GPIO1_8,
+ TPS6594_REG_INT_STARTUP,
+ TPS6594_REG_INT_MISC,
+ TPS6594_REG_INT_MODERATE_ERR,
+ TPS6594_REG_INT_SEVERE_ERR,
+ TPS6594_REG_INT_FSM_ERR,
+ TPS6594_REG_INT_COMM_ERR,
+ TPS6594_REG_INT_READBACK_ERR,
+ TPS6594_REG_INT_ESM,
+ TPS6594_REG_RTC_STATUS,
+};
+
+static inline unsigned int tps6594_get_irq_reg(struct regmap_irq_chip_data *data,
+ unsigned int base, int index)
+{
+ return tps6594_irq_reg[index];
+};
+
+static int tps6594_handle_post_irq(void *irq_drv_data)
+{
+ struct tps6594 *tps = irq_drv_data;
+ int ret = 0;
+
+ /*
+ * When CRC is enabled, writing to a read-only bit triggers an error,
+ * and COMM_ADR_ERR_INT bit is set. Besides, bits indicating interrupts
+ * (that must be cleared) and read-only bits are sometimes grouped in
+ * the same register.
+ * Since regmap clears interrupts by doing a write per register, clearing
+ * an interrupt bit in a register containing also a read-only bit makes
+ * COMM_ADR_ERR_INT bit set. Clear immediately this bit to avoid raising
+ * a new interrupt.
+ */
+ if (tps->use_crc)
+ ret = regmap_write_bits(tps->regmap, TPS6594_REG_INT_COMM_ERR,
+ TPS6594_BIT_COMM_ADR_ERR_INT,
+ TPS6594_BIT_COMM_ADR_ERR_INT);
+
+ return ret;
+};
+
+static struct regmap_irq_chip tps6594_irq_chip = {
+ .ack_base = TPS6594_REG_INT_BUCK1_2,
+ .ack_invert = 1,
+ .clear_ack = 1,
+ .init_ack_masked = 1,
+ .num_regs = ARRAY_SIZE(tps6594_irq_reg),
+ .irqs = tps6594_irqs,
+ .num_irqs = ARRAY_SIZE(tps6594_irqs),
+ .get_irq_reg = tps6594_get_irq_reg,
+ .handle_post_irq = tps6594_handle_post_irq,
+};
+
+bool tps6594_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ return (reg >= TPS6594_REG_INT_TOP && reg <= TPS6594_REG_STAT_READBACK_ERR) ||
+ reg == TPS6594_REG_RTC_STATUS;
+}
+EXPORT_SYMBOL_GPL(tps6594_is_volatile_reg);
+
+static int tps6594_check_crc_mode(struct tps6594 *tps, bool primary_pmic)
+{
+ int ret;
+
+ /*
+ * Check if CRC is enabled.
+ * Once CRC is enabled, it can't be disabled until next power cycle.
+ */
+ tps->use_crc = true;
+ ret = regmap_test_bits(tps->regmap, TPS6594_REG_SERIAL_IF_CONFIG,
+ TPS6594_BIT_I2C1_SPI_CRC_EN);
+ if (ret == 0) {
+ ret = -EIO;
+ } else if (ret > 0) {
+ dev_info(tps->dev, "CRC feature enabled on %s PMIC",
+ primary_pmic ? "primary" : "secondary");
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static int tps6594_set_crc_feature(struct tps6594 *tps)
+{
+ int ret;
+
+ ret = tps6594_check_crc_mode(tps, true);
+ if (ret) {
+ /*
+ * If CRC is not already enabled, force PFSM I2C_2 trigger to enable it
+ * on primary PMIC.
+ */
+ tps->use_crc = false;
+ ret = regmap_write_bits(tps->regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+ TPS6594_BIT_TRIGGER_I2C(2), TPS6594_BIT_TRIGGER_I2C(2));
+ if (ret)
+ return ret;
+
+ /*
+ * Wait for PFSM to process trigger.
+ * The datasheet indicates 2 ms, and clock specification is +/-5%.
+ * 4 ms should provide sufficient margin.
+ */
+ usleep_range(4000, 5000);
+
+ ret = tps6594_check_crc_mode(tps, true);
+ }
+
+ return ret;
+}
+
+static int tps6594_enable_crc(struct tps6594 *tps)
+{
+ struct device *dev = tps->dev;
+ unsigned int is_primary;
+ unsigned long timeout = msecs_to_jiffies(TPS6594_CRC_SYNC_TIMEOUT_MS);
+ int ret;
+
+ /*
+ * CRC mode can be used with I2C or SPI protocols.
+ * If this mode is specified for primary PMIC, it will also be applied to secondary PMICs
+ * through SPMI serial interface.
+ * In this multi-PMIC synchronization scheme, the primary PMIC is the controller device
+ * on the SPMI bus, and the secondary PMICs are the target devices on the SPMI bus.
+ */
+ is_primary = of_property_read_bool(dev->of_node, "ti,primary-pmic");
+ if (is_primary) {
+ /* Enable CRC feature on primary PMIC */
+ ret = tps6594_set_crc_feature(tps);
+ if (ret)
+ return ret;
+
+ /* Notify secondary PMICs that CRC feature is enabled */
+ complete_all(&tps6594_crc_comp);
+ } else {
+ /* Wait for CRC feature enabling event from primary PMIC */
+ ret = wait_for_completion_interruptible_timeout(&tps6594_crc_comp, timeout);
+ if (ret == 0)
+ ret = -ETIMEDOUT;
+ else if (ret > 0)
+ ret = tps6594_check_crc_mode(tps, false);
+ }
+
+ return ret;
+}
+
+int tps6594_device_init(struct tps6594 *tps, bool enable_crc)
+{
+ struct device *dev = tps->dev;
+ int ret;
+
+ if (enable_crc) {
+ ret = tps6594_enable_crc(tps);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable CRC\n");
+ }
+
+ /* Keep PMIC in ACTIVE state */
+ ret = regmap_set_bits(tps->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS,
+ TPS6594_BIT_NSLEEP1B | TPS6594_BIT_NSLEEP2B);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to set PMIC state\n");
+
+ tps6594_irq_chip.irq_drv_data = tps;
+ tps6594_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL, "%s-%ld-0x%02x",
+ dev->driver->name, tps->chip_id, tps->reg);
+
+ ret = devm_regmap_add_irq_chip(dev, tps->regmap, tps->irq, IRQF_SHARED | IRQF_ONESHOT,
+ 0, &tps6594_irq_chip, &tps->irq_data);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to add regmap IRQ\n");
+
+ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, tps6594_common_cells,
+ ARRAY_SIZE(tps6594_common_cells), NULL, 0,
+ regmap_irq_get_domain(tps->irq_data));
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to add common child devices\n");
+
+ /* No RTC for LP8764 */
+ if (tps->chip_id != LP8764) {
+ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, tps6594_rtc_cells,
+ ARRAY_SIZE(tps6594_rtc_cells), NULL, 0,
+ regmap_irq_get_domain(tps->irq_data));
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to add RTC child device\n");
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tps6594_device_init);
+
+MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/tps6594-i2c.c b/drivers/mfd/tps6594-i2c.c
new file mode 100644
index 000000000000..899c88c0fe77
--- /dev/null
+++ b/drivers/mfd/tps6594-i2c.c
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * I2C access driver for TI TPS6594/TPS6593/LP8764 PMICs
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#include <linux/crc8.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/tps6594.h>
+
+static bool enable_crc;
+module_param(enable_crc, bool, 0444);
+MODULE_PARM_DESC(enable_crc, "Enable CRC feature for I2C interface");
+
+DECLARE_CRC8_TABLE(tps6594_i2c_crc_table);
+
+static int tps6594_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+ int ret = i2c_transfer(adap, msgs, num);
+
+ if (ret == num)
+ return 0;
+ else if (ret < 0)
+ return ret;
+ else
+ return -EIO;
+}
+
+static int tps6594_i2c_reg_read_with_crc(struct i2c_client *client, u8 page, u8 reg, u8 *val)
+{
+ struct i2c_msg msgs[2];
+ u8 buf_rx[] = { 0, 0 };
+ /* I2C address = I2C base address + Page index */
+ const u8 addr = client->addr + page;
+ /*
+ * CRC is calculated from every bit included in the protocol
+ * except the ACK bits from the target. Byte stream is:
+ * - B0: (I2C_addr_7bits << 1) | WR_bit, with WR_bit = 0
+ * - B1: reg
+ * - B2: (I2C_addr_7bits << 1) | RD_bit, with RD_bit = 1
+ * - B3: val
+ * - B4: CRC from B0-B1-B2-B3
+ */
+ u8 crc_data[] = { addr << 1, reg, addr << 1 | 1, 0 };
+ int ret;
+
+ /* Write register */
+ msgs[0].addr = addr;
+ msgs[0].flags = 0;
+ msgs[0].len = 1;
+ msgs[0].buf = &reg;
+
+ /* Read data and CRC */
+ msgs[1].addr = msgs[0].addr;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].len = 2;
+ msgs[1].buf = buf_rx;
+
+ ret = tps6594_i2c_transfer(client->adapter, msgs, 2);
+ if (ret < 0)
+ return ret;
+
+ crc_data[sizeof(crc_data) - 1] = *val = buf_rx[0];
+ if (buf_rx[1] != crc8(tps6594_i2c_crc_table, crc_data, sizeof(crc_data), CRC8_INIT_VALUE))
+ return -EIO;
+
+ return ret;
+}
+
+static int tps6594_i2c_reg_write_with_crc(struct i2c_client *client, u8 page, u8 reg, u8 val)
+{
+ struct i2c_msg msg;
+ u8 buf[] = { reg, val, 0 };
+ /* I2C address = I2C base address + Page index */
+ const u8 addr = client->addr + page;
+ /*
+ * CRC is calculated from every bit included in the protocol
+ * except the ACK bits from the target. Byte stream is:
+ * - B0: (I2C_addr_7bits << 1) | WR_bit, with WR_bit = 0
+ * - B1: reg
+ * - B2: val
+ * - B3: CRC from B0-B1-B2
+ */
+ const u8 crc_data[] = { addr << 1, reg, val };
+
+ /* Write register, data and CRC */
+ msg.addr = addr;
+ msg.flags = client->flags & I2C_M_TEN;
+ msg.len = sizeof(buf);
+ msg.buf = buf;
+
+ buf[msg.len - 1] = crc8(tps6594_i2c_crc_table, crc_data, sizeof(crc_data), CRC8_INIT_VALUE);
+
+ return tps6594_i2c_transfer(client->adapter, &msg, 1);
+}
+
+static int tps6594_i2c_read(void *context, const void *reg_buf, size_t reg_size,
+ void *val_buf, size_t val_size)
+{
+ struct i2c_client *client = context;
+ struct tps6594 *tps = i2c_get_clientdata(client);
+ struct i2c_msg msgs[2];
+ const u8 *reg_bytes = reg_buf;
+ u8 *val_bytes = val_buf;
+ const u8 page = reg_bytes[1];
+ u8 reg = reg_bytes[0];
+ int ret = 0;
+ int i;
+
+ if (tps->use_crc) {
+ /*
+ * Auto-increment feature does not support CRC protocol.
+ * Converts the bulk read operation into a series of single read operations.
+ */
+ for (i = 0 ; ret == 0 && i < val_size ; i++)
+ ret = tps6594_i2c_reg_read_with_crc(client, page, reg + i, val_bytes + i);
+
+ return ret;
+ }
+
+ /* Write register: I2C address = I2C base address + Page index */
+ msgs[0].addr = client->addr + page;
+ msgs[0].flags = 0;
+ msgs[0].len = 1;
+ msgs[0].buf = &reg;
+
+ /* Read data */
+ msgs[1].addr = msgs[0].addr;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].len = val_size;
+ msgs[1].buf = val_bytes;
+
+ return tps6594_i2c_transfer(client->adapter, msgs, 2);
+}
+
+static int tps6594_i2c_write(void *context, const void *data, size_t count)
+{
+ struct i2c_client *client = context;
+ struct tps6594 *tps = i2c_get_clientdata(client);
+ struct i2c_msg msg;
+ const u8 *bytes = data;
+ u8 *buf;
+ const u8 page = bytes[1];
+ const u8 reg = bytes[0];
+ int ret = 0;
+ int i;
+
+ if (tps->use_crc) {
+ /*
+ * Auto-increment feature does not support CRC protocol.
+ * Converts the bulk write operation into a series of single write operations.
+ */
+ for (i = 0 ; ret == 0 && i < count - 2 ; i++)
+ ret = tps6594_i2c_reg_write_with_crc(client, page, reg + i, bytes[i + 2]);
+
+ return ret;
+ }
+
+ /* Setup buffer: page byte is not sent */
+ buf = kzalloc(--count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ buf[0] = reg;
+ for (i = 0 ; i < count - 1 ; i++)
+ buf[i + 1] = bytes[i + 2];
+
+ /* Write register and data: I2C address = I2C base address + Page index */
+ msg.addr = client->addr + page;
+ msg.flags = client->flags & I2C_M_TEN;
+ msg.len = count;
+ msg.buf = buf;
+
+ ret = tps6594_i2c_transfer(client->adapter, &msg, 1);
+
+ kfree(buf);
+ return ret;
+}
+
+static const struct regmap_config tps6594_i2c_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .max_register = TPS6594_REG_DWD_FAIL_CNT_REG,
+ .volatile_reg = tps6594_is_volatile_reg,
+ .read = tps6594_i2c_read,
+ .write = tps6594_i2c_write,
+};
+
+static const struct of_device_id tps6594_i2c_of_match_table[] = {
+ { .compatible = "ti,tps6594-q1", .data = (void *)TPS6594, },
+ { .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, },
+ { .compatible = "ti,lp8764-q1", .data = (void *)LP8764, },
+ {}
+};
+MODULE_DEVICE_TABLE(of, tps6594_i2c_of_match_table);
+
+static int tps6594_i2c_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct tps6594 *tps;
+ const struct of_device_id *match;
+
+ tps = devm_kzalloc(dev, sizeof(*tps), GFP_KERNEL);
+ if (!tps)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, tps);
+
+ tps->dev = dev;
+ tps->reg = client->addr;
+ tps->irq = client->irq;
+
+ tps->regmap = devm_regmap_init(dev, NULL, client, &tps6594_i2c_regmap_config);
+ if (IS_ERR(tps->regmap))
+ return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n");
+
+ match = of_match_device(tps6594_i2c_of_match_table, dev);
+ if (!match)
+ 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);
+
+ return tps6594_device_init(tps, enable_crc);
+}
+
+static struct i2c_driver tps6594_i2c_driver = {
+ .driver = {
+ .name = "tps6594",
+ .of_match_table = tps6594_i2c_of_match_table,
+ },
+ .probe = tps6594_i2c_probe,
+};
+module_i2c_driver(tps6594_i2c_driver);
+
+MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 I2C Interface Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/tps6594-spi.c b/drivers/mfd/tps6594-spi.c
new file mode 100644
index 000000000000..f4b4f37f957f
--- /dev/null
+++ b/drivers/mfd/tps6594-spi.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SPI access driver for TI TPS6594/TPS6593/LP8764 PMICs
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#include <linux/crc8.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#include <linux/mfd/tps6594.h>
+
+#define TPS6594_SPI_PAGE_SHIFT 5
+#define TPS6594_SPI_READ_BIT BIT(4)
+
+static bool enable_crc;
+module_param(enable_crc, bool, 0444);
+MODULE_PARM_DESC(enable_crc, "Enable CRC feature for SPI interface");
+
+DECLARE_CRC8_TABLE(tps6594_spi_crc_table);
+
+static int tps6594_spi_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct spi_device *spi = context;
+ struct tps6594 *tps = spi_get_drvdata(spi);
+ u8 buf[4] = { 0 };
+ size_t count_rx = 1;
+ int ret;
+
+ buf[0] = reg;
+ buf[1] = TPS6594_REG_TO_PAGE(reg) << TPS6594_SPI_PAGE_SHIFT | TPS6594_SPI_READ_BIT;
+
+ if (tps->use_crc)
+ count_rx++;
+
+ ret = spi_write_then_read(spi, buf, 2, buf + 2, count_rx);
+ if (ret < 0)
+ return ret;
+
+ if (tps->use_crc && buf[3] != crc8(tps6594_spi_crc_table, buf, 3, CRC8_INIT_VALUE))
+ return -EIO;
+
+ *val = buf[2];
+
+ return 0;
+}
+
+static int tps6594_spi_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct spi_device *spi = context;
+ struct tps6594 *tps = spi_get_drvdata(spi);
+ u8 buf[4] = { 0 };
+ size_t count = 3;
+
+ buf[0] = reg;
+ buf[1] = TPS6594_REG_TO_PAGE(reg) << TPS6594_SPI_PAGE_SHIFT;
+ buf[2] = val;
+
+ if (tps->use_crc)
+ buf[3] = crc8(tps6594_spi_crc_table, buf, count++, CRC8_INIT_VALUE);
+
+ return spi_write(spi, buf, count);
+}
+
+static const struct regmap_config tps6594_spi_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .max_register = TPS6594_REG_DWD_FAIL_CNT_REG,
+ .volatile_reg = tps6594_is_volatile_reg,
+ .reg_read = tps6594_spi_reg_read,
+ .reg_write = tps6594_spi_reg_write,
+ .use_single_read = true,
+ .use_single_write = true,
+};
+
+static const struct of_device_id tps6594_spi_of_match_table[] = {
+ { .compatible = "ti,tps6594-q1", .data = (void *)TPS6594, },
+ { .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, },
+ { .compatible = "ti,lp8764-q1", .data = (void *)LP8764, },
+ {}
+};
+MODULE_DEVICE_TABLE(of, tps6594_spi_of_match_table);
+
+static int tps6594_spi_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct tps6594 *tps;
+ const struct of_device_id *match;
+
+ tps = devm_kzalloc(dev, sizeof(*tps), GFP_KERNEL);
+ if (!tps)
+ return -ENOMEM;
+
+ spi_set_drvdata(spi, tps);
+
+ tps->dev = dev;
+ tps->reg = spi->chip_select;
+ tps->irq = spi->irq;
+
+ tps->regmap = devm_regmap_init(dev, NULL, spi, &tps6594_spi_regmap_config);
+ if (IS_ERR(tps->regmap))
+ return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n");
+
+ match = of_match_device(tps6594_spi_of_match_table, dev);
+ if (!match)
+ 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);
+
+ return tps6594_device_init(tps, enable_crc);
+}
+
+static struct spi_driver tps6594_spi_driver = {
+ .driver = {
+ .name = "tps6594",
+ .of_match_table = tps6594_spi_of_match_table,
+ },
+ .probe = tps6594_spi_probe,
+};
+module_spi_driver(tps6594_spi_driver);
+
+MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 SPI Interface Driver");
+MODULE_LICENSE("GPL");
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/cardreader/rts5227.c b/drivers/misc/cardreader/rts5227.c
index d676cf63a966..3dae5e3a1697 100644
--- a/drivers/misc/cardreader/rts5227.c
+++ b/drivers/misc/cardreader/rts5227.c
@@ -195,7 +195,7 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
}
}
- if (option->force_clkreq_0)
+ if (option->force_clkreq_0 && pcr->aspm_mode == ASPM_MODE_CFG)
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG,
FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
else
diff --git a/drivers/misc/cardreader/rts5228.c b/drivers/misc/cardreader/rts5228.c
index cfebad51d1d8..f4ab09439da7 100644
--- a/drivers/misc/cardreader/rts5228.c
+++ b/drivers/misc/cardreader/rts5228.c
@@ -435,17 +435,10 @@ static void rts5228_init_from_cfg(struct rtsx_pcr *pcr)
option->ltr_enabled = false;
}
}
-
- if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN
- | PM_L1_1_EN | PM_L1_2_EN))
- option->force_clkreq_0 = false;
- else
- option->force_clkreq_0 = true;
}
static int rts5228_extra_init_hw(struct rtsx_pcr *pcr)
{
- struct rtsx_cr_option *option = &pcr->option;
rtsx_pci_write_register(pcr, RTS5228_AUTOLOAD_CFG1,
CD_RESUME_EN_MASK, CD_RESUME_EN_MASK);
@@ -476,17 +469,6 @@ static int rts5228_extra_init_hw(struct rtsx_pcr *pcr)
else
rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00);
- /*
- * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
- * to drive low, and we forcibly request clock.
- */
- if (option->force_clkreq_0)
- rtsx_pci_write_register(pcr, PETXCFG,
- FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
- else
- rtsx_pci_write_register(pcr, PETXCFG,
- FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
-
rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB);
if (pcr->rtd3_en) {
diff --git a/drivers/misc/cardreader/rts5249.c b/drivers/misc/cardreader/rts5249.c
index 91d240dd68fa..47ab72a43256 100644
--- a/drivers/misc/cardreader/rts5249.c
+++ b/drivers/misc/cardreader/rts5249.c
@@ -327,12 +327,11 @@ static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
}
}
-
/*
* If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
* to drive low, and we forcibly request clock.
*/
- if (option->force_clkreq_0)
+ if (option->force_clkreq_0 && pcr->aspm_mode == ASPM_MODE_CFG)
rtsx_pci_write_register(pcr, PETXCFG,
FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
else
diff --git a/drivers/misc/cardreader/rts5260.c b/drivers/misc/cardreader/rts5260.c
index 9b42b20a3e5a..79b18f6f73a8 100644
--- a/drivers/misc/cardreader/rts5260.c
+++ b/drivers/misc/cardreader/rts5260.c
@@ -517,17 +517,10 @@ static void rts5260_init_from_cfg(struct rtsx_pcr *pcr)
option->ltr_enabled = false;
}
}
-
- if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN
- | PM_L1_1_EN | PM_L1_2_EN))
- option->force_clkreq_0 = false;
- else
- option->force_clkreq_0 = true;
}
static int rts5260_extra_init_hw(struct rtsx_pcr *pcr)
{
- struct rtsx_cr_option *option = &pcr->option;
/* Set mcu_cnt to 7 to ensure data can be sampled properly */
rtsx_pci_write_register(pcr, 0xFC03, 0x7F, 0x07);
@@ -546,17 +539,6 @@ static int rts5260_extra_init_hw(struct rtsx_pcr *pcr)
rts5260_init_hw(pcr);
- /*
- * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
- * to drive low, and we forcibly request clock.
- */
- if (option->force_clkreq_0)
- rtsx_pci_write_register(pcr, PETXCFG,
- FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
- else
- rtsx_pci_write_register(pcr, PETXCFG,
- FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
-
rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x00);
return 0;
diff --git a/drivers/misc/cardreader/rts5261.c b/drivers/misc/cardreader/rts5261.c
index b1e76030cafd..94af6bf8a25a 100644
--- a/drivers/misc/cardreader/rts5261.c
+++ b/drivers/misc/cardreader/rts5261.c
@@ -498,17 +498,10 @@ static void rts5261_init_from_cfg(struct rtsx_pcr *pcr)
option->ltr_enabled = false;
}
}
-
- if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN
- | PM_L1_1_EN | PM_L1_2_EN))
- option->force_clkreq_0 = false;
- else
- option->force_clkreq_0 = true;
}
static int rts5261_extra_init_hw(struct rtsx_pcr *pcr)
{
- struct rtsx_cr_option *option = &pcr->option;
u32 val;
rtsx_pci_write_register(pcr, RTS5261_AUTOLOAD_CFG1,
@@ -554,17 +547,6 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr)
else
rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00);
- /*
- * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
- * to drive low, and we forcibly request clock.
- */
- if (option->force_clkreq_0)
- rtsx_pci_write_register(pcr, PETXCFG,
- FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
- else
- rtsx_pci_write_register(pcr, PETXCFG,
- FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
-
rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB);
if (pcr->rtd3_en) {
diff --git a/drivers/misc/cardreader/rtsx_pcr.c b/drivers/misc/cardreader/rtsx_pcr.c
index 32b7783e9d4f..a3f4b52bb159 100644
--- a/drivers/misc/cardreader/rtsx_pcr.c
+++ b/drivers/misc/cardreader/rtsx_pcr.c
@@ -1326,8 +1326,11 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
return err;
}
- if (pcr->aspm_mode == ASPM_MODE_REG)
+ if (pcr->aspm_mode == ASPM_MODE_REG) {
rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, 0x30, 0x30);
+ rtsx_pci_write_register(pcr, PETXCFG,
+ FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
+ }
/* No CD interrupt if probing driver with card inserted.
* So we need to initialize pcr->card_exist here.
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/bugs.c b/drivers/misc/lkdtm/bugs.c
index 48821f4c2b21..3c95600ab2f7 100644
--- a/drivers/misc/lkdtm/bugs.c
+++ b/drivers/misc/lkdtm/bugs.c
@@ -309,7 +309,7 @@ static void lkdtm_OVERFLOW_UNSIGNED(void)
struct array_bounds_flex_array {
int one;
int two;
- char data[1];
+ char data[];
};
struct array_bounds {
@@ -341,7 +341,7 @@ static void lkdtm_ARRAY_BOUNDS(void)
* For the uninstrumented flex array member, also touch 1 byte
* beyond to verify it is correctly uninstrumented.
*/
- for (i = 0; i < sizeof(not_checked->data) + 1; i++)
+ for (i = 0; i < 2; i++)
not_checked->data[i] = 'A';
pr_info("Array access beyond bounds ...\n");
@@ -487,6 +487,7 @@ static void lkdtm_UNSET_SMEP(void)
* the cr4 writing instruction.
*/
insn = (unsigned char *)native_write_cr4;
+ OPTIMIZER_HIDE_VAR(insn);
for (i = 0; i < MOV_CR4_DEPTH; i++) {
/* mov %rdi, %cr4 */
if (insn[i] == 0x0f && insn[i+1] == 0x22 && insn[i+2] == 0xe7)
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/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c
index b836936e9747..629edb6486de 100644
--- a/drivers/misc/sgi-gru/grufault.c
+++ b/drivers/misc/sgi-gru/grufault.c
@@ -185,7 +185,7 @@ static int non_atomic_pte_lookup(struct vm_area_struct *vma,
#else
*pageshift = PAGE_SHIFT;
#endif
- if (get_user_pages(vaddr, 1, write ? FOLL_WRITE : 0, &page, NULL) <= 0)
+ if (get_user_pages(vaddr, 1, write ? FOLL_WRITE : 0, &page) <= 0)
return -EFAULT;
*paddr = page_to_phys(page);
put_page(page);
@@ -228,7 +228,7 @@ static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr,
goto err;
#ifdef CONFIG_X86_64
if (unlikely(pmd_large(*pmdp)))
- pte = *(pte_t *) pmdp;
+ pte = ptep_get((pte_t *)pmdp);
else
#endif
pte = *pte_offset_kernel(pmdp, vaddr);
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..61209739dc43 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", of_node_full_name(child));
+ 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..05e2c151e632
--- /dev/null
+++ b/drivers/misc/tps6594-esm.c
@@ -0,0 +1,149 @@
+// 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>
+
+#define TPS6594_DEV_REV_1 0x08
+
+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;
+ unsigned int rev;
+ int irq;
+ int ret;
+ int i;
+
+ /*
+ * Due to a bug in revision 1 of the PMIC, the GPIO3 used for the
+ * SoC ESM function is used to power the load switch instead.
+ * As a consequence, ESM can not be used on those PMIC.
+ * Check the version and return an error in case of revision 1.
+ */
+ ret = regmap_read(tps->regmap, TPS6594_REG_DEV_REV, &rev);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to read PMIC revision\n");
+ if (rev == TPS6594_DEV_REV_1)
+ return dev_err_probe(dev, -ENODEV,
+ "ESM not supported for revision 1 PMIC\n");
+
+ 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/core/block.c b/drivers/mmc/core/block.c
index d920c4178389..b6f4be25b31b 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -178,6 +178,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
int recovery_mode,
struct mmc_queue *mq);
static void mmc_blk_hsq_req_done(struct mmc_request *mrq);
+static int mmc_spi_err_check(struct mmc_card *card);
static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
{
@@ -358,15 +359,15 @@ static const struct attribute_group *mmc_disk_attr_groups[] = {
NULL,
};
-static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
+static int mmc_blk_open(struct gendisk *disk, blk_mode_t mode)
{
- struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
+ struct mmc_blk_data *md = mmc_blk_get(disk);
int ret = -ENXIO;
mutex_lock(&block_mutex);
if (md) {
ret = 0;
- if ((mode & FMODE_WRITE) && md->read_only) {
+ if ((mode & BLK_OPEN_WRITE) && md->read_only) {
mmc_blk_put(md);
ret = -EROFS;
}
@@ -376,7 +377,7 @@ static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
return ret;
}
-static void mmc_blk_release(struct gendisk *disk, fmode_t mode)
+static void mmc_blk_release(struct gendisk *disk)
{
struct mmc_blk_data *md = disk->private_data;
@@ -608,6 +609,11 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
return 0;
+ if (mmc_host_is_spi(card->host)) {
+ if (idata->ic.write_flag || r1b_resp || cmd.flags & MMC_RSP_SPI_BUSY)
+ return mmc_spi_err_check(card);
+ return err;
+ }
/* Ensure RPMB/R1B command has completed by polling with CMD13. */
if (idata->rpmb || r1b_resp)
err = mmc_poll_for_busy(card, busy_timeout_ms, false,
@@ -757,7 +763,7 @@ static int mmc_blk_check_blkdev(struct block_device *bdev)
return 0;
}
-static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
+static int mmc_blk_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long arg)
{
struct mmc_blk_data *md;
@@ -794,7 +800,7 @@ static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
}
#ifdef CONFIG_COMPAT
-static int mmc_blk_compat_ioctl(struct block_device *bdev, fmode_t mode,
+static int mmc_blk_compat_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long arg)
{
return mmc_blk_ioctl(bdev, mode, cmd, (unsigned long) compat_ptr(arg));
@@ -2091,14 +2097,14 @@ static void mmc_blk_mq_poll_completion(struct mmc_queue *mq,
mmc_blk_urgent_bkops(mq, mqrq);
}
-static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, struct request *req)
+static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, enum mmc_issue_type issue_type)
{
unsigned long flags;
bool put_card;
spin_lock_irqsave(&mq->lock, flags);
- mq->in_flight[mmc_issue_type(mq, req)] -= 1;
+ mq->in_flight[issue_type] -= 1;
put_card = (mmc_tot_in_flight(mq) == 0);
@@ -2111,6 +2117,7 @@ static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, struct request *req)
static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req,
bool can_sleep)
{
+ enum mmc_issue_type issue_type = mmc_issue_type(mq, req);
struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
struct mmc_request *mrq = &mqrq->brq.mrq;
struct mmc_host *host = mq->card->host;
@@ -2130,7 +2137,7 @@ static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req,
blk_mq_complete_request(req);
}
- mmc_blk_mq_dec_in_flight(mq, req);
+ mmc_blk_mq_dec_in_flight(mq, issue_type);
}
void mmc_blk_mq_recovery(struct mmc_queue *mq)
@@ -2505,9 +2512,9 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
string_get_size((u64)size, 512, STRING_UNITS_2,
cap_str, sizeof(cap_str));
- pr_info("%s: %s %s %s %s\n",
+ pr_info("%s: %s %s %s%s\n",
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
- cap_str, md->read_only ? "(ro)" : "");
+ cap_str, md->read_only ? " (ro)" : "");
/* used in ->open, must be set before add_disk: */
if (area_type == MMC_BLK_DATA_AREA_MAIN)
@@ -2899,12 +2906,12 @@ static const struct file_operations mmc_dbg_ext_csd_fops = {
.llseek = default_llseek,
};
-static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md)
+static void mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md)
{
struct dentry *root;
if (!card->debugfs_root)
- return 0;
+ return;
root = card->debugfs_root;
@@ -2913,19 +2920,13 @@ static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md)
debugfs_create_file_unsafe("status", 0400, root,
card,
&mmc_dbg_card_status_fops);
- if (!md->status_dentry)
- return -EIO;
}
if (mmc_card_mmc(card)) {
md->ext_csd_dentry =
debugfs_create_file("ext_csd", S_IRUSR, root, card,
&mmc_dbg_ext_csd_fops);
- if (!md->ext_csd_dentry)
- return -EIO;
}
-
- return 0;
}
static void mmc_blk_remove_debugfs(struct mmc_card *card,
@@ -2934,22 +2935,17 @@ static void mmc_blk_remove_debugfs(struct mmc_card *card,
if (!card->debugfs_root)
return;
- if (!IS_ERR_OR_NULL(md->status_dentry)) {
- debugfs_remove(md->status_dentry);
- md->status_dentry = NULL;
- }
+ debugfs_remove(md->status_dentry);
+ md->status_dentry = NULL;
- if (!IS_ERR_OR_NULL(md->ext_csd_dentry)) {
- debugfs_remove(md->ext_csd_dentry);
- md->ext_csd_dentry = NULL;
- }
+ debugfs_remove(md->ext_csd_dentry);
+ md->ext_csd_dentry = NULL;
}
#else
-static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md)
+static void mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md)
{
- return 0;
}
static void mmc_blk_remove_debugfs(struct mmc_card *card,
diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h
index cfdd1ff40b86..4edf9057fa79 100644
--- a/drivers/mmc/core/card.h
+++ b/drivers/mmc/core/card.h
@@ -53,6 +53,10 @@ struct mmc_fixup {
unsigned int manfid;
unsigned short oemid;
+ /* Manufacturing date */
+ unsigned short year;
+ unsigned char month;
+
/* SDIO-specific fields. You can use SDIO_ANY_ID here of course */
u16 cis_vendor, cis_device;
@@ -68,6 +72,8 @@ struct mmc_fixup {
#define CID_MANFID_ANY (-1u)
#define CID_OEMID_ANY ((unsigned short) -1)
+#define CID_YEAR_ANY ((unsigned short) -1)
+#define CID_MONTH_ANY ((unsigned char) -1)
#define CID_NAME_ANY (NULL)
#define EXT_CSD_REV_ANY (-1u)
@@ -81,17 +87,21 @@ struct mmc_fixup {
#define CID_MANFID_APACER 0x27
#define CID_MANFID_KINGSTON 0x70
#define CID_MANFID_HYNIX 0x90
+#define CID_MANFID_KINGSTON_SD 0x9F
#define CID_MANFID_NUMONYX 0xFE
#define END_FIXUP { NULL }
-#define _FIXUP_EXT(_name, _manfid, _oemid, _rev_start, _rev_end, \
- _cis_vendor, _cis_device, \
- _fixup, _data, _ext_csd_rev) \
+#define _FIXUP_EXT(_name, _manfid, _oemid, _year, _month, \
+ _rev_start, _rev_end, \
+ _cis_vendor, _cis_device, \
+ _fixup, _data, _ext_csd_rev) \
{ \
.name = (_name), \
.manfid = (_manfid), \
.oemid = (_oemid), \
+ .year = (_year), \
+ .month = (_month), \
.rev_start = (_rev_start), \
.rev_end = (_rev_end), \
.cis_vendor = (_cis_vendor), \
@@ -103,8 +113,8 @@ struct mmc_fixup {
#define MMC_FIXUP_REV(_name, _manfid, _oemid, _rev_start, _rev_end, \
_fixup, _data, _ext_csd_rev) \
- _FIXUP_EXT(_name, _manfid, \
- _oemid, _rev_start, _rev_end, \
+ _FIXUP_EXT(_name, _manfid, _oemid, CID_YEAR_ANY, CID_MONTH_ANY, \
+ _rev_start, _rev_end, \
SDIO_ANY_ID, SDIO_ANY_ID, \
_fixup, _data, _ext_csd_rev) \
@@ -118,8 +128,9 @@ struct mmc_fixup {
_ext_csd_rev)
#define SDIO_FIXUP(_vendor, _device, _fixup, _data) \
- _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_ANY, \
- CID_OEMID_ANY, 0, -1ull, \
+ _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_ANY, CID_OEMID_ANY, \
+ CID_YEAR_ANY, CID_MONTH_ANY, \
+ 0, -1ull, \
_vendor, _device, \
_fixup, _data, EXT_CSD_REV_ANY) \
@@ -264,4 +275,9 @@ static inline int mmc_card_broken_sd_discard(const struct mmc_card *c)
return c->quirks & MMC_QUIRK_BROKEN_SD_DISCARD;
}
+static inline int mmc_card_broken_sd_cache(const struct mmc_card *c)
+{
+ return c->quirks & MMC_QUIRK_BROKEN_SD_CACHE;
+}
+
#endif
diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h
index 29b9497936df..32b64b564fb1 100644
--- a/drivers/mmc/core/quirks.h
+++ b/drivers/mmc/core/quirks.h
@@ -54,6 +54,15 @@ static const struct mmc_fixup __maybe_unused mmc_blk_fixups[] = {
MMC_QUIRK_BLK_NO_CMD23),
/*
+ * Kingston Canvas Go! Plus microSD cards never finish SD cache flush.
+ * This has so far only been observed on cards from 11/2019, while new
+ * cards from 2023/05 do not exhibit this behavior.
+ */
+ _FIXUP_EXT("SD64G", CID_MANFID_KINGSTON_SD, 0x5449, 2019, 11,
+ 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd,
+ MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY),
+
+ /*
* Some SD cards lockup while using CMD23 multiblock transfers.
*/
MMC_FIXUP("AF SD", CID_MANFID_ATP, CID_OEMID_ANY, add_quirk_sd,
@@ -101,6 +110,20 @@ static const struct mmc_fixup __maybe_unused mmc_blk_fixups[] = {
MMC_QUIRK_TRIM_BROKEN),
/*
+ * Micron MTFC4GACAJCN-1M advertises TRIM but it does not seems to
+ * support being used to offload WRITE_ZEROES.
+ */
+ MMC_FIXUP("Q2J54A", CID_MANFID_MICRON, 0x014e, add_quirk_mmc,
+ MMC_QUIRK_TRIM_BROKEN),
+
+ /*
+ * Kingston EMMC04G-M627 advertises TRIM but it does not seems to
+ * support being used to offload WRITE_ZEROES.
+ */
+ MMC_FIXUP("M62704", CID_MANFID_KINGSTON, 0x0100, add_quirk_mmc,
+ MMC_QUIRK_TRIM_BROKEN),
+
+ /*
* Some SD cards reports discard support while they don't
*/
MMC_FIXUP(CID_NAME_ANY, CID_MANFID_SANDISK_SD, 0x5344, add_quirk_sd,
@@ -209,6 +232,10 @@ static inline void mmc_fixup_device(struct mmc_card *card,
if (f->of_compatible &&
!mmc_fixup_of_compatible_match(card, f->of_compatible))
continue;
+ if (f->year != CID_YEAR_ANY && f->year != card->cid.year)
+ continue;
+ if (f->month != CID_MONTH_ANY && f->month != card->cid.month)
+ continue;
dev_dbg(&card->dev, "calling %ps\n", f->vendor_fixup);
f->vendor_fixup(card, f->data);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 72b664ed90cf..246ce027ae0a 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1170,7 +1170,7 @@ static int sd_parse_ext_reg_perf(struct mmc_card *card, u8 fno, u8 page,
card->ext_perf.feature_support |= SD_EXT_PERF_HOST_MAINT;
/* Cache support at bit 0. */
- if (reg_buf[4] & BIT(0))
+ if ((reg_buf[4] & BIT(0)) && !mmc_card_broken_sd_cache(card))
card->ext_perf.feature_support |= SD_EXT_PERF_CACHE;
/* Command queue support indicated via queue depth bits (0 to 4). */
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 9f793892123c..159a3e9490ae 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -550,7 +550,7 @@ config MMC_SDHCI_MSM
depends on MMC_SDHCI_PLTFM
select MMC_SDHCI_IO_ACCESSORS
select MMC_CQHCI
- select QCOM_SCM if MMC_CRYPTO
+ select QCOM_INLINE_CRYPTO_ENGINE if MMC_CRYPTO
help
This selects the Secure Digital Host Controller Interface (SDHCI)
support present in Qualcomm SOCs. The controller supports
diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h
index ba9387ed90eb..1a12e40a02e6 100644
--- a/drivers/mmc/host/cqhci.h
+++ b/drivers/mmc/host/cqhci.h
@@ -5,6 +5,7 @@
#define LINUX_MMC_CQHCI_H
#include <linux/compiler.h>
+#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/spinlock_types.h>
#include <linux/types.h>
@@ -23,6 +24,8 @@
/* capabilities */
#define CQHCI_CAP 0x04
#define CQHCI_CAP_CS 0x10000000 /* Crypto Support */
+#define CQHCI_CAP_ITCFMUL GENMASK(15, 12)
+#define CQHCI_ITCFMUL(x) FIELD_GET(CQHCI_CAP_ITCFMUL, (x))
/* configuration */
#define CQHCI_CFG 0x08
diff --git a/drivers/mmc/host/dw_mmc-bluefield.c b/drivers/mmc/host/dw_mmc-bluefield.c
index 10baf122bc15..4747e5698f48 100644
--- a/drivers/mmc/host/dw_mmc-bluefield.c
+++ b/drivers/mmc/host/dw_mmc-bluefield.c
@@ -52,7 +52,7 @@ static int dw_mci_bluefield_probe(struct platform_device *pdev)
static struct platform_driver dw_mci_bluefield_pltfm_driver = {
.probe = dw_mci_bluefield_probe,
- .remove = dw_mci_pltfm_remove,
+ .remove_new = dw_mci_pltfm_remove,
.driver = {
.name = "dwmmc_bluefield",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
index 0311a37dd4ab..e8ee7c43f60b 100644
--- a/drivers/mmc/host/dw_mmc-k3.c
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -470,7 +470,7 @@ static const struct dev_pm_ops dw_mci_k3_dev_pm_ops = {
static struct platform_driver dw_mci_k3_pltfm_driver = {
.probe = dw_mci_k3_probe,
- .remove = dw_mci_pltfm_remove,
+ .remove_new = dw_mci_pltfm_remove,
.driver = {
.name = "dwmmc_k3",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
index 48b7da2b86b3..2353fadceda1 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.c
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -121,18 +121,17 @@ static int dw_mci_pltfm_probe(struct platform_device *pdev)
return dw_mci_pltfm_register(pdev, drv_data);
}
-int dw_mci_pltfm_remove(struct platform_device *pdev)
+void dw_mci_pltfm_remove(struct platform_device *pdev)
{
struct dw_mci *host = platform_get_drvdata(pdev);
dw_mci_remove(host);
- return 0;
}
EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove);
static struct platform_driver dw_mci_pltfm_driver = {
.probe = dw_mci_pltfm_probe,
- .remove = dw_mci_pltfm_remove,
+ .remove_new = dw_mci_pltfm_remove,
.driver = {
.name = "dw_mmc",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/dw_mmc-pltfm.h b/drivers/mmc/host/dw_mmc-pltfm.h
index 2d50d7da2e36..64cf7522a3d4 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.h
+++ b/drivers/mmc/host/dw_mmc-pltfm.h
@@ -10,7 +10,7 @@
extern int dw_mci_pltfm_register(struct platform_device *pdev,
const struct dw_mci_drv_data *drv_data);
-extern int dw_mci_pltfm_remove(struct platform_device *pdev);
+extern void dw_mci_pltfm_remove(struct platform_device *pdev);
extern const struct dev_pm_ops dw_mci_pltfm_pmops;
#endif /* _DW_MMC_PLTFM_H_ */
diff --git a/drivers/mmc/host/dw_mmc-starfive.c b/drivers/mmc/host/dw_mmc-starfive.c
index dab1508bf83c..fd05a648a8bb 100644
--- a/drivers/mmc/host/dw_mmc-starfive.c
+++ b/drivers/mmc/host/dw_mmc-starfive.c
@@ -172,7 +172,7 @@ static int dw_mci_starfive_probe(struct platform_device *pdev)
static struct platform_driver dw_mci_starfive_driver = {
.probe = dw_mci_starfive_probe,
- .remove = dw_mci_pltfm_remove,
+ .remove_new = dw_mci_pltfm_remove,
.driver = {
.name = "dwmmc_starfive",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/meson-mx-sdhc-mmc.c b/drivers/mmc/host/meson-mx-sdhc-mmc.c
index da85c2f2acb8..97168cdfa8e9 100644
--- a/drivers/mmc/host/meson-mx-sdhc-mmc.c
+++ b/drivers/mmc/host/meson-mx-sdhc-mmc.c
@@ -776,6 +776,11 @@ static void meson_mx_sdhc_init_hw(struct mmc_host *mmc)
regmap_write(host->regmap, MESON_SDHC_ISTA, MESON_SDHC_ISTA_ALL_IRQS);
}
+static void meason_mx_mmc_free_host(void *data)
+{
+ mmc_free_host(data);
+}
+
static int meson_mx_sdhc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -788,8 +793,7 @@ static int meson_mx_sdhc_probe(struct platform_device *pdev)
if (!mmc)
return -ENOMEM;
- ret = devm_add_action_or_reset(dev, (void(*)(void *))mmc_free_host,
- mmc);
+ ret = devm_add_action_or_reset(dev, meason_mx_mmc_free_host, mmc);
if (ret) {
dev_err(dev, "Failed to register mmc_free_host action\n");
return ret;
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 696cbef3ff7d..769b34afa835 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -37,6 +37,7 @@
#include <linux/pinctrl/consumer.h>
#include <linux/reset.h>
#include <linux/gpio/consumer.h>
+#include <linux/workqueue.h>
#include <asm/div64.h>
#include <asm/io.h>
@@ -270,6 +271,7 @@ static struct variant_data variant_stm32_sdmmc = {
.datactrl_any_blocksz = true,
.datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.stm32_idmabsize_mask = GENMASK(12, 5),
+ .stm32_idmabsize_align = BIT(5),
.busy_timeout = true,
.busy_detect = true,
.busy_detect_flag = MCI_STM32_BUSYD0,
@@ -296,6 +298,35 @@ static struct variant_data variant_stm32_sdmmcv2 = {
.datactrl_any_blocksz = true,
.datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.stm32_idmabsize_mask = GENMASK(16, 5),
+ .stm32_idmabsize_align = BIT(5),
+ .dma_lli = true,
+ .busy_timeout = true,
+ .busy_detect = true,
+ .busy_detect_flag = MCI_STM32_BUSYD0,
+ .busy_detect_mask = MCI_STM32_BUSYD0ENDMASK,
+ .init = sdmmc_variant_init,
+};
+
+static struct variant_data variant_stm32_sdmmcv3 = {
+ .fifosize = 256 * 4,
+ .fifohalfsize = 128 * 4,
+ .f_max = 267000000,
+ .stm32_clkdiv = true,
+ .cmdreg_cpsm_enable = MCI_CPSM_STM32_ENABLE,
+ .cmdreg_lrsp_crc = MCI_CPSM_STM32_LRSP_CRC,
+ .cmdreg_srsp_crc = MCI_CPSM_STM32_SRSP_CRC,
+ .cmdreg_srsp = MCI_CPSM_STM32_SRSP,
+ .cmdreg_stop = MCI_CPSM_STM32_CMDSTOP,
+ .data_cmd_enable = MCI_CPSM_STM32_CMDTRANS,
+ .irq_pio_mask = MCI_IRQ_PIO_STM32_MASK,
+ .datactrl_first = true,
+ .datacnt_useless = true,
+ .datalength_bits = 25,
+ .datactrl_blocksz = 14,
+ .datactrl_any_blocksz = true,
+ .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
+ .stm32_idmabsize_mask = GENMASK(16, 6),
+ .stm32_idmabsize_align = BIT(6),
.dma_lli = true,
.busy_timeout = true,
.busy_detect = true,
@@ -654,10 +685,52 @@ static u32 ux500v2_get_dctrl_cfg(struct mmci_host *host)
return MCI_DPSM_ENABLE | (host->data->blksz << 16);
}
-static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
+static void ux500_busy_clear_mask_done(struct mmci_host *host)
{
void __iomem *base = host->base;
+ writel(host->variant->busy_detect_mask, base + MMCICLEAR);
+ writel(readl(base + MMCIMASK0) &
+ ~host->variant->busy_detect_mask, base + MMCIMASK0);
+ host->busy_state = MMCI_BUSY_DONE;
+ host->busy_status = 0;
+}
+
+/*
+ * ux500_busy_complete() - this will wait until the busy status
+ * goes off, saving any status that occur in the meantime into
+ * host->busy_status until we know the card is not busy any more.
+ * The function returns true when the busy detection is ended
+ * and we should continue processing the command.
+ *
+ * The Ux500 typically fires two IRQs over a busy cycle like this:
+ *
+ * DAT0 busy +-----------------+
+ * | |
+ * DAT0 not busy ----+ +--------
+ *
+ * ^ ^
+ * | |
+ * IRQ1 IRQ2
+ */
+static bool ux500_busy_complete(struct mmci_host *host, struct mmc_command *cmd,
+ u32 status, u32 err_msk)
+{
+ void __iomem *base = host->base;
+ int retries = 10;
+
+ if (status & err_msk) {
+ /* Stop any ongoing busy detection if an error occurs */
+ ux500_busy_clear_mask_done(host);
+ goto out_ret_state;
+ }
+
+ /*
+ * The state transitions are encoded in a state machine crossing
+ * the edges in this switch statement.
+ */
+ switch (host->busy_state) {
+
/*
* Before unmasking for the busy end IRQ, confirm that the
* command was sent successfully. To keep track of having a
@@ -667,19 +740,33 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
* Note that, the card may need a couple of clock cycles before
* it starts signaling busy on DAT0, hence re-read the
* MMCISTATUS register here, to allow the busy bit to be set.
- * Potentially we may even need to poll the register for a
- * while, to allow it to be set, but tests indicates that it
- * isn't needed.
*/
- if (!host->busy_status && !(status & err_msk) &&
- (readl(base + MMCISTATUS) & host->variant->busy_detect_flag)) {
- writel(readl(base + MMCIMASK0) |
- host->variant->busy_detect_mask,
- base + MMCIMASK0);
-
+ case MMCI_BUSY_DONE:
+ /*
+ * Save the first status register read to be sure to catch
+ * all bits that may be lost will retrying. If the command
+ * is still busy this will result in assigning 0 to
+ * host->busy_status, which is what it should be in IDLE.
+ */
host->busy_status = status & (MCI_CMDSENT | MCI_CMDRESPEND);
- return false;
- }
+ while (retries) {
+ status = readl(base + MMCISTATUS);
+ /* Keep accumulating status bits */
+ host->busy_status |= status & (MCI_CMDSENT | MCI_CMDRESPEND);
+ if (status & host->variant->busy_detect_flag) {
+ writel(readl(base + MMCIMASK0) |
+ host->variant->busy_detect_mask,
+ base + MMCIMASK0);
+ host->busy_state = MMCI_BUSY_WAITING_FOR_START_IRQ;
+ schedule_delayed_work(&host->ux500_busy_timeout_work,
+ msecs_to_jiffies(cmd->busy_timeout));
+ goto out_ret_state;
+ }
+ retries--;
+ }
+ dev_dbg(mmc_dev(host->mmc), "no busy signalling in time\n");
+ ux500_busy_clear_mask_done(host);
+ break;
/*
* If there is a command in-progress that has been successfully
@@ -692,27 +779,39 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
* both the start and the end interrupts needs to be cleared,
* one after the other. So, clear the busy start IRQ here.
*/
- if (host->busy_status &&
- (status & host->variant->busy_detect_flag)) {
- writel(host->variant->busy_detect_mask, base + MMCICLEAR);
- return false;
- }
+ case MMCI_BUSY_WAITING_FOR_START_IRQ:
+ if (status & host->variant->busy_detect_flag) {
+ host->busy_status |= status & (MCI_CMDSENT | MCI_CMDRESPEND);
+ writel(host->variant->busy_detect_mask, base + MMCICLEAR);
+ host->busy_state = MMCI_BUSY_WAITING_FOR_END_IRQ;
+ } else {
+ dev_dbg(mmc_dev(host->mmc),
+ "lost busy status when waiting for busy start IRQ\n");
+ cancel_delayed_work(&host->ux500_busy_timeout_work);
+ ux500_busy_clear_mask_done(host);
+ }
+ break;
- /*
- * If there is a command in-progress that has been successfully
- * sent and the busy bit isn't set, it means we have received
- * the busy end IRQ. Clear and mask the IRQ, then continue to
- * process the command.
- */
- if (host->busy_status) {
- writel(host->variant->busy_detect_mask, base + MMCICLEAR);
+ case MMCI_BUSY_WAITING_FOR_END_IRQ:
+ if (!(status & host->variant->busy_detect_flag)) {
+ host->busy_status |= status & (MCI_CMDSENT | MCI_CMDRESPEND);
+ writel(host->variant->busy_detect_mask, base + MMCICLEAR);
+ cancel_delayed_work(&host->ux500_busy_timeout_work);
+ ux500_busy_clear_mask_done(host);
+ } else {
+ dev_dbg(mmc_dev(host->mmc),
+ "busy status still asserted when handling busy end IRQ - will keep waiting\n");
+ }
+ break;
- writel(readl(base + MMCIMASK0) &
- ~host->variant->busy_detect_mask, base + MMCIMASK0);
- host->busy_status = 0;
+ default:
+ dev_dbg(mmc_dev(host->mmc), "fell through on state %d\n",
+ host->busy_state);
+ break;
}
- return true;
+out_ret_state:
+ return (host->busy_state == MMCI_BUSY_DONE);
}
/*
@@ -1214,6 +1313,7 @@ static void
mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
{
void __iomem *base = host->base;
+ bool busy_resp = cmd->flags & MMC_RSP_BUSY;
unsigned long long clks;
dev_dbg(mmc_dev(host->mmc), "op %02x arg %08x flags %08x\n",
@@ -1238,10 +1338,14 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
c |= host->variant->cmdreg_srsp;
}
- if (host->variant->busy_timeout && cmd->flags & MMC_RSP_BUSY) {
- if (!cmd->busy_timeout)
- cmd->busy_timeout = 10 * MSEC_PER_SEC;
+ host->busy_status = 0;
+ host->busy_state = MMCI_BUSY_DONE;
+ /* Assign a default timeout if the core does not provide one */
+ if (busy_resp && !cmd->busy_timeout)
+ cmd->busy_timeout = 10 * MSEC_PER_SEC;
+
+ if (busy_resp && host->variant->busy_timeout) {
if (cmd->busy_timeout > host->mmc->max_busy_timeout)
clks = (unsigned long long)host->mmc->max_busy_timeout * host->cclk;
else
@@ -1382,7 +1486,7 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
/* Handle busy detection on DAT0 if the variant supports it. */
if (busy_resp && host->variant->busy_detect)
- if (!host->ops->busy_complete(host, status, err_msk))
+ if (!host->ops->busy_complete(host, cmd, status, err_msk))
return;
host->cmd = NULL;
@@ -1429,6 +1533,34 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
}
}
+/*
+ * This busy timeout worker is used to "kick" the command IRQ if a
+ * busy detect IRQ fails to appear in reasonable time. Only used on
+ * variants with busy detection IRQ delivery.
+ */
+static void ux500_busy_timeout_work(struct work_struct *work)
+{
+ struct mmci_host *host = container_of(work, struct mmci_host,
+ ux500_busy_timeout_work.work);
+ unsigned long flags;
+ u32 status;
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ if (host->cmd) {
+ dev_dbg(mmc_dev(host->mmc), "timeout waiting for busy IRQ\n");
+
+ /* If we are still busy let's tag on a cmd-timeout error. */
+ status = readl(host->base + MMCISTATUS);
+ if (status & host->variant->busy_detect_flag)
+ status |= MCI_CMDTIMEOUT;
+
+ mmci_cmd_irq(host, host->cmd, status);
+ }
+
+ spin_unlock_irqrestore(&host->lock, flags);
+}
+
static int mmci_get_rx_fifocnt(struct mmci_host *host, u32 status, int remain)
{
return remain - (readl(host->base + MMCIFIFOCNT) << 2);
@@ -2243,6 +2375,10 @@ static int mmci_probe(struct amba_device *dev,
goto clk_disable;
}
+ if (host->variant->busy_detect)
+ INIT_DELAYED_WORK(&host->ux500_busy_timeout_work,
+ ux500_busy_timeout_work);
+
writel(MCI_IRQENABLE | variant->start_err, host->base + MMCIMASK0);
amba_set_drvdata(dev, mmc);
@@ -2441,6 +2577,11 @@ static const struct amba_id mmci_ids[] = {
.mask = 0xf0ffffff,
.data = &variant_stm32_sdmmcv2,
},
+ {
+ .id = 0x00353180,
+ .mask = 0xf0ffffff,
+ .data = &variant_stm32_sdmmcv3,
+ },
/* Qualcomm variants */
{
.id = 0x00051180,
@@ -2456,6 +2597,7 @@ static struct amba_driver mmci_driver = {
.drv = {
.name = DRIVER_NAME,
.pm = &mmci_dev_pm_ops,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe = mmci_probe,
.remove = mmci_remove,
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index e1a9b96a3396..253197f132fc 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -218,6 +218,11 @@
#define MCI_STM32_BUSYD0ENDMASK BIT(21)
#define MMCIMASK1 0x040
+
+/* STM32 sdmmc data FIFO threshold register */
+#define MMCI_STM32_FIFOTHRR 0x044
+#define MMCI_STM32_THR_MASK GENMASK(3, 0)
+
#define MMCIFIFOCNT 0x048
#define MMCIFIFO 0x080 /* to 0x0bc */
@@ -227,8 +232,6 @@
#define MMCI_STM32_IDMALLIEN BIT(1)
#define MMCI_STM32_IDMABSIZER 0x054
-#define MMCI_STM32_IDMABNDT_SHIFT 5
-#define MMCI_STM32_IDMABNDT_MASK GENMASK(12, 5)
#define MMCI_STM32_IDMABASE0R 0x058
@@ -262,6 +265,19 @@ struct dma_chan;
struct mmci_host;
/**
+ * enum mmci_busy_state - enumerate the busy detect wait states
+ *
+ * This is used for the state machine waiting for different busy detect
+ * interrupts on hardware that fire a single IRQ for start and end of
+ * the busy detect phase on DAT0.
+ */
+enum mmci_busy_state {
+ MMCI_BUSY_WAITING_FOR_START_IRQ,
+ MMCI_BUSY_WAITING_FOR_END_IRQ,
+ MMCI_BUSY_DONE,
+};
+
+/**
* struct variant_data - MMCI variant-specific quirks
* @clkreg: default value for MCICLOCK register
* @clkreg_enable: enable value for MMCICLOCK register
@@ -361,6 +377,7 @@ struct variant_data {
u32 opendrain;
u8 dma_lli:1;
u32 stm32_idmabsize_mask;
+ u32 stm32_idmabsize_align;
void (*init)(struct mmci_host *host);
};
@@ -380,7 +397,7 @@ struct mmci_host_ops {
void (*dma_error)(struct mmci_host *host);
void (*set_clkreg)(struct mmci_host *host, unsigned int desired);
void (*set_pwrreg)(struct mmci_host *host, unsigned int pwr);
- bool (*busy_complete)(struct mmci_host *host, u32 status, u32 err_msk);
+ bool (*busy_complete)(struct mmci_host *host, struct mmc_command *cmd, u32 status, u32 err_msk);
void (*pre_sig_volt_switch)(struct mmci_host *host);
int (*post_sig_volt_switch)(struct mmci_host *host, struct mmc_ios *ios);
};
@@ -409,6 +426,7 @@ struct mmci_host {
u32 clk_reg;
u32 clk_reg_add;
u32 datactrl_reg;
+ enum mmci_busy_state busy_state;
u32 busy_status;
u32 mask1_reg;
u8 vqmmc_enabled:1;
@@ -437,6 +455,7 @@ struct mmci_host {
void *dma_priv;
s32 next_cookie;
+ struct delayed_work ux500_busy_timeout_work;
};
#define dma_inprogress(host) ((host)->dma_in_progress)
diff --git a/drivers/mmc/host/mmci_stm32_sdmmc.c b/drivers/mmc/host/mmci_stm32_sdmmc.c
index 60bca78a72b1..35067e1e6cd8 100644
--- a/drivers/mmc/host/mmci_stm32_sdmmc.c
+++ b/drivers/mmc/host/mmci_stm32_sdmmc.c
@@ -15,7 +15,6 @@
#include "mmci.h"
#define SDMMC_LLI_BUF_LEN PAGE_SIZE
-#define SDMMC_IDMA_BURST BIT(MMCI_STM32_IDMABNDT_SHIFT)
#define DLYB_CR 0x0
#define DLYB_CR_DEN BIT(0)
@@ -34,6 +33,20 @@
#define DLYB_LNG_TIMEOUT_US 1000
#define SDMMC_VSWEND_TIMEOUT_US 10000
+#define SYSCFG_DLYBSD_CR 0x0
+#define DLYBSD_CR_EN BIT(0)
+#define DLYBSD_CR_RXTAPSEL_MASK GENMASK(6, 1)
+#define DLYBSD_TAPSEL_NB 32
+#define DLYBSD_BYP_EN BIT(16)
+#define DLYBSD_BYP_CMD GENMASK(21, 17)
+#define DLYBSD_ANTIGLITCH_EN BIT(22)
+
+#define SYSCFG_DLYBSD_SR 0x4
+#define DLYBSD_SR_LOCK BIT(0)
+#define DLYBSD_SR_RXTAPSEL_ACK BIT(1)
+
+#define DLYBSD_TIMEOUT_1S_IN_US 1000000
+
struct sdmmc_lli_desc {
u32 idmalar;
u32 idmabase;
@@ -48,10 +61,21 @@ struct sdmmc_idma {
bool use_bounce_buffer;
};
+struct sdmmc_dlyb;
+
+struct sdmmc_tuning_ops {
+ int (*dlyb_enable)(struct sdmmc_dlyb *dlyb);
+ void (*set_input_ck)(struct sdmmc_dlyb *dlyb);
+ int (*tuning_prepare)(struct mmci_host *host);
+ int (*set_cfg)(struct sdmmc_dlyb *dlyb, int unit __maybe_unused,
+ int phase, bool sampler __maybe_unused);
+};
+
struct sdmmc_dlyb {
void __iomem *base;
u32 unit;
u32 max;
+ struct sdmmc_tuning_ops *ops;
};
static int sdmmc_idma_validate_data(struct mmci_host *host,
@@ -69,7 +93,8 @@ static int sdmmc_idma_validate_data(struct mmci_host *host,
idma->use_bounce_buffer = false;
for_each_sg(data->sg, sg, data->sg_len - 1, i) {
if (!IS_ALIGNED(sg->offset, sizeof(u32)) ||
- !IS_ALIGNED(sg->length, SDMMC_IDMA_BURST)) {
+ !IS_ALIGNED(sg->length,
+ host->variant->stm32_idmabsize_align)) {
dev_dbg(mmc_dev(host->mmc),
"unaligned scatterlist: ofst:%x length:%d\n",
data->sg->offset, data->sg->length);
@@ -293,23 +318,13 @@ static void mmci_sdmmc_set_clkreg(struct mmci_host *host, unsigned int desired)
clk |= host->clk_reg_add;
clk |= ddr;
- /*
- * SDMMC_FBCK is selected when an external Delay Block is needed
- * with SDR104 or HS200.
- */
- if (host->mmc->ios.timing >= MMC_TIMING_UHS_SDR50) {
+ if (host->mmc->ios.timing >= MMC_TIMING_UHS_SDR50)
clk |= MCI_STM32_CLK_BUSSPEED;
- if (host->mmc->ios.timing == MMC_TIMING_UHS_SDR104 ||
- host->mmc->ios.timing == MMC_TIMING_MMC_HS200) {
- clk &= ~MCI_STM32_CLK_SEL_MSK;
- clk |= MCI_STM32_CLK_SELFBCK;
- }
- }
mmci_write_clkreg(host, clk);
}
-static void sdmmc_dlyb_input_ck(struct sdmmc_dlyb *dlyb)
+static void sdmmc_dlyb_mp15_input_ck(struct sdmmc_dlyb *dlyb)
{
if (!dlyb || !dlyb->base)
return;
@@ -326,7 +341,8 @@ static void mmci_sdmmc_set_pwrreg(struct mmci_host *host, unsigned int pwr)
/* adds OF options */
pwr = host->pwr_reg_add;
- sdmmc_dlyb_input_ck(dlyb);
+ if (dlyb && dlyb->ops->set_input_ck)
+ dlyb->ops->set_input_ck(dlyb);
if (ios.power_mode == MMC_POWER_OFF) {
/* Only a reset could power-off sdmmc */
@@ -371,6 +387,19 @@ static u32 sdmmc_get_dctrl_cfg(struct mmci_host *host)
datactrl = mmci_dctrl_blksz(host);
+ if (host->hw_revision >= 3) {
+ u32 thr = 0;
+
+ if (host->mmc->ios.timing == MMC_TIMING_UHS_SDR104 ||
+ host->mmc->ios.timing == MMC_TIMING_MMC_HS200) {
+ thr = ffs(min_t(unsigned int, host->data->blksz,
+ host->variant->fifosize));
+ thr = min_t(u32, thr, MMCI_STM32_THR_MASK);
+ }
+
+ writel_relaxed(thr, host->base + MMCI_STM32_FIFOTHRR);
+ }
+
if (host->mmc->card && mmc_card_sdio(host->mmc->card) &&
host->data->blocks == 1)
datactrl |= MCI_DPSM_STM32_MODE_SDIO;
@@ -382,7 +411,8 @@ static u32 sdmmc_get_dctrl_cfg(struct mmci_host *host)
return datactrl;
}
-static bool sdmmc_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
+static bool sdmmc_busy_complete(struct mmci_host *host, struct mmc_command *cmd,
+ u32 status, u32 err_msk)
{
void __iomem *base = host->base;
u32 busy_d0, busy_d0end, mask, sdmmc_status;
@@ -423,8 +453,15 @@ complete:
return true;
}
-static void sdmmc_dlyb_set_cfgr(struct sdmmc_dlyb *dlyb,
- int unit, int phase, bool sampler)
+static int sdmmc_dlyb_mp15_enable(struct sdmmc_dlyb *dlyb)
+{
+ writel_relaxed(DLYB_CR_DEN, dlyb->base + DLYB_CR);
+
+ return 0;
+}
+
+static int sdmmc_dlyb_mp15_set_cfg(struct sdmmc_dlyb *dlyb,
+ int unit, int phase, bool sampler)
{
u32 cfgr;
@@ -436,16 +473,18 @@ static void sdmmc_dlyb_set_cfgr(struct sdmmc_dlyb *dlyb,
if (!sampler)
writel_relaxed(DLYB_CR_DEN, dlyb->base + DLYB_CR);
+
+ return 0;
}
-static int sdmmc_dlyb_lng_tuning(struct mmci_host *host)
+static int sdmmc_dlyb_mp15_prepare(struct mmci_host *host)
{
struct sdmmc_dlyb *dlyb = host->variant_priv;
u32 cfgr;
int i, lng, ret;
for (i = 0; i <= DLYB_CFGR_UNIT_MAX; i++) {
- sdmmc_dlyb_set_cfgr(dlyb, i, DLYB_CFGR_SEL_MAX, true);
+ dlyb->ops->set_cfg(dlyb, i, DLYB_CFGR_SEL_MAX, true);
ret = readl_relaxed_poll_timeout(dlyb->base + DLYB_CFGR, cfgr,
(cfgr & DLYB_CFGR_LNGF),
@@ -471,14 +510,58 @@ static int sdmmc_dlyb_lng_tuning(struct mmci_host *host)
return 0;
}
+static int sdmmc_dlyb_mp25_enable(struct sdmmc_dlyb *dlyb)
+{
+ u32 cr, sr;
+
+ cr = readl_relaxed(dlyb->base + SYSCFG_DLYBSD_CR);
+ cr |= DLYBSD_CR_EN;
+
+ writel_relaxed(cr, dlyb->base + SYSCFG_DLYBSD_CR);
+
+ return readl_relaxed_poll_timeout(dlyb->base + SYSCFG_DLYBSD_SR,
+ sr, sr & DLYBSD_SR_LOCK, 1,
+ DLYBSD_TIMEOUT_1S_IN_US);
+}
+
+static int sdmmc_dlyb_mp25_set_cfg(struct sdmmc_dlyb *dlyb,
+ int unit __maybe_unused, int phase,
+ bool sampler __maybe_unused)
+{
+ u32 cr, sr;
+
+ cr = readl_relaxed(dlyb->base + SYSCFG_DLYBSD_CR);
+ cr &= ~DLYBSD_CR_RXTAPSEL_MASK;
+ cr |= FIELD_PREP(DLYBSD_CR_RXTAPSEL_MASK, phase);
+
+ writel_relaxed(cr, dlyb->base + SYSCFG_DLYBSD_CR);
+
+ return readl_relaxed_poll_timeout(dlyb->base + SYSCFG_DLYBSD_SR,
+ sr, sr & DLYBSD_SR_RXTAPSEL_ACK, 1,
+ DLYBSD_TIMEOUT_1S_IN_US);
+}
+
+static int sdmmc_dlyb_mp25_prepare(struct mmci_host *host)
+{
+ struct sdmmc_dlyb *dlyb = host->variant_priv;
+
+ dlyb->max = DLYBSD_TAPSEL_NB;
+
+ return 0;
+}
+
static int sdmmc_dlyb_phase_tuning(struct mmci_host *host, u32 opcode)
{
struct sdmmc_dlyb *dlyb = host->variant_priv;
int cur_len = 0, max_len = 0, end_of_len = 0;
- int phase;
+ int phase, ret;
for (phase = 0; phase <= dlyb->max; phase++) {
- sdmmc_dlyb_set_cfgr(dlyb, dlyb->unit, phase, false);
+ ret = dlyb->ops->set_cfg(dlyb, dlyb->unit, phase, false);
+ if (ret) {
+ dev_err(mmc_dev(host->mmc), "tuning config failed\n");
+ return ret;
+ }
if (mmc_send_tuning(host->mmc, opcode, NULL)) {
cur_len = 0;
@@ -496,10 +579,15 @@ static int sdmmc_dlyb_phase_tuning(struct mmci_host *host, u32 opcode)
return -EINVAL;
}
- writel_relaxed(0, dlyb->base + DLYB_CR);
+ if (dlyb->ops->set_input_ck)
+ dlyb->ops->set_input_ck(dlyb);
phase = end_of_len - max_len / 2;
- sdmmc_dlyb_set_cfgr(dlyb, dlyb->unit, phase, false);
+ ret = dlyb->ops->set_cfg(dlyb, dlyb->unit, phase, false);
+ if (ret) {
+ dev_err(mmc_dev(host->mmc), "tuning reconfig failed\n");
+ return ret;
+ }
dev_dbg(mmc_dev(host->mmc), "unit:%d max_dly:%d phase:%d\n",
dlyb->unit, dlyb->max, phase);
@@ -511,12 +599,33 @@ static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
{
struct mmci_host *host = mmc_priv(mmc);
struct sdmmc_dlyb *dlyb = host->variant_priv;
+ u32 clk;
+ int ret;
+
+ if ((host->mmc->ios.timing != MMC_TIMING_UHS_SDR104 &&
+ host->mmc->ios.timing != MMC_TIMING_MMC_HS200) ||
+ host->mmc->actual_clock <= 50000000)
+ return 0;
if (!dlyb || !dlyb->base)
return -EINVAL;
- if (sdmmc_dlyb_lng_tuning(host))
- return -EINVAL;
+ ret = dlyb->ops->dlyb_enable(dlyb);
+ if (ret)
+ return ret;
+
+ /*
+ * SDMMC_FBCK is selected when an external Delay Block is needed
+ * with SDR104 or HS200.
+ */
+ clk = host->clk_reg;
+ clk &= ~MCI_STM32_CLK_SEL_MSK;
+ clk |= MCI_STM32_CLK_SELFBCK;
+ mmci_write_clkreg(host, clk);
+
+ ret = dlyb->ops->tuning_prepare(host);
+ if (ret)
+ return ret;
return sdmmc_dlyb_phase_tuning(host, opcode);
}
@@ -574,6 +683,19 @@ static struct mmci_host_ops sdmmc_variant_ops = {
.post_sig_volt_switch = sdmmc_post_sig_volt_switch,
};
+static struct sdmmc_tuning_ops dlyb_tuning_mp15_ops = {
+ .dlyb_enable = sdmmc_dlyb_mp15_enable,
+ .set_input_ck = sdmmc_dlyb_mp15_input_ck,
+ .tuning_prepare = sdmmc_dlyb_mp15_prepare,
+ .set_cfg = sdmmc_dlyb_mp15_set_cfg,
+};
+
+static struct sdmmc_tuning_ops dlyb_tuning_mp25_ops = {
+ .dlyb_enable = sdmmc_dlyb_mp25_enable,
+ .tuning_prepare = sdmmc_dlyb_mp25_prepare,
+ .set_cfg = sdmmc_dlyb_mp25_set_cfg,
+};
+
void sdmmc_variant_init(struct mmci_host *host)
{
struct device_node *np = host->mmc->parent->of_node;
@@ -592,6 +714,11 @@ void sdmmc_variant_init(struct mmci_host *host)
return;
dlyb->base = base_dlyb;
+ if (of_device_is_compatible(np, "st,stm32mp25-sdmmc2"))
+ dlyb->ops = &dlyb_tuning_mp25_ops;
+ else
+ dlyb->ops = &dlyb_tuning_mp15_ops;
+
host->variant_priv = dlyb;
host->mmc_ops->execute_tuning = sdmmc_execute_tuning;
}
diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c
index 2d002c81dcf3..d0d6ffcf78d4 100644
--- a/drivers/mmc/host/moxart-mmc.c
+++ b/drivers/mmc/host/moxart-mmc.c
@@ -338,13 +338,7 @@ static void moxart_transfer_pio(struct moxart_host *host)
return;
}
for (len = 0; len < remain && len < host->fifo_width;) {
- /* SCR data must be read in big endian. */
- if (data->mrq->cmd->opcode == SD_APP_SEND_SCR)
- *sgp = ioread32be(host->base +
- REG_DATA_WINDOW);
- else
- *sgp = ioread32(host->base +
- REG_DATA_WINDOW);
+ *sgp = ioread32(host->base + REG_DATA_WINDOW);
sgp++;
len += 4;
}
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 9785ec91654f..02403ff99e0d 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -473,6 +473,7 @@ struct msdc_host {
struct msdc_tune_para def_tune_para; /* default tune setting */
struct msdc_tune_para saved_tune_para; /* tune result of CMD21/CMD19 */
struct cqhci_host *cq_host;
+ u32 cq_ssc1_time;
};
static const struct mtk_mmc_compatible mt2701_compat = {
@@ -2450,9 +2451,49 @@ static void msdc_hs400_enhanced_strobe(struct mmc_host *mmc,
}
}
+static void msdc_cqe_cit_cal(struct msdc_host *host, u64 timer_ns)
+{
+ struct mmc_host *mmc = mmc_from_priv(host);
+ struct cqhci_host *cq_host = mmc->cqe_private;
+ u8 itcfmul;
+ u64 hclk_freq, value;
+
+ /*
+ * On MediaTek SoCs the MSDC controller's CQE uses msdc_hclk as ITCFVAL
+ * so we multiply/divide the HCLK frequency by ITCFMUL to calculate the
+ * Send Status Command Idle Timer (CIT) value.
+ */
+ hclk_freq = (u64)clk_get_rate(host->h_clk);
+ itcfmul = CQHCI_ITCFMUL(cqhci_readl(cq_host, CQHCI_CAP));
+ switch (itcfmul) {
+ case 0x0:
+ do_div(hclk_freq, 1000);
+ break;
+ case 0x1:
+ do_div(hclk_freq, 100);
+ break;
+ case 0x2:
+ do_div(hclk_freq, 10);
+ break;
+ case 0x3:
+ break;
+ case 0x4:
+ hclk_freq = hclk_freq * 10;
+ break;
+ default:
+ host->cq_ssc1_time = 0x40;
+ return;
+ }
+
+ value = hclk_freq * timer_ns;
+ do_div(value, 1000000000);
+ host->cq_ssc1_time = value;
+}
+
static void msdc_cqe_enable(struct mmc_host *mmc)
{
struct msdc_host *host = mmc_priv(mmc);
+ struct cqhci_host *cq_host = mmc->cqe_private;
/* enable cmdq irq */
writel(MSDC_INT_CMDQ, host->base + MSDC_INTEN);
@@ -2462,6 +2503,9 @@ static void msdc_cqe_enable(struct mmc_host *mmc)
msdc_set_busy_timeout(host, 20 * 1000000000ULL, 0);
/* default read data timeout 1s */
msdc_set_timeout(host, 1000000000ULL, 0);
+
+ /* Set the send status command idle timer */
+ cqhci_writel(cq_host, host->cq_ssc1_time, CQHCI_SSC1);
}
static void msdc_cqe_disable(struct mmc_host *mmc, bool recovery)
@@ -2707,7 +2751,7 @@ static int msdc_drv_probe(struct platform_device *pdev)
/* Support for SDIO eint irq ? */
if ((mmc->pm_caps & MMC_PM_WAKE_SDIO_IRQ) && (mmc->pm_caps & MMC_PM_KEEP_POWER)) {
- host->eint_irq = platform_get_irq_byname(pdev, "sdio_wakeup");
+ host->eint_irq = platform_get_irq_byname_optional(pdev, "sdio_wakeup");
if (host->eint_irq > 0) {
host->pins_eint = pinctrl_lookup_state(host->pinctrl, "state_eint");
if (IS_ERR(host->pins_eint)) {
@@ -2803,6 +2847,8 @@ static int msdc_drv_probe(struct platform_device *pdev)
/* cqhci 16bit length */
/* 0 size, means 65536 so we don't have to -1 here */
mmc->max_seg_size = 64 * 1024;
+ /* Reduce CIT to 0x40 that corresponds to 2.35us */
+ msdc_cqe_cit_cal(host, 2350);
}
ret = devm_request_irq(&pdev->dev, host->irq, msdc_irq,
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/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 1877d583fe8c..1c935b5bafe1 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -13,12 +13,13 @@
#include <linux/pm_opp.h>
#include <linux/slab.h>
#include <linux/iopoll.h>
-#include <linux/firmware/qcom/qcom_scm.h>
#include <linux/regulator/consumer.h>
#include <linux/interconnect.h>
#include <linux/pinctrl/consumer.h>
#include <linux/reset.h>
+#include <soc/qcom/ice.h>
+
#include "sdhci-cqhci.h"
#include "sdhci-pltfm.h"
#include "cqhci.h"
@@ -258,12 +259,14 @@ struct sdhci_msm_variant_info {
struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC mapped address */
- void __iomem *ice_mem; /* MSM ICE mapped address (if available) */
int pwr_irq; /* power irq */
struct clk *bus_clk; /* SDHC bus voter clock */
struct clk *xo_clk; /* TCXO clk needed for FLL feature of cm_dll*/
- /* core, iface, cal, sleep, and ice clocks */
- struct clk_bulk_data bulk_clks[5];
+ /* core, iface, cal and sleep clocks */
+ struct clk_bulk_data bulk_clks[4];
+#ifdef CONFIG_MMC_CRYPTO
+ struct qcom_ice *ice;
+#endif
unsigned long clk_rate;
struct mmc_host *mmc;
bool use_14lpp_dll_reset;
@@ -1804,164 +1807,51 @@ out:
#ifdef CONFIG_MMC_CRYPTO
-#define AES_256_XTS_KEY_SIZE 64
-
-/* QCOM ICE registers */
-
-#define QCOM_ICE_REG_VERSION 0x0008
-
-#define QCOM_ICE_REG_FUSE_SETTING 0x0010
-#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_REG_BIST_STATUS 0x0070
-#define QCOM_ICE_BIST_STATUS_MASK 0xF0000000
-
-#define QCOM_ICE_REG_ADVANCED_CONTROL 0x1000
-
-#define sdhci_msm_ice_writel(host, val, reg) \
- writel((val), (host)->ice_mem + (reg))
-#define sdhci_msm_ice_readl(host, reg) \
- readl((host)->ice_mem + (reg))
-
-static bool sdhci_msm_ice_supported(struct sdhci_msm_host *msm_host)
-{
- struct device *dev = mmc_dev(msm_host->mmc);
- u32 regval = sdhci_msm_ice_readl(msm_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 = sdhci_msm_ice_readl(msm_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;
-}
-
-static inline struct clk *sdhci_msm_ice_get_clk(struct device *dev)
-{
- return devm_clk_get(dev, "ice");
-}
-
static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,
struct cqhci_host *cq_host)
{
struct mmc_host *mmc = msm_host->mmc;
struct device *dev = mmc_dev(mmc);
- struct resource *res;
+ struct qcom_ice *ice;
if (!(cqhci_readl(cq_host, CQHCI_CAP) & CQHCI_CAP_CS))
return 0;
- res = platform_get_resource_byname(msm_host->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;
+ ice = of_qcom_ice_get(dev);
+ if (ice == ERR_PTR(-EOPNOTSUPP)) {
+ dev_warn(dev, "Disabling inline encryption support\n");
+ ice = NULL;
}
- msm_host->ice_mem = devm_ioremap_resource(dev, res);
- if (IS_ERR(msm_host->ice_mem))
- return PTR_ERR(msm_host->ice_mem);
-
- if (!sdhci_msm_ice_supported(msm_host))
- goto disable;
+ if (IS_ERR_OR_NULL(ice))
+ return PTR_ERR_OR_ZERO(ice);
+ msm_host->ice = ice;
mmc->caps2 |= MMC_CAP2_CRYPTO;
- return 0;
-disable:
- dev_warn(dev, "Disabling inline encryption support\n");
return 0;
}
-static void sdhci_msm_ice_low_power_mode_enable(struct sdhci_msm_host *msm_host)
-{
- u32 regval;
-
- regval = sdhci_msm_ice_readl(msm_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;
- sdhci_msm_ice_writel(msm_host, regval, QCOM_ICE_REG_ADVANCED_CONTROL);
-}
-
-static void sdhci_msm_ice_optimization_enable(struct sdhci_msm_host *msm_host)
+static void sdhci_msm_ice_enable(struct sdhci_msm_host *msm_host)
{
- u32 regval;
-
- /* ICE Optimizations Enable Sequence */
- regval = sdhci_msm_ice_readl(msm_host, QCOM_ICE_REG_ADVANCED_CONTROL);
- regval |= 0xD807100;
- /* ICE HPG requires delay before writing */
- udelay(5);
- sdhci_msm_ice_writel(msm_host, regval, QCOM_ICE_REG_ADVANCED_CONTROL);
- udelay(5);
+ if (msm_host->mmc->caps2 & MMC_CAP2_CRYPTO)
+ qcom_ice_enable(msm_host->ice);
}
-/*
- * Wait until the ICE BIST (built-in self-test) has completed.
- *
- * This may be necessary before ICE can be used.
- *
- * Note that we don't really care whether the BIST passed or failed; we really
- * just want to make sure that it isn't still running. This is because (a) the
- * BIST is a FIPS compliance thing that never fails in practice, (b) ICE is
- * documented to reject crypto requests if the BIST fails, so we needn't do it
- * in software too, and (c) properly testing storage encryption requires testing
- * the full storage stack anyway, and not relying on hardware-level self-tests.
- */
-static int sdhci_msm_ice_wait_bist_status(struct sdhci_msm_host *msm_host)
+static __maybe_unused int sdhci_msm_ice_resume(struct sdhci_msm_host *msm_host)
{
- u32 regval;
- int err;
+ if (msm_host->mmc->caps2 & MMC_CAP2_CRYPTO)
+ return qcom_ice_resume(msm_host->ice);
- err = readl_poll_timeout(msm_host->ice_mem + QCOM_ICE_REG_BIST_STATUS,
- regval, !(regval & QCOM_ICE_BIST_STATUS_MASK),
- 50, 5000);
- if (err)
- dev_err(mmc_dev(msm_host->mmc),
- "Timed out waiting for ICE self-test to complete\n");
- return err;
+ return 0;
}
-static void sdhci_msm_ice_enable(struct sdhci_msm_host *msm_host)
+static __maybe_unused int sdhci_msm_ice_suspend(struct sdhci_msm_host *msm_host)
{
- if (!(msm_host->mmc->caps2 & MMC_CAP2_CRYPTO))
- return;
- sdhci_msm_ice_low_power_mode_enable(msm_host);
- sdhci_msm_ice_optimization_enable(msm_host);
- sdhci_msm_ice_wait_bist_status(msm_host);
-}
+ if (msm_host->mmc->caps2 & MMC_CAP2_CRYPTO)
+ return qcom_ice_suspend(msm_host->ice);
-static int __maybe_unused sdhci_msm_ice_resume(struct sdhci_msm_host *msm_host)
-{
- if (!(msm_host->mmc->caps2 & MMC_CAP2_CRYPTO))
- return 0;
- return sdhci_msm_ice_wait_bist_status(msm_host);
+ return 0;
}
/*
@@ -1972,48 +1862,28 @@ static int sdhci_msm_program_key(struct cqhci_host *cq_host,
const union cqhci_crypto_cfg_entry *cfg,
int slot)
{
- struct device *dev = mmc_dev(cq_host->mmc);
+ struct sdhci_host *host = mmc_priv(cq_host->mmc);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
union cqhci_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 & CQHCI_CRYPTO_CONFIGURATION_ENABLE))
- return qcom_scm_ice_invalidate_key(slot);
/* Only AES-256-XTS has been tested so far. */
cap = cq_host->crypto_cap_array[cfg->crypto_cap_idx];
if (cap.algorithm_id != CQHCI_CRYPTO_ALG_AES_XTS ||
- cap.key_size != CQHCI_CRYPTO_KEY_SIZE_256) {
- dev_err_ratelimited(dev,
- "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n",
- cap.algorithm_id, cap.key_size);
+ cap.key_size != CQHCI_CRYPTO_KEY_SIZE_256)
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;
+ if (cfg->config_enable & CQHCI_CRYPTO_CONFIGURATION_ENABLE)
+ return qcom_ice_program_key(msm_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(msm_host->ice, slot);
}
+
#else /* CONFIG_MMC_CRYPTO */
-static inline struct clk *sdhci_msm_ice_get_clk(struct device *dev)
-{
- return NULL;
-}
static inline int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,
struct cqhci_host *cq_host)
@@ -2025,11 +1895,17 @@ static inline void sdhci_msm_ice_enable(struct sdhci_msm_host *msm_host)
{
}
-static inline int __maybe_unused
+static inline __maybe_unused int
sdhci_msm_ice_resume(struct sdhci_msm_host *msm_host)
{
return 0;
}
+
+static inline __maybe_unused int
+sdhci_msm_ice_suspend(struct sdhci_msm_host *msm_host)
+{
+ return 0;
+}
#endif /* !CONFIG_MMC_CRYPTO */
/*****************************************************************************\
@@ -2633,11 +2509,6 @@ static int sdhci_msm_probe(struct platform_device *pdev)
clk = NULL;
msm_host->bulk_clks[3].clk = clk;
- clk = sdhci_msm_ice_get_clk(&pdev->dev);
- if (IS_ERR(clk))
- clk = NULL;
- msm_host->bulk_clks[4].clk = clk;
-
ret = clk_bulk_prepare_enable(ARRAY_SIZE(msm_host->bulk_clks),
msm_host->bulk_clks);
if (ret)
@@ -2830,7 +2701,7 @@ static __maybe_unused int sdhci_msm_runtime_suspend(struct device *dev)
clk_bulk_disable_unprepare(ARRAY_SIZE(msm_host->bulk_clks),
msm_host->bulk_clks);
- return 0;
+ return sdhci_msm_ice_suspend(msm_host);
}
static __maybe_unused int sdhci_msm_runtime_resume(struct device *dev)
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 01975d145200..1c2572c0f012 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -1903,6 +1903,7 @@ static const struct pci_device_id pci_ids[] = {
SDHCI_PCI_DEVICE(GLI, 9750, gl9750),
SDHCI_PCI_DEVICE(GLI, 9755, gl9755),
SDHCI_PCI_DEVICE(GLI, 9763E, gl9763e),
+ SDHCI_PCI_DEVICE(GLI, 9767, gl9767),
SDHCI_PCI_DEVICE_CLASS(AMD, SYSTEM_SDHCI, PCI_CLASS_MASK, amd),
/* Generic SD host controller */
{PCI_DEVICE_CLASS(SYSTEM_SDHCI, PCI_CLASS_MASK)},
diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c
index 633a8ee8f8c5..ae8c307b7aa7 100644
--- a/drivers/mmc/host/sdhci-pci-gli.c
+++ b/drivers/mmc/host/sdhci-pci-gli.c
@@ -149,6 +149,72 @@
#define PCI_GLI_9755_PM_CTRL 0xFC
#define PCI_GLI_9755_PM_STATE GENMASK(1, 0)
+#define SDHCI_GLI_9767_GM_BURST_SIZE 0x510
+#define SDHCI_GLI_9767_GM_BURST_SIZE_AXI_ALWAYS_SET BIT(8)
+
+#define PCIE_GLI_9767_VHS 0x884
+#define GLI_9767_VHS_REV GENMASK(19, 16)
+#define GLI_9767_VHS_REV_R 0x0
+#define GLI_9767_VHS_REV_M 0x1
+#define GLI_9767_VHS_REV_W 0x2
+
+#define PCIE_GLI_9767_COM_MAILBOX 0x888
+#define PCIE_GLI_9767_COM_MAILBOX_SSC_EN BIT(1)
+
+#define PCIE_GLI_9767_CFG 0x8A0
+#define PCIE_GLI_9767_CFG_LOW_PWR_OFF BIT(12)
+
+#define PCIE_GLI_9767_COMBO_MUX_CTL 0x8C8
+#define PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN BIT(6)
+#define PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN BIT(10)
+
+#define PCIE_GLI_9767_PWR_MACRO_CTL 0x8D0
+#define PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE GENMASK(3, 0)
+#define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE GENMASK(15, 12)
+#define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE_VALUE 0x7
+#define PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL GENMASK(29, 28)
+#define PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL_VALUE 0x3
+
+#define PCIE_GLI_9767_SCR 0x8E0
+#define PCIE_GLI_9767_SCR_AUTO_AXI_W_BURST BIT(6)
+#define PCIE_GLI_9767_SCR_AUTO_AXI_R_BURST BIT(7)
+#define PCIE_GLI_9767_SCR_AXI_REQ BIT(9)
+#define PCIE_GLI_9767_SCR_CARD_DET_PWR_SAVING_EN BIT(10)
+#define PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE0 BIT(16)
+#define PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE1 BIT(17)
+#define PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF BIT(21)
+#define PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN BIT(30)
+
+#define PCIE_GLI_9767_SDHC_CAP 0x91C
+#define PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT BIT(5)
+
+#define PCIE_GLI_9767_SD_PLL_CTL 0x938
+#define PCIE_GLI_9767_SD_PLL_CTL_PLL_LDIV GENMASK(9, 0)
+#define PCIE_GLI_9767_SD_PLL_CTL_PLL_PDIV GENMASK(15, 12)
+#define PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN BIT(16)
+#define PCIE_GLI_9767_SD_PLL_CTL_SSC_EN BIT(19)
+#define PCIE_GLI_9767_SD_PLL_CTL_SSC_STEP_SETTING GENMASK(28, 24)
+
+#define PCIE_GLI_9767_SD_PLL_CTL2 0x93C
+#define PCIE_GLI_9767_SD_PLL_CTL2_PLLSSC_PPM GENMASK(31, 16)
+
+#define PCIE_GLI_9767_SD_EXPRESS_CTL 0x940
+#define PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE BIT(0)
+#define PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE BIT(1)
+
+#define PCIE_GLI_9767_SD_DATA_MULTI_CTL 0x944
+#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME GENMASK(23, 16)
+#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE 0x64
+
+#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2 0x950
+#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE BIT(0)
+
+#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2 0x954
+#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN BIT(0)
+
+#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2 0x958
+#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN BIT(0)
+
#define GLI_MAX_TUNING_LOOP 40
/* Genesys Logic chipset */
@@ -693,6 +759,293 @@ static void gl9755_hw_setting(struct sdhci_pci_slot *slot)
gl9755_wt_off(pdev);
}
+static inline void gl9767_vhs_read(struct pci_dev *pdev)
+{
+ u32 vhs_enable;
+ u32 vhs_value;
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &vhs_value);
+ vhs_enable = FIELD_GET(GLI_9767_VHS_REV, vhs_value);
+
+ if (vhs_enable == GLI_9767_VHS_REV_R)
+ return;
+
+ vhs_value &= ~GLI_9767_VHS_REV;
+ vhs_value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_R);
+
+ pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, vhs_value);
+}
+
+static inline void gl9767_vhs_write(struct pci_dev *pdev)
+{
+ u32 vhs_enable;
+ u32 vhs_value;
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &vhs_value);
+ vhs_enable = FIELD_GET(GLI_9767_VHS_REV, vhs_value);
+
+ if (vhs_enable == GLI_9767_VHS_REV_W)
+ return;
+
+ vhs_value &= ~GLI_9767_VHS_REV;
+ vhs_value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_W);
+
+ pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, vhs_value);
+}
+
+static bool gl9767_ssc_enable(struct pci_dev *pdev)
+{
+ u32 value;
+ u8 enable;
+
+ gl9767_vhs_write(pdev);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_COM_MAILBOX, &value);
+ enable = FIELD_GET(PCIE_GLI_9767_COM_MAILBOX_SSC_EN, value);
+
+ gl9767_vhs_read(pdev);
+
+ return enable;
+}
+
+static void gl9767_set_ssc(struct pci_dev *pdev, u8 enable, u8 step, u16 ppm)
+{
+ u32 pll;
+ u32 ssc;
+
+ gl9767_vhs_write(pdev);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, &pll);
+ pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL2, &ssc);
+ pll &= ~(PCIE_GLI_9767_SD_PLL_CTL_SSC_STEP_SETTING |
+ PCIE_GLI_9767_SD_PLL_CTL_SSC_EN);
+ ssc &= ~PCIE_GLI_9767_SD_PLL_CTL2_PLLSSC_PPM;
+ pll |= FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_SSC_STEP_SETTING, step) |
+ FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_SSC_EN, enable);
+ ssc |= FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL2_PLLSSC_PPM, ppm);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL2, ssc);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, pll);
+
+ gl9767_vhs_read(pdev);
+}
+
+static void gl9767_set_pll(struct pci_dev *pdev, u8 dir, u16 ldiv, u8 pdiv)
+{
+ u32 pll;
+
+ gl9767_vhs_write(pdev);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, &pll);
+ pll &= ~(PCIE_GLI_9767_SD_PLL_CTL_PLL_LDIV |
+ PCIE_GLI_9767_SD_PLL_CTL_PLL_PDIV |
+ PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN);
+ pll |= FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_PLL_LDIV, ldiv) |
+ FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_PLL_PDIV, pdiv) |
+ FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN, dir);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, pll);
+
+ gl9767_vhs_read(pdev);
+
+ /* wait for pll stable */
+ usleep_range(1000, 1100);
+}
+
+static void gl9767_set_ssc_pll_205mhz(struct pci_dev *pdev)
+{
+ bool enable = gl9767_ssc_enable(pdev);
+
+ /* set pll to 205MHz and ssc */
+ gl9767_set_ssc(pdev, enable, 0x1F, 0xF5C3);
+ gl9767_set_pll(pdev, 0x1, 0x246, 0x0);
+}
+
+static void gl9767_disable_ssc_pll(struct pci_dev *pdev)
+{
+ u32 pll;
+
+ gl9767_vhs_write(pdev);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, &pll);
+ pll &= ~(PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN | PCIE_GLI_9767_SD_PLL_CTL_SSC_EN);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, pll);
+
+ gl9767_vhs_read(pdev);
+}
+
+static void sdhci_gl9767_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+ struct sdhci_pci_slot *slot = sdhci_priv(host);
+ struct mmc_ios *ios = &host->mmc->ios;
+ struct pci_dev *pdev;
+ u32 value;
+ u16 clk;
+
+ pdev = slot->chip->pdev;
+ host->mmc->actual_clock = 0;
+
+ gl9767_vhs_write(pdev);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
+ value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
+
+ gl9767_disable_ssc_pll(pdev);
+ sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+
+ if (clock == 0)
+ return;
+
+ clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
+ if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) {
+ host->mmc->actual_clock = 205000000;
+ gl9767_set_ssc_pll_205mhz(pdev);
+ }
+
+ sdhci_enable_clk(host, clk);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
+ value &= ~PCIE_GLI_9767_CFG_LOW_PWR_OFF;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
+
+ gl9767_vhs_read(pdev);
+}
+
+static void gli_set_9767(struct sdhci_host *host)
+{
+ u32 value;
+
+ value = sdhci_readl(host, SDHCI_GLI_9767_GM_BURST_SIZE);
+ value &= ~SDHCI_GLI_9767_GM_BURST_SIZE_AXI_ALWAYS_SET;
+ sdhci_writel(host, value, SDHCI_GLI_9767_GM_BURST_SIZE);
+}
+
+static void gl9767_hw_setting(struct sdhci_pci_slot *slot)
+{
+ struct pci_dev *pdev = slot->chip->pdev;
+ u32 value;
+
+ gl9767_vhs_write(pdev);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_PWR_MACRO_CTL, &value);
+ value &= ~(PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE |
+ PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE |
+ PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL);
+
+ value |= PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE |
+ FIELD_PREP(PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE,
+ PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE_VALUE) |
+ FIELD_PREP(PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL,
+ PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL_VALUE);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_PWR_MACRO_CTL, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_SCR, &value);
+ value &= ~(PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE0 |
+ PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE1 |
+ PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN);
+
+ value |= PCIE_GLI_9767_SCR_AUTO_AXI_W_BURST |
+ PCIE_GLI_9767_SCR_AUTO_AXI_R_BURST |
+ PCIE_GLI_9767_SCR_AXI_REQ |
+ PCIE_GLI_9767_SCR_CARD_DET_PWR_SAVING_EN |
+ PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_SCR, value);
+
+ gl9767_vhs_read(pdev);
+}
+
+static void sdhci_gl9767_reset(struct sdhci_host *host, u8 mask)
+{
+ sdhci_reset(host, mask);
+ gli_set_9767(host);
+}
+
+static int gl9767_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ struct sdhci_pci_slot *slot = sdhci_priv(host);
+ struct pci_dev *pdev;
+ u32 value;
+ int i;
+
+ pdev = slot->chip->pdev;
+
+ if (mmc->ops->get_ro(mmc)) {
+ mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V);
+ return 0;
+ }
+
+ gl9767_vhs_write(pdev);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, &value);
+ value &= ~(PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN | PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, &value);
+ value &= ~PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME;
+ value |= FIELD_PREP(PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME,
+ PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value);
+ value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, &value);
+ value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, &value);
+ value |= PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
+ value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
+
+ value = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ value &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_PLL_EN);
+ sdhci_writew(host, value, SDHCI_CLOCK_CONTROL);
+
+ value = sdhci_readb(host, SDHCI_POWER_CONTROL);
+ value |= (SDHCI_VDD2_POWER_180 | SDHCI_VDD2_POWER_ON);
+ sdhci_writeb(host, value, SDHCI_POWER_CONTROL);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value);
+ value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value);
+
+ for (i = 0; i < 2; i++) {
+ usleep_range(10000, 10100);
+ pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value);
+ if (value & PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE) {
+ pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2,
+ value);
+ break;
+ }
+ }
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_SDHC_CAP, &value);
+ if (value & PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT) {
+ pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value);
+ value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value);
+ } else {
+ mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V);
+
+ value = sdhci_readb(host, SDHCI_POWER_CONTROL);
+ value &= ~(SDHCI_VDD2_POWER_180 | SDHCI_VDD2_POWER_ON);
+ sdhci_writeb(host, value, SDHCI_POWER_CONTROL);
+
+ value = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ value |= (SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_PLL_EN);
+ sdhci_writew(host, value, SDHCI_CLOCK_CONTROL);
+ }
+
+ gl9767_vhs_read(pdev);
+
+ return 0;
+}
+
static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)
{
struct sdhci_host *host = slot->host;
@@ -717,6 +1070,21 @@ static int gli_probe_slot_gl9755(struct sdhci_pci_slot *slot)
return 0;
}
+static int gli_probe_slot_gl9767(struct sdhci_pci_slot *slot)
+{
+ struct sdhci_host *host = slot->host;
+
+ gli_set_9767(host);
+ gl9767_hw_setting(slot);
+ gli_pcie_enable_msi(slot);
+ slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
+ host->mmc->caps2 |= MMC_CAP2_SD_EXP;
+ host->mmc_host_ops.init_sd_express = gl9767_init_sd_express;
+ sdhci_enable_v4_mode(host);
+
+ return 0;
+}
+
static void sdhci_gli_voltage_switch(struct sdhci_host *host)
{
/*
@@ -740,6 +1108,25 @@ static void sdhci_gli_voltage_switch(struct sdhci_host *host)
usleep_range(100000, 110000);
}
+static void sdhci_gl9767_voltage_switch(struct sdhci_host *host)
+{
+ /*
+ * According to Section 3.6.1 signal voltage switch procedure in
+ * SD Host Controller Simplified Spec. 4.20, steps 6~8 are as
+ * follows:
+ * (6) Set 1.8V Signal Enable in the Host Control 2 register.
+ * (7) Wait 5ms. 1.8V voltage regulator shall be stable within this
+ * period.
+ * (8) If 1.8V Signal Enable is cleared by Host Controller, go to
+ * step (12).
+ *
+ * Wait 5ms after set 1.8V signal enable in Host Control 2 register
+ * to ensure 1.8V signal enable bit is set by GL9767.
+ *
+ */
+ usleep_range(5000, 5500);
+}
+
static void sdhci_gl9750_reset(struct sdhci_host *host, u8 mask)
{
sdhci_reset(host, mask);
@@ -1150,3 +1537,22 @@ const struct sdhci_pci_fixes sdhci_gl9763e = {
#endif
.add_host = gl9763e_add_host,
};
+
+static const struct sdhci_ops sdhci_gl9767_ops = {
+ .set_clock = sdhci_gl9767_set_clock,
+ .enable_dma = sdhci_pci_enable_dma,
+ .set_bus_width = sdhci_set_bus_width,
+ .reset = sdhci_gl9767_reset,
+ .set_uhs_signaling = sdhci_set_uhs_signaling,
+ .voltage_switch = sdhci_gl9767_voltage_switch,
+};
+
+const struct sdhci_pci_fixes sdhci_gl9767 = {
+ .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+ .quirks2 = SDHCI_QUIRK2_BROKEN_DDR50,
+ .probe_slot = gli_probe_slot_gl9767,
+ .ops = &sdhci_gl9767_ops,
+#ifdef CONFIG_PM_SLEEP
+ .resume = sdhci_pci_gli_resume,
+#endif
+};
diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h
index 3661a224fb04..9c8863956381 100644
--- a/drivers/mmc/host/sdhci-pci.h
+++ b/drivers/mmc/host/sdhci-pci.h
@@ -76,6 +76,7 @@
#define PCI_DEVICE_ID_GLI_9755 0x9755
#define PCI_DEVICE_ID_GLI_9750 0x9750
#define PCI_DEVICE_ID_GLI_9763E 0xe763
+#define PCI_DEVICE_ID_GLI_9767 0x9767
/*
* PCI device class and mask
@@ -195,5 +196,6 @@ extern const struct sdhci_pci_fixes sdhci_o2;
extern const struct sdhci_pci_fixes sdhci_gl9750;
extern const struct sdhci_pci_fixes sdhci_gl9755;
extern const struct sdhci_pci_fixes sdhci_gl9763e;
+extern const struct sdhci_pci_fixes sdhci_gl9767;
#endif /* __SDHCI_PCI_H */
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 3241916141d7..ff41aa56564e 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1167,6 +1167,8 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
}
}
+ sdhci_config_dma(host);
+
if (host->flags & SDHCI_REQ_USE_DMA) {
int sg_cnt = sdhci_pre_dma_transfer(host, data, COOKIE_MAPPED);
@@ -1186,8 +1188,6 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
}
}
- sdhci_config_dma(host);
-
if (!(host->flags & SDHCI_REQ_USE_DMA)) {
int flags;
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index f4f2085c274c..f219bdea8f28 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -99,6 +99,13 @@
#define SDHCI_POWER_180 0x0A
#define SDHCI_POWER_300 0x0C
#define SDHCI_POWER_330 0x0E
+/*
+ * VDD2 - UHS2 or PCIe/NVMe
+ * VDD2 power on/off and voltage select
+ */
+#define SDHCI_VDD2_POWER_ON 0x10
+#define SDHCI_VDD2_POWER_120 0x80
+#define SDHCI_VDD2_POWER_180 0xA0
#define SDHCI_BLOCK_GAP_CONTROL 0x2A
diff --git a/drivers/mmc/host/sdhci_f_sdh30.c b/drivers/mmc/host/sdhci_f_sdh30.c
index a202a69a4b08..3215063bcf86 100644
--- a/drivers/mmc/host/sdhci_f_sdh30.c
+++ b/drivers/mmc/host/sdhci_f_sdh30.c
@@ -29,9 +29,16 @@ struct f_sdhost_priv {
bool enable_cmd_dat_delay;
};
+static void *sdhci_f_sdhost_priv(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+ return sdhci_pltfm_priv(pltfm_host);
+}
+
static void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host)
{
- struct f_sdhost_priv *priv = sdhci_priv(host);
+ struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host);
u32 ctrl = 0;
usleep_range(2500, 3000);
@@ -64,7 +71,7 @@ static unsigned int sdhci_f_sdh30_get_min_clock(struct sdhci_host *host)
static void sdhci_f_sdh30_reset(struct sdhci_host *host, u8 mask)
{
- struct f_sdhost_priv *priv = sdhci_priv(host);
+ struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host);
u32 ctl;
if (sdhci_readw(host, SDHCI_CLOCK_CONTROL) == 0)
@@ -95,30 +102,32 @@ static const struct sdhci_ops sdhci_f_sdh30_ops = {
.set_uhs_signaling = sdhci_set_uhs_signaling,
};
+static const struct sdhci_pltfm_data sdhci_f_sdh30_pltfm_data = {
+ .ops = &sdhci_f_sdh30_ops,
+ .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
+ | SDHCI_QUIRK_INVERTED_WRITE_PROTECT,
+ .quirks2 = SDHCI_QUIRK2_SUPPORT_SINGLE
+ | SDHCI_QUIRK2_TUNING_WORK_AROUND,
+};
+
static int sdhci_f_sdh30_probe(struct platform_device *pdev)
{
struct sdhci_host *host;
struct device *dev = &pdev->dev;
- int irq, ctrl = 0, ret = 0;
+ int ctrl = 0, ret = 0;
struct f_sdhost_priv *priv;
+ struct sdhci_pltfm_host *pltfm_host;
u32 reg = 0;
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return irq;
-
- host = sdhci_alloc_host(dev, sizeof(struct f_sdhost_priv));
+ host = sdhci_pltfm_init(pdev, &sdhci_f_sdh30_pltfm_data,
+ sizeof(struct f_sdhost_priv));
if (IS_ERR(host))
return PTR_ERR(host);
- priv = sdhci_priv(host);
+ pltfm_host = sdhci_priv(host);
+ priv = sdhci_pltfm_priv(pltfm_host);
priv->dev = dev;
- host->quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
- SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
- host->quirks2 = SDHCI_QUIRK2_SUPPORT_SINGLE |
- SDHCI_QUIRK2_TUNING_WORK_AROUND;
-
priv->enable_cmd_dat_delay = device_property_read_bool(dev,
"fujitsu,cmd-dat-delay-select");
@@ -126,18 +135,6 @@ static int sdhci_f_sdh30_probe(struct platform_device *pdev)
if (ret)
goto err;
- platform_set_drvdata(pdev, host);
-
- host->hw_name = "f_sdh30";
- host->ops = &sdhci_f_sdh30_ops;
- host->irq = irq;
-
- host->ioaddr = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(host->ioaddr)) {
- ret = PTR_ERR(host->ioaddr);
- goto err;
- }
-
if (dev_of_node(dev)) {
sdhci_get_of_property(pdev);
@@ -204,24 +201,24 @@ err_rst:
err_clk:
clk_disable_unprepare(priv->clk_iface);
err:
- sdhci_free_host(host);
+ sdhci_pltfm_free(pdev);
+
return ret;
}
static int sdhci_f_sdh30_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
- struct f_sdhost_priv *priv = sdhci_priv(host);
+ struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host);
+ struct clk *clk_iface = priv->clk_iface;
+ struct reset_control *rst = priv->rst;
+ struct clk *clk = priv->clk;
- sdhci_remove_host(host, readl(host->ioaddr + SDHCI_INT_STATUS) ==
- 0xffffffff);
-
- reset_control_assert(priv->rst);
- clk_disable_unprepare(priv->clk);
- clk_disable_unprepare(priv->clk_iface);
+ sdhci_pltfm_unregister(pdev);
- sdhci_free_host(host);
- platform_set_drvdata(pdev, NULL);
+ reset_control_assert(rst);
+ clk_disable_unprepare(clk);
+ clk_disable_unprepare(clk_iface);
return 0;
}
diff --git a/drivers/mmc/host/sunplus-mmc.c b/drivers/mmc/host/sunplus-mmc.c
index db5e0dcdfa7f..2bdebeb1f8e4 100644
--- a/drivers/mmc/host/sunplus-mmc.c
+++ b/drivers/mmc/host/sunplus-mmc.c
@@ -863,11 +863,9 @@ static int spmmc_drv_probe(struct platform_device *pdev)
struct spmmc_host *host;
int ret = 0;
- mmc = mmc_alloc_host(sizeof(*host), &pdev->dev);
- if (!mmc) {
- ret = -ENOMEM;
- goto probe_free_host;
- }
+ mmc = devm_mmc_alloc_host(&pdev->dev, sizeof(struct spmmc_host));
+ if (!mmc)
+ return -ENOMEM;
host = mmc_priv(mmc);
host->mmc = mmc;
@@ -902,7 +900,7 @@ static int spmmc_drv_probe(struct platform_device *pdev)
ret = mmc_of_parse(mmc);
if (ret)
- goto probe_free_host;
+ goto clk_disable;
mmc->ops = &spmmc_ops;
mmc->f_min = SPMMC_MIN_CLK;
@@ -911,7 +909,7 @@ static int spmmc_drv_probe(struct platform_device *pdev)
ret = mmc_regulator_get_supply(mmc);
if (ret)
- goto probe_free_host;
+ goto clk_disable;
if (!mmc->ocr_avail)
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
@@ -927,14 +925,17 @@ static int spmmc_drv_probe(struct platform_device *pdev)
host->tuning_info.enable_tuning = 1;
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
- mmc_add_host(mmc);
+ ret = mmc_add_host(mmc);
+ if (ret)
+ goto pm_disable;
- return ret;
+ return 0;
-probe_free_host:
- if (mmc)
- mmc_free_host(mmc);
+pm_disable:
+ pm_runtime_disable(&pdev->dev);
+clk_disable:
+ clk_disable_unprepare(host->clk);
return ret;
}
@@ -948,7 +949,6 @@ static int spmmc_drv_remove(struct platform_device *dev)
pm_runtime_put_noidle(&dev->dev);
pm_runtime_disable(&dev->dev);
platform_set_drvdata(dev, NULL);
- mmc_free_host(host->mmc);
return 0;
}
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
index 521af9251f33..bf2a92fba0ed 100644
--- a/drivers/mmc/host/wbsd.c
+++ b/drivers/mmc/host/wbsd.c
@@ -1705,8 +1705,6 @@ static int wbsd_init(struct device *dev, int base, int irq, int dma,
wbsd_release_resources(host);
wbsd_free_mmc(dev);
-
- mmc_free_host(mmc);
return ret;
}
diff --git a/drivers/most/configfs.c b/drivers/most/configfs.c
index 27b0c923597f..36d8c917f65f 100644
--- a/drivers/most/configfs.c
+++ b/drivers/most/configfs.c
@@ -204,7 +204,7 @@ static ssize_t mdev_link_device_store(struct config_item *item,
{
struct mdev_link *mdev_link = to_mdev_link(item);
- strlcpy(mdev_link->device, page, sizeof(mdev_link->device));
+ strscpy(mdev_link->device, page, sizeof(mdev_link->device));
strim(mdev_link->device);
return count;
}
@@ -219,7 +219,7 @@ static ssize_t mdev_link_channel_store(struct config_item *item,
{
struct mdev_link *mdev_link = to_mdev_link(item);
- strlcpy(mdev_link->channel, page, sizeof(mdev_link->channel));
+ strscpy(mdev_link->channel, page, sizeof(mdev_link->channel));
strim(mdev_link->channel);
return count;
}
@@ -234,7 +234,7 @@ static ssize_t mdev_link_comp_store(struct config_item *item,
{
struct mdev_link *mdev_link = to_mdev_link(item);
- strlcpy(mdev_link->comp, page, sizeof(mdev_link->comp));
+ strscpy(mdev_link->comp, page, sizeof(mdev_link->comp));
strim(mdev_link->comp);
return count;
}
@@ -250,7 +250,7 @@ static ssize_t mdev_link_comp_params_store(struct config_item *item,
{
struct mdev_link *mdev_link = to_mdev_link(item);
- strlcpy(mdev_link->comp_params, page, sizeof(mdev_link->comp_params));
+ strscpy(mdev_link->comp_params, page, sizeof(mdev_link->comp_params));
strim(mdev_link->comp_params);
return count;
}
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 54f92d09d9cf..11b06fefaa0e 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -1,8 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Common Flash Interface support:
* Intel Extended Vendor Command Set (ID 0x0001)
*
- * (C) 2000 Red Hat. GPL'd
+ * (C) 2000 Red Hat.
*
*
* 10/10/2000 Nicolas Pitre <nico@fluxnic.net>
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 67453f59c69c..153fb8d0008e 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Common Flash Interface support:
* AMD & Fujitsu Standard Vendor Command Set (ID 0x0002)
@@ -16,8 +17,6 @@
* 25/09/2008 Christopher Moore: TopBottom fixup for many Macronix with CFI V1.0
*
* Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
- *
- * This code is GPL
*/
#include <linux/module.h>
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c
index d35df526e0a6..60c7f6f751c7 100644
--- a/drivers/mtd/chips/cfi_cmdset_0020.c
+++ b/drivers/mtd/chips/cfi_cmdset_0020.c
@@ -1,8 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Common Flash Interface support:
* ST Advanced Architecture Command Set (ID 0x0020)
*
- * (C) 2000 Red Hat. GPL'd
+ * (C) 2000 Red Hat.
*
* 10/10/2000 Nicolas Pitre <nico@fluxnic.net>
* - completely revamped method functions so they are aware and
diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c
index cf426956454c..a04b6174181c 100644
--- a/drivers/mtd/chips/cfi_probe.c
+++ b/drivers/mtd/chips/cfi_probe.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
Common Flash Interface probe code.
- (C) 2000 Red Hat. GPL'd.
+ (C) 2000 Red Hat.
*/
#include <linux/module.h>
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c
index 6a6a2a21d2ed..140c69a67e82 100644
--- a/drivers/mtd/chips/cfi_util.c
+++ b/drivers/mtd/chips/cfi_util.c
@@ -1,11 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Common Flash Interface support:
* Generic utility functions not dependent on command set
*
* Copyright (C) 2002 Red Hat
* Copyright (C) 2003 STMicroelectronics Limited
- *
- * This code is covered by the GPL.
*/
#include <linux/module.h>
diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c
index 4d4f97841016..9e53fcd7600d 100644
--- a/drivers/mtd/chips/gen_probe.c
+++ b/drivers/mtd/chips/gen_probe.c
@@ -1,7 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Routines common to all CFI-type probes.
* (C) 2001-2003 Red Hat, Inc.
- * GPL'd
*/
#include <linux/kernel.h>
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index 6f7e7e1b3fe5..23c32fe584b7 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
Common Flash Interface probe code.
- (C) 2000 Red Hat. GPL'd.
+ (C) 2000 Red Hat.
See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5)
for the standard this probe goes back to.
diff --git a/drivers/mtd/chips/map_ram.c b/drivers/mtd/chips/map_ram.c
index c37fce926864..e8dd6496927e 100644
--- a/drivers/mtd/chips/map_ram.c
+++ b/drivers/mtd/chips/map_ram.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Common code to handle map devices which are simple RAM
- * (C) 2000 Red Hat. GPL'd.
+ * (C) 2000 Red Hat.
*/
#include <linux/module.h>
diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c
index 20e3604b4d71..0823b15aaadb 100644
--- a/drivers/mtd/chips/map_rom.c
+++ b/drivers/mtd/chips/map_rom.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Common code to handle map devices which are simple ROM
- * (C) 2000 Red Hat. GPL'd.
+ * (C) 2000 Red Hat.
*/
#include <linux/module.h>
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 4cd37ec45762..be106dc20ff3 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -209,40 +209,34 @@ static void block2mtd_free_device(struct block2mtd_dev *dev)
if (dev->blkdev) {
invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
0, -1);
- blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+ blkdev_put(dev->blkdev, NULL);
}
kfree(dev);
}
-
-static struct block2mtd_dev *add_device(char *devname, int erase_size,
- char *label, int timeout)
+/*
+ * This function is marked __ref because it calls the __init marked
+ * early_lookup_bdev when called from the early boot code.
+ */
+static struct block_device __ref *mdtblock_early_get_bdev(const char *devname,
+ blk_mode_t mode, int timeout, struct block2mtd_dev *dev)
{
+ struct block_device *bdev = ERR_PTR(-ENODEV);
#ifndef MODULE
int i;
-#endif
- const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
- struct block_device *bdev;
- struct block2mtd_dev *dev;
- char *name;
- if (!devname)
- return NULL;
-
- dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
- if (!dev)
- return NULL;
-
- /* Get a handle on the device */
- bdev = blkdev_get_by_path(devname, mode, dev);
+ /*
+ * We can't use early_lookup_bdev from a running system.
+ */
+ if (system_state >= SYSTEM_RUNNING)
+ return bdev;
-#ifndef MODULE
/*
* We might not have the root device mounted at this point.
* Try to resolve the device name by other means.
*/
- for (i = 0; IS_ERR(bdev) && i <= timeout; i++) {
+ for (i = 0; i <= timeout; i++) {
dev_t devt;
if (i)
@@ -254,13 +248,35 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
msleep(1000);
wait_for_device_probe();
- devt = name_to_dev_t(devname);
- if (!devt)
- continue;
- bdev = blkdev_get_by_dev(devt, mode, dev);
+ if (!early_lookup_bdev(devname, &devt)) {
+ bdev = blkdev_get_by_dev(devt, mode, dev, NULL);
+ if (!IS_ERR(bdev))
+ break;
+ }
}
#endif
+ return bdev;
+}
+static struct block2mtd_dev *add_device(char *devname, int erase_size,
+ char *label, int timeout)
+{
+ const blk_mode_t mode = BLK_OPEN_READ | BLK_OPEN_WRITE;
+ struct block_device *bdev;
+ struct block2mtd_dev *dev;
+ char *name;
+
+ if (!devname)
+ return NULL;
+
+ dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ /* Get a handle on the device */
+ bdev = blkdev_get_by_path(devname, mode, dev, NULL);
+ if (IS_ERR(bdev))
+ bdev = mdtblock_early_get_bdev(devname, mode, timeout, dev);
if (IS_ERR(bdev)) {
pr_err("error: cannot open device %s\n", devname);
goto err_free_block2mtd;
diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c
index 54861d889c30..3dbb1aa80bfa 100644
--- a/drivers/mtd/devices/st_spi_fsm.c
+++ b/drivers/mtd/devices/st_spi_fsm.c
@@ -2046,34 +2046,26 @@ static int stfsm_probe(struct platform_device *pdev)
return PTR_ERR(fsm->base);
}
- fsm->clk = devm_clk_get(&pdev->dev, NULL);
+ fsm->clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(fsm->clk)) {
dev_err(fsm->dev, "Couldn't find EMI clock.\n");
return PTR_ERR(fsm->clk);
}
- ret = clk_prepare_enable(fsm->clk);
- if (ret) {
- dev_err(fsm->dev, "Failed to enable EMI clock.\n");
- return ret;
- }
-
mutex_init(&fsm->lock);
ret = stfsm_init(fsm);
if (ret) {
dev_err(&pdev->dev, "Failed to initialise FSM Controller\n");
- goto err_clk_unprepare;
+ return ret;
}
stfsm_fetch_platform_configs(pdev);
/* Detect SPI FLASH device */
info = stfsm_jedec_probe(fsm);
- if (!info) {
- ret = -ENODEV;
- goto err_clk_unprepare;
- }
+ if (!info)
+ return -ENODEV;
fsm->info = info;
/* Use device size to determine address width */
@@ -2089,7 +2081,7 @@ static int stfsm_probe(struct platform_device *pdev)
else
ret = stfsm_prepare_rwe_seqs_default(fsm);
if (ret)
- goto err_clk_unprepare;
+ return ret;
fsm->mtd.name = info->name;
fsm->mtd.dev.parent = &pdev->dev;
@@ -2112,13 +2104,7 @@ static int stfsm_probe(struct platform_device *pdev)
(long long)fsm->mtd.size, (long long)(fsm->mtd.size >> 20),
fsm->mtd.erasesize, (fsm->mtd.erasesize >> 10));
- ret = mtd_device_register(&fsm->mtd, NULL, 0);
- if (ret) {
-err_clk_unprepare:
- clk_disable_unprepare(fsm->clk);
- }
-
- return ret;
+ return mtd_device_register(&fsm->mtd, NULL, 0);
}
static int stfsm_remove(struct platform_device *pdev)
@@ -2127,8 +2113,6 @@ static int stfsm_remove(struct platform_device *pdev)
WARN_ON(mtd_device_unregister(&fsm->mtd));
- clk_disable_unprepare(fsm->clk);
-
return 0;
}
diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c
index 3e0fff3f129e..ecf68922da73 100644
--- a/drivers/mtd/maps/pismo.c
+++ b/drivers/mtd/maps/pismo.c
@@ -259,7 +259,7 @@ static struct i2c_driver pismo_driver = {
.driver = {
.name = "pismo",
},
- .probe_new = pismo_probe,
+ .probe = pismo_probe,
.remove = pismo_remove,
.id_table = pismo_id,
};
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 60b222799871..ff18636e0889 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -182,9 +182,9 @@ static blk_status_t mtd_queue_rq(struct blk_mq_hw_ctx *hctx,
return BLK_STS_OK;
}
-static int blktrans_open(struct block_device *bdev, fmode_t mode)
+static int blktrans_open(struct gendisk *disk, blk_mode_t mode)
{
- struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data;
+ struct mtd_blktrans_dev *dev = disk->private_data;
int ret = 0;
kref_get(&dev->ref);
@@ -208,7 +208,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
ret = __get_mtd_device(dev->mtd);
if (ret)
goto error_release;
- dev->file_mode = mode;
+ dev->writable = mode & BLK_OPEN_WRITE;
unlock:
dev->open++;
@@ -225,7 +225,7 @@ error_put:
return ret;
}
-static void blktrans_release(struct gendisk *disk, fmode_t mode)
+static void blktrans_release(struct gendisk *disk)
{
struct mtd_blktrans_dev *dev = disk->private_data;
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
index a0a1194dc1d9..fa476fb4dffb 100644
--- a/drivers/mtd/mtdblock.c
+++ b/drivers/mtd/mtdblock.c
@@ -294,7 +294,7 @@ static void mtdblock_release(struct mtd_blktrans_dev *mbd)
* It was the last usage. Free the cache, but only sync if
* opened for writing.
*/
- if (mbd->file_mode & FMODE_WRITE)
+ if (mbd->writable)
mtd_sync(mbd->mtd);
vfree(mtdblk->cache_data);
}
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 60670b2f70b9..e00b12aa5ec9 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -23,6 +23,7 @@
#include <linux/idr.h>
#include <linux/backing-dev.h>
#include <linux/gfp.h>
+#include <linux/random.h>
#include <linux/slab.h>
#include <linux/reboot.h>
#include <linux/leds.h>
@@ -966,6 +967,26 @@ static int mtd_otp_nvmem_add(struct mtd_info *mtd)
}
if (size > 0) {
+ /*
+ * The factory OTP contains thing such as a unique serial
+ * number and is small, so let's read it out and put it
+ * into the entropy pool.
+ */
+ void *otp;
+
+ otp = kmalloc(size, GFP_KERNEL);
+ if (!otp) {
+ err = -ENOMEM;
+ goto err;
+ }
+ err = mtd_nvmem_fact_otp_reg_read(mtd, 0, otp, size);
+ if (err < 0) {
+ kfree(otp);
+ goto err;
+ }
+ add_device_randomness(otp, err);
+ kfree(otp);
+
nvmem = mtd_otp_nvmem_register(mtd, "factory-otp", size,
mtd_nvmem_fact_otp_reg_read);
if (IS_ERR(nvmem)) {
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 85f5ee6f06fc..a46affbb037d 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -326,7 +326,6 @@ static int __mtd_del_partition(struct mtd_info *mtd)
static int __del_mtd_partitions(struct mtd_info *mtd)
{
struct mtd_info *child, *next;
- LIST_HEAD(tmp_list);
int ret, err = 0;
list_for_each_entry_safe(child, next, &mtd->partitions, part.node) {
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 917cdfb815b9..d93e861d8ba7 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -67,5 +67,6 @@ nand-objs += nand_esmt.o
nand-objs += nand_hynix.o
nand-objs += nand_macronix.o
nand-objs += nand_micron.o
+nand-objs += nand_sandisk.o
nand-objs += nand_samsung.o
nand-objs += nand_toshiba.o
diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c
index d513d2db3549..906eef70cb6d 100644
--- a/drivers/mtd/nand/raw/arasan-nand-controller.c
+++ b/drivers/mtd/nand/raw/arasan-nand-controller.c
@@ -973,21 +973,6 @@ static int anfc_setup_interface(struct nand_chip *chip, int target,
nvddr = nand_get_nvddr_timings(conf);
if (IS_ERR(nvddr))
return PTR_ERR(nvddr);
-
- /*
- * The controller only supports data payload requests which are
- * a multiple of 4. In practice, most data accesses are 4-byte
- * aligned and this is not an issue. However, rounding up will
- * simply be refused by the controller if we reached the end of
- * the device *and* we are using the NV-DDR interface(!). In
- * this situation, unaligned data requests ending at the device
- * boundary will confuse the controller and cannot be performed.
- *
- * This is something that happens in nand_read_subpage() when
- * selecting software ECC support and must be avoided.
- */
- if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT)
- return -ENOTSUPP;
} else {
sdr = nand_get_sdr_timings(conf);
if (IS_ERR(sdr))
diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c
index 086426139173..7366e85c09fd 100644
--- a/drivers/mtd/nand/raw/fsl_upm.c
+++ b/drivers/mtd/nand/raw/fsl_upm.c
@@ -135,7 +135,7 @@ static int fun_exec_op(struct nand_chip *chip, const struct nand_operation *op,
unsigned int i;
int ret;
- if (op->cs > NAND_MAX_CHIPS)
+ if (op->cs >= NAND_MAX_CHIPS)
return -EINVAL;
if (check_only)
diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
index 7016e0f38398..e9932da18bdd 100644
--- a/drivers/mtd/nand/raw/internals.h
+++ b/drivers/mtd/nand/raw/internals.h
@@ -73,6 +73,7 @@ extern const struct nand_manufacturer_ops hynix_nand_manuf_ops;
extern const struct nand_manufacturer_ops macronix_nand_manuf_ops;
extern const struct nand_manufacturer_ops micron_nand_manuf_ops;
extern const struct nand_manufacturer_ops samsung_nand_manuf_ops;
+extern const struct nand_manufacturer_ops sandisk_nand_manuf_ops;
extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops;
/* MLC pairing schemes */
diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
index 1feea7d82252..b10011dec1e6 100644
--- a/drivers/mtd/nand/raw/meson_nand.c
+++ b/drivers/mtd/nand/raw/meson_nand.c
@@ -38,6 +38,7 @@
#define NFC_CMD_SCRAMBLER_DISABLE 0
#define NFC_CMD_SHORTMODE_DISABLE 0
#define NFC_CMD_RB_INT BIT(14)
+#define NFC_CMD_RB_INT_NO_PIN ((0xb << 10) | BIT(18) | BIT(16))
#define NFC_CMD_GET_SIZE(x) (((x) >> 22) & GENMASK(4, 0))
@@ -76,6 +77,7 @@
#define GENCMDIADDRH(aih, addr) ((aih) | (((addr) >> 16) & 0xffff))
#define DMA_DIR(dir) ((dir) ? NFC_CMD_N2M : NFC_CMD_M2N)
+#define DMA_ADDR_ALIGN 8
#define ECC_CHECK_RETURN_FF (-1)
@@ -108,6 +110,11 @@
#define PER_INFO_BYTE 8
+#define NFC_CMD_RAW_LEN GENMASK(13, 0)
+
+#define NFC_COLUMN_ADDR_0 0
+#define NFC_COLUMN_ADDR_1 0
+
struct meson_nfc_nand_chip {
struct list_head node;
struct nand_chip nand;
@@ -179,6 +186,7 @@ struct meson_nfc {
u32 info_bytes;
unsigned long assigned_cs;
+ bool no_rb_pin;
};
enum {
@@ -280,7 +288,7 @@ static void meson_nfc_cmd_access(struct nand_chip *nand, int raw, bool dir,
if (raw) {
len = mtd->writesize + mtd->oobsize;
- cmd = (len & GENMASK(13, 0)) | scrambler | DMA_DIR(dir);
+ cmd = len | scrambler | DMA_DIR(dir);
writel(cmd, nfc->reg_base + NFC_REG_CMD);
return;
}
@@ -392,7 +400,42 @@ static void meson_nfc_set_data_oob(struct nand_chip *nand,
}
}
-static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
+static int meson_nfc_wait_no_rb_pin(struct meson_nfc *nfc, int timeout_ms,
+ bool need_cmd_read0)
+{
+ u32 cmd, cfg;
+
+ meson_nfc_cmd_idle(nfc, nfc->timing.twb);
+ meson_nfc_drain_cmd(nfc);
+ meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT);
+
+ cfg = readl(nfc->reg_base + NFC_REG_CFG);
+ cfg |= NFC_RB_IRQ_EN;
+ writel(cfg, nfc->reg_base + NFC_REG_CFG);
+
+ reinit_completion(&nfc->completion);
+ cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_STATUS;
+ writel(cmd, nfc->reg_base + NFC_REG_CMD);
+
+ /* use the max erase time as the maximum clock for waiting R/B */
+ cmd = NFC_CMD_RB | NFC_CMD_RB_INT_NO_PIN | nfc->timing.tbers_max;
+ writel(cmd, nfc->reg_base + NFC_REG_CMD);
+
+ if (!wait_for_completion_timeout(&nfc->completion,
+ msecs_to_jiffies(timeout_ms)))
+ return -ETIMEDOUT;
+
+ if (need_cmd_read0) {
+ cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_READ0;
+ writel(cmd, nfc->reg_base + NFC_REG_CMD);
+ meson_nfc_drain_cmd(nfc);
+ meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT);
+ }
+
+ return 0;
+}
+
+static int meson_nfc_wait_rb_pin(struct meson_nfc *nfc, int timeout_ms)
{
u32 cmd, cfg;
int ret = 0;
@@ -420,6 +463,27 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
return ret;
}
+static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms,
+ bool need_cmd_read0)
+{
+ if (nfc->no_rb_pin) {
+ /* This mode is used when there is no wired R/B pin.
+ * It works like 'nand_soft_waitrdy()', but instead of
+ * polling NAND_CMD_STATUS bit in the software loop,
+ * it will wait for interrupt - controllers checks IO
+ * bus and when it detects NAND_CMD_STATUS on it, it
+ * raises interrupt. After interrupt, NAND_CMD_READ0 is
+ * sent as terminator of the ready waiting procedure if
+ * needed (for all cases except page programming - this
+ * is reason of 'need_cmd_read0' flag).
+ */
+ return meson_nfc_wait_no_rb_pin(nfc, timeout_ms,
+ need_cmd_read0);
+ } else {
+ return meson_nfc_wait_rb_pin(nfc, timeout_ms);
+ }
+}
+
static void meson_nfc_set_user_byte(struct nand_chip *nand, u8 *oob_buf)
{
struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
@@ -544,7 +608,7 @@ static int meson_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len)
if (ret)
goto out;
- cmd = NFC_CMD_N2M | (len & GENMASK(13, 0));
+ cmd = NFC_CMD_N2M | len;
writel(cmd, nfc->reg_base + NFC_REG_CMD);
meson_nfc_drain_cmd(nfc);
@@ -568,7 +632,7 @@ static int meson_nfc_write_buf(struct nand_chip *nand, u8 *buf, int len)
if (ret)
return ret;
- cmd = NFC_CMD_M2N | (len & GENMASK(13, 0));
+ cmd = NFC_CMD_M2N | len;
writel(cmd, nfc->reg_base + NFC_REG_CMD);
meson_nfc_drain_cmd(nfc);
@@ -595,12 +659,12 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand,
cmd0 = in ? NAND_CMD_READ0 : NAND_CMD_SEQIN;
nfc->cmdfifo.rw.cmd0 = cs | NFC_CMD_CLE | cmd0;
- addrs[0] = cs | NFC_CMD_ALE | 0;
+ addrs[0] = cs | NFC_CMD_ALE | NFC_COLUMN_ADDR_0;
if (mtd->writesize <= 512) {
cmd_num--;
row_start = 1;
} else {
- addrs[1] = cs | NFC_CMD_ALE | 0;
+ addrs[1] = cs | NFC_CMD_ALE | NFC_COLUMN_ADDR_1;
row_start = 2;
}
@@ -623,7 +687,7 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand,
if (in) {
nfc->cmdfifo.rw.cmd1 = cs | NFC_CMD_CLE | NAND_CMD_READSTART;
writel(nfc->cmdfifo.rw.cmd1, nfc->reg_base + NFC_REG_CMD);
- meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tR_max));
+ meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tR_max), true);
} else {
meson_nfc_cmd_idle(nfc, nfc->timing.tadl);
}
@@ -669,7 +733,7 @@ static int meson_nfc_write_page_sub(struct nand_chip *nand,
cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_PAGEPROG;
writel(cmd, nfc->reg_base + NFC_REG_CMD);
- meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tPROG_max));
+ meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tPROG_max), false);
meson_nfc_dma_buffer_release(nand, data_len, info_len, DMA_TO_DEVICE);
@@ -842,6 +906,9 @@ static int meson_nfc_read_oob(struct nand_chip *nand, int page)
static bool meson_nfc_is_buffer_dma_safe(const void *buffer)
{
+ if ((uintptr_t)buffer % DMA_ADDR_ALIGN)
+ return false;
+
if (virt_addr_valid(buffer) && (!object_is_on_stack(buffer)))
return true;
return false;
@@ -899,6 +966,31 @@ meson_nand_op_put_dma_safe_output_buf(const struct nand_op_instr *instr,
kfree(buf);
}
+static int meson_nfc_check_op(struct nand_chip *chip,
+ const struct nand_operation *op)
+{
+ int op_id;
+
+ for (op_id = 0; op_id < op->ninstrs; op_id++) {
+ const struct nand_op_instr *instr;
+
+ instr = &op->instrs[op_id];
+
+ switch (instr->type) {
+ case NAND_OP_DATA_IN_INSTR:
+ case NAND_OP_DATA_OUT_INSTR:
+ if (instr->ctx.data.len > NFC_CMD_RAW_LEN)
+ return -ENOTSUPP;
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
static int meson_nfc_exec_op(struct nand_chip *nand,
const struct nand_operation *op, bool check_only)
{
@@ -907,8 +999,13 @@ static int meson_nfc_exec_op(struct nand_chip *nand,
const struct nand_op_instr *instr = NULL;
void *buf;
u32 op_id, delay_idle, cmd;
+ int err;
int i;
+ err = meson_nfc_check_op(nand, op);
+ if (err)
+ return err;
+
if (check_only)
return 0;
@@ -952,7 +1049,8 @@ static int meson_nfc_exec_op(struct nand_chip *nand,
break;
case NAND_OP_WAITRDY_INSTR:
- meson_nfc_queue_rb(nfc, instr->ctx.waitrdy.timeout_ms);
+ meson_nfc_queue_rb(nfc, instr->ctx.waitrdy.timeout_ms,
+ true);
if (instr->delay_ns)
meson_nfc_cmd_idle(nfc, delay_idle);
break;
@@ -1180,7 +1278,7 @@ static int meson_nand_attach_chip(struct nand_chip *nand)
struct meson_nfc *nfc = nand_get_controller_data(nand);
struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
struct mtd_info *mtd = nand_to_mtd(nand);
- int nsectors = mtd->writesize / 1024;
+ int raw_writesize;
int ret;
if (!mtd->name) {
@@ -1192,13 +1290,20 @@ static int meson_nand_attach_chip(struct nand_chip *nand)
return -ENOMEM;
}
+ raw_writesize = mtd->writesize + mtd->oobsize;
+ if (raw_writesize > NFC_CMD_RAW_LEN) {
+ dev_err(nfc->dev, "too big write size in raw mode: %d > %ld\n",
+ raw_writesize, NFC_CMD_RAW_LEN);
+ return -EINVAL;
+ }
+
if (nand->bbt_options & NAND_BBT_USE_FLASH)
nand->bbt_options |= NAND_BBT_NO_OOB;
nand->options |= NAND_NO_SUBPAGE_WRITE;
ret = nand_ecc_choose_conf(nand, nfc->data->ecc_caps,
- mtd->oobsize - 2 * nsectors);
+ mtd->oobsize - 2);
if (ret) {
dev_err(nfc->dev, "failed to ECC init\n");
return -EINVAL;
@@ -1248,6 +1353,7 @@ meson_nfc_nand_chip_init(struct device *dev,
struct mtd_info *mtd;
int ret, i;
u32 tmp, nsels;
+ u32 nand_rb_val = 0;
nsels = of_property_count_elems_of_size(np, "reg", sizeof(u32));
if (!nsels || nsels > MAX_CE_NUM) {
@@ -1287,6 +1393,15 @@ meson_nfc_nand_chip_init(struct device *dev,
mtd->owner = THIS_MODULE;
mtd->dev.parent = dev;
+ ret = of_property_read_u32(np, "nand-rb", &nand_rb_val);
+ if (ret == -EINVAL)
+ nfc->no_rb_pin = true;
+ else if (ret)
+ return ret;
+
+ if (nand_rb_val)
+ return -EINVAL;
+
ret = nand_scan(nand, nsels);
if (ret)
return ret;
diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
index dacc5529b3df..650351c62af6 100644
--- a/drivers/mtd/nand/raw/nand_ids.c
+++ b/drivers/mtd/nand/raw/nand_ids.c
@@ -44,6 +44,9 @@ struct nand_flash_dev nand_flash_ids[] = {
{"TC58NVG6D2 64G 3.3V 8-bit",
{ .id = {0x98, 0xde, 0x94, 0x82, 0x76, 0x56, 0x04, 0x20} },
SZ_8K, SZ_8K, SZ_2M, 0, 8, 640, NAND_ECC_INFO(40, SZ_1K) },
+ {"SDTNQGAMA 64G 3.3V 8-bit",
+ { .id = {0x45, 0xde, 0x94, 0x93, 0x76, 0x57} },
+ SZ_16K, SZ_8K, SZ_4M, 0, 6, 1280, NAND_ECC_INFO(40, SZ_1K) },
{"SDTNRGAMA 64G 3.3V 8-bit",
{ .id = {0x45, 0xde, 0x94, 0x93, 0x76, 0x50} },
SZ_16K, SZ_8K, SZ_4M, 0, 6, 1280, NAND_ECC_INFO(40, SZ_1K) },
@@ -188,7 +191,7 @@ static const struct nand_manufacturer_desc nand_manufacturer_descs[] = {
{NAND_MFR_NATIONAL, "National"},
{NAND_MFR_RENESAS, "Renesas"},
{NAND_MFR_SAMSUNG, "Samsung", &samsung_nand_manuf_ops},
- {NAND_MFR_SANDISK, "SanDisk"},
+ {NAND_MFR_SANDISK, "SanDisk", &sandisk_nand_manuf_ops},
{NAND_MFR_STMICRO, "ST Micro"},
{NAND_MFR_TOSHIBA, "Toshiba", &toshiba_nand_manuf_ops},
{NAND_MFR_WINBOND, "Winbond"},
diff --git a/drivers/mtd/nand/raw/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c
index 385957eb6762..e229de32ff50 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -6,6 +6,7 @@
* Author: Boris Brezillon <boris.brezillon@free-electrons.com>
*/
+#include <linux/slab.h>
#include "linux/delay.h"
#include "internals.h"
@@ -31,6 +32,16 @@
#define MXIC_CMD_POWER_DOWN 0xB9
+#define ONFI_FEATURE_ADDR_30LFXG18AC_OTP 0x90
+#define MACRONIX_30LFXG18AC_OTP_START_PAGE 2
+#define MACRONIX_30LFXG18AC_OTP_PAGES 30
+#define MACRONIX_30LFXG18AC_OTP_PAGE_SIZE 2112
+#define MACRONIX_30LFXG18AC_OTP_SIZE_BYTES \
+ (MACRONIX_30LFXG18AC_OTP_PAGES * \
+ MACRONIX_30LFXG18AC_OTP_PAGE_SIZE)
+
+#define MACRONIX_30LFXG18AC_OTP_EN BIT(0)
+
struct nand_onfi_vendor_macronix {
u8 reserved;
u8 reliability_func;
@@ -315,6 +326,161 @@ static void macronix_nand_deep_power_down_support(struct nand_chip *chip)
chip->ops.resume = mxic_nand_resume;
}
+static int macronix_30lfxg18ac_get_otp_info(struct mtd_info *mtd, size_t len,
+ size_t *retlen,
+ struct otp_info *buf)
+{
+ if (len < sizeof(*buf))
+ return -EINVAL;
+
+ /* Always report that OTP is unlocked. Reason is that this
+ * type of flash chip doesn't provide way to check that OTP
+ * is locked or not: subfeature parameter is implemented as
+ * volatile register. Technically OTP region could be locked
+ * and become readonly, but as there is no way to check it,
+ * don't allow to lock it ('_lock_user_prot_reg' callback
+ * always returns -EOPNOTSUPP) and thus we report that OTP
+ * is unlocked.
+ */
+ buf->locked = 0;
+ buf->start = 0;
+ buf->length = MACRONIX_30LFXG18AC_OTP_SIZE_BYTES;
+
+ *retlen = sizeof(*buf);
+
+ return 0;
+}
+
+static int macronix_30lfxg18ac_otp_enable(struct nand_chip *nand)
+{
+ u8 feature_buf[ONFI_SUBFEATURE_PARAM_LEN] = { 0 };
+
+ feature_buf[0] = MACRONIX_30LFXG18AC_OTP_EN;
+ return nand_set_features(nand, ONFI_FEATURE_ADDR_30LFXG18AC_OTP,
+ feature_buf);
+}
+
+static int macronix_30lfxg18ac_otp_disable(struct nand_chip *nand)
+{
+ u8 feature_buf[ONFI_SUBFEATURE_PARAM_LEN] = { 0 };
+
+ return nand_set_features(nand, ONFI_FEATURE_ADDR_30LFXG18AC_OTP,
+ feature_buf);
+}
+
+static int __macronix_30lfxg18ac_rw_otp(struct mtd_info *mtd,
+ loff_t offs_in_flash,
+ size_t len, size_t *retlen,
+ u_char *buf, bool write)
+{
+ struct nand_chip *nand;
+ size_t bytes_handled;
+ off_t offs_in_page;
+ u64 page;
+ int ret;
+
+ nand = mtd_to_nand(mtd);
+ nand_select_target(nand, 0);
+
+ ret = macronix_30lfxg18ac_otp_enable(nand);
+ if (ret)
+ goto out_otp;
+
+ page = offs_in_flash;
+ /* 'page' will be result of division. */
+ offs_in_page = do_div(page, MACRONIX_30LFXG18AC_OTP_PAGE_SIZE);
+ bytes_handled = 0;
+
+ while (bytes_handled < len &&
+ page < MACRONIX_30LFXG18AC_OTP_PAGES) {
+ size_t bytes_to_handle;
+ u64 phys_page = page + MACRONIX_30LFXG18AC_OTP_START_PAGE;
+
+ bytes_to_handle = min_t(size_t, len - bytes_handled,
+ MACRONIX_30LFXG18AC_OTP_PAGE_SIZE -
+ offs_in_page);
+
+ if (write)
+ ret = nand_prog_page_op(nand, phys_page, offs_in_page,
+ &buf[bytes_handled], bytes_to_handle);
+ else
+ ret = nand_read_page_op(nand, phys_page, offs_in_page,
+ &buf[bytes_handled], bytes_to_handle);
+ if (ret)
+ goto out_otp;
+
+ bytes_handled += bytes_to_handle;
+ offs_in_page = 0;
+ page++;
+ }
+
+ *retlen = bytes_handled;
+
+out_otp:
+ if (ret)
+ dev_err(&mtd->dev, "failed to perform OTP IO: %i\n", ret);
+
+ ret = macronix_30lfxg18ac_otp_disable(nand);
+ if (ret)
+ dev_err(&mtd->dev, "failed to leave OTP mode after %s\n",
+ write ? "write" : "read");
+
+ nand_deselect_target(nand);
+
+ return ret;
+}
+
+static int macronix_30lfxg18ac_write_otp(struct mtd_info *mtd, loff_t to,
+ size_t len, size_t *rlen,
+ const u_char *buf)
+{
+ return __macronix_30lfxg18ac_rw_otp(mtd, to, len, rlen, (u_char *)buf,
+ true);
+}
+
+static int macronix_30lfxg18ac_read_otp(struct mtd_info *mtd, loff_t from,
+ size_t len, size_t *rlen,
+ u_char *buf)
+{
+ return __macronix_30lfxg18ac_rw_otp(mtd, from, len, rlen, buf, false);
+}
+
+static int macronix_30lfxg18ac_lock_otp(struct mtd_info *mtd, loff_t from,
+ size_t len)
+{
+ /* See comment in 'macronix_30lfxg18ac_get_otp_info()'. */
+ return -EOPNOTSUPP;
+}
+
+static void macronix_nand_setup_otp(struct nand_chip *chip)
+{
+ static const char * const supported_otp_models[] = {
+ "MX30LF1G18AC",
+ "MX30LF2G18AC",
+ "MX30LF4G18AC",
+ };
+ struct mtd_info *mtd;
+
+ if (match_string(supported_otp_models,
+ ARRAY_SIZE(supported_otp_models),
+ chip->parameters.model) < 0)
+ return;
+
+ if (!chip->parameters.supports_set_get_features)
+ return;
+
+ bitmap_set(chip->parameters.get_feature_list,
+ ONFI_FEATURE_ADDR_30LFXG18AC_OTP, 1);
+ bitmap_set(chip->parameters.set_feature_list,
+ ONFI_FEATURE_ADDR_30LFXG18AC_OTP, 1);
+
+ mtd = nand_to_mtd(chip);
+ mtd->_get_user_prot_info = macronix_30lfxg18ac_get_otp_info;
+ mtd->_read_user_prot_reg = macronix_30lfxg18ac_read_otp;
+ mtd->_write_user_prot_reg = macronix_30lfxg18ac_write_otp;
+ mtd->_lock_user_prot_reg = macronix_30lfxg18ac_lock_otp;
+}
+
static int macronix_nand_init(struct nand_chip *chip)
{
if (nand_is_slc(chip))
@@ -324,6 +490,7 @@ static int macronix_nand_init(struct nand_chip *chip)
macronix_nand_onfi_init(chip);
macronix_nand_block_protection_support(chip);
macronix_nand_deep_power_down_support(chip);
+ macronix_nand_setup_otp(chip);
return 0;
}
diff --git a/drivers/mtd/nand/raw/nand_sandisk.c b/drivers/mtd/nand/raw/nand_sandisk.c
new file mode 100644
index 000000000000..7c66e4187dc7
--- /dev/null
+++ b/drivers/mtd/nand/raw/nand_sandisk.c
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "internals.h"
+
+static int
+sdtnqgama_choose_interface_config(struct nand_chip *chip,
+ struct nand_interface_config *iface)
+{
+ onfi_fill_interface_config(chip, iface, NAND_SDR_IFACE, 0);
+
+ return nand_choose_best_sdr_timings(chip, iface, NULL);
+}
+
+static int sandisk_nand_init(struct nand_chip *chip)
+{
+ if (!strncmp("SDTNQGAMA", chip->parameters.model,
+ sizeof("SDTNQGAMA") - 1))
+ chip->ops.choose_interface_config =
+ &sdtnqgama_choose_interface_config;
+
+ return 0;
+}
+
+const struct nand_manufacturer_ops sandisk_nand_manuf_ops = {
+ .init = sandisk_nand_init,
+};
diff --git a/drivers/mtd/nand/raw/omap_elm.c b/drivers/mtd/nand/raw/omap_elm.c
index 6e1eac6644a6..4a97d4a76454 100644
--- a/drivers/mtd/nand/raw/omap_elm.c
+++ b/drivers/mtd/nand/raw/omap_elm.c
@@ -177,17 +177,17 @@ static void elm_load_syndrome(struct elm_info *info,
switch (info->bch_type) {
case BCH8_ECC:
/* syndrome fragment 0 = ecc[9-12B] */
- val = cpu_to_be32(*(u32 *) &ecc[9]);
+ val = (__force u32)cpu_to_be32(*(u32 *)&ecc[9]);
elm_write_reg(info, offset, val);
/* syndrome fragment 1 = ecc[5-8B] */
offset += 4;
- val = cpu_to_be32(*(u32 *) &ecc[5]);
+ val = (__force u32)cpu_to_be32(*(u32 *)&ecc[5]);
elm_write_reg(info, offset, val);
/* syndrome fragment 2 = ecc[1-4B] */
offset += 4;
- val = cpu_to_be32(*(u32 *) &ecc[1]);
+ val = (__force u32)cpu_to_be32(*(u32 *)&ecc[1]);
elm_write_reg(info, offset, val);
/* syndrome fragment 3 = ecc[0B] */
@@ -197,35 +197,35 @@ static void elm_load_syndrome(struct elm_info *info,
break;
case BCH4_ECC:
/* syndrome fragment 0 = ecc[20-52b] bits */
- val = (cpu_to_be32(*(u32 *) &ecc[3]) >> 4) |
+ val = ((__force u32)cpu_to_be32(*(u32 *)&ecc[3]) >> 4) |
((ecc[2] & 0xf) << 28);
elm_write_reg(info, offset, val);
/* syndrome fragment 1 = ecc[0-20b] bits */
offset += 4;
- val = cpu_to_be32(*(u32 *) &ecc[0]) >> 12;
+ val = (__force u32)cpu_to_be32(*(u32 *)&ecc[0]) >> 12;
elm_write_reg(info, offset, val);
break;
case BCH16_ECC:
- val = cpu_to_be32(*(u32 *) &ecc[22]);
+ val = (__force u32)cpu_to_be32(*(u32 *)&ecc[22]);
elm_write_reg(info, offset, val);
offset += 4;
- val = cpu_to_be32(*(u32 *) &ecc[18]);
+ val = (__force u32)cpu_to_be32(*(u32 *)&ecc[18]);
elm_write_reg(info, offset, val);
offset += 4;
- val = cpu_to_be32(*(u32 *) &ecc[14]);
+ val = (__force u32)cpu_to_be32(*(u32 *)&ecc[14]);
elm_write_reg(info, offset, val);
offset += 4;
- val = cpu_to_be32(*(u32 *) &ecc[10]);
+ val = (__force u32)cpu_to_be32(*(u32 *)&ecc[10]);
elm_write_reg(info, offset, val);
offset += 4;
- val = cpu_to_be32(*(u32 *) &ecc[6]);
+ val = (__force u32)cpu_to_be32(*(u32 *)&ecc[6]);
elm_write_reg(info, offset, val);
offset += 4;
- val = cpu_to_be32(*(u32 *) &ecc[2]);
+ val = (__force u32)cpu_to_be32(*(u32 *)&ecc[2]);
elm_write_reg(info, offset, val);
offset += 4;
- val = cpu_to_be32(*(u32 *) &ecc[0]) >> 16;
+ val = (__force u32)cpu_to_be32(*(u32 *)&ecc[0]) >> 16;
elm_write_reg(info, offset, val);
break;
default:
diff --git a/drivers/mtd/nand/raw/rockchip-nand-controller.c b/drivers/mtd/nand/raw/rockchip-nand-controller.c
index 2312e27362cb..5a04680342c3 100644
--- a/drivers/mtd/nand/raw/rockchip-nand-controller.c
+++ b/drivers/mtd/nand/raw/rockchip-nand-controller.c
@@ -562,9 +562,10 @@ static int rk_nfc_write_page_raw(struct nand_chip *chip, const u8 *buf,
* BBM OOB1 OOB2 OOB3 |......| PA0 PA1 PA2 PA3
*
* The rk_nfc_ooblayout_free() function already has reserved
- * these 4 bytes with:
+ * these 4 bytes together with 2 bytes for BBM
+ * by reducing it's length:
*
- * oob_region->offset = NFC_SYS_DATA_SIZE + 2;
+ * oob_region->length = rknand->metadata_size - NFC_SYS_DATA_SIZE - 2;
*/
if (!i)
memcpy(rk_nfc_oob_ptr(chip, i),
@@ -597,7 +598,7 @@ static int rk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf,
int pages_per_blk = mtd->erasesize / mtd->writesize;
int ret = 0, i, boot_rom_mode = 0;
dma_addr_t dma_data, dma_oob;
- u32 reg;
+ u32 tmp;
u8 *oob;
nand_prog_page_begin_op(chip, page, 0, NULL, 0);
@@ -624,6 +625,13 @@ static int rk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf,
*
* 0xFF 0xFF 0xFF 0xFF | BBM OOB1 OOB2 OOB3 | ...
*
+ * The code here just swaps the first 4 bytes with the last
+ * 4 bytes without losing any data.
+ *
+ * The chip->oob_poi data layout:
+ *
+ * BBM OOB1 OOB2 OOB3 |......| PA0 PA1 PA2 PA3
+ *
* Configure the ECC algorithm supported by the boot ROM.
*/
if ((page < (pages_per_blk * rknand->boot_blks)) &&
@@ -634,21 +642,17 @@ static int rk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf,
}
for (i = 0; i < ecc->steps; i++) {
- if (!i) {
- reg = 0xFFFFFFFF;
- } else {
+ if (!i)
+ oob = chip->oob_poi + (ecc->steps - 1) * NFC_SYS_DATA_SIZE;
+ else
oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE;
- reg = oob[0] | oob[1] << 8 | oob[2] << 16 |
- oob[3] << 24;
- }
- if (!i && boot_rom_mode)
- reg = (page & (pages_per_blk - 1)) * 4;
+ tmp = oob[0] | oob[1] << 8 | oob[2] << 16 | oob[3] << 24;
if (nfc->cfg->type == NFC_V9)
- nfc->oob_buf[i] = reg;
+ nfc->oob_buf[i] = tmp;
else
- nfc->oob_buf[i * (oob_step / 4)] = reg;
+ nfc->oob_buf[i * (oob_step / 4)] = tmp;
}
dma_data = dma_map_single(nfc->dev, (void *)nfc->page_buf,
@@ -811,12 +815,17 @@ static int rk_nfc_read_page_hwecc(struct nand_chip *chip, u8 *buf, int oob_on,
goto timeout_err;
}
- for (i = 1; i < ecc->steps; i++) {
- oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE;
+ for (i = 0; i < ecc->steps; i++) {
+ if (!i)
+ oob = chip->oob_poi + (ecc->steps - 1) * NFC_SYS_DATA_SIZE;
+ else
+ oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE;
+
if (nfc->cfg->type == NFC_V9)
tmp = nfc->oob_buf[i];
else
tmp = nfc->oob_buf[i * (oob_step / 4)];
+
*oob++ = (u8)tmp;
*oob++ = (u8)(tmp >> 8);
*oob++ = (u8)(tmp >> 16);
@@ -933,12 +942,8 @@ static int rk_nfc_ooblayout_free(struct mtd_info *mtd, int section,
if (section)
return -ERANGE;
- /*
- * The beginning of the OOB area stores the reserved data for the NFC,
- * the size of the reserved data is NFC_SYS_DATA_SIZE bytes.
- */
oob_region->length = rknand->metadata_size - NFC_SYS_DATA_SIZE - 2;
- oob_region->offset = NFC_SYS_DATA_SIZE + 2;
+ oob_region->offset = 2;
return 0;
}
diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c
index 6b043e24855f..cfd7c3b26dc4 100644
--- a/drivers/mtd/nand/spi/gigadevice.c
+++ b/drivers/mtd/nand/spi/gigadevice.c
@@ -501,6 +501,16 @@ static const struct spinand_info gigadevice_spinand_table[] = {
SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
gd5fxgq4uexxg_ecc_get_status)),
+ SPINAND_INFO("GD5F2GQ5xExxH",
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x22),
+ NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
+ NAND_ECCREQ(4, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
+ &write_cache_variants,
+ &update_cache_variants),
+ SPINAND_HAS_QE_BIT,
+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
+ gd5fxgq4uexxg_ecc_get_status)),
};
static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = {
diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
index 722a9738ba37..3dfc7e1e5241 100644
--- a/drivers/mtd/nand/spi/macronix.c
+++ b/drivers/mtd/nand/spi/macronix.c
@@ -299,6 +299,26 @@ static const struct spinand_info macronix_spinand_table[] = {
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
mx35lf1ge4ab_ecc_get_status)),
+ SPINAND_INFO("MX31LF2GE4BC",
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x2e),
+ NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ SPINAND_HAS_QE_BIT,
+ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+ mx35lf1ge4ab_ecc_get_status)),
+ SPINAND_INFO("MX3UF2GE4BC",
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae),
+ NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ SPINAND_HAS_QE_BIT,
+ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+ mx35lf1ge4ab_ecc_get_status)),
};
static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = {
diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c
index 7380b1ebaccd..a80427c13121 100644
--- a/drivers/mtd/nand/spi/toshiba.c
+++ b/drivers/mtd/nand/spi/toshiba.c
@@ -73,7 +73,7 @@ static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand,
{
struct nand_device *nand = spinand_to_nand(spinand);
u8 mbf = 0;
- struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf);
+ struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, spinand->scratchbuf);
switch (status & STATUS_ECC_MASK) {
case STATUS_ECC_NO_BITFLIPS:
@@ -92,7 +92,7 @@ static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand,
if (spi_mem_exec_op(spinand->spimem, &op))
return nanddev_get_ecc_conf(nand)->strength;
- mbf >>= 4;
+ mbf = *(spinand->scratchbuf) >> 4;
if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf))
return nanddev_get_ecc_conf(nand)->strength;
diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
index 3ad58cd284d8..f507e3759301 100644
--- a/drivers/mtd/nand/spi/winbond.c
+++ b/drivers/mtd/nand/spi/winbond.c
@@ -108,7 +108,7 @@ static int w25n02kv_ecc_get_status(struct spinand_device *spinand,
{
struct nand_device *nand = spinand_to_nand(spinand);
u8 mbf = 0;
- struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf);
+ struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, spinand->scratchbuf);
switch (status & STATUS_ECC_MASK) {
case STATUS_ECC_NO_BITFLIPS:
@@ -126,7 +126,7 @@ static int w25n02kv_ecc_get_status(struct spinand_device *spinand,
if (spi_mem_exec_op(spinand->spimem, &op))
return nanddev_get_ecc_conf(nand)->strength;
- mbf >>= 4;
+ mbf = *(spinand->scratchbuf) >> 4;
if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf))
return nanddev_get_ecc_conf(nand)->strength;
diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c
index 4cfec3b7b446..b5b3c4c44a94 100644
--- a/drivers/mtd/sm_ftl.c
+++ b/drivers/mtd/sm_ftl.c
@@ -981,7 +981,7 @@ restart:
/* Update the FTL table */
zone->lba_to_phys_table[ftl->cache_block] = write_sector;
- /* Write succesfull, so erase and free the old block */
+ /* Write successful, so erase and free the old block */
if (block_num > 0)
sm_erase_block(ftl, zone_num, block_num, 1);
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 36876aa849ed..15f9a80c10b9 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -361,7 +361,7 @@ static int cypress_nor_determine_addr_mode_by_sr1(struct spi_nor *nor,
*/
static int cypress_nor_set_addr_mode_nbytes(struct spi_nor *nor)
{
- struct spi_mem_op op = {};
+ struct spi_mem_op op;
u8 addr_mode;
int ret;
@@ -492,7 +492,7 @@ s25fs256t_post_bfpt_fixup(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
const struct sfdp_bfpt *bfpt)
{
- struct spi_mem_op op = {};
+ struct spi_mem_op op;
int ret;
ret = cypress_nor_set_addr_mode_nbytes(nor);
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
index 3711d7f74600..437c5b83ffe5 100644
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -227,9 +227,9 @@ static blk_status_t ubiblock_read(struct request *req)
return BLK_STS_OK;
}
-static int ubiblock_open(struct block_device *bdev, fmode_t mode)
+static int ubiblock_open(struct gendisk *disk, blk_mode_t mode)
{
- struct ubiblock *dev = bdev->bd_disk->private_data;
+ struct ubiblock *dev = disk->private_data;
int ret;
mutex_lock(&dev->dev_mutex);
@@ -246,11 +246,10 @@ static int ubiblock_open(struct block_device *bdev, fmode_t mode)
* It's just a paranoid check, as write requests will get rejected
* in any case.
*/
- if (mode & FMODE_WRITE) {
+ if (mode & BLK_OPEN_WRITE) {
ret = -EROFS;
goto out_unlock;
}
-
dev->desc = ubi_open_volume(dev->ubi_num, dev->vol_id, UBI_READONLY);
if (IS_ERR(dev->desc)) {
dev_err(disk_to_dev(dev->gd), "failed to open ubi volume %d_%d",
@@ -270,7 +269,7 @@ out_unlock:
return ret;
}
-static void ubiblock_release(struct gendisk *gd, fmode_t mode)
+static void ubiblock_release(struct gendisk *gd)
{
struct ubiblock *dev = gd->private_data;
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/Kconfig b/drivers/net/Kconfig
index d0a1ed216d15..368c6f5b327e 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -403,7 +403,6 @@ config TUN_VNET_CROSS_LE
config VETH
tristate "Virtual ethernet pair device"
select PAGE_POOL
- select PAGE_POOL_STATS
help
This device is a local ethernet tunnel. Devices are created in pairs.
When one end receives the packet it appears on its pair and vice
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/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index b9dbad3a8af8..fc5da5d7744d 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -660,10 +660,10 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
return NULL;
arp = (struct arp_pkt *)skb_network_header(skb);
- /* Don't modify or load balance ARPs that do not originate locally
- * (e.g.,arrive via a bridge).
+ /* Don't modify or load balance ARPs that do not originate
+ * from the bond itself or a VLAN directly above the bond.
*/
- if (!bond_slave_has_mac_rx(bond, arp->mac_src))
+ if (!bond_slave_has_mac_rcu(bond, arp->mac_src))
return NULL;
dev = ip_dev_find(dev_net(bond->dev), arp->ip_src);
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index edbaa1444f8e..447b06ea4fc9 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1,8 +1,9 @@
+// SPDX-License-Identifier: GPL-1.0+
/*
* originally based on the dummy device.
*
* Copyright 1999, Thomas Davis, tadavis@lbl.gov.
- * Licensed under the GPL. Based on dummy.c, and eql.c devices.
+ * Based on dummy.c, and eql.c devices.
*
* bonding.c: an Ethernet Bonding driver
*
@@ -1507,6 +1508,11 @@ static void bond_setup_by_slave(struct net_device *bond_dev,
memcpy(bond_dev->broadcast, slave_dev->broadcast,
slave_dev->addr_len);
+
+ if (slave_dev->flags & IFF_POINTOPOINT) {
+ bond_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
+ bond_dev->flags |= (IFF_POINTOPOINT | IFF_NOARP);
+ }
}
/* On bonding slaves other than the currently active slave, suppress
@@ -2871,6 +2877,8 @@ static bool bond_has_this_ip(struct bonding *bond, __be32 ip)
return ret;
}
+#define BOND_VLAN_PROTO_NONE cpu_to_be16(0xffff)
+
static bool bond_handle_vlan(struct slave *slave, struct bond_vlan_tag *tags,
struct sk_buff *skb)
{
@@ -2878,13 +2886,13 @@ static bool bond_handle_vlan(struct slave *slave, struct bond_vlan_tag *tags,
struct net_device *slave_dev = slave->dev;
struct bond_vlan_tag *outer_tag = tags;
- if (!tags || tags->vlan_proto == VLAN_N_VID)
+ if (!tags || tags->vlan_proto == BOND_VLAN_PROTO_NONE)
return true;
tags++;
/* Go through all the tags backwards and add them to the packet */
- while (tags->vlan_proto != VLAN_N_VID) {
+ while (tags->vlan_proto != BOND_VLAN_PROTO_NONE) {
if (!tags->vlan_id) {
tags++;
continue;
@@ -2960,7 +2968,7 @@ struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev,
tags = kcalloc(level + 1, sizeof(*tags), GFP_ATOMIC);
if (!tags)
return ERR_PTR(-ENOMEM);
- tags[level].vlan_proto = VLAN_N_VID;
+ tags[level].vlan_proto = BOND_VLAN_PROTO_NONE;
return tags;
}
@@ -4197,7 +4205,7 @@ u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb)
return skb->hash;
return __bond_xmit_hash(bond, skb, skb->data, skb->protocol,
- skb_mac_offset(skb), skb_network_offset(skb),
+ 0, skb_network_offset(skb),
skb_headlen(skb));
}
@@ -5439,7 +5447,7 @@ static netdev_tx_t bond_tls_device_xmit(struct bonding *bond, struct sk_buff *sk
{
struct net_device *tls_netdev = rcu_dereference(tls_get_ctx(skb->sk)->netdev);
- /* tls_netdev might become NULL, even if tls_is_sk_tx_device_offloaded
+ /* tls_netdev might become NULL, even if tls_is_skb_tx_device_offloaded
* was true, if tls_device_down is running in parallel, but it's OK,
* because bond_get_slave_by_dev has a NULL check.
*/
@@ -5458,7 +5466,7 @@ static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev
return NETDEV_TX_OK;
#if IS_ENABLED(CONFIG_TLS_DEVICE)
- if (skb->sk && tls_is_sk_tx_device_offloaded(skb->sk))
+ if (tls_is_skb_tx_device_offloaded(skb))
return bond_tls_device_xmit(bond, skb, dev);
#endif
@@ -5893,7 +5901,9 @@ void bond_setup(struct net_device *bond_dev)
bond_dev->hw_features = BOND_VLAN_FEATURES |
NETIF_F_HW_VLAN_CTAG_RX |
- NETIF_F_HW_VLAN_CTAG_FILTER;
+ NETIF_F_HW_VLAN_CTAG_FILTER |
+ NETIF_F_HW_VLAN_STAG_RX |
+ NETIF_F_HW_VLAN_STAG_FILTER;
bond_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
bond_dev->features |= bond_dev->hw_features;
diff --git a/drivers/net/bonding/bonding_priv.h b/drivers/net/bonding/bonding_priv.h
index 48cdf3a49a7d..fef6288c6944 100644
--- a/drivers/net/bonding/bonding_priv.h
+++ b/drivers/net/bonding/bonding_priv.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-1.0+ */
/*
* Bond several ethernet interfaces into a Cisco, running 'Etherchannel'.
*
@@ -7,9 +8,6 @@
* BUT, I'm the one who modified it for ethernet, so:
* (c) Copyright 1999, Thomas Davis, tadavis@lbl.gov
*
- * This software may be used and distributed according to the terms
- * of the GNU Public License, incorporated herein by reference.
- *
*/
#ifndef _BONDING_PRIV_H
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index b190007c01be..a5c5036dfb94 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -153,8 +153,7 @@ config CAN_JANZ_ICAN3
config CAN_KVASER_PCIEFD
depends on PCI
tristate "Kvaser PCIe FD cards"
- select CRC32
- help
+ help
This is a driver for the Kvaser PCI Express CAN FD family.
Supported devices:
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 199cb200f2bd..4621266851ed 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -1346,7 +1346,7 @@ static int at91_can_probe(struct platform_device *pdev)
return err;
}
-static int at91_can_remove(struct platform_device *pdev)
+static void at91_can_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct at91_priv *priv = netdev_priv(dev);
@@ -1362,8 +1362,6 @@ static int at91_can_remove(struct platform_device *pdev)
clk_put(priv->clk);
free_candev(dev);
-
- return 0;
}
static const struct platform_device_id at91_can_id_table[] = {
@@ -1381,7 +1379,7 @@ MODULE_DEVICE_TABLE(platform, at91_can_id_table);
static struct platform_driver at91_can_driver = {
.probe = at91_can_probe,
- .remove = at91_can_remove,
+ .remove_new = at91_can_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = of_match_ptr(at91_can_dt_ids),
diff --git a/drivers/net/can/bxcan.c b/drivers/net/can/bxcan.c
index 027a8a162fe4..39de7164bc4e 100644
--- a/drivers/net/can/bxcan.c
+++ b/drivers/net/can/bxcan.c
@@ -966,22 +966,16 @@ static int bxcan_probe(struct platform_device *pdev)
}
rx_irq = platform_get_irq_byname(pdev, "rx0");
- if (rx_irq < 0) {
- dev_err(dev, "failed to get rx0 irq\n");
+ if (rx_irq < 0)
return rx_irq;
- }
tx_irq = platform_get_irq_byname(pdev, "tx");
- if (tx_irq < 0) {
- dev_err(dev, "failed to get tx irq\n");
+ if (tx_irq < 0)
return tx_irq;
- }
sce_irq = platform_get_irq_byname(pdev, "sce");
- if (sce_irq < 0) {
- dev_err(dev, "failed to get sce irq\n");
+ if (sce_irq < 0)
return sce_irq;
- }
ndev = alloc_candev(sizeof(struct bxcan_priv), BXCAN_TX_MB_NUM);
if (!ndev) {
@@ -1039,7 +1033,7 @@ out_free_candev:
return err;
}
-static int bxcan_remove(struct platform_device *pdev)
+static void bxcan_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct bxcan_priv *priv = netdev_priv(ndev);
@@ -1048,7 +1042,6 @@ static int bxcan_remove(struct platform_device *pdev)
clk_disable_unprepare(priv->clk);
can_rx_offload_del(&priv->offload);
free_candev(ndev);
- return 0;
}
static int __maybe_unused bxcan_suspend(struct device *dev)
@@ -1100,7 +1093,7 @@ static struct platform_driver bxcan_driver = {
.of_match_table = bxcan_of_match,
},
.probe = bxcan_probe,
- .remove = bxcan_remove,
+ .remove_new = bxcan_remove,
};
module_platform_driver(bxcan_driver);
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index 03ccb7cfacaf..925930b6c4ca 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -410,7 +410,7 @@ exit:
return ret;
}
-static int c_can_plat_remove(struct platform_device *pdev)
+static void c_can_plat_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct c_can_priv *priv = netdev_priv(dev);
@@ -418,8 +418,6 @@ static int c_can_plat_remove(struct platform_device *pdev)
unregister_c_can_dev(dev);
pm_runtime_disable(priv->device);
free_c_can_dev(dev);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -487,7 +485,7 @@ static struct platform_driver c_can_plat_driver = {
.of_match_table = c_can_of_table,
},
.probe = c_can_plat_probe,
- .remove = c_can_plat_remove,
+ .remove_new = c_can_plat_remove,
.suspend = c_can_suspend,
.resume = c_can_resume,
.id_table = c_can_id_table,
diff --git a/drivers/net/can/cc770/cc770_isa.c b/drivers/net/can/cc770/cc770_isa.c
index 8f6dccd5a587..22009440a983 100644
--- a/drivers/net/can/cc770/cc770_isa.c
+++ b/drivers/net/can/cc770/cc770_isa.c
@@ -285,7 +285,7 @@ exit:
return err;
}
-static int cc770_isa_remove(struct platform_device *pdev)
+static void cc770_isa_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct cc770_priv *priv = netdev_priv(dev);
@@ -303,13 +303,11 @@ static int cc770_isa_remove(struct platform_device *pdev)
release_region(port[idx], CC770_IOSIZE);
}
free_cc770dev(dev);
-
- return 0;
}
static struct platform_driver cc770_isa_driver = {
.probe = cc770_isa_probe,
- .remove = cc770_isa_remove,
+ .remove_new = cc770_isa_remove,
.driver = {
.name = KBUILD_MODNAME,
},
diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c
index 8dcc32e4e30e..13bcfba05f18 100644
--- a/drivers/net/can/cc770/cc770_platform.c
+++ b/drivers/net/can/cc770/cc770_platform.c
@@ -230,7 +230,7 @@ exit_release_mem:
return err;
}
-static int cc770_platform_remove(struct platform_device *pdev)
+static void cc770_platform_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct cc770_priv *priv = netdev_priv(dev);
@@ -242,8 +242,6 @@ static int cc770_platform_remove(struct platform_device *pdev)
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(mem->start, resource_size(mem));
-
- return 0;
}
static const struct of_device_id cc770_platform_table[] = {
@@ -259,7 +257,7 @@ static struct platform_driver cc770_platform_driver = {
.of_match_table = cc770_platform_table,
},
.probe = cc770_platform_probe,
- .remove = cc770_platform_remove,
+ .remove_new = cc770_platform_remove,
};
module_platform_driver(cc770_platform_driver);
diff --git a/drivers/net/can/ctucanfd/ctucanfd_platform.c b/drivers/net/can/ctucanfd/ctucanfd_platform.c
index a17561d97192..55bb10b157b4 100644
--- a/drivers/net/can/ctucanfd/ctucanfd_platform.c
+++ b/drivers/net/can/ctucanfd/ctucanfd_platform.c
@@ -86,7 +86,7 @@ err:
* This function frees all the resources allocated to the device.
* Return: 0 always
*/
-static int ctucan_platform_remove(struct platform_device *pdev)
+static void ctucan_platform_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct ctucan_priv *priv = netdev_priv(ndev);
@@ -97,8 +97,6 @@ static int ctucan_platform_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
netif_napi_del(&priv->napi);
free_candev(ndev);
-
- return 0;
}
static SIMPLE_DEV_PM_OPS(ctucan_platform_pm_ops, ctucan_suspend, ctucan_resume);
@@ -113,7 +111,7 @@ MODULE_DEVICE_TABLE(of, ctucan_of_match);
static struct platform_driver ctucanfd_driver = {
.probe = ctucan_platform_probe,
- .remove = ctucan_platform_remove,
+ .remove_new = ctucan_platform_remove,
.driver = {
.name = DRV_NAME,
.pm = &ctucan_platform_pm_ops,
diff --git a/drivers/net/can/dev/length.c b/drivers/net/can/dev/length.c
index b48140b1102e..b7f4d76dd444 100644
--- a/drivers/net/can/dev/length.c
+++ b/drivers/net/can/dev/length.c
@@ -78,18 +78,7 @@ unsigned int can_skb_get_frame_len(const struct sk_buff *skb)
else
len = cf->len;
- if (can_is_canfd_skb(skb)) {
- if (cf->can_id & CAN_EFF_FLAG)
- len += CANFD_FRAME_OVERHEAD_EFF;
- else
- len += CANFD_FRAME_OVERHEAD_SFF;
- } else {
- if (cf->can_id & CAN_EFF_FLAG)
- len += CAN_FRAME_OVERHEAD_EFF;
- else
- len += CAN_FRAME_OVERHEAD_SFF;
- }
-
- return len;
+ return can_frame_bytes(can_is_canfd_skb(skb), cf->can_id & CAN_EFF_FLAG,
+ false, len);
}
EXPORT_SYMBOL_GPL(can_skb_get_frame_len);
diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c
index 81ebf0562c89..161e45a7e8c1 100644
--- a/drivers/net/can/dev/rx-offload.c
+++ b/drivers/net/can/dev/rx-offload.c
@@ -220,7 +220,7 @@ int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload)
EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_fifo);
int can_rx_offload_queue_timestamp(struct can_rx_offload *offload,
- struct sk_buff *skb, u32 timestamp)
+ struct sk_buff *skb, u32 timestamp)
{
struct can_rx_offload_cb *cb;
diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
index 6d638c93977b..ff0fc18baf13 100644
--- a/drivers/net/can/flexcan/flexcan-core.c
+++ b/drivers/net/can/flexcan/flexcan-core.c
@@ -2218,7 +2218,7 @@ static int flexcan_probe(struct platform_device *pdev)
return err;
}
-static int flexcan_remove(struct platform_device *pdev)
+static void flexcan_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
@@ -2227,8 +2227,6 @@ static int flexcan_remove(struct platform_device *pdev)
unregister_flexcandev(dev);
pm_runtime_disable(&pdev->dev);
free_candev(dev);
-
- return 0;
}
static int __maybe_unused flexcan_suspend(struct device *device)
@@ -2379,7 +2377,7 @@ static struct platform_driver flexcan_driver = {
.of_match_table = flexcan_of_match,
},
.probe = flexcan_probe,
- .remove = flexcan_remove,
+ .remove_new = flexcan_remove,
.id_table = flexcan_id_table,
};
diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
index 4bedcc3eea0d..3174efdae271 100644
--- a/drivers/net/can/grcan.c
+++ b/drivers/net/can/grcan.c
@@ -1696,7 +1696,7 @@ exit_error:
return err;
}
-static int grcan_remove(struct platform_device *ofdev)
+static void grcan_remove(struct platform_device *ofdev)
{
struct net_device *dev = platform_get_drvdata(ofdev);
struct grcan_priv *priv = netdev_priv(dev);
@@ -1706,8 +1706,6 @@ static int grcan_remove(struct platform_device *ofdev)
irq_dispose_mapping(dev->irq);
netif_napi_del(&priv->napi);
free_candev(dev);
-
- return 0;
}
static const struct of_device_id grcan_match[] = {
@@ -1726,7 +1724,7 @@ static struct platform_driver grcan_driver = {
.of_match_table = grcan_match,
},
.probe = grcan_probe,
- .remove = grcan_remove,
+ .remove_new = grcan_remove,
};
module_platform_driver(grcan_driver);
diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c
index 07eaf724a572..1d6642c94f2f 100644
--- a/drivers/net/can/ifi_canfd/ifi_canfd.c
+++ b/drivers/net/can/ifi_canfd/ifi_canfd.c
@@ -1013,15 +1013,13 @@ err_reg:
return ret;
}
-static int ifi_canfd_plat_remove(struct platform_device *pdev)
+static void ifi_canfd_plat_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
unregister_candev(ndev);
platform_set_drvdata(pdev, NULL);
free_candev(ndev);
-
- return 0;
}
static const struct of_device_id ifi_canfd_of_table[] = {
@@ -1036,7 +1034,7 @@ static struct platform_driver ifi_canfd_plat_driver = {
.of_match_table = ifi_canfd_of_table,
},
.probe = ifi_canfd_plat_probe,
- .remove = ifi_canfd_plat_remove,
+ .remove_new = ifi_canfd_plat_remove,
};
module_platform_driver(ifi_canfd_plat_driver);
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
index 0732a5092141..d048ea565b89 100644
--- a/drivers/net/can/janz-ican3.c
+++ b/drivers/net/can/janz-ican3.c
@@ -2023,7 +2023,7 @@ out_return:
return ret;
}
-static int ican3_remove(struct platform_device *pdev)
+static void ican3_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct ican3_dev *mod = netdev_priv(ndev);
@@ -2042,8 +2042,6 @@ static int ican3_remove(struct platform_device *pdev)
iounmap(mod->dpm);
free_candev(ndev);
-
- return 0;
}
static struct platform_driver ican3_driver = {
@@ -2051,7 +2049,7 @@ static struct platform_driver ican3_driver = {
.name = DRV_NAME,
},
.probe = ican3_probe,
- .remove = ican3_remove,
+ .remove_new = ican3_remove,
};
module_platform_driver(ican3_driver);
diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c
index be189edb256c..db6256f2b1b3 100644
--- a/drivers/net/can/kvaser_pciefd.c
+++ b/drivers/net/can/kvaser_pciefd.c
@@ -3,19 +3,19 @@
* Parts of this driver are based on the following:
* - Kvaser linux pciefd driver (version 5.25)
* - PEAK linux canfd driver
- * - Altera Avalon EPCS flash controller driver
*/
-#include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/bitfield.h>
+#include <linux/can/dev.h>
#include <linux/device.h>
#include <linux/ethtool.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/minmax.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
#include <linux/pci.h>
-#include <linux/can/dev.h>
#include <linux/timer.h>
-#include <linux/netdevice.h>
-#include <linux/crc32.h>
-#include <linux/iopoll.h>
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Kvaser AB <support@kvaser.com>");
@@ -25,42 +25,25 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices");
#define KVASER_PCIEFD_WAIT_TIMEOUT msecs_to_jiffies(1000)
#define KVASER_PCIEFD_BEC_POLL_FREQ (jiffies + msecs_to_jiffies(200))
-#define KVASER_PCIEFD_MAX_ERR_REP 256
-#define KVASER_PCIEFD_CAN_TX_MAX_COUNT 17
-#define KVASER_PCIEFD_MAX_CAN_CHANNELS 4
-#define KVASER_PCIEFD_DMA_COUNT 2
+#define KVASER_PCIEFD_MAX_ERR_REP 256U
+#define KVASER_PCIEFD_CAN_TX_MAX_COUNT 17U
+#define KVASER_PCIEFD_MAX_CAN_CHANNELS 4UL
+#define KVASER_PCIEFD_DMA_COUNT 2U
-#define KVASER_PCIEFD_DMA_SIZE (4 * 1024)
-#define KVASER_PCIEFD_64BIT_DMA_BIT BIT(0)
+#define KVASER_PCIEFD_DMA_SIZE (4U * 1024U)
#define KVASER_PCIEFD_VENDOR 0x1a07
-#define KVASER_PCIEFD_4HS_ID 0x0d
-#define KVASER_PCIEFD_2HS_ID 0x0e
-#define KVASER_PCIEFD_HS_ID 0x0f
-#define KVASER_PCIEFD_MINIPCIE_HS_ID 0x10
-#define KVASER_PCIEFD_MINIPCIE_2HS_ID 0x11
+#define KVASER_PCIEFD_4HS_DEVICE_ID 0x000d
+#define KVASER_PCIEFD_2HS_V2_DEVICE_ID 0x000e
+#define KVASER_PCIEFD_HS_V2_DEVICE_ID 0x000f
+#define KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID 0x0010
+#define KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID 0x0011
/* PCIe IRQ registers */
#define KVASER_PCIEFD_IRQ_REG 0x40
#define KVASER_PCIEFD_IEN_REG 0x50
-/* DMA map */
+/* DMA address translation map register base */
#define KVASER_PCIEFD_DMA_MAP_BASE 0x1000
-/* Kvaser KCAN CAN controller registers */
-#define KVASER_PCIEFD_KCAN0_BASE 0x10000
-#define KVASER_PCIEFD_KCAN_BASE_OFFSET 0x1000
-#define KVASER_PCIEFD_KCAN_FIFO_REG 0x100
-#define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180
-#define KVASER_PCIEFD_KCAN_CTRL_REG 0x2c0
-#define KVASER_PCIEFD_KCAN_CMD_REG 0x400
-#define KVASER_PCIEFD_KCAN_IEN_REG 0x408
-#define KVASER_PCIEFD_KCAN_IRQ_REG 0x410
-#define KVASER_PCIEFD_KCAN_TX_NPACKETS_REG 0x414
-#define KVASER_PCIEFD_KCAN_STAT_REG 0x418
-#define KVASER_PCIEFD_KCAN_MODE_REG 0x41c
-#define KVASER_PCIEFD_KCAN_BTRN_REG 0x420
-#define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424
-#define KVASER_PCIEFD_KCAN_BTRD_REG 0x428
-#define KVASER_PCIEFD_KCAN_PWM_REG 0x430
/* Loopback control register */
#define KVASER_PCIEFD_LOOP_REG 0x1f000
/* System identification and information registers */
@@ -78,183 +61,196 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices");
#define KVASER_PCIEFD_SRB_STAT_REG (KVASER_PCIEFD_SRB_BASE + 0x210)
#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG (KVASER_PCIEFD_SRB_BASE + 0x214)
#define KVASER_PCIEFD_SRB_CTRL_REG (KVASER_PCIEFD_SRB_BASE + 0x218)
-/* EPCS flash controller registers */
-#define KVASER_PCIEFD_SPI_BASE 0x1fc00
-#define KVASER_PCIEFD_SPI_RX_REG KVASER_PCIEFD_SPI_BASE
-#define KVASER_PCIEFD_SPI_TX_REG (KVASER_PCIEFD_SPI_BASE + 0x4)
-#define KVASER_PCIEFD_SPI_STATUS_REG (KVASER_PCIEFD_SPI_BASE + 0x8)
-#define KVASER_PCIEFD_SPI_CTRL_REG (KVASER_PCIEFD_SPI_BASE + 0xc)
-#define KVASER_PCIEFD_SPI_SSEL_REG (KVASER_PCIEFD_SPI_BASE + 0x14)
-
-#define KVASER_PCIEFD_IRQ_ALL_MSK 0x1f
+/* Kvaser KCAN CAN controller registers */
+#define KVASER_PCIEFD_KCAN0_BASE 0x10000
+#define KVASER_PCIEFD_KCAN_BASE_OFFSET 0x1000
+#define KVASER_PCIEFD_KCAN_FIFO_REG 0x100
+#define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180
+#define KVASER_PCIEFD_KCAN_CTRL_REG 0x2c0
+#define KVASER_PCIEFD_KCAN_CMD_REG 0x400
+#define KVASER_PCIEFD_KCAN_IEN_REG 0x408
+#define KVASER_PCIEFD_KCAN_IRQ_REG 0x410
+#define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG 0x414
+#define KVASER_PCIEFD_KCAN_STAT_REG 0x418
+#define KVASER_PCIEFD_KCAN_MODE_REG 0x41c
+#define KVASER_PCIEFD_KCAN_BTRN_REG 0x420
+#define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424
+#define KVASER_PCIEFD_KCAN_BTRD_REG 0x428
+#define KVASER_PCIEFD_KCAN_PWM_REG 0x430
+
+/* PCI interrupt fields */
#define KVASER_PCIEFD_IRQ_SRB BIT(4)
+#define KVASER_PCIEFD_IRQ_ALL_MASK GENMASK(4, 0)
-#define KVASER_PCIEFD_SYSID_NRCHAN_SHIFT 24
-#define KVASER_PCIEFD_SYSID_MAJOR_VER_SHIFT 16
-#define KVASER_PCIEFD_SYSID_BUILD_VER_SHIFT 1
+/* Enable 64-bit DMA address translation */
+#define KVASER_PCIEFD_64BIT_DMA_BIT BIT(0)
+
+/* System build information fields */
+#define KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK GENMASK(31, 24)
+#define KVASER_PCIEFD_SYSID_VERSION_MAJOR_MASK GENMASK(23, 16)
+#define KVASER_PCIEFD_SYSID_VERSION_MINOR_MASK GENMASK(7, 0)
+#define KVASER_PCIEFD_SYSID_BUILD_SEQ_MASK GENMASK(15, 1)
/* Reset DMA buffer 0, 1 and FIFO offset */
-#define KVASER_PCIEFD_SRB_CMD_RDB0 BIT(4)
#define KVASER_PCIEFD_SRB_CMD_RDB1 BIT(5)
+#define KVASER_PCIEFD_SRB_CMD_RDB0 BIT(4)
#define KVASER_PCIEFD_SRB_CMD_FOR BIT(0)
-/* DMA packet done, buffer 0 and 1 */
-#define KVASER_PCIEFD_SRB_IRQ_DPD0 BIT(8)
-#define KVASER_PCIEFD_SRB_IRQ_DPD1 BIT(9)
-/* DMA overflow, buffer 0 and 1 */
-#define KVASER_PCIEFD_SRB_IRQ_DOF0 BIT(10)
-#define KVASER_PCIEFD_SRB_IRQ_DOF1 BIT(11)
/* DMA underflow, buffer 0 and 1 */
-#define KVASER_PCIEFD_SRB_IRQ_DUF0 BIT(12)
#define KVASER_PCIEFD_SRB_IRQ_DUF1 BIT(13)
+#define KVASER_PCIEFD_SRB_IRQ_DUF0 BIT(12)
+/* DMA overflow, buffer 0 and 1 */
+#define KVASER_PCIEFD_SRB_IRQ_DOF1 BIT(11)
+#define KVASER_PCIEFD_SRB_IRQ_DOF0 BIT(10)
+/* DMA packet done, buffer 0 and 1 */
+#define KVASER_PCIEFD_SRB_IRQ_DPD1 BIT(9)
+#define KVASER_PCIEFD_SRB_IRQ_DPD0 BIT(8)
+/* Got DMA support */
+#define KVASER_PCIEFD_SRB_STAT_DMA BIT(24)
/* DMA idle */
#define KVASER_PCIEFD_SRB_STAT_DI BIT(15)
-/* DMA support */
-#define KVASER_PCIEFD_SRB_STAT_DMA BIT(24)
/* SRB current packet level */
-#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK 0xff
+#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK GENMASK(7, 0)
/* DMA Enable */
#define KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE BIT(0)
-/* EPCS flash controller definitions */
-#define KVASER_PCIEFD_CFG_IMG_SZ (64 * 1024)
-#define KVASER_PCIEFD_CFG_IMG_OFFSET (31 * 65536L)
-#define KVASER_PCIEFD_CFG_MAX_PARAMS 256
-#define KVASER_PCIEFD_CFG_MAGIC 0xcafef00d
-#define KVASER_PCIEFD_CFG_PARAM_MAX_SZ 24
-#define KVASER_PCIEFD_CFG_SYS_VER 1
-#define KVASER_PCIEFD_CFG_PARAM_NR_CHAN 130
-#define KVASER_PCIEFD_SPI_TMT BIT(5)
-#define KVASER_PCIEFD_SPI_TRDY BIT(6)
-#define KVASER_PCIEFD_SPI_RRDY BIT(7)
-#define KVASER_PCIEFD_FLASH_ID_EPCS16 0x14
-/* Commands for controlling the onboard flash */
-#define KVASER_PCIEFD_FLASH_RES_CMD 0xab
-#define KVASER_PCIEFD_FLASH_READ_CMD 0x3
-#define KVASER_PCIEFD_FLASH_STATUS_CMD 0x5
-
-/* Kvaser KCAN definitions */
-#define KVASER_PCIEFD_KCAN_CTRL_EFLUSH (4 << 29)
-#define KVASER_PCIEFD_KCAN_CTRL_EFRAME (5 << 29)
-
-#define KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT 16
-/* Request status packet */
-#define KVASER_PCIEFD_KCAN_CMD_SRQ BIT(0)
+/* KCAN CTRL packet types */
+#define KVASER_PCIEFD_KCAN_CTRL_TYPE_MASK GENMASK(31, 29)
+#define KVASER_PCIEFD_KCAN_CTRL_TYPE_EFLUSH 0x4
+#define KVASER_PCIEFD_KCAN_CTRL_TYPE_EFRAME 0x5
+
+/* Command sequence number */
+#define KVASER_PCIEFD_KCAN_CMD_SEQ_MASK GENMASK(23, 16)
+/* Command bits */
+#define KVASER_PCIEFD_KCAN_CMD_MASK GENMASK(5, 0)
/* Abort, flush and reset */
#define KVASER_PCIEFD_KCAN_CMD_AT BIT(1)
+/* Request status packet */
+#define KVASER_PCIEFD_KCAN_CMD_SRQ BIT(0)
-/* Tx FIFO unaligned read */
-#define KVASER_PCIEFD_KCAN_IRQ_TAR BIT(0)
-/* Tx FIFO unaligned end */
-#define KVASER_PCIEFD_KCAN_IRQ_TAE BIT(1)
-/* Bus parameter protection error */
-#define KVASER_PCIEFD_KCAN_IRQ_BPP BIT(2)
-/* FDF bit when controller is in classic mode */
-#define KVASER_PCIEFD_KCAN_IRQ_FDIC BIT(3)
-/* Rx FIFO overflow */
-#define KVASER_PCIEFD_KCAN_IRQ_ROF BIT(5)
-/* Abort done */
-#define KVASER_PCIEFD_KCAN_IRQ_ABD BIT(13)
-/* Tx buffer flush done */
-#define KVASER_PCIEFD_KCAN_IRQ_TFD BIT(14)
-/* Tx FIFO overflow */
-#define KVASER_PCIEFD_KCAN_IRQ_TOF BIT(15)
-/* Tx FIFO empty */
-#define KVASER_PCIEFD_KCAN_IRQ_TE BIT(16)
/* Transmitter unaligned */
#define KVASER_PCIEFD_KCAN_IRQ_TAL BIT(17)
+/* Tx FIFO empty */
+#define KVASER_PCIEFD_KCAN_IRQ_TE BIT(16)
+/* Tx FIFO overflow */
+#define KVASER_PCIEFD_KCAN_IRQ_TOF BIT(15)
+/* Tx buffer flush done */
+#define KVASER_PCIEFD_KCAN_IRQ_TFD BIT(14)
+/* Abort done */
+#define KVASER_PCIEFD_KCAN_IRQ_ABD BIT(13)
+/* Rx FIFO overflow */
+#define KVASER_PCIEFD_KCAN_IRQ_ROF BIT(5)
+/* FDF bit when controller is in classic CAN mode */
+#define KVASER_PCIEFD_KCAN_IRQ_FDIC BIT(3)
+/* Bus parameter protection error */
+#define KVASER_PCIEFD_KCAN_IRQ_BPP BIT(2)
+/* Tx FIFO unaligned end */
+#define KVASER_PCIEFD_KCAN_IRQ_TAE BIT(1)
+/* Tx FIFO unaligned read */
+#define KVASER_PCIEFD_KCAN_IRQ_TAR BIT(0)
-#define KVASER_PCIEFD_KCAN_TX_NPACKETS_MAX_SHIFT 16
+/* Tx FIFO size */
+#define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_MAX_MASK GENMASK(23, 16)
+/* Tx FIFO current packet level */
+#define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK GENMASK(7, 0)
-#define KVASER_PCIEFD_KCAN_STAT_SEQNO_SHIFT 24
-/* Abort request */
-#define KVASER_PCIEFD_KCAN_STAT_AR BIT(7)
-/* Idle state. Controller in reset mode and no abort or flush pending */
-#define KVASER_PCIEFD_KCAN_STAT_IDLE BIT(10)
-/* Bus off */
-#define KVASER_PCIEFD_KCAN_STAT_BOFF BIT(11)
-/* Reset mode request */
-#define KVASER_PCIEFD_KCAN_STAT_RMR BIT(14)
-/* Controller in reset mode */
-#define KVASER_PCIEFD_KCAN_STAT_IRM BIT(15)
-/* Controller got one-shot capability */
-#define KVASER_PCIEFD_KCAN_STAT_CAP BIT(16)
+/* Current status packet sequence number */
+#define KVASER_PCIEFD_KCAN_STAT_SEQNO_MASK GENMASK(31, 24)
/* Controller got CAN FD capability */
#define KVASER_PCIEFD_KCAN_STAT_FD BIT(19)
-#define KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MSK (KVASER_PCIEFD_KCAN_STAT_AR | \
- KVASER_PCIEFD_KCAN_STAT_BOFF | KVASER_PCIEFD_KCAN_STAT_RMR | \
- KVASER_PCIEFD_KCAN_STAT_IRM)
+/* Controller got one-shot capability */
+#define KVASER_PCIEFD_KCAN_STAT_CAP BIT(16)
+/* Controller in reset mode */
+#define KVASER_PCIEFD_KCAN_STAT_IRM BIT(15)
+/* Reset mode request */
+#define KVASER_PCIEFD_KCAN_STAT_RMR BIT(14)
+/* Bus off */
+#define KVASER_PCIEFD_KCAN_STAT_BOFF BIT(11)
+/* Idle state. Controller in reset mode and no abort or flush pending */
+#define KVASER_PCIEFD_KCAN_STAT_IDLE BIT(10)
+/* Abort request */
+#define KVASER_PCIEFD_KCAN_STAT_AR BIT(7)
+/* Controller is bus off */
+#define KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MASK \
+ (KVASER_PCIEFD_KCAN_STAT_AR | KVASER_PCIEFD_KCAN_STAT_BOFF | \
+ KVASER_PCIEFD_KCAN_STAT_RMR | KVASER_PCIEFD_KCAN_STAT_IRM)
-/* Reset mode */
-#define KVASER_PCIEFD_KCAN_MODE_RM BIT(8)
-/* Listen only mode */
-#define KVASER_PCIEFD_KCAN_MODE_LOM BIT(9)
-/* Error packet enable */
-#define KVASER_PCIEFD_KCAN_MODE_EPEN BIT(12)
-/* CAN FD non-ISO */
-#define KVASER_PCIEFD_KCAN_MODE_NIFDEN BIT(15)
-/* Acknowledgment packet type */
-#define KVASER_PCIEFD_KCAN_MODE_APT BIT(20)
-/* Active error flag enable. Clear to force error passive */
-#define KVASER_PCIEFD_KCAN_MODE_EEN BIT(23)
/* Classic CAN mode */
#define KVASER_PCIEFD_KCAN_MODE_CCM BIT(31)
+/* Active error flag enable. Clear to force error passive */
+#define KVASER_PCIEFD_KCAN_MODE_EEN BIT(23)
+/* Acknowledgment packet type */
+#define KVASER_PCIEFD_KCAN_MODE_APT BIT(20)
+/* CAN FD non-ISO */
+#define KVASER_PCIEFD_KCAN_MODE_NIFDEN BIT(15)
+/* Error packet enable */
+#define KVASER_PCIEFD_KCAN_MODE_EPEN BIT(12)
+/* Listen only mode */
+#define KVASER_PCIEFD_KCAN_MODE_LOM BIT(9)
+/* Reset mode */
+#define KVASER_PCIEFD_KCAN_MODE_RM BIT(8)
-#define KVASER_PCIEFD_KCAN_BTRN_SJW_SHIFT 13
-#define KVASER_PCIEFD_KCAN_BTRN_TSEG1_SHIFT 17
-#define KVASER_PCIEFD_KCAN_BTRN_TSEG2_SHIFT 26
-
-#define KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT 16
-
-/* Kvaser KCAN packet types */
-#define KVASER_PCIEFD_PACK_TYPE_DATA 0
-#define KVASER_PCIEFD_PACK_TYPE_ACK 1
-#define KVASER_PCIEFD_PACK_TYPE_TXRQ 2
-#define KVASER_PCIEFD_PACK_TYPE_ERROR 3
-#define KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK 4
-#define KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK 5
-#define KVASER_PCIEFD_PACK_TYPE_ACK_DATA 6
-#define KVASER_PCIEFD_PACK_TYPE_STATUS 8
-#define KVASER_PCIEFD_PACK_TYPE_BUS_LOAD 9
-
-/* Kvaser KCAN packet common definitions */
-#define KVASER_PCIEFD_PACKET_SEQ_MSK 0xff
-#define KVASER_PCIEFD_PACKET_CHID_SHIFT 25
-#define KVASER_PCIEFD_PACKET_TYPE_SHIFT 28
-
-/* Kvaser KCAN TDATA and RDATA first word */
+/* BTRN and BTRD fields */
+#define KVASER_PCIEFD_KCAN_BTRN_TSEG2_MASK GENMASK(30, 26)
+#define KVASER_PCIEFD_KCAN_BTRN_TSEG1_MASK GENMASK(25, 17)
+#define KVASER_PCIEFD_KCAN_BTRN_SJW_MASK GENMASK(16, 13)
+#define KVASER_PCIEFD_KCAN_BTRN_BRP_MASK GENMASK(12, 0)
+
+/* PWM Control fields */
+#define KVASER_PCIEFD_KCAN_PWM_TOP_MASK GENMASK(23, 16)
+#define KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK GENMASK(7, 0)
+
+/* KCAN packet type IDs */
+#define KVASER_PCIEFD_PACK_TYPE_DATA 0x0
+#define KVASER_PCIEFD_PACK_TYPE_ACK 0x1
+#define KVASER_PCIEFD_PACK_TYPE_TXRQ 0x2
+#define KVASER_PCIEFD_PACK_TYPE_ERROR 0x3
+#define KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK 0x4
+#define KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK 0x5
+#define KVASER_PCIEFD_PACK_TYPE_ACK_DATA 0x6
+#define KVASER_PCIEFD_PACK_TYPE_STATUS 0x8
+#define KVASER_PCIEFD_PACK_TYPE_BUS_LOAD 0x9
+
+/* Common KCAN packet definitions, second word */
+#define KVASER_PCIEFD_PACKET_TYPE_MASK GENMASK(31, 28)
+#define KVASER_PCIEFD_PACKET_CHID_MASK GENMASK(27, 25)
+#define KVASER_PCIEFD_PACKET_SEQ_MASK GENMASK(7, 0)
+
+/* KCAN Transmit/Receive data packet, first word */
#define KVASER_PCIEFD_RPACKET_IDE BIT(30)
#define KVASER_PCIEFD_RPACKET_RTR BIT(29)
-/* Kvaser KCAN TDATA and RDATA second word */
-#define KVASER_PCIEFD_RPACKET_ESI BIT(13)
-#define KVASER_PCIEFD_RPACKET_BRS BIT(14)
-#define KVASER_PCIEFD_RPACKET_FDF BIT(15)
-#define KVASER_PCIEFD_RPACKET_DLC_SHIFT 8
-/* Kvaser KCAN TDATA second word */
-#define KVASER_PCIEFD_TPACKET_SMS BIT(16)
+#define KVASER_PCIEFD_RPACKET_ID_MASK GENMASK(28, 0)
+/* KCAN Transmit data packet, second word */
#define KVASER_PCIEFD_TPACKET_AREQ BIT(31)
+#define KVASER_PCIEFD_TPACKET_SMS BIT(16)
+/* KCAN Transmit/Receive data packet, second word */
+#define KVASER_PCIEFD_RPACKET_FDF BIT(15)
+#define KVASER_PCIEFD_RPACKET_BRS BIT(14)
+#define KVASER_PCIEFD_RPACKET_ESI BIT(13)
+#define KVASER_PCIEFD_RPACKET_DLC_MASK GENMASK(11, 8)
-/* Kvaser KCAN APACKET */
-#define KVASER_PCIEFD_APACKET_FLU BIT(8)
-#define KVASER_PCIEFD_APACKET_CT BIT(9)
-#define KVASER_PCIEFD_APACKET_ABL BIT(10)
+/* KCAN Transmit acknowledge packet, first word */
#define KVASER_PCIEFD_APACKET_NACK BIT(11)
+#define KVASER_PCIEFD_APACKET_ABL BIT(10)
+#define KVASER_PCIEFD_APACKET_CT BIT(9)
+#define KVASER_PCIEFD_APACKET_FLU BIT(8)
-/* Kvaser KCAN SPACK first word */
-#define KVASER_PCIEFD_SPACK_RXERR_SHIFT 8
-#define KVASER_PCIEFD_SPACK_BOFF BIT(16)
-#define KVASER_PCIEFD_SPACK_IDET BIT(20)
-#define KVASER_PCIEFD_SPACK_IRM BIT(21)
+/* KCAN Status packet, first word */
#define KVASER_PCIEFD_SPACK_RMCD BIT(22)
-/* Kvaser KCAN SPACK second word */
-#define KVASER_PCIEFD_SPACK_AUTO BIT(21)
-#define KVASER_PCIEFD_SPACK_EWLR BIT(23)
+#define KVASER_PCIEFD_SPACK_IRM BIT(21)
+#define KVASER_PCIEFD_SPACK_IDET BIT(20)
+#define KVASER_PCIEFD_SPACK_BOFF BIT(16)
+#define KVASER_PCIEFD_SPACK_RXERR_MASK GENMASK(15, 8)
+#define KVASER_PCIEFD_SPACK_TXERR_MASK GENMASK(7, 0)
+/* KCAN Status packet, second word */
#define KVASER_PCIEFD_SPACK_EPLR BIT(24)
+#define KVASER_PCIEFD_SPACK_EWLR BIT(23)
+#define KVASER_PCIEFD_SPACK_AUTO BIT(21)
-/* Kvaser KCAN_EPACK second word */
+/* KCAN Error detected packet, second word */
#define KVASER_PCIEFD_EPACK_DIR_TX BIT(0)
struct kvaser_pciefd;
@@ -306,195 +302,43 @@ static const struct can_bittiming_const kvaser_pciefd_bittiming_const = {
.brp_inc = 1,
};
-struct kvaser_pciefd_cfg_param {
- __le32 magic;
- __le32 nr;
- __le32 len;
- u8 data[KVASER_PCIEFD_CFG_PARAM_MAX_SZ];
-};
-
-struct kvaser_pciefd_cfg_img {
- __le32 version;
- __le32 magic;
- __le32 crc;
- struct kvaser_pciefd_cfg_param params[KVASER_PCIEFD_CFG_MAX_PARAMS];
-};
-
static struct pci_device_id kvaser_pciefd_id_table[] = {
- { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4HS_ID), },
- { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2HS_ID), },
- { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_HS_ID), },
- { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_HS_ID), },
- { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_ID), },
- { 0,},
+ {
+ PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4HS_DEVICE_ID),
+ },
+ {
+ PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2HS_V2_DEVICE_ID),
+ },
+ {
+ PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_HS_V2_DEVICE_ID),
+ },
+ {
+ PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID),
+ },
+ {
+ PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID),
+ },
+ {
+ 0,
+ },
};
MODULE_DEVICE_TABLE(pci, kvaser_pciefd_id_table);
-/* Onboard flash memory functions */
-static int kvaser_pciefd_spi_wait_loop(struct kvaser_pciefd *pcie, int msk)
-{
- u32 res;
-
- return readl_poll_timeout(pcie->reg_base + KVASER_PCIEFD_SPI_STATUS_REG,
- res, res & msk, 0, 10);
-}
-
-static int kvaser_pciefd_spi_cmd(struct kvaser_pciefd *pcie, const u8 *tx,
- u32 tx_len, u8 *rx, u32 rx_len)
-{
- int c;
-
- iowrite32(BIT(0), pcie->reg_base + KVASER_PCIEFD_SPI_SSEL_REG);
- iowrite32(BIT(10), pcie->reg_base + KVASER_PCIEFD_SPI_CTRL_REG);
- ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG);
-
- c = tx_len;
- while (c--) {
- if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TRDY))
- return -EIO;
-
- iowrite32(*tx++, pcie->reg_base + KVASER_PCIEFD_SPI_TX_REG);
-
- if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_RRDY))
- return -EIO;
-
- ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG);
- }
-
- c = rx_len;
- while (c-- > 0) {
- if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TRDY))
- return -EIO;
-
- iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SPI_TX_REG);
-
- if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_RRDY))
- return -EIO;
-
- *rx++ = ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG);
- }
-
- if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TMT))
- return -EIO;
-
- iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SPI_CTRL_REG);
-
- if (c != -1) {
- dev_err(&pcie->pci->dev, "Flash SPI transfer failed\n");
- return -EIO;
- }
-
- return 0;
-}
-
-static int kvaser_pciefd_cfg_read_and_verify(struct kvaser_pciefd *pcie,
- struct kvaser_pciefd_cfg_img *img)
-{
- int offset = KVASER_PCIEFD_CFG_IMG_OFFSET;
- int res, crc;
- u8 *crc_buff;
-
- u8 cmd[] = {
- KVASER_PCIEFD_FLASH_READ_CMD,
- (u8)((offset >> 16) & 0xff),
- (u8)((offset >> 8) & 0xff),
- (u8)(offset & 0xff)
- };
-
- res = kvaser_pciefd_spi_cmd(pcie, cmd, ARRAY_SIZE(cmd), (u8 *)img,
- KVASER_PCIEFD_CFG_IMG_SZ);
- if (res)
- return res;
-
- crc_buff = (u8 *)img->params;
-
- if (le32_to_cpu(img->version) != KVASER_PCIEFD_CFG_SYS_VER) {
- dev_err(&pcie->pci->dev,
- "Config flash corrupted, version number is wrong\n");
- return -ENODEV;
- }
-
- if (le32_to_cpu(img->magic) != KVASER_PCIEFD_CFG_MAGIC) {
- dev_err(&pcie->pci->dev,
- "Config flash corrupted, magic number is wrong\n");
- return -ENODEV;
- }
-
- crc = ~crc32_be(0xffffffff, crc_buff, sizeof(img->params));
- if (le32_to_cpu(img->crc) != crc) {
- dev_err(&pcie->pci->dev,
- "Stored CRC does not match flash image contents\n");
- return -EIO;
- }
-
- return 0;
-}
-
-static void kvaser_pciefd_cfg_read_params(struct kvaser_pciefd *pcie,
- struct kvaser_pciefd_cfg_img *img)
+static inline void kvaser_pciefd_send_kcan_cmd(struct kvaser_pciefd_can *can, u32 cmd)
{
- struct kvaser_pciefd_cfg_param *param;
-
- param = &img->params[KVASER_PCIEFD_CFG_PARAM_NR_CHAN];
- memcpy(&pcie->nr_channels, param->data, le32_to_cpu(param->len));
+ iowrite32(FIELD_PREP(KVASER_PCIEFD_KCAN_CMD_MASK, cmd) |
+ FIELD_PREP(KVASER_PCIEFD_KCAN_CMD_SEQ_MASK, ++can->cmd_seq),
+ can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG);
}
-static int kvaser_pciefd_read_cfg(struct kvaser_pciefd *pcie)
+static inline void kvaser_pciefd_request_status(struct kvaser_pciefd_can *can)
{
- int res;
- struct kvaser_pciefd_cfg_img *img;
-
- /* Read electronic signature */
- u8 cmd[] = {KVASER_PCIEFD_FLASH_RES_CMD, 0, 0, 0};
-
- res = kvaser_pciefd_spi_cmd(pcie, cmd, ARRAY_SIZE(cmd), cmd, 1);
- if (res)
- return -EIO;
-
- img = kmalloc(KVASER_PCIEFD_CFG_IMG_SZ, GFP_KERNEL);
- if (!img)
- return -ENOMEM;
-
- if (cmd[0] != KVASER_PCIEFD_FLASH_ID_EPCS16) {
- dev_err(&pcie->pci->dev,
- "Flash id is 0x%x instead of expected EPCS16 (0x%x)\n",
- cmd[0], KVASER_PCIEFD_FLASH_ID_EPCS16);
-
- res = -ENODEV;
- goto image_free;
- }
-
- cmd[0] = KVASER_PCIEFD_FLASH_STATUS_CMD;
- res = kvaser_pciefd_spi_cmd(pcie, cmd, 1, cmd, 1);
- if (res) {
- goto image_free;
- } else if (cmd[0] & 1) {
- res = -EIO;
- /* No write is ever done, the WIP should never be set */
- dev_err(&pcie->pci->dev, "Unexpected WIP bit set in flash\n");
- goto image_free;
- }
-
- res = kvaser_pciefd_cfg_read_and_verify(pcie, img);
- if (res) {
- res = -EIO;
- goto image_free;
- }
-
- kvaser_pciefd_cfg_read_params(pcie, img);
-
-image_free:
- kfree(img);
- return res;
+ kvaser_pciefd_send_kcan_cmd(can, KVASER_PCIEFD_KCAN_CMD_SRQ);
}
-static void kvaser_pciefd_request_status(struct kvaser_pciefd_can *can)
+static inline void kvaser_pciefd_abort_flush_reset(struct kvaser_pciefd_can *can)
{
- u32 cmd;
-
- cmd = KVASER_PCIEFD_KCAN_CMD_SRQ;
- cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT;
- iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG);
+ kvaser_pciefd_send_kcan_cmd(can, KVASER_PCIEFD_KCAN_CMD_AT);
}
static void kvaser_pciefd_enable_err_gen(struct kvaser_pciefd_can *can)
@@ -523,7 +367,7 @@ static void kvaser_pciefd_disable_err_gen(struct kvaser_pciefd_can *can)
spin_unlock_irqrestore(&can->lock, irq);
}
-static int kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can)
+static void kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can)
{
u32 msk;
@@ -534,8 +378,13 @@ static int kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can)
KVASER_PCIEFD_KCAN_IRQ_TAR;
iowrite32(msk, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
+}
- return 0;
+static inline void kvaser_pciefd_set_skb_timestamp(const struct kvaser_pciefd *pcie,
+ struct sk_buff *skb, u64 timestamp)
+{
+ skb_hwtstamps(skb)->hwtstamp =
+ ns_to_ktime(div_u64(timestamp * 1000, pcie->freq_to_ticks_div));
}
static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can)
@@ -544,7 +393,6 @@ static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can)
unsigned long irq;
spin_lock_irqsave(&can->lock, irq);
-
mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
if (can->can.ctrlmode & CAN_CTRLMODE_FD) {
mode &= ~KVASER_PCIEFD_KCAN_MODE_CCM;
@@ -561,7 +409,6 @@ static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can)
mode |= KVASER_PCIEFD_KCAN_MODE_LOM;
else
mode &= ~KVASER_PCIEFD_KCAN_MODE_LOM;
-
mode |= KVASER_PCIEFD_KCAN_MODE_EEN;
mode |= KVASER_PCIEFD_KCAN_MODE_EPEN;
/* Use ACK packet type */
@@ -578,18 +425,13 @@ static void kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can *can)
unsigned long irq;
spin_lock_irqsave(&can->lock, irq);
- iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
+ iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
-
status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
if (status & KVASER_PCIEFD_KCAN_STAT_IDLE) {
- u32 cmd;
-
/* If controller is already idle, run abort, flush and reset */
- cmd = KVASER_PCIEFD_KCAN_CMD_AT;
- cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT;
- iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG);
+ kvaser_pciefd_abort_flush_reset(can);
} else if (!(status & KVASER_PCIEFD_KCAN_STAT_RMR)) {
u32 mode;
@@ -598,7 +440,6 @@ static void kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can *can)
mode |= KVASER_PCIEFD_KCAN_MODE_RM;
iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
}
-
spin_unlock_irqrestore(&can->lock, irq);
}
@@ -608,7 +449,6 @@ static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can)
unsigned long irq;
del_timer(&can->bec_poll_timer);
-
if (!completion_done(&can->flush_comp))
kvaser_pciefd_start_controller_flush(can);
@@ -620,11 +460,9 @@ static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can)
spin_lock_irqsave(&can->lock, irq);
iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
- iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
-
+ iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
-
mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
mode &= ~KVASER_PCIEFD_KCAN_MODE_RM;
iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
@@ -637,11 +475,10 @@ static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can)
}
/* Reset interrupt handling */
iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
- iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
+ iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
kvaser_pciefd_set_tx_irq(can);
kvaser_pciefd_setup_controller(can);
-
can->can.state = CAN_STATE_ERROR_ACTIVE;
netif_wake_queue(can->can.dev);
can->bec.txerr = 0;
@@ -659,10 +496,9 @@ static void kvaser_pciefd_pwm_stop(struct kvaser_pciefd_can *can)
spin_lock_irqsave(&can->lock, irq);
pwm_ctrl = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
- top = (pwm_ctrl >> KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT) & 0xff;
-
+ top = FIELD_GET(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, pwm_ctrl);
/* Set duty cycle to zero */
- pwm_ctrl |= top;
+ pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, top);
iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
spin_unlock_irqrestore(&can->lock, irq);
}
@@ -675,18 +511,17 @@ static void kvaser_pciefd_pwm_start(struct kvaser_pciefd_can *can)
kvaser_pciefd_pwm_stop(can);
spin_lock_irqsave(&can->lock, irq);
-
- /* Set frequency to 500 KHz*/
+ /* Set frequency to 500 KHz */
top = can->kv_pcie->bus_freq / (2 * 500000) - 1;
- pwm_ctrl = top & 0xff;
- pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT;
+ pwm_ctrl = FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, top);
+ pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, top);
iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
/* Set duty cycle to 95 */
trigger = (100 * top - 95 * (top + 1) + 50) / 100;
- pwm_ctrl = trigger & 0xff;
- pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT;
+ pwm_ctrl = FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, trigger);
+ pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, top);
iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
spin_unlock_irqrestore(&can->lock, irq);
}
@@ -741,7 +576,6 @@ static int kvaser_pciefd_prepare_tx_packet(struct kvaser_pciefd_tx_packet *p,
int seq = can->echo_idx;
memset(p, 0, sizeof(*p));
-
if (can->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
p->header[1] |= KVASER_PCIEFD_TPACKET_SMS;
@@ -751,19 +585,24 @@ static int kvaser_pciefd_prepare_tx_packet(struct kvaser_pciefd_tx_packet *p,
if (cf->can_id & CAN_EFF_FLAG)
p->header[0] |= KVASER_PCIEFD_RPACKET_IDE;
- p->header[0] |= cf->can_id & CAN_EFF_MASK;
- p->header[1] |= can_fd_len2dlc(cf->len) << KVASER_PCIEFD_RPACKET_DLC_SHIFT;
+ p->header[0] |= FIELD_PREP(KVASER_PCIEFD_RPACKET_ID_MASK, cf->can_id);
p->header[1] |= KVASER_PCIEFD_TPACKET_AREQ;
if (can_is_canfd_skb(skb)) {
+ p->header[1] |= FIELD_PREP(KVASER_PCIEFD_RPACKET_DLC_MASK,
+ can_fd_len2dlc(cf->len));
p->header[1] |= KVASER_PCIEFD_RPACKET_FDF;
if (cf->flags & CANFD_BRS)
p->header[1] |= KVASER_PCIEFD_RPACKET_BRS;
if (cf->flags & CANFD_ESI)
p->header[1] |= KVASER_PCIEFD_RPACKET_ESI;
+ } else {
+ p->header[1] |=
+ FIELD_PREP(KVASER_PCIEFD_RPACKET_DLC_MASK,
+ can_get_cc_dlc((struct can_frame *)cf, can->can.ctrlmode));
}
- p->header[1] |= seq & KVASER_PCIEFD_PACKET_SEQ_MSK;
+ p->header[1] |= FIELD_PREP(KVASER_PCIEFD_PACKET_SEQ_MASK, seq);
packet_size = cf->len;
memcpy(p->data, cf->data, packet_size);
@@ -777,16 +616,15 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb,
struct kvaser_pciefd_can *can = netdev_priv(netdev);
unsigned long irq_flags;
struct kvaser_pciefd_tx_packet packet;
- int nwords;
+ int nr_words;
u8 count;
if (can_dev_dropped_skb(netdev, skb))
return NETDEV_TX_OK;
- nwords = kvaser_pciefd_prepare_tx_packet(&packet, can, skb);
+ nr_words = kvaser_pciefd_prepare_tx_packet(&packet, can, skb);
spin_lock_irqsave(&can->echo_lock, irq_flags);
-
/* Prepare and save echo skb in internal slot */
can_put_echo_skb(skb, netdev, can->echo_idx, 0);
@@ -799,13 +637,13 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb,
iowrite32(packet.header[1],
can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG);
- if (nwords) {
- u32 data_last = ((u32 *)packet.data)[nwords - 1];
+ if (nr_words) {
+ u32 data_last = ((u32 *)packet.data)[nr_words - 1];
/* Write data to fifo, except last word */
iowrite32_rep(can->reg_base +
KVASER_PCIEFD_KCAN_FIFO_REG, packet.data,
- nwords - 1);
+ nr_words - 1);
/* Write last word to end of fifo */
__raw_writel(data_last, can->reg_base +
KVASER_PCIEFD_KCAN_FIFO_LAST_REG);
@@ -815,14 +653,13 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb,
KVASER_PCIEFD_KCAN_FIFO_LAST_REG);
}
- count = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NPACKETS_REG);
+ count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK,
+ ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG));
/* No room for a new message, stop the queue until at least one
* successful transmit
*/
- if (count >= KVASER_PCIEFD_CAN_TX_MAX_COUNT ||
- can->can.echo_skb[can->echo_idx])
+ if (count >= can->can.echo_skb_max || can->can.echo_skb[can->echo_idx])
netif_stop_queue(netdev);
-
spin_unlock_irqrestore(&can->echo_lock, irq_flags);
return NETDEV_TX_OK;
@@ -840,25 +677,20 @@ static int kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can *can, bool data)
else
bt = &can->can.bittiming;
- btrn = ((bt->phase_seg2 - 1) & 0x1f) <<
- KVASER_PCIEFD_KCAN_BTRN_TSEG2_SHIFT |
- (((bt->prop_seg + bt->phase_seg1) - 1) & 0x1ff) <<
- KVASER_PCIEFD_KCAN_BTRN_TSEG1_SHIFT |
- ((bt->sjw - 1) & 0xf) << KVASER_PCIEFD_KCAN_BTRN_SJW_SHIFT |
- ((bt->brp - 1) & 0x1fff);
+ btrn = FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_TSEG2_MASK, bt->phase_seg2 - 1) |
+ FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_TSEG1_MASK, bt->prop_seg + bt->phase_seg1 - 1) |
+ FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_SJW_MASK, bt->sjw - 1) |
+ FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_BRP_MASK, bt->brp - 1);
spin_lock_irqsave(&can->lock, irq_flags);
mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
-
/* Put the circuit in reset mode */
iowrite32(mode | KVASER_PCIEFD_KCAN_MODE_RM,
can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
/* Can only set bittiming if in reset mode */
ret = readl_poll_timeout(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG,
- test, test & KVASER_PCIEFD_KCAN_MODE_RM,
- 0, 10);
-
+ test, test & KVASER_PCIEFD_KCAN_MODE_RM, 0, 10);
if (ret) {
spin_unlock_irqrestore(&can->lock, irq_flags);
return -EBUSY;
@@ -868,11 +700,10 @@ static int kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can *can, bool data)
iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRD_REG);
else
iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRN_REG);
-
/* Restore previous reset mode status */
iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
-
spin_unlock_irqrestore(&can->lock, irq_flags);
+
return 0;
}
@@ -910,6 +741,7 @@ static int kvaser_pciefd_get_berr_counter(const struct net_device *ndev,
bec->rxerr = can->bec.rxerr;
bec->txerr = can->bec.txerr;
+
return 0;
}
@@ -941,7 +773,7 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
for (i = 0; i < pcie->nr_channels; i++) {
struct net_device *netdev;
struct kvaser_pciefd_can *can;
- u32 status, tx_npackets;
+ u32 status, tx_nr_packets_max;
netdev = alloc_candev(sizeof(struct kvaser_pciefd_can),
KVASER_PCIEFD_CAN_TX_MAX_COUNT);
@@ -953,7 +785,6 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
netdev->ethtool_ops = &kvaser_pciefd_ethtool_ops;
can->reg_base = pcie->reg_base + KVASER_PCIEFD_KCAN0_BASE +
i * KVASER_PCIEFD_KCAN_BASE_OFFSET;
-
can->kv_pcie = pcie;
can->cmd_seq = 0;
can->err_rep_cnt = 0;
@@ -962,41 +793,31 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
init_completion(&can->start_comp);
init_completion(&can->flush_comp);
- timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer,
- 0);
+ timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer, 0);
/* Disable Bus load reporting */
iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_BUS_LOAD_REG);
- tx_npackets = ioread32(can->reg_base +
- KVASER_PCIEFD_KCAN_TX_NPACKETS_REG);
- if (((tx_npackets >> KVASER_PCIEFD_KCAN_TX_NPACKETS_MAX_SHIFT) &
- 0xff) < KVASER_PCIEFD_CAN_TX_MAX_COUNT) {
- dev_err(&pcie->pci->dev,
- "Max Tx count is smaller than expected\n");
-
- free_candev(netdev);
- return -ENODEV;
- }
+ tx_nr_packets_max =
+ FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_MAX_MASK,
+ ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG));
can->can.clock.freq = pcie->freq;
- can->can.echo_skb_max = KVASER_PCIEFD_CAN_TX_MAX_COUNT;
+ can->can.echo_skb_max = min(KVASER_PCIEFD_CAN_TX_MAX_COUNT, tx_nr_packets_max - 1);
can->echo_idx = 0;
spin_lock_init(&can->echo_lock);
spin_lock_init(&can->lock);
+
can->can.bittiming_const = &kvaser_pciefd_bittiming_const;
can->can.data_bittiming_const = &kvaser_pciefd_bittiming_const;
-
can->can.do_set_bittiming = kvaser_pciefd_set_nominal_bittiming;
- can->can.do_set_data_bittiming =
- kvaser_pciefd_set_data_bittiming;
-
+ can->can.do_set_data_bittiming = kvaser_pciefd_set_data_bittiming;
can->can.do_set_mode = kvaser_pciefd_set_mode;
can->can.do_get_berr_counter = kvaser_pciefd_get_berr_counter;
-
can->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY |
CAN_CTRLMODE_FD |
- CAN_CTRLMODE_FD_NON_ISO;
+ CAN_CTRLMODE_FD_NON_ISO |
+ CAN_CTRLMODE_CC_LEN8_DLC;
status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
if (!(status & KVASER_PCIEFD_KCAN_STAT_FD)) {
@@ -1011,10 +832,9 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
can->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT;
netdev->flags |= IFF_ECHO;
-
SET_NETDEV_DEV(netdev, &pcie->pci->dev);
- iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
+ iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
@@ -1073,18 +893,16 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
for (i = 0; i < KVASER_PCIEFD_DMA_COUNT; i++) {
unsigned int offset = KVASER_PCIEFD_DMA_MAP_BASE + 8 * i;
- pcie->dma_data[i] =
- dmam_alloc_coherent(&pcie->pci->dev,
- KVASER_PCIEFD_DMA_SIZE,
- &dma_addr[i],
- GFP_KERNEL);
+ pcie->dma_data[i] = dmam_alloc_coherent(&pcie->pci->dev,
+ KVASER_PCIEFD_DMA_SIZE,
+ &dma_addr[i],
+ GFP_KERNEL);
if (!pcie->dma_data[i] || !dma_addr[i]) {
dev_err(&pcie->pci->dev, "Rx dma_alloc(%u) failure\n",
KVASER_PCIEFD_DMA_SIZE);
return -ENOMEM;
}
-
kvaser_pciefd_write_dma_map(pcie, dma_addr[i], offset);
}
@@ -1092,10 +910,10 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
iowrite32(KVASER_PCIEFD_SRB_CMD_FOR | KVASER_PCIEFD_SRB_CMD_RDB0 |
KVASER_PCIEFD_SRB_CMD_RDB1,
pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG);
-
/* Empty Rx FIFO */
- srb_packet_count = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG) &
- KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK;
+ srb_packet_count =
+ FIELD_GET(KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK,
+ ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG));
while (srb_packet_count) {
/* Drop current packet in FIFO */
ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_FIFO_LAST_REG);
@@ -1117,37 +935,21 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
static int kvaser_pciefd_setup_board(struct kvaser_pciefd *pcie)
{
- u32 sysid, srb_status, build;
- u8 sysid_nr_chan;
- int ret;
-
- ret = kvaser_pciefd_read_cfg(pcie);
- if (ret)
- return ret;
-
- sysid = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_VERSION_REG);
- sysid_nr_chan = (sysid >> KVASER_PCIEFD_SYSID_NRCHAN_SHIFT) & 0xff;
- if (pcie->nr_channels != sysid_nr_chan) {
- dev_err(&pcie->pci->dev,
- "Number of channels does not match: %u vs %u\n",
- pcie->nr_channels,
- sysid_nr_chan);
- return -ENODEV;
- }
+ u32 version, srb_status, build;
- if (pcie->nr_channels > KVASER_PCIEFD_MAX_CAN_CHANNELS)
- pcie->nr_channels = KVASER_PCIEFD_MAX_CAN_CHANNELS;
+ version = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_VERSION_REG);
+ pcie->nr_channels = min(KVASER_PCIEFD_MAX_CAN_CHANNELS,
+ FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK, version));
build = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_BUILD_REG);
- dev_dbg(&pcie->pci->dev, "Version %u.%u.%u\n",
- (sysid >> KVASER_PCIEFD_SYSID_MAJOR_VER_SHIFT) & 0xff,
- sysid & 0xff,
- (build >> KVASER_PCIEFD_SYSID_BUILD_VER_SHIFT) & 0x7fff);
+ dev_dbg(&pcie->pci->dev, "Version %lu.%lu.%lu\n",
+ FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MAJOR_MASK, version),
+ FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MINOR_MASK, version),
+ FIELD_GET(KVASER_PCIEFD_SYSID_BUILD_SEQ_MASK, build));
srb_status = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_STAT_REG);
if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DMA)) {
- dev_err(&pcie->pci->dev,
- "Hardware without DMA is not supported\n");
+ dev_err(&pcie->pci->dev, "Hardware without DMA is not supported\n");
return -ENODEV;
}
@@ -1157,10 +959,10 @@ static int kvaser_pciefd_setup_board(struct kvaser_pciefd *pcie)
pcie->freq_to_ticks_div = pcie->freq / 1000000;
if (pcie->freq_to_ticks_div == 0)
pcie->freq_to_ticks_div = 1;
-
/* Turn off all loopback functionality */
iowrite32(0, pcie->reg_base + KVASER_PCIEFD_LOOP_REG);
- return ret;
+
+ return 0;
}
static int kvaser_pciefd_handle_data_packet(struct kvaser_pciefd *pcie,
@@ -1170,56 +972,48 @@ static int kvaser_pciefd_handle_data_packet(struct kvaser_pciefd *pcie,
struct sk_buff *skb;
struct canfd_frame *cf;
struct can_priv *priv;
- struct net_device_stats *stats;
- struct skb_shared_hwtstamps *shhwtstamps;
- u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
+ u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
+ u8 dlc;
if (ch_id >= pcie->nr_channels)
return -EIO;
priv = &pcie->can[ch_id]->can;
- stats = &priv->dev->stats;
+ dlc = FIELD_GET(KVASER_PCIEFD_RPACKET_DLC_MASK, p->header[1]);
if (p->header[1] & KVASER_PCIEFD_RPACKET_FDF) {
skb = alloc_canfd_skb(priv->dev, &cf);
if (!skb) {
- stats->rx_dropped++;
+ priv->dev->stats.rx_dropped++;
return -ENOMEM;
}
+ cf->len = can_fd_dlc2len(dlc);
if (p->header[1] & KVASER_PCIEFD_RPACKET_BRS)
cf->flags |= CANFD_BRS;
-
if (p->header[1] & KVASER_PCIEFD_RPACKET_ESI)
cf->flags |= CANFD_ESI;
} else {
skb = alloc_can_skb(priv->dev, (struct can_frame **)&cf);
if (!skb) {
- stats->rx_dropped++;
+ priv->dev->stats.rx_dropped++;
return -ENOMEM;
}
+ can_frame_set_cc_len((struct can_frame *)cf, dlc, priv->ctrlmode);
}
- cf->can_id = p->header[0] & CAN_EFF_MASK;
+ cf->can_id = FIELD_GET(KVASER_PCIEFD_RPACKET_ID_MASK, p->header[0]);
if (p->header[0] & KVASER_PCIEFD_RPACKET_IDE)
cf->can_id |= CAN_EFF_FLAG;
- cf->len = can_fd_dlc2len(p->header[1] >> KVASER_PCIEFD_RPACKET_DLC_SHIFT);
-
if (p->header[0] & KVASER_PCIEFD_RPACKET_RTR) {
cf->can_id |= CAN_RTR_FLAG;
} else {
memcpy(cf->data, data, cf->len);
-
- stats->rx_bytes += cf->len;
+ priv->dev->stats.rx_bytes += cf->len;
}
- stats->rx_packets++;
-
- shhwtstamps = skb_hwtstamps(skb);
-
- shhwtstamps->hwtstamp =
- ns_to_ktime(div_u64(p->timestamp * 1000,
- pcie->freq_to_ticks_div));
+ priv->dev->stats.rx_packets++;
+ kvaser_pciefd_set_skb_timestamp(pcie, skb, p->timestamp);
return netif_rx(skb);
}
@@ -1239,7 +1033,6 @@ static void kvaser_pciefd_change_state(struct kvaser_pciefd_can *can,
spin_lock_irqsave(&can->lock, irq_flags);
netif_stop_queue(can->can.dev);
spin_unlock_irqrestore(&can->lock, irq_flags);
-
/* Prevent CAN controller from auto recover from bus off */
if (!can->can.restart_ms) {
kvaser_pciefd_start_controller_flush(can);
@@ -1257,7 +1050,7 @@ static void kvaser_pciefd_packet_to_state(struct kvaser_pciefd_rx_packet *p,
if (p->header[0] & KVASER_PCIEFD_SPACK_BOFF ||
p->header[0] & KVASER_PCIEFD_SPACK_IRM)
*new_state = CAN_STATE_BUS_OFF;
- else if (bec->txerr >= 255 || bec->rxerr >= 255)
+ else if (bec->txerr >= 255 || bec->rxerr >= 255)
*new_state = CAN_STATE_BUS_OFF;
else if (p->header[1] & KVASER_PCIEFD_SPACK_EPLR)
*new_state = CAN_STATE_ERROR_PASSIVE;
@@ -1282,23 +1075,16 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can,
struct net_device *ndev = can->can.dev;
struct sk_buff *skb;
struct can_frame *cf = NULL;
- struct skb_shared_hwtstamps *shhwtstamps;
- struct net_device_stats *stats = &ndev->stats;
old_state = can->can.state;
- bec.txerr = p->header[0] & 0xff;
- bec.rxerr = (p->header[0] >> KVASER_PCIEFD_SPACK_RXERR_SHIFT) & 0xff;
-
- kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state,
- &rx_state);
+ bec.txerr = FIELD_GET(KVASER_PCIEFD_SPACK_TXERR_MASK, p->header[0]);
+ bec.rxerr = FIELD_GET(KVASER_PCIEFD_SPACK_RXERR_MASK, p->header[0]);
+ kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, &rx_state);
skb = alloc_can_err_skb(ndev, &cf);
-
if (new_state != old_state) {
- kvaser_pciefd_change_state(can, cf, new_state, tx_state,
- rx_state);
-
+ kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state);
if (old_state == CAN_STATE_BUS_OFF &&
new_state == CAN_STATE_ERROR_ACTIVE &&
can->can.restart_ms) {
@@ -1311,28 +1097,25 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can,
can->err_rep_cnt++;
can->can.can_stats.bus_error++;
if (p->header[1] & KVASER_PCIEFD_EPACK_DIR_TX)
- stats->tx_errors++;
+ ndev->stats.tx_errors++;
else
- stats->rx_errors++;
+ ndev->stats.rx_errors++;
can->bec.txerr = bec.txerr;
can->bec.rxerr = bec.rxerr;
if (!skb) {
- stats->rx_dropped++;
+ ndev->stats.rx_dropped++;
return -ENOMEM;
}
- shhwtstamps = skb_hwtstamps(skb);
- shhwtstamps->hwtstamp =
- ns_to_ktime(div_u64(p->timestamp * 1000,
- can->kv_pcie->freq_to_ticks_div));
+ kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp);
cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_CNT;
-
cf->data[6] = bec.txerr;
cf->data[7] = bec.rxerr;
netif_rx(skb);
+
return 0;
}
@@ -1340,19 +1123,19 @@ static int kvaser_pciefd_handle_error_packet(struct kvaser_pciefd *pcie,
struct kvaser_pciefd_rx_packet *p)
{
struct kvaser_pciefd_can *can;
- u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
+ u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
if (ch_id >= pcie->nr_channels)
return -EIO;
can = pcie->can[ch_id];
-
kvaser_pciefd_rx_error_frame(can, p);
if (can->err_rep_cnt >= KVASER_PCIEFD_MAX_ERR_REP)
/* Do not report more errors, until bec_poll_timer expires */
kvaser_pciefd_disable_err_gen(can);
/* Start polling the error counters */
mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ);
+
return 0;
}
@@ -1364,29 +1147,22 @@ static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can,
old_state = can->can.state;
- bec.txerr = p->header[0] & 0xff;
- bec.rxerr = (p->header[0] >> KVASER_PCIEFD_SPACK_RXERR_SHIFT) & 0xff;
-
- kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state,
- &rx_state);
+ bec.txerr = FIELD_GET(KVASER_PCIEFD_SPACK_TXERR_MASK, p->header[0]);
+ bec.rxerr = FIELD_GET(KVASER_PCIEFD_SPACK_RXERR_MASK, p->header[0]);
+ kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, &rx_state);
if (new_state != old_state) {
struct net_device *ndev = can->can.dev;
struct sk_buff *skb;
struct can_frame *cf;
- struct skb_shared_hwtstamps *shhwtstamps;
skb = alloc_can_err_skb(ndev, &cf);
if (!skb) {
- struct net_device_stats *stats = &ndev->stats;
-
- stats->rx_dropped++;
+ ndev->stats.rx_dropped++;
return -ENOMEM;
}
- kvaser_pciefd_change_state(can, cf, new_state, tx_state,
- rx_state);
-
+ kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state);
if (old_state == CAN_STATE_BUS_OFF &&
new_state == CAN_STATE_ERROR_ACTIVE &&
can->can.restart_ms) {
@@ -1394,10 +1170,7 @@ static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can,
cf->can_id |= CAN_ERR_RESTARTED;
}
- shhwtstamps = skb_hwtstamps(skb);
- shhwtstamps->hwtstamp =
- ns_to_ktime(div_u64(p->timestamp * 1000,
- can->kv_pcie->freq_to_ticks_div));
+ kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp);
cf->data[6] = bec.txerr;
cf->data[7] = bec.rxerr;
@@ -1419,7 +1192,7 @@ static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie,
struct kvaser_pciefd_can *can;
u8 cmdseq;
u32 status;
- u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
+ u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
if (ch_id >= pcie->nr_channels)
return -EIO;
@@ -1427,43 +1200,40 @@ static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie,
can = pcie->can[ch_id];
status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
- cmdseq = (status >> KVASER_PCIEFD_KCAN_STAT_SEQNO_SHIFT) & 0xff;
+ cmdseq = FIELD_GET(KVASER_PCIEFD_KCAN_STAT_SEQNO_MASK, status);
/* Reset done, start abort and flush */
if (p->header[0] & KVASER_PCIEFD_SPACK_IRM &&
p->header[0] & KVASER_PCIEFD_SPACK_RMCD &&
p->header[1] & KVASER_PCIEFD_SPACK_AUTO &&
- cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) &&
+ cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1]) &&
status & KVASER_PCIEFD_KCAN_STAT_IDLE) {
- u32 cmd;
-
iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
- cmd = KVASER_PCIEFD_KCAN_CMD_AT;
- cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT;
- iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG);
+ kvaser_pciefd_abort_flush_reset(can);
} else if (p->header[0] & KVASER_PCIEFD_SPACK_IDET &&
p->header[0] & KVASER_PCIEFD_SPACK_IRM &&
- cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) &&
+ cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1]) &&
status & KVASER_PCIEFD_KCAN_STAT_IDLE) {
/* Reset detected, send end of flush if no packet are in FIFO */
- u8 count = ioread32(can->reg_base +
- KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff;
+ u8 count;
+ count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK,
+ ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG));
if (!count)
- iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH,
+ iowrite32(FIELD_PREP(KVASER_PCIEFD_KCAN_CTRL_TYPE_MASK,
+ KVASER_PCIEFD_KCAN_CTRL_TYPE_EFLUSH),
can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG);
} else if (!(p->header[1] & KVASER_PCIEFD_SPACK_AUTO) &&
- cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK)) {
+ cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1])) {
/* Response to status request received */
kvaser_pciefd_handle_status_resp(can, p);
if (can->can.state != CAN_STATE_BUS_OFF &&
can->can.state != CAN_STATE_ERROR_ACTIVE) {
- mod_timer(&can->bec_poll_timer,
- KVASER_PCIEFD_BEC_POLL_FREQ);
+ mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ);
}
} else if (p->header[0] & KVASER_PCIEFD_SPACK_RMCD &&
- !(status & KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MSK)) {
+ !(status & KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MASK)) {
/* Reset to bus on detected */
if (!completion_done(&can->start_comp))
complete(&can->start_comp);
@@ -1472,50 +1242,14 @@ static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie,
return 0;
}
-static int kvaser_pciefd_handle_eack_packet(struct kvaser_pciefd *pcie,
- struct kvaser_pciefd_rx_packet *p)
-{
- struct kvaser_pciefd_can *can;
- u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
-
- if (ch_id >= pcie->nr_channels)
- return -EIO;
-
- can = pcie->can[ch_id];
-
- /* If this is the last flushed packet, send end of flush */
- if (p->header[0] & KVASER_PCIEFD_APACKET_FLU) {
- u8 count = ioread32(can->reg_base +
- KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff;
-
- if (count == 0)
- iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH,
- can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG);
- } else {
- int echo_idx = p->header[0] & KVASER_PCIEFD_PACKET_SEQ_MSK;
- int dlc = can_get_echo_skb(can->can.dev, echo_idx, NULL);
- struct net_device_stats *stats = &can->can.dev->stats;
-
- stats->tx_bytes += dlc;
- stats->tx_packets++;
-
- if (netif_queue_stopped(can->can.dev))
- netif_wake_queue(can->can.dev);
- }
-
- return 0;
-}
-
static void kvaser_pciefd_handle_nack_packet(struct kvaser_pciefd_can *can,
struct kvaser_pciefd_rx_packet *p)
{
struct sk_buff *skb;
- struct net_device_stats *stats = &can->can.dev->stats;
struct can_frame *cf;
skb = alloc_can_err_skb(can->can.dev, &cf);
-
- stats->tx_errors++;
+ can->can.dev->stats.tx_errors++;
if (p->header[0] & KVASER_PCIEFD_APACKET_ABL) {
if (skb)
cf->can_id |= CAN_ERR_LOSTARB;
@@ -1526,9 +1260,10 @@ static void kvaser_pciefd_handle_nack_packet(struct kvaser_pciefd_can *can,
if (skb) {
cf->can_id |= CAN_ERR_BUSERROR;
+ kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp);
netif_rx(skb);
} else {
- stats->rx_dropped++;
+ can->can.dev->stats.rx_dropped++;
netdev_warn(can->can.dev, "No memory left for err_skb\n");
}
}
@@ -1538,7 +1273,7 @@ static int kvaser_pciefd_handle_ack_packet(struct kvaser_pciefd *pcie,
{
struct kvaser_pciefd_can *can;
bool one_shot_fail = false;
- u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
+ u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
if (ch_id >= pcie->nr_channels)
return -EIO;
@@ -1556,20 +1291,24 @@ static int kvaser_pciefd_handle_ack_packet(struct kvaser_pciefd *pcie,
if (p->header[0] & KVASER_PCIEFD_APACKET_FLU) {
netdev_dbg(can->can.dev, "Packet was flushed\n");
} else {
- int echo_idx = p->header[0] & KVASER_PCIEFD_PACKET_SEQ_MSK;
- int dlc = can_get_echo_skb(can->can.dev, echo_idx, NULL);
- u8 count = ioread32(can->reg_base +
- KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff;
+ int echo_idx = FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[0]);
+ int len;
+ u8 count;
+ struct sk_buff *skb;
- if (count < KVASER_PCIEFD_CAN_TX_MAX_COUNT &&
- netif_queue_stopped(can->can.dev))
+ skb = can->can.echo_skb[echo_idx];
+ if (skb)
+ kvaser_pciefd_set_skb_timestamp(pcie, skb, p->timestamp);
+ len = can_get_echo_skb(can->can.dev, echo_idx, NULL);
+ count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK,
+ ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG));
+
+ if (count < can->can.echo_skb_max && netif_queue_stopped(can->can.dev))
netif_wake_queue(can->can.dev);
if (!one_shot_fail) {
- struct net_device_stats *stats = &can->can.dev->stats;
-
- stats->tx_bytes += dlc;
- stats->tx_packets++;
+ can->can.dev->stats.tx_bytes += len;
+ can->can.dev->stats.tx_packets++;
}
}
@@ -1580,7 +1319,7 @@ static int kvaser_pciefd_handle_eflush_packet(struct kvaser_pciefd *pcie,
struct kvaser_pciefd_rx_packet *p)
{
struct kvaser_pciefd_can *can;
- u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
+ u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
if (ch_id >= pcie->nr_channels)
return -EIO;
@@ -1619,15 +1358,15 @@ static int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos,
pos += 2;
p->timestamp = le64_to_cpu(timestamp);
- type = (p->header[1] >> KVASER_PCIEFD_PACKET_TYPE_SHIFT) & 0xf;
+ type = FIELD_GET(KVASER_PCIEFD_PACKET_TYPE_MASK, p->header[1]);
switch (type) {
case KVASER_PCIEFD_PACK_TYPE_DATA:
ret = kvaser_pciefd_handle_data_packet(pcie, p, &buffer[pos]);
if (!(p->header[0] & KVASER_PCIEFD_RPACKET_RTR)) {
u8 data_len;
- data_len = can_fd_dlc2len(p->header[1] >>
- KVASER_PCIEFD_RPACKET_DLC_SHIFT);
+ data_len = can_fd_dlc2len(FIELD_GET(KVASER_PCIEFD_RPACKET_DLC_MASK,
+ p->header[1]));
pos += DIV_ROUND_UP(data_len, 4);
}
break;
@@ -1644,16 +1383,13 @@ static int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos,
ret = kvaser_pciefd_handle_error_packet(pcie, p);
break;
- case KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK:
- ret = kvaser_pciefd_handle_eack_packet(pcie, p);
- break;
-
case KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK:
ret = kvaser_pciefd_handle_eflush_packet(pcie, p);
break;
case KVASER_PCIEFD_PACK_TYPE_ACK_DATA:
case KVASER_PCIEFD_PACK_TYPE_BUS_LOAD:
+ case KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK:
case KVASER_PCIEFD_PACK_TYPE_TXRQ:
dev_info(&pcie->pci->dev,
"Received unexpected packet type 0x%08X\n", type);
@@ -1692,7 +1428,7 @@ static int kvaser_pciefd_read_buffer(struct kvaser_pciefd *pcie, int dma_buf)
return res;
}
-static int kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie)
+static void kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie)
{
u32 irq;
@@ -1718,10 +1454,9 @@ static int kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie)
dev_err(&pcie->pci->dev, "DMA IRQ error 0x%08X\n", irq);
iowrite32(irq, pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG);
- return 0;
}
-static int kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can)
+static void kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can)
{
u32 irq = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
@@ -1739,7 +1474,6 @@ static int kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can)
netdev_err(can->can.dev, "Rx FIFO overflow\n");
iowrite32(irq, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
- return 0;
}
static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev)
@@ -1750,7 +1484,7 @@ static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev)
board_irq = ioread32(pcie->reg_base + KVASER_PCIEFD_IRQ_REG);
- if (!(board_irq & KVASER_PCIEFD_IRQ_ALL_MSK))
+ if (!(board_irq & KVASER_PCIEFD_IRQ_ALL_MASK))
return IRQ_NONE;
if (board_irq & KVASER_PCIEFD_IRQ_SRB)
@@ -1768,20 +1502,18 @@ static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev)
kvaser_pciefd_transmit_irq(pcie->can[i]);
}
- iowrite32(board_irq, pcie->reg_base + KVASER_PCIEFD_IRQ_REG);
return IRQ_HANDLED;
}
static void kvaser_pciefd_teardown_can_ctrls(struct kvaser_pciefd *pcie)
{
int i;
- struct kvaser_pciefd_can *can;
for (i = 0; i < pcie->nr_channels; i++) {
- can = pcie->can[i];
+ struct kvaser_pciefd_can *can = pcie->can[i];
+
if (can) {
- iowrite32(0,
- can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
+ iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
kvaser_pciefd_pwm_stop(can);
free_candev(can->can.dev);
}
@@ -1842,10 +1574,8 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev,
KVASER_PCIEFD_SRB_IRQ_DUF0 | KVASER_PCIEFD_SRB_IRQ_DUF1,
pcie->reg_base + KVASER_PCIEFD_SRB_IEN_REG);
- /* Reset IRQ handling, expected to be off before */
- iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK,
- pcie->reg_base + KVASER_PCIEFD_IRQ_REG);
- iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK,
+ /* Enable PCI interrupts */
+ iowrite32(KVASER_PCIEFD_IRQ_ALL_MASK,
pcie->reg_base + KVASER_PCIEFD_IEN_REG);
/* Ready the DMA buffers */
@@ -1884,14 +1614,13 @@ err_disable_pci:
static void kvaser_pciefd_remove_all_ctrls(struct kvaser_pciefd *pcie)
{
- struct kvaser_pciefd_can *can;
int i;
for (i = 0; i < pcie->nr_channels; i++) {
- can = pcie->can[i];
+ struct kvaser_pciefd_can *can = pcie->can[i];
+
if (can) {
- iowrite32(0,
- can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
+ iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
unregister_candev(can->can.dev);
del_timer(&can->bec_poll_timer);
kvaser_pciefd_pwm_stop(can);
@@ -1906,10 +1635,8 @@ static void kvaser_pciefd_remove(struct pci_dev *pdev)
kvaser_pciefd_remove_all_ctrls(pcie);
- /* Turn off IRQ generation */
+ /* Disable interrupts */
iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG);
- iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK,
- pcie->reg_base + KVASER_PCIEFD_IRQ_REG);
iowrite32(0, pcie->reg_base + KVASER_PCIEFD_IEN_REG);
free_irq(pcie->pci->irq, pcie);
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index a5003435802b..c5af92bcc9c9 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -469,7 +469,7 @@ static void m_can_receive_skb(struct m_can_classdev *cdev,
int err;
err = can_rx_offload_queue_timestamp(&cdev->offload, skb,
- timestamp);
+ timestamp);
if (err)
stats->rx_fifo_errors++;
} else {
@@ -895,7 +895,7 @@ static int m_can_handle_bus_errors(struct net_device *dev, u32 irqstatus,
netdev_dbg(dev, "Arbitration phase error detected\n");
work_done += m_can_handle_lec_err(dev, lec);
}
-
+
if (is_lec_err(dlec)) {
netdev_dbg(dev, "Data phase error detected\n");
work_done += m_can_handle_lec_err(dev, dlec);
diff --git a/drivers/net/can/m_can/m_can_platform.c b/drivers/net/can/m_can/m_can_platform.c
index 9c1dcf838006..94dc82644113 100644
--- a/drivers/net/can/m_can/m_can_platform.c
+++ b/drivers/net/can/m_can/m_can_platform.c
@@ -164,7 +164,7 @@ static __maybe_unused int m_can_resume(struct device *dev)
return m_can_class_resume(dev);
}
-static int m_can_plat_remove(struct platform_device *pdev)
+static void m_can_plat_remove(struct platform_device *pdev)
{
struct m_can_plat_priv *priv = platform_get_drvdata(pdev);
struct m_can_classdev *mcan_class = &priv->cdev;
@@ -172,8 +172,6 @@ static int m_can_plat_remove(struct platform_device *pdev)
m_can_class_unregister(mcan_class);
m_can_class_free_dev(mcan_class->net);
-
- return 0;
}
static int __maybe_unused m_can_runtime_suspend(struct device *dev)
@@ -223,7 +221,7 @@ static struct platform_driver m_can_plat_driver = {
.pm = &m_can_pmops,
},
.probe = m_can_plat_probe,
- .remove = m_can_plat_remove,
+ .remove_new = m_can_plat_remove,
};
module_platform_driver(m_can_plat_driver);
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index b0ed798ae70f..4837df6efa92 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -349,7 +349,7 @@ exit_unmap_mem:
return err;
}
-static int mpc5xxx_can_remove(struct platform_device *ofdev)
+static void mpc5xxx_can_remove(struct platform_device *ofdev)
{
const struct of_device_id *match;
const struct mpc5xxx_can_data *data;
@@ -365,8 +365,6 @@ static int mpc5xxx_can_remove(struct platform_device *ofdev)
iounmap(priv->reg_base);
irq_dispose_mapping(dev->irq);
free_candev(dev);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -437,7 +435,7 @@ static struct platform_driver mpc5xxx_can_driver = {
.of_match_table = mpc5xxx_can_table,
},
.probe = mpc5xxx_can_probe,
- .remove = mpc5xxx_can_remove,
+ .remove_new = mpc5xxx_can_remove,
#ifdef CONFIG_PM
.suspend = mpc5xxx_can_suspend,
.resume = mpc5xxx_can_resume,
diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c
index cc43c9c5e38c..f5aa5dbacaf2 100644
--- a/drivers/net/can/rcar/rcar_can.c
+++ b/drivers/net/can/rcar/rcar_can.c
@@ -824,7 +824,7 @@ fail:
return err;
}
-static int rcar_can_remove(struct platform_device *pdev)
+static void rcar_can_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct rcar_can_priv *priv = netdev_priv(ndev);
@@ -832,7 +832,6 @@ static int rcar_can_remove(struct platform_device *pdev)
unregister_candev(ndev);
netif_napi_del(&priv->napi);
free_candev(ndev);
- return 0;
}
static int __maybe_unused rcar_can_suspend(struct device *dev)
@@ -908,7 +907,7 @@ static struct platform_driver rcar_can_driver = {
.pm = &rcar_can_pm_ops,
},
.probe = rcar_can_probe,
- .remove = rcar_can_remove,
+ .remove_new = rcar_can_remove,
};
module_platform_driver(rcar_can_driver);
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index 963c42f43755..e4d748913439 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -2078,7 +2078,7 @@ fail_dev:
return err;
}
-static int rcar_canfd_remove(struct platform_device *pdev)
+static void rcar_canfd_remove(struct platform_device *pdev)
{
struct rcar_canfd_global *gpriv = platform_get_drvdata(pdev);
u32 ch;
@@ -2096,8 +2096,6 @@ static int rcar_canfd_remove(struct platform_device *pdev)
clk_disable_unprepare(gpriv->clkp);
reset_control_assert(gpriv->rstc1);
reset_control_assert(gpriv->rstc2);
-
- return 0;
}
static int __maybe_unused rcar_canfd_suspend(struct device *dev)
@@ -2130,7 +2128,7 @@ static struct platform_driver rcar_canfd_driver = {
.pm = &rcar_canfd_pm_ops,
},
.probe = rcar_canfd_probe,
- .remove = rcar_canfd_remove,
+ .remove_new = rcar_canfd_remove,
};
module_platform_driver(rcar_canfd_driver);
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index aac5956e4a53..0ada0e160e93 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -387,6 +387,16 @@ static void sja1000_rx(struct net_device *dev)
netif_rx(skb);
}
+static irqreturn_t sja1000_reset_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = (struct net_device *)dev_id;
+
+ netdev_dbg(dev, "performing a soft reset upon overrun\n");
+ sja1000_start(dev);
+
+ return IRQ_HANDLED;
+}
+
static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
{
struct sja1000_priv *priv = netdev_priv(dev);
@@ -397,6 +407,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
enum can_state rx_state, tx_state;
unsigned int rxerr, txerr;
uint8_t ecc, alc;
+ int ret = 0;
skb = alloc_can_err_skb(dev, &cf);
if (skb == NULL)
@@ -413,6 +424,15 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
stats->rx_over_errors++;
stats->rx_errors++;
sja1000_write_cmdreg(priv, CMD_CDO); /* clear bit */
+
+ /* Some controllers needs additional handling upon overrun
+ * condition: the controller may sometimes be totally confused
+ * and refuse any new frame while its buffer is empty. The only
+ * way to re-sync the read vs. write buffer offsets is to
+ * stop any current handling and perform a reset.
+ */
+ if (priv->flags & SJA1000_QUIRK_RESET_ON_OVERRUN)
+ ret = IRQ_WAKE_THREAD;
}
if (isrc & IRQ_EI) {
@@ -492,7 +512,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
netif_rx(skb);
- return 0;
+ return ret;
}
irqreturn_t sja1000_interrupt(int irq, void *dev_id)
@@ -501,7 +521,8 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
struct sja1000_priv *priv = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
uint8_t isrc, status;
- int n = 0;
+ irqreturn_t ret = 0;
+ int n = 0, err;
if (priv->pre_irq)
priv->pre_irq(priv);
@@ -546,19 +567,25 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
}
if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
/* error interrupt */
- if (sja1000_err(dev, isrc, status))
+ err = sja1000_err(dev, isrc, status);
+ if (err == IRQ_WAKE_THREAD)
+ ret = err;
+ if (err)
break;
}
n++;
}
out:
+ if (!ret)
+ ret = (n) ? IRQ_HANDLED : IRQ_NONE;
+
if (priv->post_irq)
priv->post_irq(priv);
if (n >= SJA1000_MAX_IRQ)
netdev_dbg(dev, "%d messages handled in ISR", n);
- return (n) ? IRQ_HANDLED : IRQ_NONE;
+ return ret;
}
EXPORT_SYMBOL_GPL(sja1000_interrupt);
@@ -577,8 +604,9 @@ static int sja1000_open(struct net_device *dev)
/* register interrupt handler, if not done by the device driver */
if (!(priv->flags & SJA1000_CUSTOM_IRQ_HANDLER)) {
- err = request_irq(dev->irq, sja1000_interrupt, priv->irq_flags,
- dev->name, (void *)dev);
+ err = request_threaded_irq(dev->irq, sja1000_interrupt,
+ sja1000_reset_interrupt,
+ priv->irq_flags, dev->name, (void *)dev);
if (err) {
close_candev(dev);
return -EAGAIN;
diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h
index 7f736f1df547..f015e39e2224 100644
--- a/drivers/net/can/sja1000/sja1000.h
+++ b/drivers/net/can/sja1000/sja1000.h
@@ -147,6 +147,7 @@
*/
#define SJA1000_CUSTOM_IRQ_HANDLER BIT(0)
#define SJA1000_QUIRK_NO_CDR_REG BIT(1)
+#define SJA1000_QUIRK_RESET_ON_OVERRUN BIT(2)
/*
* SJA1000 private data structure
diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c
index db3e767d5320..fca5a9a1d857 100644
--- a/drivers/net/can/sja1000/sja1000_isa.c
+++ b/drivers/net/can/sja1000/sja1000_isa.c
@@ -223,7 +223,7 @@ exit:
return err;
}
-static int sja1000_isa_remove(struct platform_device *pdev)
+static void sja1000_isa_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct sja1000_priv *priv = netdev_priv(dev);
@@ -241,13 +241,11 @@ static int sja1000_isa_remove(struct platform_device *pdev)
release_region(port[idx], SJA1000_IOSIZE);
}
free_sja1000dev(dev);
-
- return 0;
}
static struct platform_driver sja1000_isa_driver = {
.probe = sja1000_isa_probe,
- .remove = sja1000_isa_remove,
+ .remove_new = sja1000_isa_remove,
.driver = {
.name = DRV_NAME,
},
diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c
index 6779d5357069..4e59952c66d4 100644
--- a/drivers/net/can/sja1000/sja1000_platform.c
+++ b/drivers/net/can/sja1000/sja1000_platform.c
@@ -106,7 +106,7 @@ static void sp_technologic_init(struct sja1000_priv *priv, struct device_node *o
static void sp_rzn1_init(struct sja1000_priv *priv, struct device_node *of)
{
- priv->flags = SJA1000_QUIRK_NO_CDR_REG;
+ priv->flags = SJA1000_QUIRK_NO_CDR_REG | SJA1000_QUIRK_RESET_ON_OVERRUN;
}
static void sp_populate(struct sja1000_priv *priv,
@@ -277,6 +277,9 @@ static int sp_probe(struct platform_device *pdev)
priv->irq_flags = IRQF_SHARED;
}
+ if (priv->flags & SJA1000_QUIRK_RESET_ON_OVERRUN)
+ priv->irq_flags |= IRQF_ONESHOT;
+
dev->irq = irq;
priv->reg_base = addr;
@@ -317,19 +320,17 @@ static int sp_probe(struct platform_device *pdev)
return err;
}
-static int sp_remove(struct platform_device *pdev)
+static void sp_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
unregister_sja1000dev(dev);
free_sja1000dev(dev);
-
- return 0;
}
static struct platform_driver sp_driver = {
.probe = sp_probe,
- .remove = sp_remove,
+ .remove_new = sp_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = sp_of_table,
diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c
index c72f505d29fe..bd25137062c5 100644
--- a/drivers/net/can/softing/softing_main.c
+++ b/drivers/net/can/softing/softing_main.c
@@ -729,7 +729,7 @@ static const struct attribute_group softing_pdev_group = {
/*
* platform driver
*/
-static int softing_pdev_remove(struct platform_device *pdev)
+static void softing_pdev_remove(struct platform_device *pdev)
{
struct softing *card = platform_get_drvdata(pdev);
int j;
@@ -747,7 +747,6 @@ static int softing_pdev_remove(struct platform_device *pdev)
iounmap(card->dpram);
kfree(card);
- return 0;
}
static int softing_pdev_probe(struct platform_device *pdev)
@@ -855,7 +854,7 @@ static struct platform_driver softing_driver = {
.name = KBUILD_MODNAME,
},
.probe = softing_pdev_probe,
- .remove = softing_pdev_remove,
+ .remove_new = softing_pdev_remove,
};
module_platform_driver(softing_driver);
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
index 68df6d4641b5..eebf967f4711 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -227,6 +227,8 @@ static int
__mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv,
const u8 mode_req, bool nowait)
{
+ const struct can_bittiming *bt = &priv->can.bittiming;
+ unsigned long timeout_us = MCP251XFD_POLL_TIMEOUT_US;
u32 con = 0, con_reqop, osc = 0;
u8 mode;
int err;
@@ -246,12 +248,16 @@ __mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv,
if (mode_req == MCP251XFD_REG_CON_MODE_SLEEP || nowait)
return 0;
+ if (bt->bitrate)
+ timeout_us = max_t(unsigned long, timeout_us,
+ MCP251XFD_FRAME_LEN_MAX_BITS * USEC_PER_SEC /
+ bt->bitrate);
+
err = regmap_read_poll_timeout(priv->map_reg, MCP251XFD_REG_CON, con,
!mcp251xfd_reg_invalid(con) &&
FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK,
con) == mode_req,
- MCP251XFD_POLL_SLEEP_US,
- MCP251XFD_POLL_TIMEOUT_US);
+ MCP251XFD_POLL_SLEEP_US, timeout_us);
if (err != -ETIMEDOUT && err != -EBADMSG)
return err;
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
index 7024ff0cc2c0..24510b3b8020 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
@@ -387,6 +387,7 @@ static_assert(MCP251XFD_TIMESTAMP_WORK_DELAY_SEC <
#define MCP251XFD_OSC_STAB_TIMEOUT_US (10 * MCP251XFD_OSC_STAB_SLEEP_US)
#define MCP251XFD_POLL_SLEEP_US (10)
#define MCP251XFD_POLL_TIMEOUT_US (USEC_PER_MSEC)
+#define MCP251XFD_FRAME_LEN_MAX_BITS (736)
/* Misc */
#define MCP251XFD_NAPI_WEIGHT 32
diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c
index 2b78f9197681..0827830bbf28 100644
--- a/drivers/net/can/sun4i_can.c
+++ b/drivers/net/can/sun4i_can.c
@@ -791,14 +791,12 @@ static const struct of_device_id sun4ican_of_match[] = {
MODULE_DEVICE_TABLE(of, sun4ican_of_match);
-static int sun4ican_remove(struct platform_device *pdev)
+static void sun4ican_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
unregister_netdev(dev);
free_candev(dev);
-
- return 0;
}
static int sun4ican_probe(struct platform_device *pdev)
@@ -901,7 +899,7 @@ static struct platform_driver sun4i_can_driver = {
.of_match_table = sun4ican_of_match,
},
.probe = sun4ican_probe,
- .remove = sun4ican_remove,
+ .remove_new = sun4ican_remove,
};
module_platform_driver(sun4i_can_driver);
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
index 27700f72eac2..54284661992e 100644
--- a/drivers/net/can/ti_hecc.c
+++ b/drivers/net/can/ti_hecc.c
@@ -625,7 +625,7 @@ static int ti_hecc_error(struct net_device *ndev, int int_status,
timestamp = hecc_read(priv, HECC_CANLNT);
err = can_rx_offload_queue_timestamp(&priv->offload, skb,
- timestamp);
+ timestamp);
if (err)
ndev->stats.rx_fifo_errors++;
}
@@ -963,7 +963,7 @@ probe_exit_candev:
return err;
}
-static int ti_hecc_remove(struct platform_device *pdev)
+static void ti_hecc_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct ti_hecc_priv *priv = netdev_priv(ndev);
@@ -973,8 +973,6 @@ static int ti_hecc_remove(struct platform_device *pdev)
clk_put(priv->clk);
can_rx_offload_del(&priv->offload);
free_candev(ndev);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -1028,7 +1026,7 @@ static struct platform_driver ti_hecc_driver = {
.of_match_table = ti_hecc_dt_ids,
},
.probe = ti_hecc_probe,
- .remove = ti_hecc_remove,
+ .remove_new = ti_hecc_remove,
.suspend = ti_hecc_suspend,
.resume = ti_hecc_resume,
};
diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig
index 445504ababce..58fcd2b34820 100644
--- a/drivers/net/can/usb/Kconfig
+++ b/drivers/net/can/usb/Kconfig
@@ -38,6 +38,18 @@ config CAN_ETAS_ES58X
To compile this driver as a module, choose M here: the module
will be called etas_es58x.
+config CAN_F81604
+ tristate "Fintek F81604 USB to 2CAN interface"
+ help
+ This driver supports the Fintek F81604 USB to 2CAN interface.
+ The device can support CAN2.0A/B protocol and also support
+ 2 output pins to control external terminator (optional).
+
+ To compile this driver as a module, choose M here: the module will
+ be called f81604.
+
+ (see also https://www.fintek.com.tw).
+
config CAN_GS_USB
tristate "Geschwister Schneider UG and candleLight compatible interfaces"
help
diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile
index 1ea16be5743b..8b11088e9a59 100644
--- a/drivers/net/can/usb/Makefile
+++ b/drivers/net/can/usb/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_CAN_8DEV_USB) += usb_8dev.o
obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o
obj-$(CONFIG_CAN_ESD_USB) += esd_usb.o
obj-$(CONFIG_CAN_ETAS_ES58X) += etas_es58x/
+obj-$(CONFIG_CAN_F81604) += f81604.o
obj-$(CONFIG_CAN_GS_USB) += gs_usb.o
obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb/
obj-$(CONFIG_CAN_MCBA_USB) += mcba_usb.o
diff --git a/drivers/net/can/usb/esd_usb.c b/drivers/net/can/usb/esd_usb.c
index d33bac3a6c10..6201637ac0ff 100644
--- a/drivers/net/can/usb/esd_usb.c
+++ b/drivers/net/can/usb/esd_usb.c
@@ -3,18 +3,19 @@
* CAN driver for esd electronics gmbh CAN-USB/2 and CAN-USB/Micro
*
* Copyright (C) 2010-2012 esd electronic system design gmbh, Matthias Fuchs <socketcan@esd.eu>
- * Copyright (C) 2022 esd electronics gmbh, Frank Jungclaus <frank.jungclaus@esd.eu>
+ * Copyright (C) 2022-2023 esd electronics gmbh, Frank Jungclaus <frank.jungclaus@esd.eu>
*/
-#include <linux/ethtool.h>
-#include <linux/signal.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/usb.h>
#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
+#include <linux/ethtool.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/units.h>
+#include <linux/usb.h>
MODULE_AUTHOR("Matthias Fuchs <socketcan@esd.eu>");
MODULE_AUTHOR("Frank Jungclaus <frank.jungclaus@esd.eu>");
@@ -22,95 +23,87 @@ MODULE_DESCRIPTION("CAN driver for esd electronics gmbh CAN-USB/2 and CAN-USB/Mi
MODULE_LICENSE("GPL v2");
/* USB vendor and product ID */
-#define USB_ESDGMBH_VENDOR_ID 0x0ab4
-#define USB_CANUSB2_PRODUCT_ID 0x0010
-#define USB_CANUSBM_PRODUCT_ID 0x0011
+#define ESD_USB_ESDGMBH_VENDOR_ID 0x0ab4
+#define ESD_USB_CANUSB2_PRODUCT_ID 0x0010
+#define ESD_USB_CANUSBM_PRODUCT_ID 0x0011
/* CAN controller clock frequencies */
-#define ESD_USB2_CAN_CLOCK 60000000
-#define ESD_USBM_CAN_CLOCK 36000000
+#define ESD_USB_2_CAN_CLOCK (60 * MEGA) /* Hz */
+#define ESD_USB_M_CAN_CLOCK (36 * MEGA) /* Hz */
/* Maximum number of CAN nets */
#define ESD_USB_MAX_NETS 2
/* USB commands */
-#define CMD_VERSION 1 /* also used for VERSION_REPLY */
-#define CMD_CAN_RX 2 /* device to host only */
-#define CMD_CAN_TX 3 /* also used for TX_DONE */
-#define CMD_SETBAUD 4 /* also used for SETBAUD_REPLY */
-#define CMD_TS 5 /* also used for TS_REPLY */
-#define CMD_IDADD 6 /* also used for IDADD_REPLY */
+#define ESD_USB_CMD_VERSION 1 /* also used for VERSION_REPLY */
+#define ESD_USB_CMD_CAN_RX 2 /* device to host only */
+#define ESD_USB_CMD_CAN_TX 3 /* also used for TX_DONE */
+#define ESD_USB_CMD_SETBAUD 4 /* also used for SETBAUD_REPLY */
+#define ESD_USB_CMD_TS 5 /* also used for TS_REPLY */
+#define ESD_USB_CMD_IDADD 6 /* also used for IDADD_REPLY */
/* esd CAN message flags - dlc field */
-#define ESD_RTR 0x10
+#define ESD_USB_RTR BIT(4)
/* esd CAN message flags - id field */
-#define ESD_EXTID 0x20000000
-#define ESD_EVENT 0x40000000
-#define ESD_IDMASK 0x1fffffff
+#define ESD_USB_EXTID BIT(29)
+#define ESD_USB_EVENT BIT(30)
+#define ESD_USB_IDMASK GENMASK(28, 0)
/* esd CAN event ids */
-#define ESD_EV_CAN_ERROR_EXT 2 /* CAN controller specific diagnostic data */
+#define ESD_USB_EV_CAN_ERROR_EXT 2 /* CAN controller specific diagnostic data */
/* baudrate message flags */
-#define ESD_USB_UBR 0x80000000
-#define ESD_USB_LOM 0x40000000
-#define ESD_USB_NO_BAUDRATE 0x7fffffff
-
-/* bit timing CAN-USB/2 */
-#define ESD_USB2_TSEG1_MIN 1
-#define ESD_USB2_TSEG1_MAX 16
-#define ESD_USB2_TSEG1_SHIFT 16
-#define ESD_USB2_TSEG2_MIN 1
-#define ESD_USB2_TSEG2_MAX 8
-#define ESD_USB2_TSEG2_SHIFT 20
-#define ESD_USB2_SJW_MAX 4
-#define ESD_USB2_SJW_SHIFT 14
-#define ESD_USBM_SJW_SHIFT 24
-#define ESD_USB2_BRP_MIN 1
-#define ESD_USB2_BRP_MAX 1024
-#define ESD_USB2_BRP_INC 1
-#define ESD_USB2_3_SAMPLES 0x00800000
+#define ESD_USB_LOM BIT(30) /* Listen Only Mode */
+#define ESD_USB_UBR BIT(31) /* User Bit Rate (controller BTR) in bits 0..27 */
+#define ESD_USB_NO_BAUDRATE GENMASK(30, 0) /* bit rate unconfigured */
+
+/* bit timing esd CAN-USB */
+#define ESD_USB_2_TSEG1_SHIFT 16
+#define ESD_USB_2_TSEG2_SHIFT 20
+#define ESD_USB_2_SJW_SHIFT 14
+#define ESD_USB_M_SJW_SHIFT 24
+#define ESD_USB_TRIPLE_SAMPLES BIT(23)
/* esd IDADD message */
-#define ESD_ID_ENABLE 0x80
-#define ESD_MAX_ID_SEGMENT 64
+#define ESD_USB_ID_ENABLE BIT(7)
+#define ESD_USB_MAX_ID_SEGMENT 64
/* SJA1000 ECC register (emulated by usb firmware) */
-#define SJA1000_ECC_SEG 0x1F
-#define SJA1000_ECC_DIR 0x20
-#define SJA1000_ECC_ERR 0x06
-#define SJA1000_ECC_BIT 0x00
-#define SJA1000_ECC_FORM 0x40
-#define SJA1000_ECC_STUFF 0x80
-#define SJA1000_ECC_MASK 0xc0
+#define ESD_USB_SJA1000_ECC_SEG GENMASK(4, 0)
+#define ESD_USB_SJA1000_ECC_DIR BIT(5)
+#define ESD_USB_SJA1000_ECC_ERR BIT(2, 1)
+#define ESD_USB_SJA1000_ECC_BIT 0x00
+#define ESD_USB_SJA1000_ECC_FORM BIT(6)
+#define ESD_USB_SJA1000_ECC_STUFF BIT(7)
+#define ESD_USB_SJA1000_ECC_MASK GENMASK(7, 6)
/* esd bus state event codes */
-#define ESD_BUSSTATE_MASK 0xc0
-#define ESD_BUSSTATE_WARN 0x40
-#define ESD_BUSSTATE_ERRPASSIVE 0x80
-#define ESD_BUSSTATE_BUSOFF 0xc0
+#define ESD_USB_BUSSTATE_MASK GENMASK(7, 6)
+#define ESD_USB_BUSSTATE_WARN BIT(6)
+#define ESD_USB_BUSSTATE_ERRPASSIVE BIT(7)
+#define ESD_USB_BUSSTATE_BUSOFF GENMASK(7, 6)
-#define RX_BUFFER_SIZE 1024
-#define MAX_RX_URBS 4
-#define MAX_TX_URBS 16 /* must be power of 2 */
+#define ESD_USB_RX_BUFFER_SIZE 1024
+#define ESD_USB_MAX_RX_URBS 4
+#define ESD_USB_MAX_TX_URBS 16 /* must be power of 2 */
-struct header_msg {
- u8 len; /* len is always the total message length in 32bit words */
+struct esd_usb_header_msg {
+ u8 len; /* total message length in 32bit words */
u8 cmd;
u8 rsvd[2];
};
-struct version_msg {
- u8 len;
+struct esd_usb_version_msg {
+ u8 len; /* total message length in 32bit words */
u8 cmd;
u8 rsvd;
u8 flags;
__le32 drv_version;
};
-struct version_reply_msg {
- u8 len;
+struct esd_usb_version_reply_msg {
+ u8 len; /* total message length in 32bit words */
u8 cmd;
u8 nets;
u8 features;
@@ -120,15 +113,15 @@ struct version_reply_msg {
__le32 ts;
};
-struct rx_msg {
- u8 len;
+struct esd_usb_rx_msg {
+ u8 len; /* total message length in 32bit words */
u8 cmd;
u8 net;
u8 dlc;
__le32 ts;
__le32 id; /* upper 3 bits contain flags */
union {
- u8 data[8];
+ u8 data[CAN_MAX_DLEN];
struct {
u8 status; /* CAN Controller Status */
u8 ecc; /* Error Capture Register */
@@ -138,18 +131,18 @@ struct rx_msg {
};
};
-struct tx_msg {
- u8 len;
+struct esd_usb_tx_msg {
+ u8 len; /* total message length in 32bit words */
u8 cmd;
u8 net;
u8 dlc;
u32 hnd; /* opaque handle, not used by device */
__le32 id; /* upper 3 bits contain flags */
- u8 data[8];
+ u8 data[CAN_MAX_DLEN];
};
-struct tx_done_msg {
- u8 len;
+struct esd_usb_tx_done_msg {
+ u8 len; /* total message length in 32bit words */
u8 cmd;
u8 net;
u8 status;
@@ -157,16 +150,16 @@ struct tx_done_msg {
__le32 ts;
};
-struct id_filter_msg {
- u8 len;
+struct esd_usb_id_filter_msg {
+ u8 len; /* total message length in 32bit words */
u8 cmd;
u8 net;
u8 option;
- __le32 mask[ESD_MAX_ID_SEGMENT + 1];
+ __le32 mask[ESD_USB_MAX_ID_SEGMENT + 1]; /* +1 for 29bit extended IDs */
};
-struct set_baudrate_msg {
- u8 len;
+struct esd_usb_set_baudrate_msg {
+ u8 len; /* total message length in 32bit words */
u8 cmd;
u8 net;
u8 rsvd;
@@ -175,19 +168,19 @@ struct set_baudrate_msg {
/* Main message type used between library and application */
union __packed esd_usb_msg {
- struct header_msg hdr;
- struct version_msg version;
- struct version_reply_msg version_reply;
- struct rx_msg rx;
- struct tx_msg tx;
- struct tx_done_msg txdone;
- struct set_baudrate_msg setbaud;
- struct id_filter_msg filter;
+ struct esd_usb_header_msg hdr;
+ struct esd_usb_version_msg version;
+ struct esd_usb_version_reply_msg version_reply;
+ struct esd_usb_rx_msg rx;
+ struct esd_usb_tx_msg tx;
+ struct esd_usb_tx_done_msg txdone;
+ struct esd_usb_set_baudrate_msg setbaud;
+ struct esd_usb_id_filter_msg filter;
};
static struct usb_device_id esd_usb_table[] = {
- {USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSB2_PRODUCT_ID)},
- {USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSBM_PRODUCT_ID)},
+ {USB_DEVICE(ESD_USB_ESDGMBH_VENDOR_ID, ESD_USB_CANUSB2_PRODUCT_ID)},
+ {USB_DEVICE(ESD_USB_ESDGMBH_VENDOR_ID, ESD_USB_CANUSBM_PRODUCT_ID)},
{}
};
MODULE_DEVICE_TABLE(usb, esd_usb_table);
@@ -208,8 +201,8 @@ struct esd_usb {
int net_count;
u32 version;
int rxinitdone;
- void *rxbuf[MAX_RX_URBS];
- dma_addr_t rxbuf_dma[MAX_RX_URBS];
+ void *rxbuf[ESD_USB_MAX_RX_URBS];
+ dma_addr_t rxbuf_dma[ESD_USB_MAX_RX_URBS];
};
struct esd_usb_net_priv {
@@ -217,7 +210,7 @@ struct esd_usb_net_priv {
atomic_t active_tx_jobs;
struct usb_anchor tx_submitted;
- struct esd_tx_urb_context tx_contexts[MAX_TX_URBS];
+ struct esd_tx_urb_context tx_contexts[ESD_USB_MAX_TX_URBS];
struct esd_usb *usb;
struct net_device *netdev;
@@ -232,9 +225,9 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv,
struct net_device_stats *stats = &priv->netdev->stats;
struct can_frame *cf;
struct sk_buff *skb;
- u32 id = le32_to_cpu(msg->rx.id) & ESD_IDMASK;
+ u32 id = le32_to_cpu(msg->rx.id) & ESD_USB_IDMASK;
- if (id == ESD_EV_CAN_ERROR_EXT) {
+ if (id == ESD_USB_EV_CAN_ERROR_EXT) {
u8 state = msg->rx.ev_can_err_ext.status;
u8 ecc = msg->rx.ev_can_err_ext.ecc;
@@ -261,15 +254,15 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv,
priv->old_state = state;
- switch (state & ESD_BUSSTATE_MASK) {
- case ESD_BUSSTATE_BUSOFF:
+ switch (state & ESD_USB_BUSSTATE_MASK) {
+ case ESD_USB_BUSSTATE_BUSOFF:
new_state = CAN_STATE_BUS_OFF;
can_bus_off(priv->netdev);
break;
- case ESD_BUSSTATE_WARN:
+ case ESD_USB_BUSSTATE_WARN:
new_state = CAN_STATE_ERROR_WARNING;
break;
- case ESD_BUSSTATE_ERRPASSIVE:
+ case ESD_USB_BUSSTATE_ERRPASSIVE:
new_state = CAN_STATE_ERROR_PASSIVE;
break;
default:
@@ -291,14 +284,14 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv,
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
- switch (ecc & SJA1000_ECC_MASK) {
- case SJA1000_ECC_BIT:
+ switch (ecc & ESD_USB_SJA1000_ECC_MASK) {
+ case ESD_USB_SJA1000_ECC_BIT:
cf->data[2] |= CAN_ERR_PROT_BIT;
break;
- case SJA1000_ECC_FORM:
+ case ESD_USB_SJA1000_ECC_FORM:
cf->data[2] |= CAN_ERR_PROT_FORM;
break;
- case SJA1000_ECC_STUFF:
+ case ESD_USB_SJA1000_ECC_STUFF:
cf->data[2] |= CAN_ERR_PROT_STUFF;
break;
default:
@@ -306,11 +299,11 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv,
}
/* Error occurred during transmission? */
- if (!(ecc & SJA1000_ECC_DIR))
+ if (!(ecc & ESD_USB_SJA1000_ECC_DIR))
cf->data[2] |= CAN_ERR_PROT_TX;
/* Bit stream position in CAN frame as the error was detected */
- cf->data[3] = ecc & SJA1000_ECC_SEG;
+ cf->data[3] = ecc & ESD_USB_SJA1000_ECC_SEG;
}
if (skb) {
@@ -337,7 +330,7 @@ static void esd_usb_rx_can_msg(struct esd_usb_net_priv *priv,
id = le32_to_cpu(msg->rx.id);
- if (id & ESD_EVENT) {
+ if (id & ESD_USB_EVENT) {
esd_usb_rx_event(priv, msg);
} else {
skb = alloc_can_skb(priv->netdev, &cf);
@@ -346,14 +339,14 @@ static void esd_usb_rx_can_msg(struct esd_usb_net_priv *priv,
return;
}
- cf->can_id = id & ESD_IDMASK;
- can_frame_set_cc_len(cf, msg->rx.dlc & ~ESD_RTR,
+ cf->can_id = id & ESD_USB_IDMASK;
+ can_frame_set_cc_len(cf, msg->rx.dlc & ~ESD_USB_RTR,
priv->can.ctrlmode);
- if (id & ESD_EXTID)
+ if (id & ESD_USB_EXTID)
cf->can_id |= CAN_EFF_FLAG;
- if (msg->rx.dlc & ESD_RTR) {
+ if (msg->rx.dlc & ESD_USB_RTR) {
cf->can_id |= CAN_RTR_FLAG;
} else {
for (i = 0; i < cf->len; i++)
@@ -377,7 +370,7 @@ static void esd_usb_tx_done_msg(struct esd_usb_net_priv *priv,
if (!netif_device_present(netdev))
return;
- context = &priv->tx_contexts[msg->txdone.hnd & (MAX_TX_URBS - 1)];
+ context = &priv->tx_contexts[msg->txdone.hnd & (ESD_USB_MAX_TX_URBS - 1)];
if (!msg->txdone.status) {
stats->tx_packets++;
@@ -389,7 +382,7 @@ static void esd_usb_tx_done_msg(struct esd_usb_net_priv *priv,
}
/* Release context */
- context->echo_index = MAX_TX_URBS;
+ context->echo_index = ESD_USB_MAX_TX_URBS;
atomic_dec(&priv->active_tx_jobs);
netif_wake_queue(netdev);
@@ -424,7 +417,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb)
msg = (union esd_usb_msg *)(urb->transfer_buffer + pos);
switch (msg->hdr.cmd) {
- case CMD_CAN_RX:
+ case ESD_USB_CMD_CAN_RX:
if (msg->rx.net >= dev->net_count) {
dev_err(dev->udev->dev.parent, "format error\n");
break;
@@ -433,7 +426,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb)
esd_usb_rx_can_msg(dev->nets[msg->rx.net], msg);
break;
- case CMD_CAN_TX:
+ case ESD_USB_CMD_CAN_TX:
if (msg->txdone.net >= dev->net_count) {
dev_err(dev->udev->dev.parent, "format error\n");
break;
@@ -444,7 +437,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb)
break;
}
- pos += msg->hdr.len << 2;
+ pos += msg->hdr.len * sizeof(u32); /* convert to # of bytes */
if (pos > urb->actual_length) {
dev_err(dev->udev->dev.parent, "format error\n");
@@ -454,7 +447,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb)
resubmit_urb:
usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
- urb->transfer_buffer, RX_BUFFER_SIZE,
+ urb->transfer_buffer, ESD_USB_RX_BUFFER_SIZE,
esd_usb_read_bulk_callback, dev);
retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -538,7 +531,7 @@ static int esd_usb_send_msg(struct esd_usb *dev, union esd_usb_msg *msg)
return usb_bulk_msg(dev->udev,
usb_sndbulkpipe(dev->udev, 2),
msg,
- msg->hdr.len << 2,
+ msg->hdr.len * sizeof(u32), /* convert to # of bytes */
&actual_length,
1000);
}
@@ -563,7 +556,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev)
if (dev->rxinitdone)
return 0;
- for (i = 0; i < MAX_RX_URBS; i++) {
+ for (i = 0; i < ESD_USB_MAX_RX_URBS; i++) {
struct urb *urb = NULL;
u8 *buf = NULL;
dma_addr_t buf_dma;
@@ -575,7 +568,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev)
break;
}
- buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL,
+ buf = usb_alloc_coherent(dev->udev, ESD_USB_RX_BUFFER_SIZE, GFP_KERNEL,
&buf_dma);
if (!buf) {
dev_warn(dev->udev->dev.parent,
@@ -588,7 +581,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev)
usb_fill_bulk_urb(urb, dev->udev,
usb_rcvbulkpipe(dev->udev, 1),
- buf, RX_BUFFER_SIZE,
+ buf, ESD_USB_RX_BUFFER_SIZE,
esd_usb_read_bulk_callback, dev);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
usb_anchor_urb(urb, &dev->rx_submitted);
@@ -596,7 +589,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev)
err = usb_submit_urb(urb, GFP_KERNEL);
if (err) {
usb_unanchor_urb(urb);
- usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
+ usb_free_coherent(dev->udev, ESD_USB_RX_BUFFER_SIZE, buf,
urb->transfer_dma);
goto freeurb;
}
@@ -618,7 +611,7 @@ freeurb:
}
/* Warn if we've couldn't transmit all the URBs */
- if (i < MAX_RX_URBS) {
+ if (i < ESD_USB_MAX_RX_URBS) {
dev_warn(dev->udev->dev.parent,
"rx performance may be slow\n");
}
@@ -653,14 +646,14 @@ static int esd_usb_start(struct esd_usb_net_priv *priv)
* the number of the starting bitmask (0..64) to the filter.option
* field followed by only some bitmasks.
*/
- msg->hdr.cmd = CMD_IDADD;
- msg->hdr.len = 2 + ESD_MAX_ID_SEGMENT;
+ msg->hdr.cmd = ESD_USB_CMD_IDADD;
+ msg->hdr.len = sizeof(struct esd_usb_id_filter_msg) / sizeof(u32); /* # of 32bit words */
msg->filter.net = priv->index;
- msg->filter.option = ESD_ID_ENABLE; /* start with segment 0 */
- for (i = 0; i < ESD_MAX_ID_SEGMENT; i++)
- msg->filter.mask[i] = cpu_to_le32(0xffffffff);
+ msg->filter.option = ESD_USB_ID_ENABLE; /* start with segment 0 */
+ for (i = 0; i < ESD_USB_MAX_ID_SEGMENT; i++)
+ msg->filter.mask[i] = cpu_to_le32(GENMASK(31, 0));
/* enable 29bit extended IDs */
- msg->filter.mask[ESD_MAX_ID_SEGMENT] = cpu_to_le32(0x00000001);
+ msg->filter.mask[ESD_USB_MAX_ID_SEGMENT] = cpu_to_le32(BIT(0));
err = esd_usb_send_msg(dev, msg);
if (err)
@@ -689,8 +682,8 @@ static void unlink_all_urbs(struct esd_usb *dev)
usb_kill_anchored_urbs(&dev->rx_submitted);
- for (i = 0; i < MAX_RX_URBS; ++i)
- usb_free_coherent(dev->udev, RX_BUFFER_SIZE,
+ for (i = 0; i < ESD_USB_MAX_RX_URBS; ++i)
+ usb_free_coherent(dev->udev, ESD_USB_RX_BUFFER_SIZE,
dev->rxbuf[i], dev->rxbuf_dma[i]);
for (i = 0; i < dev->net_count; i++) {
@@ -699,8 +692,8 @@ static void unlink_all_urbs(struct esd_usb *dev)
usb_kill_anchored_urbs(&priv->tx_submitted);
atomic_set(&priv->active_tx_jobs, 0);
- for (j = 0; j < MAX_TX_URBS; j++)
- priv->tx_contexts[j].echo_index = MAX_TX_URBS;
+ for (j = 0; j < ESD_USB_MAX_TX_URBS; j++)
+ priv->tx_contexts[j].echo_index = ESD_USB_MAX_TX_URBS;
}
}
}
@@ -765,25 +758,27 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb,
msg = (union esd_usb_msg *)buf;
- msg->hdr.len = 3; /* minimal length */
- msg->hdr.cmd = CMD_CAN_TX;
+ /* minimal length as # of 32bit words */
+ msg->hdr.len = offsetof(struct esd_usb_tx_msg, data) / sizeof(u32);
+ msg->hdr.cmd = ESD_USB_CMD_CAN_TX;
msg->tx.net = priv->index;
msg->tx.dlc = can_get_cc_dlc(cf, priv->can.ctrlmode);
msg->tx.id = cpu_to_le32(cf->can_id & CAN_ERR_MASK);
if (cf->can_id & CAN_RTR_FLAG)
- msg->tx.dlc |= ESD_RTR;
+ msg->tx.dlc |= ESD_USB_RTR;
if (cf->can_id & CAN_EFF_FLAG)
- msg->tx.id |= cpu_to_le32(ESD_EXTID);
+ msg->tx.id |= cpu_to_le32(ESD_USB_EXTID);
for (i = 0; i < cf->len; i++)
msg->tx.data[i] = cf->data[i];
- msg->hdr.len += (cf->len + 3) >> 2;
+ /* round up, then divide by 4 to add the payload length as # of 32bit words */
+ msg->hdr.len += DIV_ROUND_UP(cf->len, sizeof(u32));
- for (i = 0; i < MAX_TX_URBS; i++) {
- if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) {
+ for (i = 0; i < ESD_USB_MAX_TX_URBS; i++) {
+ if (priv->tx_contexts[i].echo_index == ESD_USB_MAX_TX_URBS) {
context = &priv->tx_contexts[i];
break;
}
@@ -800,10 +795,10 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb,
context->echo_index = i;
/* hnd must not be 0 - MSB is stripped in txdone handling */
- msg->tx.hnd = 0x80000000 | i; /* returned in TX done message */
+ msg->tx.hnd = BIT(31) | i; /* returned in TX done message */
usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), buf,
- msg->hdr.len << 2,
+ msg->hdr.len * sizeof(u32), /* convert to # of bytes */
esd_usb_write_bulk_callback, context);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -815,7 +810,7 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb,
atomic_inc(&priv->active_tx_jobs);
/* Slow down tx path */
- if (atomic_read(&priv->active_tx_jobs) >= MAX_TX_URBS)
+ if (atomic_read(&priv->active_tx_jobs) >= ESD_USB_MAX_TX_URBS)
netif_stop_queue(netdev);
err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -865,18 +860,18 @@ static int esd_usb_close(struct net_device *netdev)
return -ENOMEM;
/* Disable all IDs (see esd_usb_start()) */
- msg->hdr.cmd = CMD_IDADD;
- msg->hdr.len = 2 + ESD_MAX_ID_SEGMENT;
+ msg->hdr.cmd = ESD_USB_CMD_IDADD;
+ msg->hdr.len = sizeof(struct esd_usb_id_filter_msg) / sizeof(u32);/* # of 32bit words */
msg->filter.net = priv->index;
- msg->filter.option = ESD_ID_ENABLE; /* start with segment 0 */
- for (i = 0; i <= ESD_MAX_ID_SEGMENT; i++)
+ msg->filter.option = ESD_USB_ID_ENABLE; /* start with segment 0 */
+ for (i = 0; i <= ESD_USB_MAX_ID_SEGMENT; i++)
msg->filter.mask[i] = 0;
if (esd_usb_send_msg(priv->usb, msg) < 0)
netdev_err(netdev, "sending idadd message failed\n");
/* set CAN controller to reset mode */
- msg->hdr.len = 2;
- msg->hdr.cmd = CMD_SETBAUD;
+ msg->hdr.len = sizeof(struct esd_usb_set_baudrate_msg) / sizeof(u32); /* # of 32bit words */
+ msg->hdr.cmd = ESD_USB_CMD_SETBAUD;
msg->setbaud.net = priv->index;
msg->setbaud.rsvd = 0;
msg->setbaud.baud = cpu_to_le32(ESD_USB_NO_BAUDRATE);
@@ -905,20 +900,21 @@ static const struct ethtool_ops esd_usb_ethtool_ops = {
.get_ts_info = ethtool_op_get_ts_info,
};
-static const struct can_bittiming_const esd_usb2_bittiming_const = {
- .name = "esd_usb2",
- .tseg1_min = ESD_USB2_TSEG1_MIN,
- .tseg1_max = ESD_USB2_TSEG1_MAX,
- .tseg2_min = ESD_USB2_TSEG2_MIN,
- .tseg2_max = ESD_USB2_TSEG2_MAX,
- .sjw_max = ESD_USB2_SJW_MAX,
- .brp_min = ESD_USB2_BRP_MIN,
- .brp_max = ESD_USB2_BRP_MAX,
- .brp_inc = ESD_USB2_BRP_INC,
+static const struct can_bittiming_const esd_usb_2_bittiming_const = {
+ .name = "esd_usb_2",
+ .tseg1_min = 1,
+ .tseg1_max = 16,
+ .tseg2_min = 1,
+ .tseg2_max = 8,
+ .sjw_max = 4,
+ .brp_min = 1,
+ .brp_max = 1024,
+ .brp_inc = 1,
};
-static int esd_usb2_set_bittiming(struct net_device *netdev)
+static int esd_usb_2_set_bittiming(struct net_device *netdev)
{
+ const struct can_bittiming_const *btc = &esd_usb_2_bittiming_const;
struct esd_usb_net_priv *priv = netdev_priv(netdev);
struct can_bittiming *bt = &priv->can.bittiming;
union esd_usb_msg *msg;
@@ -930,35 +926,35 @@ static int esd_usb2_set_bittiming(struct net_device *netdev)
if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
canbtr |= ESD_USB_LOM;
- canbtr |= (bt->brp - 1) & (ESD_USB2_BRP_MAX - 1);
+ canbtr |= (bt->brp - 1) & (btc->brp_max - 1);
if (le16_to_cpu(priv->usb->udev->descriptor.idProduct) ==
- USB_CANUSBM_PRODUCT_ID)
- sjw_shift = ESD_USBM_SJW_SHIFT;
+ ESD_USB_CANUSBM_PRODUCT_ID)
+ sjw_shift = ESD_USB_M_SJW_SHIFT;
else
- sjw_shift = ESD_USB2_SJW_SHIFT;
+ sjw_shift = ESD_USB_2_SJW_SHIFT;
- canbtr |= ((bt->sjw - 1) & (ESD_USB2_SJW_MAX - 1))
+ canbtr |= ((bt->sjw - 1) & (btc->sjw_max - 1))
<< sjw_shift;
canbtr |= ((bt->prop_seg + bt->phase_seg1 - 1)
- & (ESD_USB2_TSEG1_MAX - 1))
- << ESD_USB2_TSEG1_SHIFT;
- canbtr |= ((bt->phase_seg2 - 1) & (ESD_USB2_TSEG2_MAX - 1))
- << ESD_USB2_TSEG2_SHIFT;
+ & (btc->tseg1_max - 1))
+ << ESD_USB_2_TSEG1_SHIFT;
+ canbtr |= ((bt->phase_seg2 - 1) & (btc->tseg2_max - 1))
+ << ESD_USB_2_TSEG2_SHIFT;
if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
- canbtr |= ESD_USB2_3_SAMPLES;
+ canbtr |= ESD_USB_TRIPLE_SAMPLES;
msg = kmalloc(sizeof(*msg), GFP_KERNEL);
if (!msg)
return -ENOMEM;
- msg->hdr.len = 2;
- msg->hdr.cmd = CMD_SETBAUD;
+ msg->hdr.len = sizeof(struct esd_usb_set_baudrate_msg) / sizeof(u32); /* # of 32bit words */
+ msg->hdr.cmd = ESD_USB_CMD_SETBAUD;
msg->setbaud.net = priv->index;
msg->setbaud.rsvd = 0;
msg->setbaud.baud = cpu_to_le32(canbtr);
- netdev_info(netdev, "setting BTR=%#x\n", canbtr);
+ netdev_dbg(netdev, "setting BTR=%#x\n", canbtr);
err = esd_usb_send_msg(priv->usb, msg);
@@ -999,7 +995,7 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index)
int err = 0;
int i;
- netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS);
+ netdev = alloc_candev(sizeof(*priv), ESD_USB_MAX_TX_URBS);
if (!netdev) {
dev_err(&intf->dev, "couldn't alloc candev\n");
err = -ENOMEM;
@@ -1011,8 +1007,8 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index)
init_usb_anchor(&priv->tx_submitted);
atomic_set(&priv->active_tx_jobs, 0);
- for (i = 0; i < MAX_TX_URBS; i++)
- priv->tx_contexts[i].echo_index = MAX_TX_URBS;
+ for (i = 0; i < ESD_USB_MAX_TX_URBS; i++)
+ priv->tx_contexts[i].echo_index = ESD_USB_MAX_TX_URBS;
priv->usb = dev;
priv->netdev = netdev;
@@ -1024,15 +1020,15 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index)
CAN_CTRLMODE_BERR_REPORTING;
if (le16_to_cpu(dev->udev->descriptor.idProduct) ==
- USB_CANUSBM_PRODUCT_ID)
- priv->can.clock.freq = ESD_USBM_CAN_CLOCK;
+ ESD_USB_CANUSBM_PRODUCT_ID)
+ priv->can.clock.freq = ESD_USB_M_CAN_CLOCK;
else {
- priv->can.clock.freq = ESD_USB2_CAN_CLOCK;
+ priv->can.clock.freq = ESD_USB_2_CAN_CLOCK;
priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
}
- priv->can.bittiming_const = &esd_usb2_bittiming_const;
- priv->can.do_set_bittiming = esd_usb2_set_bittiming;
+ priv->can.bittiming_const = &esd_usb_2_bittiming_const;
+ priv->can.do_set_bittiming = esd_usb_2_set_bittiming;
priv->can.do_set_mode = esd_usb_set_mode;
priv->can.do_get_berr_counter = esd_usb_get_berr_counter;
@@ -1090,8 +1086,8 @@ static int esd_usb_probe(struct usb_interface *intf,
}
/* query number of CAN interfaces (nets) */
- msg->hdr.cmd = CMD_VERSION;
- msg->hdr.len = 2;
+ msg->hdr.cmd = ESD_USB_CMD_VERSION;
+ msg->hdr.len = sizeof(struct esd_usb_version_msg) / sizeof(u32); /* # of 32bit words */
msg->version.rsvd = 0;
msg->version.flags = 0;
msg->version.drv_version = 0;
diff --git a/drivers/net/can/usb/f81604.c b/drivers/net/can/usb/f81604.c
new file mode 100644
index 000000000000..ec8cef7fd2d5
--- /dev/null
+++ b/drivers/net/can/usb/f81604.c
@@ -0,0 +1,1201 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Fintek F81604 USB-to-2CAN controller driver.
+ *
+ * Copyright (C) 2023 Ji-Ze Hong (Peter Hong) <peter_hong@fintek.com.tw>
+ */
+#include <linux/bitfield.h>
+#include <linux/netdevice.h>
+#include <linux/units.h>
+#include <linux/usb.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+#include <linux/can/platform/sja1000.h>
+
+#include <asm-generic/unaligned.h>
+
+/* vendor and product id */
+#define F81604_VENDOR_ID 0x2c42
+#define F81604_PRODUCT_ID 0x1709
+#define F81604_CAN_CLOCK (12 * MEGA)
+#define F81604_MAX_DEV 2
+#define F81604_SET_DEVICE_RETRY 10
+
+#define F81604_USB_TIMEOUT 2000
+#define F81604_SET_GET_REGISTER 0xA0
+#define F81604_PORT_OFFSET 0x1000
+#define F81604_MAX_RX_URBS 4
+
+#define F81604_CMD_DATA 0x00
+
+#define F81604_DLC_LEN_MASK GENMASK(3, 0)
+#define F81604_DLC_EFF_BIT BIT(7)
+#define F81604_DLC_RTR_BIT BIT(6)
+
+#define F81604_SFF_SHIFT 5
+#define F81604_EFF_SHIFT 3
+
+#define F81604_BRP_MASK GENMASK(5, 0)
+#define F81604_SJW_MASK GENMASK(7, 6)
+
+#define F81604_SEG1_MASK GENMASK(3, 0)
+#define F81604_SEG2_MASK GENMASK(6, 4)
+
+#define F81604_CLEAR_ALC 0
+#define F81604_CLEAR_ECC 1
+#define F81604_CLEAR_OVERRUN 2
+
+/* device setting */
+#define F81604_CTRL_MODE_REG 0x80
+#define F81604_TX_ONESHOT (0x03 << 3)
+#define F81604_TX_NORMAL (0x01 << 3)
+#define F81604_RX_AUTO_RELEASE_BUF BIT(1)
+#define F81604_INT_WHEN_CHANGE BIT(0)
+
+#define F81604_TERMINATOR_REG 0x105
+#define F81604_CAN0_TERM BIT(2)
+#define F81604_CAN1_TERM BIT(3)
+
+#define F81604_TERMINATION_DISABLED CAN_TERMINATION_DISABLED
+#define F81604_TERMINATION_ENABLED 120
+
+/* SJA1000 registers - manual section 6.4 (Pelican Mode) */
+#define F81604_SJA1000_MOD 0x00
+#define F81604_SJA1000_CMR 0x01
+#define F81604_SJA1000_IR 0x03
+#define F81604_SJA1000_IER 0x04
+#define F81604_SJA1000_ALC 0x0B
+#define F81604_SJA1000_ECC 0x0C
+#define F81604_SJA1000_RXERR 0x0E
+#define F81604_SJA1000_TXERR 0x0F
+#define F81604_SJA1000_ACCC0 0x10
+#define F81604_SJA1000_ACCM0 0x14
+#define F81604_MAX_FILTER_CNT 4
+
+/* Common registers - manual section 6.5 */
+#define F81604_SJA1000_BTR0 0x06
+#define F81604_SJA1000_BTR1 0x07
+#define F81604_SJA1000_BTR1_SAMPLE_TRIPLE BIT(7)
+#define F81604_SJA1000_OCR 0x08
+#define F81604_SJA1000_CDR 0x1F
+
+/* mode register */
+#define F81604_SJA1000_MOD_RM 0x01
+#define F81604_SJA1000_MOD_LOM 0x02
+#define F81604_SJA1000_MOD_STM 0x04
+
+/* commands */
+#define F81604_SJA1000_CMD_CDO 0x08
+
+/* interrupt sources */
+#define F81604_SJA1000_IRQ_BEI 0x80
+#define F81604_SJA1000_IRQ_ALI 0x40
+#define F81604_SJA1000_IRQ_EPI 0x20
+#define F81604_SJA1000_IRQ_DOI 0x08
+#define F81604_SJA1000_IRQ_EI 0x04
+#define F81604_SJA1000_IRQ_TI 0x02
+#define F81604_SJA1000_IRQ_RI 0x01
+#define F81604_SJA1000_IRQ_ALL 0xFF
+#define F81604_SJA1000_IRQ_OFF 0x00
+
+/* status register content */
+#define F81604_SJA1000_SR_BS 0x80
+#define F81604_SJA1000_SR_ES 0x40
+#define F81604_SJA1000_SR_TCS 0x08
+
+/* ECC register */
+#define F81604_SJA1000_ECC_SEG 0x1F
+#define F81604_SJA1000_ECC_DIR 0x20
+#define F81604_SJA1000_ECC_BIT 0x00
+#define F81604_SJA1000_ECC_FORM 0x40
+#define F81604_SJA1000_ECC_STUFF 0x80
+#define F81604_SJA1000_ECC_MASK 0xc0
+
+/* ALC register */
+#define F81604_SJA1000_ALC_MASK 0x1f
+
+/* table of devices that work with this driver */
+static const struct usb_device_id f81604_table[] = {
+ { USB_DEVICE(F81604_VENDOR_ID, F81604_PRODUCT_ID) },
+ {} /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, f81604_table);
+
+static const struct ethtool_ops f81604_ethtool_ops = {
+ .get_ts_info = ethtool_op_get_ts_info,
+};
+
+static const u16 f81604_termination[] = { F81604_TERMINATION_DISABLED,
+ F81604_TERMINATION_ENABLED };
+
+struct f81604_priv {
+ struct net_device *netdev[F81604_MAX_DEV];
+};
+
+struct f81604_port_priv {
+ struct can_priv can;
+ struct net_device *netdev;
+ struct sk_buff *echo_skb;
+
+ unsigned long clear_flags;
+ struct work_struct clear_reg_work;
+
+ struct usb_device *dev;
+ struct usb_interface *intf;
+
+ struct usb_anchor urbs_anchor;
+};
+
+/* Interrupt endpoint data format:
+ * Byte 0: Status register.
+ * Byte 1: Interrupt register.
+ * Byte 2: Interrupt enable register.
+ * Byte 3: Arbitration lost capture(ALC) register.
+ * Byte 4: Error code capture(ECC) register.
+ * Byte 5: Error warning limit register.
+ * Byte 6: RX error counter register.
+ * Byte 7: TX error counter register.
+ * Byte 8: Reserved.
+ */
+struct f81604_int_data {
+ u8 sr;
+ u8 isrc;
+ u8 ier;
+ u8 alc;
+ u8 ecc;
+ u8 ewlr;
+ u8 rxerr;
+ u8 txerr;
+ u8 val;
+} __packed __aligned(4);
+
+struct f81604_sff {
+ __be16 id;
+ u8 data[CAN_MAX_DLEN];
+} __packed __aligned(2);
+
+struct f81604_eff {
+ __be32 id;
+ u8 data[CAN_MAX_DLEN];
+} __packed __aligned(2);
+
+struct f81604_can_frame {
+ u8 cmd;
+
+ /* According for F81604 DLC define:
+ * bit 3~0: data length (0~8)
+ * bit6: is RTR flag.
+ * bit7: is EFF frame.
+ */
+ u8 dlc;
+
+ union {
+ struct f81604_sff sff;
+ struct f81604_eff eff;
+ };
+} __packed __aligned(2);
+
+static const u8 bulk_in_addr[F81604_MAX_DEV] = { 2, 4 };
+static const u8 bulk_out_addr[F81604_MAX_DEV] = { 1, 3 };
+static const u8 int_in_addr[F81604_MAX_DEV] = { 1, 3 };
+
+static int f81604_write(struct usb_device *dev, u16 reg, u8 data)
+{
+ int ret;
+
+ ret = usb_control_msg_send(dev, 0, F81604_SET_GET_REGISTER,
+ USB_TYPE_VENDOR | USB_DIR_OUT, 0, reg,
+ &data, sizeof(data), F81604_USB_TIMEOUT,
+ GFP_KERNEL);
+ if (ret)
+ dev_err(&dev->dev, "%s: reg: %x data: %x failed: %pe\n",
+ __func__, reg, data, ERR_PTR(ret));
+
+ return ret;
+}
+
+static int f81604_read(struct usb_device *dev, u16 reg, u8 *data)
+{
+ int ret;
+
+ ret = usb_control_msg_recv(dev, 0, F81604_SET_GET_REGISTER,
+ USB_TYPE_VENDOR | USB_DIR_IN, 0, reg, data,
+ sizeof(*data), F81604_USB_TIMEOUT,
+ GFP_KERNEL);
+
+ if (ret < 0)
+ dev_err(&dev->dev, "%s: reg: %x failed: %pe\n", __func__, reg,
+ ERR_PTR(ret));
+
+ return ret;
+}
+
+static int f81604_update_bits(struct usb_device *dev, u16 reg, u8 mask,
+ u8 data)
+{
+ int ret;
+ u8 tmp;
+
+ ret = f81604_read(dev, reg, &tmp);
+ if (ret)
+ return ret;
+
+ tmp &= ~mask;
+ tmp |= (mask & data);
+
+ return f81604_write(dev, reg, tmp);
+}
+
+static int f81604_sja1000_write(struct f81604_port_priv *priv, u16 reg,
+ u8 data)
+{
+ int port = priv->netdev->dev_port;
+ int real_reg;
+
+ real_reg = reg + F81604_PORT_OFFSET * port + F81604_PORT_OFFSET;
+ return f81604_write(priv->dev, real_reg, data);
+}
+
+static int f81604_sja1000_read(struct f81604_port_priv *priv, u16 reg,
+ u8 *data)
+{
+ int port = priv->netdev->dev_port;
+ int real_reg;
+
+ real_reg = reg + F81604_PORT_OFFSET * port + F81604_PORT_OFFSET;
+ return f81604_read(priv->dev, real_reg, data);
+}
+
+static int f81604_set_reset_mode(struct f81604_port_priv *priv)
+{
+ int ret, i;
+ u8 tmp;
+
+ /* disable interrupts */
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_IER,
+ F81604_SJA1000_IRQ_OFF);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < F81604_SET_DEVICE_RETRY; i++) {
+ ret = f81604_sja1000_read(priv, F81604_SJA1000_MOD, &tmp);
+ if (ret)
+ return ret;
+
+ /* check reset bit */
+ if (tmp & F81604_SJA1000_MOD_RM) {
+ priv->can.state = CAN_STATE_STOPPED;
+ return 0;
+ }
+
+ /* reset chip */
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_MOD,
+ F81604_SJA1000_MOD_RM);
+ if (ret)
+ return ret;
+ }
+
+ return -EPERM;
+}
+
+static int f81604_set_normal_mode(struct f81604_port_priv *priv)
+{
+ u8 tmp, ier = 0;
+ u8 mod_reg = 0;
+ int ret, i;
+
+ for (i = 0; i < F81604_SET_DEVICE_RETRY; i++) {
+ ret = f81604_sja1000_read(priv, F81604_SJA1000_MOD, &tmp);
+ if (ret)
+ return ret;
+
+ /* check reset bit */
+ if ((tmp & F81604_SJA1000_MOD_RM) == 0) {
+ priv->can.state = CAN_STATE_ERROR_ACTIVE;
+ /* enable interrupts, RI handled by bulk-in */
+ ier = F81604_SJA1000_IRQ_ALL & ~F81604_SJA1000_IRQ_RI;
+ if (!(priv->can.ctrlmode &
+ CAN_CTRLMODE_BERR_REPORTING))
+ ier &= ~F81604_SJA1000_IRQ_BEI;
+
+ return f81604_sja1000_write(priv, F81604_SJA1000_IER,
+ ier);
+ }
+
+ /* set chip to normal mode */
+ if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+ mod_reg |= F81604_SJA1000_MOD_LOM;
+ if (priv->can.ctrlmode & CAN_CTRLMODE_PRESUME_ACK)
+ mod_reg |= F81604_SJA1000_MOD_STM;
+
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_MOD, mod_reg);
+ if (ret)
+ return ret;
+ }
+
+ return -EPERM;
+}
+
+static int f81604_chipset_init(struct f81604_port_priv *priv)
+{
+ int i, ret;
+
+ /* set clock divider and output control register */
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_CDR,
+ CDR_CBP | CDR_PELICAN);
+ if (ret)
+ return ret;
+
+ /* set acceptance filter (accept all) */
+ for (i = 0; i < F81604_MAX_FILTER_CNT; ++i) {
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_ACCC0 + i, 0);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < F81604_MAX_FILTER_CNT; ++i) {
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_ACCM0 + i,
+ 0xFF);
+ if (ret)
+ return ret;
+ }
+
+ return f81604_sja1000_write(priv, F81604_SJA1000_OCR,
+ OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL |
+ OCR_MODE_NORMAL);
+}
+
+static void f81604_process_rx_packet(struct net_device *netdev,
+ struct f81604_can_frame *frame)
+{
+ struct net_device_stats *stats = &netdev->stats;
+ struct can_frame *cf;
+ struct sk_buff *skb;
+
+ if (frame->cmd != F81604_CMD_DATA)
+ return;
+
+ skb = alloc_can_skb(netdev, &cf);
+ if (!skb) {
+ stats->rx_dropped++;
+ return;
+ }
+
+ cf->len = can_cc_dlc2len(frame->dlc & F81604_DLC_LEN_MASK);
+
+ if (frame->dlc & F81604_DLC_EFF_BIT) {
+ cf->can_id = get_unaligned_be32(&frame->eff.id) >>
+ F81604_EFF_SHIFT;
+ cf->can_id |= CAN_EFF_FLAG;
+
+ if (!(frame->dlc & F81604_DLC_RTR_BIT))
+ memcpy(cf->data, frame->eff.data, cf->len);
+ } else {
+ cf->can_id = get_unaligned_be16(&frame->sff.id) >>
+ F81604_SFF_SHIFT;
+
+ if (!(frame->dlc & F81604_DLC_RTR_BIT))
+ memcpy(cf->data, frame->sff.data, cf->len);
+ }
+
+ if (frame->dlc & F81604_DLC_RTR_BIT)
+ cf->can_id |= CAN_RTR_FLAG;
+ else
+ stats->rx_bytes += cf->len;
+
+ stats->rx_packets++;
+ netif_rx(skb);
+}
+
+static void f81604_read_bulk_callback(struct urb *urb)
+{
+ struct f81604_can_frame *frame = urb->transfer_buffer;
+ struct net_device *netdev = urb->context;
+ int ret;
+
+ if (!netif_device_present(netdev))
+ return;
+
+ if (urb->status)
+ netdev_info(netdev, "%s: URB aborted %pe\n", __func__,
+ ERR_PTR(urb->status));
+
+ switch (urb->status) {
+ case 0: /* success */
+ break;
+
+ case -ENOENT:
+ case -EPIPE:
+ case -EPROTO:
+ case -ESHUTDOWN:
+ return;
+
+ default:
+ goto resubmit_urb;
+ }
+
+ if (urb->actual_length != sizeof(*frame)) {
+ netdev_warn(netdev, "URB length %u not equal to %zu\n",
+ urb->actual_length, sizeof(*frame));
+ goto resubmit_urb;
+ }
+
+ f81604_process_rx_packet(netdev, frame);
+
+resubmit_urb:
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret == -ENODEV)
+ netif_device_detach(netdev);
+ else if (ret)
+ netdev_err(netdev,
+ "%s: failed to resubmit read bulk urb: %pe\n",
+ __func__, ERR_PTR(ret));
+}
+
+static void f81604_handle_tx(struct f81604_port_priv *priv,
+ struct f81604_int_data *data)
+{
+ struct net_device *netdev = priv->netdev;
+ struct net_device_stats *stats = &netdev->stats;
+
+ /* transmission buffer released */
+ if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT &&
+ !(data->sr & F81604_SJA1000_SR_TCS)) {
+ stats->tx_errors++;
+ can_free_echo_skb(netdev, 0, NULL);
+ } else {
+ /* transmission complete */
+ stats->tx_bytes += can_get_echo_skb(netdev, 0, NULL);
+ stats->tx_packets++;
+ }
+
+ netif_wake_queue(netdev);
+}
+
+static void f81604_handle_can_bus_errors(struct f81604_port_priv *priv,
+ struct f81604_int_data *data)
+{
+ enum can_state can_state = priv->can.state;
+ struct net_device *netdev = priv->netdev;
+ struct net_device_stats *stats = &netdev->stats;
+ struct can_frame *cf;
+ struct sk_buff *skb;
+
+ /* Note: ALC/ECC will not auto clear by read here, must be cleared by
+ * read register (via clear_reg_work).
+ */
+
+ skb = alloc_can_err_skb(netdev, &cf);
+ if (skb) {
+ cf->can_id |= CAN_ERR_CNT;
+ cf->data[6] = data->txerr;
+ cf->data[7] = data->rxerr;
+ }
+
+ if (data->isrc & F81604_SJA1000_IRQ_DOI) {
+ /* data overrun interrupt */
+ netdev_dbg(netdev, "data overrun interrupt\n");
+
+ if (skb) {
+ cf->can_id |= CAN_ERR_CRTL;
+ cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+ }
+
+ stats->rx_over_errors++;
+ stats->rx_errors++;
+
+ set_bit(F81604_CLEAR_OVERRUN, &priv->clear_flags);
+ }
+
+ if (data->isrc & F81604_SJA1000_IRQ_EI) {
+ /* error warning interrupt */
+ netdev_dbg(netdev, "error warning interrupt\n");
+
+ if (data->sr & F81604_SJA1000_SR_BS)
+ can_state = CAN_STATE_BUS_OFF;
+ else if (data->sr & F81604_SJA1000_SR_ES)
+ can_state = CAN_STATE_ERROR_WARNING;
+ else
+ can_state = CAN_STATE_ERROR_ACTIVE;
+ }
+
+ if (data->isrc & F81604_SJA1000_IRQ_BEI) {
+ /* bus error interrupt */
+ netdev_dbg(netdev, "bus error interrupt\n");
+
+ priv->can.can_stats.bus_error++;
+ stats->rx_errors++;
+
+ if (skb) {
+ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+
+ /* set error type */
+ switch (data->ecc & F81604_SJA1000_ECC_MASK) {
+ case F81604_SJA1000_ECC_BIT:
+ cf->data[2] |= CAN_ERR_PROT_BIT;
+ break;
+ case F81604_SJA1000_ECC_FORM:
+ cf->data[2] |= CAN_ERR_PROT_FORM;
+ break;
+ case F81604_SJA1000_ECC_STUFF:
+ cf->data[2] |= CAN_ERR_PROT_STUFF;
+ break;
+ default:
+ break;
+ }
+
+ /* set error location */
+ cf->data[3] = data->ecc & F81604_SJA1000_ECC_SEG;
+
+ /* Error occurred during transmission? */
+ if ((data->ecc & F81604_SJA1000_ECC_DIR) == 0)
+ cf->data[2] |= CAN_ERR_PROT_TX;
+ }
+
+ set_bit(F81604_CLEAR_ECC, &priv->clear_flags);
+ }
+
+ if (data->isrc & F81604_SJA1000_IRQ_EPI) {
+ if (can_state == CAN_STATE_ERROR_PASSIVE)
+ can_state = CAN_STATE_ERROR_WARNING;
+ else
+ can_state = CAN_STATE_ERROR_PASSIVE;
+
+ /* error passive interrupt */
+ netdev_dbg(netdev, "error passive interrupt: %d\n", can_state);
+ }
+
+ if (data->isrc & F81604_SJA1000_IRQ_ALI) {
+ /* arbitration lost interrupt */
+ netdev_dbg(netdev, "arbitration lost interrupt\n");
+
+ priv->can.can_stats.arbitration_lost++;
+
+ if (skb) {
+ cf->can_id |= CAN_ERR_LOSTARB;
+ cf->data[0] = data->alc & F81604_SJA1000_ALC_MASK;
+ }
+
+ set_bit(F81604_CLEAR_ALC, &priv->clear_flags);
+ }
+
+ if (can_state != priv->can.state) {
+ enum can_state tx_state, rx_state;
+
+ tx_state = data->txerr >= data->rxerr ? can_state : 0;
+ rx_state = data->txerr <= data->rxerr ? can_state : 0;
+
+ can_change_state(netdev, cf, tx_state, rx_state);
+
+ if (can_state == CAN_STATE_BUS_OFF)
+ can_bus_off(netdev);
+ }
+
+ if (priv->clear_flags)
+ schedule_work(&priv->clear_reg_work);
+
+ if (skb)
+ netif_rx(skb);
+}
+
+static void f81604_read_int_callback(struct urb *urb)
+{
+ struct f81604_int_data *data = urb->transfer_buffer;
+ struct net_device *netdev = urb->context;
+ struct f81604_port_priv *priv;
+ int ret;
+
+ priv = netdev_priv(netdev);
+
+ if (!netif_device_present(netdev))
+ return;
+
+ if (urb->status)
+ netdev_info(netdev, "%s: Int URB aborted: %pe\n", __func__,
+ ERR_PTR(urb->status));
+
+ switch (urb->status) {
+ case 0: /* success */
+ break;
+
+ case -ENOENT:
+ case -EPIPE:
+ case -EPROTO:
+ case -ESHUTDOWN:
+ return;
+
+ default:
+ goto resubmit_urb;
+ }
+
+ /* handle Errors */
+ if (data->isrc & (F81604_SJA1000_IRQ_DOI | F81604_SJA1000_IRQ_EI |
+ F81604_SJA1000_IRQ_BEI | F81604_SJA1000_IRQ_EPI |
+ F81604_SJA1000_IRQ_ALI))
+ f81604_handle_can_bus_errors(priv, data);
+
+ /* handle TX */
+ if (priv->can.state != CAN_STATE_BUS_OFF &&
+ (data->isrc & F81604_SJA1000_IRQ_TI))
+ f81604_handle_tx(priv, data);
+
+resubmit_urb:
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret == -ENODEV)
+ netif_device_detach(netdev);
+ else if (ret)
+ netdev_err(netdev, "%s: failed to resubmit int urb: %pe\n",
+ __func__, ERR_PTR(ret));
+}
+
+static void f81604_unregister_urbs(struct f81604_port_priv *priv)
+{
+ usb_kill_anchored_urbs(&priv->urbs_anchor);
+}
+
+static int f81604_register_urbs(struct f81604_port_priv *priv)
+{
+ struct net_device *netdev = priv->netdev;
+ struct f81604_int_data *int_data;
+ int id = netdev->dev_port;
+ struct urb *int_urb;
+ int rx_urb_cnt;
+ int ret;
+
+ for (rx_urb_cnt = 0; rx_urb_cnt < F81604_MAX_RX_URBS; ++rx_urb_cnt) {
+ struct f81604_can_frame *frame;
+ struct urb *rx_urb;
+
+ rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!rx_urb) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ frame = kmalloc(sizeof(*frame), GFP_KERNEL);
+ if (!frame) {
+ usb_free_urb(rx_urb);
+ ret = -ENOMEM;
+ break;
+ }
+
+ usb_fill_bulk_urb(rx_urb, priv->dev,
+ usb_rcvbulkpipe(priv->dev, bulk_in_addr[id]),
+ frame, sizeof(*frame),
+ f81604_read_bulk_callback, netdev);
+
+ rx_urb->transfer_flags |= URB_FREE_BUFFER;
+ usb_anchor_urb(rx_urb, &priv->urbs_anchor);
+
+ ret = usb_submit_urb(rx_urb, GFP_KERNEL);
+ if (ret) {
+ usb_unanchor_urb(rx_urb);
+ usb_free_urb(rx_urb);
+ break;
+ }
+
+ /* Drop reference, USB core will take care of freeing it */
+ usb_free_urb(rx_urb);
+ }
+
+ if (rx_urb_cnt == 0) {
+ netdev_warn(netdev, "%s: submit rx urb failed: %pe\n",
+ __func__, ERR_PTR(ret));
+
+ goto error;
+ }
+
+ int_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!int_urb) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ int_data = kmalloc(sizeof(*int_data), GFP_KERNEL);
+ if (!int_data) {
+ usb_free_urb(int_urb);
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ usb_fill_int_urb(int_urb, priv->dev,
+ usb_rcvintpipe(priv->dev, int_in_addr[id]), int_data,
+ sizeof(*int_data), f81604_read_int_callback, netdev,
+ 1);
+
+ int_urb->transfer_flags |= URB_FREE_BUFFER;
+ usb_anchor_urb(int_urb, &priv->urbs_anchor);
+
+ ret = usb_submit_urb(int_urb, GFP_KERNEL);
+ if (ret) {
+ usb_unanchor_urb(int_urb);
+ usb_free_urb(int_urb);
+
+ netdev_warn(netdev, "%s: submit int urb failed: %pe\n",
+ __func__, ERR_PTR(ret));
+ goto error;
+ }
+
+ /* Drop reference, USB core will take care of freeing it */
+ usb_free_urb(int_urb);
+
+ return 0;
+
+error:
+ f81604_unregister_urbs(priv);
+ return ret;
+}
+
+static int f81604_start(struct net_device *netdev)
+{
+ struct f81604_port_priv *priv = netdev_priv(netdev);
+ int ret;
+ u8 mode;
+ u8 tmp;
+
+ mode = F81604_RX_AUTO_RELEASE_BUF | F81604_INT_WHEN_CHANGE;
+
+ /* Set TR/AT mode */
+ if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
+ mode |= F81604_TX_ONESHOT;
+ else
+ mode |= F81604_TX_NORMAL;
+
+ ret = f81604_sja1000_write(priv, F81604_CTRL_MODE_REG, mode);
+ if (ret)
+ return ret;
+
+ /* set reset mode */
+ ret = f81604_set_reset_mode(priv);
+ if (ret)
+ return ret;
+
+ ret = f81604_chipset_init(priv);
+ if (ret)
+ return ret;
+
+ /* Clear error counters and error code capture */
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_TXERR, 0);
+ if (ret)
+ return ret;
+
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_RXERR, 0);
+ if (ret)
+ return ret;
+
+ /* Read clear for ECC/ALC/IR register */
+ ret = f81604_sja1000_read(priv, F81604_SJA1000_ECC, &tmp);
+ if (ret)
+ return ret;
+
+ ret = f81604_sja1000_read(priv, F81604_SJA1000_ALC, &tmp);
+ if (ret)
+ return ret;
+
+ ret = f81604_sja1000_read(priv, F81604_SJA1000_IR, &tmp);
+ if (ret)
+ return ret;
+
+ ret = f81604_register_urbs(priv);
+ if (ret)
+ return ret;
+
+ ret = f81604_set_normal_mode(priv);
+ if (ret) {
+ f81604_unregister_urbs(priv);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int f81604_set_bittiming(struct net_device *dev)
+{
+ struct f81604_port_priv *priv = netdev_priv(dev);
+ struct can_bittiming *bt = &priv->can.bittiming;
+ u8 btr0, btr1;
+ int ret;
+
+ btr0 = FIELD_PREP(F81604_BRP_MASK, bt->brp - 1) |
+ FIELD_PREP(F81604_SJW_MASK, bt->sjw - 1);
+
+ btr1 = FIELD_PREP(F81604_SEG1_MASK,
+ bt->prop_seg + bt->phase_seg1 - 1) |
+ FIELD_PREP(F81604_SEG2_MASK, bt->phase_seg2 - 1);
+
+ if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
+ btr1 |= F81604_SJA1000_BTR1_SAMPLE_TRIPLE;
+
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_BTR0, btr0);
+ if (ret) {
+ netdev_warn(dev, "%s: Set BTR0 failed: %pe\n", __func__,
+ ERR_PTR(ret));
+ return ret;
+ }
+
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_BTR1, btr1);
+ if (ret) {
+ netdev_warn(dev, "%s: Set BTR1 failed: %pe\n", __func__,
+ ERR_PTR(ret));
+ return ret;
+ }
+
+ return 0;
+}
+
+static int f81604_set_mode(struct net_device *netdev, enum can_mode mode)
+{
+ int ret;
+
+ switch (mode) {
+ case CAN_MODE_START:
+ ret = f81604_start(netdev);
+ if (!ret && netif_queue_stopped(netdev))
+ netif_wake_queue(netdev);
+ break;
+
+ default:
+ ret = -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
+static void f81604_write_bulk_callback(struct urb *urb)
+{
+ struct net_device *netdev = urb->context;
+
+ if (!netif_device_present(netdev))
+ return;
+
+ if (urb->status)
+ netdev_info(netdev, "%s: Tx URB error: %pe\n", __func__,
+ ERR_PTR(urb->status));
+}
+
+static void f81604_clear_reg_work(struct work_struct *work)
+{
+ struct f81604_port_priv *priv;
+ u8 tmp;
+
+ priv = container_of(work, struct f81604_port_priv, clear_reg_work);
+
+ /* dummy read for clear Arbitration lost capture(ALC) register. */
+ if (test_and_clear_bit(F81604_CLEAR_ALC, &priv->clear_flags))
+ f81604_sja1000_read(priv, F81604_SJA1000_ALC, &tmp);
+
+ /* dummy read for clear Error code capture(ECC) register. */
+ if (test_and_clear_bit(F81604_CLEAR_ECC, &priv->clear_flags))
+ f81604_sja1000_read(priv, F81604_SJA1000_ECC, &tmp);
+
+ /* dummy write for clear data overrun flag. */
+ if (test_and_clear_bit(F81604_CLEAR_OVERRUN, &priv->clear_flags))
+ f81604_sja1000_write(priv, F81604_SJA1000_CMR,
+ F81604_SJA1000_CMD_CDO);
+}
+
+static netdev_tx_t f81604_start_xmit(struct sk_buff *skb,
+ struct net_device *netdev)
+{
+ struct can_frame *cf = (struct can_frame *)skb->data;
+ struct f81604_port_priv *priv = netdev_priv(netdev);
+ struct net_device_stats *stats = &netdev->stats;
+ struct f81604_can_frame *frame;
+ struct urb *write_urb;
+ int ret;
+
+ if (can_dev_dropped_skb(netdev, skb))
+ return NETDEV_TX_OK;
+
+ netif_stop_queue(netdev);
+
+ write_urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!write_urb)
+ goto nomem_urb;
+
+ frame = kzalloc(sizeof(*frame), GFP_ATOMIC);
+ if (!frame)
+ goto nomem_buf;
+
+ usb_fill_bulk_urb(write_urb, priv->dev,
+ usb_sndbulkpipe(priv->dev,
+ bulk_out_addr[netdev->dev_port]),
+ frame, sizeof(*frame), f81604_write_bulk_callback,
+ priv->netdev);
+
+ write_urb->transfer_flags |= URB_FREE_BUFFER;
+
+ frame->cmd = F81604_CMD_DATA;
+ frame->dlc = cf->len;
+
+ if (cf->can_id & CAN_RTR_FLAG)
+ frame->dlc |= F81604_DLC_RTR_BIT;
+
+ if (cf->can_id & CAN_EFF_FLAG) {
+ u32 id = (cf->can_id & CAN_EFF_MASK) << F81604_EFF_SHIFT;
+
+ put_unaligned_be32(id, &frame->eff.id);
+
+ frame->dlc |= F81604_DLC_EFF_BIT;
+
+ if (!(cf->can_id & CAN_RTR_FLAG))
+ memcpy(&frame->eff.data, cf->data, cf->len);
+ } else {
+ u32 id = (cf->can_id & CAN_SFF_MASK) << F81604_SFF_SHIFT;
+
+ put_unaligned_be16(id, &frame->sff.id);
+
+ if (!(cf->can_id & CAN_RTR_FLAG))
+ memcpy(&frame->sff.data, cf->data, cf->len);
+ }
+
+ can_put_echo_skb(skb, netdev, 0, 0);
+
+ ret = usb_submit_urb(write_urb, GFP_ATOMIC);
+ if (ret) {
+ netdev_err(netdev, "%s: failed to resubmit tx bulk urb: %pe\n",
+ __func__, ERR_PTR(ret));
+
+ can_free_echo_skb(netdev, 0, NULL);
+ stats->tx_dropped++;
+ stats->tx_errors++;
+
+ if (ret == -ENODEV)
+ netif_device_detach(netdev);
+ else
+ netif_wake_queue(netdev);
+ }
+
+ /* let usb core take care of this urb */
+ usb_free_urb(write_urb);
+
+ return NETDEV_TX_OK;
+
+nomem_buf:
+ usb_free_urb(write_urb);
+
+nomem_urb:
+ dev_kfree_skb(skb);
+ stats->tx_dropped++;
+ stats->tx_errors++;
+ netif_wake_queue(netdev);
+
+ return NETDEV_TX_OK;
+}
+
+static int f81604_get_berr_counter(const struct net_device *netdev,
+ struct can_berr_counter *bec)
+{
+ struct f81604_port_priv *priv = netdev_priv(netdev);
+ u8 txerr, rxerr;
+ int ret;
+
+ ret = f81604_sja1000_read(priv, F81604_SJA1000_TXERR, &txerr);
+ if (ret)
+ return ret;
+
+ ret = f81604_sja1000_read(priv, F81604_SJA1000_RXERR, &rxerr);
+ if (ret)
+ return ret;
+
+ bec->txerr = txerr;
+ bec->rxerr = rxerr;
+
+ return 0;
+}
+
+/* Open USB device */
+static int f81604_open(struct net_device *netdev)
+{
+ int ret;
+
+ ret = open_candev(netdev);
+ if (ret)
+ return ret;
+
+ ret = f81604_start(netdev);
+ if (ret) {
+ if (ret == -ENODEV)
+ netif_device_detach(netdev);
+
+ close_candev(netdev);
+ return ret;
+ }
+
+ netif_start_queue(netdev);
+ return 0;
+}
+
+/* Close USB device */
+static int f81604_close(struct net_device *netdev)
+{
+ struct f81604_port_priv *priv = netdev_priv(netdev);
+
+ f81604_set_reset_mode(priv);
+
+ netif_stop_queue(netdev);
+ cancel_work_sync(&priv->clear_reg_work);
+ close_candev(netdev);
+
+ f81604_unregister_urbs(priv);
+
+ return 0;
+}
+
+static const struct net_device_ops f81604_netdev_ops = {
+ .ndo_open = f81604_open,
+ .ndo_stop = f81604_close,
+ .ndo_start_xmit = f81604_start_xmit,
+ .ndo_change_mtu = can_change_mtu,
+};
+
+static const struct can_bittiming_const f81604_bittiming_const = {
+ .name = KBUILD_MODNAME,
+ .tseg1_min = 1,
+ .tseg1_max = 16,
+ .tseg2_min = 1,
+ .tseg2_max = 8,
+ .sjw_max = 4,
+ .brp_min = 1,
+ .brp_max = 64,
+ .brp_inc = 1,
+};
+
+/* Called by the usb core when driver is unloaded or device is removed */
+static void f81604_disconnect(struct usb_interface *intf)
+{
+ struct f81604_priv *priv = usb_get_intfdata(intf);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) {
+ if (!priv->netdev[i])
+ continue;
+
+ unregister_netdev(priv->netdev[i]);
+ free_candev(priv->netdev[i]);
+ }
+}
+
+static int __f81604_set_termination(struct usb_device *dev, int idx, u16 term)
+{
+ u8 mask, data = 0;
+
+ if (idx == 0)
+ mask = F81604_CAN0_TERM;
+ else
+ mask = F81604_CAN1_TERM;
+
+ if (term)
+ data = mask;
+
+ return f81604_update_bits(dev, F81604_TERMINATOR_REG, mask, data);
+}
+
+static int f81604_set_termination(struct net_device *netdev, u16 term)
+{
+ struct f81604_port_priv *port_priv = netdev_priv(netdev);
+
+ ASSERT_RTNL();
+
+ return __f81604_set_termination(port_priv->dev, netdev->dev_port,
+ term);
+}
+
+static int f81604_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct net_device *netdev;
+ struct f81604_priv *priv;
+ int i, ret;
+
+ priv = devm_kzalloc(&intf->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ usb_set_intfdata(intf, priv);
+
+ for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) {
+ ret = __f81604_set_termination(dev, i, 0);
+ if (ret) {
+ dev_err(&intf->dev,
+ "Setting termination of CH#%d failed: %pe\n",
+ i, ERR_PTR(ret));
+ return ret;
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) {
+ struct f81604_port_priv *port_priv;
+
+ netdev = alloc_candev(sizeof(*port_priv), 1);
+ if (!netdev) {
+ dev_err(&intf->dev, "Couldn't alloc candev: %d\n", i);
+ ret = -ENOMEM;
+
+ goto failure_cleanup;
+ }
+
+ port_priv = netdev_priv(netdev);
+
+ INIT_WORK(&port_priv->clear_reg_work, f81604_clear_reg_work);
+ init_usb_anchor(&port_priv->urbs_anchor);
+
+ port_priv->intf = intf;
+ port_priv->dev = dev;
+ port_priv->netdev = netdev;
+ port_priv->can.clock.freq = F81604_CAN_CLOCK;
+
+ port_priv->can.termination_const = f81604_termination;
+ port_priv->can.termination_const_cnt =
+ ARRAY_SIZE(f81604_termination);
+ port_priv->can.bittiming_const = &f81604_bittiming_const;
+ port_priv->can.do_set_bittiming = f81604_set_bittiming;
+ port_priv->can.do_set_mode = f81604_set_mode;
+ port_priv->can.do_set_termination = f81604_set_termination;
+ port_priv->can.do_get_berr_counter = f81604_get_berr_counter;
+ port_priv->can.ctrlmode_supported =
+ CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_3_SAMPLES |
+ CAN_CTRLMODE_ONE_SHOT | CAN_CTRLMODE_BERR_REPORTING |
+ CAN_CTRLMODE_PRESUME_ACK;
+
+ netdev->ethtool_ops = &f81604_ethtool_ops;
+ netdev->netdev_ops = &f81604_netdev_ops;
+ netdev->flags |= IFF_ECHO;
+ netdev->dev_port = i;
+
+ SET_NETDEV_DEV(netdev, &intf->dev);
+
+ ret = register_candev(netdev);
+ if (ret) {
+ netdev_err(netdev, "register CAN device failed: %pe\n",
+ ERR_PTR(ret));
+ free_candev(netdev);
+
+ goto failure_cleanup;
+ }
+
+ priv->netdev[i] = netdev;
+ }
+
+ return 0;
+
+failure_cleanup:
+ f81604_disconnect(intf);
+ return ret;
+}
+
+static struct usb_driver f81604_driver = {
+ .name = KBUILD_MODNAME,
+ .probe = f81604_probe,
+ .disconnect = f81604_disconnect,
+ .id_table = f81604_table,
+};
+
+module_usb_driver(f81604_driver);
+
+MODULE_AUTHOR("Ji-Ze Hong (Peter Hong) <peter_hong@fintek.com.tw>");
+MODULE_DESCRIPTION("Fintek F81604 USB to 2xCANBUS");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index d476c2884008..bd9eb066ecf1 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -303,12 +303,6 @@ struct gs_can {
struct can_bittiming_const bt_const, data_bt_const;
unsigned int channel; /* channel number */
- /* time counter for hardware timestamps */
- struct cyclecounter cc;
- struct timecounter tc;
- spinlock_t tc_lock; /* spinlock to guard access tc->cycle_last */
- struct delayed_work timestamp;
-
u32 feature;
unsigned int hf_size_tx;
@@ -325,6 +319,13 @@ struct gs_usb {
struct gs_can *canch[GS_MAX_INTF];
struct usb_anchor rx_submitted;
struct usb_device *udev;
+
+ /* time counter for hardware timestamps */
+ struct cyclecounter cc;
+ struct timecounter tc;
+ spinlock_t tc_lock; /* spinlock to guard access tc->cycle_last */
+ struct delayed_work timestamp;
+
unsigned int hf_size_rx;
u8 active_channels;
};
@@ -388,15 +389,15 @@ static int gs_cmd_reset(struct gs_can *dev)
GFP_KERNEL);
}
-static inline int gs_usb_get_timestamp(const struct gs_can *dev,
+static inline int gs_usb_get_timestamp(const struct gs_usb *parent,
u32 *timestamp_p)
{
__le32 timestamp;
int rc;
- rc = usb_control_msg_recv(dev->udev, 0, GS_USB_BREQ_TIMESTAMP,
+ rc = usb_control_msg_recv(parent->udev, 0, GS_USB_BREQ_TIMESTAMP,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
- dev->channel, 0,
+ 0, 0,
&timestamp, sizeof(timestamp),
USB_CTRL_GET_TIMEOUT,
GFP_KERNEL);
@@ -410,20 +411,20 @@ static inline int gs_usb_get_timestamp(const struct gs_can *dev,
static u64 gs_usb_timestamp_read(const struct cyclecounter *cc) __must_hold(&dev->tc_lock)
{
- struct gs_can *dev = container_of(cc, struct gs_can, cc);
+ struct gs_usb *parent = container_of(cc, struct gs_usb, cc);
u32 timestamp = 0;
int err;
- lockdep_assert_held(&dev->tc_lock);
+ lockdep_assert_held(&parent->tc_lock);
/* drop lock for synchronous USB transfer */
- spin_unlock_bh(&dev->tc_lock);
- err = gs_usb_get_timestamp(dev, &timestamp);
- spin_lock_bh(&dev->tc_lock);
+ spin_unlock_bh(&parent->tc_lock);
+ err = gs_usb_get_timestamp(parent, &timestamp);
+ spin_lock_bh(&parent->tc_lock);
if (err)
- netdev_err(dev->netdev,
- "Error %d while reading timestamp. HW timestamps may be inaccurate.",
- err);
+ dev_err(&parent->udev->dev,
+ "Error %d while reading timestamp. HW timestamps may be inaccurate.",
+ err);
return timestamp;
}
@@ -431,14 +432,14 @@ static u64 gs_usb_timestamp_read(const struct cyclecounter *cc) __must_hold(&dev
static void gs_usb_timestamp_work(struct work_struct *work)
{
struct delayed_work *delayed_work = to_delayed_work(work);
- struct gs_can *dev;
+ struct gs_usb *parent;
- dev = container_of(delayed_work, struct gs_can, timestamp);
- spin_lock_bh(&dev->tc_lock);
- timecounter_read(&dev->tc);
- spin_unlock_bh(&dev->tc_lock);
+ parent = container_of(delayed_work, struct gs_usb, timestamp);
+ spin_lock_bh(&parent->tc_lock);
+ timecounter_read(&parent->tc);
+ spin_unlock_bh(&parent->tc_lock);
- schedule_delayed_work(&dev->timestamp,
+ schedule_delayed_work(&parent->timestamp,
GS_USB_TIMESTAMP_WORK_DELAY_SEC * HZ);
}
@@ -446,37 +447,38 @@ static void gs_usb_skb_set_timestamp(struct gs_can *dev,
struct sk_buff *skb, u32 timestamp)
{
struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb);
+ struct gs_usb *parent = dev->parent;
u64 ns;
- spin_lock_bh(&dev->tc_lock);
- ns = timecounter_cyc2time(&dev->tc, timestamp);
- spin_unlock_bh(&dev->tc_lock);
+ spin_lock_bh(&parent->tc_lock);
+ ns = timecounter_cyc2time(&parent->tc, timestamp);
+ spin_unlock_bh(&parent->tc_lock);
hwtstamps->hwtstamp = ns_to_ktime(ns);
}
-static void gs_usb_timestamp_init(struct gs_can *dev)
+static void gs_usb_timestamp_init(struct gs_usb *parent)
{
- struct cyclecounter *cc = &dev->cc;
+ struct cyclecounter *cc = &parent->cc;
cc->read = gs_usb_timestamp_read;
cc->mask = CYCLECOUNTER_MASK(32);
cc->shift = 32 - bits_per(NSEC_PER_SEC / GS_USB_TIMESTAMP_TIMER_HZ);
cc->mult = clocksource_hz2mult(GS_USB_TIMESTAMP_TIMER_HZ, cc->shift);
- spin_lock_init(&dev->tc_lock);
- spin_lock_bh(&dev->tc_lock);
- timecounter_init(&dev->tc, &dev->cc, ktime_get_real_ns());
- spin_unlock_bh(&dev->tc_lock);
+ spin_lock_init(&parent->tc_lock);
+ spin_lock_bh(&parent->tc_lock);
+ timecounter_init(&parent->tc, &parent->cc, ktime_get_real_ns());
+ spin_unlock_bh(&parent->tc_lock);
- INIT_DELAYED_WORK(&dev->timestamp, gs_usb_timestamp_work);
- schedule_delayed_work(&dev->timestamp,
+ INIT_DELAYED_WORK(&parent->timestamp, gs_usb_timestamp_work);
+ schedule_delayed_work(&parent->timestamp,
GS_USB_TIMESTAMP_WORK_DELAY_SEC * HZ);
}
-static void gs_usb_timestamp_stop(struct gs_can *dev)
+static void gs_usb_timestamp_stop(struct gs_usb *parent)
{
- cancel_delayed_work_sync(&dev->timestamp);
+ cancel_delayed_work_sync(&parent->timestamp);
}
static void gs_update_state(struct gs_can *dev, struct can_frame *cf)
@@ -560,6 +562,9 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
if (!netif_device_present(netdev))
return;
+ if (!netif_running(netdev))
+ goto resubmit_urb;
+
if (hf->echo_id == -1) { /* normal rx */
if (hf->flags & GS_CAN_FLAG_FD) {
skb = alloc_canfd_skb(dev->netdev, &cfd);
@@ -833,6 +838,7 @@ static int gs_can_open(struct net_device *netdev)
.mode = cpu_to_le32(GS_CAN_MODE_START),
};
struct gs_host_frame *hf;
+ struct urb *urb = NULL;
u32 ctrlmode;
u32 flags = 0;
int rc, i;
@@ -855,14 +861,18 @@ static int gs_can_open(struct net_device *netdev)
}
if (!parent->active_channels) {
+ if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+ gs_usb_timestamp_init(parent);
+
for (i = 0; i < GS_MAX_RX_URBS; i++) {
- struct urb *urb;
u8 *buf;
/* alloc rx urb */
urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb)
- return -ENOMEM;
+ if (!urb) {
+ rc = -ENOMEM;
+ goto out_usb_kill_anchored_urbs;
+ }
/* alloc rx buffer */
buf = kmalloc(dev->parent->hf_size_rx,
@@ -870,8 +880,8 @@ static int gs_can_open(struct net_device *netdev)
if (!buf) {
netdev_err(netdev,
"No memory left for USB buffer\n");
- usb_free_urb(urb);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto out_usb_free_urb;
}
/* fill, anchor, and submit rx urb */
@@ -894,9 +904,7 @@ static int gs_can_open(struct net_device *netdev)
netdev_err(netdev,
"usb_submit failed (err=%d)\n", rc);
- usb_unanchor_urb(urb);
- usb_free_urb(urb);
- break;
+ goto out_usb_unanchor_urb;
}
/* Drop reference,
@@ -926,13 +934,9 @@ static int gs_can_open(struct net_device *netdev)
flags |= GS_CAN_MODE_FD;
/* if hardware supports timestamps, enable it */
- if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) {
+ if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
flags |= GS_CAN_MODE_HW_TIMESTAMP;
- /* start polling timestamp */
- gs_usb_timestamp_init(dev);
- }
-
/* finally start device */
dev->can.state = CAN_STATE_ERROR_ACTIVE;
dm.flags = cpu_to_le32(flags);
@@ -942,10 +946,9 @@ static int gs_can_open(struct net_device *netdev)
GFP_KERNEL);
if (rc) {
netdev_err(netdev, "Couldn't start device (err=%d)\n", rc);
- if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
- gs_usb_timestamp_stop(dev);
dev->can.state = CAN_STATE_STOPPED;
- return rc;
+
+ goto out_usb_kill_anchored_urbs;
}
parent->active_channels++;
@@ -953,6 +956,22 @@ static int gs_can_open(struct net_device *netdev)
netif_start_queue(netdev);
return 0;
+
+out_usb_unanchor_urb:
+ usb_unanchor_urb(urb);
+out_usb_free_urb:
+ usb_free_urb(urb);
+out_usb_kill_anchored_urbs:
+ if (!parent->active_channels) {
+ usb_kill_anchored_urbs(&dev->tx_submitted);
+
+ if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+ gs_usb_timestamp_stop(parent);
+ }
+
+ close_candev(netdev);
+
+ return rc;
}
static int gs_usb_get_state(const struct net_device *netdev,
@@ -998,20 +1017,21 @@ static int gs_can_close(struct net_device *netdev)
netif_stop_queue(netdev);
- /* stop polling timestamp */
- if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
- gs_usb_timestamp_stop(dev);
-
/* Stop polling */
parent->active_channels--;
if (!parent->active_channels) {
usb_kill_anchored_urbs(&parent->rx_submitted);
+
+ if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+ gs_usb_timestamp_stop(parent);
}
/* Stop sending URBs */
usb_kill_anchored_urbs(&dev->tx_submitted);
atomic_set(&dev->active_tx_urbs, 0);
+ dev->can.state = CAN_STATE_STOPPED;
+
/* reset the device */
rc = gs_cmd_reset(dev);
if (rc < 0)
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
index 7135ec851341..71ef4db5c09f 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
@@ -816,7 +816,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
init_completion(&priv->stop_comp);
init_completion(&priv->flush_comp);
init_completion(&priv->get_busparams_comp);
- priv->can.ctrlmode_supported = 0;
+ priv->can.ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC;
priv->dev = dev;
priv->netdev = netdev;
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
index ef341c4254fc..c7ba768dfe17 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
@@ -1263,7 +1263,7 @@ static void kvaser_usb_hydra_rx_msg_std(const struct kvaser_usb *dev,
if (flags & KVASER_USB_HYDRA_CF_FLAG_OVERRUN)
kvaser_usb_can_rx_over_error(priv->netdev);
- cf->len = can_cc_dlc2len(cmd->rx_can.dlc);
+ can_frame_set_cc_len((struct can_frame *)cf, cmd->rx_can.dlc, priv->can.ctrlmode);
if (flags & KVASER_USB_HYDRA_CF_FLAG_REMOTE_FRAME) {
cf->can_id |= CAN_RTR_FLAG;
@@ -1342,7 +1342,7 @@ static void kvaser_usb_hydra_rx_msg_ext(const struct kvaser_usb *dev,
if (flags & KVASER_USB_HYDRA_CF_FLAG_ESI)
cf->flags |= CANFD_ESI;
} else {
- cf->len = can_cc_dlc2len(dlc);
+ can_frame_set_cc_len((struct can_frame *)cf, dlc, priv->can.ctrlmode);
}
if (flags & KVASER_USB_HYDRA_CF_FLAG_REMOTE_FRAME) {
@@ -1442,7 +1442,7 @@ kvaser_usb_hydra_frame_to_cmd_ext(const struct kvaser_usb_net_priv *priv,
struct kvaser_usb *dev = priv->dev;
struct kvaser_cmd_ext *cmd;
struct canfd_frame *cf = (struct canfd_frame *)skb->data;
- u8 dlc = can_fd_len2dlc(cf->len);
+ u8 dlc;
u8 nbr_of_bytes = cf->len;
u32 flags;
u32 id;
@@ -1467,6 +1467,11 @@ kvaser_usb_hydra_frame_to_cmd_ext(const struct kvaser_usb_net_priv *priv,
cmd->len = cpu_to_le16(*cmd_len);
+ if (can_is_canfd_skb(skb))
+ dlc = can_fd_len2dlc(cf->len);
+ else
+ dlc = can_get_cc_dlc((struct can_frame *)cf, priv->can.ctrlmode);
+
cmd->tx_can.databytes = nbr_of_bytes;
cmd->tx_can.dlc = dlc;
@@ -1542,7 +1547,7 @@ kvaser_usb_hydra_frame_to_cmd_std(const struct kvaser_usb_net_priv *priv,
id = cf->can_id & CAN_SFF_MASK;
}
- cmd->tx_can.dlc = cf->len;
+ cmd->tx_can.dlc = can_get_cc_dlc(cf, priv->can.ctrlmode);
flags = (cf->can_id & CAN_EFF_FLAG ?
KVASER_USB_HYDRA_CF_FLAG_EXTENDED_ID : 0);
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
index 1c2f99ce4c6c..23bd7574b1c7 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
@@ -573,7 +573,7 @@ kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv,
cmd->u.tx_can.data[1] = cf->can_id & 0x3f;
}
- cmd->u.tx_can.data[5] = cf->len;
+ cmd->u.tx_can.data[5] = can_get_cc_dlc(cf, priv->can.ctrlmode);
memcpy(&cmd->u.tx_can.data[6], cf->data, cf->len);
if (cf->can_id & CAN_RTR_FLAG)
@@ -1349,7 +1349,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev,
else
cf->can_id &= CAN_SFF_MASK;
- cf->len = can_cc_dlc2len(cmd->u.leaf.log_message.dlc);
+ can_frame_set_cc_len(cf, cmd->u.leaf.log_message.dlc & 0xF, priv->can.ctrlmode);
if (cmd->u.leaf.log_message.flags & MSG_FLAG_REMOTE_FRAME)
cf->can_id |= CAN_RTR_FLAG;
@@ -1367,7 +1367,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev,
cf->can_id |= CAN_EFF_FLAG;
}
- cf->len = can_cc_dlc2len(rx_data[5]);
+ can_frame_set_cc_len(cf, rx_data[5] & 0xF, priv->can.ctrlmode);
if (cmd->u.rx_can_header.flag & MSG_FLAG_REMOTE_FRAME)
cf->can_id |= CAN_RTR_FLAG;
diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c
index 4068d962203d..98c669ad5141 100644
--- a/drivers/net/can/vxcan.c
+++ b/drivers/net/can/vxcan.c
@@ -192,12 +192,7 @@ static int vxcan_newlink(struct net *net, struct net_device *dev,
nla_peer = data[VXCAN_INFO_PEER];
ifmp = nla_data(nla_peer);
- err = rtnl_nla_parse_ifla(peer_tb,
- nla_data(nla_peer) +
- sizeof(struct ifinfomsg),
- nla_len(nla_peer) -
- sizeof(struct ifinfomsg),
- NULL);
+ err = rtnl_nla_parse_ifinfomsg(peer_tb, nla_peer, extack);
if (err < 0)
return err;
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
index 43c812ea1de0..4d3283db3a13 100644
--- a/drivers/net/can/xilinx_can.c
+++ b/drivers/net/can/xilinx_can.c
@@ -28,6 +28,7 @@
#include <linux/types.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
+#include <linux/phy/phy.h>
#include <linux/pm_runtime.h>
#define DRIVER_NAME "xilinx_can"
@@ -198,6 +199,7 @@ struct xcan_devtype_data {
* @bus_clk: Pointer to struct clk
* @can_clk: Pointer to struct clk
* @devtype: Device type specific constants
+ * @transceiver: Optional pointer to associated CAN transceiver
*/
struct xcan_priv {
struct can_priv can;
@@ -215,6 +217,7 @@ struct xcan_priv {
struct clk *bus_clk;
struct clk *can_clk;
struct xcan_devtype_data devtype;
+ struct phy *transceiver;
};
/* CAN Bittiming constants as per Xilinx CAN specs */
@@ -1419,6 +1422,10 @@ static int xcan_open(struct net_device *ndev)
struct xcan_priv *priv = netdev_priv(ndev);
int ret;
+ ret = phy_power_on(priv->transceiver);
+ if (ret)
+ return ret;
+
ret = pm_runtime_get_sync(priv->dev);
if (ret < 0) {
netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
@@ -1462,6 +1469,7 @@ err_irq:
free_irq(ndev->irq, ndev);
err:
pm_runtime_put(priv->dev);
+ phy_power_off(priv->transceiver);
return ret;
}
@@ -1483,6 +1491,7 @@ static int xcan_close(struct net_device *ndev)
close_candev(ndev);
pm_runtime_put(priv->dev);
+ phy_power_off(priv->transceiver);
return 0;
}
@@ -1713,6 +1722,7 @@ static int xcan_probe(struct platform_device *pdev)
{
struct net_device *ndev;
struct xcan_priv *priv;
+ struct phy *transceiver;
const struct of_device_id *of_id;
const struct xcan_devtype_data *devtype = &xcan_axi_data;
void __iomem *addr;
@@ -1843,6 +1853,14 @@ static int xcan_probe(struct platform_device *pdev)
goto err_free;
}
+ transceiver = devm_phy_optional_get(&pdev->dev, NULL);
+ if (IS_ERR(transceiver)) {
+ ret = PTR_ERR(transceiver);
+ dev_err_probe(&pdev->dev, ret, "failed to get phy\n");
+ goto err_free;
+ }
+ priv->transceiver = transceiver;
+
priv->write_reg = xcan_write_reg_le;
priv->read_reg = xcan_read_reg_le;
@@ -1869,6 +1887,7 @@ static int xcan_probe(struct platform_device *pdev)
goto err_disableclks;
}
+ of_can_transceiver(ndev);
pm_runtime_put(&pdev->dev);
if (priv->devtype.flags & XCAN_FLAG_CANFD_2) {
@@ -1898,20 +1917,18 @@ err:
* This function frees all the resources allocated to the device.
* Return: 0 always
*/
-static int xcan_remove(struct platform_device *pdev)
+static void xcan_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
unregister_candev(ndev);
pm_runtime_disable(&pdev->dev);
free_candev(ndev);
-
- return 0;
}
static struct platform_driver xcan_driver = {
.probe = xcan_probe,
- .remove = xcan_remove,
+ .remove_new = xcan_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &xcan_dev_pm_ops,
diff --git a/drivers/net/dsa/b53/b53_serdes.c b/drivers/net/dsa/b53/b53_serdes.c
index 0690210770ff..b0ccebcd3ffa 100644
--- a/drivers/net/dsa/b53/b53_serdes.c
+++ b/drivers/net/dsa/b53/b53_serdes.c
@@ -65,7 +65,7 @@ static u16 b53_serdes_read(struct b53_device *dev, u8 lane,
return b53_serdes_read_blk(dev, offset, block);
}
-static int b53_serdes_config(struct phylink_pcs *pcs, unsigned int mode,
+static int b53_serdes_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -239,6 +239,7 @@ int b53_serdes_init(struct b53_device *dev, int port)
pcs->dev = dev;
pcs->lane = lane;
pcs->pcs.ops = &b53_pcs_ops;
+ pcs->pcs.neg_mode = true;
return 0;
}
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index cde253d27bd0..72374b066f64 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -1436,7 +1436,9 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
if (IS_ERR(priv->clk))
return PTR_ERR(priv->clk);
- clk_prepare_enable(priv->clk);
+ ret = clk_prepare_enable(priv->clk);
+ if (ret)
+ return ret;
priv->clk_mdiv = devm_clk_get_optional(&pdev->dev, "sw_switch_mdiv");
if (IS_ERR(priv->clk_mdiv)) {
@@ -1444,7 +1446,9 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
goto out_clk;
}
- clk_prepare_enable(priv->clk_mdiv);
+ ret = clk_prepare_enable(priv->clk_mdiv);
+ if (ret)
+ goto out_clk;
ret = bcm_sf2_sw_rst(priv);
if (ret) {
diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c
index 595a548bb0a8..af50001ccdd4 100644
--- a/drivers/net/dsa/hirschmann/hellcreek.c
+++ b/drivers/net/dsa/hirschmann/hellcreek.c
@@ -1885,13 +1885,17 @@ static int hellcreek_port_setup_tc(struct dsa_switch *ds, int port,
case TC_SETUP_QDISC_TAPRIO: {
struct tc_taprio_qopt_offload *taprio = type_data;
- if (!hellcreek_validate_schedule(hellcreek, taprio))
- return -EOPNOTSUPP;
+ switch (taprio->cmd) {
+ case TAPRIO_CMD_REPLACE:
+ if (!hellcreek_validate_schedule(hellcreek, taprio))
+ return -EOPNOTSUPP;
- if (taprio->enable)
return hellcreek_port_set_schedule(ds, port, taprio);
-
- return hellcreek_port_del_schedule(ds, port);
+ case TAPRIO_CMD_DESTROY:
+ return hellcreek_port_del_schedule(ds, port);
+ default:
+ return -EOPNOTSUPP;
+ }
}
default:
return -EOPNOTSUPP;
diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c
index c0215a8770f4..ff76444057d2 100644
--- a/drivers/net/dsa/lan9303-core.c
+++ b/drivers/net/dsa/lan9303-core.c
@@ -1458,7 +1458,6 @@ int lan9303_remove(struct lan9303 *chip)
/* assert reset to the whole device to prevent it from doing anything */
gpiod_set_value_cansleep(chip->reset_gpio, 1);
- gpiod_unexport(chip->reset_gpio);
return 0;
}
diff --git a/drivers/net/dsa/lan9303_i2c.c b/drivers/net/dsa/lan9303_i2c.c
index e8844820c3a9..bbbec322bc4f 100644
--- a/drivers/net/dsa/lan9303_i2c.c
+++ b/drivers/net/dsa/lan9303_i2c.c
@@ -105,7 +105,7 @@ static struct i2c_driver lan9303_i2c_driver = {
.name = "LAN9303_I2C",
.of_match_table = lan9303_i2c_of_match,
},
- .probe_new = lan9303_i2c_probe,
+ .probe = lan9303_i2c_probe,
.remove = lan9303_i2c_remove,
.shutdown = lan9303_i2c_shutdown,
.id_table = lan9303_i2c_id,
diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c
index f56fca1b1a22..91aba470fb2f 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -28,13 +28,13 @@
static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
{
- regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0);
+ regmap_update_bits(ksz_regmap_8(dev), addr, bits, set ? bits : 0);
}
static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
bool set)
{
- regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset),
+ regmap_update_bits(ksz_regmap_8(dev), PORT_CTRL_ADDR(port, offset),
bits, set ? bits : 0);
}
@@ -506,7 +506,13 @@ static int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr,
(data_hi & masks[STATIC_MAC_TABLE_FWD_PORTS]) >>
shifts[STATIC_MAC_FWD_PORTS];
alu->is_override = (data_hi & masks[STATIC_MAC_TABLE_OVERRIDE]) ? 1 : 0;
- data_hi >>= 1;
+
+ /* KSZ8795 family switches have STATIC_MAC_TABLE_USE_FID and
+ * STATIC_MAC_TABLE_FID definitions off by 1 when doing read on the
+ * static MAC table compared to doing write.
+ */
+ if (ksz_is_ksz87xx(dev))
+ data_hi >>= 1;
alu->is_static = true;
alu->is_use_fid = (data_hi & masks[STATIC_MAC_TABLE_USE_FID]) ? 1 : 0;
alu->fid = (data_hi & masks[STATIC_MAC_TABLE_FID]) >>
@@ -941,7 +947,6 @@ void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port)
{
u8 learn[DSA_MAX_PORTS];
int first, index, cnt;
- struct ksz_port *p;
const u16 *regs;
regs = dev->info->regs;
@@ -955,9 +960,6 @@ void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port)
cnt = dev->info->port_cnt;
}
for (index = first; index < cnt; index++) {
- p = &dev->ports[index];
- if (!p->on)
- continue;
ksz_pread8(dev, index, regs[P_STP_CTRL], &learn[index]);
if (!(learn[index] & PORT_LEARN_DISABLE))
ksz_pwrite8(dev, index, regs[P_STP_CTRL],
@@ -965,9 +967,6 @@ void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port)
}
ksz_cfg(dev, S_FLUSH_TABLE_CTRL, SW_FLUSH_DYN_MAC_TABLE, true);
for (index = first; index < cnt; index++) {
- p = &dev->ports[index];
- if (!p->on)
- continue;
if (!(learn[index] & PORT_LEARN_DISABLE))
ksz_pwrite8(dev, index, regs[P_STP_CTRL], learn[index]);
}
@@ -1338,25 +1337,14 @@ void ksz8_config_cpu_port(struct dsa_switch *ds)
ksz_cfg(dev, regs[S_TAIL_TAG_CTRL], masks[SW_TAIL_TAG_ENABLE], true);
- p = &dev->ports[dev->cpu_port];
- p->on = 1;
-
ksz8_port_setup(dev, dev->cpu_port, true);
for (i = 0; i < dev->phy_port_cnt; i++) {
- p = &dev->ports[i];
-
ksz_port_stp_state_set(ds, i, BR_STATE_DISABLED);
-
- /* Last port may be disabled. */
- if (i == dev->phy_port_cnt)
- break;
- p->on = 1;
}
for (i = 0; i < dev->phy_port_cnt; i++) {
p = &dev->ports[i];
- if (!p->on)
- continue;
+
if (!ksz_is_ksz88x3(dev)) {
ksz_pread8(dev, i, regs[P_REMOTE_STATUS], &remote);
if (remote & KSZ8_PORT_FIBER_MODE)
@@ -1425,14 +1413,14 @@ int ksz8_setup(struct dsa_switch *ds)
ksz_cfg(dev, S_LINK_AGING_CTRL, SW_LINK_AUTO_AGING, true);
/* Enable aggressive back off algorithm in half duplex mode. */
- regmap_update_bits(dev->regmap[0], REG_SW_CTRL_1,
+ regmap_update_bits(ksz_regmap_8(dev), REG_SW_CTRL_1,
SW_AGGR_BACKOFF, SW_AGGR_BACKOFF);
/*
* Make sure unicast VLAN boundary is set as default and
* enable no excessive collision drop.
*/
- regmap_update_bits(dev->regmap[0], REG_SW_CTRL_2,
+ regmap_update_bits(ksz_regmap_8(dev), REG_SW_CTRL_2,
UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP,
UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP);
diff --git a/drivers/net/dsa/microchip/ksz8863_smi.c b/drivers/net/dsa/microchip/ksz8863_smi.c
index 3698112138b7..fd6e2e69a42a 100644
--- a/drivers/net/dsa/microchip/ksz8863_smi.c
+++ b/drivers/net/dsa/microchip/ksz8863_smi.c
@@ -104,6 +104,7 @@ static const struct regmap_config ksz8863_regmap_config[] = {
.cache_type = REGCACHE_NONE,
.lock = ksz_regmap_lock,
.unlock = ksz_regmap_unlock,
+ .max_register = U8_MAX,
},
{
.name = "#16",
@@ -113,6 +114,7 @@ static const struct regmap_config ksz8863_regmap_config[] = {
.cache_type = REGCACHE_NONE,
.lock = ksz_regmap_lock,
.unlock = ksz_regmap_unlock,
+ .max_register = U8_MAX,
},
{
.name = "#32",
@@ -122,11 +124,14 @@ static const struct regmap_config ksz8863_regmap_config[] = {
.cache_type = REGCACHE_NONE,
.lock = ksz_regmap_lock,
.unlock = ksz_regmap_unlock,
+ .max_register = U8_MAX,
}
};
static int ksz8863_smi_probe(struct mdio_device *mdiodev)
{
+ struct device *ddev = &mdiodev->dev;
+ const struct ksz_chip_data *chip;
struct regmap_config rc;
struct ksz_device *dev;
int ret;
@@ -136,9 +141,15 @@ static int ksz8863_smi_probe(struct mdio_device *mdiodev)
if (!dev)
return -ENOMEM;
- for (i = 0; i < ARRAY_SIZE(ksz8863_regmap_config); i++) {
+ chip = device_get_match_data(ddev);
+ if (!chip)
+ return -EINVAL;
+
+ for (i = 0; i < __KSZ_NUM_REGMAPS; i++) {
rc = ksz8863_regmap_config[i];
rc.lock_arg = &dev->regmap_mutex;
+ rc.wr_table = chip->wr_table;
+ rc.rd_table = chip->rd_table;
dev->regmap[i] = devm_regmap_init(&mdiodev->dev,
&regmap_smi[i], dev,
&rc);
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index bf13d47c26cf..83b7f2d5c1ea 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -21,25 +21,25 @@
static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
{
- regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0);
+ regmap_update_bits(ksz_regmap_8(dev), addr, bits, set ? bits : 0);
}
static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
bool set)
{
- regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset),
+ regmap_update_bits(ksz_regmap_8(dev), PORT_CTRL_ADDR(port, offset),
bits, set ? bits : 0);
}
static void ksz9477_cfg32(struct ksz_device *dev, u32 addr, u32 bits, bool set)
{
- regmap_update_bits(dev->regmap[2], addr, bits, set ? bits : 0);
+ regmap_update_bits(ksz_regmap_32(dev), addr, bits, set ? bits : 0);
}
static void ksz9477_port_cfg32(struct ksz_device *dev, int port, int offset,
u32 bits, bool set)
{
- regmap_update_bits(dev->regmap[2], PORT_CTRL_ADDR(port, offset),
+ regmap_update_bits(ksz_regmap_32(dev), PORT_CTRL_ADDR(port, offset),
bits, set ? bits : 0);
}
@@ -52,7 +52,7 @@ int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu)
frame_size = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
- return regmap_update_bits(dev->regmap[1], REG_SW_MTU__2,
+ return regmap_update_bits(ksz_regmap_16(dev), REG_SW_MTU__2,
REG_SW_MTU_MASK, frame_size);
}
@@ -60,7 +60,7 @@ static int ksz9477_wait_vlan_ctrl_ready(struct ksz_device *dev)
{
unsigned int val;
- return regmap_read_poll_timeout(dev->regmap[0], REG_SW_VLAN_CTRL,
+ return regmap_read_poll_timeout(ksz_regmap_8(dev), REG_SW_VLAN_CTRL,
val, !(val & VLAN_START), 10, 1000);
}
@@ -147,7 +147,7 @@ static int ksz9477_wait_alu_ready(struct ksz_device *dev)
{
unsigned int val;
- return regmap_read_poll_timeout(dev->regmap[2], REG_SW_ALU_CTRL__4,
+ return regmap_read_poll_timeout(ksz_regmap_32(dev), REG_SW_ALU_CTRL__4,
val, !(val & ALU_START), 10, 1000);
}
@@ -155,7 +155,7 @@ static int ksz9477_wait_alu_sta_ready(struct ksz_device *dev)
{
unsigned int val;
- return regmap_read_poll_timeout(dev->regmap[2],
+ return regmap_read_poll_timeout(ksz_regmap_32(dev),
REG_SW_ALU_STAT_CTRL__4,
val, !(val & ALU_STAT_START),
10, 1000);
@@ -170,7 +170,7 @@ int ksz9477_reset_switch(struct ksz_device *dev)
ksz_cfg(dev, REG_SW_OPERATION, SW_RESET, true);
/* turn off SPI DO Edge select */
- regmap_update_bits(dev->regmap[0], REG_SW_GLOBAL_SERIAL_CTRL_0,
+ regmap_update_bits(ksz_regmap_8(dev), REG_SW_GLOBAL_SERIAL_CTRL_0,
SPI_AUTO_EDGE_DETECTION, 0);
/* default configuration */
@@ -213,7 +213,7 @@ void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt)
data |= (addr << MIB_COUNTER_INDEX_S);
ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data);
- ret = regmap_read_poll_timeout(dev->regmap[2],
+ ret = regmap_read_poll_timeout(ksz_regmap_32(dev),
PORT_CTRL_ADDR(port, REG_PORT_MIB_CTRL_STAT__4),
val, !(val & MIB_COUNTER_READ), 10, 1000);
/* failed to read MIB. get out of loop */
@@ -329,11 +329,27 @@ int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
int ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val)
{
+ u32 mask, val32;
+
/* No real PHY after this. */
if (!dev->info->internal_phy[addr])
return 0;
- return ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val);
+ if (reg < 0x10)
+ return ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val);
+
+ /* Errata: When using SPI, I2C, or in-band register access,
+ * writes to certain PHY registers should be performed as
+ * 32-bit writes instead of 16-bit writes.
+ */
+ val32 = val;
+ mask = 0xffff;
+ if ((reg & 1) == 0) {
+ val32 <<= 16;
+ mask <<= 16;
+ }
+ reg &= ~1;
+ return ksz_prmw32(dev, addr, 0x100 + (reg << 1), mask, val32);
}
void ksz9477_cfg_port_member(struct ksz_device *dev, int port, u8 member)
@@ -346,7 +362,7 @@ void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port)
const u16 *regs = dev->info->regs;
u8 data;
- regmap_update_bits(dev->regmap[0], REG_SW_LUE_CTRL_2,
+ regmap_update_bits(ksz_regmap_8(dev), REG_SW_LUE_CTRL_2,
SW_FLUSH_OPTION_M << SW_FLUSH_OPTION_S,
SW_FLUSH_OPTION_DYN_MAC << SW_FLUSH_OPTION_S);
@@ -889,62 +905,6 @@ static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port)
return interface;
}
-static void ksz9477_port_mmd_write(struct ksz_device *dev, int port,
- u8 dev_addr, u16 reg_addr, u16 val)
-{
- ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP,
- MMD_SETUP(PORT_MMD_OP_INDEX, dev_addr));
- ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, reg_addr);
- ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP,
- MMD_SETUP(PORT_MMD_OP_DATA_NO_INCR, dev_addr));
- ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, val);
-}
-
-static void ksz9477_phy_errata_setup(struct ksz_device *dev, int port)
-{
- /* Apply PHY settings to address errata listed in
- * KSZ9477, KSZ9897, KSZ9896, KSZ9567, KSZ8565
- * Silicon Errata and Data Sheet Clarification documents:
- *
- * Register settings are needed to improve PHY receive performance
- */
- ksz9477_port_mmd_write(dev, port, 0x01, 0x6f, 0xdd0b);
- ksz9477_port_mmd_write(dev, port, 0x01, 0x8f, 0x6032);
- ksz9477_port_mmd_write(dev, port, 0x01, 0x9d, 0x248c);
- ksz9477_port_mmd_write(dev, port, 0x01, 0x75, 0x0060);
- ksz9477_port_mmd_write(dev, port, 0x01, 0xd3, 0x7777);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x06, 0x3008);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x08, 0x2001);
-
- /* Transmit waveform amplitude can be improved
- * (1000BASE-T, 100BASE-TX, 10BASE-Te)
- */
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x04, 0x00d0);
-
- /* Energy Efficient Ethernet (EEE) feature select must
- * be manually disabled (except on KSZ8565 which is 100Mbit)
- */
- if (dev->info->gbit_capable[port])
- ksz9477_port_mmd_write(dev, port, 0x07, 0x3c, 0x0000);
-
- /* Register settings are required to meet data sheet
- * supply current specifications
- */
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x13, 0x6eff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x14, 0xe6ff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x15, 0x6eff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x16, 0xe6ff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x17, 0x00ff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x18, 0x43ff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x19, 0xc3ff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x1a, 0x6fff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x1b, 0x07ff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x1c, 0x0fff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x1d, 0xe7ff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x1e, 0xefff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x20, 0xeeee);
-}
-
void ksz9477_get_caps(struct ksz_device *dev, int port,
struct phylink_config *config)
{
@@ -1029,20 +989,10 @@ void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
/* enable 802.1p priority */
ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_PRIO_ENABLE, true);
- if (dev->info->internal_phy[port]) {
- /* do not force flow control */
- ksz_port_cfg(dev, port, REG_PORT_CTRL_0,
- PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL,
- false);
-
- if (dev->info->phy_errata_9477)
- ksz9477_phy_errata_setup(dev, port);
- } else {
- /* force flow control */
- ksz_port_cfg(dev, port, REG_PORT_CTRL_0,
- PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL,
- true);
- }
+ /* force flow control for non-PHY ports only */
+ ksz_port_cfg(dev, port, REG_PORT_CTRL_0,
+ PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL,
+ !dev->info->internal_phy[port]);
if (cpu_port)
member = dsa_user_ports(ds);
@@ -1165,7 +1115,7 @@ int ksz9477_setup(struct dsa_switch *ds)
ksz_cfg(dev, REG_SW_MAC_CTRL_1, SW_JUMBO_PACKET, true);
/* Now we can configure default MTU value */
- ret = regmap_update_bits(dev->regmap[1], REG_SW_MTU__2, REG_SW_MTU_MASK,
+ ret = regmap_update_bits(ksz_regmap_16(dev), REG_SW_MTU__2, REG_SW_MTU_MASK,
VLAN_ETH_FRAME_LEN + ETH_FCS_LEN);
if (ret)
return ret;
diff --git a/drivers/net/dsa/microchip/ksz9477_i2c.c b/drivers/net/dsa/microchip/ksz9477_i2c.c
index 97a317263a2f..2710afad4f3a 100644
--- a/drivers/net/dsa/microchip/ksz9477_i2c.c
+++ b/drivers/net/dsa/microchip/ksz9477_i2c.c
@@ -24,7 +24,7 @@ static int ksz9477_i2c_probe(struct i2c_client *i2c)
if (!dev)
return -ENOMEM;
- for (i = 0; i < ARRAY_SIZE(ksz9477_regmap_config); i++) {
+ for (i = 0; i < __KSZ_NUM_REGMAPS; i++) {
rc = ksz9477_regmap_config[i];
rc.lock_arg = &dev->regmap_mutex;
dev->regmap[i] = devm_regmap_init_i2c(i2c, &rc);
@@ -119,7 +119,7 @@ static struct i2c_driver ksz9477_i2c_driver = {
.name = "ksz9477-switch",
.of_match_table = ksz9477_dt_ids,
},
- .probe_new = ksz9477_i2c_probe,
+ .probe = ksz9477_i2c_probe,
.remove = ksz9477_i2c_remove,
.shutdown = ksz9477_i2c_shutdown,
.id_table = ksz9477_i2c_id,
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index a4428be5f483..6c0623f88654 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -331,13 +331,13 @@ static const u32 ksz8795_masks[] = {
[STATIC_MAC_TABLE_VALID] = BIT(21),
[STATIC_MAC_TABLE_USE_FID] = BIT(23),
[STATIC_MAC_TABLE_FID] = GENMASK(30, 24),
- [STATIC_MAC_TABLE_OVERRIDE] = BIT(26),
- [STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(24, 20),
+ [STATIC_MAC_TABLE_OVERRIDE] = BIT(22),
+ [STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(20, 16),
[DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(6, 0),
- [DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(8),
+ [DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(7),
[DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7),
[DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 29),
- [DYNAMIC_MAC_TABLE_FID] = GENMASK(26, 20),
+ [DYNAMIC_MAC_TABLE_FID] = GENMASK(22, 16),
[DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(26, 24),
[DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(28, 27),
[P_MII_TX_FLOW_CTRL] = BIT(5),
@@ -635,10 +635,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
regmap_reg_range(0x1030, 0x1030),
regmap_reg_range(0x1100, 0x1115),
regmap_reg_range(0x111a, 0x111f),
- regmap_reg_range(0x1122, 0x1127),
- regmap_reg_range(0x112a, 0x112b),
- regmap_reg_range(0x1136, 0x1139),
- regmap_reg_range(0x113e, 0x113f),
+ regmap_reg_range(0x1120, 0x112b),
+ regmap_reg_range(0x1134, 0x113b),
+ regmap_reg_range(0x113c, 0x113f),
regmap_reg_range(0x1400, 0x1401),
regmap_reg_range(0x1403, 0x1403),
regmap_reg_range(0x1410, 0x1417),
@@ -669,10 +668,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
regmap_reg_range(0x2030, 0x2030),
regmap_reg_range(0x2100, 0x2115),
regmap_reg_range(0x211a, 0x211f),
- regmap_reg_range(0x2122, 0x2127),
- regmap_reg_range(0x212a, 0x212b),
- regmap_reg_range(0x2136, 0x2139),
- regmap_reg_range(0x213e, 0x213f),
+ regmap_reg_range(0x2120, 0x212b),
+ regmap_reg_range(0x2134, 0x213b),
+ regmap_reg_range(0x213c, 0x213f),
regmap_reg_range(0x2400, 0x2401),
regmap_reg_range(0x2403, 0x2403),
regmap_reg_range(0x2410, 0x2417),
@@ -703,10 +701,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
regmap_reg_range(0x3030, 0x3030),
regmap_reg_range(0x3100, 0x3115),
regmap_reg_range(0x311a, 0x311f),
- regmap_reg_range(0x3122, 0x3127),
- regmap_reg_range(0x312a, 0x312b),
- regmap_reg_range(0x3136, 0x3139),
- regmap_reg_range(0x313e, 0x313f),
+ regmap_reg_range(0x3120, 0x312b),
+ regmap_reg_range(0x3134, 0x313b),
+ regmap_reg_range(0x313c, 0x313f),
regmap_reg_range(0x3400, 0x3401),
regmap_reg_range(0x3403, 0x3403),
regmap_reg_range(0x3410, 0x3417),
@@ -737,10 +734,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
regmap_reg_range(0x4030, 0x4030),
regmap_reg_range(0x4100, 0x4115),
regmap_reg_range(0x411a, 0x411f),
- regmap_reg_range(0x4122, 0x4127),
- regmap_reg_range(0x412a, 0x412b),
- regmap_reg_range(0x4136, 0x4139),
- regmap_reg_range(0x413e, 0x413f),
+ regmap_reg_range(0x4120, 0x412b),
+ regmap_reg_range(0x4134, 0x413b),
+ regmap_reg_range(0x413c, 0x413f),
regmap_reg_range(0x4400, 0x4401),
regmap_reg_range(0x4403, 0x4403),
regmap_reg_range(0x4410, 0x4417),
@@ -771,10 +767,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
regmap_reg_range(0x5030, 0x5030),
regmap_reg_range(0x5100, 0x5115),
regmap_reg_range(0x511a, 0x511f),
- regmap_reg_range(0x5122, 0x5127),
- regmap_reg_range(0x512a, 0x512b),
- regmap_reg_range(0x5136, 0x5139),
- regmap_reg_range(0x513e, 0x513f),
+ regmap_reg_range(0x5120, 0x512b),
+ regmap_reg_range(0x5134, 0x513b),
+ regmap_reg_range(0x513c, 0x513f),
regmap_reg_range(0x5400, 0x5401),
regmap_reg_range(0x5403, 0x5403),
regmap_reg_range(0x5410, 0x5417),
@@ -1075,6 +1070,45 @@ static const struct regmap_access_table ksz9896_register_set = {
.n_yes_ranges = ARRAY_SIZE(ksz9896_valid_regs),
};
+static const struct regmap_range ksz8873_valid_regs[] = {
+ regmap_reg_range(0x00, 0x01),
+ /* global control register */
+ regmap_reg_range(0x02, 0x0f),
+
+ /* port registers */
+ regmap_reg_range(0x10, 0x1d),
+ regmap_reg_range(0x1e, 0x1f),
+ regmap_reg_range(0x20, 0x2d),
+ regmap_reg_range(0x2e, 0x2f),
+ regmap_reg_range(0x30, 0x39),
+ regmap_reg_range(0x3f, 0x3f),
+
+ /* advanced control registers */
+ regmap_reg_range(0x60, 0x6f),
+ regmap_reg_range(0x70, 0x75),
+ regmap_reg_range(0x76, 0x78),
+ regmap_reg_range(0x79, 0x7a),
+ regmap_reg_range(0x7b, 0x83),
+ regmap_reg_range(0x8e, 0x99),
+ regmap_reg_range(0x9a, 0xa5),
+ regmap_reg_range(0xa6, 0xa6),
+ regmap_reg_range(0xa7, 0xaa),
+ regmap_reg_range(0xab, 0xae),
+ regmap_reg_range(0xaf, 0xba),
+ regmap_reg_range(0xbb, 0xbc),
+ regmap_reg_range(0xbd, 0xbd),
+ regmap_reg_range(0xc0, 0xc0),
+ regmap_reg_range(0xc2, 0xc2),
+ regmap_reg_range(0xc3, 0xc3),
+ regmap_reg_range(0xc4, 0xc4),
+ regmap_reg_range(0xc6, 0xc6),
+};
+
+static const struct regmap_access_table ksz8873_register_set = {
+ .yes_ranges = ksz8873_valid_regs,
+ .n_yes_ranges = ARRAY_SIZE(ksz8873_valid_regs),
+};
+
const struct ksz_chip_data ksz_switch_chips[] = {
[KSZ8563] = {
.chip_id = KSZ8563_CHIP_ID,
@@ -1214,6 +1248,8 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.supports_mii = {false, false, true},
.supports_rmii = {false, false, true},
.internal_phy = {true, true, false},
+ .wr_table = &ksz8873_register_set,
+ .rd_table = &ksz8873_register_set,
},
[KSZ9477] = {
@@ -1229,7 +1265,6 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.tc_cbs_supported = true,
.tc_ets_supported = true,
.ops = &ksz9477_dev_ops,
- .phy_errata_9477 = true,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
.reg_mib_cnt = MIB_COUNTER_NUM,
@@ -1262,7 +1297,6 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.port_nirqs = 2,
.num_tx_queues = 4,
.ops = &ksz9477_dev_ops,
- .phy_errata_9477 = true,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
.reg_mib_cnt = MIB_COUNTER_NUM,
@@ -1295,7 +1329,6 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.port_nirqs = 2,
.num_tx_queues = 4,
.ops = &ksz9477_dev_ops,
- .phy_errata_9477 = true,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
.reg_mib_cnt = MIB_COUNTER_NUM,
@@ -1382,7 +1415,6 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.tc_cbs_supported = true,
.tc_ets_supported = true,
.ops = &ksz9477_dev_ops,
- .phy_errata_9477 = true,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
.reg_mib_cnt = MIB_COUNTER_NUM,
@@ -2095,7 +2127,7 @@ static int ksz_setup(struct dsa_switch *ds)
}
/* set broadcast storm protection 10% rate */
- regmap_update_bits(dev->regmap[1], regs[S_BROADCAST_CTRL],
+ regmap_update_bits(ksz_regmap_16(dev), regs[S_BROADCAST_CTRL],
BROADCAST_STORM_RATE,
(BROADCAST_STORM_VALUE *
BROADCAST_STORM_PROT_RATE) / 100);
@@ -2106,7 +2138,7 @@ static int ksz_setup(struct dsa_switch *ds)
ds->num_tx_queues = dev->info->num_tx_queues;
- regmap_update_bits(dev->regmap[0], regs[S_MULTICAST_CTRL],
+ regmap_update_bits(ksz_regmap_8(dev), regs[S_MULTICAST_CTRL],
MULTICAST_STORM_DISABLE, MULTICAST_STORM_DISABLE);
ksz_init_mib_timer(dev);
@@ -2156,7 +2188,7 @@ static int ksz_setup(struct dsa_switch *ds)
}
/* start switch */
- regmap_update_bits(dev->regmap[0], regs[S_START_CTRL],
+ regmap_update_bits(ksz_regmap_8(dev), regs[S_START_CTRL],
SW_START, SW_START);
return 0;
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 8abecaf6089e..a4de58847dea 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -22,6 +22,13 @@
struct ksz_device;
struct ksz_port;
+enum ksz_regmap_width {
+ KSZ_REGMAP_8,
+ KSZ_REGMAP_16,
+ KSZ_REGMAP_32,
+ __KSZ_NUM_REGMAPS,
+};
+
struct vlan_table {
u32 table[3];
};
@@ -53,7 +60,6 @@ struct ksz_chip_data {
bool tc_cbs_supported;
bool tc_ets_supported;
const struct ksz_dev_ops *ops;
- bool phy_errata_9477;
bool ksz87xx_eee_link_erratum;
const struct ksz_mib_names *mib_names;
int mib_cnt;
@@ -101,7 +107,6 @@ struct ksz_port {
int stp_state;
struct phy_device phydev;
- u32 on:1; /* port is not disabled by hardware */
u32 fiber:1; /* port is fiber */
u32 force:1;
u32 read:1; /* read MIB counters in background */
@@ -137,7 +142,7 @@ struct ksz_device {
const struct ksz_dev_ops *dev_ops;
struct device *dev;
- struct regmap *regmap[3];
+ struct regmap *regmap[__KSZ_NUM_REGMAPS];
void *priv;
int irq;
@@ -377,11 +382,25 @@ phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit);
extern const struct ksz_chip_data ksz_switch_chips[];
/* Common register access functions */
+static inline struct regmap *ksz_regmap_8(struct ksz_device *dev)
+{
+ return dev->regmap[KSZ_REGMAP_8];
+}
+
+static inline struct regmap *ksz_regmap_16(struct ksz_device *dev)
+{
+ return dev->regmap[KSZ_REGMAP_16];
+}
+
+static inline struct regmap *ksz_regmap_32(struct ksz_device *dev)
+{
+ return dev->regmap[KSZ_REGMAP_32];
+}
static inline int ksz_read8(struct ksz_device *dev, u32 reg, u8 *val)
{
unsigned int value;
- int ret = regmap_read(dev->regmap[0], reg, &value);
+ int ret = regmap_read(ksz_regmap_8(dev), reg, &value);
if (ret)
dev_err(dev->dev, "can't read 8bit reg: 0x%x %pe\n", reg,
@@ -394,7 +413,7 @@ static inline int ksz_read8(struct ksz_device *dev, u32 reg, u8 *val)
static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val)
{
unsigned int value;
- int ret = regmap_read(dev->regmap[1], reg, &value);
+ int ret = regmap_read(ksz_regmap_16(dev), reg, &value);
if (ret)
dev_err(dev->dev, "can't read 16bit reg: 0x%x %pe\n", reg,
@@ -407,7 +426,7 @@ static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val)
static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val)
{
unsigned int value;
- int ret = regmap_read(dev->regmap[2], reg, &value);
+ int ret = regmap_read(ksz_regmap_32(dev), reg, &value);
if (ret)
dev_err(dev->dev, "can't read 32bit reg: 0x%x %pe\n", reg,
@@ -422,7 +441,7 @@ static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val)
u32 value[2];
int ret;
- ret = regmap_bulk_read(dev->regmap[2], reg, value, 2);
+ ret = regmap_bulk_read(ksz_regmap_32(dev), reg, value, 2);
if (ret)
dev_err(dev->dev, "can't read 64bit reg: 0x%x %pe\n", reg,
ERR_PTR(ret));
@@ -436,7 +455,7 @@ static inline int ksz_write8(struct ksz_device *dev, u32 reg, u8 value)
{
int ret;
- ret = regmap_write(dev->regmap[0], reg, value);
+ ret = regmap_write(ksz_regmap_8(dev), reg, value);
if (ret)
dev_err(dev->dev, "can't write 8bit reg: 0x%x %pe\n", reg,
ERR_PTR(ret));
@@ -448,7 +467,7 @@ static inline int ksz_write16(struct ksz_device *dev, u32 reg, u16 value)
{
int ret;
- ret = regmap_write(dev->regmap[1], reg, value);
+ ret = regmap_write(ksz_regmap_16(dev), reg, value);
if (ret)
dev_err(dev->dev, "can't write 16bit reg: 0x%x %pe\n", reg,
ERR_PTR(ret));
@@ -460,7 +479,7 @@ static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value)
{
int ret;
- ret = regmap_write(dev->regmap[2], reg, value);
+ ret = regmap_write(ksz_regmap_32(dev), reg, value);
if (ret)
dev_err(dev->dev, "can't write 32bit reg: 0x%x %pe\n", reg,
ERR_PTR(ret));
@@ -473,7 +492,7 @@ static inline int ksz_rmw16(struct ksz_device *dev, u32 reg, u16 mask,
{
int ret;
- ret = regmap_update_bits(dev->regmap[1], reg, mask, value);
+ ret = regmap_update_bits(ksz_regmap_16(dev), reg, mask, value);
if (ret)
dev_err(dev->dev, "can't rmw 16bit reg 0x%x: %pe\n", reg,
ERR_PTR(ret));
@@ -486,7 +505,7 @@ static inline int ksz_rmw32(struct ksz_device *dev, u32 reg, u32 mask,
{
int ret;
- ret = regmap_update_bits(dev->regmap[2], reg, mask, value);
+ ret = regmap_update_bits(ksz_regmap_32(dev), reg, mask, value);
if (ret)
dev_err(dev->dev, "can't rmw 32bit reg 0x%x: %pe\n", reg,
ERR_PTR(ret));
@@ -503,12 +522,19 @@ static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value)
val[0] = swab32(value & 0xffffffffULL);
val[1] = swab32(value >> 32ULL);
- return regmap_bulk_write(dev->regmap[2], reg, val, 2);
+ return regmap_bulk_write(ksz_regmap_32(dev), reg, val, 2);
}
static inline int ksz_rmw8(struct ksz_device *dev, int offset, u8 mask, u8 val)
{
- return regmap_update_bits(dev->regmap[0], offset, mask, val);
+ int ret;
+
+ ret = regmap_update_bits(ksz_regmap_8(dev), offset, mask, val);
+ if (ret)
+ dev_err(dev->dev, "can't rmw 8bit reg 0x%x: %pe\n", offset,
+ ERR_PTR(ret));
+
+ return ret;
}
static inline int ksz_pread8(struct ksz_device *dev, int port, int offset,
@@ -549,12 +575,18 @@ static inline int ksz_pwrite32(struct ksz_device *dev, int port, int offset,
data);
}
-static inline void ksz_prmw8(struct ksz_device *dev, int port, int offset,
- u8 mask, u8 val)
+static inline int ksz_prmw8(struct ksz_device *dev, int port, int offset,
+ u8 mask, u8 val)
{
- regmap_update_bits(dev->regmap[0],
- dev->dev_ops->get_port_addr(port, offset),
- mask, val);
+ return ksz_rmw8(dev, dev->dev_ops->get_port_addr(port, offset),
+ mask, val);
+}
+
+static inline int ksz_prmw32(struct ksz_device *dev, int port, int offset,
+ u32 mask, u32 val)
+{
+ return ksz_rmw32(dev, dev->dev_ops->get_port_addr(port, offset),
+ mask, val);
}
static inline void ksz_regmap_lock(void *__mtx)
@@ -569,6 +601,13 @@ static inline void ksz_regmap_unlock(void *__mtx)
mutex_unlock(mtx);
}
+static inline bool ksz_is_ksz87xx(struct ksz_device *dev)
+{
+ return dev->chip_id == KSZ8795_CHIP_ID ||
+ dev->chip_id == KSZ8794_CHIP_ID ||
+ dev->chip_id == KSZ8765_CHIP_ID;
+}
+
static inline bool ksz_is_ksz88x3(struct ksz_device *dev)
{
return dev->chip_id == KSZ8830_CHIP_ID;
@@ -709,9 +748,9 @@ static inline int is_lan937x(struct ksz_device *dev)
#define KSZ_REGMAP_TABLE(ksz, swp, regbits, regpad, regalign) \
static const struct regmap_config ksz##_regmap_config[] = { \
- KSZ_REGMAP_ENTRY(8, swp, (regbits), (regpad), (regalign)), \
- KSZ_REGMAP_ENTRY(16, swp, (regbits), (regpad), (regalign)), \
- KSZ_REGMAP_ENTRY(32, swp, (regbits), (regpad), (regalign)), \
+ [KSZ_REGMAP_8] = KSZ_REGMAP_ENTRY(8, swp, (regbits), (regpad), (regalign)), \
+ [KSZ_REGMAP_16] = KSZ_REGMAP_ENTRY(16, swp, (regbits), (regpad), (regalign)), \
+ [KSZ_REGMAP_32] = KSZ_REGMAP_ENTRY(32, swp, (regbits), (regpad), (regalign)), \
}
#endif
diff --git a/drivers/net/dsa/microchip/ksz_spi.c b/drivers/net/dsa/microchip/ksz_spi.c
index 96c52e8fb51b..279338451621 100644
--- a/drivers/net/dsa/microchip/ksz_spi.c
+++ b/drivers/net/dsa/microchip/ksz_spi.c
@@ -63,7 +63,7 @@ static int ksz_spi_probe(struct spi_device *spi)
else
regmap_config = ksz9477_regmap_config;
- for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) {
+ for (i = 0; i < __KSZ_NUM_REGMAPS; i++) {
rc = regmap_config[i];
rc.lock_arg = &dev->regmap_mutex;
rc.wr_table = chip->wr_table;
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index 399a3905e6ca..b479a628b1ae 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -20,13 +20,13 @@
static int lan937x_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
{
- return regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0);
+ return regmap_update_bits(ksz_regmap_8(dev), addr, bits, set ? bits : 0);
}
static int lan937x_port_cfg(struct ksz_device *dev, int port, int offset,
u8 bits, bool set)
{
- return regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset),
+ return regmap_update_bits(ksz_regmap_8(dev), PORT_CTRL_ADDR(port, offset),
bits, set ? bits : 0);
}
@@ -86,7 +86,7 @@ static int lan937x_internal_phy_write(struct ksz_device *dev, int addr, int reg,
if (ret < 0)
return ret;
- ret = regmap_read_poll_timeout(dev->regmap[1], REG_VPHY_IND_CTRL__2,
+ ret = regmap_read_poll_timeout(ksz_regmap_16(dev), REG_VPHY_IND_CTRL__2,
value, !(value & VPHY_IND_BUSY), 10,
1000);
if (ret < 0) {
@@ -116,7 +116,7 @@ static int lan937x_internal_phy_read(struct ksz_device *dev, int addr, int reg,
if (ret < 0)
return ret;
- ret = regmap_read_poll_timeout(dev->regmap[1], REG_VPHY_IND_CTRL__2,
+ ret = regmap_read_poll_timeout(ksz_regmap_16(dev), REG_VPHY_IND_CTRL__2,
value, !(value & VPHY_IND_BUSY), 10,
1000);
if (ret < 0) {
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 7e773c4ba046..b8bb9f3b3609 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -1006,6 +1006,10 @@ mt753x_trap_frames(struct mt7530_priv *priv)
mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
MT753X_BPDU_CPU_ONLY);
+ /* Trap 802.1X PAE frames to the CPU port(s) */
+ mt7530_rmw(priv, MT753X_BPC, MT753X_PAE_PORT_FW_MASK,
+ MT753X_PAE_PORT_FW(MT753X_BPDU_CPU_ONLY));
+
/* Trap LLDP frames with :0E MAC DA to the CPU port(s) */
mt7530_rmw(priv, MT753X_RGAC2, MT753X_R0E_PORT_FW_MASK,
MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY));
@@ -3005,7 +3009,7 @@ static void mt7530_pcs_get_state(struct phylink_pcs *pcs,
state->pause |= MLO_PAUSE_TX;
}
-static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -3033,6 +3037,7 @@ mt753x_setup(struct dsa_switch *ds)
/* Initialise the PCS devices */
for (i = 0; i < priv->ds->num_ports; i++) {
priv->pcs[i].pcs.ops = priv->info->pcs_ops;
+ priv->pcs[i].pcs.neg_mode = true;
priv->pcs[i].priv = priv;
priv->pcs[i].port = i;
}
diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
index 08045b035e6a..17e42d30fff4 100644
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -66,6 +66,8 @@ enum mt753x_id {
/* Registers for BPDU and PAE frame control*/
#define MT753X_BPC 0x24
#define MT753X_BPDU_PORT_FW_MASK GENMASK(2, 0)
+#define MT753X_PAE_PORT_FW_MASK GENMASK(18, 16)
+#define MT753X_PAE_PORT_FW(x) FIELD_PREP(MT753X_PAE_PORT_FW_MASK, x)
/* Register for :03 and :0E MAC DA frame control */
#define MT753X_RGAC2 0x2c
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 08a46ffd53af..7af2f08a62f1 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -109,6 +109,13 @@ int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
usleep_range(1000, 2000);
}
+ err = mv88e6xxx_read(chip, addr, reg, &data);
+ if (err)
+ return err;
+
+ if ((data & mask) == val)
+ return 0;
+
dev_err(chip->dev, "Timeout while waiting for switch\n");
return -ETIMEDOUT;
}
@@ -463,11 +470,11 @@ restore_link:
return err;
}
-static int mv88e6xxx_phy_is_internal(struct dsa_switch *ds, int port)
+static int mv88e6xxx_phy_is_internal(struct mv88e6xxx_chip *chip, int port)
{
- struct mv88e6xxx_chip *chip = ds->priv;
-
- return port < chip->info->num_internal_phys;
+ return port >= chip->info->internal_phys_offset &&
+ port < chip->info->num_internal_phys +
+ chip->info->internal_phys_offset;
}
static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port)
@@ -479,7 +486,7 @@ static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port)
* report whether the port is internal.
*/
if (chip->info->family == MV88E6XXX_FAMILY_6250)
- return port < chip->info->num_internal_phys;
+ return mv88e6xxx_phy_is_internal(chip, port);
err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
if (err) {
@@ -584,7 +591,7 @@ static void mv88e6095_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100;
- if (mv88e6xxx_phy_is_internal(chip->ds, port)) {
+ if (mv88e6xxx_phy_is_internal(chip, port)) {
__set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces);
} else {
if (cmode < ARRAY_SIZE(mv88e6185_phy_interface_modes) &&
@@ -790,6 +797,8 @@ static void mv88e6393x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
unsigned long *supported = config->supported_interfaces;
bool is_6191x =
chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6191X;
+ bool is_6361 =
+ chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361;
mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported);
@@ -804,13 +813,16 @@ static void mv88e6393x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
/* 6191X supports >1G modes only on port 10 */
if (!is_6191x || port == 10) {
__set_bit(PHY_INTERFACE_MODE_2500BASEX, supported);
- __set_bit(PHY_INTERFACE_MODE_5GBASER, supported);
- __set_bit(PHY_INTERFACE_MODE_10GBASER, supported);
- /* FIXME: USXGMII is not supported yet */
- /* __set_bit(PHY_INTERFACE_MODE_USXGMII, supported); */
-
- config->mac_capabilities |= MAC_2500FD | MAC_5000FD |
- MAC_10000FD;
+ config->mac_capabilities |= MAC_2500FD;
+
+ /* 6361 only supports up to 2500BaseX */
+ if (!is_6361) {
+ __set_bit(PHY_INTERFACE_MODE_5GBASER, supported);
+ __set_bit(PHY_INTERFACE_MODE_10GBASER, supported);
+ __set_bit(PHY_INTERFACE_MODE_USXGMII, supported);
+ config->mac_capabilities |= MAC_5000FD |
+ MAC_10000FD;
+ }
}
}
@@ -832,7 +844,7 @@ static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port,
chip->info->ops->phylink_get_caps(chip, port, config);
mv88e6xxx_reg_unlock(chip);
- if (mv88e6xxx_phy_is_internal(ds, port)) {
+ if (mv88e6xxx_phy_is_internal(chip, port)) {
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
config->supported_interfaces);
/* Internal ports with no phy-mode need GMII for PHYLIB */
@@ -841,29 +853,38 @@ static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port,
}
}
+static int mv88e6xxx_mac_prepare(struct dsa_switch *ds, int port,
+ unsigned int mode, phy_interface_t interface)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+ int err = 0;
+
+ /* In inband mode, the link may come up at any time while the link
+ * is not forced down. Force the link down while we reconfigure the
+ * interface mode.
+ */
+ if (mode == MLO_AN_INBAND &&
+ chip->ports[port].interface != interface &&
+ chip->info->ops->port_set_link) {
+ mv88e6xxx_reg_lock(chip);
+ err = chip->info->ops->port_set_link(chip, port,
+ LINK_FORCED_DOWN);
+ mv88e6xxx_reg_unlock(chip);
+ }
+
+ return err;
+}
+
static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
unsigned int mode,
const struct phylink_link_state *state)
{
struct mv88e6xxx_chip *chip = ds->priv;
- struct mv88e6xxx_port *p;
int err = 0;
- p = &chip->ports[port];
-
mv88e6xxx_reg_lock(chip);
- if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(ds, port)) {
- /* In inband mode, the link may come up at any time while the
- * link is not forced down. Force the link down while we
- * reconfigure the interface mode.
- */
- if (mode == MLO_AN_INBAND &&
- p->interface != state->interface &&
- chip->info->ops->port_set_link)
- chip->info->ops->port_set_link(chip, port,
- LINK_FORCED_DOWN);
-
+ if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(chip, port)) {
err = mv88e6xxx_port_config_interface(chip, port,
state->interface);
if (err && err != -EOPNOTSUPP)
@@ -880,24 +901,38 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
err = 0;
}
+err_unlock:
+ mv88e6xxx_reg_unlock(chip);
+
+ if (err && err != -EOPNOTSUPP)
+ dev_err(ds->dev, "p%d: failed to configure MAC/PCS\n", port);
+}
+
+static int mv88e6xxx_mac_finish(struct dsa_switch *ds, int port,
+ unsigned int mode, phy_interface_t interface)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+ int err = 0;
+
/* Undo the forced down state above after completing configuration
* irrespective of its state on entry, which allows the link to come
* up in the in-band case where there is no separate SERDES. Also
* ensure that the link can come up if the PPU is in use and we are
* in PHY mode (we treat the PPU as an effective in-band mechanism.)
*/
+ mv88e6xxx_reg_lock(chip);
+
if (chip->info->ops->port_set_link &&
- ((mode == MLO_AN_INBAND && p->interface != state->interface) ||
+ ((mode == MLO_AN_INBAND &&
+ chip->ports[port].interface != interface) ||
(mode == MLO_AN_PHY && mv88e6xxx_port_ppu_updates(chip, port))))
- chip->info->ops->port_set_link(chip, port, LINK_UNFORCED);
-
- p->interface = state->interface;
+ err = chip->info->ops->port_set_link(chip, port, LINK_UNFORCED);
-err_unlock:
mv88e6xxx_reg_unlock(chip);
- if (err && err != -EOPNOTSUPP)
- dev_err(ds->dev, "p%d: failed to configure MAC/PCS\n", port);
+ chip->ports[port].interface = interface;
+
+ return err;
}
static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port,
@@ -2999,6 +3034,14 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
/* If there is a GPIO connected to the reset pin, toggle it */
if (gpiod) {
+ /* If the switch has just been reset and not yet completed
+ * loading EEPROM, the reset may interrupt the I2C transaction
+ * mid-byte, causing the first EEPROM read after the reset
+ * from the wrong location resulting in the switch booting
+ * to wrong mode and inoperable.
+ */
+ mv88e6xxx_g1_wait_eeprom_done(chip);
+
gpiod_set_value_cansleep(gpiod, 1);
usleep_range(10000, 20000);
gpiod_set_value_cansleep(gpiod, 0);
@@ -3311,7 +3354,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
caps = pl_config.mac_capabilities;
if (chip->info->ops->port_max_speed_mode)
- mode = chip->info->ops->port_max_speed_mode(port);
+ mode = chip->info->ops->port_max_speed_mode(chip, port);
else
mode = PHY_INTERFACE_MODE_NA;
@@ -5043,6 +5086,7 @@ static const struct mv88e6xxx_ops mv88e6250_ops = {
.avb_ops = &mv88e6352_avb_ops,
.ptp_ops = &mv88e6250_ptp_ops,
.phylink_get_caps = mv88e6250_phylink_get_caps,
+ .set_max_frame_size = mv88e6185_g1_set_max_frame_size,
};
static const struct mv88e6xxx_ops mv88e6290_ops = {
@@ -5642,6 +5686,46 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
};
static const struct mv88e6xxx_info mv88e6xxx_table[] = {
+ [MV88E6020] = {
+ .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6020,
+ .family = MV88E6XXX_FAMILY_6250,
+ .name = "Marvell 88E6020",
+ .num_databases = 64,
+ .num_ports = 4,
+ .num_internal_phys = 2,
+ .max_vid = 4095,
+ .port_base_addr = 0x8,
+ .phy_base_addr = 0x0,
+ .global1_addr = 0xf,
+ .global2_addr = 0x7,
+ .age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .g2_irqs = 5,
+ .atu_move_port_mask = 0xf,
+ .dual_chip = true,
+ .ops = &mv88e6250_ops,
+ },
+
+ [MV88E6071] = {
+ .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6071,
+ .family = MV88E6XXX_FAMILY_6250,
+ .name = "Marvell 88E6071",
+ .num_databases = 64,
+ .num_ports = 7,
+ .num_internal_phys = 5,
+ .max_vid = 4095,
+ .port_base_addr = 0x08,
+ .phy_base_addr = 0x00,
+ .global1_addr = 0x0f,
+ .global2_addr = 0x07,
+ .age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .g2_irqs = 5,
+ .atu_move_port_mask = 0xf,
+ .dual_chip = true,
+ .ops = &mv88e6250_ops,
+ },
+
[MV88E6085] = {
.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6085,
.family = MV88E6XXX_FAMILY_6097,
@@ -6024,7 +6108,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.name = "Marvell 88E6191X",
.num_databases = 4096,
.num_ports = 11, /* 10 + Z80 */
- .num_internal_phys = 9,
+ .num_internal_phys = 8,
+ .internal_phys_offset = 1,
.max_vid = 8191,
.max_sid = 63,
.port_base_addr = 0x0,
@@ -6047,7 +6132,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.name = "Marvell 88E6193X",
.num_databases = 4096,
.num_ports = 11, /* 10 + Z80 */
- .num_internal_phys = 9,
+ .num_internal_phys = 8,
+ .internal_phys_offset = 1,
.max_vid = 8191,
.max_sid = 63,
.port_base_addr = 0x0,
@@ -6309,6 +6395,32 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.ptp_support = true,
.ops = &mv88e6352_ops,
},
+ [MV88E6361] = {
+ .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6361,
+ .family = MV88E6XXX_FAMILY_6393,
+ .name = "Marvell 88E6361",
+ .num_databases = 4096,
+ .num_macs = 16384,
+ .num_ports = 11,
+ /* Ports 1, 2 and 8 are not routed */
+ .invalid_port_mask = BIT(1) | BIT(2) | BIT(8),
+ .num_internal_phys = 5,
+ .internal_phys_offset = 3,
+ .max_vid = 4095,
+ .max_sid = 63,
+ .port_base_addr = 0x0,
+ .phy_base_addr = 0x0,
+ .global1_addr = 0x1b,
+ .global2_addr = 0x1c,
+ .age_time_coeff = 3750,
+ .g1_irqs = 10,
+ .g2_irqs = 14,
+ .atu_move_port_mask = 0x1f,
+ .pvt = true,
+ .multi_chip = true,
+ .ptp_support = true,
+ .ops = &mv88e6393x_ops,
+ },
[MV88E6390] = {
.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390,
.family = MV88E6XXX_FAMILY_6390,
@@ -6366,7 +6478,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.name = "Marvell 88E6393X",
.num_databases = 4096,
.num_ports = 11, /* 10 + Z80 */
- .num_internal_phys = 9,
+ .num_internal_phys = 8,
+ .internal_phys_offset = 1,
.max_vid = 8191,
.max_sid = 63,
.port_base_addr = 0x0,
@@ -7002,7 +7115,9 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
.port_teardown = mv88e6xxx_port_teardown,
.phylink_get_caps = mv88e6xxx_get_caps,
.phylink_mac_link_state = mv88e6xxx_serdes_pcs_get_state,
+ .phylink_mac_prepare = mv88e6xxx_mac_prepare,
.phylink_mac_config = mv88e6xxx_mac_config,
+ .phylink_mac_finish = mv88e6xxx_mac_finish,
.phylink_mac_an_restart = mv88e6xxx_serdes_pcs_an_restart,
.phylink_mac_link_down = mv88e6xxx_mac_link_down,
.phylink_mac_link_up = mv88e6xxx_mac_link_up,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index da6e1339f809..0ad34b2d8913 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -54,6 +54,8 @@ enum mv88e6xxx_frame_mode {
/* List of supported models */
enum mv88e6xxx_model {
+ MV88E6020,
+ MV88E6071,
MV88E6085,
MV88E6095,
MV88E6097,
@@ -82,6 +84,7 @@ enum mv88e6xxx_model {
MV88E6350,
MV88E6351,
MV88E6352,
+ MV88E6361,
MV88E6390,
MV88E6390X,
MV88E6393X,
@@ -94,13 +97,13 @@ enum mv88e6xxx_family {
MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */
MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */
MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */
- MV88E6XXX_FAMILY_6250, /* 6220 6250 */
+ MV88E6XXX_FAMILY_6250, /* 6220 6250 6020 6071 */
MV88E6XXX_FAMILY_6320, /* 6320 6321 */
MV88E6XXX_FAMILY_6341, /* 6141 6341 */
MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */
MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */
MV88E6XXX_FAMILY_6390, /* 6190 6190X 6191 6290 6390 6390X */
- MV88E6XXX_FAMILY_6393, /* 6191X 6193X 6393X */
+ MV88E6XXX_FAMILY_6393, /* 6191X 6193X 6361 6393X */
};
/**
@@ -167,6 +170,11 @@ struct mv88e6xxx_info {
/* Supports PTP */
bool ptp_support;
+
+ /* Internal PHY start index. 0 means that internal PHYs range starts at
+ * port 0, 1 means internal PHYs range starts at port 1, etc
+ */
+ unsigned int internal_phys_offset;
};
struct mv88e6xxx_atu_entry {
@@ -513,7 +521,8 @@ struct mv88e6xxx_ops {
int speed, int duplex);
/* What interface mode should be used for maximum speed? */
- phy_interface_t (*port_max_speed_mode)(int port);
+ phy_interface_t (*port_max_speed_mode)(struct mv88e6xxx_chip *chip,
+ int port);
int (*port_tag_remap)(struct mv88e6xxx_chip *chip, int port);
diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
index 615896893076..937a01f2ba75 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -1196,9 +1196,12 @@ out:
int mv88e6xxx_g2_irq_mdio_setup(struct mv88e6xxx_chip *chip,
struct mii_bus *bus)
{
+ int phy_start = chip->info->internal_phys_offset;
+ int phy_end = chip->info->internal_phys_offset +
+ chip->info->num_internal_phys;
int phy, irq;
- for (phy = 0; phy < chip->info->num_internal_phys; phy++) {
+ for (phy = phy_start; phy < phy_end; phy++) {
irq = irq_find_mapping(chip->g2_irq.domain, phy);
if (irq < 0)
return irq;
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index f79cf716c541..dd66ec902d4c 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -342,7 +342,8 @@ int mv88e6341_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
duplex);
}
-phy_interface_t mv88e6341_port_max_speed_mode(int port)
+phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip,
+ int port)
{
if (port == 5)
return PHY_INTERFACE_MODE_2500BASEX;
@@ -381,7 +382,8 @@ int mv88e6390_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
duplex);
}
-phy_interface_t mv88e6390_port_max_speed_mode(int port)
+phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip,
+ int port)
{
if (port == 9 || port == 10)
return PHY_INTERFACE_MODE_2500BASEX;
@@ -403,7 +405,8 @@ int mv88e6390x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
duplex);
}
-phy_interface_t mv88e6390x_port_max_speed_mode(int port)
+phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip,
+ int port)
{
if (port == 9 || port == 10)
return PHY_INTERFACE_MODE_XAUI;
@@ -421,6 +424,10 @@ int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
u16 reg, ctrl;
int err;
+ if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361 &&
+ speed > 2500)
+ return -EOPNOTSUPP;
+
if (speed == 200 && port != 0)
return -EOPNOTSUPP;
@@ -500,12 +507,17 @@ int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
return 0;
}
-phy_interface_t mv88e6393x_port_max_speed_mode(int port)
+phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip,
+ int port)
{
- if (port == 0 || port == 9 || port == 10)
- return PHY_INTERFACE_MODE_10GBASER;
- return PHY_INTERFACE_MODE_NA;
+ if (port != 0 && port != 9 && port != 10)
+ return PHY_INTERFACE_MODE_NA;
+
+ if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361)
+ return PHY_INTERFACE_MODE_2500BASEX;
+
+ return PHY_INTERFACE_MODE_10GBASER;
}
static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
@@ -554,6 +566,9 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
case PHY_INTERFACE_MODE_10GBASER:
cmode = MV88E6393X_PORT_STS_CMODE_10GBASER;
break;
+ case PHY_INTERFACE_MODE_USXGMII:
+ cmode = MV88E6393X_PORT_STS_CMODE_USXGMII;
+ break;
default:
cmode = 0;
}
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index d19b6303b91f..86deeb347cbc 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -111,6 +111,8 @@
/* Offset 0x03: Switch Identifier Register */
#define MV88E6XXX_PORT_SWITCH_ID 0x03
#define MV88E6XXX_PORT_SWITCH_ID_PROD_MASK 0xfff0
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6020 0x0200
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6071 0x0710
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6085 0x04a0
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6095 0x0950
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6097 0x0990
@@ -133,6 +135,7 @@
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6220 0x2200
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6250 0x2500
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6361 0x2610
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6321 0x3100
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6141 0x3400
@@ -359,10 +362,14 @@ int mv88e6390x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int speed, int duplex);
-phy_interface_t mv88e6341_port_max_speed_mode(int port);
-phy_interface_t mv88e6390_port_max_speed_mode(int port);
-phy_interface_t mv88e6390x_port_max_speed_mode(int port);
-phy_interface_t mv88e6393x_port_max_speed_mode(int port);
+phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip,
+ int port);
+phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip,
+ int port);
+phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip,
+ int port);
+phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip,
+ int port);
int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state);
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index 72faec8f44dc..80167d53212f 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -683,7 +683,8 @@ int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode == MV88E6393X_PORT_STS_CMODE_5GBASER ||
- cmode == MV88E6393X_PORT_STS_CMODE_10GBASER)
+ cmode == MV88E6393X_PORT_STS_CMODE_10GBASER ||
+ cmode == MV88E6393X_PORT_STS_CMODE_USXGMII)
lane = port;
return lane;
@@ -984,7 +985,42 @@ static int mv88e6393x_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip,
state->speed = SPEED_10000;
state->duplex = DUPLEX_FULL;
}
+ return 0;
+}
+
+/* USXGMII registers for Marvell switch 88e639x are undocumented and this function is based
+ * on some educated guesses. It appears that there are no status bits related to
+ * autonegotiation complete or flow control.
+ */
+static int mv88e639x_serdes_pcs_get_state_usxgmii(struct mv88e6xxx_chip *chip,
+ int port, int lane,
+ struct phylink_link_state *state)
+{
+ u16 status, lp_status;
+ int err;
+ err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
+ MV88E6390_USXGMII_PHY_STATUS, &status);
+ if (err) {
+ dev_err(chip->dev, "can't read Serdes USXGMII PHY status: %d\n", err);
+ return err;
+ }
+ dev_dbg(chip->dev, "USXGMII PHY status: 0x%x\n", status);
+
+ state->link = !!(status & MDIO_USXGMII_LINK);
+ state->an_complete = state->link;
+
+ if (state->link) {
+ err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
+ MV88E6390_USXGMII_LP_STATUS, &lp_status);
+ if (err) {
+ dev_err(chip->dev, "can't read Serdes USXGMII LP status: %d\n", err);
+ return err;
+ }
+ dev_dbg(chip->dev, "USXGMII LP status: 0x%x\n", lp_status);
+ /* lp_status appears to include the "link" bit as per USXGMII spec. */
+ phylink_decode_usxgmii_word(state, lp_status);
+ }
return 0;
}
@@ -1020,6 +1056,9 @@ int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
case PHY_INTERFACE_MODE_10GBASER:
return mv88e6393x_serdes_pcs_get_state_10g(chip, port, lane,
state);
+ case PHY_INTERFACE_MODE_USXGMII:
+ return mv88e639x_serdes_pcs_get_state_usxgmii(chip, port, lane,
+ state);
default:
return -EOPNOTSUPP;
@@ -1173,6 +1212,7 @@ int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
case MV88E6393X_PORT_STS_CMODE_5GBASER:
case MV88E6393X_PORT_STS_CMODE_10GBASER:
+ case MV88E6393X_PORT_STS_CMODE_USXGMII:
return mv88e6393x_serdes_irq_enable_10g(chip, lane, enable);
}
@@ -1213,6 +1253,7 @@ irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
break;
case MV88E6393X_PORT_STS_CMODE_5GBASER:
case MV88E6393X_PORT_STS_CMODE_10GBASER:
+ case MV88E6393X_PORT_STS_CMODE_USXGMII:
err = mv88e6393x_serdes_irq_status_10g(chip, lane, &status);
if (err)
return err;
@@ -1477,7 +1518,8 @@ static int mv88e6393x_serdes_erratum_5_2(struct mv88e6xxx_chip *chip, int lane,
* to SERDES operating in 10G mode. These registers only apply to 10G
* operation and have no effect on other speeds.
*/
- if (cmode != MV88E6393X_PORT_STS_CMODE_10GBASER)
+ if (cmode != MV88E6393X_PORT_STS_CMODE_10GBASER &&
+ cmode != MV88E6393X_PORT_STS_CMODE_USXGMII)
return 0;
for (i = 0; i < ARRAY_SIZE(fixes); ++i) {
@@ -1582,6 +1624,7 @@ int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
break;
case MV88E6393X_PORT_STS_CMODE_5GBASER:
case MV88E6393X_PORT_STS_CMODE_10GBASER:
+ case MV88E6393X_PORT_STS_CMODE_USXGMII:
err = mv88e6390_serdes_power_10g(chip, lane, on);
break;
default:
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h
index 29bb4e91e2f6..e245687ddb1d 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.h
+++ b/drivers/net/dsa/mv88e6xxx/serdes.h
@@ -48,6 +48,10 @@
#define MV88E6393X_10G_INT_LINK_CHANGE BIT(2)
#define MV88E6393X_10G_INT_STATUS 0x9001
+/* USXGMII */
+#define MV88E6390_USXGMII_LP_STATUS 0xf0a2
+#define MV88E6390_USXGMII_PHY_STATUS 0xf0a6
+
/* 1000BASE-X and SGMII */
#define MV88E6390_SGMII_BMCR (0x2000 + MII_BMCR)
#define MV88E6390_SGMII_BMSR (0x2000 + MII_BMSR)
diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index 80861ac090ae..bef879c6d500 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -1286,7 +1286,6 @@ static int felix_parse_ports_node(struct felix *felix,
if (err < 0) {
dev_info(dev, "Unsupported PHY mode %s on port %d\n",
phy_modes(phy_mode), port);
- of_node_put(child);
/* Leave port_phy_modes[port] = 0, which is also
* PHY_INTERFACE_MODE_NA. This will perform a
@@ -1626,8 +1625,10 @@ static void felix_teardown(struct dsa_switch *ds)
struct felix *felix = ocelot_to_felix(ocelot);
struct dsa_port *dp;
+ rtnl_lock();
if (felix->tag_proto_ops)
felix->tag_proto_ops->teardown(ds);
+ rtnl_unlock();
dsa_switch_for_each_available_port(dp, ds)
ocelot_deinit_port(ocelot, dp->index);
@@ -1725,6 +1726,18 @@ static bool felix_rxtstamp(struct dsa_switch *ds, int port,
u32 tstamp_hi;
u64 tstamp;
+ switch (type & PTP_CLASS_PMASK) {
+ case PTP_CLASS_L2:
+ if (!(ocelot->ports[port]->trap_proto & OCELOT_PROTO_PTP_L2))
+ return false;
+ break;
+ case PTP_CLASS_IPV4:
+ case PTP_CLASS_IPV6:
+ if (!(ocelot->ports[port]->trap_proto & OCELOT_PROTO_PTP_L4))
+ return false;
+ break;
+ }
+
/* If the "no XTR IRQ" workaround is in use, tell DSA to defer this skb
* for RX timestamping. Then free it, and poll for its copy through
* MMIO in the CPU port module, and inject that into the stack from
@@ -1774,16 +1787,15 @@ static int felix_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
{
struct ocelot *ocelot = ds->priv;
struct ocelot_port *ocelot_port = ocelot->ports[port];
- struct felix *felix = ocelot_to_felix(ocelot);
ocelot_port_set_maxlen(ocelot, port, new_mtu);
- mutex_lock(&ocelot->tas_lock);
+ mutex_lock(&ocelot->fwd_domain_lock);
- if (ocelot_port->taprio && felix->info->tas_guard_bands_update)
- felix->info->tas_guard_bands_update(ocelot, port);
+ if (ocelot_port->taprio && ocelot->ops->tas_guard_bands_update)
+ ocelot->ops->tas_guard_bands_update(ocelot, port);
- mutex_unlock(&ocelot->tas_lock);
+ mutex_unlock(&ocelot->fwd_domain_lock);
return 0;
}
diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
index 96008c046da5..1d4befe7cfe8 100644
--- a/drivers/net/dsa/ocelot/felix.h
+++ b/drivers/net/dsa/ocelot/felix.h
@@ -57,7 +57,6 @@ struct felix_info {
void (*mdio_bus_free)(struct ocelot *ocelot);
int (*port_setup_tc)(struct dsa_switch *ds, int port,
enum tc_setup_type type, void *type_data);
- void (*tas_guard_bands_update)(struct ocelot *ocelot, int port);
void (*port_sched_speed_set)(struct ocelot *ocelot, int port,
u32 speed);
void (*phylink_mac_config)(struct ocelot *ocelot, int port,
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index d172a3e9736c..f16daa9b1765 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -1021,7 +1021,6 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
for (port = 0; port < felix->info->num_ports; port++) {
struct ocelot_port *ocelot_port = ocelot->ports[port];
struct phylink_pcs *phylink_pcs;
- struct mdio_device *mdio_device;
if (dsa_is_unused_port(felix->ds, port))
continue;
@@ -1029,16 +1028,10 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
if (ocelot_port->phy_mode == PHY_INTERFACE_MODE_INTERNAL)
continue;
- mdio_device = mdio_device_create(felix->imdio, port);
- if (IS_ERR(mdio_device))
+ phylink_pcs = lynx_pcs_create_mdiodev(felix->imdio, port);
+ if (IS_ERR(phylink_pcs))
continue;
- phylink_pcs = lynx_pcs_create(mdio_device);
- if (!phylink_pcs) {
- mdio_device_free(mdio_device);
- continue;
- }
-
felix->pcs[port] = phylink_pcs;
dev_info(dev, "Found PCS at internal MDIO address %d\n", port);
@@ -1054,14 +1047,9 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot)
for (port = 0; port < ocelot->num_phys_ports; port++) {
struct phylink_pcs *phylink_pcs = felix->pcs[port];
- struct mdio_device *mdio_device;
-
- if (!phylink_pcs)
- continue;
- mdio_device = lynx_get_mdio_device(phylink_pcs);
- mdio_device_free(mdio_device);
- lynx_pcs_destroy(phylink_pcs);
+ if (phylink_pcs)
+ lynx_pcs_destroy(phylink_pcs);
}
mdiobus_unregister(felix->imdio);
mdiobus_free(felix->imdio);
@@ -1081,6 +1069,9 @@ static u64 vsc9959_tas_remaining_gate_len_ps(u64 gate_len_ns)
if (gate_len_ns == U64_MAX)
return U64_MAX;
+ if (gate_len_ns < VSC9959_TAS_MIN_GATE_LEN_NS)
+ return 0;
+
return (gate_len_ns - VSC9959_TAS_MIN_GATE_LEN_NS) * PSEC_PER_NSEC;
}
@@ -1221,15 +1212,17 @@ static u32 vsc9959_tas_tc_max_sdu(struct tc_taprio_qopt_offload *taprio, int tc)
static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
{
struct ocelot_port *ocelot_port = ocelot->ports[port];
+ struct ocelot_mm_state *mm = &ocelot->mm[port];
struct tc_taprio_qopt_offload *taprio;
u64 min_gate_len[OCELOT_NUM_TC];
+ u32 val, maxlen, add_frag_size;
+ u64 needed_min_frag_time_ps;
int speed, picos_per_byte;
u64 needed_bit_time_ps;
- u32 val, maxlen;
u8 tas_speed;
int tc;
- lockdep_assert_held(&ocelot->tas_lock);
+ lockdep_assert_held(&ocelot->fwd_domain_lock);
taprio = ocelot_port->taprio;
@@ -1265,14 +1258,21 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
*/
needed_bit_time_ps = (u64)(maxlen + 24) * picos_per_byte;
+ /* Preemptible TCs don't need to pass a full MTU, the port will
+ * automatically emit a HOLD request when a preemptible TC gate closes
+ */
+ val = ocelot_read_rix(ocelot, QSYS_PREEMPTION_CFG, port);
+ add_frag_size = QSYS_PREEMPTION_CFG_MM_ADD_FRAG_SIZE_X(val);
+ needed_min_frag_time_ps = picos_per_byte *
+ (u64)(24 + 2 * ethtool_mm_frag_size_add_to_min(add_frag_size));
+
dev_dbg(ocelot->dev,
- "port %d: max frame size %d needs %llu ps at speed %d\n",
- port, maxlen, needed_bit_time_ps, speed);
+ "port %d: max frame size %d needs %llu ps, %llu ps for mPackets at speed %d\n",
+ port, maxlen, needed_bit_time_ps, needed_min_frag_time_ps,
+ speed);
vsc9959_tas_min_gate_lengths(taprio, min_gate_len);
- mutex_lock(&ocelot->fwd_domain_lock);
-
for (tc = 0; tc < OCELOT_NUM_TC; tc++) {
u32 requested_max_sdu = vsc9959_tas_tc_max_sdu(taprio, tc);
u64 remaining_gate_len_ps;
@@ -1281,7 +1281,9 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
remaining_gate_len_ps =
vsc9959_tas_remaining_gate_len_ps(min_gate_len[tc]);
- if (remaining_gate_len_ps > needed_bit_time_ps) {
+ if ((mm->active_preemptible_tcs & BIT(tc)) ?
+ remaining_gate_len_ps > needed_min_frag_time_ps :
+ remaining_gate_len_ps > needed_bit_time_ps) {
/* Setting QMAXSDU_CFG to 0 disables oversized frame
* dropping.
*/
@@ -1335,8 +1337,6 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
ocelot_write_rix(ocelot, maxlen, QSYS_PORT_MAX_SDU, port);
ocelot->ops->cut_through_fwd(ocelot);
-
- mutex_unlock(&ocelot->fwd_domain_lock);
}
static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
@@ -1363,7 +1363,7 @@ static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
break;
}
- mutex_lock(&ocelot->tas_lock);
+ mutex_lock(&ocelot->fwd_domain_lock);
ocelot_rmw_rix(ocelot,
QSYS_TAG_CONFIG_LINK_SPEED(tas_speed),
@@ -1373,7 +1373,7 @@ static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
if (ocelot_port->taprio)
vsc9959_tas_guard_bands_update(ocelot, port);
- mutex_unlock(&ocelot->tas_lock);
+ mutex_unlock(&ocelot->fwd_domain_lock);
}
static void vsc9959_new_base_time(struct ocelot *ocelot, ktime_t base_time,
@@ -1421,9 +1421,9 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
int ret, i;
u32 val;
- mutex_lock(&ocelot->tas_lock);
+ mutex_lock(&ocelot->fwd_domain_lock);
- if (!taprio->enable) {
+ if (taprio->cmd == TAPRIO_CMD_DESTROY) {
ocelot_port_mqprio(ocelot, port, &taprio->mqprio);
ocelot_rmw_rix(ocelot, 0, QSYS_TAG_CONFIG_ENABLE,
QSYS_TAG_CONFIG, port);
@@ -1433,8 +1433,11 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
vsc9959_tas_guard_bands_update(ocelot, port);
- mutex_unlock(&ocelot->tas_lock);
+ mutex_unlock(&ocelot->fwd_domain_lock);
return 0;
+ } else if (taprio->cmd != TAPRIO_CMD_REPLACE) {
+ ret = -EOPNOTSUPP;
+ goto err_unlock;
}
ret = ocelot_port_mqprio(ocelot, port, &taprio->mqprio);
@@ -1513,7 +1516,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
ocelot_port->taprio = taprio_offload_get(taprio);
vsc9959_tas_guard_bands_update(ocelot, port);
- mutex_unlock(&ocelot->tas_lock);
+ mutex_unlock(&ocelot->fwd_domain_lock);
return 0;
@@ -1521,7 +1524,7 @@ err_reset_tc:
taprio->mqprio.qopt.num_tc = 0;
ocelot_port_mqprio(ocelot, port, &taprio->mqprio);
err_unlock:
- mutex_unlock(&ocelot->tas_lock);
+ mutex_unlock(&ocelot->fwd_domain_lock);
return ret;
}
@@ -1534,7 +1537,7 @@ static void vsc9959_tas_clock_adjust(struct ocelot *ocelot)
int port;
u32 val;
- mutex_lock(&ocelot->tas_lock);
+ mutex_lock(&ocelot->fwd_domain_lock);
for (port = 0; port < ocelot->num_phys_ports; port++) {
ocelot_port = ocelot->ports[port];
@@ -1572,7 +1575,7 @@ static void vsc9959_tas_clock_adjust(struct ocelot *ocelot)
QSYS_TAG_CONFIG_ENABLE,
QSYS_TAG_CONFIG, port);
}
- mutex_unlock(&ocelot->tas_lock);
+ mutex_unlock(&ocelot->fwd_domain_lock);
}
static int vsc9959_qos_port_cbs_set(struct dsa_switch *ds, int port,
@@ -1643,6 +1646,18 @@ static int vsc9959_qos_query_caps(struct tc_query_caps_base *base)
}
}
+static int vsc9959_qos_port_mqprio(struct ocelot *ocelot, int port,
+ struct tc_mqprio_qopt_offload *mqprio)
+{
+ int ret;
+
+ mutex_lock(&ocelot->fwd_domain_lock);
+ ret = ocelot_port_mqprio(ocelot, port, mqprio);
+ mutex_unlock(&ocelot->fwd_domain_lock);
+
+ return ret;
+}
+
static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port,
enum tc_setup_type type,
void *type_data)
@@ -1655,7 +1670,7 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port,
case TC_SETUP_QDISC_TAPRIO:
return vsc9959_qos_port_tas_set(ocelot, port, type_data);
case TC_SETUP_QDISC_MQPRIO:
- return ocelot_port_mqprio(ocelot, port, type_data);
+ return vsc9959_qos_port_mqprio(ocelot, port, type_data);
case TC_SETUP_QDISC_CBS:
return vsc9959_qos_port_cbs_set(ds, port, type_data);
default:
@@ -2600,6 +2615,7 @@ static const struct ocelot_ops vsc9959_ops = {
.cut_through_fwd = vsc9959_cut_through_fwd,
.tas_clock_adjust = vsc9959_tas_clock_adjust,
.update_stats = vsc9959_update_stats,
+ .tas_guard_bands_update = vsc9959_tas_guard_bands_update,
};
static const struct felix_info felix_info_vsc9959 = {
@@ -2625,7 +2641,6 @@ static const struct felix_info felix_info_vsc9959 = {
.port_modes = vsc9959_port_modes,
.port_setup_tc = vsc9959_port_setup_tc,
.port_sched_speed_set = vsc9959_sched_speed_set,
- .tas_guard_bands_update = vsc9959_tas_guard_bands_update,
};
/* The INTB interrupt is shared between for PTP TX timestamp availability
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
index 96d4972a62f0..15003b2af264 100644
--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
+++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
@@ -912,7 +912,6 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
for (port = 0; port < felix->info->num_ports; port++) {
struct ocelot_port *ocelot_port = ocelot->ports[port];
struct phylink_pcs *phylink_pcs;
- struct mdio_device *mdio_device;
int addr = port + 4;
if (dsa_is_unused_port(felix->ds, port))
@@ -921,16 +920,10 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
if (ocelot_port->phy_mode == PHY_INTERFACE_MODE_INTERNAL)
continue;
- mdio_device = mdio_device_create(felix->imdio, addr);
- if (IS_ERR(mdio_device))
+ phylink_pcs = lynx_pcs_create_mdiodev(felix->imdio, addr);
+ if (IS_ERR(phylink_pcs))
continue;
- phylink_pcs = lynx_pcs_create(mdio_device);
- if (!phylink_pcs) {
- mdio_device_free(mdio_device);
- continue;
- }
-
felix->pcs[port] = phylink_pcs;
dev_info(dev, "Found PCS at internal MDIO address %d\n", addr);
@@ -946,14 +939,9 @@ static void vsc9953_mdio_bus_free(struct ocelot *ocelot)
for (port = 0; port < ocelot->num_phys_ports; port++) {
struct phylink_pcs *phylink_pcs = felix->pcs[port];
- struct mdio_device *mdio_device;
-
- if (!phylink_pcs)
- continue;
- mdio_device = lynx_get_mdio_device(phylink_pcs);
- mdio_device_free(mdio_device);
- lynx_pcs_destroy(phylink_pcs);
+ if (phylink_pcs)
+ lynx_pcs_destroy(phylink_pcs);
}
/* mdiobus_unregister and mdiobus_free handled by devres */
diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c
index e7b98b864fa1..3b0937031499 100644
--- a/drivers/net/dsa/qca/ar9331.c
+++ b/drivers/net/dsa/qca/ar9331.c
@@ -391,7 +391,7 @@ static int ar9331_sw_mbus_init(struct ar9331_sw_priv *priv)
static int ar9331_sw_setup_port(struct dsa_switch *ds, int port)
{
- struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+ struct ar9331_sw_priv *priv = ds->priv;
struct regmap *regmap = priv->regmap;
u32 port_mask, port_ctrl, val;
int ret;
@@ -439,7 +439,7 @@ error:
static int ar9331_sw_setup(struct dsa_switch *ds)
{
- struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+ struct ar9331_sw_priv *priv = ds->priv;
struct regmap *regmap = priv->regmap;
int ret, i;
@@ -484,7 +484,7 @@ error:
static void ar9331_sw_port_disable(struct dsa_switch *ds, int port)
{
- struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+ struct ar9331_sw_priv *priv = ds->priv;
struct regmap *regmap = priv->regmap;
int ret;
@@ -527,7 +527,7 @@ static void ar9331_sw_phylink_mac_config(struct dsa_switch *ds, int port,
unsigned int mode,
const struct phylink_link_state *state)
{
- struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+ struct ar9331_sw_priv *priv = ds->priv;
struct regmap *regmap = priv->regmap;
int ret;
@@ -542,7 +542,7 @@ static void ar9331_sw_phylink_mac_link_down(struct dsa_switch *ds, int port,
unsigned int mode,
phy_interface_t interface)
{
- struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+ struct ar9331_sw_priv *priv = ds->priv;
struct ar9331_sw_port *p = &priv->port[port];
struct regmap *regmap = priv->regmap;
int ret;
@@ -562,7 +562,7 @@ static void ar9331_sw_phylink_mac_link_up(struct dsa_switch *ds, int port,
int speed, int duplex,
bool tx_pause, bool rx_pause)
{
- struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+ struct ar9331_sw_priv *priv = ds->priv;
struct ar9331_sw_port *p = &priv->port[port];
struct regmap *regmap = priv->regmap;
u32 val;
@@ -665,7 +665,7 @@ static void ar9331_do_stats_poll(struct work_struct *work)
static void ar9331_get_stats64(struct dsa_switch *ds, int port,
struct rtnl_link_stats64 *s)
{
- struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+ struct ar9331_sw_priv *priv = ds->priv;
struct ar9331_sw_port *p = &priv->port[port];
spin_lock(&p->stats_lock);
@@ -676,7 +676,7 @@ static void ar9331_get_stats64(struct dsa_switch *ds, int port,
static void ar9331_get_pause_stats(struct dsa_switch *ds, int port,
struct ethtool_pause_stats *pause_stats)
{
- struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+ struct ar9331_sw_priv *priv = ds->priv;
struct ar9331_sw_port *p = &priv->port[port];
spin_lock(&p->stats_lock);
@@ -1002,6 +1002,8 @@ static const struct regmap_config ar9331_mdio_regmap_config = {
.val_bits = 32,
.reg_stride = 4,
.max_register = AR9331_SW_REG_PAGE,
+ .use_single_read = true,
+ .use_single_write = true,
.ranges = ar9331_regmap_range,
.num_ranges = ARRAY_SIZE(ar9331_regmap_range),
@@ -1018,8 +1020,6 @@ static struct regmap_bus ar9331_sw_bus = {
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
.read = ar9331_mdio_read,
.write = ar9331_sw_bus_write,
- .max_raw_read = 4,
- .max_raw_write = 4,
};
static int ar9331_sw_probe(struct mdio_device *mdiodev)
diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c
index 6d5ac7588a69..efe9380d4a15 100644
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
@@ -576,8 +576,11 @@ static struct regmap_config qca8k_regmap_config = {
.rd_table = &qca8k_readable_table,
.disable_locking = true, /* Locking is handled by qca8k read/write */
.cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */
- .max_raw_read = 32, /* mgmt eth can read/write up to 8 registers at time */
- .max_raw_write = 32,
+ .max_raw_read = 32, /* mgmt eth can read up to 8 registers at time */
+ /* ATU regs suffer from a bug where some data are not correctly
+ * written. Disable bulk write to correctly write ATU entry.
+ */
+ .use_single_write = true,
};
static int
@@ -588,6 +591,9 @@ qca8k_phy_eth_busy_wait(struct qca8k_mgmt_eth_data *mgmt_eth_data,
bool ack;
int ret;
+ if (!skb)
+ return -ENOMEM;
+
reinit_completion(&mgmt_eth_data->rw_done);
/* Increment seq_num and set it in the copy pkt */
@@ -1493,7 +1499,7 @@ static void qca8k_pcs_get_state(struct phylink_pcs *pcs,
state->pause |= MLO_PAUSE_TX;
}
-static int qca8k_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+static int qca8k_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -1520,14 +1526,12 @@ static int qca8k_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
}
/* Enable/disable SerDes auto-negotiation as necessary */
- ret = qca8k_read(priv, QCA8K_REG_PWS, &val);
+ val = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED ?
+ 0 : QCA8K_PWS_SERDES_AEN_DIS;
+
+ ret = qca8k_rmw(priv, QCA8K_REG_PWS, QCA8K_PWS_SERDES_AEN_DIS, val);
if (ret)
return ret;
- if (phylink_autoneg_inband(mode))
- val &= ~QCA8K_PWS_SERDES_AEN_DIS;
- else
- val |= QCA8K_PWS_SERDES_AEN_DIS;
- qca8k_write(priv, QCA8K_REG_PWS, val);
/* Configure the SGMII parameters */
ret = qca8k_read(priv, QCA8K_REG_SGMII_CTRL, &val);
@@ -1598,6 +1602,7 @@ static void qca8k_setup_pcs(struct qca8k_priv *priv, struct qca8k_pcs *qpcs,
int port)
{
qpcs->pcs.ops = &qca8k_pcs_ops;
+ qpcs->pcs.neg_mode = true;
/* We don't have interrupts for link changes, so we need to poll */
qpcs->pcs.poll = true;
@@ -1756,7 +1761,7 @@ static int qca8k_connect_tag_protocol(struct dsa_switch *ds,
static int
qca8k_setup(struct dsa_switch *ds)
{
- struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+ struct qca8k_priv *priv = ds->priv;
int cpu_port, ret, i;
u32 mask;
diff --git a/drivers/net/dsa/qca/qca8k-common.c b/drivers/net/dsa/qca/qca8k-common.c
index 96773e432558..13b8452ce5b2 100644
--- a/drivers/net/dsa/qca/qca8k-common.c
+++ b/drivers/net/dsa/qca/qca8k-common.c
@@ -244,7 +244,7 @@ void qca8k_fdb_flush(struct qca8k_priv *priv)
}
static int qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask,
- const u8 *mac, u16 vid)
+ const u8 *mac, u16 vid, u8 aging)
{
struct qca8k_fdb fdb = { 0 };
int ret;
@@ -261,10 +261,12 @@ static int qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask,
goto exit;
/* Rule exist. Delete first */
- if (!fdb.aging) {
+ if (fdb.aging) {
ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
if (ret)
goto exit;
+ } else {
+ fdb.aging = aging;
}
/* Add port to fdb portmask */
@@ -291,6 +293,10 @@ static int qca8k_fdb_search_and_del(struct qca8k_priv *priv, u8 port_mask,
if (ret < 0)
goto exit;
+ ret = qca8k_fdb_read(priv, &fdb);
+ if (ret < 0)
+ goto exit;
+
/* Rule doesn't exist. Why delete? */
if (!fdb.aging) {
ret = -EINVAL;
@@ -760,7 +766,7 @@ int qca8k_port_fdb_add(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid,
struct dsa_db db)
{
- struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+ struct qca8k_priv *priv = ds->priv;
u16 port_mask = BIT(port);
return qca8k_port_fdb_insert(priv, addr, port_mask, vid);
@@ -770,7 +776,7 @@ int qca8k_port_fdb_del(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid,
struct dsa_db db)
{
- struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+ struct qca8k_priv *priv = ds->priv;
u16 port_mask = BIT(port);
if (!vid)
@@ -782,7 +788,7 @@ int qca8k_port_fdb_del(struct dsa_switch *ds, int port,
int qca8k_port_fdb_dump(struct dsa_switch *ds, int port,
dsa_fdb_dump_cb_t *cb, void *data)
{
- struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+ struct qca8k_priv *priv = ds->priv;
struct qca8k_fdb _fdb = { 0 };
int cnt = QCA8K_NUM_FDB_RECORDS;
bool is_static;
@@ -810,7 +816,11 @@ int qca8k_port_mdb_add(struct dsa_switch *ds, int port,
const u8 *addr = mdb->addr;
u16 vid = mdb->vid;
- return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid);
+ if (!vid)
+ vid = QCA8K_PORT_VID_DEF;
+
+ return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid,
+ QCA8K_ATU_STATUS_STATIC);
}
int qca8k_port_mdb_del(struct dsa_switch *ds, int port,
@@ -821,6 +831,9 @@ int qca8k_port_mdb_del(struct dsa_switch *ds, int port,
const u8 *addr = mdb->addr;
u16 vid = mdb->vid;
+ if (!vid)
+ vid = QCA8K_PORT_VID_DEF;
+
return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid);
}
diff --git a/drivers/net/dsa/qca/qca8k-leds.c b/drivers/net/dsa/qca/qca8k-leds.c
index b883692b7d86..1261e0bb21ef 100644
--- a/drivers/net/dsa/qca/qca8k-leds.c
+++ b/drivers/net/dsa/qca/qca8k-leds.c
@@ -5,6 +5,18 @@
#include "qca8k.h"
#include "qca8k_leds.h"
+static u32 qca8k_phy_to_port(int phy)
+{
+ /* Internal PHY 0 has port at index 1.
+ * Internal PHY 1 has port at index 2.
+ * Internal PHY 2 has port at index 3.
+ * Internal PHY 3 has port at index 4.
+ * Internal PHY 4 has port at index 5.
+ */
+
+ return phy + 1;
+}
+
static int
qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info)
{
@@ -32,6 +44,53 @@ qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en
}
static int
+qca8k_get_control_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info)
+{
+ reg_info->reg = QCA8K_LED_CTRL_REG(led_num);
+
+ /* 6 total control rule:
+ * 3 control rules for phy0-3 that applies to all their leds
+ * 3 control rules for phy4
+ */
+ if (port_num == 4)
+ reg_info->shift = QCA8K_LED_PHY4_CONTROL_RULE_SHIFT;
+ else
+ reg_info->shift = QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT;
+
+ return 0;
+}
+
+static int
+qca8k_parse_netdev(unsigned long rules, u32 *offload_trigger)
+{
+ /* Parsing specific to netdev trigger */
+ if (test_bit(TRIGGER_NETDEV_TX, &rules))
+ *offload_trigger |= QCA8K_LED_TX_BLINK_MASK;
+ if (test_bit(TRIGGER_NETDEV_RX, &rules))
+ *offload_trigger |= QCA8K_LED_RX_BLINK_MASK;
+ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules))
+ *offload_trigger |= QCA8K_LED_LINK_10M_EN_MASK;
+ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules))
+ *offload_trigger |= QCA8K_LED_LINK_100M_EN_MASK;
+ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules))
+ *offload_trigger |= QCA8K_LED_LINK_1000M_EN_MASK;
+ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules))
+ *offload_trigger |= QCA8K_LED_HALF_DUPLEX_MASK;
+ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules))
+ *offload_trigger |= QCA8K_LED_FULL_DUPLEX_MASK;
+
+ if (rules && !*offload_trigger)
+ return -EOPNOTSUPP;
+
+ /* Enable some default rule by default to the requested mode:
+ * - Blink at 4Hz by default
+ */
+ *offload_trigger |= QCA8K_LED_BLINK_4HZ;
+
+ return 0;
+}
+
+static int
qca8k_led_brightness_set(struct qca8k_led *led,
enum led_brightness brightness)
{
@@ -165,6 +224,143 @@ qca8k_cled_blink_set(struct led_classdev *ldev,
}
static int
+qca8k_cled_trigger_offload(struct led_classdev *ldev, bool enable)
+{
+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
+
+ struct qca8k_led_pattern_en reg_info;
+ struct qca8k_priv *priv = led->priv;
+ u32 mask, val = QCA8K_LED_ALWAYS_OFF;
+
+ qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
+
+ if (enable)
+ val = QCA8K_LED_RULE_CONTROLLED;
+
+ if (led->port_num == 0 || led->port_num == 4) {
+ mask = QCA8K_LED_PATTERN_EN_MASK;
+ val <<= QCA8K_LED_PATTERN_EN_SHIFT;
+ } else {
+ mask = QCA8K_LED_PHY123_PATTERN_EN_MASK;
+ }
+
+ return regmap_update_bits(priv->regmap, reg_info.reg, mask << reg_info.shift,
+ val << reg_info.shift);
+}
+
+static bool
+qca8k_cled_hw_control_status(struct led_classdev *ldev)
+{
+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
+
+ struct qca8k_led_pattern_en reg_info;
+ struct qca8k_priv *priv = led->priv;
+ u32 val;
+
+ qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
+
+ regmap_read(priv->regmap, reg_info.reg, &val);
+
+ val >>= reg_info.shift;
+
+ if (led->port_num == 0 || led->port_num == 4) {
+ val &= QCA8K_LED_PATTERN_EN_MASK;
+ val >>= QCA8K_LED_PATTERN_EN_SHIFT;
+ } else {
+ val &= QCA8K_LED_PHY123_PATTERN_EN_MASK;
+ }
+
+ return val == QCA8K_LED_RULE_CONTROLLED;
+}
+
+static int
+qca8k_cled_hw_control_is_supported(struct led_classdev *ldev, unsigned long rules)
+{
+ u32 offload_trigger = 0;
+
+ return qca8k_parse_netdev(rules, &offload_trigger);
+}
+
+static int
+qca8k_cled_hw_control_set(struct led_classdev *ldev, unsigned long rules)
+{
+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
+ struct qca8k_led_pattern_en reg_info;
+ struct qca8k_priv *priv = led->priv;
+ u32 offload_trigger = 0;
+ int ret;
+
+ ret = qca8k_parse_netdev(rules, &offload_trigger);
+ if (ret)
+ return ret;
+
+ ret = qca8k_cled_trigger_offload(ldev, true);
+ if (ret)
+ return ret;
+
+ qca8k_get_control_led_reg(led->port_num, led->led_num, &reg_info);
+
+ return regmap_update_bits(priv->regmap, reg_info.reg,
+ QCA8K_LED_RULE_MASK << reg_info.shift,
+ offload_trigger << reg_info.shift);
+}
+
+static int
+qca8k_cled_hw_control_get(struct led_classdev *ldev, unsigned long *rules)
+{
+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
+ struct qca8k_led_pattern_en reg_info;
+ struct qca8k_priv *priv = led->priv;
+ u32 val;
+ int ret;
+
+ /* With hw control not active return err */
+ if (!qca8k_cled_hw_control_status(ldev))
+ return -EINVAL;
+
+ qca8k_get_control_led_reg(led->port_num, led->led_num, &reg_info);
+
+ ret = regmap_read(priv->regmap, reg_info.reg, &val);
+ if (ret)
+ return ret;
+
+ val >>= reg_info.shift;
+ val &= QCA8K_LED_RULE_MASK;
+
+ /* Parsing specific to netdev trigger */
+ if (val & QCA8K_LED_TX_BLINK_MASK)
+ set_bit(TRIGGER_NETDEV_TX, rules);
+ if (val & QCA8K_LED_RX_BLINK_MASK)
+ set_bit(TRIGGER_NETDEV_RX, rules);
+ if (val & QCA8K_LED_LINK_10M_EN_MASK)
+ set_bit(TRIGGER_NETDEV_LINK_10, rules);
+ if (val & QCA8K_LED_LINK_100M_EN_MASK)
+ set_bit(TRIGGER_NETDEV_LINK_100, rules);
+ if (val & QCA8K_LED_LINK_1000M_EN_MASK)
+ set_bit(TRIGGER_NETDEV_LINK_1000, rules);
+ if (val & QCA8K_LED_HALF_DUPLEX_MASK)
+ set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules);
+ if (val & QCA8K_LED_FULL_DUPLEX_MASK)
+ set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules);
+
+ return 0;
+}
+
+static struct device *qca8k_cled_hw_control_get_device(struct led_classdev *ldev)
+{
+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
+ struct qca8k_priv *priv = led->priv;
+ struct dsa_port *dp;
+
+ dp = dsa_to_port(priv->ds, qca8k_phy_to_port(led->port_num));
+ if (!dp)
+ return NULL;
+ if (dp->slave)
+ return &dp->slave->dev;
+ return NULL;
+}
+
+static int
qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num)
{
struct fwnode_handle *led = NULL, *leds = NULL;
@@ -224,6 +420,11 @@ qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int p
port_led->cdev.max_brightness = 1;
port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking;
port_led->cdev.blink_set = qca8k_cled_blink_set;
+ port_led->cdev.hw_control_is_supported = qca8k_cled_hw_control_is_supported;
+ port_led->cdev.hw_control_set = qca8k_cled_hw_control_set;
+ port_led->cdev.hw_control_get = qca8k_cled_hw_control_get;
+ port_led->cdev.hw_control_get_device = qca8k_cled_hw_control_get_device;
+ port_led->cdev.hw_control_trigger = "netdev";
init_data.default_label = ":port";
init_data.fwnode = led;
init_data.devname_mandatory = true;
diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h
index fb1549a5fe32..dee35ba924ad 100644
--- a/drivers/net/dsa/sja1105/sja1105.h
+++ b/drivers/net/dsa/sja1105/sja1105.h
@@ -252,6 +252,7 @@ struct sja1105_private {
unsigned long ucast_egress_floods;
unsigned long bcast_egress_floods;
unsigned long hwts_tx_en;
+ unsigned long hwts_rx_en;
const struct sja1105_info *info;
size_t max_xfer_len;
struct spi_device *spidev;
@@ -289,7 +290,6 @@ struct sja1105_spi_message {
/* From sja1105_main.c */
enum sja1105_reset_reason {
SJA1105_VLAN_FILTERING = 0,
- SJA1105_RX_HWTSTAMPING,
SJA1105_AGEING_TIME,
SJA1105_SCHEDULING,
SJA1105_BEST_EFFORT_POLICING,
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index b70dcf32a26d..3529a565b4aa 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -866,12 +866,12 @@ static int sja1105_init_general_params(struct sja1105_private *priv)
.hostprio = 7,
.mac_fltres1 = SJA1105_LINKLOCAL_FILTER_A,
.mac_flt1 = SJA1105_LINKLOCAL_FILTER_A_MASK,
- .incl_srcpt1 = false,
- .send_meta1 = false,
+ .incl_srcpt1 = true,
+ .send_meta1 = true,
.mac_fltres0 = SJA1105_LINKLOCAL_FILTER_B,
.mac_flt0 = SJA1105_LINKLOCAL_FILTER_B_MASK,
- .incl_srcpt0 = false,
- .send_meta0 = false,
+ .incl_srcpt0 = true,
+ .send_meta0 = true,
/* Default to an invalid value */
.mirr_port = priv->ds->num_ports,
/* No TTEthernet */
@@ -2215,7 +2215,6 @@ static int sja1105_reload_cbs(struct sja1105_private *priv)
static const char * const sja1105_reset_reasons[] = {
[SJA1105_VLAN_FILTERING] = "VLAN filtering",
- [SJA1105_RX_HWTSTAMPING] = "RX timestamping",
[SJA1105_AGEING_TIME] = "Ageing time",
[SJA1105_SCHEDULING] = "Time-aware scheduling",
[SJA1105_BEST_EFFORT_POLICING] = "Best-effort policing",
@@ -2314,7 +2313,7 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
for (i = 0; i < ds->num_ports; i++) {
struct dw_xpcs *xpcs = priv->xpcs[i];
- unsigned int mode;
+ unsigned int neg_mode;
rc = sja1105_adjust_port_config(priv, i, speed_mbps[i]);
if (rc < 0)
@@ -2324,17 +2323,15 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
continue;
if (bmcr[i] & BMCR_ANENABLE)
- mode = MLO_AN_INBAND;
- else if (priv->fixed_link[i])
- mode = MLO_AN_FIXED;
+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
else
- mode = MLO_AN_PHY;
+ neg_mode = PHYLINK_PCS_NEG_OUTBAND;
- rc = xpcs_do_config(xpcs, priv->phy_mode[i], mode, NULL);
+ rc = xpcs_do_config(xpcs, priv->phy_mode[i], NULL, neg_mode);
if (rc < 0)
goto out;
- if (!phylink_autoneg_inband(mode)) {
+ if (neg_mode == PHYLINK_PCS_NEG_OUTBAND) {
int speed = SPEED_UNKNOWN;
if (priv->phy_mode[i] == PHY_INTERFACE_MODE_2500BASEX)
@@ -2346,7 +2343,7 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
else
speed = SPEED_10;
- xpcs_link_up(&xpcs->pcs, mode, priv->phy_mode[i],
+ xpcs_link_up(&xpcs->pcs, neg_mode, priv->phy_mode[i],
speed, DUPLEX_FULL);
}
}
@@ -2407,11 +2404,6 @@ int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled,
general_params->tpid = tpid;
/* EtherType used to identify outer tagged (S-tag) VLAN traffic */
general_params->tpid2 = tpid2;
- /* When VLAN filtering is on, we need to at least be able to
- * decode management traffic through the "backup plan".
- */
- general_params->incl_srcpt1 = enabled;
- general_params->incl_srcpt0 = enabled;
for (port = 0; port < ds->num_ports; port++) {
if (dsa_is_unused_port(ds, port))
diff --git a/drivers/net/dsa/sja1105/sja1105_mdio.c b/drivers/net/dsa/sja1105/sja1105_mdio.c
index 01f1cb719042..833e55e4b961 100644
--- a/drivers/net/dsa/sja1105/sja1105_mdio.c
+++ b/drivers/net/dsa/sja1105/sja1105_mdio.c
@@ -400,7 +400,6 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
}
for (port = 0; port < ds->num_ports; port++) {
- struct mdio_device *mdiodev;
struct dw_xpcs *xpcs;
if (dsa_is_unused_port(ds, port))
@@ -410,13 +409,7 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
priv->phy_mode[port] != PHY_INTERFACE_MODE_2500BASEX)
continue;
- mdiodev = mdio_device_create(bus, port);
- if (IS_ERR(mdiodev)) {
- rc = PTR_ERR(mdiodev);
- goto out_pcs_free;
- }
-
- xpcs = xpcs_create(mdiodev, priv->phy_mode[port]);
+ xpcs = xpcs_create_mdiodev(bus, port, priv->phy_mode[port]);
if (IS_ERR(xpcs)) {
rc = PTR_ERR(xpcs);
goto out_pcs_free;
@@ -434,7 +427,6 @@ out_pcs_free:
if (!priv->xpcs[port])
continue;
- mdio_device_free(priv->xpcs[port]->mdiodev);
xpcs_destroy(priv->xpcs[port]);
priv->xpcs[port] = NULL;
}
@@ -457,7 +449,6 @@ static void sja1105_mdiobus_pcs_unregister(struct sja1105_private *priv)
if (!priv->xpcs[port])
continue;
- mdio_device_free(priv->xpcs[port]->mdiodev);
xpcs_destroy(priv->xpcs[port]);
priv->xpcs[port] = NULL;
}
diff --git a/drivers/net/dsa/sja1105/sja1105_ptp.c b/drivers/net/dsa/sja1105/sja1105_ptp.c
index 30fb2cc40164..a7d41e781398 100644
--- a/drivers/net/dsa/sja1105/sja1105_ptp.c
+++ b/drivers/net/dsa/sja1105/sja1105_ptp.c
@@ -58,35 +58,10 @@ enum sja1105_ptp_clk_mode {
#define ptp_data_to_sja1105(d) \
container_of((d), struct sja1105_private, ptp_data)
-/* Must be called only while the RX timestamping state of the tagger
- * is turned off
- */
-static int sja1105_change_rxtstamping(struct sja1105_private *priv,
- bool on)
-{
- struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
- struct sja1105_general_params_entry *general_params;
- struct sja1105_table *table;
-
- table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS];
- general_params = table->entries;
- general_params->send_meta1 = on;
- general_params->send_meta0 = on;
-
- ptp_cancel_worker_sync(ptp_data->clock);
- skb_queue_purge(&ptp_data->skb_txtstamp_queue);
- skb_queue_purge(&ptp_data->skb_rxtstamp_queue);
-
- return sja1105_static_config_reload(priv, SJA1105_RX_HWTSTAMPING);
-}
-
int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)
{
- struct sja1105_tagger_data *tagger_data = sja1105_tagger_data(ds);
struct sja1105_private *priv = ds->priv;
struct hwtstamp_config config;
- bool rx_on;
- int rc;
if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
return -EFAULT;
@@ -104,26 +79,13 @@ int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)
switch (config.rx_filter) {
case HWTSTAMP_FILTER_NONE:
- rx_on = false;
+ priv->hwts_rx_en &= ~BIT(port);
break;
default:
- rx_on = true;
+ priv->hwts_rx_en |= BIT(port);
break;
}
- if (rx_on != tagger_data->rxtstamp_get_state(ds)) {
- tagger_data->rxtstamp_set_state(ds, false);
-
- rc = sja1105_change_rxtstamping(priv, rx_on);
- if (rc < 0) {
- dev_err(ds->dev,
- "Failed to change RX timestamping: %d\n", rc);
- return rc;
- }
- if (rx_on)
- tagger_data->rxtstamp_set_state(ds, true);
- }
-
if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
return -EFAULT;
return 0;
@@ -131,7 +93,6 @@ int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)
int sja1105_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr)
{
- struct sja1105_tagger_data *tagger_data = sja1105_tagger_data(ds);
struct sja1105_private *priv = ds->priv;
struct hwtstamp_config config;
@@ -140,7 +101,7 @@ int sja1105_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr)
config.tx_type = HWTSTAMP_TX_ON;
else
config.tx_type = HWTSTAMP_TX_OFF;
- if (tagger_data->rxtstamp_get_state(ds))
+ if (priv->hwts_rx_en & BIT(port))
config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
else
config.rx_filter = HWTSTAMP_FILTER_NONE;
@@ -413,11 +374,10 @@ static long sja1105_rxtstamp_work(struct ptp_clock_info *ptp)
bool sja1105_rxtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
{
- struct sja1105_tagger_data *tagger_data = sja1105_tagger_data(ds);
struct sja1105_private *priv = ds->priv;
struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
- if (!tagger_data->rxtstamp_get_state(ds))
+ if (!(priv->hwts_rx_en & BIT(port)))
return false;
/* We need to read the full PTP clock to reconstruct the Rx
diff --git a/drivers/net/dsa/sja1105/sja1105_tas.c b/drivers/net/dsa/sja1105/sja1105_tas.c
index e6153848a950..d7818710bc02 100644
--- a/drivers/net/dsa/sja1105/sja1105_tas.c
+++ b/drivers/net/dsa/sja1105/sja1105_tas.c
@@ -516,10 +516,11 @@ int sja1105_setup_tc_taprio(struct dsa_switch *ds, int port,
/* Can't change an already configured port (must delete qdisc first).
* Can't delete the qdisc from an unconfigured port.
*/
- if (!!tas_data->offload[port] == admin->enable)
+ if ((!!tas_data->offload[port] && admin->cmd == TAPRIO_CMD_REPLACE) ||
+ (!tas_data->offload[port] && admin->cmd == TAPRIO_CMD_DESTROY))
return -EINVAL;
- if (!admin->enable) {
+ if (admin->cmd == TAPRIO_CMD_DESTROY) {
taprio_offload_free(tas_data->offload[port]);
tas_data->offload[port] = NULL;
@@ -528,6 +529,8 @@ int sja1105_setup_tc_taprio(struct dsa_switch *ds, int port,
return rc;
return sja1105_static_config_reload(priv, SJA1105_SCHEDULING);
+ } else if (admin->cmd != TAPRIO_CMD_REPLACE) {
+ return -EOPNOTSUPP;
}
/* The cycle time extension is the amount of time the last cycle from
diff --git a/drivers/net/dsa/vitesse-vsc73xx-core.c b/drivers/net/dsa/vitesse-vsc73xx-core.c
index ae55167ce0a6..ef1a4a7c47b2 100644
--- a/drivers/net/dsa/vitesse-vsc73xx-core.c
+++ b/drivers/net/dsa/vitesse-vsc73xx-core.c
@@ -1025,17 +1025,17 @@ static int vsc73xx_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
struct vsc73xx *vsc = ds->priv;
return vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port,
- VSC73XX_MAXLEN, new_mtu);
+ VSC73XX_MAXLEN, new_mtu + ETH_HLEN + ETH_FCS_LEN);
}
/* According to application not "VSC7398 Jumbo Frames" setting
- * up the MTU to 9.6 KB does not affect the performance on standard
+ * up the frame size to 9.6 KB does not affect the performance on standard
* frames. It is clear from the application note that
* "9.6 kilobytes" == 9600 bytes.
*/
static int vsc73xx_get_max_mtu(struct dsa_switch *ds, int port)
{
- return 9600;
+ return 9600 - ETH_HLEN - ETH_FCS_LEN;
}
static const struct dsa_switch_ops vsc73xx_ds_ops = {
diff --git a/drivers/net/dsa/xrs700x/xrs700x_i2c.c b/drivers/net/dsa/xrs700x/xrs700x_i2c.c
index 14ff6887a225..c1179d7311f7 100644
--- a/drivers/net/dsa/xrs700x/xrs700x_i2c.c
+++ b/drivers/net/dsa/xrs700x/xrs700x_i2c.c
@@ -147,7 +147,7 @@ static struct i2c_driver xrs700x_i2c_driver = {
.name = "xrs700x-i2c",
.of_match_table = of_match_ptr(xrs700x_i2c_dt_ids),
},
- .probe_new = xrs700x_i2c_probe,
+ .probe = xrs700x_i2c_probe,
.remove = xrs700x_i2c_remove,
.shutdown = xrs700x_i2c_shutdown,
.id_table = xrs700x_i2c_id,
diff --git a/drivers/net/ethernet/8390/8390.h b/drivers/net/ethernet/8390/8390.h
index e52264465998..f784a6e2ab0e 100644
--- a/drivers/net/ethernet/8390/8390.h
+++ b/drivers/net/ethernet/8390/8390.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-1.0+ */
+
/* Generic NS8390 register definitions. */
/* This file is part of Donald Becker's 8390 drivers, and is distributed
diff --git a/drivers/net/ethernet/8390/apne.c b/drivers/net/ethernet/8390/apne.c
index 991ad953aa79..a09f383dd249 100644
--- a/drivers/net/ethernet/8390/apne.c
+++ b/drivers/net/ethernet/8390/apne.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Amiga Linux/68k 8390 based PCMCIA Ethernet Driver for the Amiga 1200
*
@@ -19,12 +20,6 @@
*
* ----------------------------------------------------------------------------
*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of the Linux
- * distribution for more details.
- *
- * ----------------------------------------------------------------------------
- *
*/
diff --git a/drivers/net/ethernet/8390/axnet_cs.c b/drivers/net/ethernet/8390/axnet_cs.c
index 78f985885547..fea489af72fb 100644
--- a/drivers/net/ethernet/8390/axnet_cs.c
+++ b/drivers/net/ethernet/8390/axnet_cs.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-1.0+
+
/*======================================================================
A PCMCIA ethernet driver for Asix AX88190-based cards
@@ -17,9 +19,7 @@
Written 1992,1993 by Donald Becker.
Copyright 1993 United States Government as represented by the
- Director, National Security Agency. This software may be used and
- distributed according to the terms of the GNU General Public License,
- incorporated herein by reference.
+ Director, National Security Agency.
Donald Becker may be reached at becker@scyld.com
======================================================================*/
diff --git a/drivers/net/ethernet/8390/hydra.c b/drivers/net/ethernet/8390/hydra.c
index 1df7601af86a..24f49a8ff903 100644
--- a/drivers/net/ethernet/8390/hydra.c
+++ b/drivers/net/ethernet/8390/hydra.c
@@ -1,10 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
/* New Hydra driver using generic 8390 core */
/* Based on old hydra driver by Topi Kanerva (topi@susanna.oulu.fi) */
-/* This file is subject to the terms and conditions of the GNU General */
-/* Public License. See the file COPYING in the main directory of the */
-/* Linux distribution for more details. */
-
/* Peter De Schrijver (p2@mind.be) */
/* Oldenburg 2000 */
diff --git a/drivers/net/ethernet/8390/lib8390.c b/drivers/net/ethernet/8390/lib8390.c
index e84021282edf..84aeb8054304 100644
--- a/drivers/net/ethernet/8390/lib8390.c
+++ b/drivers/net/ethernet/8390/lib8390.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-1.0+
+
/* 8390.c: A general NS8390 ethernet driver core for linux. */
/*
Written 1992-94 by Donald Becker.
@@ -5,9 +7,6 @@
Copyright 1993 United States Government as represented by the
Director, National Security Agency.
- This software may be used and distributed according to the terms
- of the GNU General Public License, incorporated herein by reference.
-
The author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation
410 Severn Ave., Suite 210
diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c
index 7fb819b9b89a..4a0a095a1a8a 100644
--- a/drivers/net/ethernet/8390/mac8390.c
+++ b/drivers/net/ethernet/8390/mac8390.c
@@ -1,11 +1,9 @@
+// SPDX-License-Identifier: GPL-1.0+
/* mac8390.c: New driver for 8390-based Nubus (or Nubus-alike)
Ethernet cards on Linux */
/* Based on the former daynaport.c driver, by Alan Cox. Some code
taken from or inspired by skeleton.c by Donald Becker, acenic.c by
- Jes Sorensen, and ne2k-pci.c by Donald Becker and Paul Gortmaker.
-
- This software may be used and distributed according to the terms of
- the GNU Public License, incorporated herein by reference. */
+ Jes Sorensen, and ne2k-pci.c by Donald Becker and Paul Gortmaker. */
/* 2000-02-28: support added for Dayna and Kinetics cards by
A.G.deWijn@phys.uu.nl */
diff --git a/drivers/net/ethernet/8390/mcf8390.c b/drivers/net/ethernet/8390/mcf8390.c
index 8a7918d33419..217838b28220 100644
--- a/drivers/net/ethernet/8390/mcf8390.c
+++ b/drivers/net/ethernet/8390/mcf8390.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Support for ColdFire CPU based boards using a NS8390 Ethernet device.
*
@@ -5,9 +6,6 @@
*
* (C) Copyright 2012, Greg Ungerer <gerg@uclinux.org>
*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of the Linux
- * distribution for more details.
*/
#include <linux/module.h>
diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c
index bc9c81dc00fd..7d89ec1cf273 100644
--- a/drivers/net/ethernet/8390/ne.c
+++ b/drivers/net/ethernet/8390/ne.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-1.0+
/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */
/*
Written 1992-94 by Donald Becker.
@@ -5,9 +6,6 @@
Copyright 1993 United States Government as represented by the
Director, National Security Agency.
- This software may be used and distributed according to the terms
- of the GNU General Public License, incorporated herein by reference.
-
The author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
diff --git a/drivers/net/ethernet/8390/ne2k-pci.c b/drivers/net/ethernet/8390/ne2k-pci.c
index 6a0a2039600a..2c6bd36d2f31 100644
--- a/drivers/net/ethernet/8390/ne2k-pci.c
+++ b/drivers/net/ethernet/8390/ne2k-pci.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-1.0+
/* A Linux device driver for PCI NE2000 clones.
*
* Authors and other copyright holders:
diff --git a/drivers/net/ethernet/8390/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c
index 0f07fe03da98..9bd5e991f1e5 100644
--- a/drivers/net/ethernet/8390/pcnet_cs.c
+++ b/drivers/net/ethernet/8390/pcnet_cs.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-1.0+
/*======================================================================
A PCMCIA ethernet driver for NS8390-based cards
@@ -17,9 +18,7 @@
Written 1992,1993 by Donald Becker.
Copyright 1993 United States Government as represented by the
- Director, National Security Agency. This software may be used and
- distributed according to the terms of the GNU General Public License,
- incorporated herein by reference.
+ Director, National Security Agency.
Donald Becker may be reached at becker@scyld.com
Based also on Keith Moore's changes to Don Becker's code, for IBM
diff --git a/drivers/net/ethernet/8390/smc-ultra.c b/drivers/net/ethernet/8390/smc-ultra.c
index 7465650c8078..22ca804b2e95 100644
--- a/drivers/net/ethernet/8390/smc-ultra.c
+++ b/drivers/net/ethernet/8390/smc-ultra.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-1.0+
/* smc-ultra.c: A SMC Ultra ethernet driver for linux. */
/*
This is a driver for the SMC Ultra and SMC EtherEZ ISA ethercards.
@@ -7,9 +8,6 @@
Copyright 1993 United States Government as represented by the
Director, National Security Agency.
- This software may be used and distributed according to the terms
- of the GNU General Public License, incorporated herein by reference.
-
The author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation
410 Severn Ave., Suite 210
diff --git a/drivers/net/ethernet/8390/stnic.c b/drivers/net/ethernet/8390/stnic.c
index bd89ca8a92df..265976e3b64a 100644
--- a/drivers/net/ethernet/8390/stnic.c
+++ b/drivers/net/ethernet/8390/stnic.c
@@ -1,9 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-only
/* stnic.c : A SH7750 specific part of driver for NS DP83902A ST-NIC.
*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
* Copyright (C) 1999 kaz Kojima
*/
diff --git a/drivers/net/ethernet/8390/wd.c b/drivers/net/ethernet/8390/wd.c
index 119021d41451..ffd639477dfc 100644
--- a/drivers/net/ethernet/8390/wd.c
+++ b/drivers/net/ethernet/8390/wd.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-1.0+
/* wd.c: A WD80x3 ethernet driver for linux. */
/*
Written 1993-94 by Donald Becker.
@@ -5,9 +6,6 @@
Copyright 1993 United States Government as represented by the
Director, National Security Agency.
- This software may be used and distributed according to the terms
- of the GNU General Public License, incorporated herein by reference.
-
The author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation
410 Severn Ave., Suite 210
diff --git a/drivers/net/ethernet/8390/zorro8390.c b/drivers/net/ethernet/8390/zorro8390.c
index e8b4fe813a08..d70390e9d03d 100644
--- a/drivers/net/ethernet/8390/zorro8390.c
+++ b/drivers/net/ethernet/8390/zorro8390.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Amiga Linux/m68k and Linux/PPC Zorro NS8390 Ethernet Driver
*
@@ -9,12 +10,6 @@
*
* ---------------------------------------------------------------------------
*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of the Linux
- * distribution for more details.
- *
- * ---------------------------------------------------------------------------
- *
* The Ariadne II and X-Surf are Zorro-II boards containing Realtek RTL8019AS
* Ethernet Controllers.
*/
diff --git a/drivers/net/ethernet/altera/Kconfig b/drivers/net/ethernet/altera/Kconfig
index dd7fd41ccde5..17985319088c 100644
--- a/drivers/net/ethernet/altera/Kconfig
+++ b/drivers/net/ethernet/altera/Kconfig
@@ -4,7 +4,9 @@ config ALTERA_TSE
depends on HAS_DMA
select PHYLIB
select PHYLINK
- select PCS_ALTERA_TSE
+ select PCS_LYNX
+ select MDIO_REGMAP
+ select REGMAP_MMIO
help
This driver supports the Altera Triple-Speed (TSE) Ethernet MAC.
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
index 66e3af73ec41..2e15800e5310 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -27,14 +27,16 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mii.h>
+#include <linux/mdio/mdio-regmap.h>
#include <linux/netdevice.h>
#include <linux/of_device.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/of_platform.h>
-#include <linux/pcs-altera-tse.h>
+#include <linux/pcs-lynx.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/skbuff.h>
#include <asm/cacheflush.h>
@@ -1036,10 +1038,6 @@ static struct net_device_ops altera_tse_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static void alt_tse_mac_an_restart(struct phylink_config *config)
-{
-}
-
static void alt_tse_mac_config(struct phylink_config *config, unsigned int mode,
const struct phylink_link_state *state)
{
@@ -1096,7 +1094,6 @@ static struct phylink_pcs *alt_tse_select_pcs(struct phylink_config *config,
}
static const struct phylink_mac_ops alt_tse_phylink_ops = {
- .mac_an_restart = alt_tse_mac_an_restart,
.mac_config = alt_tse_mac_config,
.mac_link_down = alt_tse_mac_link_down,
.mac_link_up = alt_tse_mac_link_up,
@@ -1137,13 +1134,16 @@ static int request_and_map(struct platform_device *pdev, const char *name,
static int altera_tse_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id = NULL;
+ struct regmap_config pcs_regmap_cfg;
struct altera_tse_private *priv;
+ struct mdio_regmap_config mrc;
struct resource *control_port;
+ struct regmap *pcs_regmap;
struct resource *dma_res;
struct resource *pcs_res;
+ struct mii_bus *pcs_bus;
struct net_device *ndev;
void __iomem *descmap;
- int pcs_reg_width = 2;
int ret = -ENODEV;
ndev = alloc_etherdev(sizeof(struct altera_tse_private));
@@ -1255,18 +1255,41 @@ static int altera_tse_probe(struct platform_device *pdev)
if (ret)
goto err_free_netdev;
+ memset(&pcs_regmap_cfg, 0, sizeof(pcs_regmap_cfg));
+ memset(&mrc, 0, sizeof(mrc));
/* SGMII PCS address space. The location can vary depending on how the
* IP is integrated. We can have a resource dedicated to it at a specific
* address space, but if it's not the case, we fallback to the mdiophy0
* from the MAC's address space
*/
- ret = request_and_map(pdev, "pcs", &pcs_res,
- &priv->pcs_base);
+ ret = request_and_map(pdev, "pcs", &pcs_res, &priv->pcs_base);
if (ret) {
+ /* If we can't find a dedicated resource for the PCS, fallback
+ * to the internal PCS, that has a different address stride
+ */
priv->pcs_base = priv->mac_dev + tse_csroffs(mdio_phy0);
- pcs_reg_width = 4;
+ pcs_regmap_cfg.reg_bits = 32;
+ /* Values are MDIO-like values, on 16 bits */
+ pcs_regmap_cfg.val_bits = 16;
+ pcs_regmap_cfg.reg_shift = REGMAP_UPSHIFT(2);
+ } else {
+ pcs_regmap_cfg.reg_bits = 16;
+ pcs_regmap_cfg.val_bits = 16;
+ pcs_regmap_cfg.reg_shift = REGMAP_UPSHIFT(1);
}
+ /* Create a regmap for the PCS so that it can be used by the PCS driver */
+ pcs_regmap = devm_regmap_init_mmio(&pdev->dev, priv->pcs_base,
+ &pcs_regmap_cfg);
+ if (IS_ERR(pcs_regmap)) {
+ ret = PTR_ERR(pcs_regmap);
+ goto err_free_netdev;
+ }
+ mrc.regmap = pcs_regmap;
+ mrc.parent = &pdev->dev;
+ mrc.valid_addr = 0x0;
+ mrc.autoscan = false;
+
/* Rx IRQ */
priv->rx_irq = platform_get_irq_byname(pdev, "rx_irq");
if (priv->rx_irq == -ENXIO) {
@@ -1389,7 +1412,18 @@ static int altera_tse_probe(struct platform_device *pdev)
(unsigned long) control_port->start, priv->rx_irq,
priv->tx_irq);
- priv->pcs = alt_tse_pcs_create(ndev, priv->pcs_base, pcs_reg_width);
+ snprintf(mrc.name, MII_BUS_ID_SIZE, "%s-pcs-mii", ndev->name);
+ pcs_bus = devm_mdio_regmap_register(&pdev->dev, &mrc);
+ if (IS_ERR(pcs_bus)) {
+ ret = PTR_ERR(pcs_bus);
+ goto err_init_pcs;
+ }
+
+ priv->pcs = lynx_pcs_create_mdiodev(pcs_bus, 0);
+ if (IS_ERR(priv->pcs)) {
+ ret = PTR_ERR(priv->pcs);
+ goto err_init_pcs;
+ }
priv->phylink_config.dev = &ndev->dev;
priv->phylink_config.type = PHYLINK_NETDEV;
@@ -1412,12 +1446,13 @@ static int altera_tse_probe(struct platform_device *pdev)
if (IS_ERR(priv->phylink)) {
dev_err(&pdev->dev, "failed to create phylink\n");
ret = PTR_ERR(priv->phylink);
- goto err_init_phy;
+ goto err_init_phylink;
}
return 0;
-
-err_init_phy:
+err_init_phylink:
+ lynx_pcs_destroy(priv->pcs);
+err_init_pcs:
unregister_netdev(ndev);
err_register_netdev:
netif_napi_del(&priv->napi);
@@ -1438,6 +1473,8 @@ static int altera_tse_remove(struct platform_device *pdev)
altera_tse_mdio_destroy(ndev);
unregister_netdev(ndev);
phylink_destroy(priv->phylink);
+ lynx_pcs_destroy(priv->pcs);
+
free_netdev(ndev);
return 0;
diff --git a/drivers/net/ethernet/amazon/ena/ena_admin_defs.h b/drivers/net/ethernet/amazon/ena/ena_admin_defs.h
index 466ad9470d1f..6de0d590be34 100644
--- a/drivers/net/ethernet/amazon/ena/ena_admin_defs.h
+++ b/drivers/net/ethernet/amazon/ena/ena_admin_defs.h
@@ -869,7 +869,9 @@ struct ena_admin_host_info {
* 2 : interrupt_moderation
* 3 : rx_buf_mirroring
* 4 : rss_configurable_function_key
- * 31:5 : reserved
+ * 5 : reserved
+ * 6 : rx_page_reuse
+ * 31:7 : reserved
*/
u32 driver_supported_features;
};
@@ -1184,6 +1186,8 @@ struct ena_admin_ena_mmio_req_read_less_resp {
#define ENA_ADMIN_HOST_INFO_RX_BUF_MIRRORING_MASK BIT(3)
#define ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_SHIFT 4
#define ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_MASK BIT(4)
+#define ENA_ADMIN_HOST_INFO_RX_PAGE_REUSE_SHIFT 6
+#define ENA_ADMIN_HOST_INFO_RX_PAGE_REUSE_MASK BIT(6)
/* aenq_common_desc */
#define ENA_ADMIN_AENQ_COMMON_DESC_PHASE_MASK BIT(0)
diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c
index 451c3a1b6255..633b321d7fdd 100644
--- a/drivers/net/ethernet/amazon/ena/ena_com.c
+++ b/drivers/net/ethernet/amazon/ena/ena_com.c
@@ -35,6 +35,8 @@
#define ENA_REGS_ADMIN_INTR_MASK 1
+#define ENA_MAX_BACKOFF_DELAY_EXP 16U
+
#define ENA_MIN_ADMIN_POLL_US 100
#define ENA_MAX_ADMIN_POLL_US 5000
@@ -536,6 +538,7 @@ static int ena_com_comp_status_to_errno(struct ena_com_admin_queue *admin_queue,
static void ena_delay_exponential_backoff_us(u32 exp, u32 delay_us)
{
+ exp = min_t(u32, exp, ENA_MAX_BACKOFF_DELAY_EXP);
delay_us = max_t(u32, ENA_MIN_ADMIN_POLL_US, delay_us);
delay_us = min_t(u32, delay_us * (1U << exp), ENA_MAX_ADMIN_POLL_US);
usleep_range(delay_us, 2 * delay_us);
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
index e6a6efaeb87c..d19593fae226 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -1023,7 +1023,7 @@ static int ena_alloc_rx_buffer(struct ena_ring *rx_ring,
int tailroom;
/* restore page offset value in case it has been changed by device */
- rx_info->page_offset = headroom;
+ rx_info->buf_offset = headroom;
/* if previous allocated page is not used */
if (unlikely(rx_info->page))
@@ -1040,6 +1040,8 @@ static int ena_alloc_rx_buffer(struct ena_ring *rx_ring,
tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
rx_info->page = page;
+ rx_info->dma_addr = dma;
+ rx_info->page_offset = 0;
ena_buf = &rx_info->ena_buf;
ena_buf->paddr = dma + headroom;
ena_buf->len = ENA_PAGE_SIZE - headroom - tailroom;
@@ -1047,14 +1049,12 @@ static int ena_alloc_rx_buffer(struct ena_ring *rx_ring,
return 0;
}
-static void ena_unmap_rx_buff(struct ena_ring *rx_ring,
- struct ena_rx_buffer *rx_info)
+static void ena_unmap_rx_buff_attrs(struct ena_ring *rx_ring,
+ struct ena_rx_buffer *rx_info,
+ unsigned long attrs)
{
- struct ena_com_buf *ena_buf = &rx_info->ena_buf;
-
- dma_unmap_page(rx_ring->dev, ena_buf->paddr - rx_ring->rx_headroom,
- ENA_PAGE_SIZE,
- DMA_BIDIRECTIONAL);
+ dma_unmap_page_attrs(rx_ring->dev, rx_info->dma_addr, ENA_PAGE_SIZE,
+ DMA_BIDIRECTIONAL, attrs);
}
static void ena_free_rx_page(struct ena_ring *rx_ring,
@@ -1068,7 +1068,7 @@ static void ena_free_rx_page(struct ena_ring *rx_ring,
return;
}
- ena_unmap_rx_buff(rx_ring, rx_info);
+ ena_unmap_rx_buff_attrs(rx_ring, rx_info, 0);
__free_page(page);
rx_info->page = NULL;
@@ -1406,14 +1406,14 @@ static int ena_clean_tx_irq(struct ena_ring *tx_ring, u32 budget)
return tx_pkts;
}
-static struct sk_buff *ena_alloc_skb(struct ena_ring *rx_ring, void *first_frag)
+static struct sk_buff *ena_alloc_skb(struct ena_ring *rx_ring, void *first_frag, u16 len)
{
struct sk_buff *skb;
if (!first_frag)
- skb = napi_alloc_skb(rx_ring->napi, rx_ring->rx_copybreak);
+ skb = napi_alloc_skb(rx_ring->napi, len);
else
- skb = napi_build_skb(first_frag, ENA_PAGE_SIZE);
+ skb = napi_build_skb(first_frag, len);
if (unlikely(!skb)) {
ena_increase_stat(&rx_ring->rx_stats.skb_alloc_fail, 1,
@@ -1422,24 +1422,47 @@ static struct sk_buff *ena_alloc_skb(struct ena_ring *rx_ring, void *first_frag)
netif_dbg(rx_ring->adapter, rx_err, rx_ring->netdev,
"Failed to allocate skb. first_frag %s\n",
first_frag ? "provided" : "not provided");
- return NULL;
}
return skb;
}
+static bool ena_try_rx_buf_page_reuse(struct ena_rx_buffer *rx_info, u16 buf_len,
+ u16 len, int pkt_offset)
+{
+ struct ena_com_buf *ena_buf = &rx_info->ena_buf;
+
+ /* More than ENA_MIN_RX_BUF_SIZE left in the reused buffer
+ * for data + headroom + tailroom.
+ */
+ if (SKB_DATA_ALIGN(len + pkt_offset) + ENA_MIN_RX_BUF_SIZE <= ena_buf->len) {
+ page_ref_inc(rx_info->page);
+ rx_info->page_offset += buf_len;
+ ena_buf->paddr += buf_len;
+ ena_buf->len -= buf_len;
+ return true;
+ }
+
+ return false;
+}
+
static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
struct ena_com_rx_buf_info *ena_bufs,
u32 descs,
u16 *next_to_clean)
{
+ int tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+ bool is_xdp_loaded = ena_xdp_present_ring(rx_ring);
struct ena_rx_buffer *rx_info;
struct ena_adapter *adapter;
+ int page_offset, pkt_offset;
+ dma_addr_t pre_reuse_paddr;
u16 len, req_id, buf = 0;
+ bool reuse_rx_buf_page;
struct sk_buff *skb;
- void *page_addr;
- u32 page_offset;
- void *data_addr;
+ void *buf_addr;
+ int buf_offset;
+ u16 buf_len;
len = ena_bufs[buf].len;
req_id = ena_bufs[buf].req_id;
@@ -1459,34 +1482,30 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
"rx_info %p page %p\n",
rx_info, rx_info->page);
- /* save virt address of first buffer */
- page_addr = page_address(rx_info->page);
+ buf_offset = rx_info->buf_offset;
+ pkt_offset = buf_offset - rx_ring->rx_headroom;
page_offset = rx_info->page_offset;
- data_addr = page_addr + page_offset;
-
- prefetch(data_addr);
+ buf_addr = page_address(rx_info->page) + page_offset;
if (len <= rx_ring->rx_copybreak) {
- skb = ena_alloc_skb(rx_ring, NULL);
+ skb = ena_alloc_skb(rx_ring, NULL, len);
if (unlikely(!skb))
return NULL;
- netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
- "RX allocated small packet. len %d. data_len %d\n",
- skb->len, skb->data_len);
-
/* sync this buffer for CPU use */
dma_sync_single_for_cpu(rx_ring->dev,
- dma_unmap_addr(&rx_info->ena_buf, paddr),
+ dma_unmap_addr(&rx_info->ena_buf, paddr) + pkt_offset,
len,
DMA_FROM_DEVICE);
- skb_copy_to_linear_data(skb, data_addr, len);
+ skb_copy_to_linear_data(skb, buf_addr + buf_offset, len);
dma_sync_single_for_device(rx_ring->dev,
- dma_unmap_addr(&rx_info->ena_buf, paddr),
+ dma_unmap_addr(&rx_info->ena_buf, paddr) + pkt_offset,
len,
DMA_FROM_DEVICE);
skb_put(skb, len);
+ netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
+ "RX allocated small packet. len %d.\n", skb->len);
skb->protocol = eth_type_trans(skb, rx_ring->netdev);
rx_ring->free_ids[*next_to_clean] = req_id;
*next_to_clean = ENA_RX_RING_IDX_ADD(*next_to_clean, descs,
@@ -1494,14 +1513,28 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
return skb;
}
- ena_unmap_rx_buff(rx_ring, rx_info);
+ buf_len = SKB_DATA_ALIGN(len + buf_offset + tailroom);
+
+ pre_reuse_paddr = dma_unmap_addr(&rx_info->ena_buf, paddr);
+
+ /* If XDP isn't loaded try to reuse part of the RX buffer */
+ reuse_rx_buf_page = !is_xdp_loaded &&
+ ena_try_rx_buf_page_reuse(rx_info, buf_len, len, pkt_offset);
- skb = ena_alloc_skb(rx_ring, page_addr);
+ dma_sync_single_for_cpu(rx_ring->dev,
+ pre_reuse_paddr + pkt_offset,
+ len,
+ DMA_FROM_DEVICE);
+
+ if (!reuse_rx_buf_page)
+ ena_unmap_rx_buff_attrs(rx_ring, rx_info, DMA_ATTR_SKIP_CPU_SYNC);
+
+ skb = ena_alloc_skb(rx_ring, buf_addr, buf_len);
if (unlikely(!skb))
return NULL;
/* Populate skb's linear part */
- skb_reserve(skb, page_offset);
+ skb_reserve(skb, buf_offset);
skb_put(skb, len);
skb->protocol = eth_type_trans(skb, rx_ring->netdev);
@@ -1510,7 +1543,8 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
"RX skb updated. len %d. data_len %d\n",
skb->len, skb->data_len);
- rx_info->page = NULL;
+ if (!reuse_rx_buf_page)
+ rx_info->page = NULL;
rx_ring->free_ids[*next_to_clean] = req_id;
*next_to_clean =
@@ -1525,10 +1559,28 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
rx_info = &rx_ring->rx_buffer_info[req_id];
- ena_unmap_rx_buff(rx_ring, rx_info);
+ /* rx_info->buf_offset includes rx_ring->rx_headroom */
+ buf_offset = rx_info->buf_offset;
+ pkt_offset = buf_offset - rx_ring->rx_headroom;
+ buf_len = SKB_DATA_ALIGN(len + buf_offset + tailroom);
+ page_offset = rx_info->page_offset;
+
+ pre_reuse_paddr = dma_unmap_addr(&rx_info->ena_buf, paddr);
+
+ reuse_rx_buf_page = !is_xdp_loaded &&
+ ena_try_rx_buf_page_reuse(rx_info, buf_len, len, pkt_offset);
+
+ dma_sync_single_for_cpu(rx_ring->dev,
+ pre_reuse_paddr + pkt_offset,
+ len,
+ DMA_FROM_DEVICE);
+
+ if (!reuse_rx_buf_page)
+ ena_unmap_rx_buff_attrs(rx_ring, rx_info,
+ DMA_ATTR_SKIP_CPU_SYNC);
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_info->page,
- rx_info->page_offset, len, ENA_PAGE_SIZE);
+ page_offset + buf_offset, len, buf_len);
} while (1);
@@ -1626,7 +1678,7 @@ static int ena_xdp_handle_buff(struct ena_ring *rx_ring, struct xdp_buff *xdp)
rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id];
xdp_prepare_buff(xdp, page_address(rx_info->page),
- rx_info->page_offset,
+ rx_info->buf_offset,
rx_ring->ena_bufs[0].len, false);
/* If for some reason we received a bigger packet than
* we expect, then we simply drop it
@@ -1638,7 +1690,7 @@ static int ena_xdp_handle_buff(struct ena_ring *rx_ring, struct xdp_buff *xdp)
/* The xdp program might expand the headers */
if (ret == ENA_XDP_PASS) {
- rx_info->page_offset = xdp->data - xdp->data_hard_start;
+ rx_info->buf_offset = xdp->data - xdp->data_hard_start;
rx_ring->ena_bufs[0].len = xdp->data_end - xdp->data;
}
@@ -1693,7 +1745,7 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,
/* First descriptor might have an offset set by the device */
rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id];
- rx_info->page_offset += ena_rx_ctx.pkt_offset;
+ rx_info->buf_offset += ena_rx_ctx.pkt_offset;
netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
"rx_poll: q %d got packet from ena. descs #: %d l3 proto %d l4 proto %d hash: %x\n",
@@ -1723,8 +1775,9 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,
* from RX side.
*/
if (xdp_verdict & ENA_XDP_FORWARDED) {
- ena_unmap_rx_buff(rx_ring,
- &rx_ring->rx_buffer_info[req_id]);
+ ena_unmap_rx_buff_attrs(rx_ring,
+ &rx_ring->rx_buffer_info[req_id],
+ 0);
rx_ring->rx_buffer_info[req_id].page = NULL;
}
}
@@ -3233,7 +3286,8 @@ static void ena_config_host_info(struct ena_com_dev *ena_dev, struct pci_dev *pd
ENA_ADMIN_HOST_INFO_RX_OFFSET_MASK |
ENA_ADMIN_HOST_INFO_INTERRUPT_MODERATION_MASK |
ENA_ADMIN_HOST_INFO_RX_BUF_MIRRORING_MASK |
- ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_MASK;
+ ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_MASK |
+ ENA_ADMIN_HOST_INFO_RX_PAGE_REUSE_MASK;
rc = ena_com_set_host_attributes(ena_dev);
if (rc) {
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h
index 5a0d4ee76172..248b715b4d68 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.h
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h
@@ -51,6 +51,8 @@
#define ENA_DEFAULT_RING_SIZE (1024)
#define ENA_MIN_RING_SIZE (256)
+#define ENA_MIN_RX_BUF_SIZE (2048)
+
#define ENA_MIN_NUM_IO_QUEUES (1)
#define ENA_TX_WAKEUP_THRESH (MAX_SKB_FRAGS + 2)
@@ -175,7 +177,9 @@ struct ena_tx_buffer {
struct ena_rx_buffer {
struct sk_buff *skb;
struct page *page;
+ dma_addr_t dma_addr;
u32 page_offset;
+ u32 buf_offset;
struct ena_com_buf ena_buf;
} ____cacheline_aligned;
diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c
index 483a070d96fa..f2c79456d745 100644
--- a/drivers/net/ethernet/amd/pds_core/core.c
+++ b/drivers/net/ethernet/amd/pds_core/core.c
@@ -196,7 +196,7 @@ int pdsc_qcq_alloc(struct pdsc *pdsc, unsigned int type, unsigned int index,
dma_addr_t q_base_pa;
int err;
- qcq->q.info = vzalloc(num_descs * sizeof(*qcq->q.info));
+ qcq->q.info = vcalloc(num_descs, sizeof(*qcq->q.info));
if (!qcq->q.info) {
err = -ENOMEM;
goto err_out;
@@ -219,7 +219,7 @@ int pdsc_qcq_alloc(struct pdsc *pdsc, unsigned int type, unsigned int index,
if (err)
goto err_out_free_q_info;
- qcq->cq.info = vzalloc(num_descs * sizeof(*qcq->cq.info));
+ qcq->cq.info = vcalloc(num_descs, sizeof(*qcq->cq.info));
if (!qcq->cq.info) {
err = -ENOMEM;
goto err_out_free_irq;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 16e7fb2c0dae..6a716337f48b 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -2782,9 +2782,9 @@ static bool xgbe_phy_valid_speed_baset_mode(struct xgbe_prv_data *pdata,
switch (speed) {
case SPEED_10:
- /* Supported in ver >= 30H */
+ /* Supported in ver 21H and ver >= 30H */
ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER);
- return (ver >= 0x30) ? true : false;
+ return (ver == 0x21 || ver >= 0x30);
case SPEED_100:
case SPEED_1000:
return true;
@@ -2806,9 +2806,10 @@ static bool xgbe_phy_valid_speed_sfp_mode(struct xgbe_prv_data *pdata,
switch (speed) {
case SPEED_10:
- /* Supported in ver >= 30H */
+ /* Supported in ver 21H and ver >= 30H */
ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER);
- return (ver >= 0x30) && (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000);
+ return ((ver == 0x21 || ver >= 0x30) &&
+ (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000));
case SPEED_100:
return (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000);
case SPEED_1000:
@@ -3158,9 +3159,9 @@ static bool xgbe_phy_port_mode_mismatch(struct xgbe_prv_data *pdata)
struct xgbe_phy_data *phy_data = pdata->phy_data;
unsigned int ver;
- /* 10 Mbps speed is not supported in ver < 30H */
+ /* 10 Mbps speed is supported in ver 21H and ver >= 30H */
ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER);
- if (ver < 0x30 && (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10))
+ if ((ver < 0x30 && ver != 0x21) && (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10))
return true;
switch (phy_data->port_mode) {
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c
index 7eb5851eb95d..6afff8af5e86 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c
@@ -289,7 +289,7 @@ static int aq_get_txsc_stats(struct aq_hw_s *hw, const int sc_idx,
static int aq_mdo_dev_open(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
int ret = 0;
if (netif_carrier_ok(nic->ndev))
@@ -300,7 +300,7 @@ static int aq_mdo_dev_open(struct macsec_context *ctx)
static int aq_mdo_dev_stop(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
int i;
for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
@@ -439,7 +439,7 @@ static enum aq_macsec_sc_sa sc_sa_from_num_an(const int num_an)
static int aq_mdo_add_secy(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
const struct macsec_secy *secy = ctx->secy;
enum aq_macsec_sc_sa sc_sa;
@@ -474,7 +474,7 @@ static int aq_mdo_add_secy(struct macsec_context *ctx)
static int aq_mdo_upd_secy(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
const struct macsec_secy *secy = ctx->secy;
int txsc_idx;
int ret = 0;
@@ -528,7 +528,7 @@ static int aq_clear_txsc(struct aq_nic_s *nic, const int txsc_idx,
static int aq_mdo_del_secy(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
int ret = 0;
if (!nic->macsec_cfg)
@@ -576,7 +576,7 @@ static int aq_update_txsa(struct aq_nic_s *nic, const unsigned int sc_idx,
static int aq_mdo_add_txsa(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
const struct macsec_secy *secy = ctx->secy;
struct aq_macsec_txsc *aq_txsc;
@@ -603,7 +603,7 @@ static int aq_mdo_add_txsa(struct macsec_context *ctx)
static int aq_mdo_upd_txsa(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
const struct macsec_secy *secy = ctx->secy;
struct aq_macsec_txsc *aq_txsc;
@@ -652,7 +652,7 @@ static int aq_clear_txsa(struct aq_nic_s *nic, struct aq_macsec_txsc *aq_txsc,
static int aq_mdo_del_txsa(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
int txsc_idx;
int ret = 0;
@@ -744,7 +744,7 @@ static int aq_set_rxsc(struct aq_nic_s *nic, const u32 rxsc_idx)
static int aq_mdo_add_rxsc(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
const u32 rxsc_idx_max = aq_sc_idx_max(cfg->sc_sa);
u32 rxsc_idx;
@@ -775,7 +775,7 @@ static int aq_mdo_add_rxsc(struct macsec_context *ctx)
static int aq_mdo_upd_rxsc(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
int rxsc_idx;
int ret = 0;
@@ -838,7 +838,7 @@ static int aq_clear_rxsc(struct aq_nic_s *nic, const int rxsc_idx,
static int aq_mdo_del_rxsc(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
enum aq_clear_type clear_type = AQ_CLEAR_SW;
int rxsc_idx;
int ret = 0;
@@ -906,8 +906,8 @@ static int aq_update_rxsa(struct aq_nic_s *nic, const unsigned int sc_idx,
static int aq_mdo_add_rxsa(struct macsec_context *ctx)
{
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
const struct macsec_rx_sc *rx_sc = ctx->sa.rx_sa->sc;
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
const struct macsec_secy *secy = ctx->secy;
struct aq_macsec_rxsc *aq_rxsc;
int rxsc_idx;
@@ -933,8 +933,8 @@ static int aq_mdo_add_rxsa(struct macsec_context *ctx)
static int aq_mdo_upd_rxsa(struct macsec_context *ctx)
{
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
const struct macsec_rx_sc *rx_sc = ctx->sa.rx_sa->sc;
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
const struct macsec_secy *secy = ctx->secy;
int rxsc_idx;
@@ -982,8 +982,8 @@ static int aq_clear_rxsa(struct aq_nic_s *nic, struct aq_macsec_rxsc *aq_rxsc,
static int aq_mdo_del_rxsa(struct macsec_context *ctx)
{
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
const struct macsec_rx_sc *rx_sc = ctx->sa.rx_sa->sc;
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
int rxsc_idx;
int ret = 0;
@@ -1000,7 +1000,7 @@ static int aq_mdo_del_rxsa(struct macsec_context *ctx)
static int aq_mdo_get_dev_stats(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_common_stats *stats = &nic->macsec_cfg->stats;
struct aq_hw_s *hw = nic->aq_hw;
@@ -1020,7 +1020,7 @@ static int aq_mdo_get_dev_stats(struct macsec_context *ctx)
static int aq_mdo_get_tx_sc_stats(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_tx_sc_stats *stats;
struct aq_hw_s *hw = nic->aq_hw;
struct aq_macsec_txsc *aq_txsc;
@@ -1044,7 +1044,7 @@ static int aq_mdo_get_tx_sc_stats(struct macsec_context *ctx)
static int aq_mdo_get_tx_sa_stats(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
struct aq_macsec_tx_sa_stats *stats;
struct aq_hw_s *hw = nic->aq_hw;
@@ -1084,7 +1084,7 @@ static int aq_mdo_get_tx_sa_stats(struct macsec_context *ctx)
static int aq_mdo_get_rx_sc_stats(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
struct aq_macsec_rx_sa_stats *stats;
struct aq_hw_s *hw = nic->aq_hw;
@@ -1129,7 +1129,7 @@ static int aq_mdo_get_rx_sc_stats(struct macsec_context *ctx)
static int aq_mdo_get_rx_sa_stats(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
struct aq_macsec_rx_sa_stats *stats;
struct aq_hw_s *hw = nic->aq_hw;
@@ -1399,7 +1399,7 @@ static void aq_check_txsa_expiration(struct aq_nic_s *nic)
#define AQ_LOCKED_MDO_DEF(mdo) \
static int aq_locked_mdo_##mdo(struct macsec_context *ctx) \
{ \
- struct aq_nic_s *nic = netdev_priv(ctx->netdev); \
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); \
int ret; \
mutex_lock(&nic->macsec_mutex); \
ret = aq_mdo_##mdo(ctx); \
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
index 7f933175cbda..4de22eed099a 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
@@ -532,10 +532,10 @@ static bool aq_add_rx_fragment(struct device *dev,
buff_->rxdata.pg_off,
buff_->len,
DMA_FROM_DEVICE);
- skb_frag_off_set(frag, buff_->rxdata.pg_off);
- skb_frag_size_set(frag, buff_->len);
sinfo->xdp_frags_size += buff_->len;
- __skb_frag_set_page(frag, buff_->rxdata.page);
+ skb_frag_fill_page_desc(frag, buff_->rxdata.page,
+ buff_->rxdata.pg_off,
+ buff_->len);
buff_->is_cleaned = 1;
diff --git a/drivers/net/ethernet/arc/emac.h b/drivers/net/ethernet/arc/emac.h
index d820ae03a966..0e244f0e25fd 100644
--- a/drivers/net/ethernet/arc/emac.h
+++ b/drivers/net/ethernet/arc/emac.h
@@ -220,6 +220,6 @@ static inline void arc_reg_clr(struct arc_emac_priv *priv, int reg, int mask)
int arc_mdio_probe(struct arc_emac_priv *priv);
int arc_mdio_remove(struct arc_emac_priv *priv);
int arc_emac_probe(struct net_device *ndev, int interface);
-int arc_emac_remove(struct net_device *ndev);
+void arc_emac_remove(struct net_device *ndev);
#endif /* ARC_EMAC_H */
diff --git a/drivers/net/ethernet/arc/emac_arc.c b/drivers/net/ethernet/arc/emac_arc.c
index 800620b8f10d..ce3147e886a1 100644
--- a/drivers/net/ethernet/arc/emac_arc.c
+++ b/drivers/net/ethernet/arc/emac_arc.c
@@ -61,11 +61,11 @@ out_netdev:
static int emac_arc_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
- int err;
- err = arc_emac_remove(ndev);
+ arc_emac_remove(ndev);
free_netdev(ndev);
- return err;
+
+ return 0;
}
static const struct of_device_id emac_arc_dt_ids[] = {
diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c
index ba0646b3b122..2b427d8a1831 100644
--- a/drivers/net/ethernet/arc/emac_main.c
+++ b/drivers/net/ethernet/arc/emac_main.c
@@ -1008,7 +1008,7 @@ out_put_node:
}
EXPORT_SYMBOL_GPL(arc_emac_probe);
-int arc_emac_remove(struct net_device *ndev)
+void arc_emac_remove(struct net_device *ndev)
{
struct arc_emac_priv *priv = netdev_priv(ndev);
@@ -1019,8 +1019,6 @@ int arc_emac_remove(struct net_device *ndev)
if (!IS_ERR(priv->clk))
clk_disable_unprepare(priv->clk);
-
- return 0;
}
EXPORT_SYMBOL_GPL(arc_emac_remove);
diff --git a/drivers/net/ethernet/arc/emac_rockchip.c b/drivers/net/ethernet/arc/emac_rockchip.c
index 1c9ca3bcb871..509101112279 100644
--- a/drivers/net/ethernet/arc/emac_rockchip.c
+++ b/drivers/net/ethernet/arc/emac_rockchip.c
@@ -248,9 +248,8 @@ static int emac_rockchip_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct rockchip_priv_data *priv = netdev_priv(ndev);
- int err;
- err = arc_emac_remove(ndev);
+ arc_emac_remove(ndev);
clk_disable_unprepare(priv->refclk);
@@ -261,7 +260,7 @@ static int emac_rockchip_remove(struct platform_device *pdev)
clk_disable_unprepare(priv->macclk);
free_netdev(ndev);
- return err;
+ return 0;
}
static struct platform_driver emac_rockchip_driver = {
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 4a288799633f..940c5d1ff9cf 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -2094,8 +2094,11 @@ static int atl1c_tso_csum(struct atl1c_adapter *adapter,
real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
+ ntohs(ip_hdr(skb)->tot_len));
- if (real_len < skb->len)
- pskb_trim(skb, real_len);
+ if (real_len < skb->len) {
+ err = pskb_trim(skb, real_len);
+ if (err)
+ return err;
+ }
hdr_len = skb_tcp_all_headers(skb);
if (unlikely(skb->len == hdr_len)) {
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index 5db0f3495a32..5935be190b9e 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -1641,8 +1641,11 @@ static int atl1e_tso_csum(struct atl1e_adapter *adapter,
real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
+ ntohs(ip_hdr(skb)->tot_len));
- if (real_len < skb->len)
- pskb_trim(skb, real_len);
+ if (real_len < skb->len) {
+ err = pskb_trim(skb, real_len);
+ if (err)
+ return err;
+ }
hdr_len = skb_tcp_all_headers(skb);
if (unlikely(skb->len == hdr_len)) {
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index c8444bcdf527..02aa6fd8ebc2 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -2113,8 +2113,11 @@ static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
real_len = (((unsigned char *)iph - skb->data) +
ntohs(iph->tot_len));
- if (real_len < skb->len)
- pskb_trim(skb, real_len);
+ if (real_len < skb->len) {
+ err = pskb_trim(skb, real_len);
+ if (err)
+ return err;
+ }
hdr_len = skb_tcp_all_headers(skb);
if (skb->len == hdr_len) {
iph->check = 0;
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index 392ec09a1d8a..3e4fb3c3e834 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -1793,11 +1793,9 @@ static int b44_nway_reset(struct net_device *dev)
b44_readphy(bp, MII_BMCR, &bmcr);
b44_readphy(bp, MII_BMCR, &bmcr);
r = -EINVAL;
- if (bmcr & BMCR_ANENABLE) {
- b44_writephy(bp, MII_BMCR,
- bmcr | BMCR_ANRESTART);
- r = 0;
- }
+ if (bmcr & BMCR_ANENABLE)
+ r = b44_writephy(bp, MII_BMCR,
+ bmcr | BMCR_ANRESTART);
spin_unlock_irq(&bp->lock);
return r;
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index 1761df8fb7f9..52ee3751187a 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1448,7 +1448,7 @@ int bgmac_phy_connect_direct(struct bgmac *bgmac)
int err;
phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, NULL);
- if (!phy_dev || IS_ERR(phy_dev)) {
+ if (IS_ERR(phy_dev)) {
dev_err(bgmac->dev, "Failed to register fixed PHY device\n");
return -ENODEV;
}
@@ -1492,8 +1492,6 @@ int bgmac_enet_probe(struct bgmac *bgmac)
bgmac->in_init = true;
- bgmac_chip_intrs_off(bgmac);
-
net_dev->irq = bgmac->irq;
SET_NETDEV_DEV(net_dev, bgmac->dev);
dev_set_drvdata(bgmac->dev, bgmac);
@@ -1511,6 +1509,8 @@ int bgmac_enet_probe(struct bgmac *bgmac)
*/
bgmac_clk_enable(bgmac, 0);
+ bgmac_chip_intrs_off(bgmac);
+
/* This seems to be fixing IRQ by assigning OOB #6 to the core */
if (!(bgmac->feature_flags & BGMAC_FEAT_IDM_MASK)) {
if (bgmac->feature_flags & BGMAC_FEAT_IRQ_ID_OOB_6)
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 466e1d62bcf6..0d917a9699c5 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -2955,7 +2955,6 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
shinfo = skb_shinfo(skb);
shinfo->nr_frags--;
page = skb_frag_page(&shinfo->frags[shinfo->nr_frags]);
- __skb_frag_set_page(&shinfo->frags[shinfo->nr_frags], NULL);
cons_rx_pg->page = page;
dev_kfree_skb(skb);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 8bcde0a6e011..e2a4e1088b7f 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1508,6 +1508,8 @@ struct bnx2x {
bool cnic_loaded;
struct cnic_eth_dev *(*cnic_probe)(struct net_device *);
+ bool nic_stopped;
+
/* Flag that indicates that we can start looking for FCoE L2 queue
* completions in the default status block.
*/
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 6ea5521074d3..e9c1e1bb5580 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -2715,6 +2715,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
bnx2x_add_all_napi(bp);
DP(NETIF_MSG_IFUP, "napi added\n");
bnx2x_napi_enable(bp);
+ bp->nic_stopped = false;
if (IS_PF(bp)) {
/* set pf load just before approaching the MCP */
@@ -2960,6 +2961,7 @@ load_error2:
load_error1:
bnx2x_napi_disable(bp);
bnx2x_del_all_napi(bp);
+ bp->nic_stopped = true;
/* clear pf_load status, as it was already set */
if (IS_PF(bp))
@@ -3095,14 +3097,17 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
if (!CHIP_IS_E1x(bp))
bnx2x_pf_disable(bp);
- /* Disable HW interrupts, NAPI */
- bnx2x_netif_stop(bp, 1);
- /* Delete all NAPI objects */
- bnx2x_del_all_napi(bp);
- if (CNIC_LOADED(bp))
- bnx2x_del_all_napi_cnic(bp);
- /* Release IRQs */
- bnx2x_free_irq(bp);
+ if (!bp->nic_stopped) {
+ /* Disable HW interrupts, NAPI */
+ bnx2x_netif_stop(bp, 1);
+ /* Delete all NAPI objects */
+ bnx2x_del_all_napi(bp);
+ if (CNIC_LOADED(bp))
+ bnx2x_del_all_napi_cnic(bp);
+ /* Release IRQs */
+ bnx2x_free_irq(bp);
+ bp->nic_stopped = true;
+ }
/* Report UNLOAD_DONE to MCP */
bnx2x_send_unload_done(bp, false);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 1e7a6f1d4223..0d8e61c63c7c 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -9474,15 +9474,18 @@ unload_error:
}
}
- /* Disable HW interrupts, NAPI */
- bnx2x_netif_stop(bp, 1);
- /* Delete all NAPI objects */
- bnx2x_del_all_napi(bp);
- if (CNIC_LOADED(bp))
- bnx2x_del_all_napi_cnic(bp);
+ if (!bp->nic_stopped) {
+ /* Disable HW interrupts, NAPI */
+ bnx2x_netif_stop(bp, 1);
+ /* Delete all NAPI objects */
+ bnx2x_del_all_napi(bp);
+ if (CNIC_LOADED(bp))
+ bnx2x_del_all_napi_cnic(bp);
- /* Release IRQs */
- bnx2x_free_irq(bp);
+ /* Release IRQs */
+ bnx2x_free_irq(bp);
+ bp->nic_stopped = true;
+ }
/* Reset the chip, unless PCI function is offline. If we reach this
* point following a PCI error handling, it means device is really
@@ -14238,13 +14241,16 @@ static pci_ers_result_t bnx2x_io_slot_reset(struct pci_dev *pdev)
}
bnx2x_drain_tx_queues(bp);
bnx2x_send_unload_req(bp, UNLOAD_RECOVERY);
- bnx2x_netif_stop(bp, 1);
- bnx2x_del_all_napi(bp);
+ if (!bp->nic_stopped) {
+ bnx2x_netif_stop(bp, 1);
+ bnx2x_del_all_napi(bp);
- if (CNIC_LOADED(bp))
- bnx2x_del_all_napi_cnic(bp);
+ if (CNIC_LOADED(bp))
+ bnx2x_del_all_napi_cnic(bp);
- bnx2x_free_irq(bp);
+ bnx2x_free_irq(bp);
+ bp->nic_stopped = true;
+ }
/* Report UNLOAD_DONE to MCP */
bnx2x_send_unload_done(bp, true);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index 0657a0f5170f..8946a931e87e 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -529,13 +529,16 @@ void bnx2x_vfpf_close_vf(struct bnx2x *bp)
bnx2x_vfpf_finalize(bp, &req->first_tlv);
free_irq:
- /* Disable HW interrupts, NAPI */
- bnx2x_netif_stop(bp, 0);
- /* Delete all NAPI objects */
- bnx2x_del_all_napi(bp);
-
- /* Release IRQs */
- bnx2x_free_irq(bp);
+ if (!bp->nic_stopped) {
+ /* Disable HW interrupts, NAPI */
+ bnx2x_netif_stop(bp, 0);
+ /* Delete all NAPI objects */
+ bnx2x_del_all_napi(bp);
+
+ /* Release IRQs */
+ bnx2x_free_irq(bp);
+ bp->nic_stopped = true;
+ }
}
static void bnx2x_leading_vfq_init(struct bnx2x *bp, struct bnx2x_virtf *vf,
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index b499bc9c4e06..1eb490c48c52 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -633,12 +633,13 @@ tx_kick_pending:
return NETDEV_TX_OK;
}
-static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
+static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
{
struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, txr->txq_index);
u16 cons = txr->tx_cons;
struct pci_dev *pdev = bp->pdev;
+ int nr_pkts = bnapi->tx_pkts;
int i;
unsigned int tx_bytes = 0;
@@ -688,6 +689,7 @@ next_tx_int:
dev_kfree_skb_any(skb);
}
+ bnapi->tx_pkts = 0;
WRITE_ONCE(txr->tx_cons, cons);
__netif_txq_completed_wake(txq, nr_pkts, tx_bytes,
@@ -697,17 +699,24 @@ next_tx_int:
static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping,
struct bnxt_rx_ring_info *rxr,
+ unsigned int *offset,
gfp_t gfp)
{
struct device *dev = &bp->pdev->dev;
struct page *page;
- page = page_pool_dev_alloc_pages(rxr->page_pool);
+ if (PAGE_SIZE > BNXT_RX_PAGE_SIZE) {
+ page = page_pool_dev_alloc_frag(rxr->page_pool, offset,
+ BNXT_RX_PAGE_SIZE);
+ } else {
+ page = page_pool_dev_alloc_pages(rxr->page_pool);
+ *offset = 0;
+ }
if (!page)
return NULL;
- *mapping = dma_map_page_attrs(dev, page, 0, PAGE_SIZE, bp->rx_dir,
- DMA_ATTR_WEAK_ORDERING);
+ *mapping = dma_map_page_attrs(dev, page, *offset, BNXT_RX_PAGE_SIZE,
+ bp->rx_dir, DMA_ATTR_WEAK_ORDERING);
if (dma_mapping_error(dev, *mapping)) {
page_pool_recycle_direct(rxr->page_pool, page);
return NULL;
@@ -747,15 +756,16 @@ int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
dma_addr_t mapping;
if (BNXT_RX_PAGE_MODE(bp)) {
+ unsigned int offset;
struct page *page =
- __bnxt_alloc_rx_page(bp, &mapping, rxr, gfp);
+ __bnxt_alloc_rx_page(bp, &mapping, rxr, &offset, gfp);
if (!page)
return -ENOMEM;
mapping += bp->rx_dma_offset;
rx_buf->data = page;
- rx_buf->data_ptr = page_address(page) + bp->rx_offset;
+ rx_buf->data_ptr = page_address(page) + offset + bp->rx_offset;
} else {
u8 *data = __bnxt_alloc_rx_frag(bp, &mapping, gfp);
@@ -815,7 +825,7 @@ static inline int bnxt_alloc_rx_page(struct bnxt *bp,
unsigned int offset = 0;
if (BNXT_RX_PAGE_MODE(bp)) {
- page = __bnxt_alloc_rx_page(bp, &mapping, rxr, gfp);
+ page = __bnxt_alloc_rx_page(bp, &mapping, rxr, &offset, gfp);
if (!page)
return -ENOMEM;
@@ -962,15 +972,15 @@ static struct sk_buff *bnxt_rx_multi_page_skb(struct bnxt *bp,
return NULL;
}
dma_addr -= bp->rx_dma_offset;
- dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, PAGE_SIZE, bp->rx_dir,
- DMA_ATTR_WEAK_ORDERING);
- skb = build_skb(page_address(page), PAGE_SIZE);
+ dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE,
+ bp->rx_dir, DMA_ATTR_WEAK_ORDERING);
+ skb = build_skb(data_ptr - bp->rx_offset, BNXT_RX_PAGE_SIZE);
if (!skb) {
page_pool_recycle_direct(rxr->page_pool, page);
return NULL;
}
skb_mark_for_recycle(skb);
- skb_reserve(skb, bp->rx_dma_offset);
+ skb_reserve(skb, bp->rx_offset);
__skb_put(skb, len);
return skb;
@@ -996,8 +1006,8 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp,
return NULL;
}
dma_addr -= bp->rx_dma_offset;
- dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, PAGE_SIZE, bp->rx_dir,
- DMA_ATTR_WEAK_ORDERING);
+ dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE,
+ bp->rx_dir, DMA_ATTR_WEAK_ORDERING);
if (unlikely(!payload))
payload = eth_get_headlen(bp->dev, data_ptr, len);
@@ -1010,7 +1020,7 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp,
skb_mark_for_recycle(skb);
off = (void *)data_ptr - page_address(page);
- skb_add_rx_frag(skb, 0, page, off, len, PAGE_SIZE);
+ skb_add_rx_frag(skb, 0, page, off, len, BNXT_RX_PAGE_SIZE);
memcpy(skb->data - NET_IP_ALIGN, data_ptr - NET_IP_ALIGN,
payload + NET_IP_ALIGN);
@@ -1085,9 +1095,8 @@ static u32 __bnxt_rx_agg_pages(struct bnxt *bp,
RX_AGG_CMP_LEN) >> RX_AGG_CMP_LEN_SHIFT;
cons_rx_buf = &rxr->rx_agg_ring[cons];
- skb_frag_off_set(frag, cons_rx_buf->offset);
- skb_frag_size_set(frag, frag_len);
- __skb_frag_set_page(frag, cons_rx_buf->page);
+ skb_frag_fill_page_desc(frag, cons_rx_buf->page,
+ cons_rx_buf->offset, frag_len);
shinfo->nr_frags = i + 1;
__clear_bit(cons, rxr->rx_agg_bmap);
@@ -1103,10 +1112,7 @@ static u32 __bnxt_rx_agg_pages(struct bnxt *bp,
xdp_buff_set_frag_pfmemalloc(xdp);
if (bnxt_alloc_rx_page(bp, rxr, prod, GFP_ATOMIC) != 0) {
- unsigned int nr_frags;
-
- nr_frags = --shinfo->nr_frags;
- __skb_frag_set_page(&shinfo->frags[nr_frags], NULL);
+ --shinfo->nr_frags;
cons_rx_buf->page = page;
/* Update prod since possibly some pages have been
@@ -1145,7 +1151,7 @@ static struct sk_buff *bnxt_rx_agg_pages_skb(struct bnxt *bp,
skb->data_len += total_frag_len;
skb->len += total_frag_len;
- skb->truesize += PAGE_SIZE * agg_bufs;
+ skb->truesize += BNXT_RX_PAGE_SIZE * agg_bufs;
return skb;
}
@@ -2573,12 +2579,11 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
return rx_pkts;
}
-static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi)
+static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi,
+ int budget)
{
- if (bnapi->tx_pkts) {
- bnapi->tx_int(bp, bnapi, bnapi->tx_pkts);
- bnapi->tx_pkts = 0;
- }
+ if (bnapi->tx_pkts)
+ bnapi->tx_int(bp, bnapi, budget);
if ((bnapi->events & BNXT_RX_EVENT) && !(bnapi->in_reset)) {
struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
@@ -2607,7 +2612,7 @@ static int bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
*/
bnxt_db_cq(bp, &cpr->cp_db, cpr->cp_raw_cons);
- __bnxt_poll_work_done(bp, bnapi);
+ __bnxt_poll_work_done(bp, bnapi, budget);
return rx_pkts;
}
@@ -2738,7 +2743,7 @@ static int __bnxt_poll_cqs(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
}
static void __bnxt_poll_cqs_done(struct bnxt *bp, struct bnxt_napi *bnapi,
- u64 dbr_type)
+ u64 dbr_type, int budget)
{
struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
int i;
@@ -2754,7 +2759,7 @@ static void __bnxt_poll_cqs_done(struct bnxt *bp, struct bnxt_napi *bnapi,
cpr2->had_work_done = 0;
}
}
- __bnxt_poll_work_done(bp, bnapi);
+ __bnxt_poll_work_done(bp, bnapi, budget);
}
static int bnxt_poll_p5(struct napi_struct *napi, int budget)
@@ -2784,7 +2789,8 @@ static int bnxt_poll_p5(struct napi_struct *napi, int budget)
if (cpr->has_more_work)
break;
- __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ_ARMALL);
+ __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ_ARMALL,
+ budget);
cpr->cp_raw_cons = raw_cons;
if (napi_complete_done(napi, work_done))
BNXT_DB_NQ_ARM_P5(&cpr->cp_db,
@@ -2814,7 +2820,7 @@ static int bnxt_poll_p5(struct napi_struct *napi, int budget)
}
raw_cons = NEXT_RAW_CMP(raw_cons);
}
- __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ);
+ __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ, budget);
if (raw_cons != cpr->cp_raw_cons) {
cpr->cp_raw_cons = raw_cons;
BNXT_DB_NQ_P5(&cpr->cp_db, raw_cons);
@@ -2947,8 +2953,8 @@ skip_rx_tpa_free:
rx_buf->data = NULL;
if (BNXT_RX_PAGE_MODE(bp)) {
mapping -= bp->rx_dma_offset;
- dma_unmap_page_attrs(&pdev->dev, mapping, PAGE_SIZE,
- bp->rx_dir,
+ dma_unmap_page_attrs(&pdev->dev, mapping,
+ BNXT_RX_PAGE_SIZE, bp->rx_dir,
DMA_ATTR_WEAK_ORDERING);
page_pool_recycle_direct(rxr->page_pool, data);
} else {
@@ -3217,6 +3223,8 @@ static int bnxt_alloc_rx_page_pool(struct bnxt *bp,
pp.napi = &rxr->bnapi->napi;
pp.dev = &bp->pdev->dev;
pp.dma_dir = DMA_BIDIRECTIONAL;
+ if (PAGE_SIZE > BNXT_RX_PAGE_SIZE)
+ pp.flags |= PP_FLAG_PAGE_FRAG;
rxr->page_pool = page_pool_create(&pp);
if (IS_ERR(rxr->page_pool)) {
@@ -3993,26 +4001,29 @@ void bnxt_set_ring_params(struct bnxt *bp)
*/
int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode)
{
+ struct net_device *dev = bp->dev;
+
if (page_mode) {
bp->flags &= ~BNXT_FLAG_AGG_RINGS;
bp->flags |= BNXT_FLAG_RX_PAGE_MODE;
- if (bp->dev->mtu > BNXT_MAX_PAGE_MODE_MTU) {
+ if (bp->xdp_prog->aux->xdp_has_frags)
+ dev->max_mtu = min_t(u16, bp->max_mtu, BNXT_MAX_MTU);
+ else
+ dev->max_mtu =
+ min_t(u16, bp->max_mtu, BNXT_MAX_PAGE_MODE_MTU);
+ if (dev->mtu > BNXT_MAX_PAGE_MODE_MTU) {
bp->flags |= BNXT_FLAG_JUMBO;
bp->rx_skb_func = bnxt_rx_multi_page_skb;
- bp->dev->max_mtu =
- min_t(u16, bp->max_mtu, BNXT_MAX_MTU);
} else {
bp->flags |= BNXT_FLAG_NO_AGG_RINGS;
bp->rx_skb_func = bnxt_rx_page_skb;
- bp->dev->max_mtu =
- min_t(u16, bp->max_mtu, BNXT_MAX_PAGE_MODE_MTU);
}
bp->rx_dir = DMA_BIDIRECTIONAL;
/* Disable LRO or GRO_HW */
- netdev_update_features(bp->dev);
+ netdev_update_features(dev);
} else {
- bp->dev->max_mtu = bp->max_mtu;
+ dev->max_mtu = bp->max_mtu;
bp->flags &= ~BNXT_FLAG_RX_PAGE_MODE;
bp->rx_dir = DMA_FROM_DEVICE;
bp->rx_skb_func = bnxt_rx_skb;
@@ -9433,6 +9444,8 @@ static void bnxt_enable_napi(struct bnxt *bp)
cpr->sw_stats.rx.rx_resets++;
bnapi->in_reset = false;
+ bnapi->tx_pkts = 0;
+
if (bnapi->rx_ring) {
INIT_WORK(&cpr->dim.work, bnxt_dim_work);
cpr->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 080e73496066..bb95c3dc5270 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -1005,7 +1005,7 @@ struct bnxt_napi {
struct bnxt_tx_ring_info *tx_ring;
void (*tx_int)(struct bnxt *, struct bnxt_napi *,
- int);
+ int budget);
int tx_pkts;
u8 events;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
index 2f1a1f2d2157..1467b94a6427 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
@@ -468,6 +468,7 @@ static void bnxt_vf_rep_netdev_init(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,
struct net_device *pf_dev = bp->dev;
u16 max_mtu;
+ SET_NETDEV_DEV(dev, &bp->pdev->dev);
dev->netdev_ops = &bnxt_vf_rep_netdev_ops;
dev->ethtool_ops = &bnxt_vf_rep_ethtool_ops;
/* Just inherit all the featues of the parent PF as the VF-R
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
index 4efa5fe6972b..fb43232310b2 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
@@ -125,16 +125,20 @@ static void __bnxt_xmit_xdp_redirect(struct bnxt *bp,
dma_unmap_len_set(tx_buf, len, 0);
}
-void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
+void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
{
struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
bool rx_doorbell_needed = false;
+ int nr_pkts = bnapi->tx_pkts;
struct bnxt_sw_tx_bd *tx_buf;
u16 tx_cons = txr->tx_cons;
u16 last_tx_cons = tx_cons;
int i, j, frags;
+ if (!budget)
+ return;
+
for (i = 0; i < nr_pkts; i++) {
tx_buf = &txr->tx_buf_ring[tx_cons];
@@ -161,6 +165,8 @@ void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
}
tx_cons = NEXT_TX(tx_cons);
}
+
+ bnapi->tx_pkts = 0;
WRITE_ONCE(txr->tx_cons, tx_cons);
if (rx_doorbell_needed) {
tx_buf = &txr->tx_buf_ring[last_tx_cons];
@@ -180,8 +186,8 @@ void bnxt_xdp_buff_init(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
u16 cons, u8 *data_ptr, unsigned int len,
struct xdp_buff *xdp)
{
+ u32 buflen = BNXT_RX_PAGE_SIZE;
struct bnxt_sw_rx_bd *rx_buf;
- u32 buflen = PAGE_SIZE;
struct pci_dev *pdev;
dma_addr_t mapping;
u32 offset;
@@ -297,7 +303,7 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
rx_buf = &rxr->rx_buf_ring[cons];
mapping = rx_buf->mapping - bp->rx_dma_offset;
dma_unmap_page_attrs(&pdev->dev, mapping,
- PAGE_SIZE, bp->rx_dir,
+ BNXT_RX_PAGE_SIZE, bp->rx_dir,
DMA_ATTR_WEAK_ORDERING);
/* if we are unable to allocate a new buffer, abort and reuse */
@@ -480,7 +486,7 @@ bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb, u8 num_frags,
}
xdp_update_skb_shared_info(skb, num_frags,
sinfo->xdp_frags_size,
- PAGE_SIZE * sinfo->nr_frags,
+ BNXT_RX_PAGE_SIZE * sinfo->nr_frags,
xdp_buff_is_frag_pfmemalloc(xdp));
return skb;
}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
index ea430d6961df..5e412c5655ba 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
@@ -16,7 +16,7 @@ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp,
struct bnxt_tx_ring_info *txr,
dma_addr_t mapping, u32 len,
struct xdp_buff *xdp);
-void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts);
+void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget);
bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
struct xdp_buff xdp, struct page *page, u8 **data_ptr,
unsigned int *len, u8 *event);
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
index 3a4b6cb7b7b9..7a41cad5788f 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
@@ -42,6 +42,12 @@ void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
struct bcmgenet_priv *priv = netdev_priv(dev);
struct device *kdev = &priv->pdev->dev;
+ if (dev->phydev) {
+ phy_ethtool_get_wol(dev->phydev, wol);
+ if (wol->supported)
+ return;
+ }
+
if (!device_can_wakeup(kdev)) {
wol->supported = 0;
wol->wolopts = 0;
@@ -63,6 +69,14 @@ int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
struct device *kdev = &priv->pdev->dev;
+ int ret;
+
+ /* Try Wake-on-LAN from the PHY first */
+ if (dev->phydev) {
+ ret = phy_ethtool_set_wol(dev->phydev, wol);
+ if (ret != -EOPNOTSUPP)
+ return ret;
+ }
if (!device_can_wakeup(kdev))
return -ENOTSUPP;
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
index c15ed0acdb77..cc3afb605b1e 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -617,7 +617,7 @@ static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
};
phydev = fixed_phy_register(PHY_POLL, &fphy_status, NULL);
- if (!phydev || IS_ERR(phydev)) {
+ if (IS_ERR(phydev)) {
dev_err(kdev, "failed to register fixed PHY device\n");
return -ENODEV;
}
@@ -673,5 +673,7 @@ void bcmgenet_mii_exit(struct net_device *dev)
if (of_phy_is_fixed_link(dn))
of_phy_deregister_fixed_link(dn);
of_node_put(priv->phy_dn);
+ clk_prepare_enable(priv->clk);
platform_device_unregister(priv->mii_pdev);
+ clk_disable_unprepare(priv->clk);
}
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 58747292521d..cb2810f175cc 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -57,6 +57,7 @@
#include <linux/crc32poly.h>
#include <net/checksum.h>
+#include <net/gso.h>
#include <net/ip.h>
#include <linux/io.h>
@@ -224,6 +225,7 @@ MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox
MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(FIRMWARE_TG3);
+MODULE_FIRMWARE(FIRMWARE_TG357766);
MODULE_FIRMWARE(FIRMWARE_TG3TSO);
MODULE_FIRMWARE(FIRMWARE_TG3TSO5);
@@ -6879,7 +6881,10 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
ri->data = NULL;
- skb = build_skb(data, frag_size);
+ if (frag_size)
+ skb = build_skb(data, frag_size);
+ else
+ skb = slab_build_skb(data);
if (!skb) {
tg3_frag_free(frag_size != 0, data);
goto drop_it_no_recycle;
diff --git a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c
index 04ad0f2b9677..7246e13dd559 100644
--- a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c
+++ b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c
@@ -512,11 +512,6 @@ bnad_debugfs_init(struct bnad *bnad)
if (!bnad->port_debugfs_root) {
bnad->port_debugfs_root =
debugfs_create_dir(name, bna_debugfs_root);
- if (!bnad->port_debugfs_root) {
- netdev_warn(bnad->netdev,
- "debugfs root dir creation failed\n");
- return;
- }
atomic_inc(&bna_debugfs_port_count);
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index cfbdd0022764..78c972bb1d96 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -82,6 +82,7 @@
#define GEM_NCFGR 0x0004 /* Network Config */
#define GEM_USRIO 0x000c /* User IO */
#define GEM_DMACFG 0x0010 /* DMA Configuration */
+#define GEM_PBUFRXCUT 0x0044 /* RX Partial Store and Forward */
#define GEM_JML 0x0048 /* Jumbo Max Length */
#define GEM_HS_MAC_CONFIG 0x0050 /* GEM high speed config */
#define GEM_HRB 0x0080 /* Hash Bottom */
@@ -347,6 +348,10 @@
#define GEM_ADDR64_SIZE 1
+/* Bitfields in PBUFRXCUT */
+#define GEM_ENCUTTHRU_OFFSET 31 /* Enable RX partial store and forward */
+#define GEM_ENCUTTHRU_SIZE 1
+
/* Bitfields in NSR */
#define MACB_NSR_LINK_OFFSET 0 /* pcs_link_state */
#define MACB_NSR_LINK_SIZE 1
@@ -513,6 +518,8 @@
#define GEM_TX_PKT_BUFF_OFFSET 21
#define GEM_TX_PKT_BUFF_SIZE 1
+#define GEM_RX_PBUF_ADDR_OFFSET 22
+#define GEM_RX_PBUF_ADDR_SIZE 4
/* Bitfields in DCFG5. */
#define GEM_TSU_OFFSET 8
@@ -521,6 +528,8 @@
/* Bitfields in DCFG6. */
#define GEM_PBUF_LSO_OFFSET 27
#define GEM_PBUF_LSO_SIZE 1
+#define GEM_PBUF_CUTTHRU_OFFSET 25
+#define GEM_PBUF_CUTTHRU_SIZE 1
#define GEM_DAW64_OFFSET 23
#define GEM_DAW64_SIZE 1
@@ -1181,6 +1190,7 @@ struct macb_config {
struct clk **hclk, struct clk **tx_clk,
struct clk **rx_clk, struct clk **tsu_clk);
int (*init)(struct platform_device *pdev);
+ unsigned int max_tx_length;
int jumbo_max_len;
const struct macb_usrio_config *usrio;
};
@@ -1289,6 +1299,9 @@ struct macb {
u32 wol;
+ /* holds value of rx watermark value for pbuf_rxcutthru register */
+ u32 rx_watermark;
+
struct macb_ptp_info *ptp_info; /* macb-ptp interface */
struct phy *sgmii_phy; /* for ZynqMP SGMII mode */
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 29a1199dad14..82929ee76739 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -563,7 +563,7 @@ static void macb_set_tx_clk(struct macb *bp, int speed)
netdev_err(bp->dev, "adjusting tx_clk failed.\n");
}
-static void macb_usx_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
+static void macb_usx_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface, int speed,
int duplex)
{
@@ -596,7 +596,7 @@ static void macb_usx_pcs_get_state(struct phylink_pcs *pcs,
}
static int macb_usx_pcs_config(struct phylink_pcs *pcs,
- unsigned int mode,
+ unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -621,7 +621,7 @@ static void macb_pcs_an_restart(struct phylink_pcs *pcs)
}
static int macb_pcs_config(struct phylink_pcs *pcs,
- unsigned int mode,
+ unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -862,7 +862,9 @@ static int macb_mii_probe(struct net_device *dev)
struct macb *bp = netdev_priv(dev);
bp->phylink_sgmii_pcs.ops = &macb_phylink_pcs_ops;
+ bp->phylink_sgmii_pcs.neg_mode = true;
bp->phylink_usx_pcs.ops = &macb_phylink_usx_pcs_ops;
+ bp->phylink_usx_pcs.neg_mode = true;
bp->phylink_config.dev = &dev->dev;
bp->phylink_config.type = PHYLINK_NETDEV;
@@ -2635,6 +2637,9 @@ static void macb_reset_hw(struct macb *bp)
macb_writel(bp, TSR, -1);
macb_writel(bp, RSR, -1);
+ /* Disable RX partial store and forward and reset watermark value */
+ gem_writel(bp, PBUFRXCUT, 0);
+
/* Disable all interrupts */
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
queue_writel(queue, IDR, -1);
@@ -2792,6 +2797,10 @@ static void macb_init_hw(struct macb *bp)
bp->rx_frm_len_mask = MACB_RX_JFRMLEN_MASK;
macb_configure_dma(bp);
+
+ /* Enable RX partial store and forward and set watermark */
+ if (bp->rx_watermark)
+ gem_writel(bp, PBUFRXCUT, (bp->rx_watermark | GEM_BIT(ENCUTTHRU)));
}
/* The hash address register is 64 bits long and takes up two
@@ -4117,14 +4126,12 @@ static int macb_init(struct platform_device *pdev)
/* setup appropriated routines according to adapter type */
if (macb_is_gem(bp)) {
- bp->max_tx_length = GEM_MAX_TX_LEN;
bp->macbgem_ops.mog_alloc_rx_buffers = gem_alloc_rx_buffers;
bp->macbgem_ops.mog_free_rx_buffers = gem_free_rx_buffers;
bp->macbgem_ops.mog_init_rings = gem_init_rings;
bp->macbgem_ops.mog_rx = gem_rx;
dev->ethtool_ops = &gem_ethtool_ops;
} else {
- bp->max_tx_length = MACB_MAX_TX_LEN;
bp->macbgem_ops.mog_alloc_rx_buffers = macb_alloc_rx_buffers;
bp->macbgem_ops.mog_free_rx_buffers = macb_free_rx_buffers;
bp->macbgem_ops.mog_init_rings = macb_init_rings;
@@ -4861,7 +4868,8 @@ static const struct macb_config mpfs_config = {
.clk_init = macb_clk_init,
.init = init_reset_optional,
.usrio = &macb_default_usrio,
- .jumbo_max_len = 10240,
+ .max_tx_length = 4040, /* Cadence Erratum 1686 */
+ .jumbo_max_len = 4040,
};
static const struct macb_config sama7g5_gem_config = {
@@ -4947,6 +4955,7 @@ static int macb_probe(struct platform_device *pdev)
phy_interface_t interface;
struct net_device *dev;
struct resource *regs;
+ u32 wtrmrk_rst_val;
void __iomem *mem;
struct macb *bp;
int err, val;
@@ -5012,6 +5021,13 @@ static int macb_probe(struct platform_device *pdev)
if (macb_config)
bp->jumbo_max_len = macb_config->jumbo_max_len;
+ if (!hw_is_gem(bp->regs, bp->native_io))
+ bp->max_tx_length = MACB_MAX_TX_LEN;
+ else if (macb_config->max_tx_length)
+ bp->max_tx_length = macb_config->max_tx_length;
+ else
+ bp->max_tx_length = GEM_MAX_TX_LEN;
+
bp->wol = 0;
if (of_property_read_bool(np, "magic-packet"))
bp->wol |= MACB_WOL_HAS_MAGIC_PACKET;
@@ -5019,6 +5035,25 @@ static int macb_probe(struct platform_device *pdev)
bp->usrio = macb_config->usrio;
+ /* By default we set to partial store and forward mode for zynqmp.
+ * Disable if not set in devicetree.
+ */
+ if (GEM_BFEXT(PBUF_CUTTHRU, gem_readl(bp, DCFG6))) {
+ err = of_property_read_u32(bp->pdev->dev.of_node,
+ "cdns,rx-watermark",
+ &bp->rx_watermark);
+
+ if (!err) {
+ /* Disable partial store and forward in case of error or
+ * invalid watermark value
+ */
+ wtrmrk_rst_val = (1 << (GEM_BFEXT(RX_PBUF_ADDR, gem_readl(bp, DCFG2)))) - 1;
+ if (bp->rx_watermark > wtrmrk_rst_val || !bp->rx_watermark) {
+ dev_info(&bp->pdev->dev, "Invalid watermark value\n");
+ bp->rx_watermark = 0;
+ }
+ }
+ }
spin_lock_init(&bp->lock);
/* setup capabilities */
@@ -5159,6 +5194,9 @@ static int __maybe_unused macb_suspend(struct device *dev)
unsigned int q;
int err;
+ if (!device_may_wakeup(&bp->dev->dev))
+ phy_exit(bp->sgmii_phy);
+
if (!netif_running(netdev))
return 0;
@@ -5219,7 +5257,6 @@ static int __maybe_unused macb_suspend(struct device *dev)
if (!(bp->wol & MACB_WOL_ENABLED)) {
rtnl_lock();
phylink_stop(bp->phylink);
- phy_exit(bp->sgmii_phy);
rtnl_unlock();
spin_lock_irqsave(&bp->lock, flags);
macb_reset_hw(bp);
@@ -5249,6 +5286,9 @@ static int __maybe_unused macb_resume(struct device *dev)
unsigned int q;
int err;
+ if (!device_may_wakeup(&bp->dev->dev))
+ phy_init(bp->sgmii_phy);
+
if (!netif_running(netdev))
return 0;
@@ -5309,8 +5349,6 @@ static int __maybe_unused macb_resume(struct device *dev)
macb_set_rx_mode(netdev);
macb_restore_features(bp);
rtnl_lock();
- if (!device_may_wakeup(&bp->dev->dev))
- phy_init(bp->sgmii_phy);
phylink_start(bp->phylink);
rtnl_unlock();
diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig
index 1c76c95b0b27..ca742cc146d7 100644
--- a/drivers/net/ethernet/cavium/Kconfig
+++ b/drivers/net/ethernet/cavium/Kconfig
@@ -62,6 +62,9 @@ config CAVIUM_PTP
Precision Time Protocol or other purposes. Timestamps can be used in
BGX, TNS, GTI, and NIC blocks.
+config LIQUIDIO_CORE
+ tristate
+
config LIQUIDIO
tristate "Cavium LiquidIO support"
depends on 64BIT && PCI
@@ -69,6 +72,7 @@ config LIQUIDIO
depends on PTP_1588_CLOCK_OPTIONAL
select FW_LOADER
select LIBCRC32C
+ select LIQUIDIO_CORE
select NET_DEVLINK
help
This driver supports Cavium LiquidIO Intelligent Server Adapters
@@ -92,6 +96,7 @@ config LIQUIDIO_VF
tristate "Cavium LiquidIO VF support"
depends on 64BIT && PCI_MSI
depends on PTP_1588_CLOCK_OPTIONAL
+ select LIQUIDIO_CORE
help
This driver supports Cavium LiquidIO Intelligent Server Adapter
based on CN23XX chips.
diff --git a/drivers/net/ethernet/cavium/liquidio/Makefile b/drivers/net/ethernet/cavium/liquidio/Makefile
index bc9937502043..4ee80af88e79 100644
--- a/drivers/net/ethernet/cavium/liquidio/Makefile
+++ b/drivers/net/ethernet/cavium/liquidio/Makefile
@@ -3,7 +3,9 @@
# Cavium Liquidio ethernet device driver
#
-common-objs := lio_ethtool.o \
+obj-$(CONFIG_LIQUIDIO_CORE) += liquidio-core.o
+liquidio-core-y := \
+ lio_ethtool.o \
lio_core.o \
request_manager.o \
response_manager.o \
@@ -18,7 +20,7 @@ common-objs := lio_ethtool.o \
octeon_nic.o
obj-$(CONFIG_LIQUIDIO) += liquidio.o
-liquidio-y := lio_main.o octeon_console.o lio_vf_rep.o $(common-objs)
+liquidio-y := lio_main.o octeon_console.o lio_vf_rep.o
obj-$(CONFIG_LIQUIDIO_VF) += liquidio_vf.o
-liquidio_vf-y := lio_vf_main.o $(common-objs)
+liquidio_vf-y := lio_vf_main.o
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
index 9ed3d1ab2ca5..068ed52b66c9 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
@@ -719,12 +719,10 @@ static int cn23xx_setup_pf_mbox(struct octeon_device *oct)
for (i = 0; i < oct->sriov_info.max_vfs; i++) {
q_no = i * oct->sriov_info.rings_per_vf;
- mbox = vmalloc(sizeof(*mbox));
+ mbox = vzalloc(sizeof(*mbox));
if (!mbox)
goto free_mbox;
- memset(mbox, 0, sizeof(struct octeon_mbox));
-
spin_lock_init(&mbox->lock);
mbox->oct_dev = oct;
@@ -1377,6 +1375,7 @@ int setup_cn23xx_octeon_pf_device(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(setup_cn23xx_octeon_pf_device);
int validate_cn23xx_pf_config_info(struct octeon_device *oct,
struct octeon_config *conf23xx)
@@ -1435,6 +1434,7 @@ int cn23xx_fw_loaded(struct octeon_device *oct)
val = octeon_read_csr64(oct, CN23XX_SLI_SCRATCH2);
return (val >> SCR2_BIT_FW_LOADED) & 1ULL;
}
+EXPORT_SYMBOL_GPL(cn23xx_fw_loaded);
void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx,
u8 *mac)
@@ -1456,6 +1456,7 @@ void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx,
octeon_mbox_write(oct, &mbox_cmd);
}
}
+EXPORT_SYMBOL_GPL(cn23xx_tell_vf_its_macaddr_changed);
static void
cn23xx_get_vf_stats_callback(struct octeon_device *oct,
@@ -1510,3 +1511,4 @@ int cn23xx_get_vf_stats(struct octeon_device *oct, int vfidx,
return 0;
}
+EXPORT_SYMBOL_GPL(cn23xx_get_vf_stats);
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
index fda49404968c..dd5d80fee24f 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
@@ -279,12 +279,10 @@ static int cn23xx_setup_vf_mbox(struct octeon_device *oct)
{
struct octeon_mbox *mbox = NULL;
- mbox = vmalloc(sizeof(*mbox));
+ mbox = vzalloc(sizeof(*mbox));
if (!mbox)
return 1;
- memset(mbox, 0, sizeof(struct octeon_mbox));
-
spin_lock_init(&mbox->lock);
mbox->oct_dev = oct;
@@ -386,6 +384,7 @@ void cn23xx_vf_ask_pf_to_do_flr(struct octeon_device *oct)
octeon_mbox_write(oct, &mbox_cmd);
}
+EXPORT_SYMBOL_GPL(cn23xx_vf_ask_pf_to_do_flr);
static void octeon_pfvf_hs_callback(struct octeon_device *oct,
struct octeon_mbox_cmd *cmd,
@@ -468,6 +467,7 @@ int cn23xx_octeon_pfvf_handshake(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(cn23xx_octeon_pfvf_handshake);
static void cn23xx_handle_vf_mbox_intr(struct octeon_ioq_vector *ioq_vector)
{
@@ -680,3 +680,4 @@ int cn23xx_setup_octeon_vf_device(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(cn23xx_setup_octeon_vf_device);
diff --git a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c
index 39643be8c30a..93fccfec288d 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c
@@ -697,6 +697,7 @@ int lio_setup_cn66xx_octeon_device(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(lio_setup_cn66xx_octeon_device);
int lio_validate_cn6xxx_config_info(struct octeon_device *oct,
struct octeon_config *conf6xxx)
diff --git a/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c b/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c
index 30254e4cf70f..b5103def3761 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c
@@ -181,3 +181,4 @@ int lio_setup_cn68xx_octeon_device(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(lio_setup_cn68xx_octeon_device);
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_core.c b/drivers/net/ethernet/cavium/liquidio/lio_core.c
index 882b2be06ea0..9cc6303c82ff 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_core.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_core.c
@@ -26,6 +26,9 @@
#include "octeon_main.h"
#include "octeon_network.h"
+MODULE_AUTHOR("Cavium Networks, <support@cavium.com>");
+MODULE_LICENSE("GPL");
+
/* OOM task polling interval */
#define LIO_OOM_POLL_INTERVAL_MS 250
@@ -71,6 +74,7 @@ void lio_delete_glists(struct lio *lio)
kfree(lio->glist);
lio->glist = NULL;
}
+EXPORT_SYMBOL_GPL(lio_delete_glists);
/**
* lio_setup_glists - Setup gather lists
@@ -154,6 +158,7 @@ int lio_setup_glists(struct octeon_device *oct, struct lio *lio, int num_iqs)
return 0;
}
+EXPORT_SYMBOL_GPL(lio_setup_glists);
int liquidio_set_feature(struct net_device *netdev, int cmd, u16 param1)
{
@@ -180,6 +185,7 @@ int liquidio_set_feature(struct net_device *netdev, int cmd, u16 param1)
}
return ret;
}
+EXPORT_SYMBOL_GPL(liquidio_set_feature);
void octeon_report_tx_completion_to_bql(void *txq, unsigned int pkts_compl,
unsigned int bytes_compl)
@@ -395,6 +401,7 @@ void liquidio_link_ctrl_cmd_completion(void *nctrl_ptr)
nctrl->ncmd.s.cmd);
}
}
+EXPORT_SYMBOL_GPL(liquidio_link_ctrl_cmd_completion);
void octeon_pf_changed_vf_macaddr(struct octeon_device *oct, u8 *mac)
{
@@ -478,6 +485,7 @@ int setup_rx_oom_poll_fn(struct net_device *netdev)
return 0;
}
+EXPORT_SYMBOL_GPL(setup_rx_oom_poll_fn);
void cleanup_rx_oom_poll_fn(struct net_device *netdev)
{
@@ -495,6 +503,7 @@ void cleanup_rx_oom_poll_fn(struct net_device *netdev)
}
}
}
+EXPORT_SYMBOL_GPL(cleanup_rx_oom_poll_fn);
/* Runs in interrupt context. */
static void lio_update_txq_status(struct octeon_device *oct, int iq_num)
@@ -899,6 +908,7 @@ int liquidio_setup_io_queues(struct octeon_device *octeon_dev, int ifidx,
return 0;
}
+EXPORT_SYMBOL_GPL(liquidio_setup_io_queues);
static
int liquidio_schedule_msix_droq_pkt_handler(struct octeon_droq *droq, u64 ret)
@@ -1194,6 +1204,7 @@ int octeon_setup_interrupt(struct octeon_device *oct, u32 num_ioqs)
}
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_setup_interrupt);
/**
* liquidio_change_mtu - Net device change_mtu
@@ -1256,6 +1267,7 @@ int liquidio_change_mtu(struct net_device *netdev, int new_mtu)
WRITE_ONCE(sc->caller_is_done, true);
return 0;
}
+EXPORT_SYMBOL_GPL(liquidio_change_mtu);
int lio_wait_for_clean_oq(struct octeon_device *oct)
{
@@ -1279,6 +1291,7 @@ int lio_wait_for_clean_oq(struct octeon_device *oct)
return pending_pkts;
}
+EXPORT_SYMBOL_GPL(lio_wait_for_clean_oq);
static void
octnet_nic_stats_callback(struct octeon_device *oct_dev,
@@ -1509,6 +1522,7 @@ lio_fetch_stats_exit:
return;
}
+EXPORT_SYMBOL_GPL(lio_fetch_stats);
int liquidio_set_speed(struct lio *lio, int speed)
{
@@ -1659,6 +1673,7 @@ int liquidio_get_speed(struct lio *lio)
return retval;
}
+EXPORT_SYMBOL_GPL(liquidio_get_speed);
int liquidio_set_fec(struct lio *lio, int on_off)
{
@@ -1812,3 +1827,4 @@ int liquidio_get_fec(struct lio *lio)
return retval;
}
+EXPORT_SYMBOL_GPL(liquidio_get_fec);
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
index 2c10ae3f7fc1..9d56181a301f 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
@@ -3180,3 +3180,4 @@ void liquidio_set_ethtool_ops(struct net_device *netdev)
else
netdev->ethtool_ops = &lio_ethtool_ops;
}
+EXPORT_SYMBOL_GPL(liquidio_set_ethtool_ops);
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 9bd1d2d7027d..100daadbea2a 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -191,8 +191,7 @@ static void octeon_droq_bh(struct tasklet_struct *t)
static int lio_wait_for_oq_pkts(struct octeon_device *oct)
{
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
int retry = 100, pkt_cnt = 0, pending_pkts = 0;
int i;
@@ -950,8 +949,7 @@ static void octeon_destroy_resources(struct octeon_device *oct)
{
int i, refcount;
struct msix_entry *msix_entries;
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
struct handshake *hs;
@@ -1211,8 +1209,7 @@ static int send_rx_ctrl_cmd(struct lio *lio, int start_stop)
static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx)
{
struct net_device *netdev = oct->props[ifidx].netdev;
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
struct napi_struct *napi, *n;
struct lio *lio;
@@ -1774,8 +1771,7 @@ static int liquidio_open(struct net_device *netdev)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
struct napi_struct *napi, *n;
int ret = 0;
@@ -1855,8 +1851,7 @@ static int liquidio_stop(struct net_device *netdev)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
struct napi_struct *napi, *n;
int ret = 0;
@@ -4057,8 +4052,7 @@ static int octeon_device_init(struct octeon_device *octeon_dev)
char bootcmd[] = "\n";
char *dbg_enb = NULL;
enum lio_fw_state fw_state;
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)octeon_dev->priv;
+ struct octeon_device_priv *oct_priv = octeon_dev->priv;
atomic_set(&octeon_dev->status, OCT_DEV_BEGIN_STATE);
/* Enable access to the octeon device and make its DMA capability
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index e2921aec3da0..62c2eadc33e3 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -72,8 +72,7 @@ static int liquidio_stop(struct net_device *netdev);
static int lio_wait_for_oq_pkts(struct octeon_device *oct)
{
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
int retry = MAX_IO_PENDING_PKT_COUNT;
int pkt_cnt = 0, pending_pkts;
int i;
@@ -442,8 +441,7 @@ static void octeon_pci_flr(struct octeon_device *oct)
*/
static void octeon_destroy_resources(struct octeon_device *oct)
{
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
struct msix_entry *msix_entries;
int i;
@@ -659,8 +657,7 @@ static int send_rx_ctrl_cmd(struct lio *lio, int start_stop)
static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx)
{
struct net_device *netdev = oct->props[ifidx].netdev;
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
struct napi_struct *napi, *n;
struct lio *lio;
@@ -909,8 +906,7 @@ static int liquidio_open(struct net_device *netdev)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
struct napi_struct *napi, *n;
int ret = 0;
@@ -956,8 +952,7 @@ static int liquidio_stop(struct net_device *netdev)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
struct napi_struct *napi, *n;
int ret = 0;
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.c b/drivers/net/ethernet/cavium/liquidio/octeon_device.c
index e159194d0aef..364f4f912dc2 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.c
@@ -564,6 +564,7 @@ void octeon_init_device_list(int conf_type)
for (i = 0; i < MAX_OCTEON_DEVICES; i++)
oct_set_config_info(i, conf_type);
}
+EXPORT_SYMBOL_GPL(octeon_init_device_list);
static void *__retrieve_octeon_config_info(struct octeon_device *oct,
u16 card_type)
@@ -633,6 +634,7 @@ char *lio_get_state_string(atomic_t *state_ptr)
return oct_dev_state_str[OCT_DEV_STATE_INVALID];
return oct_dev_state_str[istate];
}
+EXPORT_SYMBOL_GPL(lio_get_state_string);
static char *get_oct_app_string(u32 app_mode)
{
@@ -661,6 +663,7 @@ void octeon_free_device_mem(struct octeon_device *oct)
octeon_device[i] = NULL;
octeon_device_count--;
}
+EXPORT_SYMBOL_GPL(octeon_free_device_mem);
static struct octeon_device *octeon_allocate_device_mem(u32 pci_id,
u32 priv_size)
@@ -747,6 +750,7 @@ struct octeon_device *octeon_allocate_device(u32 pci_id,
return oct;
}
+EXPORT_SYMBOL_GPL(octeon_allocate_device);
/** Register a device's bus location at initialization time.
* @param octeon_dev - pointer to the octeon device structure.
@@ -804,6 +808,7 @@ int octeon_register_device(struct octeon_device *oct,
return refcount;
}
+EXPORT_SYMBOL_GPL(octeon_register_device);
/** Deregister a device at de-initialization time.
* @param octeon_dev - pointer to the octeon device structure.
@@ -821,6 +826,7 @@ int octeon_deregister_device(struct octeon_device *oct)
return refcount;
}
+EXPORT_SYMBOL_GPL(octeon_deregister_device);
int
octeon_allocate_ioq_vector(struct octeon_device *oct, u32 num_ioqs)
@@ -853,12 +859,14 @@ octeon_allocate_ioq_vector(struct octeon_device *oct, u32 num_ioqs)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_allocate_ioq_vector);
void
octeon_free_ioq_vector(struct octeon_device *oct)
{
vfree(oct->ioq_vector);
}
+EXPORT_SYMBOL_GPL(octeon_free_ioq_vector);
/* this function is only for setting up the first queue */
int octeon_setup_instr_queues(struct octeon_device *oct)
@@ -904,6 +912,7 @@ int octeon_setup_instr_queues(struct octeon_device *oct)
oct->num_iqs++;
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_setup_instr_queues);
int octeon_setup_output_queues(struct octeon_device *oct)
{
@@ -940,6 +949,7 @@ int octeon_setup_output_queues(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_setup_output_queues);
int octeon_set_io_queues_off(struct octeon_device *oct)
{
@@ -989,6 +999,7 @@ int octeon_set_io_queues_off(struct octeon_device *oct)
}
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_set_io_queues_off);
void octeon_set_droq_pkt_op(struct octeon_device *oct,
u32 q_no,
@@ -1027,6 +1038,7 @@ int octeon_init_dispatch_list(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_init_dispatch_list);
void octeon_delete_dispatch_list(struct octeon_device *oct)
{
@@ -1058,6 +1070,7 @@ void octeon_delete_dispatch_list(struct octeon_device *oct)
kfree(temp);
}
}
+EXPORT_SYMBOL_GPL(octeon_delete_dispatch_list);
octeon_dispatch_fn_t
octeon_get_dispatch(struct octeon_device *octeon_dev, u16 opcode,
@@ -1180,6 +1193,7 @@ octeon_register_dispatch_fn(struct octeon_device *oct,
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_register_dispatch_fn);
int octeon_core_drv_init(struct octeon_recv_info *recv_info, void *buf)
{
@@ -1262,6 +1276,7 @@ core_drv_init_err:
octeon_free_recv_info(recv_info);
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_core_drv_init);
int octeon_get_tx_qsize(struct octeon_device *oct, u32 q_no)
@@ -1272,6 +1287,7 @@ int octeon_get_tx_qsize(struct octeon_device *oct, u32 q_no)
return -1;
}
+EXPORT_SYMBOL_GPL(octeon_get_tx_qsize);
int octeon_get_rx_qsize(struct octeon_device *oct, u32 q_no)
{
@@ -1280,6 +1296,7 @@ int octeon_get_rx_qsize(struct octeon_device *oct, u32 q_no)
return oct->droq[q_no]->max_count;
return -1;
}
+EXPORT_SYMBOL_GPL(octeon_get_rx_qsize);
/* Retruns the host firmware handshake OCTEON specific configuration */
struct octeon_config *octeon_get_conf(struct octeon_device *oct)
@@ -1302,6 +1319,7 @@ struct octeon_config *octeon_get_conf(struct octeon_device *oct)
}
return default_oct_conf;
}
+EXPORT_SYMBOL_GPL(octeon_get_conf);
/* scratch register address is same in all the OCT-II and CN70XX models */
#define CNXX_SLI_SCRATCH1 0x3C0
@@ -1318,6 +1336,7 @@ struct octeon_device *lio_get_device(u32 octeon_id)
else
return octeon_device[octeon_id];
}
+EXPORT_SYMBOL_GPL(lio_get_device);
u64 lio_pci_readq(struct octeon_device *oct, u64 addr)
{
@@ -1349,6 +1368,7 @@ u64 lio_pci_readq(struct octeon_device *oct, u64 addr)
return val64;
}
+EXPORT_SYMBOL_GPL(lio_pci_readq);
void lio_pci_writeq(struct octeon_device *oct,
u64 val,
@@ -1369,6 +1389,7 @@ void lio_pci_writeq(struct octeon_device *oct,
spin_unlock_irqrestore(&oct->pci_win_lock, flags);
}
+EXPORT_SYMBOL_GPL(lio_pci_writeq);
int octeon_mem_access_ok(struct octeon_device *oct)
{
@@ -1388,6 +1409,7 @@ int octeon_mem_access_ok(struct octeon_device *oct)
return access_okay ? 0 : 1;
}
+EXPORT_SYMBOL_GPL(octeon_mem_access_ok);
int octeon_wait_for_ddr_init(struct octeon_device *oct, u32 *timeout)
{
@@ -1408,6 +1430,7 @@ int octeon_wait_for_ddr_init(struct octeon_device *oct, u32 *timeout)
return ret;
}
+EXPORT_SYMBOL_GPL(octeon_wait_for_ddr_init);
/* Get the octeon id assigned to the octeon device passed as argument.
* This function is exported to other modules.
@@ -1462,3 +1485,4 @@ void lio_enable_irq(struct octeon_droq *droq, struct octeon_instr_queue *iq)
}
}
}
+EXPORT_SYMBOL_GPL(lio_enable_irq);
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c
index d4080bddcb6b..0d6ee30affb9 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c
@@ -107,6 +107,7 @@ u32 octeon_droq_check_hw_for_pkts(struct octeon_droq *droq)
return last_count;
}
+EXPORT_SYMBOL_GPL(octeon_droq_check_hw_for_pkts);
static void octeon_droq_compute_max_packet_bufs(struct octeon_droq *droq)
{
@@ -216,6 +217,7 @@ int octeon_delete_droq(struct octeon_device *oct, u32 q_no)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_delete_droq);
int octeon_init_droq(struct octeon_device *oct,
u32 q_no,
@@ -773,6 +775,7 @@ octeon_droq_process_packets(struct octeon_device *oct,
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_droq_process_packets);
/*
* Utility function to poll for packets. check_hw_for_packets must be
@@ -921,6 +924,7 @@ int octeon_unregister_droq_ops(struct octeon_device *oct, u32 q_no)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_unregister_droq_ops);
int octeon_create_droq(struct octeon_device *oct,
u32 q_no, u32 num_descs,
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c b/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c
index 7ccab36143c1..d70132437af3 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c
@@ -164,6 +164,7 @@ octeon_pci_read_core_mem(struct octeon_device *oct,
{
__octeon_pci_rw_core_mem(oct, coreaddr, buf, len, 1);
}
+EXPORT_SYMBOL_GPL(octeon_pci_read_core_mem);
void
octeon_pci_write_core_mem(struct octeon_device *oct,
@@ -173,6 +174,7 @@ octeon_pci_write_core_mem(struct octeon_device *oct,
{
__octeon_pci_rw_core_mem(oct, coreaddr, (u8 *)buf, len, 0);
}
+EXPORT_SYMBOL_GPL(octeon_pci_write_core_mem);
u64 octeon_read_device_mem64(struct octeon_device *oct, u64 coreaddr)
{
@@ -182,6 +184,7 @@ u64 octeon_read_device_mem64(struct octeon_device *oct, u64 coreaddr)
return be64_to_cpu(ret);
}
+EXPORT_SYMBOL_GPL(octeon_read_device_mem64);
u32 octeon_read_device_mem32(struct octeon_device *oct, u64 coreaddr)
{
@@ -191,6 +194,7 @@ u32 octeon_read_device_mem32(struct octeon_device *oct, u64 coreaddr)
return be32_to_cpu(ret);
}
+EXPORT_SYMBOL_GPL(octeon_read_device_mem32);
void octeon_write_device_mem32(struct octeon_device *oct, u64 coreaddr,
u32 val)
@@ -199,3 +203,4 @@ void octeon_write_device_mem32(struct octeon_device *oct, u64 coreaddr,
__octeon_pci_rw_core_mem(oct, coreaddr, (u8 *)&t, 4, 0);
}
+EXPORT_SYMBOL_GPL(octeon_write_device_mem32);
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_nic.c b/drivers/net/ethernet/cavium/liquidio/octeon_nic.c
index 1a706f81bbb0..dee56ea740e7 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_nic.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_nic.c
@@ -79,6 +79,7 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct,
return sc;
}
+EXPORT_SYMBOL_GPL(octeon_alloc_soft_command_resp);
int octnet_send_nic_data_pkt(struct octeon_device *oct,
struct octnic_data_pkt *ndata,
@@ -90,6 +91,7 @@ int octnet_send_nic_data_pkt(struct octeon_device *oct,
ndata->buf, ndata->datasize,
ndata->reqtype);
}
+EXPORT_SYMBOL_GPL(octnet_send_nic_data_pkt);
static inline struct octeon_soft_command
*octnic_alloc_ctrl_pkt_sc(struct octeon_device *oct,
@@ -196,3 +198,4 @@ octnet_send_nic_ctrl_pkt(struct octeon_device *oct,
return retval;
}
+EXPORT_SYMBOL_GPL(octnet_send_nic_ctrl_pkt);
diff --git a/drivers/net/ethernet/cavium/liquidio/request_manager.c b/drivers/net/ethernet/cavium/liquidio/request_manager.c
index 32f854c0cd79..de8a6ce86ad7 100644
--- a/drivers/net/ethernet/cavium/liquidio/request_manager.c
+++ b/drivers/net/ethernet/cavium/liquidio/request_manager.c
@@ -185,6 +185,7 @@ int octeon_delete_instr_queue(struct octeon_device *oct, u32 iq_no)
}
return 1;
}
+EXPORT_SYMBOL_GPL(octeon_delete_instr_queue);
/* Return 0 on success, 1 on failure */
int octeon_setup_iq(struct octeon_device *oct,
@@ -258,6 +259,7 @@ int lio_wait_for_instr_fetch(struct octeon_device *oct)
return instr_cnt;
}
+EXPORT_SYMBOL_GPL(lio_wait_for_instr_fetch);
static inline void
ring_doorbell(struct octeon_device *oct, struct octeon_instr_queue *iq)
@@ -282,6 +284,7 @@ octeon_ring_doorbell_locked(struct octeon_device *oct, u32 iq_no)
ring_doorbell(oct, iq);
spin_unlock(&iq->post_lock);
}
+EXPORT_SYMBOL_GPL(octeon_ring_doorbell_locked);
static inline void __copy_cmd_into_iq(struct octeon_instr_queue *iq,
u8 *cmd)
@@ -345,6 +348,7 @@ octeon_register_reqtype_free_fn(struct octeon_device *oct, int reqtype,
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_register_reqtype_free_fn);
static inline void
__add_to_request_list(struct octeon_instr_queue *iq,
@@ -430,6 +434,7 @@ lio_process_iq_request_list(struct octeon_device *oct,
return inst_count;
}
+EXPORT_SYMBOL_GPL(lio_process_iq_request_list);
/* Can only be called from process context */
int
@@ -566,6 +571,7 @@ octeon_send_command(struct octeon_device *oct, u32 iq_no,
return st.status;
}
+EXPORT_SYMBOL_GPL(octeon_send_command);
void
octeon_prepare_soft_command(struct octeon_device *oct,
@@ -673,6 +679,7 @@ octeon_prepare_soft_command(struct octeon_device *oct,
}
}
}
+EXPORT_SYMBOL_GPL(octeon_prepare_soft_command);
int octeon_send_soft_command(struct octeon_device *oct,
struct octeon_soft_command *sc)
@@ -726,6 +733,7 @@ int octeon_send_soft_command(struct octeon_device *oct,
return (octeon_send_command(oct, sc->iq_no, 1, &sc->cmd, sc,
len, REQTYPE_SOFT_COMMAND));
}
+EXPORT_SYMBOL_GPL(octeon_send_soft_command);
int octeon_setup_sc_buffer_pool(struct octeon_device *oct)
{
@@ -755,6 +763,7 @@ int octeon_setup_sc_buffer_pool(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_setup_sc_buffer_pool);
int octeon_free_sc_done_list(struct octeon_device *oct)
{
@@ -794,6 +803,7 @@ int octeon_free_sc_done_list(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_free_sc_done_list);
int octeon_free_sc_zombie_list(struct octeon_device *oct)
{
@@ -818,6 +828,7 @@ int octeon_free_sc_zombie_list(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_free_sc_zombie_list);
int octeon_free_sc_buffer_pool(struct octeon_device *oct)
{
@@ -842,6 +853,7 @@ int octeon_free_sc_buffer_pool(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_free_sc_buffer_pool);
struct octeon_soft_command *octeon_alloc_soft_command(struct octeon_device *oct,
u32 datasize,
@@ -913,6 +925,7 @@ struct octeon_soft_command *octeon_alloc_soft_command(struct octeon_device *oct,
return sc;
}
+EXPORT_SYMBOL_GPL(octeon_alloc_soft_command);
void octeon_free_soft_command(struct octeon_device *oct,
struct octeon_soft_command *sc)
@@ -925,3 +938,4 @@ void octeon_free_soft_command(struct octeon_device *oct,
spin_unlock_bh(&oct->sc_buf_pool.lock);
}
+EXPORT_SYMBOL_GPL(octeon_free_soft_command);
diff --git a/drivers/net/ethernet/cavium/liquidio/response_manager.c b/drivers/net/ethernet/cavium/liquidio/response_manager.c
index ac7747ccf56a..861050966e18 100644
--- a/drivers/net/ethernet/cavium/liquidio/response_manager.c
+++ b/drivers/net/ethernet/cavium/liquidio/response_manager.c
@@ -52,12 +52,14 @@ int octeon_setup_response_list(struct octeon_device *oct)
return ret;
}
+EXPORT_SYMBOL_GPL(octeon_setup_response_list);
void octeon_delete_response_list(struct octeon_device *oct)
{
cancel_delayed_work_sync(&oct->dma_comp_wq.wk.work);
destroy_workqueue(oct->dma_comp_wq.wq);
}
+EXPORT_SYMBOL_GPL(octeon_delete_response_list);
int lio_process_ordered_list(struct octeon_device *octeon_dev,
u32 force_quit)
@@ -219,6 +221,7 @@ int lio_process_ordered_list(struct octeon_device *octeon_dev,
return 0;
}
+EXPORT_SYMBOL_GPL(lio_process_ordered_list);
static void oct_poll_req_completion(struct work_struct *work)
{
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index 7eb2ddbe9bad..a317feb8decb 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -1126,8 +1126,7 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
}
poll:
- lmac->check_link = alloc_workqueue("check_link", WQ_UNBOUND |
- WQ_MEM_RECLAIM, 1);
+ lmac->check_link = alloc_ordered_workqueue("check_link", WQ_MEM_RECLAIM);
if (!lmac->check_link)
return -ENOMEM;
INIT_DELAYED_WORK(&lmac->dwork, bgx_poll_for_link);
diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c
index efa7f401529e..2e9a74fe0970 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c
@@ -2184,9 +2184,8 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs,
len -= offset;
rx_frag += nr_frags;
- __skb_frag_set_page(rx_frag, sd->pg_chunk.page);
- skb_frag_off_set(rx_frag, sd->pg_chunk.offset + offset);
- skb_frag_size_set(rx_frag, len);
+ skb_frag_fill_page_desc(rx_frag, sd->pg_chunk.page,
+ sd->pg_chunk.offset + offset, len);
skb->len += len;
skb->data_len += len;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index f0bc7396ce2b..2eb33a727bba 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -1175,7 +1175,7 @@ static u16 cxgb_select_queue(struct net_device *dev, struct sk_buff *skb,
txq = netdev_pick_tx(dev, skb, sb_dev);
if (xfrm_offload(skb) || is_ptp_enabled(skb, dev) ||
skb->encapsulation ||
- cxgb4_is_ktls_skb(skb) ||
+ tls_is_skb_tx_device_offloaded(skb) ||
(proto != IPPROTO_TCP && proto != IPPROTO_UDP))
txq = txq % pi->nqsets;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index 34546f5312ee..a9599ba26975 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -497,11 +497,6 @@ struct cxgb4_uld_info {
#endif
};
-static inline bool cxgb4_is_ktls_skb(struct sk_buff *skb)
-{
- return skb->sk && tls_is_sk_tx_device_offloaded(skb->sk);
-}
-
void cxgb4_uld_enable(struct adapter *adap);
void cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p);
int cxgb4_unregister_uld(enum cxgb4_uld type);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index 46809e2d94ee..98dd78551d89 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -1530,7 +1530,7 @@ static netdev_tx_t cxgb4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
#endif /* CHELSIO_IPSEC_INLINE */
#if IS_ENABLED(CONFIG_CHELSIO_TLS_DEVICE)
- if (cxgb4_is_ktls_skb(skb) &&
+ if (tls_is_skb_tx_device_offloaded(skb) &&
(skb->len - skb_tcp_all_headers(skb)))
return adap->uld[CXGB4_ULD_KTLS].tx_handler(skb, dev);
#endif /* CHELSIO_TLS_DEVICE */
diff --git a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c
index 1a5fdd755e9e..bcdc7fc2f427 100644
--- a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c
+++ b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c
@@ -1946,7 +1946,7 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev)
tls_ctx = tls_get_ctx(skb->sk);
tls_netdev = rcu_dereference_bh(tls_ctx->netdev);
/* Don't quit on NULL: if tls_device_down is running in parallel,
- * netdev might become NULL, even if tls_is_sk_tx_device_offloaded was
+ * netdev might become NULL, even if tls_is_skb_tx_device_offloaded was
* true. Rather continue processing this packet.
*/
if (unlikely(tls_netdev && tls_netdev != dev))
diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h
index 41714203ace8..68562a82d036 100644
--- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h
+++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h
@@ -568,8 +568,7 @@ void chtls_destroy_sock(struct sock *sk);
int chtls_sendmsg(struct sock *sk, struct msghdr *msg, size_t size);
int chtls_recvmsg(struct sock *sk, struct msghdr *msg,
size_t len, int flags, int *addr_len);
-int chtls_sendpage(struct sock *sk, struct page *page,
- int offset, size_t size, int flags);
+void chtls_splice_eof(struct socket *sock);
int send_tx_flowc_wr(struct sock *sk, int compl,
u32 snd_nxt, u32 rcv_nxt);
void chtls_tcp_push(struct sock *sk, int flags);
diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c
index c2e7037c7ba1..7750702900fa 100644
--- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c
+++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c
@@ -1466,7 +1466,7 @@ static void make_established(struct sock *sk, u32 snd_isn, unsigned int opt)
tp->write_seq = snd_isn;
tp->snd_nxt = snd_isn;
tp->snd_una = snd_isn;
- inet_sk(sk)->inet_id = get_random_u16();
+ atomic_set(&inet_sk(sk)->inet_id, get_random_u16());
assign_rxopt(sk, opt);
if (tp->rcv_wnd > (RCV_BUFSIZ_M << 10))
diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c
index ae6b17b96bf1..5fc64e47568a 100644
--- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c
+++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c
@@ -1092,7 +1092,17 @@ new_buf:
if (copy > size)
copy = size;
- if (skb_tailroom(skb) > 0) {
+ if (msg->msg_flags & MSG_SPLICE_PAGES) {
+ err = skb_splice_from_iter(skb, &msg->msg_iter, copy,
+ sk->sk_allocation);
+ if (err < 0) {
+ if (err == -EMSGSIZE)
+ goto new_buf;
+ goto do_fault;
+ }
+ copy = err;
+ sk_wmem_queued_add(sk, copy);
+ } else if (skb_tailroom(skb) > 0) {
copy = min(copy, skb_tailroom(skb));
if (is_tls_tx(csk))
copy = min_t(int, copy, csk->tlshws.txleft);
@@ -1227,113 +1237,13 @@ out_err:
goto done;
}
-int chtls_sendpage(struct sock *sk, struct page *page,
- int offset, size_t size, int flags)
+void chtls_splice_eof(struct socket *sock)
{
- struct chtls_sock *csk;
- struct chtls_dev *cdev;
- int mss, err, copied;
- struct tcp_sock *tp;
- long timeo;
+ struct sock *sk = sock->sk;
- tp = tcp_sk(sk);
- copied = 0;
- csk = rcu_dereference_sk_user_data(sk);
- cdev = csk->cdev;
lock_sock(sk);
- timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
-
- err = sk_stream_wait_connect(sk, &timeo);
- if (!sk_in_state(sk, TCPF_ESTABLISHED | TCPF_CLOSE_WAIT) &&
- err != 0)
- goto out_err;
-
- mss = csk->mss;
- csk_set_flag(csk, CSK_TX_MORE_DATA);
-
- while (size > 0) {
- struct sk_buff *skb = skb_peek_tail(&csk->txq);
- int copy, i;
-
- if (!skb || (ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND) ||
- (copy = mss - skb->len) <= 0) {
-new_buf:
- if (!csk_mem_free(cdev, sk))
- goto wait_for_sndbuf;
-
- if (is_tls_tx(csk)) {
- skb = get_record_skb(sk,
- select_size(sk, size,
- flags,
- TX_TLSHDR_LEN),
- true);
- } else {
- skb = get_tx_skb(sk, 0);
- }
- if (!skb)
- goto wait_for_memory;
- copy = mss;
- }
- if (copy > size)
- copy = size;
-
- i = skb_shinfo(skb)->nr_frags;
- if (skb_can_coalesce(skb, i, page, offset)) {
- skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy);
- } else if (i < MAX_SKB_FRAGS) {
- get_page(page);
- skb_fill_page_desc(skb, i, page, offset, copy);
- } else {
- tx_skb_finalize(skb);
- push_frames_if_head(sk);
- goto new_buf;
- }
-
- skb->len += copy;
- if (skb->len == mss)
- tx_skb_finalize(skb);
- skb->data_len += copy;
- skb->truesize += copy;
- sk->sk_wmem_queued += copy;
- tp->write_seq += copy;
- copied += copy;
- offset += copy;
- size -= copy;
-
- if (corked(tp, flags) &&
- (sk_stream_wspace(sk) < sk_stream_min_wspace(sk)))
- ULP_SKB_CB(skb)->flags |= ULPCB_FLAG_NO_APPEND;
-
- if (!size)
- break;
-
- if (unlikely(ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND))
- push_frames_if_head(sk);
- continue;
-wait_for_sndbuf:
- set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
-wait_for_memory:
- err = csk_wait_memory(cdev, sk, &timeo);
- if (err)
- goto do_error;
- }
-out:
- csk_reset_flag(csk, CSK_TX_MORE_DATA);
- if (copied)
- chtls_tcp_push(sk, flags);
-done:
+ chtls_tcp_push(sk, 0);
release_sock(sk);
- return copied;
-
-do_error:
- if (copied)
- goto out;
-
-out_err:
- if (csk_conn_inline(csk))
- csk_reset_flag(csk, CSK_TX_MORE_DATA);
- copied = sk_stream_error(sk, flags, err);
- goto done;
}
static void chtls_select_window(struct sock *sk)
diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
index 1e55b12fee51..455a54708be4 100644
--- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
+++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
@@ -606,7 +606,7 @@ static void __init chtls_init_ulp_ops(void)
chtls_cpl_prot.destroy = chtls_destroy_sock;
chtls_cpl_prot.shutdown = chtls_shutdown;
chtls_cpl_prot.sendmsg = chtls_sendmsg;
- chtls_cpl_prot.sendpage = chtls_sendpage;
+ chtls_cpl_prot.splice_eof = chtls_splice_eof;
chtls_cpl_prot.recvmsg = chtls_recvmsg;
chtls_cpl_prot.setsockopt = chtls_setsockopt;
chtls_cpl_prot.getsockopt = chtls_getsockopt;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 0defd519ba62..0616b5fe241c 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1138,7 +1138,8 @@ static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter,
(lancer_chip(adapter) || BE3_chip(adapter) ||
skb_vlan_tag_present(skb)) && is_ipv4_pkt(skb)) {
ip = (struct iphdr *)ip_hdr(skb);
- pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len));
+ if (unlikely(pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len))))
+ goto tx_drop;
}
/* If vlan tag is already inlined in the packet, skip HW VLAN
@@ -2343,11 +2344,10 @@ static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb,
hdr_len = ETH_HLEN;
memcpy(skb->data, start, hdr_len);
skb_shinfo(skb)->nr_frags = 1;
- skb_frag_set_page(skb, 0, page_info->page);
- skb_frag_off_set(&skb_shinfo(skb)->frags[0],
- page_info->page_offset + hdr_len);
- skb_frag_size_set(&skb_shinfo(skb)->frags[0],
- curr_frag_len - hdr_len);
+ skb_frag_fill_page_desc(&skb_shinfo(skb)->frags[0],
+ page_info->page,
+ page_info->page_offset + hdr_len,
+ curr_frag_len - hdr_len);
skb->data_len = curr_frag_len - hdr_len;
skb->truesize += rx_frag_size;
skb->tail += hdr_len;
@@ -2369,16 +2369,17 @@ static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb,
if (page_info->page_offset == 0) {
/* Fresh page */
j++;
- skb_frag_set_page(skb, j, page_info->page);
- skb_frag_off_set(&skb_shinfo(skb)->frags[j],
- page_info->page_offset);
- skb_frag_size_set(&skb_shinfo(skb)->frags[j], 0);
+ skb_frag_fill_page_desc(&skb_shinfo(skb)->frags[j],
+ page_info->page,
+ page_info->page_offset,
+ curr_frag_len);
skb_shinfo(skb)->nr_frags++;
} else {
put_page(page_info->page);
+ skb_frag_size_add(&skb_shinfo(skb)->frags[j],
+ curr_frag_len);
}
- skb_frag_size_add(&skb_shinfo(skb)->frags[j], curr_frag_len);
skb->len += curr_frag_len;
skb->data_len += curr_frag_len;
skb->truesize += rx_frag_size;
@@ -2451,14 +2452,16 @@ static void be_rx_compl_process_gro(struct be_rx_obj *rxo,
if (i == 0 || page_info->page_offset == 0) {
/* First frag or Fresh page */
j++;
- skb_frag_set_page(skb, j, page_info->page);
- skb_frag_off_set(&skb_shinfo(skb)->frags[j],
- page_info->page_offset);
- skb_frag_size_set(&skb_shinfo(skb)->frags[j], 0);
+ skb_frag_fill_page_desc(&skb_shinfo(skb)->frags[j],
+ page_info->page,
+ page_info->page_offset,
+ curr_frag_len);
} else {
put_page(page_info->page);
+ skb_frag_size_add(&skb_shinfo(skb)->frags[j],
+ curr_frag_len);
}
- skb_frag_size_add(&skb_shinfo(skb)->frags[j], curr_frag_len);
+
skb->truesize += rx_frag_size;
remaining -= curr_frag_len;
memset(page_info, 0, sizeof(*page_info));
diff --git a/drivers/net/ethernet/engleder/tsnep_selftests.c b/drivers/net/ethernet/engleder/tsnep_selftests.c
index 1581d6b22232..8a9145f93147 100644
--- a/drivers/net/ethernet/engleder/tsnep_selftests.c
+++ b/drivers/net/ethernet/engleder/tsnep_selftests.c
@@ -329,7 +329,7 @@ static bool disable_taprio(struct tsnep_adapter *adapter)
int retval;
memset(&qopt, 0, sizeof(qopt));
- qopt.enable = 0;
+ qopt.cmd = TAPRIO_CMD_DESTROY;
retval = tsnep_tc_setup(adapter->netdev, TC_SETUP_QDISC_TAPRIO, &qopt);
if (retval)
return false;
@@ -360,7 +360,7 @@ static bool tsnep_test_taprio(struct tsnep_adapter *adapter)
for (i = 0; i < 255; i++)
qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;
- qopt->enable = 1;
+ qopt->cmd = TAPRIO_CMD_REPLACE;
qopt->base_time = ktime_set(0, 0);
qopt->cycle_time = 1500000;
qopt->cycle_time_extension = 0;
@@ -382,7 +382,7 @@ static bool tsnep_test_taprio(struct tsnep_adapter *adapter)
if (!run_taprio(adapter, qopt, 100))
goto failed;
- qopt->enable = 1;
+ qopt->cmd = TAPRIO_CMD_REPLACE;
qopt->base_time = ktime_set(0, 0);
qopt->cycle_time = 411854;
qopt->cycle_time_extension = 0;
@@ -406,7 +406,7 @@ static bool tsnep_test_taprio(struct tsnep_adapter *adapter)
if (!run_taprio(adapter, qopt, 100))
goto failed;
- qopt->enable = 1;
+ qopt->cmd = TAPRIO_CMD_REPLACE;
qopt->base_time = ktime_set(0, 0);
delay_base_time(adapter, qopt, 12);
qopt->cycle_time = 125000;
@@ -457,7 +457,7 @@ static bool tsnep_test_taprio_change(struct tsnep_adapter *adapter)
for (i = 0; i < 255; i++)
qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;
- qopt->enable = 1;
+ qopt->cmd = TAPRIO_CMD_REPLACE;
qopt->base_time = ktime_set(0, 0);
qopt->cycle_time = 100000;
qopt->cycle_time_extension = 0;
@@ -610,7 +610,7 @@ static bool tsnep_test_taprio_extension(struct tsnep_adapter *adapter)
for (i = 0; i < 255; i++)
qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;
- qopt->enable = 1;
+ qopt->cmd = TAPRIO_CMD_REPLACE;
qopt->base_time = ktime_set(0, 0);
qopt->cycle_time = 100000;
qopt->cycle_time_extension = 50000;
diff --git a/drivers/net/ethernet/engleder/tsnep_tc.c b/drivers/net/ethernet/engleder/tsnep_tc.c
index d083e6684f12..745b191a5540 100644
--- a/drivers/net/ethernet/engleder/tsnep_tc.c
+++ b/drivers/net/ethernet/engleder/tsnep_tc.c
@@ -325,7 +325,7 @@ static int tsnep_taprio(struct tsnep_adapter *adapter,
if (!adapter->gate_control)
return -EOPNOTSUPP;
- if (!qopt->enable) {
+ if (qopt->cmd == TAPRIO_CMD_DESTROY) {
/* disable gate control if active */
mutex_lock(&adapter->gate_control_lock);
@@ -337,6 +337,8 @@ static int tsnep_taprio(struct tsnep_adapter *adapter,
mutex_unlock(&adapter->gate_control_lock);
return 0;
+ } else if (qopt->cmd != TAPRIO_CMD_REPLACE) {
+ return -EOPNOTSUPP;
}
retval = tsnep_validate_gcl(qopt);
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig
index 1c78f66a89da..75401d2a5fb4 100644
--- a/drivers/net/ethernet/freescale/Kconfig
+++ b/drivers/net/ethernet/freescale/Kconfig
@@ -29,7 +29,7 @@ config FEC
select CRC32
select PHYLIB
select PAGE_POOL
- select PAGE_POOL_STATS
+ imply PAGE_POOL_STATS
imply NET_SELFTESTS
help
Say Y here if you want to use the built-in 10/100 Fast ethernet
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-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
index 00e50bd30189..a69bb22c37ea 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
@@ -252,8 +252,8 @@ static int dpaa2_pcs_create(struct dpaa2_mac *mac,
struct fwnode_handle *dpmac_node,
int id)
{
- struct mdio_device *mdiodev;
struct fwnode_handle *node;
+ struct phylink_pcs *pcs;
node = fwnode_find_reference(dpmac_node, "pcs-handle", 0);
if (IS_ERR(node)) {
@@ -262,26 +262,27 @@ static int dpaa2_pcs_create(struct dpaa2_mac *mac,
return 0;
}
- if (!fwnode_device_is_available(node)) {
- netdev_err(mac->net_dev, "pcs-handle node not available\n");
- fwnode_handle_put(node);
- return -ENODEV;
- }
-
- mdiodev = fwnode_mdio_find_device(node);
+ pcs = lynx_pcs_create_fwnode(node);
fwnode_handle_put(node);
- if (!mdiodev) {
+
+ if (pcs == ERR_PTR(-EPROBE_DEFER)) {
netdev_dbg(mac->net_dev, "missing PCS device\n");
return -EPROBE_DEFER;
}
- mac->pcs = lynx_pcs_create(mdiodev);
- if (!mac->pcs) {
- netdev_err(mac->net_dev, "lynx_pcs_create() failed\n");
- put_device(&mdiodev->dev);
- return -ENOMEM;
+ if (pcs == ERR_PTR(-ENODEV)) {
+ netdev_err(mac->net_dev, "pcs-handle node not available\n");
+ return PTR_ERR(pcs);
+ }
+
+ if (IS_ERR(pcs)) {
+ netdev_err(mac->net_dev,
+ "lynx_pcs_create_fwnode() failed: %pe\n", pcs);
+ return PTR_ERR(pcs);
}
+ mac->pcs = pcs;
+
return 0;
}
@@ -290,11 +291,7 @@ static void dpaa2_pcs_destroy(struct dpaa2_mac *mac)
struct phylink_pcs *phylink_pcs = mac->pcs;
if (phylink_pcs) {
- struct mdio_device *mdio = lynx_get_mdio_device(phylink_pcs);
- struct device *dev = &mdio->dev;
-
lynx_pcs_destroy(phylink_pcs);
- put_device(dev);
mac->pcs = NULL;
}
}
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/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 9e1b2536e9a9..35461165de0d 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -1451,9 +1451,8 @@ static void enetc_add_rx_buff_to_xdp(struct enetc_bdr *rx_ring, int i,
xdp_buff_set_frag_pfmemalloc(xdp_buff);
frag = &shinfo->frags[shinfo->nr_frags];
- skb_frag_off_set(frag, rx_swbd->page_offset);
- skb_frag_size_set(frag, size);
- __skb_frag_set_page(frag, rx_swbd->page);
+ skb_frag_fill_page_desc(frag, rx_swbd->page, rx_swbd->page_offset,
+ size);
shinfo->nr_frags++;
}
@@ -1790,7 +1789,7 @@ static int enetc_alloc_tx_resource(struct enetc_bdr_resource *res,
res->bd_count = bd_count;
res->bd_size = sizeof(union enetc_tx_bd);
- res->tx_swbd = vzalloc(bd_count * sizeof(*res->tx_swbd));
+ res->tx_swbd = vcalloc(bd_count, sizeof(*res->tx_swbd));
if (!res->tx_swbd)
return -ENOMEM;
@@ -1878,7 +1877,7 @@ static int enetc_alloc_rx_resource(struct enetc_bdr_resource *res,
if (extended)
res->bd_size *= 2;
- res->rx_swbd = vzalloc(bd_count * sizeof(struct enetc_rx_swbd));
+ res->rx_swbd = vcalloc(bd_count, sizeof(struct enetc_rx_swbd));
if (!res->rx_swbd)
return -ENOMEM;
@@ -2639,7 +2638,7 @@ static void enetc_debug_tx_ring_prios(struct enetc_ndev_priv *priv)
priv->tx_ring[i]->prio);
}
-static void enetc_reset_tc_mqprio(struct net_device *ndev)
+void enetc_reset_tc_mqprio(struct net_device *ndev)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_hw *hw = &priv->si->hw;
@@ -2664,6 +2663,7 @@ static void enetc_reset_tc_mqprio(struct net_device *ndev)
enetc_change_preemptible_tcs(priv, 0);
}
+EXPORT_SYMBOL_GPL(enetc_reset_tc_mqprio);
int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)
{
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index c97a8e3d7a7f..8577cf7699a0 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -429,6 +429,7 @@ struct net_device_stats *enetc_get_stats(struct net_device *ndev);
void enetc_set_features(struct net_device *ndev, netdev_features_t features);
int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd);
int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data);
+void enetc_reset_tc_mqprio(struct net_device *ndev);
int enetc_setup_bpf(struct net_device *ndev, struct netdev_bpf *bpf);
int enetc_xdp_xmit(struct net_device *ndev, int num_frames,
struct xdp_frame **frames, u32 flags);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 7cd22d370caa..e0a4cb7e3f50 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -863,7 +863,6 @@ static int enetc_imdio_create(struct enetc_pf *pf)
struct device *dev = &pf->si->pdev->dev;
struct enetc_mdio_priv *mdio_priv;
struct phylink_pcs *phylink_pcs;
- struct mdio_device *mdio_device;
struct mii_bus *bus;
int err;
@@ -889,17 +888,9 @@ static int enetc_imdio_create(struct enetc_pf *pf)
goto free_mdio_bus;
}
- mdio_device = mdio_device_create(bus, 0);
- if (IS_ERR(mdio_device)) {
- err = PTR_ERR(mdio_device);
- dev_err(dev, "cannot create mdio device (%d)\n", err);
- goto unregister_mdiobus;
- }
-
- phylink_pcs = lynx_pcs_create(mdio_device);
- if (!phylink_pcs) {
- mdio_device_free(mdio_device);
- err = -ENOMEM;
+ phylink_pcs = lynx_pcs_create_mdiodev(bus, 0);
+ if (IS_ERR(phylink_pcs)) {
+ err = PTR_ERR(phylink_pcs);
dev_err(dev, "cannot create lynx pcs (%d)\n", err);
goto unregister_mdiobus;
}
@@ -918,13 +909,8 @@ free_mdio_bus:
static void enetc_imdio_remove(struct enetc_pf *pf)
{
- struct mdio_device *mdio_device;
-
- if (pf->pcs) {
- mdio_device = lynx_get_mdio_device(pf->pcs);
- mdio_device_free(mdio_device);
+ if (pf->pcs)
lynx_pcs_destroy(pf->pcs);
- }
if (pf->imdio) {
mdiobus_unregister(pf->imdio);
mdiobus_free(pf->imdio);
@@ -1200,14 +1186,9 @@ static int enetc_init_port_rss_memory(struct enetc_si *si)
static int enetc_pf_register_with_ierb(struct pci_dev *pdev)
{
- struct device_node *node = pdev->dev.of_node;
struct platform_device *ierb_pdev;
struct device_node *ierb_node;
- /* Don't register with the IERB if the PF itself is disabled */
- if (!node || !of_device_is_available(node))
- return 0;
-
ierb_node = of_find_compatible_node(NULL, NULL,
"fsl,ls1028a-enetc-ierb");
if (!ierb_node || !of_device_is_available(ierb_node))
@@ -1222,56 +1203,81 @@ static int enetc_pf_register_with_ierb(struct pci_dev *pdev)
return enetc_ierb_register_pf(ierb_pdev, pdev);
}
-static int enetc_pf_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
{
- struct device_node *node = pdev->dev.of_node;
- struct enetc_ndev_priv *priv;
- struct net_device *ndev;
struct enetc_si *si;
- struct enetc_pf *pf;
int err;
- err = enetc_pf_register_with_ierb(pdev);
- if (err == -EPROBE_DEFER)
- return err;
- if (err)
- dev_warn(&pdev->dev,
- "Could not register with IERB driver: %pe, please update the device tree\n",
- ERR_PTR(err));
-
- err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf));
- if (err)
- return dev_err_probe(&pdev->dev, err, "PCI probing failed\n");
+ err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(struct enetc_pf));
+ if (err) {
+ dev_err_probe(&pdev->dev, err, "PCI probing failed\n");
+ goto out;
+ }
si = pci_get_drvdata(pdev);
if (!si->hw.port || !si->hw.global) {
err = -ENODEV;
dev_err(&pdev->dev, "could not map PF space, probing a VF?\n");
- goto err_map_pf_space;
+ goto out_pci_remove;
}
err = enetc_setup_cbdr(&pdev->dev, &si->hw, ENETC_CBDR_DEFAULT_SIZE,
&si->cbd_ring);
if (err)
- goto err_setup_cbdr;
+ goto out_pci_remove;
err = enetc_init_port_rfs_memory(si);
if (err) {
dev_err(&pdev->dev, "Failed to initialize RFS memory\n");
- goto err_init_port_rfs;
+ goto out_teardown_cbdr;
}
err = enetc_init_port_rss_memory(si);
if (err) {
dev_err(&pdev->dev, "Failed to initialize RSS memory\n");
- goto err_init_port_rss;
+ goto out_teardown_cbdr;
}
- if (node && !of_device_is_available(node)) {
- dev_info(&pdev->dev, "device is disabled, skipping\n");
- err = -ENODEV;
- goto err_device_disabled;
+ return si;
+
+out_teardown_cbdr:
+ enetc_teardown_cbdr(&si->cbd_ring);
+out_pci_remove:
+ enetc_pci_remove(pdev);
+out:
+ return ERR_PTR(err);
+}
+
+static void enetc_psi_destroy(struct pci_dev *pdev)
+{
+ struct enetc_si *si = pci_get_drvdata(pdev);
+
+ enetc_teardown_cbdr(&si->cbd_ring);
+ enetc_pci_remove(pdev);
+}
+
+static int enetc_pf_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct enetc_ndev_priv *priv;
+ struct net_device *ndev;
+ struct enetc_si *si;
+ struct enetc_pf *pf;
+ int err;
+
+ err = enetc_pf_register_with_ierb(pdev);
+ if (err == -EPROBE_DEFER)
+ return err;
+ if (err)
+ dev_warn(&pdev->dev,
+ "Could not register with IERB driver: %pe, please update the device tree\n",
+ ERR_PTR(err));
+
+ si = enetc_psi_create(pdev);
+ if (IS_ERR(si)) {
+ err = PTR_ERR(si);
+ goto err_psi_create;
}
pf = enetc_si_priv(si);
@@ -1353,15 +1359,9 @@ err_alloc_si_res:
si->ndev = NULL;
free_netdev(ndev);
err_alloc_netdev:
-err_init_port_rss:
-err_init_port_rfs:
-err_device_disabled:
err_setup_mac_addresses:
- enetc_teardown_cbdr(&si->cbd_ring);
-err_setup_cbdr:
-err_map_pf_space:
- enetc_pci_remove(pdev);
-
+ enetc_psi_destroy(pdev);
+err_psi_create:
return err;
}
@@ -1384,12 +1384,29 @@ static void enetc_pf_remove(struct pci_dev *pdev)
enetc_free_msix(priv);
enetc_free_si_resources(priv);
- enetc_teardown_cbdr(&si->cbd_ring);
free_netdev(si->ndev);
- enetc_pci_remove(pdev);
+ enetc_psi_destroy(pdev);
+}
+
+static void enetc_fixup_clear_rss_rfs(struct pci_dev *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct enetc_si *si;
+
+ /* Only apply quirk for disabled functions. For the ones
+ * that are enabled, enetc_pf_probe() will apply it.
+ */
+ if (node && of_device_is_available(node))
+ return;
+
+ si = enetc_psi_create(pdev);
+ if (si)
+ enetc_psi_destroy(pdev);
}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PF,
+ enetc_fixup_clear_rss_rfs);
static const struct pci_device_id enetc_pf_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PF) },
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
index 126007ab70f6..270cbd5e8684 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
@@ -43,10 +43,9 @@ void enetc_sched_speed_set(struct enetc_ndev_priv *priv, int speed)
enetc_port_wr(hw, ENETC_PMR, (tmp & ~ENETC_PMR_PSPEED_MASK) | pspeed);
}
-static int enetc_setup_taprio(struct net_device *ndev,
+static int enetc_setup_taprio(struct enetc_ndev_priv *priv,
struct tc_taprio_qopt_offload *admin_conf)
{
- struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_hw *hw = &priv->si->hw;
struct enetc_cbd cbd = {.cmd = 0};
struct tgs_gcl_conf *gcl_config;
@@ -60,19 +59,13 @@ static int enetc_setup_taprio(struct net_device *ndev,
int err;
int i;
+ /* TSD and Qbv are mutually exclusive in hardware */
+ for (i = 0; i < priv->num_tx_rings; i++)
+ if (priv->tx_ring[i]->tsd_enable)
+ return -EBUSY;
+
if (admin_conf->num_entries > enetc_get_max_gcl_len(hw))
return -EINVAL;
- gcl_len = admin_conf->num_entries;
-
- tge = enetc_rd(hw, ENETC_PTGCR);
- if (!admin_conf->enable) {
- enetc_wr(hw, ENETC_PTGCR, tge & ~ENETC_PTGCR_TGE);
- enetc_reset_ptcmsdur(hw);
-
- priv->active_offloads &= ~ENETC_F_QBV;
-
- return 0;
- }
if (admin_conf->cycle_time > U32_MAX ||
admin_conf->cycle_time_extension > U32_MAX)
@@ -82,6 +75,7 @@ static int enetc_setup_taprio(struct net_device *ndev,
* control BD descriptor.
*/
gcl_config = &cbd.gcl_conf;
+ gcl_len = admin_conf->num_entries;
data_size = struct_size(gcl_data, entry, gcl_len);
tmp = enetc_cbd_alloc_data_mem(priv->si, &cbd, data_size,
@@ -115,6 +109,7 @@ static int enetc_setup_taprio(struct net_device *ndev,
cbd.cls = BDCR_CMD_PORT_GCL;
cbd.status_flags = 0;
+ tge = enetc_rd(hw, ENETC_PTGCR);
enetc_wr(hw, ENETC_PTGCR, tge | ENETC_PTGCR_TGE);
err = enetc_send_cmd(priv->si, &cbd);
@@ -132,25 +127,95 @@ static int enetc_setup_taprio(struct net_device *ndev,
return 0;
}
-int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data)
+static void enetc_reset_taprio_stats(struct enetc_ndev_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->num_tx_rings; i++)
+ priv->tx_ring[i]->stats.win_drop = 0;
+}
+
+static void enetc_reset_taprio(struct enetc_ndev_priv *priv)
+{
+ struct enetc_hw *hw = &priv->si->hw;
+ u32 val;
+
+ val = enetc_rd(hw, ENETC_PTGCR);
+ enetc_wr(hw, ENETC_PTGCR, val & ~ENETC_PTGCR_TGE);
+ enetc_reset_ptcmsdur(hw);
+
+ priv->active_offloads &= ~ENETC_F_QBV;
+}
+
+static void enetc_taprio_destroy(struct net_device *ndev)
{
- struct tc_taprio_qopt_offload *taprio = type_data;
struct enetc_ndev_priv *priv = netdev_priv(ndev);
- int err, i;
- /* TSD and Qbv are mutually exclusive in hardware */
+ enetc_reset_taprio(priv);
+ enetc_reset_tc_mqprio(ndev);
+ enetc_reset_taprio_stats(priv);
+}
+
+static void enetc_taprio_stats(struct net_device *ndev,
+ struct tc_taprio_qopt_stats *stats)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ u64 window_drops = 0;
+ int i;
+
for (i = 0; i < priv->num_tx_rings; i++)
- if (priv->tx_ring[i]->tsd_enable)
- return -EBUSY;
+ window_drops += priv->tx_ring[i]->stats.win_drop;
+
+ stats->window_drops = window_drops;
+}
+
+static void enetc_taprio_queue_stats(struct net_device *ndev,
+ struct tc_taprio_qopt_queue_stats *queue_stats)
+{
+ struct tc_taprio_qopt_stats *stats = &queue_stats->stats;
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ int queue = queue_stats->queue;
- err = enetc_setup_tc_mqprio(ndev, &taprio->mqprio);
+ stats->window_drops = priv->tx_ring[queue]->stats.win_drop;
+}
+
+static int enetc_taprio_replace(struct net_device *ndev,
+ struct tc_taprio_qopt_offload *offload)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ int err;
+
+ err = enetc_setup_tc_mqprio(ndev, &offload->mqprio);
if (err)
return err;
- err = enetc_setup_taprio(ndev, taprio);
- if (err) {
- taprio->mqprio.qopt.num_tc = 0;
- enetc_setup_tc_mqprio(ndev, &taprio->mqprio);
+ err = enetc_setup_taprio(priv, offload);
+ if (err)
+ enetc_reset_tc_mqprio(ndev);
+
+ return err;
+}
+
+int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data)
+{
+ struct tc_taprio_qopt_offload *offload = type_data;
+ int err = 0;
+
+ switch (offload->cmd) {
+ case TAPRIO_CMD_REPLACE:
+ err = enetc_taprio_replace(ndev, offload);
+ break;
+ case TAPRIO_CMD_DESTROY:
+ enetc_taprio_destroy(ndev);
+ break;
+ case TAPRIO_CMD_STATS:
+ enetc_taprio_stats(ndev, &offload->stats);
+ break;
+ case TAPRIO_CMD_QUEUE_STATS:
+ enetc_taprio_queue_stats(ndev, &offload->queue_stats);
+ break;
+ default:
+ err = -EOPNOTSUPP;
}
return err;
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 9939ccafb556..63a053dea819 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -355,7 +355,7 @@ struct bufdesc_ex {
#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
#define FEC_ENET_TX_FRSIZE 2048
#define FEC_ENET_TX_FRPPG (PAGE_SIZE / FEC_ENET_TX_FRSIZE)
-#define TX_RING_SIZE 512 /* Must be power of two */
+#define TX_RING_SIZE 1024 /* Must be power of two */
#define TX_RING_MOD_MASK 511 /* for this to work */
#define BD_ENET_RX_INT 0x00800000
@@ -544,10 +544,23 @@ enum {
XDP_STATS_TOTAL,
};
+enum fec_txbuf_type {
+ FEC_TXBUF_T_SKB,
+ FEC_TXBUF_T_XDP_NDO,
+};
+
+struct fec_tx_buffer {
+ union {
+ struct sk_buff *skb;
+ struct xdp_frame *xdp;
+ };
+ enum fec_txbuf_type type;
+};
+
struct fec_enet_priv_tx_q {
struct bufdesc_prop bd;
unsigned char *tx_bounce[TX_RING_SIZE];
- struct sk_buff *tx_skbuff[TX_RING_SIZE];
+ struct fec_tx_buffer tx_buf[TX_RING_SIZE];
unsigned short tx_stop_threshold;
unsigned short tx_wake_threshold;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 38e5b5abe067..66b5cbdb43b9 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -397,7 +397,7 @@ static void fec_dump(struct net_device *ndev)
fec16_to_cpu(bdp->cbd_sc),
fec32_to_cpu(bdp->cbd_bufaddr),
fec16_to_cpu(bdp->cbd_datlen),
- txq->tx_skbuff[index]);
+ txq->tx_buf[index].skb);
bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
index++;
} while (bdp != txq->bd.base);
@@ -654,7 +654,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
index = fec_enet_get_bd_index(last_bdp, &txq->bd);
/* Save skb pointer */
- txq->tx_skbuff[index] = skb;
+ txq->tx_buf[index].skb = skb;
/* Make sure the updates to rest of the descriptor are performed before
* transferring ownership.
@@ -672,9 +672,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
skb_tx_timestamp(skb);
- /* Make sure the update to bdp and tx_skbuff are performed before
- * txq->bd.cur.
- */
+ /* Make sure the update to bdp is performed before txq->bd.cur. */
wmb();
txq->bd.cur = bdp;
@@ -862,7 +860,7 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
}
/* Save skb pointer */
- txq->tx_skbuff[index] = skb;
+ txq->tx_buf[index].skb = skb;
skb_tx_timestamp(skb);
txq->bd.cur = bdp;
@@ -952,16 +950,33 @@ static void fec_enet_bd_init(struct net_device *dev)
for (i = 0; i < txq->bd.ring_size; i++) {
/* Initialize the BD for every fragment in the page. */
bdp->cbd_sc = cpu_to_fec16(0);
- if (bdp->cbd_bufaddr &&
- !IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr)))
- dma_unmap_single(&fep->pdev->dev,
- fec32_to_cpu(bdp->cbd_bufaddr),
- fec16_to_cpu(bdp->cbd_datlen),
- DMA_TO_DEVICE);
- if (txq->tx_skbuff[i]) {
- dev_kfree_skb_any(txq->tx_skbuff[i]);
- txq->tx_skbuff[i] = NULL;
+ if (txq->tx_buf[i].type == FEC_TXBUF_T_SKB) {
+ if (bdp->cbd_bufaddr &&
+ !IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr)))
+ dma_unmap_single(&fep->pdev->dev,
+ fec32_to_cpu(bdp->cbd_bufaddr),
+ fec16_to_cpu(bdp->cbd_datlen),
+ DMA_TO_DEVICE);
+ if (txq->tx_buf[i].skb) {
+ dev_kfree_skb_any(txq->tx_buf[i].skb);
+ txq->tx_buf[i].skb = NULL;
+ }
+ } else {
+ if (bdp->cbd_bufaddr)
+ dma_unmap_single(&fep->pdev->dev,
+ fec32_to_cpu(bdp->cbd_bufaddr),
+ fec16_to_cpu(bdp->cbd_datlen),
+ DMA_TO_DEVICE);
+
+ if (txq->tx_buf[i].xdp) {
+ xdp_return_frame(txq->tx_buf[i].xdp);
+ txq->tx_buf[i].xdp = NULL;
+ }
+
+ /* restore default tx buffer type: FEC_TXBUF_T_SKB */
+ txq->tx_buf[i].type = FEC_TXBUF_T_SKB;
}
+
bdp->cbd_bufaddr = cpu_to_fec32(0);
bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
}
@@ -1011,24 +1026,6 @@ static void fec_enet_enable_ring(struct net_device *ndev)
}
}
-static void fec_enet_reset_skb(struct net_device *ndev)
-{
- struct fec_enet_private *fep = netdev_priv(ndev);
- struct fec_enet_priv_tx_q *txq;
- int i, j;
-
- for (i = 0; i < fep->num_tx_queues; i++) {
- txq = fep->tx_queue[i];
-
- for (j = 0; j < txq->bd.ring_size; j++) {
- if (txq->tx_skbuff[j]) {
- dev_kfree_skb_any(txq->tx_skbuff[j]);
- txq->tx_skbuff[j] = NULL;
- }
- }
- }
-}
-
/*
* This function is called to start or restart the FEC during a link
* change, transmit timeout, or to reconfigure the FEC. The network
@@ -1071,9 +1068,6 @@ fec_restart(struct net_device *ndev)
fec_enet_enable_ring(ndev);
- /* Reset tx SKB buffers. */
- fec_enet_reset_skb(ndev);
-
/* Enable MII mode */
if (fep->full_duplex == DUPLEX_FULL) {
/* FD enable */
@@ -1378,9 +1372,10 @@ fec_enet_hwtstamp(struct fec_enet_private *fep, unsigned ts,
}
static void
-fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
+fec_enet_tx_queue(struct net_device *ndev, u16 queue_id, int budget)
{
struct fec_enet_private *fep;
+ struct xdp_frame *xdpf;
struct bufdesc *bdp;
unsigned short status;
struct sk_buff *skb;
@@ -1408,16 +1403,39 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
index = fec_enet_get_bd_index(bdp, &txq->bd);
- skb = txq->tx_skbuff[index];
- txq->tx_skbuff[index] = NULL;
- if (!IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr)))
- dma_unmap_single(&fep->pdev->dev,
- fec32_to_cpu(bdp->cbd_bufaddr),
- fec16_to_cpu(bdp->cbd_datlen),
- DMA_TO_DEVICE);
- bdp->cbd_bufaddr = cpu_to_fec32(0);
- if (!skb)
- goto skb_done;
+ if (txq->tx_buf[index].type == FEC_TXBUF_T_SKB) {
+ skb = txq->tx_buf[index].skb;
+ txq->tx_buf[index].skb = NULL;
+ if (bdp->cbd_bufaddr &&
+ !IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr)))
+ dma_unmap_single(&fep->pdev->dev,
+ fec32_to_cpu(bdp->cbd_bufaddr),
+ fec16_to_cpu(bdp->cbd_datlen),
+ DMA_TO_DEVICE);
+ bdp->cbd_bufaddr = cpu_to_fec32(0);
+ if (!skb)
+ goto tx_buf_done;
+ } else {
+ /* Tx processing cannot call any XDP (or page pool) APIs if
+ * the "budget" is 0. Because NAPI is called with budget of
+ * 0 (such as netpoll) indicates we may be in an IRQ context,
+ * however, we can't use the page pool from IRQ context.
+ */
+ if (unlikely(!budget))
+ break;
+
+ xdpf = txq->tx_buf[index].xdp;
+ if (bdp->cbd_bufaddr)
+ dma_unmap_single(&fep->pdev->dev,
+ fec32_to_cpu(bdp->cbd_bufaddr),
+ fec16_to_cpu(bdp->cbd_datlen),
+ DMA_TO_DEVICE);
+ bdp->cbd_bufaddr = cpu_to_fec32(0);
+ if (!xdpf) {
+ txq->tx_buf[index].type = FEC_TXBUF_T_SKB;
+ goto tx_buf_done;
+ }
+ }
/* Check for errors. */
if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
@@ -1436,21 +1454,11 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
ndev->stats.tx_carrier_errors++;
} else {
ndev->stats.tx_packets++;
- ndev->stats.tx_bytes += skb->len;
- }
- /* NOTE: SKBTX_IN_PROGRESS being set does not imply it's we who
- * are to time stamp the packet, so we still need to check time
- * stamping enabled flag.
- */
- if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS &&
- fep->hwts_tx_en) &&
- fep->bufdesc_ex) {
- struct skb_shared_hwtstamps shhwtstamps;
- struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
-
- fec_enet_hwtstamp(fep, fec32_to_cpu(ebdp->ts), &shhwtstamps);
- skb_tstamp_tx(skb, &shhwtstamps);
+ if (txq->tx_buf[index].type == FEC_TXBUF_T_SKB)
+ ndev->stats.tx_bytes += skb->len;
+ else
+ ndev->stats.tx_bytes += xdpf->len;
}
/* Deferred means some collisions occurred during transmit,
@@ -1459,10 +1467,32 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
if (status & BD_ENET_TX_DEF)
ndev->stats.collisions++;
- /* Free the sk buffer associated with this last transmit */
- dev_kfree_skb_any(skb);
-skb_done:
- /* Make sure the update to bdp and tx_skbuff are performed
+ if (txq->tx_buf[index].type == FEC_TXBUF_T_SKB) {
+ /* NOTE: SKBTX_IN_PROGRESS being set does not imply it's we who
+ * are to time stamp the packet, so we still need to check time
+ * stamping enabled flag.
+ */
+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS &&
+ fep->hwts_tx_en) && fep->bufdesc_ex) {
+ struct skb_shared_hwtstamps shhwtstamps;
+ struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
+
+ fec_enet_hwtstamp(fep, fec32_to_cpu(ebdp->ts), &shhwtstamps);
+ skb_tstamp_tx(skb, &shhwtstamps);
+ }
+
+ /* Free the sk buffer associated with this last transmit */
+ dev_kfree_skb_any(skb);
+ } else {
+ xdp_return_frame(xdpf);
+
+ txq->tx_buf[index].xdp = NULL;
+ /* restore default tx buffer type: FEC_TXBUF_T_SKB */
+ txq->tx_buf[index].type = FEC_TXBUF_T_SKB;
+ }
+
+tx_buf_done:
+ /* Make sure the update to bdp and tx_buf are performed
* before dirty_tx
*/
wmb();
@@ -1486,14 +1516,14 @@ skb_done:
writel(0, txq->bd.reg_desc_active);
}
-static void fec_enet_tx(struct net_device *ndev)
+static void fec_enet_tx(struct net_device *ndev, int budget)
{
struct fec_enet_private *fep = netdev_priv(ndev);
int i;
/* Make sure that AVB queues are processed first. */
for (i = fep->num_tx_queues - 1; i >= 0; i--)
- fec_enet_tx_queue(ndev, i);
+ fec_enet_tx_queue(ndev, i, budget);
}
static void fec_enet_update_cbd(struct fec_enet_priv_rx_q *rxq,
@@ -1836,7 +1866,7 @@ static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
do {
done += fec_enet_rx(ndev, budget - done);
- fec_enet_tx(ndev);
+ fec_enet_tx(ndev, budget);
} while ((done < budget) && fec_enet_collect_events(fep));
if (done < budget) {
@@ -2810,6 +2840,7 @@ static void fec_enet_get_xdp_stats(struct fec_enet_private *fep, u64 *data)
static void fec_enet_page_pool_stats(struct fec_enet_private *fep, u64 *data)
{
+#ifdef CONFIG_PAGE_POOL_STATS
struct page_pool_stats stats = {};
struct fec_enet_priv_rx_q *rxq;
int i;
@@ -2824,6 +2855,7 @@ static void fec_enet_page_pool_stats(struct fec_enet_private *fep, u64 *data)
}
page_pool_ethtool_stats_get(data, &stats);
+#endif
}
static void fec_enet_get_ethtool_stats(struct net_device *dev,
@@ -3268,9 +3300,19 @@ static void fec_enet_free_buffers(struct net_device *ndev)
for (i = 0; i < txq->bd.ring_size; i++) {
kfree(txq->tx_bounce[i]);
txq->tx_bounce[i] = NULL;
- skb = txq->tx_skbuff[i];
- txq->tx_skbuff[i] = NULL;
- dev_kfree_skb(skb);
+
+ if (txq->tx_buf[i].type == FEC_TXBUF_T_SKB) {
+ skb = txq->tx_buf[i].skb;
+ txq->tx_buf[i].skb = NULL;
+ dev_kfree_skb(skb);
+ } else {
+ if (txq->tx_buf[i].xdp) {
+ xdp_return_frame(txq->tx_buf[i].xdp);
+ txq->tx_buf[i].xdp = NULL;
+ }
+
+ txq->tx_buf[i].type = FEC_TXBUF_T_SKB;
+ }
}
}
}
@@ -3315,8 +3357,7 @@ static int fec_enet_alloc_queue(struct net_device *ndev)
fep->total_tx_ring_size += fep->tx_queue[i]->bd.ring_size;
txq->tx_stop_threshold = FEC_MAX_SKB_DESCS;
- txq->tx_wake_threshold =
- (txq->bd.ring_size - txq->tx_stop_threshold) / 2;
+ txq->tx_wake_threshold = FEC_MAX_SKB_DESCS + 2 * MAX_SKB_FRAGS;
txq->tso_hdrs = dma_alloc_coherent(&fep->pdev->dev,
txq->bd.ring_size * TSO_HEADER_SIZE,
@@ -3751,12 +3792,18 @@ static int fec_enet_bpf(struct net_device *dev, struct netdev_bpf *bpf)
if (fep->quirks & FEC_QUIRK_SWAP_FRAME)
return -EOPNOTSUPP;
+ if (!bpf->prog)
+ xdp_features_clear_redirect_target(dev);
+
if (is_run) {
napi_disable(&fep->napi);
netif_tx_disable(dev);
}
old_prog = xchg(&fep->xdp_prog, bpf->prog);
+ if (old_prog)
+ bpf_prog_put(old_prog);
+
fec_restart(dev);
if (is_run) {
@@ -3764,8 +3811,8 @@ static int fec_enet_bpf(struct net_device *dev, struct netdev_bpf *bpf)
netif_tx_start_all_queues(dev);
}
- if (old_prog)
- bpf_prog_put(old_prog);
+ if (bpf->prog)
+ xdp_features_set_redirect_target(dev, false);
return 0;
@@ -3791,19 +3838,18 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
struct xdp_frame *frame)
{
unsigned int index, status, estatus;
- struct bufdesc *bdp, *last_bdp;
+ struct bufdesc *bdp;
dma_addr_t dma_addr;
int entries_free;
entries_free = fec_enet_get_free_txdesc_num(txq);
if (entries_free < MAX_SKB_FRAGS + 1) {
- netdev_err(fep->netdev, "NOT enough BD for SG!\n");
- return NETDEV_TX_BUSY;
+ netdev_err_once(fep->netdev, "NOT enough BD for SG!\n");
+ return -EBUSY;
}
/* Fill in a Tx ring entry */
bdp = txq->bd.cur;
- last_bdp = bdp;
status = fec16_to_cpu(bdp->cbd_sc);
status &= ~BD_ENET_TX_STATS;
@@ -3812,7 +3858,7 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
dma_addr = dma_map_single(&fep->pdev->dev, frame->data,
frame->len, DMA_TO_DEVICE);
if (dma_mapping_error(&fep->pdev->dev, dma_addr))
- return FEC_ENET_XDP_CONSUMED;
+ return -ENOMEM;
status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST);
if (fep->bufdesc_ex)
@@ -3831,8 +3877,8 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
ebdp->cbd_esc = cpu_to_fec32(estatus);
}
- index = fec_enet_get_bd_index(last_bdp, &txq->bd);
- txq->tx_skbuff[index] = NULL;
+ txq->tx_buf[index].type = FEC_TXBUF_T_XDP_NDO;
+ txq->tx_buf[index].xdp = frame;
/* Make sure the updates to rest of the descriptor are performed before
* transferring ownership.
@@ -3846,7 +3892,7 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
bdp->cbd_sc = cpu_to_fec16(status);
/* If this was the last BD in the ring, start at the beginning again. */
- bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd);
+ bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
/* Make sure the update to bdp are performed before txq->bd.cur. */
dma_wmb();
@@ -3878,8 +3924,10 @@ static int fec_enet_xdp_xmit(struct net_device *dev,
__netif_tx_lock(nq, cpu);
+ /* Avoid tx timeout as XDP shares the queue with kernel stack */
+ txq_trans_cond_update(nq);
for (i = 0; i < num_frames; i++) {
- if (fec_enet_txq_xmit_frame(fep, txq, frames[i]) != 0)
+ if (fec_enet_txq_xmit_frame(fep, txq, frames[i]) < 0)
break;
sent_frames++;
}
@@ -4035,6 +4083,10 @@ static int fec_enet_init(struct net_device *ndev)
ndev->hw_features = ndev->features;
+ if (!(fep->quirks & FEC_QUIRK_SWAP_FRAME))
+ ndev->xdp_features = NETDEV_XDP_ACT_BASIC |
+ NETDEV_XDP_ACT_REDIRECT;
+
fec_restart(ndev);
if (fep->quirks & FEC_QUIRK_MIB_CLEAR)
diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index d528ca681b6f..3088da7adf0f 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -763,15 +763,15 @@ static void dtsec_pcs_get_state(struct phylink_pcs *pcs,
phylink_mii_c22_pcs_get_state(dtsec->tbidev, state);
}
-static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
{
struct fman_mac *dtsec = pcs_to_dtsec(pcs);
- return phylink_mii_c22_pcs_config(dtsec->tbidev, mode, interface,
- advertising);
+ return phylink_mii_c22_pcs_config(dtsec->tbidev, interface,
+ advertising, neg_mode);
}
static void dtsec_pcs_an_restart(struct phylink_pcs *pcs)
@@ -1447,6 +1447,7 @@ int dtsec_initialization(struct mac_device *mac_dev,
goto _return_fm_mac_free;
}
dtsec->pcs.ops = &dtsec_pcs_ops;
+ dtsec->pcs.neg_mode = true;
dtsec->pcs.poll = true;
supported = mac_dev->phylink_config.supported_interfaces;
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index 625c79d5636f..3b75cc543be9 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -976,14 +976,10 @@ static int memac_init(struct fman_mac *memac)
static void pcs_put(struct phylink_pcs *pcs)
{
- struct mdio_device *mdiodev;
-
if (IS_ERR_OR_NULL(pcs))
return;
- mdiodev = lynx_get_mdio_device(pcs);
lynx_pcs_destroy(pcs);
- mdio_device_free(mdiodev);
}
static int memac_free(struct fman_mac *memac)
@@ -1043,20 +1039,14 @@ static struct phylink_pcs *memac_pcs_create(struct device_node *mac_node,
int index)
{
struct device_node *node;
- struct mdio_device *mdiodev = NULL;
struct phylink_pcs *pcs;
node = of_parse_phandle(mac_node, "pcsphy-handle", index);
- if (node && of_device_is_available(node))
- mdiodev = of_mdio_find_device(node);
- of_node_put(node);
+ if (!node)
+ return ERR_PTR(-ENODEV);
- if (!mdiodev)
- return ERR_PTR(-EPROBE_DEFER);
-
- pcs = lynx_pcs_create(mdiodev);
- if (!pcs)
- mdio_device_free(mdiodev);
+ pcs = lynx_pcs_create_fwnode(of_fwnode_handle(node));
+ of_node_put(node);
return pcs;
}
diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
index d37d7a19a759..59a8f0bd0f5c 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
@@ -127,7 +127,7 @@ static int fs_enet_mdio_probe(struct platform_device *ofdev)
if (ret)
goto out_res;
- snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%pap", &res.start);
fec->fecp = ioremap(res.start, resource_size(&res));
if (!fec->fecp) {
diff --git a/drivers/net/ethernet/fungible/funeth/funeth_rx.c b/drivers/net/ethernet/fungible/funeth/funeth_rx.c
index 29a6c2ede43a..7e2584895de3 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_rx.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_rx.c
@@ -323,9 +323,8 @@ static int fun_gather_pkt(struct funeth_rxq *q, unsigned int tot_len,
if (ref_ok)
ref_ok |= buf->node;
- __skb_frag_set_page(frags, buf->page);
- skb_frag_off_set(frags, q->buf_offset);
- skb_frag_size_set(frags++, frag_len);
+ skb_frag_fill_page_desc(frags++, buf->page, q->buf_offset,
+ frag_len);
tot_len -= frag_len;
if (!tot_len)
diff --git a/drivers/net/ethernet/fungible/funeth/funeth_tx.c b/drivers/net/ethernet/fungible/funeth/funeth_tx.c
index 706d81e39a54..8ddefd3ec15b 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_tx.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_tx.c
@@ -348,8 +348,7 @@ netdev_tx_t fun_start_xmit(struct sk_buff *skb, struct net_device *netdev)
unsigned int tls_len = 0;
unsigned int ndesc;
- if (IS_ENABLED(CONFIG_TLS_DEVICE) && skb->sk &&
- tls_is_sk_tx_device_offloaded(skb->sk)) {
+ if (tls_is_skb_tx_device_offloaded(skb)) {
skb = fun_tls_tx(skb, q, &tls_len);
if (unlikely(!skb))
goto dropped;
diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index 98eb78d98e9f..4b425bf71ede 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -964,5 +964,6 @@ void gve_handle_report_stats(struct gve_priv *priv);
/* exported by ethtool.c */
extern const struct ethtool_ops gve_ethtool_ops;
/* needed by ethtool */
+extern char gve_driver_name[];
extern const char gve_version_str[];
#endif /* _GVE_H_ */
diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c
index cfd4b8d284d1..233e5946905e 100644
--- a/drivers/net/ethernet/google/gve/gve_ethtool.c
+++ b/drivers/net/ethernet/google/gve/gve_ethtool.c
@@ -15,7 +15,7 @@ static void gve_get_drvinfo(struct net_device *netdev,
{
struct gve_priv *priv = netdev_priv(netdev);
- strscpy(info->driver, "gve", sizeof(info->driver));
+ strscpy(info->driver, gve_driver_name, sizeof(info->driver));
strscpy(info->version, gve_version_str, sizeof(info->version));
strscpy(info->bus_info, pci_name(priv->pdev), sizeof(info->bus_info));
}
@@ -590,6 +590,9 @@ static int gve_get_link_ksettings(struct net_device *netdev,
err = gve_adminq_report_link_speed(priv);
cmd->base.speed = priv->link_speed;
+
+ cmd->base.duplex = DUPLEX_FULL;
+
return err;
}
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index caa00c72aeeb..e6f1711d9be0 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -31,7 +31,9 @@
// Minimum amount of time between queue kicks in msec (10 seconds)
#define MIN_TX_TIMEOUT_GAP (1000 * 10)
+#define DQO_TX_MAX 0x3FFFF
+char gve_driver_name[] = "gve";
const char gve_version_str[] = GVE_VERSION;
static const char gve_version_prefix[] = GVE_VERSION_PREFIX;
@@ -2047,6 +2049,10 @@ static int gve_init_priv(struct gve_priv *priv, bool skip_describe_device)
goto err;
}
+ /* Big TCP is only supported on DQ*/
+ if (!gve_is_gqi(priv))
+ netif_set_tso_max_size(priv->dev, DQO_TX_MAX);
+
priv->num_registered_pages = 0;
priv->rx_copybreak = GVE_DEFAULT_RX_COPYBREAK;
/* gvnic has one Notification Block per MSI-x vector, except for the
@@ -2195,7 +2201,7 @@ static int gve_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
return err;
- err = pci_request_regions(pdev, "gvnic-cfg");
+ err = pci_request_regions(pdev, gve_driver_name);
if (err)
goto abort_with_enabled;
@@ -2388,8 +2394,8 @@ static const struct pci_device_id gve_id_table[] = {
{ }
};
-static struct pci_driver gvnic_driver = {
- .name = "gvnic",
+static struct pci_driver gve_driver = {
+ .name = gve_driver_name,
.id_table = gve_id_table,
.probe = gve_probe,
.remove = gve_remove,
@@ -2400,10 +2406,10 @@ static struct pci_driver gvnic_driver = {
#endif
};
-module_pci_driver(gvnic_driver);
+module_pci_driver(gve_driver);
MODULE_DEVICE_TABLE(pci, gve_id_table);
MODULE_AUTHOR("Google, Inc.");
-MODULE_DESCRIPTION("gVNIC Driver");
+MODULE_DESCRIPTION("Google Virtual NIC Driver");
MODULE_LICENSE("Dual MIT/GPL");
MODULE_VERSION(GVE_VERSION);
diff --git a/drivers/net/ethernet/google/gve/gve_tx.c b/drivers/net/ethernet/google/gve/gve_tx.c
index 813da572abca..6957a865cff3 100644
--- a/drivers/net/ethernet/google/gve/gve_tx.c
+++ b/drivers/net/ethernet/google/gve/gve_tx.c
@@ -248,7 +248,7 @@ static int gve_tx_alloc_ring(struct gve_priv *priv, int idx)
tx->mask = slots - 1;
/* alloc metadata */
- tx->info = vzalloc(sizeof(*tx->info) * slots);
+ tx->info = vcalloc(slots, sizeof(*tx->info));
if (!tx->info)
return -ENOMEM;
diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
index b76143bfd594..3c09e66ba1ab 100644
--- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
@@ -8,6 +8,7 @@
#include "gve_adminq.h"
#include "gve_utils.h"
#include "gve_dqo.h"
+#include <net/ip.h>
#include <linux/tcp.h>
#include <linux/slab.h>
#include <linux/skbuff.h>
@@ -646,6 +647,9 @@ static int gve_try_tx_skb(struct gve_priv *priv, struct gve_tx_ring *tx,
goto drop;
}
+ if (unlikely(ipv6_hopopt_jumbo_remove(skb)))
+ goto drop;
+
num_buffer_descs = gve_num_buffer_descs_needed(skb);
} else {
num_buffer_descs = gve_num_buffer_descs_needed(skb);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
index 9c9c72dc57e0..514a20bce4f4 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
@@ -31,6 +31,7 @@
#include <linux/pci.h>
#include <linux/pkt_sched.h>
#include <linux/types.h>
+#include <linux/bitmap.h>
#include <net/pkt_cls.h>
#include <net/pkt_sched.h>
@@ -101,6 +102,7 @@ enum HNAE3_DEV_CAP_BITS {
HNAE3_DEV_SUPPORT_FEC_STATS_B,
HNAE3_DEV_SUPPORT_LANE_NUM_B,
HNAE3_DEV_SUPPORT_WOL_B,
+ HNAE3_DEV_SUPPORT_TM_FLUSH_B,
};
#define hnae3_ae_dev_fd_supported(ae_dev) \
@@ -172,6 +174,9 @@ enum HNAE3_DEV_CAP_BITS {
#define hnae3_ae_dev_wol_supported(ae_dev) \
test_bit(HNAE3_DEV_SUPPORT_WOL_B, (ae_dev)->caps)
+#define hnae3_ae_dev_tm_flush_supported(hdev) \
+ test_bit(HNAE3_DEV_SUPPORT_TM_FLUSH_B, (hdev)->ae_dev->caps)
+
enum HNAE3_PF_CAP_BITS {
HNAE3_PF_SUPPORT_VLAN_FLTR_MDF_B = 0,
};
@@ -407,7 +412,7 @@ struct hnae3_ae_dev {
unsigned long hw_err_reset_req;
struct hnae3_dev_specs dev_specs;
u32 dev_version;
- unsigned long caps[BITS_TO_LONGS(HNAE3_DEV_CAPS_MAX_NUM)];
+ DECLARE_BITMAP(caps, HNAE3_DEV_CAPS_MAX_NUM);
void *priv;
};
@@ -647,8 +652,7 @@ struct hnae3_ae_ops {
int (*rm_mc_addr)(struct hnae3_handle *handle,
const unsigned char *addr);
void (*set_tso_stats)(struct hnae3_handle *handle, int enable);
- void (*update_stats)(struct hnae3_handle *handle,
- struct net_device_stats *net_stats);
+ void (*update_stats)(struct hnae3_handle *handle);
void (*get_stats)(struct hnae3_handle *handle, u64 *data);
void (*get_mac_stats)(struct hnae3_handle *handle,
struct hns3_mac_stats *mac_stats);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c
index b85c412683dd..dcecb23daac6 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c
@@ -156,6 +156,7 @@ static const struct hclge_comm_caps_bit_map hclge_pf_cmd_caps[] = {
{HCLGE_COMM_CAP_FEC_STATS_B, HNAE3_DEV_SUPPORT_FEC_STATS_B},
{HCLGE_COMM_CAP_LANE_NUM_B, HNAE3_DEV_SUPPORT_LANE_NUM_B},
{HCLGE_COMM_CAP_WOL_B, HNAE3_DEV_SUPPORT_WOL_B},
+ {HCLGE_COMM_CAP_TM_FLUSH_B, HNAE3_DEV_SUPPORT_TM_FLUSH_B},
};
static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = {
@@ -172,6 +173,20 @@ static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = {
};
static void
+hclge_comm_capability_to_bitmap(unsigned long *bitmap, __le32 *caps)
+{
+ const unsigned int words = HCLGE_COMM_QUERY_CAP_LENGTH;
+ u32 val[HCLGE_COMM_QUERY_CAP_LENGTH];
+ unsigned int i;
+
+ for (i = 0; i < words; i++)
+ val[i] = __le32_to_cpu(caps[i]);
+
+ bitmap_from_arr32(bitmap, val,
+ HCLGE_COMM_QUERY_CAP_LENGTH * BITS_PER_TYPE(u32));
+}
+
+static void
hclge_comm_parse_capability(struct hnae3_ae_dev *ae_dev, bool is_pf,
struct hclge_comm_query_version_cmd *cmd)
{
@@ -179,11 +194,12 @@ hclge_comm_parse_capability(struct hnae3_ae_dev *ae_dev, bool is_pf,
is_pf ? hclge_pf_cmd_caps : hclge_vf_cmd_caps;
u32 size = is_pf ? ARRAY_SIZE(hclge_pf_cmd_caps) :
ARRAY_SIZE(hclge_vf_cmd_caps);
- u32 caps, i;
+ DECLARE_BITMAP(caps, HCLGE_COMM_QUERY_CAP_LENGTH * BITS_PER_TYPE(u32));
+ u32 i;
- caps = __le32_to_cpu(cmd->caps[0]);
+ hclge_comm_capability_to_bitmap(caps, cmd->caps);
for (i = 0; i < size; i++)
- if (hnae3_get_bit(caps, caps_map[i].imp_bit))
+ if (test_bit(caps_map[i].imp_bit, caps))
set_bit(caps_map[i].local_bit, ae_dev->caps);
}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h
index 18f1b4bf362d..2b7197ce0ae8 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h
@@ -153,6 +153,7 @@ enum hclge_opcode_type {
HCLGE_OPC_TM_INTERNAL_STS = 0x0850,
HCLGE_OPC_TM_INTERNAL_CNT = 0x0851,
HCLGE_OPC_TM_INTERNAL_STS_1 = 0x0852,
+ HCLGE_OPC_TM_FLUSH = 0x0872,
/* Packet buffer allocate commands */
HCLGE_OPC_TX_BUFF_ALLOC = 0x0901,
@@ -349,6 +350,7 @@ enum HCLGE_COMM_CAP_BITS {
HCLGE_COMM_CAP_FEC_STATS_B = 25,
HCLGE_COMM_CAP_LANE_NUM_B = 27,
HCLGE_COMM_CAP_WOL_B = 28,
+ HCLGE_COMM_CAP_TM_FLUSH_B = 31,
};
enum HCLGE_COMM_API_CAP_BITS {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c
index ae2736549526..b4ae2160aff4 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c
@@ -305,8 +305,7 @@ int hclge_comm_set_rss_indir_table(struct hnae3_ae_dev *ae_dev,
return 0;
}
-int hclge_comm_set_rss_input_tuple(struct hnae3_handle *nic,
- struct hclge_comm_hw *hw, bool is_pf,
+int hclge_comm_set_rss_input_tuple(struct hclge_comm_hw *hw,
struct hclge_comm_rss_cfg *rss_cfg)
{
struct hclge_comm_rss_input_tuple_cmd *req;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.h b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.h
index 92af3d2980d3..cdafa63fe38b 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.h
@@ -112,8 +112,7 @@ int hclge_comm_init_rss_tuple_cmd(struct hclge_comm_rss_cfg *rss_cfg,
struct hnae3_ae_dev *ae_dev,
struct hclge_comm_rss_input_tuple_cmd *req);
u64 hclge_comm_convert_rss_tuple(u8 tuple_sets);
-int hclge_comm_set_rss_input_tuple(struct hnae3_handle *nic,
- struct hclge_comm_hw *hw, bool is_pf,
+int hclge_comm_set_rss_input_tuple(struct hclge_comm_hw *hw,
struct hclge_comm_rss_cfg *rss_cfg);
int hclge_comm_set_rss_indir_table(struct hnae3_ae_dev *ae_dev,
struct hclge_comm_hw *hw, const u16 *indir);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
index d385ffc21876..f276b5ecb431 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
@@ -411,6 +411,9 @@ static struct hns3_dbg_cap_info hns3_dbg_cap[] = {
}, {
.name = "support wake on lan",
.cap_bit = HNAE3_DEV_SUPPORT_WOL_B,
+ }, {
+ .name = "support tm flush",
+ .cap_bit = HNAE3_DEV_SUPPORT_TM_FLUSH_B,
}
};
@@ -438,19 +441,36 @@ static void hns3_dbg_fill_content(char *content, u16 len,
const struct hns3_dbg_item *items,
const char **result, u16 size)
{
+#define HNS3_DBG_LINE_END_LEN 2
char *pos = content;
+ u16 item_len;
u16 i;
+ if (!len) {
+ return;
+ } else if (len <= HNS3_DBG_LINE_END_LEN) {
+ *pos++ = '\0';
+ return;
+ }
+
memset(content, ' ', len);
- for (i = 0; i < size; i++) {
- if (result)
- strncpy(pos, result[i], strlen(result[i]));
- else
- strncpy(pos, items[i].name, strlen(items[i].name));
+ len -= HNS3_DBG_LINE_END_LEN;
- pos += strlen(items[i].name) + items[i].interval;
+ for (i = 0; i < size; i++) {
+ item_len = strlen(items[i].name) + items[i].interval;
+ if (len < item_len)
+ break;
+
+ if (result) {
+ if (item_len < strlen(result[i]))
+ break;
+ memcpy(pos, result[i], strlen(result[i]));
+ } else {
+ memcpy(pos, items[i].name, strlen(items[i].name));
+ }
+ pos += item_len;
+ len -= item_len;
}
-
*pos++ = '\n';
*pos++ = '\0';
}
@@ -941,8 +961,7 @@ static const struct hns3_dbg_item tx_bd_info_items[] = {
{ "MSS_HW_CSUM", 0 },
};
-static void hns3_dump_tx_bd_info(struct hns3_nic_priv *priv,
- struct hns3_desc *desc, char **result, int idx)
+static void hns3_dump_tx_bd_info(struct hns3_desc *desc, char **result, int idx)
{
unsigned int j = 0;
@@ -991,7 +1010,7 @@ static int hns3_dbg_tx_bd_info(struct hns3_dbg_data *d, char *buf, int len)
for (i = 0; i < ring->desc_num; i++) {
desc = &ring->desc[i];
- hns3_dump_tx_bd_info(priv, desc, result, i);
+ hns3_dump_tx_bd_info(desc, result, i);
hns3_dbg_fill_content(content, sizeof(content),
tx_bd_info_items, (const char **)result,
ARRAY_SIZE(tx_bd_info_items));
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index b676496ec6d7..b7b51e56b030 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -2538,7 +2538,7 @@ static void hns3_nic_get_stats64(struct net_device *netdev,
if (test_bit(HNS3_NIC_STATE_DOWN, &priv->state))
return;
- handle->ae_algo->ops->update_stats(handle, &netdev->stats);
+ handle->ae_algo->ops->update_stats(handle);
memset(&ring_total_stats, 0, sizeof(ring_total_stats));
for (idx = 0; idx < queue_num; idx++) {
@@ -5854,6 +5854,9 @@ void hns3_external_lb_prepare(struct net_device *ndev, bool if_running)
if (!if_running)
return;
+ if (test_and_set_bit(HNS3_NIC_STATE_DOWN, &priv->state))
+ return;
+
netif_carrier_off(ndev);
netif_tx_disable(ndev);
@@ -5882,7 +5885,16 @@ void hns3_external_lb_restore(struct net_device *ndev, bool if_running)
if (!if_running)
return;
- hns3_nic_reset_all_ring(priv->ae_handle);
+ if (hns3_nic_resetting(ndev))
+ return;
+
+ if (!test_bit(HNS3_NIC_STATE_DOWN, &priv->state))
+ return;
+
+ if (hns3_nic_reset_all_ring(priv->ae_handle))
+ return;
+
+ clear_bit(HNS3_NIC_STATE_DOWN, &priv->state);
for (i = 0; i < priv->vector_num; i++)
hns3_vector_enable(&priv->tqp_vector[i]);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
index 51d1278b18f6..407d30ee55d2 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
@@ -228,7 +228,7 @@ static u32 hns3_lb_check_rx_ring(struct hns3_nic_priv *priv, u32 budget)
}
static void hns3_lb_clear_tx_ring(struct hns3_nic_priv *priv, u32 start_ringid,
- u32 end_ringid, u32 budget)
+ u32 end_ringid)
{
u32 i;
@@ -295,8 +295,7 @@ static int hns3_lp_run_test(struct net_device *ndev, enum hnae3_loop mode)
out:
hns3_lb_clear_tx_ring(priv, HNS3_NIC_LB_TEST_RING_ID,
- HNS3_NIC_LB_TEST_RING_ID,
- HNS3_NIC_LB_TEST_PKT_NUM);
+ HNS3_NIC_LB_TEST_RING_ID);
kfree_skb(skb);
return ret_val;
@@ -618,7 +617,7 @@ static void hns3_get_stats(struct net_device *netdev,
return;
}
- h->ae_algo->ops->update_stats(h, &netdev->stats);
+ h->ae_algo->ops->update_stats(h);
/* get per-queue stats */
p = hns3_get_stats_tqps(h, p);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
index c4aded65e848..fad5a5ff3cda 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
@@ -52,7 +52,10 @@ static void hclge_tm_info_to_ieee_ets(struct hclge_dev *hdev,
for (i = 0; i < HNAE3_MAX_TC; i++) {
ets->prio_tc[i] = hdev->tm_info.prio_tc[i];
- ets->tc_tx_bw[i] = hdev->tm_info.pg_info[0].tc_dwrr[i];
+ if (i < hdev->tm_info.num_tc)
+ ets->tc_tx_bw[i] = hdev->tm_info.pg_info[0].tc_dwrr[i];
+ else
+ ets->tc_tx_bw[i] = 0;
if (hdev->tm_info.tc_info[i].tc_sch_mode ==
HCLGE_SCH_MODE_SP)
@@ -123,7 +126,8 @@ static u8 hclge_ets_tc_changed(struct hclge_dev *hdev, struct ieee_ets *ets,
}
static int hclge_ets_sch_mode_validate(struct hclge_dev *hdev,
- struct ieee_ets *ets, bool *changed)
+ struct ieee_ets *ets, bool *changed,
+ u8 tc_num)
{
bool has_ets_tc = false;
u32 total_ets_bw = 0;
@@ -137,6 +141,13 @@ static int hclge_ets_sch_mode_validate(struct hclge_dev *hdev,
*changed = true;
break;
case IEEE_8021QAZ_TSA_ETS:
+ if (i >= tc_num) {
+ dev_err(&hdev->pdev->dev,
+ "tc%u is disabled, cannot set ets bw\n",
+ i);
+ return -EINVAL;
+ }
+
/* The hardware will switch to sp mode if bandwidth is
* 0, so limit ets bandwidth must be greater than 0.
*/
@@ -176,7 +187,7 @@ static int hclge_ets_validate(struct hclge_dev *hdev, struct ieee_ets *ets,
if (ret)
return ret;
- ret = hclge_ets_sch_mode_validate(hdev, ets, changed);
+ ret = hclge_ets_sch_mode_validate(hdev, ets, changed, tc_num);
if (ret)
return ret;
@@ -216,6 +227,10 @@ static int hclge_notify_down_uinit(struct hclge_dev *hdev)
if (ret)
return ret;
+ ret = hclge_tm_flush_cfg(hdev, true);
+ if (ret)
+ return ret;
+
return hclge_notify_client(hdev, HNAE3_UNINIT_CLIENT);
}
@@ -227,6 +242,10 @@ static int hclge_notify_init_up(struct hclge_dev *hdev)
if (ret)
return ret;
+ ret = hclge_tm_flush_cfg(hdev, false);
+ if (ret)
+ return ret;
+
return hclge_notify_client(hdev, HNAE3_UP_CLIENT);
}
@@ -313,6 +332,7 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
struct net_device *netdev = h->kinfo.netdev;
struct hclge_dev *hdev = vport->back;
u8 i, j, pfc_map, *prio_tc;
+ int last_bad_ret = 0;
int ret;
if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
@@ -350,13 +370,28 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
if (ret)
return ret;
- ret = hclge_buffer_alloc(hdev);
- if (ret) {
- hclge_notify_client(hdev, HNAE3_UP_CLIENT);
+ ret = hclge_tm_flush_cfg(hdev, true);
+ if (ret)
return ret;
- }
- return hclge_notify_client(hdev, HNAE3_UP_CLIENT);
+ /* No matter whether the following operations are performed
+ * successfully or not, disabling the tm flush and notify
+ * the network status to up are necessary.
+ * Do not return immediately.
+ */
+ ret = hclge_buffer_alloc(hdev);
+ if (ret)
+ last_bad_ret = ret;
+
+ ret = hclge_tm_flush_cfg(hdev, false);
+ if (ret)
+ last_bad_ret = ret;
+
+ ret = hclge_notify_client(hdev, HNAE3_UP_CLIENT);
+ if (ret)
+ last_bad_ret = ret;
+
+ return last_bad_ret;
}
static int hclge_ieee_setapp(struct hnae3_handle *h, struct dcb_app *app)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
index a0b46e7d863e..0fb2eaee3e8a 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
@@ -88,16 +88,35 @@ static void hclge_dbg_fill_content(char *content, u16 len,
const struct hclge_dbg_item *items,
const char **result, u16 size)
{
+#define HCLGE_DBG_LINE_END_LEN 2
char *pos = content;
+ u16 item_len;
u16 i;
+ if (!len) {
+ return;
+ } else if (len <= HCLGE_DBG_LINE_END_LEN) {
+ *pos++ = '\0';
+ return;
+ }
+
memset(content, ' ', len);
+ len -= HCLGE_DBG_LINE_END_LEN;
+
for (i = 0; i < size; i++) {
- if (result)
- strncpy(pos, result[i], strlen(result[i]));
- else
- strncpy(pos, items[i].name, strlen(items[i].name));
- pos += strlen(items[i].name) + items[i].interval;
+ item_len = strlen(items[i].name) + items[i].interval;
+ if (len < item_len)
+ break;
+
+ if (result) {
+ if (item_len < strlen(result[i]))
+ break;
+ memcpy(pos, result[i], strlen(result[i]));
+ } else {
+ memcpy(pos, items[i].name, strlen(items[i].name));
+ }
+ pos += item_len;
+ len -= item_len;
}
*pos++ = '\n';
*pos++ = '\0';
@@ -674,8 +693,7 @@ static int hclge_dbg_dump_tc(struct hclge_dev *hdev, char *buf, int len)
for (i = 0; i < HNAE3_MAX_TC; i++) {
sch_mode_str = ets_weight->tc_weight[i] ? "dwrr" : "sp";
pos += scnprintf(buf + pos, len - pos, "%u %4s %3u\n",
- i, sch_mode_str,
- hdev->tm_info.pg_info[0].tc_dwrr[i]);
+ i, sch_mode_str, ets_weight->tc_weight[i]);
}
return 0;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 2689b108f7df..a940e35aef29 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -72,6 +72,8 @@ static void hclge_restore_hw_table(struct hclge_dev *hdev);
static void hclge_sync_promisc_mode(struct hclge_dev *hdev);
static void hclge_sync_fd_table(struct hclge_dev *hdev);
static void hclge_update_fec_stats(struct hclge_dev *hdev);
+static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret,
+ int wait_cnt);
static struct hnae3_ae_algo ae_algo;
@@ -689,8 +691,7 @@ static void hclge_update_stats_for_all(struct hclge_dev *hdev)
"Update MAC stats fail, status = %d.\n", status);
}
-static void hclge_update_stats(struct hnae3_handle *handle,
- struct net_device_stats *net_stats)
+static void hclge_update_stats(struct hnae3_handle *handle)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
@@ -824,7 +825,7 @@ static void hclge_get_mac_stat(struct hnae3_handle *handle,
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
- hclge_update_stats(handle, NULL);
+ hclge_update_stats(handle);
mac_stats->tx_pause_cnt = hdev->mac_stats.mac_tx_mac_pause_num;
mac_stats->rx_pause_cnt = hdev->mac_stats.mac_rx_mac_pause_num;
@@ -4965,9 +4966,7 @@ int hclge_rss_init_hw(struct hclge_dev *hdev)
if (ret)
return ret;
- ret = hclge_comm_set_rss_input_tuple(&hdev->vport[0].nic,
- &hdev->hw.hw, true,
- &hdev->rss_cfg);
+ ret = hclge_comm_set_rss_input_tuple(&hdev->hw.hw, &hdev->rss_cfg);
if (ret)
return ret;
@@ -6243,8 +6242,7 @@ static int hclge_fd_check_spec(struct hclge_dev *hdev,
return hclge_fd_check_ext_tuple(hdev, fs, unused_tuple);
}
-static void hclge_fd_get_tcpip4_tuple(struct hclge_dev *hdev,
- struct ethtool_rx_flow_spec *fs,
+static void hclge_fd_get_tcpip4_tuple(struct ethtool_rx_flow_spec *fs,
struct hclge_fd_rule *rule, u8 ip_proto)
{
rule->tuples.src_ip[IPV4_INDEX] =
@@ -6273,8 +6271,7 @@ static void hclge_fd_get_tcpip4_tuple(struct hclge_dev *hdev,
rule->tuples_mask.ip_proto = 0xFF;
}
-static void hclge_fd_get_ip4_tuple(struct hclge_dev *hdev,
- struct ethtool_rx_flow_spec *fs,
+static void hclge_fd_get_ip4_tuple(struct ethtool_rx_flow_spec *fs,
struct hclge_fd_rule *rule)
{
rule->tuples.src_ip[IPV4_INDEX] =
@@ -6297,8 +6294,7 @@ static void hclge_fd_get_ip4_tuple(struct hclge_dev *hdev,
rule->tuples_mask.ether_proto = 0xFFFF;
}
-static void hclge_fd_get_tcpip6_tuple(struct hclge_dev *hdev,
- struct ethtool_rx_flow_spec *fs,
+static void hclge_fd_get_tcpip6_tuple(struct ethtool_rx_flow_spec *fs,
struct hclge_fd_rule *rule, u8 ip_proto)
{
be32_to_cpu_array(rule->tuples.src_ip, fs->h_u.tcp_ip6_spec.ip6src,
@@ -6327,8 +6323,7 @@ static void hclge_fd_get_tcpip6_tuple(struct hclge_dev *hdev,
rule->tuples_mask.ip_proto = 0xFF;
}
-static void hclge_fd_get_ip6_tuple(struct hclge_dev *hdev,
- struct ethtool_rx_flow_spec *fs,
+static void hclge_fd_get_ip6_tuple(struct ethtool_rx_flow_spec *fs,
struct hclge_fd_rule *rule)
{
be32_to_cpu_array(rule->tuples.src_ip, fs->h_u.usr_ip6_spec.ip6src,
@@ -6351,8 +6346,7 @@ static void hclge_fd_get_ip6_tuple(struct hclge_dev *hdev,
rule->tuples_mask.ether_proto = 0xFFFF;
}
-static void hclge_fd_get_ether_tuple(struct hclge_dev *hdev,
- struct ethtool_rx_flow_spec *fs,
+static void hclge_fd_get_ether_tuple(struct ethtool_rx_flow_spec *fs,
struct hclge_fd_rule *rule)
{
ether_addr_copy(rule->tuples.src_mac, fs->h_u.ether_spec.h_source);
@@ -6388,8 +6382,7 @@ static void hclge_fd_get_user_def_tuple(struct hclge_fd_user_def_info *info,
rule->ep.user_def = *info;
}
-static int hclge_fd_get_tuple(struct hclge_dev *hdev,
- struct ethtool_rx_flow_spec *fs,
+static int hclge_fd_get_tuple(struct ethtool_rx_flow_spec *fs,
struct hclge_fd_rule *rule,
struct hclge_fd_user_def_info *info)
{
@@ -6397,31 +6390,31 @@ static int hclge_fd_get_tuple(struct hclge_dev *hdev,
switch (flow_type) {
case SCTP_V4_FLOW:
- hclge_fd_get_tcpip4_tuple(hdev, fs, rule, IPPROTO_SCTP);
+ hclge_fd_get_tcpip4_tuple(fs, rule, IPPROTO_SCTP);
break;
case TCP_V4_FLOW:
- hclge_fd_get_tcpip4_tuple(hdev, fs, rule, IPPROTO_TCP);
+ hclge_fd_get_tcpip4_tuple(fs, rule, IPPROTO_TCP);
break;
case UDP_V4_FLOW:
- hclge_fd_get_tcpip4_tuple(hdev, fs, rule, IPPROTO_UDP);
+ hclge_fd_get_tcpip4_tuple(fs, rule, IPPROTO_UDP);
break;
case IP_USER_FLOW:
- hclge_fd_get_ip4_tuple(hdev, fs, rule);
+ hclge_fd_get_ip4_tuple(fs, rule);
break;
case SCTP_V6_FLOW:
- hclge_fd_get_tcpip6_tuple(hdev, fs, rule, IPPROTO_SCTP);
+ hclge_fd_get_tcpip6_tuple(fs, rule, IPPROTO_SCTP);
break;
case TCP_V6_FLOW:
- hclge_fd_get_tcpip6_tuple(hdev, fs, rule, IPPROTO_TCP);
+ hclge_fd_get_tcpip6_tuple(fs, rule, IPPROTO_TCP);
break;
case UDP_V6_FLOW:
- hclge_fd_get_tcpip6_tuple(hdev, fs, rule, IPPROTO_UDP);
+ hclge_fd_get_tcpip6_tuple(fs, rule, IPPROTO_UDP);
break;
case IPV6_USER_FLOW:
- hclge_fd_get_ip6_tuple(hdev, fs, rule);
+ hclge_fd_get_ip6_tuple(fs, rule);
break;
case ETHER_FLOW:
- hclge_fd_get_ether_tuple(hdev, fs, rule);
+ hclge_fd_get_ether_tuple(fs, rule);
break;
default:
return -EOPNOTSUPP;
@@ -6578,7 +6571,7 @@ static int hclge_add_fd_entry(struct hnae3_handle *handle,
if (!rule)
return -ENOMEM;
- ret = hclge_fd_get_tuple(hdev, fs, rule, &info);
+ ret = hclge_fd_get_tuple(fs, rule, &info);
if (ret) {
kfree(rule);
return ret;
@@ -7567,6 +7560,8 @@ static void hclge_enable_fd(struct hnae3_handle *handle, bool enable)
static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
{
+#define HCLGE_LINK_STATUS_WAIT_CNT 3
+
struct hclge_desc desc;
struct hclge_config_mac_mode_cmd *req =
(struct hclge_config_mac_mode_cmd *)desc.data;
@@ -7591,9 +7586,15 @@ static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
req->txrx_pad_fcs_loop_en = cpu_to_le32(loop_en);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
- if (ret)
+ if (ret) {
dev_err(&hdev->pdev->dev,
"mac enable fail, ret =%d.\n", ret);
+ return;
+ }
+
+ if (!enable)
+ hclge_mac_link_status_wait(hdev, HCLGE_LINK_STATUS_DOWN,
+ HCLGE_LINK_STATUS_WAIT_CNT);
}
static int hclge_config_switch_param(struct hclge_dev *hdev, int vfid,
@@ -7656,10 +7657,9 @@ static void hclge_phy_link_status_wait(struct hclge_dev *hdev,
} while (++i < HCLGE_PHY_LINK_STATUS_NUM);
}
-static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret)
+static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret,
+ int wait_cnt)
{
-#define HCLGE_MAC_LINK_STATUS_NUM 100
-
int link_status;
int i = 0;
int ret;
@@ -7672,13 +7672,15 @@ static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret)
return 0;
msleep(HCLGE_LINK_STATUS_MS);
- } while (++i < HCLGE_MAC_LINK_STATUS_NUM);
+ } while (++i < wait_cnt);
return -EBUSY;
}
static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en,
bool is_phy)
{
+#define HCLGE_MAC_LINK_STATUS_NUM 100
+
int link_ret;
link_ret = en ? HCLGE_LINK_STATUS_UP : HCLGE_LINK_STATUS_DOWN;
@@ -7686,7 +7688,8 @@ static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en,
if (is_phy)
hclge_phy_link_status_wait(hdev, link_ret);
- return hclge_mac_link_status_wait(hdev, link_ret);
+ return hclge_mac_link_status_wait(hdev, link_ret,
+ HCLGE_MAC_LINK_STATUS_NUM);
}
static int hclge_set_app_loopback(struct hclge_dev *hdev, bool en)
@@ -10924,9 +10927,12 @@ int hclge_cfg_flowctrl(struct hclge_dev *hdev)
u32 rx_pause, tx_pause;
u8 flowctl;
- if (!phydev->link || !phydev->autoneg)
+ if (!phydev->link)
return 0;
+ if (!phydev->autoneg)
+ return hclge_mac_pause_setup_hw(hdev);
+
local_advertising = linkmode_adv_to_lcl_adv_t(phydev->advertising);
if (phydev->pause)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 81aa6b0facf5..6a43d1515585 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -835,15 +835,10 @@ struct hclge_vf_vlan_cfg {
* Then for input key(k) and mask(v), we can calculate the value by
* the formulae:
* x = (~k) & v
- * y = (k ^ ~v) & k
+ * y = k & v
*/
-#define calc_x(x, k, v) (x = ~(k) & (v))
-#define calc_y(y, k, v) \
- do { \
- const typeof(k) _k_ = (k); \
- const typeof(v) _v_ = (v); \
- (y) = (_k_ ^ ~_v_) & (_k_); \
- } while (0)
+#define calc_x(x, k, v) ((x) = ~(k) & (v))
+#define calc_y(y, k, v) ((y) = (k) & (v))
#define HCLGE_MAC_STATS_FIELD_OFF(f) (offsetof(struct hclge_mac_stats, f))
#define HCLGE_STATS_READ(p, offset) (*(u64 *)((u8 *)(p) + (offset)))
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
index 922c0da3660c..c58c31221762 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
@@ -785,6 +785,7 @@ static void hclge_tm_tc_info_init(struct hclge_dev *hdev)
static void hclge_tm_pg_info_init(struct hclge_dev *hdev)
{
#define BW_PERCENT 100
+#define DEFAULT_BW_WEIGHT 1
u8 i;
@@ -806,7 +807,7 @@ static void hclge_tm_pg_info_init(struct hclge_dev *hdev)
for (k = 0; k < hdev->tm_info.num_tc; k++)
hdev->tm_info.pg_info[i].tc_dwrr[k] = BW_PERCENT;
for (; k < HNAE3_MAX_TC; k++)
- hdev->tm_info.pg_info[i].tc_dwrr[k] = 0;
+ hdev->tm_info.pg_info[i].tc_dwrr[k] = DEFAULT_BW_WEIGHT;
}
}
@@ -1484,7 +1485,11 @@ int hclge_tm_schd_setup_hw(struct hclge_dev *hdev)
return ret;
/* Cfg schd mode for each level schd */
- return hclge_tm_schd_mode_hw(hdev);
+ ret = hclge_tm_schd_mode_hw(hdev);
+ if (ret)
+ return ret;
+
+ return hclge_tm_flush_cfg(hdev, false);
}
static int hclge_pause_param_setup_hw(struct hclge_dev *hdev)
@@ -1548,7 +1553,7 @@ static int hclge_bp_setup_hw(struct hclge_dev *hdev, u8 tc)
return 0;
}
-static int hclge_mac_pause_setup_hw(struct hclge_dev *hdev)
+int hclge_mac_pause_setup_hw(struct hclge_dev *hdev)
{
bool tx_en, rx_en;
@@ -2113,3 +2118,28 @@ int hclge_tm_get_port_shaper(struct hclge_dev *hdev,
return 0;
}
+
+int hclge_tm_flush_cfg(struct hclge_dev *hdev, bool enable)
+{
+ struct hclge_desc desc;
+ int ret;
+
+ if (!hnae3_ae_dev_tm_flush_supported(hdev))
+ return 0;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_FLUSH, false);
+
+ desc.data[0] = cpu_to_le32(enable ? HCLGE_TM_FLUSH_EN_MSK : 0);
+
+ ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "failed to config tm flush, ret = %d\n", ret);
+ return ret;
+ }
+
+ if (enable)
+ msleep(HCLGE_TM_FLUSH_TIME_MS);
+
+ return ret;
+}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
index dd6f1fd486cf..53eec6df5194 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
@@ -33,6 +33,9 @@ enum hclge_opcode_type;
#define HCLGE_DSCP_MAP_TC_BD_NUM 2
#define HCLGE_DSCP_TC_SHIFT(n) (((n) & 1) * 4)
+#define HCLGE_TM_FLUSH_TIME_MS 10
+#define HCLGE_TM_FLUSH_EN_MSK BIT(0)
+
struct hclge_pg_to_pri_link_cmd {
u8 pg_id;
u8 rsvd1[3];
@@ -242,6 +245,7 @@ int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap,
u8 pfc_bitmap);
int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx);
int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr);
+int hclge_mac_pause_setup_hw(struct hclge_dev *hdev);
void hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats);
void hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats);
int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate);
@@ -272,4 +276,5 @@ int hclge_tm_get_port_shaper(struct hclge_dev *hdev,
struct hclge_tm_shaper_para *para);
int hclge_up_to_tc_map(struct hclge_dev *hdev);
int hclge_dscp_to_tc_map(struct hclge_dev *hdev);
+int hclge_tm_flush_cfg(struct hclge_dev *hdev, bool enable);
#endif
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
index dd08989a4c7c..34f02ca8d1d2 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
@@ -121,8 +121,7 @@ static struct hclgevf_dev *hclgevf_ae_get_hdev(struct hnae3_handle *handle)
return container_of(handle, struct hclgevf_dev, nic);
}
-static void hclgevf_update_stats(struct hnae3_handle *handle,
- struct net_device_stats *net_stats)
+static void hclgevf_update_stats(struct hnae3_handle *handle)
{
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
int status;
@@ -1645,8 +1644,7 @@ err_reset:
hclgevf_reset_err_handle(hdev);
}
-static enum hnae3_reset_type hclgevf_get_reset_level(struct hclgevf_dev *hdev,
- unsigned long *addr)
+static enum hnae3_reset_type hclgevf_get_reset_level(unsigned long *addr)
{
enum hnae3_reset_type rst_level = HNAE3_NONE_RESET;
@@ -1685,8 +1683,7 @@ static void hclgevf_reset_event(struct pci_dev *pdev,
if (hdev->default_reset_request)
hdev->reset_level =
- hclgevf_get_reset_level(hdev,
- &hdev->default_reset_request);
+ hclgevf_get_reset_level(&hdev->default_reset_request);
else
hdev->reset_level = HNAE3_VF_FUNC_RESET;
@@ -1828,7 +1825,7 @@ static void hclgevf_reset_service_task(struct hclgevf_dev *hdev)
hdev->last_reset_time = jiffies;
hdev->reset_type =
- hclgevf_get_reset_level(hdev, &hdev->reset_pending);
+ hclgevf_get_reset_level(&hdev->reset_pending);
if (hdev->reset_type != HNAE3_NONE_RESET)
hclgevf_reset(hdev);
} else if (test_and_clear_bit(HCLGEVF_RESET_REQUESTED,
@@ -2160,8 +2157,7 @@ static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev)
if (ret)
return ret;
- ret = hclge_comm_set_rss_input_tuple(&hdev->nic, &hdev->hw.hw,
- false, rss_cfg);
+ ret = hclge_comm_set_rss_input_tuple(&hdev->hw.hw, rss_cfg);
if (ret)
return ret;
}
diff --git a/drivers/net/ethernet/i825xx/82596.c b/drivers/net/ethernet/i825xx/82596.c
index 3ee89ae496d0..773d7aa29ef5 100644
--- a/drivers/net/ethernet/i825xx/82596.c
+++ b/drivers/net/ethernet/i825xx/82596.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-1.0+
/* 82596.c: A generic 82596 ethernet driver for linux. */
/*
Based on Apricot.c
@@ -31,9 +32,7 @@
Driver skeleton
Written 1993 by Donald Becker.
Copyright 1993 United States Government as represented by the Director,
- National Security Agency. This software may only be used and distributed
- according to the terms of the GNU General Public License as modified by SRC,
- incorporated herein by reference.
+ National Security Agency.
The author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
diff --git a/drivers/net/ethernet/i825xx/lasi_82596.c b/drivers/net/ethernet/i825xx/lasi_82596.c
index 0af70094aba3..3e53e0c243ba 100644
--- a/drivers/net/ethernet/i825xx/lasi_82596.c
+++ b/drivers/net/ethernet/i825xx/lasi_82596.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-1.0+
/* lasi_82596.c -- driver for the intel 82596 ethernet controller, as
munged into HPPA boxen .
@@ -59,9 +60,7 @@
Driver skeleton
Written 1993 by Donald Becker.
Copyright 1993 United States Government as represented by the Director,
- National Security Agency. This software may only be used and distributed
- according to the terms of the GNU General Public License as modified by SRC,
- incorporated herein by reference.
+ National Security Agency.
The author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
diff --git a/drivers/net/ethernet/i825xx/lib82596.c b/drivers/net/ethernet/i825xx/lib82596.c
index ca2fb303fcc6..67d248a7a6f4 100644
--- a/drivers/net/ethernet/i825xx/lib82596.c
+++ b/drivers/net/ethernet/i825xx/lib82596.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-1.0+
/* lasi_82596.c -- driver for the intel 82596 ethernet controller, as
munged into HPPA boxen .
@@ -59,9 +60,7 @@
Driver skeleton
Written 1993 by Donald Becker.
Copyright 1993 United States Government as represented by the Director,
- National Security Agency. This software may only be used and distributed
- according to the terms of the GNU General Public License as modified by SRC,
- incorporated herein by reference.
+ National Security Agency.
The author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
diff --git a/drivers/net/ethernet/i825xx/sun3_82586.c b/drivers/net/ethernet/i825xx/sun3_82586.c
index 3909c6a0af89..5e27470c6b1e 100644
--- a/drivers/net/ethernet/i825xx/sun3_82586.c
+++ b/drivers/net/ethernet/i825xx/sun3_82586.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Sun3 i82586 Ethernet driver
*
diff --git a/drivers/net/ethernet/i825xx/sun3_82586.h b/drivers/net/ethernet/i825xx/sun3_82586.h
index d82eca563266..d8e249d704a7 100644
--- a/drivers/net/ethernet/i825xx/sun3_82586.h
+++ b/drivers/net/ethernet/i825xx/sun3_82586.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Intel i82586 Ethernet definitions
*
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 113fcb3e353e..832a2ae01950 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -203,7 +203,7 @@ static inline void ibmveth_flush_buffer(void *addr, unsigned long length)
unsigned long offset;
for (offset = 0; offset < length; offset += SMP_CACHE_BYTES)
- asm("dcbfl %0,%1" :: "b" (addr), "r" (offset));
+ asm("dcbf %0,%1,1" :: "b" (addr), "r" (offset));
}
/* replenish the buffers for a pool. note that we don't need to
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index c63d3ec9d328..df76cdaddcfb 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -97,6 +97,8 @@ static int pending_scrq(struct ibmvnic_adapter *,
static union sub_crq *ibmvnic_next_scrq(struct ibmvnic_adapter *,
struct ibmvnic_sub_crq_queue *);
static int ibmvnic_poll(struct napi_struct *napi, int data);
+static int reset_sub_crq_queues(struct ibmvnic_adapter *adapter);
+static inline void reinit_init_done(struct ibmvnic_adapter *adapter);
static void send_query_map(struct ibmvnic_adapter *adapter);
static int send_request_map(struct ibmvnic_adapter *, dma_addr_t, u32, u8);
static int send_request_unmap(struct ibmvnic_adapter *, u8);
@@ -114,6 +116,7 @@ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter,
static void free_long_term_buff(struct ibmvnic_adapter *adapter,
struct ibmvnic_long_term_buff *ltb);
static void ibmvnic_disable_irqs(struct ibmvnic_adapter *adapter);
+static void flush_reset_queue(struct ibmvnic_adapter *adapter);
struct ibmvnic_stat {
char name[ETH_GSTRING_LEN];
@@ -1505,8 +1508,8 @@ static const char *adapter_state_to_string(enum vnic_state state)
static int ibmvnic_login(struct net_device *netdev)
{
+ unsigned long flags, timeout = msecs_to_jiffies(20000);
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
- unsigned long timeout = msecs_to_jiffies(20000);
int retry_count = 0;
int retries = 10;
bool retry;
@@ -1527,11 +1530,9 @@ static int ibmvnic_login(struct net_device *netdev)
if (!wait_for_completion_timeout(&adapter->init_done,
timeout)) {
- netdev_warn(netdev, "Login timed out, retrying...\n");
- retry = true;
- adapter->init_done_rc = 0;
- retry_count++;
- continue;
+ netdev_warn(netdev, "Login timed out\n");
+ adapter->login_pending = false;
+ goto partial_reset;
}
if (adapter->init_done_rc == ABORTED) {
@@ -1573,10 +1574,69 @@ static int ibmvnic_login(struct net_device *netdev)
"SCRQ irq initialization failed\n");
return rc;
}
+ /* Default/timeout error handling, reset and start fresh */
} else if (adapter->init_done_rc) {
netdev_warn(netdev, "Adapter login failed, init_done_rc = %d\n",
adapter->init_done_rc);
- return -EIO;
+
+partial_reset:
+ /* adapter login failed, so free any CRQs or sub-CRQs
+ * and register again before attempting to login again.
+ * If we don't do this then the VIOS may think that
+ * we are already logged in and reject any subsequent
+ * attempts
+ */
+ netdev_warn(netdev,
+ "Freeing and re-registering CRQs before attempting to login again\n");
+ retry = true;
+ adapter->init_done_rc = 0;
+ release_sub_crqs(adapter, true);
+ /* Much of this is similar logic as ibmvnic_probe(),
+ * we are essentially re-initializing communication
+ * with the server. We really should not run any
+ * resets/failovers here because this is already a form
+ * of reset and we do not want parallel resets occurring
+ */
+ do {
+ reinit_init_done(adapter);
+ /* Clear any failovers we got in the previous
+ * pass since we are re-initializing the CRQ
+ */
+ adapter->failover_pending = false;
+ release_crq_queue(adapter);
+ /* If we don't sleep here then we risk an
+ * unnecessary failover event from the VIOS.
+ * This is a known VIOS issue caused by a vnic
+ * device freeing and registering a CRQ too
+ * quickly.
+ */
+ msleep(1500);
+ /* Avoid any resets, since we are currently
+ * resetting.
+ */
+ spin_lock_irqsave(&adapter->rwi_lock, flags);
+ flush_reset_queue(adapter);
+ spin_unlock_irqrestore(&adapter->rwi_lock,
+ flags);
+
+ rc = init_crq_queue(adapter);
+ if (rc) {
+ netdev_err(netdev, "login recovery: init CRQ failed %d\n",
+ rc);
+ return -EIO;
+ }
+
+ rc = ibmvnic_reset_init(adapter, false);
+ if (rc)
+ netdev_err(netdev, "login recovery: Reset init failed %d\n",
+ rc);
+ /* IBMVNIC_CRQ_INIT will return EAGAIN if it
+ * fails, since ibmvnic_reset_init will free
+ * irq's in failure, we won't be able to receive
+ * new CRQs so we need to keep trying. probe()
+ * handles this similarly.
+ */
+ } while (rc == -EAGAIN && retry_count++ < retries);
}
} while (retry);
@@ -1588,12 +1648,22 @@ static int ibmvnic_login(struct net_device *netdev)
static void release_login_buffer(struct ibmvnic_adapter *adapter)
{
+ if (!adapter->login_buf)
+ return;
+
+ dma_unmap_single(&adapter->vdev->dev, adapter->login_buf_token,
+ adapter->login_buf_sz, DMA_TO_DEVICE);
kfree(adapter->login_buf);
adapter->login_buf = NULL;
}
static void release_login_rsp_buffer(struct ibmvnic_adapter *adapter)
{
+ if (!adapter->login_rsp_buf)
+ return;
+
+ dma_unmap_single(&adapter->vdev->dev, adapter->login_rsp_buf_token,
+ adapter->login_rsp_buf_sz, DMA_FROM_DEVICE);
kfree(adapter->login_rsp_buf);
adapter->login_rsp_buf = NULL;
}
@@ -1816,7 +1886,14 @@ static int __ibmvnic_open(struct net_device *netdev)
if (prev_state == VNIC_CLOSED)
enable_irq(adapter->tx_scrq[i]->irq);
enable_scrq_irq(adapter, adapter->tx_scrq[i]);
- netdev_tx_reset_queue(netdev_get_tx_queue(netdev, i));
+ /* netdev_tx_reset_queue will reset dql stats. During NON_FATAL
+ * resets, don't reset the stats because there could be batched
+ * skb's waiting to be sent. If we reset dql stats, we risk
+ * num_completed being greater than num_queued. This will cause
+ * a BUG_ON in dql_completed().
+ */
+ if (adapter->reset_reason != VNIC_RESET_NON_FATAL)
+ netdev_tx_reset_queue(netdev_get_tx_queue(netdev, i));
}
rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_UP);
@@ -4823,11 +4900,14 @@ static int send_login(struct ibmvnic_adapter *adapter)
if (rc) {
adapter->login_pending = false;
netdev_err(adapter->netdev, "Failed to send login, rc=%d\n", rc);
- goto buf_rsp_map_failed;
+ goto buf_send_failed;
}
return 0;
+buf_send_failed:
+ dma_unmap_single(dev, rsp_buffer_token, rsp_buffer_size,
+ DMA_FROM_DEVICE);
buf_rsp_map_failed:
kfree(login_rsp_buffer);
adapter->login_rsp_buf = NULL;
@@ -5389,6 +5469,7 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
int num_tx_pools;
int num_rx_pools;
u64 *size_array;
+ u32 rsp_len;
int i;
/* CHECK: Test/set of login_pending does not need to be atomic
@@ -5400,11 +5481,6 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
}
adapter->login_pending = false;
- dma_unmap_single(dev, adapter->login_buf_token, adapter->login_buf_sz,
- DMA_TO_DEVICE);
- dma_unmap_single(dev, adapter->login_rsp_buf_token,
- adapter->login_rsp_buf_sz, DMA_FROM_DEVICE);
-
/* If the number of queues requested can't be allocated by the
* server, the login response will return with code 1. We will need
* to resend the login buffer with fewer queues requested.
@@ -5440,6 +5516,23 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
ibmvnic_reset(adapter, VNIC_RESET_FATAL);
return -EIO;
}
+
+ rsp_len = be32_to_cpu(login_rsp->len);
+ if (be32_to_cpu(login->login_rsp_len) < rsp_len ||
+ rsp_len <= be32_to_cpu(login_rsp->off_txsubm_subcrqs) ||
+ rsp_len <= be32_to_cpu(login_rsp->off_rxadd_subcrqs) ||
+ rsp_len <= be32_to_cpu(login_rsp->off_rxadd_buff_size) ||
+ rsp_len <= be32_to_cpu(login_rsp->off_supp_tx_desc)) {
+ /* This can happen if a login request times out and there are
+ * 2 outstanding login requests sent, the LOGIN_RSP crq
+ * could have been for the older login request. So we are
+ * parsing the newer response buffer which may be incomplete
+ */
+ dev_err(dev, "FATAL: Login rsp offsets/lengths invalid\n");
+ ibmvnic_reset(adapter, VNIC_RESET_FATAL);
+ return -EIO;
+ }
+
size_array = (u64 *)((u8 *)(adapter->login_rsp_buf) +
be32_to_cpu(adapter->login_rsp_buf->off_rxadd_buff_size));
/* variable buffer sizes are not supported, so just read the
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index bd7ef59b1f2e..771a3c909c45 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -4198,7 +4198,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
/**
* e1000e_trigger_lsc - trigger an LSC interrupt
- * @adapter:
+ * @adapter: board private structure
*
* Fire a link status change interrupt to start the watchdog.
**/
diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
index 9954493cd448..62497f5565c5 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
@@ -1839,7 +1839,7 @@ void i40e_dbg_pf_exit(struct i40e_pf *pf)
void i40e_dbg_init(void)
{
i40e_dbg_root = debugfs_create_dir(i40e_driver_name, NULL);
- if (!i40e_dbg_root)
+ if (IS_ERR(i40e_dbg_root))
pr_info("init of debugfs failed\n");
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index b847bd105b16..a86bfa3bba74 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -1788,12 +1788,6 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
- if (ether_addr_equal(netdev->dev_addr, addr->sa_data)) {
- netdev_info(netdev, "already using mac address %pM\n",
- addr->sa_data);
- return 0;
- }
-
if (test_bit(__I40E_DOWN, pf->state) ||
test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))
return -EADDRNOTAVAIL;
@@ -2615,7 +2609,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
retval = i40e_correct_mac_vlan_filters
(vsi, &tmp_add_list, &tmp_del_list,
vlan_filters);
- else
+ else if (pf->vf)
retval = i40e_correct_vf_mac_vlan_filters
(vsi, &tmp_add_list, &tmp_del_list,
vlan_filters, pf->vf[vsi->vf_id].trusted);
@@ -2788,7 +2782,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
}
/* if the VF is not trusted do not do promisc */
- if ((vsi->type == I40E_VSI_SRIOV) && !pf->vf[vsi->vf_id].trusted) {
+ if (vsi->type == I40E_VSI_SRIOV && pf->vf &&
+ !pf->vf[vsi->vf_id].trusted) {
clear_bit(__I40E_VSI_OVERFLOW_PROMISC, vsi->state);
goto out;
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c
index 9da0c87f0328..f99c1f7fec40 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c
@@ -210,11 +210,11 @@ read_nvm_exit:
* @hw: pointer to the HW structure.
* @module_pointer: module pointer location in words from the NVM beginning
* @offset: offset in words from module start
- * @words: number of words to write
- * @data: buffer with words to write to the Shadow RAM
+ * @words: number of words to read
+ * @data: buffer with words to read to the Shadow RAM
* @last_command: tells the AdminQ that this is the last command
*
- * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
+ * Reads a 16 bit words buffer to the Shadow RAM using the admin command.
**/
static int i40e_read_nvm_aq(struct i40e_hw *hw,
u8 module_pointer, u32 offset,
@@ -234,18 +234,18 @@ static int i40e_read_nvm_aq(struct i40e_hw *hw,
*/
if ((offset + words) > hw->nvm.sr_size)
i40e_debug(hw, I40E_DEBUG_NVM,
- "NVM write error: offset %d beyond Shadow RAM limit %d\n",
+ "NVM read error: offset %d beyond Shadow RAM limit %d\n",
(offset + words), hw->nvm.sr_size);
else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
- /* We can write only up to 4KB (one sector), in one AQ write */
+ /* We can read only up to 4KB (one sector), in one AQ write */
i40e_debug(hw, I40E_DEBUG_NVM,
- "NVM write fail error: tried to write %d words, limit is %d.\n",
+ "NVM read fail error: tried to read %d words, limit is %d.\n",
words, I40E_SR_SECTOR_SIZE_IN_WORDS);
else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
!= (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
- /* A single write cannot spread over two sectors */
+ /* A single read cannot spread over two sectors */
i40e_debug(hw, I40E_DEBUG_NVM,
- "NVM write error: cannot spread over two sectors in a single write offset=%d words=%d\n",
+ "NVM read error: cannot spread over two sectors in a single read offset=%d words=%d\n",
offset, words);
else
ret_code = i40e_aq_read_nvm(hw, module_pointer,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
index cd7b52fb6b46..05ec1181471e 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
@@ -582,7 +582,7 @@ static void i40e_clean_xdp_tx_buffer(struct i40e_ring *tx_ring,
* @vsi: Current VSI
* @tx_ring: XDP Tx ring
*
- * Returns true if cleanup/tranmission is done.
+ * Returns true if cleanup/transmission is done.
**/
bool i40e_clean_xdp_tx_irq(struct i40e_vsi *vsi, struct i40e_ring *tx_ring)
{
diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h
index 39d0fe76a38f..8cbdebc5b698 100644
--- a/drivers/net/ethernet/intel/iavf/iavf.h
+++ b/drivers/net/ethernet/intel/iavf/iavf.h
@@ -255,8 +255,10 @@ struct iavf_adapter {
struct workqueue_struct *wq;
struct work_struct reset_task;
struct work_struct adminq_task;
+ struct work_struct finish_config;
struct delayed_work client_task;
wait_queue_head_t down_waitqueue;
+ wait_queue_head_t reset_waitqueue;
wait_queue_head_t vc_waitqueue;
struct iavf_q_vector *q_vectors;
struct list_head vlan_filter_list;
@@ -518,14 +520,12 @@ int iavf_up(struct iavf_adapter *adapter);
void iavf_down(struct iavf_adapter *adapter);
int iavf_process_config(struct iavf_adapter *adapter);
int iavf_parse_vf_resource_msg(struct iavf_adapter *adapter);
-void iavf_schedule_reset(struct iavf_adapter *adapter);
+void iavf_schedule_reset(struct iavf_adapter *adapter, u64 flags);
void iavf_schedule_request_stats(struct iavf_adapter *adapter);
+void iavf_schedule_finish_config(struct iavf_adapter *adapter);
void iavf_reset(struct iavf_adapter *adapter);
void iavf_set_ethtool_ops(struct net_device *netdev);
void iavf_update_stats(struct iavf_adapter *adapter);
-void iavf_reset_interrupt_capability(struct iavf_adapter *adapter);
-int iavf_init_interrupt_scheme(struct iavf_adapter *adapter);
-void iavf_irq_enable_queues(struct iavf_adapter *adapter);
void iavf_free_all_tx_resources(struct iavf_adapter *adapter);
void iavf_free_all_rx_resources(struct iavf_adapter *adapter);
@@ -579,17 +579,11 @@ void iavf_enable_vlan_stripping_v2(struct iavf_adapter *adapter, u16 tpid);
void iavf_disable_vlan_stripping_v2(struct iavf_adapter *adapter, u16 tpid);
void iavf_enable_vlan_insertion_v2(struct iavf_adapter *adapter, u16 tpid);
void iavf_disable_vlan_insertion_v2(struct iavf_adapter *adapter, u16 tpid);
-int iavf_replace_primary_mac(struct iavf_adapter *adapter,
- const u8 *new_mac);
-void
-iavf_set_vlan_offload_features(struct iavf_adapter *adapter,
- netdev_features_t prev_features,
- netdev_features_t features);
void iavf_add_fdir_filter(struct iavf_adapter *adapter);
void iavf_del_fdir_filter(struct iavf_adapter *adapter);
void iavf_add_adv_rss_cfg(struct iavf_adapter *adapter);
void iavf_del_adv_rss_cfg(struct iavf_adapter *adapter);
struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
const u8 *macaddr);
-int iavf_lock_timeout(struct mutex *lock, unsigned int msecs);
+int iavf_wait_for_reset(struct iavf_adapter *adapter);
#endif /* _IAVF_H_ */
diff --git a/drivers/net/ethernet/intel/iavf/iavf_alloc.h b/drivers/net/ethernet/intel/iavf/iavf_alloc.h
index 2711573c14ec..162ea70685a6 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_alloc.h
+++ b/drivers/net/ethernet/intel/iavf/iavf_alloc.h
@@ -28,7 +28,6 @@ enum iavf_status iavf_free_dma_mem(struct iavf_hw *hw,
struct iavf_dma_mem *mem);
enum iavf_status iavf_allocate_virt_mem(struct iavf_hw *hw,
struct iavf_virt_mem *mem, u32 size);
-enum iavf_status iavf_free_virt_mem(struct iavf_hw *hw,
- struct iavf_virt_mem *mem);
+void iavf_free_virt_mem(struct iavf_hw *hw, struct iavf_virt_mem *mem);
#endif /* _IAVF_ALLOC_H_ */
diff --git a/drivers/net/ethernet/intel/iavf/iavf_common.c b/drivers/net/ethernet/intel/iavf/iavf_common.c
index dd11dbbd5551..1afd761d8052 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_common.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_common.c
@@ -35,7 +35,6 @@ enum iavf_status iavf_set_mac_type(struct iavf_hw *hw)
status = IAVF_ERR_DEVICE_NOT_SUPPORTED;
}
- hw_dbg(hw, "found mac: %d, returns: %d\n", hw->mac.type, status);
return status;
}
@@ -398,23 +397,6 @@ static enum iavf_status iavf_aq_get_set_rss_lut(struct iavf_hw *hw,
}
/**
- * iavf_aq_get_rss_lut
- * @hw: pointer to the hardware structure
- * @vsi_id: vsi fw index
- * @pf_lut: for PF table set true, for VSI table set false
- * @lut: pointer to the lut buffer provided by the caller
- * @lut_size: size of the lut buffer
- *
- * get the RSS lookup table, PF or VSI type
- **/
-enum iavf_status iavf_aq_get_rss_lut(struct iavf_hw *hw, u16 vsi_id,
- bool pf_lut, u8 *lut, u16 lut_size)
-{
- return iavf_aq_get_set_rss_lut(hw, vsi_id, pf_lut, lut, lut_size,
- false);
-}
-
-/**
* iavf_aq_set_rss_lut
* @hw: pointer to the hardware structure
* @vsi_id: vsi fw index
@@ -473,19 +455,6 @@ iavf_status iavf_aq_get_set_rss_key(struct iavf_hw *hw, u16 vsi_id,
}
/**
- * iavf_aq_get_rss_key
- * @hw: pointer to the hw struct
- * @vsi_id: vsi fw index
- * @key: pointer to key info struct
- *
- **/
-enum iavf_status iavf_aq_get_rss_key(struct iavf_hw *hw, u16 vsi_id,
- struct iavf_aqc_get_set_rss_key_data *key)
-{
- return iavf_aq_get_set_rss_key(hw, vsi_id, key, false);
-}
-
-/**
* iavf_aq_set_rss_key
* @hw: pointer to the hw struct
* @vsi_id: vsi fw index
@@ -828,17 +797,3 @@ void iavf_vf_parse_hw_config(struct iavf_hw *hw,
vsi_res++;
}
}
-
-/**
- * iavf_vf_reset
- * @hw: pointer to the hardware structure
- *
- * Send a VF_RESET message to the PF. Does not wait for response from PF
- * as none will be forthcoming. Immediately after calling this function,
- * the admin queue should be shut down and (optionally) reinitialized.
- **/
-enum iavf_status iavf_vf_reset(struct iavf_hw *hw)
-{
- return iavf_aq_send_msg_to_pf(hw, VIRTCHNL_OP_RESET_VF,
- 0, NULL, 0, NULL);
-}
diff --git a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c
index 6f171d1d85b7..a34303ad057d 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c
@@ -484,6 +484,7 @@ static int iavf_set_priv_flags(struct net_device *netdev, u32 flags)
{
struct iavf_adapter *adapter = netdev_priv(netdev);
u32 orig_flags, new_flags, changed_flags;
+ int ret = 0;
u32 i;
orig_flags = READ_ONCE(adapter->flags);
@@ -531,12 +532,14 @@ static int iavf_set_priv_flags(struct net_device *netdev, u32 flags)
/* issue a reset to force legacy-rx change to take effect */
if (changed_flags & IAVF_FLAG_LEGACY_RX) {
if (netif_running(netdev)) {
- adapter->flags |= IAVF_FLAG_RESET_NEEDED;
- queue_work(adapter->wq, &adapter->reset_task);
+ iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
+ ret = iavf_wait_for_reset(adapter);
+ if (ret)
+ netdev_warn(netdev, "Changing private flags timeout or interrupted waiting for reset");
}
}
- return 0;
+ return ret;
}
/**
@@ -627,6 +630,7 @@ static int iavf_set_ringparam(struct net_device *netdev,
{
struct iavf_adapter *adapter = netdev_priv(netdev);
u32 new_rx_count, new_tx_count;
+ int ret = 0;
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
@@ -671,11 +675,13 @@ static int iavf_set_ringparam(struct net_device *netdev,
}
if (netif_running(netdev)) {
- adapter->flags |= IAVF_FLAG_RESET_NEEDED;
- queue_work(adapter->wq, &adapter->reset_task);
+ iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
+ ret = iavf_wait_for_reset(adapter);
+ if (ret)
+ netdev_warn(netdev, "Changing ring parameters timeout or interrupted waiting for reset");
}
- return 0;
+ return ret;
}
/**
@@ -1283,6 +1289,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
fltr->ip_mask.src_port = fsp->m_u.tcp_ip4_spec.psrc;
fltr->ip_mask.dst_port = fsp->m_u.tcp_ip4_spec.pdst;
fltr->ip_mask.tos = fsp->m_u.tcp_ip4_spec.tos;
+ fltr->ip_ver = 4;
break;
case AH_V4_FLOW:
case ESP_V4_FLOW:
@@ -1294,6 +1301,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
fltr->ip_mask.v4_addrs.dst_ip = fsp->m_u.ah_ip4_spec.ip4dst;
fltr->ip_mask.spi = fsp->m_u.ah_ip4_spec.spi;
fltr->ip_mask.tos = fsp->m_u.ah_ip4_spec.tos;
+ fltr->ip_ver = 4;
break;
case IPV4_USER_FLOW:
fltr->ip_data.v4_addrs.src_ip = fsp->h_u.usr_ip4_spec.ip4src;
@@ -1306,6 +1314,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
fltr->ip_mask.l4_header = fsp->m_u.usr_ip4_spec.l4_4_bytes;
fltr->ip_mask.tos = fsp->m_u.usr_ip4_spec.tos;
fltr->ip_mask.proto = fsp->m_u.usr_ip4_spec.proto;
+ fltr->ip_ver = 4;
break;
case TCP_V6_FLOW:
case UDP_V6_FLOW:
@@ -1324,6 +1333,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
fltr->ip_mask.src_port = fsp->m_u.tcp_ip6_spec.psrc;
fltr->ip_mask.dst_port = fsp->m_u.tcp_ip6_spec.pdst;
fltr->ip_mask.tclass = fsp->m_u.tcp_ip6_spec.tclass;
+ fltr->ip_ver = 6;
break;
case AH_V6_FLOW:
case ESP_V6_FLOW:
@@ -1339,6 +1349,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
sizeof(struct in6_addr));
fltr->ip_mask.spi = fsp->m_u.ah_ip6_spec.spi;
fltr->ip_mask.tclass = fsp->m_u.ah_ip6_spec.tclass;
+ fltr->ip_ver = 6;
break;
case IPV6_USER_FLOW:
memcpy(&fltr->ip_data.v6_addrs.src_ip, fsp->h_u.usr_ip6_spec.ip6src,
@@ -1355,6 +1366,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
fltr->ip_mask.l4_header = fsp->m_u.usr_ip6_spec.l4_4_bytes;
fltr->ip_mask.tclass = fsp->m_u.usr_ip6_spec.tclass;
fltr->ip_mask.proto = fsp->m_u.usr_ip6_spec.l4_proto;
+ fltr->ip_ver = 6;
break;
case ETHER_FLOW:
fltr->eth_data.etype = fsp->h_u.ether_spec.h_proto;
@@ -1365,6 +1377,10 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
return -EINVAL;
}
+ err = iavf_validate_fdir_fltr_masks(adapter, fltr);
+ if (err)
+ return err;
+
if (iavf_fdir_is_dup_fltr(adapter, fltr))
return -EEXIST;
@@ -1395,14 +1411,15 @@ static int iavf_add_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx
if (fsp->flow_type & FLOW_MAC_EXT)
return -EINVAL;
+ spin_lock_bh(&adapter->fdir_fltr_lock);
if (adapter->fdir_active_fltr >= IAVF_MAX_FDIR_FILTERS) {
+ spin_unlock_bh(&adapter->fdir_fltr_lock);
dev_err(&adapter->pdev->dev,
"Unable to add Flow Director filter because VF reached the limit of max allowed filters (%u)\n",
IAVF_MAX_FDIR_FILTERS);
return -ENOSPC;
}
- spin_lock_bh(&adapter->fdir_fltr_lock);
if (iavf_find_fdir_fltr_by_loc(adapter, fsp->location)) {
dev_err(&adapter->pdev->dev, "Failed to add Flow Director filter, it already exists\n");
spin_unlock_bh(&adapter->fdir_fltr_lock);
@@ -1775,7 +1792,9 @@ static int iavf_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
case ETHTOOL_GRXCLSRLCNT:
if (!FDIR_FLTR_SUPPORT(adapter))
break;
+ spin_lock_bh(&adapter->fdir_fltr_lock);
cmd->rule_cnt = adapter->fdir_active_fltr;
+ spin_unlock_bh(&adapter->fdir_fltr_lock);
cmd->data = IAVF_MAX_FDIR_FILTERS;
ret = 0;
break;
@@ -1830,7 +1849,7 @@ static int iavf_set_channels(struct net_device *netdev,
{
struct iavf_adapter *adapter = netdev_priv(netdev);
u32 num_req = ch->combined_count;
- int i;
+ int ret = 0;
if ((adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) &&
adapter->num_tc) {
@@ -1852,22 +1871,13 @@ static int iavf_set_channels(struct net_device *netdev,
adapter->num_req_queues = num_req;
adapter->flags |= IAVF_FLAG_REINIT_ITR_NEEDED;
- iavf_schedule_reset(adapter);
+ iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
- /* wait for the reset is done */
- for (i = 0; i < IAVF_RESET_WAIT_COMPLETE_COUNT; i++) {
- msleep(IAVF_RESET_WAIT_MS);
- if (adapter->flags & IAVF_FLAG_RESET_PENDING)
- continue;
- break;
- }
- if (i == IAVF_RESET_WAIT_COMPLETE_COUNT) {
- adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
- adapter->num_active_queues = num_req;
- return -EOPNOTSUPP;
- }
+ ret = iavf_wait_for_reset(adapter);
+ if (ret)
+ netdev_warn(netdev, "Changing channel count timeout or interrupted waiting for reset");
- return 0;
+ return ret;
}
/**
diff --git a/drivers/net/ethernet/intel/iavf/iavf_fdir.c b/drivers/net/ethernet/intel/iavf/iavf_fdir.c
index 6146203efd84..03e774bd2a5b 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_fdir.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_fdir.c
@@ -18,6 +18,79 @@ static const struct in6_addr ipv6_addr_full_mask = {
}
};
+static const struct in6_addr ipv6_addr_zero_mask = {
+ .in6_u = {
+ .u6_addr8 = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }
+ }
+};
+
+/**
+ * iavf_validate_fdir_fltr_masks - validate Flow Director filter fields masks
+ * @adapter: pointer to the VF adapter structure
+ * @fltr: Flow Director filter data structure
+ *
+ * Returns 0 if all masks of packet fields are either full or empty. Returns
+ * error on at least one partial mask.
+ */
+int iavf_validate_fdir_fltr_masks(struct iavf_adapter *adapter,
+ struct iavf_fdir_fltr *fltr)
+{
+ if (fltr->eth_mask.etype && fltr->eth_mask.etype != htons(U16_MAX))
+ goto partial_mask;
+
+ if (fltr->ip_ver == 4) {
+ if (fltr->ip_mask.v4_addrs.src_ip &&
+ fltr->ip_mask.v4_addrs.src_ip != htonl(U32_MAX))
+ goto partial_mask;
+
+ if (fltr->ip_mask.v4_addrs.dst_ip &&
+ fltr->ip_mask.v4_addrs.dst_ip != htonl(U32_MAX))
+ goto partial_mask;
+
+ if (fltr->ip_mask.tos && fltr->ip_mask.tos != U8_MAX)
+ goto partial_mask;
+ } else if (fltr->ip_ver == 6) {
+ if (memcmp(&fltr->ip_mask.v6_addrs.src_ip, &ipv6_addr_zero_mask,
+ sizeof(struct in6_addr)) &&
+ memcmp(&fltr->ip_mask.v6_addrs.src_ip, &ipv6_addr_full_mask,
+ sizeof(struct in6_addr)))
+ goto partial_mask;
+
+ if (memcmp(&fltr->ip_mask.v6_addrs.dst_ip, &ipv6_addr_zero_mask,
+ sizeof(struct in6_addr)) &&
+ memcmp(&fltr->ip_mask.v6_addrs.dst_ip, &ipv6_addr_full_mask,
+ sizeof(struct in6_addr)))
+ goto partial_mask;
+
+ if (fltr->ip_mask.tclass && fltr->ip_mask.tclass != U8_MAX)
+ goto partial_mask;
+ }
+
+ if (fltr->ip_mask.proto && fltr->ip_mask.proto != U8_MAX)
+ goto partial_mask;
+
+ if (fltr->ip_mask.src_port && fltr->ip_mask.src_port != htons(U16_MAX))
+ goto partial_mask;
+
+ if (fltr->ip_mask.dst_port && fltr->ip_mask.dst_port != htons(U16_MAX))
+ goto partial_mask;
+
+ if (fltr->ip_mask.spi && fltr->ip_mask.spi != htonl(U32_MAX))
+ goto partial_mask;
+
+ if (fltr->ip_mask.l4_header &&
+ fltr->ip_mask.l4_header != htonl(U32_MAX))
+ goto partial_mask;
+
+ return 0;
+
+partial_mask:
+ dev_err(&adapter->pdev->dev, "Failed to add Flow Director filter, partial masks are not supported\n");
+ return -EOPNOTSUPP;
+}
+
/**
* iavf_pkt_udp_no_pay_len - the length of UDP packet without payload
* @fltr: Flow Director filter data structure
@@ -263,8 +336,6 @@ iavf_fill_fdir_ip4_hdr(struct iavf_fdir_fltr *fltr,
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, DST);
}
- fltr->ip_ver = 4;
-
return 0;
}
@@ -309,8 +380,6 @@ iavf_fill_fdir_ip6_hdr(struct iavf_fdir_fltr *fltr,
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, DST);
}
- fltr->ip_ver = 6;
-
return 0;
}
@@ -722,7 +791,9 @@ void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *f
bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr)
{
struct iavf_fdir_fltr *tmp;
+ bool ret = false;
+ spin_lock_bh(&adapter->fdir_fltr_lock);
list_for_each_entry(tmp, &adapter->fdir_list_head, list) {
if (tmp->flow_type != fltr->flow_type)
continue;
@@ -732,11 +803,14 @@ bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *
!memcmp(&tmp->ip_data, &fltr->ip_data,
sizeof(fltr->ip_data)) &&
!memcmp(&tmp->ext_data, &fltr->ext_data,
- sizeof(fltr->ext_data)))
- return true;
+ sizeof(fltr->ext_data))) {
+ ret = true;
+ break;
+ }
}
+ spin_unlock_bh(&adapter->fdir_fltr_lock);
- return false;
+ return ret;
}
/**
diff --git a/drivers/net/ethernet/intel/iavf/iavf_fdir.h b/drivers/net/ethernet/intel/iavf/iavf_fdir.h
index 33c55c366315..9eb9f73f6adf 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_fdir.h
+++ b/drivers/net/ethernet/intel/iavf/iavf_fdir.h
@@ -110,6 +110,8 @@ struct iavf_fdir_fltr {
struct virtchnl_fdir_add vc_add_msg;
};
+int iavf_validate_fdir_fltr_masks(struct iavf_adapter *adapter,
+ struct iavf_fdir_fltr *fltr);
int iavf_fill_fdir_add_msg(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 4a66873882d1..9610ca770349 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -167,6 +167,45 @@ static struct iavf_adapter *iavf_pdev_to_adapter(struct pci_dev *pdev)
}
/**
+ * iavf_is_reset_in_progress - Check if a reset is in progress
+ * @adapter: board private structure
+ */
+static bool iavf_is_reset_in_progress(struct iavf_adapter *adapter)
+{
+ if (adapter->state == __IAVF_RESETTING ||
+ adapter->flags & (IAVF_FLAG_RESET_PENDING |
+ IAVF_FLAG_RESET_NEEDED))
+ return true;
+
+ return false;
+}
+
+/**
+ * iavf_wait_for_reset - Wait for reset to finish.
+ * @adapter: board private structure
+ *
+ * Returns 0 if reset finished successfully, negative on timeout or interrupt.
+ */
+int iavf_wait_for_reset(struct iavf_adapter *adapter)
+{
+ int ret = wait_event_interruptible_timeout(adapter->reset_waitqueue,
+ !iavf_is_reset_in_progress(adapter),
+ msecs_to_jiffies(5000));
+
+ /* If ret < 0 then it means wait was interrupted.
+ * If ret == 0 then it means we got a timeout while waiting
+ * for reset to finish.
+ * If ret > 0 it means reset has finished.
+ */
+ if (ret > 0)
+ return 0;
+ else if (ret < 0)
+ return -EINTR;
+ else
+ return -EBUSY;
+}
+
+/**
* iavf_allocate_dma_mem_d - OS specific memory alloc for shared code
* @hw: pointer to the HW structure
* @mem: ptr to mem struct to fill out
@@ -192,12 +231,11 @@ enum iavf_status iavf_allocate_dma_mem_d(struct iavf_hw *hw,
}
/**
- * iavf_free_dma_mem_d - OS specific memory free for shared code
+ * iavf_free_dma_mem - wrapper for DMA memory freeing
* @hw: pointer to the HW structure
* @mem: ptr to mem struct to free
**/
-enum iavf_status iavf_free_dma_mem_d(struct iavf_hw *hw,
- struct iavf_dma_mem *mem)
+enum iavf_status iavf_free_dma_mem(struct iavf_hw *hw, struct iavf_dma_mem *mem)
{
struct iavf_adapter *adapter = (struct iavf_adapter *)hw->back;
@@ -209,13 +247,13 @@ enum iavf_status iavf_free_dma_mem_d(struct iavf_hw *hw,
}
/**
- * iavf_allocate_virt_mem_d - OS specific memory alloc for shared code
+ * iavf_allocate_virt_mem - virt memory alloc wrapper
* @hw: pointer to the HW structure
* @mem: ptr to mem struct to fill out
* @size: size of memory requested
**/
-enum iavf_status iavf_allocate_virt_mem_d(struct iavf_hw *hw,
- struct iavf_virt_mem *mem, u32 size)
+enum iavf_status iavf_allocate_virt_mem(struct iavf_hw *hw,
+ struct iavf_virt_mem *mem, u32 size)
{
if (!mem)
return IAVF_ERR_PARAM;
@@ -230,20 +268,13 @@ enum iavf_status iavf_allocate_virt_mem_d(struct iavf_hw *hw,
}
/**
- * iavf_free_virt_mem_d - OS specific memory free for shared code
+ * iavf_free_virt_mem - virt memory free wrapper
* @hw: pointer to the HW structure
* @mem: ptr to mem struct to free
**/
-enum iavf_status iavf_free_virt_mem_d(struct iavf_hw *hw,
- struct iavf_virt_mem *mem)
+void iavf_free_virt_mem(struct iavf_hw *hw, struct iavf_virt_mem *mem)
{
- if (!mem)
- return IAVF_ERR_PARAM;
-
- /* it's ok to kfree a NULL pointer */
kfree(mem->va);
-
- return 0;
}
/**
@@ -253,7 +284,7 @@ enum iavf_status iavf_free_virt_mem_d(struct iavf_hw *hw,
*
* Returns 0 on success, negative on failure
**/
-int iavf_lock_timeout(struct mutex *lock, unsigned int msecs)
+static int iavf_lock_timeout(struct mutex *lock, unsigned int msecs)
{
unsigned int wait, delay = 10;
@@ -270,12 +301,14 @@ int iavf_lock_timeout(struct mutex *lock, unsigned int msecs)
/**
* iavf_schedule_reset - Set the flags and schedule a reset event
* @adapter: board private structure
+ * @flags: IAVF_FLAG_RESET_PENDING or IAVF_FLAG_RESET_NEEDED
**/
-void iavf_schedule_reset(struct iavf_adapter *adapter)
+void iavf_schedule_reset(struct iavf_adapter *adapter, u64 flags)
{
- if (!(adapter->flags &
- (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED))) {
- adapter->flags |= IAVF_FLAG_RESET_NEEDED;
+ if (!test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section) &&
+ !(adapter->flags &
+ (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED))) {
+ adapter->flags |= flags;
queue_work(adapter->wq, &adapter->reset_task);
}
}
@@ -303,7 +336,7 @@ static void iavf_tx_timeout(struct net_device *netdev, unsigned int txqueue)
struct iavf_adapter *adapter = netdev_priv(netdev);
adapter->tx_timeout_count++;
- iavf_schedule_reset(adapter);
+ iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
}
/**
@@ -362,7 +395,7 @@ static void iavf_irq_disable(struct iavf_adapter *adapter)
* iavf_irq_enable_queues - Enable interrupt for all queues
* @adapter: board private structure
**/
-void iavf_irq_enable_queues(struct iavf_adapter *adapter)
+static void iavf_irq_enable_queues(struct iavf_adapter *adapter)
{
struct iavf_hw *hw = &adapter->hw;
int i;
@@ -1003,44 +1036,40 @@ struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
*
* Do not call this with mac_vlan_list_lock!
**/
-int iavf_replace_primary_mac(struct iavf_adapter *adapter,
- const u8 *new_mac)
+static int iavf_replace_primary_mac(struct iavf_adapter *adapter,
+ const u8 *new_mac)
{
struct iavf_hw *hw = &adapter->hw;
- struct iavf_mac_filter *f;
+ struct iavf_mac_filter *new_f;
+ struct iavf_mac_filter *old_f;
spin_lock_bh(&adapter->mac_vlan_list_lock);
- list_for_each_entry(f, &adapter->mac_filter_list, list) {
- f->is_primary = false;
+ new_f = iavf_add_filter(adapter, new_mac);
+ if (!new_f) {
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+ return -ENOMEM;
}
- f = iavf_find_filter(adapter, hw->mac.addr);
- if (f) {
- f->remove = true;
+ old_f = iavf_find_filter(adapter, hw->mac.addr);
+ if (old_f) {
+ old_f->is_primary = false;
+ old_f->remove = true;
adapter->aq_required |= IAVF_FLAG_AQ_DEL_MAC_FILTER;
}
-
- f = iavf_add_filter(adapter, new_mac);
-
- if (f) {
- /* Always send the request to add if changing primary MAC
- * even if filter is already present on the list
- */
- f->is_primary = true;
- f->add = true;
- adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER;
- ether_addr_copy(hw->mac.addr, new_mac);
- }
+ /* Always send the request to add if changing primary MAC,
+ * even if filter is already present on the list
+ */
+ new_f->is_primary = true;
+ new_f->add = true;
+ adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER;
+ ether_addr_copy(hw->mac.addr, new_mac);
spin_unlock_bh(&adapter->mac_vlan_list_lock);
/* schedule the watchdog task to immediately process the request */
- if (f) {
- mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
- return 0;
- }
- return -ENOMEM;
+ mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
+ return 0;
}
/**
@@ -1663,10 +1692,10 @@ static int iavf_set_interrupt_capability(struct iavf_adapter *adapter)
adapter->msix_entries[vector].entry = vector;
err = iavf_acquire_msix_vectors(adapter, v_budget);
+ if (!err)
+ iavf_schedule_finish_config(adapter);
out:
- netif_set_real_num_rx_queues(adapter->netdev, pairs);
- netif_set_real_num_tx_queues(adapter->netdev, pairs);
return err;
}
@@ -1840,19 +1869,16 @@ static int iavf_alloc_q_vectors(struct iavf_adapter *adapter)
static void iavf_free_q_vectors(struct iavf_adapter *adapter)
{
int q_idx, num_q_vectors;
- int napi_vectors;
if (!adapter->q_vectors)
return;
num_q_vectors = adapter->num_msix_vectors - NONQ_VECS;
- napi_vectors = adapter->num_active_queues;
for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
struct iavf_q_vector *q_vector = &adapter->q_vectors[q_idx];
- if (q_idx < napi_vectors)
- netif_napi_del(&q_vector->napi);
+ netif_napi_del(&q_vector->napi);
}
kfree(adapter->q_vectors);
adapter->q_vectors = NULL;
@@ -1863,7 +1889,7 @@ static void iavf_free_q_vectors(struct iavf_adapter *adapter)
* @adapter: board private structure
*
**/
-void iavf_reset_interrupt_capability(struct iavf_adapter *adapter)
+static void iavf_reset_interrupt_capability(struct iavf_adapter *adapter)
{
if (!adapter->msix_entries)
return;
@@ -1878,7 +1904,7 @@ void iavf_reset_interrupt_capability(struct iavf_adapter *adapter)
* @adapter: board private structure to initialize
*
**/
-int iavf_init_interrupt_scheme(struct iavf_adapter *adapter)
+static int iavf_init_interrupt_scheme(struct iavf_adapter *adapter)
{
int err;
@@ -1889,9 +1915,7 @@ int iavf_init_interrupt_scheme(struct iavf_adapter *adapter)
goto err_alloc_queues;
}
- rtnl_lock();
err = iavf_set_interrupt_capability(adapter);
- rtnl_unlock();
if (err) {
dev_err(&adapter->pdev->dev,
"Unable to setup interrupt capabilities\n");
@@ -1944,15 +1968,16 @@ static void iavf_free_rss(struct iavf_adapter *adapter)
/**
* iavf_reinit_interrupt_scheme - Reallocate queues and vectors
* @adapter: board private structure
+ * @running: true if adapter->state == __IAVF_RUNNING
*
* Returns 0 on success, negative on failure
**/
-static int iavf_reinit_interrupt_scheme(struct iavf_adapter *adapter)
+static int iavf_reinit_interrupt_scheme(struct iavf_adapter *adapter, bool running)
{
struct net_device *netdev = adapter->netdev;
int err;
- if (netif_running(netdev))
+ if (running)
iavf_free_traffic_irqs(adapter);
iavf_free_misc_irq(adapter);
iavf_reset_interrupt_capability(adapter);
@@ -1977,6 +2002,78 @@ err:
}
/**
+ * iavf_finish_config - do all netdev work that needs RTNL
+ * @work: our work_struct
+ *
+ * Do work that needs both RTNL and crit_lock.
+ **/
+static void iavf_finish_config(struct work_struct *work)
+{
+ struct iavf_adapter *adapter;
+ int pairs, err;
+
+ adapter = container_of(work, struct iavf_adapter, finish_config);
+
+ /* Always take RTNL first to prevent circular lock dependency */
+ rtnl_lock();
+ mutex_lock(&adapter->crit_lock);
+
+ if ((adapter->flags & IAVF_FLAG_SETUP_NETDEV_FEATURES) &&
+ adapter->netdev_registered &&
+ !test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section)) {
+ netdev_update_features(adapter->netdev);
+ adapter->flags &= ~IAVF_FLAG_SETUP_NETDEV_FEATURES;
+ }
+
+ switch (adapter->state) {
+ case __IAVF_DOWN:
+ if (!adapter->netdev_registered) {
+ err = register_netdevice(adapter->netdev);
+ if (err) {
+ dev_err(&adapter->pdev->dev, "Unable to register netdev (%d)\n",
+ err);
+
+ /* go back and try again.*/
+ iavf_free_rss(adapter);
+ iavf_free_misc_irq(adapter);
+ iavf_reset_interrupt_capability(adapter);
+ iavf_change_state(adapter,
+ __IAVF_INIT_CONFIG_ADAPTER);
+ goto out;
+ }
+ adapter->netdev_registered = true;
+ }
+
+ /* Set the real number of queues when reset occurs while
+ * state == __IAVF_DOWN
+ */
+ fallthrough;
+ case __IAVF_RUNNING:
+ pairs = adapter->num_active_queues;
+ netif_set_real_num_rx_queues(adapter->netdev, pairs);
+ netif_set_real_num_tx_queues(adapter->netdev, pairs);
+ break;
+
+ default:
+ break;
+ }
+
+out:
+ mutex_unlock(&adapter->crit_lock);
+ rtnl_unlock();
+}
+
+/**
+ * iavf_schedule_finish_config - Set the flags and schedule a reset event
+ * @adapter: board private structure
+ **/
+void iavf_schedule_finish_config(struct iavf_adapter *adapter)
+{
+ if (!test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section))
+ queue_work(adapter->wq, &adapter->finish_config);
+}
+
+/**
* iavf_process_aq_command - process aq_required flags
* and sends aq command
* @adapter: pointer to iavf adapter structure
@@ -2176,7 +2273,7 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter)
* the watchdog if any changes are requested to expedite the request via
* virtchnl.
**/
-void
+static void
iavf_set_vlan_offload_features(struct iavf_adapter *adapter,
netdev_features_t prev_features,
netdev_features_t features)
@@ -2383,7 +2480,7 @@ int iavf_parse_vf_resource_msg(struct iavf_adapter *adapter)
adapter->vsi_res->num_queue_pairs);
adapter->flags |= IAVF_FLAG_REINIT_MSIX_NEEDED;
adapter->num_req_queues = adapter->vsi_res->num_queue_pairs;
- iavf_schedule_reset(adapter);
+ iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
return -EAGAIN;
}
@@ -2613,22 +2710,8 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
netif_carrier_off(netdev);
adapter->link_up = false;
-
- /* set the semaphore to prevent any callbacks after device registration
- * up to time when state of driver will be set to __IAVF_DOWN
- */
- rtnl_lock();
- if (!adapter->netdev_registered) {
- err = register_netdevice(netdev);
- if (err) {
- rtnl_unlock();
- goto err_register;
- }
- }
-
- adapter->netdev_registered = true;
-
netif_tx_stop_all_queues(netdev);
+
if (CLIENT_ALLOWED(adapter)) {
err = iavf_lan_add_device(adapter);
if (err)
@@ -2641,7 +2724,6 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
iavf_change_state(adapter, __IAVF_DOWN);
set_bit(__IAVF_VSI_DOWN, adapter->vsi.state);
- rtnl_unlock();
iavf_misc_irq_enable(adapter);
wake_up(&adapter->down_waitqueue);
@@ -2661,10 +2743,11 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
/* request initial VLAN offload settings */
iavf_set_vlan_offload_features(adapter, 0, netdev->features);
+ iavf_schedule_finish_config(adapter);
return;
+
err_mem:
iavf_free_rss(adapter);
-err_register:
iavf_free_misc_irq(adapter);
err_sw_init:
iavf_reset_interrupt_capability(adapter);
@@ -2691,26 +2774,9 @@ static void iavf_watchdog_task(struct work_struct *work)
goto restart_watchdog;
}
- if ((adapter->flags & IAVF_FLAG_SETUP_NETDEV_FEATURES) &&
- adapter->netdev_registered &&
- !test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section) &&
- rtnl_trylock()) {
- netdev_update_features(adapter->netdev);
- rtnl_unlock();
- adapter->flags &= ~IAVF_FLAG_SETUP_NETDEV_FEATURES;
- }
-
if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
iavf_change_state(adapter, __IAVF_COMM_FAILED);
- if (adapter->flags & IAVF_FLAG_RESET_NEEDED) {
- adapter->aq_required = 0;
- adapter->current_op = VIRTCHNL_OP_UNKNOWN;
- mutex_unlock(&adapter->crit_lock);
- queue_work(adapter->wq, &adapter->reset_task);
- return;
- }
-
switch (adapter->state) {
case __IAVF_STARTUP:
iavf_startup(adapter);
@@ -2838,11 +2904,10 @@ static void iavf_watchdog_task(struct work_struct *work)
/* check for hw reset */
reg_val = rd32(hw, IAVF_VF_ARQLEN1) & IAVF_VF_ARQLEN1_ARQENABLE_MASK;
if (!reg_val) {
- adapter->flags |= IAVF_FLAG_RESET_PENDING;
adapter->aq_required = 0;
adapter->current_op = VIRTCHNL_OP_UNKNOWN;
dev_err(&adapter->pdev->dev, "Hardware reset detected\n");
- queue_work(adapter->wq, &adapter->reset_task);
+ iavf_schedule_reset(adapter, IAVF_FLAG_RESET_PENDING);
mutex_unlock(&adapter->crit_lock);
queue_delayed_work(adapter->wq,
&adapter->watchdog_task, HZ * 2);
@@ -2952,11 +3017,6 @@ static void iavf_reset_task(struct work_struct *work)
int i = 0, err;
bool running;
- /* Detach interface to avoid subsequent NDO callbacks */
- rtnl_lock();
- netif_device_detach(netdev);
- rtnl_unlock();
-
/* When device is being removed it doesn't make sense to run the reset
* task, just return in such a case.
*/
@@ -2964,7 +3024,7 @@ static void iavf_reset_task(struct work_struct *work)
if (adapter->state != __IAVF_REMOVE)
queue_work(adapter->wq, &adapter->reset_task);
- goto reset_finish;
+ return;
}
while (!mutex_trylock(&adapter->client_lock))
@@ -3022,11 +3082,6 @@ static void iavf_reset_task(struct work_struct *work)
iavf_disable_vf(adapter);
mutex_unlock(&adapter->client_lock);
mutex_unlock(&adapter->crit_lock);
- if (netif_running(netdev)) {
- rtnl_lock();
- dev_close(netdev);
- rtnl_unlock();
- }
return; /* Do not attempt to reinit. It's dead, Jim. */
}
@@ -3068,7 +3123,7 @@ continue_reset:
if ((adapter->flags & IAVF_FLAG_REINIT_MSIX_NEEDED) ||
(adapter->flags & IAVF_FLAG_REINIT_ITR_NEEDED)) {
- err = iavf_reinit_interrupt_scheme(adapter);
+ err = iavf_reinit_interrupt_scheme(adapter, running);
if (err)
goto reset_err;
}
@@ -3163,10 +3218,11 @@ continue_reset:
adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
+ wake_up(&adapter->reset_waitqueue);
mutex_unlock(&adapter->client_lock);
mutex_unlock(&adapter->crit_lock);
- goto reset_finish;
+ return;
reset_err:
if (running) {
set_bit(__IAVF_VSI_DOWN, adapter->vsi.state);
@@ -3176,21 +3232,7 @@ reset_err:
mutex_unlock(&adapter->client_lock);
mutex_unlock(&adapter->crit_lock);
-
- if (netif_running(netdev)) {
- /* Close device to ensure that Tx queues will not be started
- * during netif_device_attach() at the end of the reset task.
- */
- rtnl_lock();
- dev_close(netdev);
- rtnl_unlock();
- }
-
dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n");
-reset_finish:
- rtnl_lock();
- netif_device_attach(netdev);
- rtnl_unlock();
}
/**
@@ -3208,9 +3250,6 @@ static void iavf_adminq_task(struct work_struct *work)
u32 val, oldval;
u16 pending;
- if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
- goto out;
-
if (!mutex_trylock(&adapter->crit_lock)) {
if (adapter->state == __IAVF_REMOVE)
return;
@@ -3219,10 +3258,13 @@ static void iavf_adminq_task(struct work_struct *work)
goto out;
}
+ if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
+ goto unlock;
+
event.buf_len = IAVF_MAX_AQ_BUF_SIZE;
event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);
if (!event.msg_buf)
- goto out;
+ goto unlock;
do {
ret = iavf_clean_arq_element(hw, &event, &pending);
@@ -3237,11 +3279,8 @@ static void iavf_adminq_task(struct work_struct *work)
if (pending != 0)
memset(event.msg_buf, 0, IAVF_MAX_AQ_BUF_SIZE);
} while (pending);
- mutex_unlock(&adapter->crit_lock);
- if ((adapter->flags &
- (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED)) ||
- adapter->state == __IAVF_RESETTING)
+ if (iavf_is_reset_in_progress(adapter))
goto freedom;
/* check for error indications */
@@ -3283,6 +3322,8 @@ static void iavf_adminq_task(struct work_struct *work)
freedom:
kfree(event.msg_buf);
+unlock:
+ mutex_unlock(&adapter->crit_lock);
out:
/* re-enable Admin queue interrupt cause */
iavf_misc_irq_enable(adapter);
@@ -4327,6 +4368,7 @@ static int iavf_close(struct net_device *netdev)
static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
{
struct iavf_adapter *adapter = netdev_priv(netdev);
+ int ret = 0;
netdev_dbg(netdev, "changing MTU from %d to %d\n",
netdev->mtu, new_mtu);
@@ -4337,11 +4379,15 @@ static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
}
if (netif_running(netdev)) {
- adapter->flags |= IAVF_FLAG_RESET_NEEDED;
- queue_work(adapter->wq, &adapter->reset_task);
+ iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
+ ret = iavf_wait_for_reset(adapter);
+ if (ret < 0)
+ netdev_warn(netdev, "MTU change interrupted waiting for reset");
+ else if (ret)
+ netdev_warn(netdev, "MTU change timed out waiting for reset");
}
- return 0;
+ return ret;
}
#define NETIF_VLAN_OFFLOAD_FEATURES (NETIF_F_HW_VLAN_CTAG_RX | \
@@ -4934,6 +4980,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_WORK(&adapter->reset_task, iavf_reset_task);
INIT_WORK(&adapter->adminq_task, iavf_adminq_task);
+ INIT_WORK(&adapter->finish_config, iavf_finish_config);
INIT_DELAYED_WORK(&adapter->watchdog_task, iavf_watchdog_task);
INIT_DELAYED_WORK(&adapter->client_task, iavf_client_task);
queue_delayed_work(adapter->wq, &adapter->watchdog_task,
@@ -4942,6 +4989,9 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Setup the wait queue for indicating transition to down status */
init_waitqueue_head(&adapter->down_waitqueue);
+ /* Setup the wait queue for indicating transition to running state */
+ init_waitqueue_head(&adapter->reset_waitqueue);
+
/* Setup the wait queue for indicating virtchannel events */
init_waitqueue_head(&adapter->vc_waitqueue);
@@ -5073,13 +5123,15 @@ static void iavf_remove(struct pci_dev *pdev)
usleep_range(500, 1000);
}
cancel_delayed_work_sync(&adapter->watchdog_task);
+ cancel_work_sync(&adapter->finish_config);
+ rtnl_lock();
if (adapter->netdev_registered) {
- rtnl_lock();
unregister_netdevice(netdev);
adapter->netdev_registered = false;
- rtnl_unlock();
}
+ rtnl_unlock();
+
if (CLIENT_ALLOWED(adapter)) {
err = iavf_lan_del_device(adapter);
if (err)
diff --git a/drivers/net/ethernet/intel/iavf/iavf_osdep.h b/drivers/net/ethernet/intel/iavf/iavf_osdep.h
index a452ce90679a..77d33deaabb5 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_osdep.h
+++ b/drivers/net/ethernet/intel/iavf/iavf_osdep.h
@@ -13,12 +13,6 @@
/* get readq/writeq support for 32 bit kernels, use the low-first version */
#include <linux/io-64-nonatomic-lo-hi.h>
-/* File to be the magic between shared code and
- * actual OS primitives
- */
-
-#define hw_dbg(hw, S, A...) do {} while (0)
-
#define wr32(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
#define rd32(a, reg) readl((a)->hw_addr + (reg))
@@ -35,14 +29,11 @@ struct iavf_dma_mem {
#define iavf_allocate_dma_mem(h, m, unused, s, a) \
iavf_allocate_dma_mem_d(h, m, s, a)
-#define iavf_free_dma_mem(h, m) iavf_free_dma_mem_d(h, m)
struct iavf_virt_mem {
void *va;
u32 size;
};
-#define iavf_allocate_virt_mem(h, m, s) iavf_allocate_virt_mem_d(h, m, s)
-#define iavf_free_virt_mem(h, m) iavf_free_virt_mem_d(h, m)
#define iavf_debug(h, m, s, ...) \
do { \
diff --git a/drivers/net/ethernet/intel/iavf/iavf_prototype.h b/drivers/net/ethernet/intel/iavf/iavf_prototype.h
index edebfbbcffdc..940cb4203fbe 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_prototype.h
+++ b/drivers/net/ethernet/intel/iavf/iavf_prototype.h
@@ -40,12 +40,8 @@ enum iavf_status iavf_aq_queue_shutdown(struct iavf_hw *hw, bool unloading);
const char *iavf_aq_str(struct iavf_hw *hw, enum iavf_admin_queue_err aq_err);
const char *iavf_stat_str(struct iavf_hw *hw, enum iavf_status stat_err);
-enum iavf_status iavf_aq_get_rss_lut(struct iavf_hw *hw, u16 seid,
- bool pf_lut, u8 *lut, u16 lut_size);
enum iavf_status iavf_aq_set_rss_lut(struct iavf_hw *hw, u16 seid,
bool pf_lut, u8 *lut, u16 lut_size);
-enum iavf_status iavf_aq_get_rss_key(struct iavf_hw *hw, u16 seid,
- struct iavf_aqc_get_set_rss_key_data *key);
enum iavf_status iavf_aq_set_rss_key(struct iavf_hw *hw, u16 seid,
struct iavf_aqc_get_set_rss_key_data *key);
@@ -60,7 +56,6 @@ static inline struct iavf_rx_ptype_decoded decode_rx_desc_ptype(u8 ptype)
void iavf_vf_parse_hw_config(struct iavf_hw *hw,
struct virtchnl_vf_resource *msg);
-enum iavf_status iavf_vf_reset(struct iavf_hw *hw);
enum iavf_status iavf_aq_send_msg_to_pf(struct iavf_hw *hw,
enum virtchnl_ops v_opcode,
enum iavf_status v_retval,
diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.c b/drivers/net/ethernet/intel/iavf/iavf_txrx.c
index e989feda133c..8c5f6096b002 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_txrx.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.c
@@ -54,7 +54,7 @@ static void iavf_unmap_and_free_tx_resource(struct iavf_ring *ring,
* iavf_clean_tx_ring - Free any empty Tx buffers
* @tx_ring: ring to be cleaned
**/
-void iavf_clean_tx_ring(struct iavf_ring *tx_ring)
+static void iavf_clean_tx_ring(struct iavf_ring *tx_ring)
{
unsigned long bi_size;
u16 i;
@@ -110,7 +110,7 @@ void iavf_free_tx_resources(struct iavf_ring *tx_ring)
* Since there is no access to the ring head register
* in XL710, we need to use our local copies
**/
-u32 iavf_get_tx_pending(struct iavf_ring *ring, bool in_sw)
+static u32 iavf_get_tx_pending(struct iavf_ring *ring, bool in_sw)
{
u32 head, tail;
@@ -128,6 +128,24 @@ u32 iavf_get_tx_pending(struct iavf_ring *ring, bool in_sw)
}
/**
+ * iavf_force_wb - Issue SW Interrupt so HW does a wb
+ * @vsi: the VSI we care about
+ * @q_vector: the vector on which to force writeback
+ **/
+static void iavf_force_wb(struct iavf_vsi *vsi, struct iavf_q_vector *q_vector)
+{
+ u32 val = IAVF_VFINT_DYN_CTLN1_INTENA_MASK |
+ IAVF_VFINT_DYN_CTLN1_ITR_INDX_MASK | /* set noitr */
+ IAVF_VFINT_DYN_CTLN1_SWINT_TRIG_MASK |
+ IAVF_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK
+ /* allow 00 to be written to the index */;
+
+ wr32(&vsi->back->hw,
+ IAVF_VFINT_DYN_CTLN1(q_vector->reg_idx),
+ val);
+}
+
+/**
* iavf_detect_recover_hung - Function to detect and recover hung_queues
* @vsi: pointer to vsi struct with tx queues
*
@@ -352,25 +370,6 @@ static void iavf_enable_wb_on_itr(struct iavf_vsi *vsi,
q_vector->arm_wb_state = true;
}
-/**
- * iavf_force_wb - Issue SW Interrupt so HW does a wb
- * @vsi: the VSI we care about
- * @q_vector: the vector on which to force writeback
- *
- **/
-void iavf_force_wb(struct iavf_vsi *vsi, struct iavf_q_vector *q_vector)
-{
- u32 val = IAVF_VFINT_DYN_CTLN1_INTENA_MASK |
- IAVF_VFINT_DYN_CTLN1_ITR_INDX_MASK | /* set noitr */
- IAVF_VFINT_DYN_CTLN1_SWINT_TRIG_MASK |
- IAVF_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK
- /* allow 00 to be written to the index */;
-
- wr32(&vsi->back->hw,
- IAVF_VFINT_DYN_CTLN1(q_vector->reg_idx),
- val);
-}
-
static inline bool iavf_container_is_rx(struct iavf_q_vector *q_vector,
struct iavf_ring_container *rc)
{
@@ -687,7 +686,7 @@ err:
* iavf_clean_rx_ring - Free Rx buffers
* @rx_ring: ring to be cleaned
**/
-void iavf_clean_rx_ring(struct iavf_ring *rx_ring)
+static void iavf_clean_rx_ring(struct iavf_ring *rx_ring)
{
unsigned long bi_size;
u16 i;
diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.h b/drivers/net/ethernet/intel/iavf/iavf_txrx.h
index 2624bf6d009e..7e6ee32d19b6 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_txrx.h
+++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.h
@@ -442,15 +442,11 @@ static inline unsigned int iavf_rx_pg_order(struct iavf_ring *ring)
bool iavf_alloc_rx_buffers(struct iavf_ring *rxr, u16 cleaned_count);
netdev_tx_t iavf_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
-void iavf_clean_tx_ring(struct iavf_ring *tx_ring);
-void iavf_clean_rx_ring(struct iavf_ring *rx_ring);
int iavf_setup_tx_descriptors(struct iavf_ring *tx_ring);
int iavf_setup_rx_descriptors(struct iavf_ring *rx_ring);
void iavf_free_tx_resources(struct iavf_ring *tx_ring);
void iavf_free_rx_resources(struct iavf_ring *rx_ring);
int iavf_napi_poll(struct napi_struct *napi, int budget);
-void iavf_force_wb(struct iavf_vsi *vsi, struct iavf_q_vector *q_vector);
-u32 iavf_get_tx_pending(struct iavf_ring *ring, bool in_sw);
void iavf_detect_recover_hung(struct iavf_vsi *vsi);
int __iavf_maybe_stop_tx(struct iavf_ring *tx_ring, int size);
bool __iavf_chk_linearize(struct sk_buff *skb);
diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
index 7c0578b5457b..be3c007ce90a 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
@@ -1961,9 +1961,8 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
case VIRTCHNL_EVENT_RESET_IMPENDING:
dev_info(&adapter->pdev->dev, "Reset indication received from the PF\n");
if (!(adapter->flags & IAVF_FLAG_RESET_PENDING)) {
- adapter->flags |= IAVF_FLAG_RESET_PENDING;
dev_info(&adapter->pdev->dev, "Scheduling reset task\n");
- queue_work(adapter->wq, &adapter->reset_task);
+ iavf_schedule_reset(adapter, IAVF_FLAG_RESET_PENDING);
}
break;
default:
@@ -2237,6 +2236,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
iavf_process_config(adapter);
adapter->flags |= IAVF_FLAG_SETUP_NETDEV_FEATURES;
+ iavf_schedule_finish_config(adapter);
iavf_set_queue_vlan_tag_loc(adapter);
@@ -2285,6 +2285,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
case VIRTCHNL_OP_ENABLE_QUEUES:
/* enable transmits */
iavf_irq_enable(adapter, true);
+ wake_up(&adapter->reset_waitqueue);
adapter->flags &= ~IAVF_FLAG_QUEUES_DISABLED;
break;
case VIRTCHNL_OP_DISABLE_QUEUES:
diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile
index 5d89392f969b..817977e3039d 100644
--- a/drivers/net/ethernet/intel/ice/Makefile
+++ b/drivers/net/ethernet/intel/ice/Makefile
@@ -18,6 +18,7 @@ ice-y := ice_main.o \
ice_txrx_lib.o \
ice_txrx.o \
ice_fltr.o \
+ ice_irq.o \
ice_pf_vsi_vlan_ops.o \
ice_vsi_vlan_ops.o \
ice_vsi_vlan_lib.o \
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
index aa32111afd6e..4ba3d99439a0 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -32,6 +32,7 @@
#include <linux/pkt_sched.h>
#include <linux/if_bridge.h>
#include <linux/ctype.h>
+#include <linux/linkmode.h>
#include <linux/bpf.h>
#include <linux/btf.h>
#include <linux/auxiliary_bus.h>
@@ -74,6 +75,7 @@
#include "ice_lag.h"
#include "ice_vsi_vlan_ops.h"
#include "ice_gnss.h"
+#include "ice_irq.h"
#define ICE_BAR0 0
#define ICE_REQ_DESC_MULTIPLE 32
@@ -103,11 +105,6 @@
#define ICE_Q_WAIT_RETRY_LIMIT 10
#define ICE_Q_WAIT_MAX_RETRY (5 * ICE_Q_WAIT_RETRY_LIMIT)
#define ICE_MAX_LG_RSS_QS 256
-#define ICE_RES_VALID_BIT 0x8000
-#define ICE_RES_MISC_VEC_ID (ICE_RES_VALID_BIT - 1)
-#define ICE_RES_RDMA_VEC_ID (ICE_RES_MISC_VEC_ID - 1)
-/* All VF control VSIs share the same IRQ, so assign a unique ID for them */
-#define ICE_RES_VF_CTRL_VEC_ID (ICE_RES_RDMA_VEC_ID - 1)
#define ICE_INVAL_Q_INDEX 0xffff
#define ICE_MAX_RXQS_PER_TC 256 /* Used when setting VSI context per TC Rx queues */
@@ -245,12 +242,6 @@ struct ice_tc_cfg {
struct ice_tc_info tc_info[ICE_MAX_TRAFFIC_CLASS];
};
-struct ice_res_tracker {
- u16 num_entries;
- u16 end;
- u16 list[];
-};
-
struct ice_qs_cfg {
struct mutex *qs_mutex; /* will be assigned to &pf->avail_q_mutex */
unsigned long *pf_map;
@@ -348,7 +339,9 @@ struct ice_vsi {
u32 rx_buf_failed;
u32 rx_page_failed;
u16 num_q_vectors;
- u16 base_vector; /* IRQ base for OS reserved vectors */
+ /* tell if only dynamic irq allocation is allowed */
+ bool irq_dyn_alloc;
+
enum ice_vsi_type type;
u16 vsi_num; /* HW (absolute) index of this VSI */
u16 idx; /* software index in pf->vsi[] */
@@ -479,6 +472,7 @@ struct ice_q_vector {
char name[ICE_INT_NAME_STR_LEN];
u16 total_events; /* net_dim(): number of interrupts processed */
+ struct msi_map irq;
} ____cacheline_internodealigned_in_smp;
enum ice_pf_flags {
@@ -514,6 +508,12 @@ enum ice_pf_flags {
ICE_PF_FLAGS_NBITS /* must be last */
};
+enum ice_misc_thread_tasks {
+ ICE_MISC_THREAD_EXTTS_EVENT,
+ ICE_MISC_THREAD_TX_TSTAMP,
+ ICE_MISC_THREAD_NBITS /* must be last */
+};
+
struct ice_switchdev_info {
struct ice_vsi *control_vsi;
struct ice_vsi *uplink_vsi;
@@ -539,7 +539,7 @@ struct ice_pf {
/* OS reserved IRQ details */
struct msix_entry *msix_entries;
- struct ice_res_tracker *irq_tracker;
+ struct ice_irq_tracker irq_tracker;
/* First MSIX vector used by SR-IOV VFs. Calculated by subtracting the
* number of MSIX vectors needed for all SR-IOV VFs from the number of
* MSIX vectors allowed on this PF.
@@ -556,6 +556,7 @@ struct ice_pf {
DECLARE_BITMAP(features, ICE_F_MAX);
DECLARE_BITMAP(state, ICE_STATE_NBITS);
DECLARE_BITMAP(flags, ICE_PF_FLAGS_NBITS);
+ DECLARE_BITMAP(misc_thread, ICE_MISC_THREAD_NBITS);
unsigned long *avail_txqs; /* bitmap to track PF Tx queue usage */
unsigned long *avail_rxqs; /* bitmap to track PF Rx queue usage */
unsigned long serv_tmr_period;
@@ -583,8 +584,7 @@ struct ice_pf {
u32 hw_csum_rx_error;
u32 oicr_err_reg;
- u16 oicr_idx; /* Other interrupt cause MSIX vector index */
- u16 num_avail_sw_msix; /* remaining MSIX SW vectors left unclaimed */
+ struct msi_map oicr_irq; /* Other interrupt cause MSIX vector */
u16 max_pf_txqs; /* Total Tx queues PF wide */
u16 max_pf_rxqs; /* Total Rx queues PF wide */
u16 num_lan_msix; /* Total MSIX vectors for base driver */
@@ -670,7 +670,7 @@ ice_irq_dynamic_ena(struct ice_hw *hw, struct ice_vsi *vsi,
struct ice_q_vector *q_vector)
{
u32 vector = (vsi && q_vector) ? q_vector->reg_idx :
- ((struct ice_pf *)hw->back)->oicr_idx;
+ ((struct ice_pf *)hw->back)->oicr_irq.index;
int itr = ICE_ITR_NONE;
u32 val;
@@ -821,25 +821,6 @@ static inline bool ice_is_switchdev_running(struct ice_pf *pf)
return pf->switchdev.is_running;
}
-/**
- * ice_set_sriov_cap - enable SRIOV in PF flags
- * @pf: PF struct
- */
-static inline void ice_set_sriov_cap(struct ice_pf *pf)
-{
- if (pf->hw.func_caps.common_cap.sr_iov_1_1)
- set_bit(ICE_FLAG_SRIOV_CAPABLE, pf->flags);
-}
-
-/**
- * ice_clear_sriov_cap - disable SRIOV in PF flags
- * @pf: PF struct
- */
-static inline void ice_clear_sriov_cap(struct ice_pf *pf)
-{
- clear_bit(ICE_FLAG_SRIOV_CAPABLE, pf->flags);
-}
-
#define ICE_FD_STAT_CTR_BLOCK_COUNT 256
#define ICE_FD_STAT_PF_IDX(base_idx) \
((base_idx) * ICE_FD_STAT_CTR_BLOCK_COUNT)
diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
index 838d9b274d68..63d3e1dcbba5 100644
--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
@@ -1087,7 +1087,7 @@ struct ice_aqc_get_phy_caps {
#define ICE_PHY_TYPE_HIGH_100G_CAUI2 BIT_ULL(2)
#define ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC BIT_ULL(3)
#define ICE_PHY_TYPE_HIGH_100G_AUI2 BIT_ULL(4)
-#define ICE_PHY_TYPE_HIGH_MAX_INDEX 5
+#define ICE_PHY_TYPE_HIGH_MAX_INDEX 4
struct ice_aqc_get_phy_caps_data {
__le64 phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */
diff --git a/drivers/net/ethernet/intel/ice/ice_arfs.c b/drivers/net/ethernet/intel/ice/ice_arfs.c
index fba178e07600..cca0e753f38f 100644
--- a/drivers/net/ethernet/intel/ice/ice_arfs.c
+++ b/drivers/net/ethernet/intel/ice/ice_arfs.c
@@ -596,7 +596,7 @@ int ice_set_cpu_rx_rmap(struct ice_vsi *vsi)
{
struct net_device *netdev;
struct ice_pf *pf;
- int base_idx, i;
+ int i;
if (!vsi || vsi->type != ICE_VSI_PF)
return 0;
@@ -613,10 +613,9 @@ int ice_set_cpu_rx_rmap(struct ice_vsi *vsi)
if (unlikely(!netdev->rx_cpu_rmap))
return -EINVAL;
- base_idx = vsi->base_vector;
ice_for_each_q_vector(vsi, i)
if (irq_cpu_rmap_add(netdev->rx_cpu_rmap,
- pf->msix_entries[base_idx + i].vector)) {
+ vsi->q_vectors[i]->irq.virq)) {
ice_free_cpu_rx_rmap(vsi);
return -EINVAL;
}
diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c
index 1911d644dfa8..074bf9403cd1 100644
--- a/drivers/net/ethernet/intel/ice/ice_base.c
+++ b/drivers/net/ethernet/intel/ice/ice_base.c
@@ -103,10 +103,10 @@ static int ice_vsi_alloc_q_vector(struct ice_vsi *vsi, u16 v_idx)
{
struct ice_pf *pf = vsi->back;
struct ice_q_vector *q_vector;
+ int err;
/* allocate q_vector */
- q_vector = devm_kzalloc(ice_pf_to_dev(pf), sizeof(*q_vector),
- GFP_KERNEL);
+ q_vector = kzalloc(sizeof(*q_vector), GFP_KERNEL);
if (!q_vector)
return -ENOMEM;
@@ -118,9 +118,34 @@ static int ice_vsi_alloc_q_vector(struct ice_vsi *vsi, u16 v_idx)
q_vector->rx.itr_mode = ITR_DYNAMIC;
q_vector->tx.type = ICE_TX_CONTAINER;
q_vector->rx.type = ICE_RX_CONTAINER;
+ q_vector->irq.index = -ENOENT;
- if (vsi->type == ICE_VSI_VF)
+ if (vsi->type == ICE_VSI_VF) {
+ q_vector->reg_idx = ice_calc_vf_reg_idx(vsi->vf, q_vector);
goto out;
+ } else if (vsi->type == ICE_VSI_CTRL && vsi->vf) {
+ struct ice_vsi *ctrl_vsi = ice_get_vf_ctrl_vsi(pf, vsi);
+
+ if (ctrl_vsi) {
+ if (unlikely(!ctrl_vsi->q_vectors)) {
+ err = -ENOENT;
+ goto err_free_q_vector;
+ }
+
+ q_vector->irq = ctrl_vsi->q_vectors[0]->irq;
+ goto skip_alloc;
+ }
+ }
+
+ q_vector->irq = ice_alloc_irq(pf, vsi->irq_dyn_alloc);
+ if (q_vector->irq.index < 0) {
+ err = -ENOMEM;
+ goto err_free_q_vector;
+ }
+
+skip_alloc:
+ q_vector->reg_idx = q_vector->irq.index;
+
/* only set affinity_mask if the CPU is online */
if (cpu_online(v_idx))
cpumask_set_cpu(v_idx, &q_vector->affinity_mask);
@@ -137,6 +162,11 @@ out:
vsi->q_vectors[v_idx] = q_vector;
return 0;
+
+err_free_q_vector:
+ kfree(q_vector);
+
+ return err;
}
/**
@@ -168,7 +198,19 @@ static void ice_free_q_vector(struct ice_vsi *vsi, int v_idx)
if (vsi->netdev)
netif_napi_del(&q_vector->napi);
- devm_kfree(dev, q_vector);
+ /* release MSIX interrupt if q_vector had interrupt allocated */
+ if (q_vector->irq.index < 0)
+ goto free_q_vector;
+
+ /* only free last VF ctrl vsi interrupt */
+ if (vsi->type == ICE_VSI_CTRL && vsi->vf &&
+ ice_get_vf_ctrl_vsi(pf, vsi))
+ goto free_q_vector;
+
+ ice_free_irq(pf, q_vector->irq);
+
+free_q_vector:
+ kfree(q_vector);
vsi->q_vectors[v_idx] = NULL;
}
@@ -393,7 +435,8 @@ static int ice_setup_rx_ctx(struct ice_rx_ring *ring)
/* Receive Packet Data Buffer Size.
* The Packet Data Buffer Size is defined in 128 byte units.
*/
- rlan_ctx.dbuf = ring->rx_buf_len >> ICE_RLAN_CTX_DBUF_S;
+ rlan_ctx.dbuf = DIV_ROUND_UP(ring->rx_buf_len,
+ BIT_ULL(ICE_RLAN_CTX_DBUF_S));
/* use 32 byte descriptors */
rlan_ctx.dsize = 1;
@@ -758,6 +801,8 @@ void ice_vsi_free_q_vectors(struct ice_vsi *vsi)
ice_for_each_q_vector(vsi, v_idx)
ice_free_q_vector(vsi, v_idx);
+
+ vsi->num_q_vectors = 0;
}
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
index eb2dc0983776..e16d4c83ed5f 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.c
+++ b/drivers/net/ethernet/intel/ice/ice_common.c
@@ -814,8 +814,7 @@ static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
devm_kfree(ice_hw_to_dev(hw), lst_itr);
}
}
- if (recps[i].root_buf)
- devm_kfree(ice_hw_to_dev(hw), recps[i].root_buf);
+ devm_kfree(ice_hw_to_dev(hw), recps[i].root_buf);
}
ice_rm_all_sw_replay_rule_info(hw);
devm_kfree(ice_hw_to_dev(hw), sw->recp_list);
@@ -834,7 +833,7 @@ static int ice_get_fw_log_cfg(struct ice_hw *hw)
u16 size;
size = sizeof(*config) * ICE_AQC_FW_LOG_ID_MAX;
- config = devm_kzalloc(ice_hw_to_dev(hw), size, GFP_KERNEL);
+ config = kzalloc(size, GFP_KERNEL);
if (!config)
return -ENOMEM;
@@ -857,7 +856,7 @@ static int ice_get_fw_log_cfg(struct ice_hw *hw)
}
}
- devm_kfree(ice_hw_to_dev(hw), config);
+ kfree(config);
return status;
}
@@ -1011,8 +1010,7 @@ static int ice_cfg_fw_log(struct ice_hw *hw, bool enable)
}
out:
- if (data)
- devm_kfree(ice_hw_to_dev(hw), data);
+ devm_kfree(ice_hw_to_dev(hw), data);
return status;
}
diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.c b/drivers/net/ethernet/intel/ice/ice_controlq.c
index d2faf1baad2f..e7d2474c431c 100644
--- a/drivers/net/ethernet/intel/ice/ice_controlq.c
+++ b/drivers/net/ethernet/intel/ice/ice_controlq.c
@@ -339,8 +339,7 @@ do { \
} \
} \
/* free the buffer info list */ \
- if ((qi)->ring.cmd_buf) \
- devm_kfree(ice_hw_to_dev(hw), (qi)->ring.cmd_buf); \
+ devm_kfree(ice_hw_to_dev(hw), (qi)->ring.cmd_buf); \
/* free DMA head */ \
devm_kfree(ice_hw_to_dev(hw), (qi)->ring.dma_head); \
} while (0)
@@ -1056,14 +1055,19 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
if (cq->sq.next_to_use == cq->sq.count)
cq->sq.next_to_use = 0;
wr32(hw, cq->sq.tail, cq->sq.next_to_use);
+ ice_flush(hw);
+
+ /* Wait a short time before initial ice_sq_done() check, to allow
+ * hardware time for completion.
+ */
+ udelay(5);
timeout = jiffies + ICE_CTL_Q_SQ_CMD_TIMEOUT;
do {
if (ice_sq_done(hw, cq))
break;
- usleep_range(ICE_CTL_Q_SQ_CMD_USEC,
- ICE_CTL_Q_SQ_CMD_USEC * 3 / 2);
+ usleep_range(100, 150);
} while (time_before(jiffies, timeout));
/* if ready, copy the desc back to temp */
diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.h b/drivers/net/ethernet/intel/ice/ice_controlq.h
index 950b7f4a7a05..8f2fd1613a95 100644
--- a/drivers/net/ethernet/intel/ice/ice_controlq.h
+++ b/drivers/net/ethernet/intel/ice/ice_controlq.h
@@ -35,7 +35,6 @@ enum ice_ctl_q {
/* Control Queue timeout settings - max delay 1s */
#define ICE_CTL_Q_SQ_CMD_TIMEOUT HZ /* Wait max 1s */
-#define ICE_CTL_Q_SQ_CMD_USEC 100 /* Check every 100usec */
#define ICE_CTL_Q_ADMIN_INIT_TIMEOUT 10 /* Count 10 times */
#define ICE_CTL_Q_ADMIN_INIT_MSEC 100 /* Check every 100msec */
diff --git a/drivers/net/ethernet/intel/ice/ice_ddp.h b/drivers/net/ethernet/intel/ice/ice_ddp.h
index 37eadb3d27a8..41acfe26df1c 100644
--- a/drivers/net/ethernet/intel/ice/ice_ddp.h
+++ b/drivers/net/ethernet/intel/ice/ice_ddp.h
@@ -185,7 +185,7 @@ struct ice_buf_hdr {
#define ICE_MAX_ENTRIES_IN_BUF(hd_sz, ent_sz) \
((ICE_PKG_BUF_SIZE - \
- struct_size((struct ice_buf_hdr *)0, section_entry, 1) - (hd_sz)) / \
+ struct_size_t(struct ice_buf_hdr, section_entry, 1) - (hd_sz)) / \
(ent_sz))
/* ice package section IDs */
@@ -297,7 +297,7 @@ struct ice_label_section {
};
#define ICE_MAX_LABELS_IN_BUF \
- ICE_MAX_ENTRIES_IN_BUF(struct_size((struct ice_label_section *)0, \
+ ICE_MAX_ENTRIES_IN_BUF(struct_size_t(struct ice_label_section, \
label, 1) - \
sizeof(struct ice_label), \
sizeof(struct ice_label))
@@ -352,7 +352,7 @@ struct ice_boost_tcam_section {
};
#define ICE_MAX_BST_TCAMS_IN_BUF \
- ICE_MAX_ENTRIES_IN_BUF(struct_size((struct ice_boost_tcam_section *)0, \
+ ICE_MAX_ENTRIES_IN_BUF(struct_size_t(struct ice_boost_tcam_section, \
tcam, 1) - \
sizeof(struct ice_boost_tcam_entry), \
sizeof(struct ice_boost_tcam_entry))
@@ -372,8 +372,7 @@ struct ice_marker_ptype_tcam_section {
};
#define ICE_MAX_MARKER_PTYPE_TCAMS_IN_BUF \
- ICE_MAX_ENTRIES_IN_BUF( \
- struct_size((struct ice_marker_ptype_tcam_section *)0, tcam, \
+ ICE_MAX_ENTRIES_IN_BUF(struct_size_t(struct ice_marker_ptype_tcam_section, tcam, \
1) - \
sizeof(struct ice_marker_ptype_tcam_entry), \
sizeof(struct ice_marker_ptype_tcam_entry))
diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c
index bc44cc220818..80dc5445b50d 100644
--- a/drivers/net/ethernet/intel/ice/ice_devlink.c
+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
@@ -1256,8 +1256,6 @@ static const struct devlink_ops ice_devlink_ops = {
BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
.reload_down = ice_devlink_reload_down,
.reload_up = ice_devlink_reload_up,
- .port_split = ice_devlink_port_split,
- .port_unsplit = ice_devlink_port_unsplit,
.eswitch_mode_get = ice_eswitch_mode_get,
.eswitch_mode_set = ice_eswitch_mode_set,
.info_get = ice_devlink_info_get,
@@ -1512,6 +1510,11 @@ ice_devlink_set_port_split_options(struct ice_pf *pf,
ice_active_port_option = active_idx;
}
+static const struct devlink_port_ops ice_devlink_port_ops = {
+ .port_split = ice_devlink_port_split,
+ .port_unsplit = ice_devlink_port_unsplit,
+};
+
/**
* ice_devlink_create_pf_port - Create a devlink port for this PF
* @pf: the PF to create a devlink port for
@@ -1551,7 +1554,8 @@ int ice_devlink_create_pf_port(struct ice_pf *pf)
devlink_port_attrs_set(devlink_port, &attrs);
devlink = priv_to_devlink(pf);
- err = devlink_port_register(devlink, devlink_port, vsi->idx);
+ err = devlink_port_register_with_ops(devlink, devlink_port, vsi->idx,
+ &ice_devlink_port_ops);
if (err) {
dev_err(dev, "Failed to create devlink port for PF %d, error %d\n",
pf->hw.pf_id, err);
diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c
index f6dd3f8fd936..8f232c41a89e 100644
--- a/drivers/net/ethernet/intel/ice/ice_eswitch.c
+++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c
@@ -10,16 +10,15 @@
#include "ice_tc_lib.h"
/**
- * ice_eswitch_add_vf_mac_rule - add adv rule with VF's MAC
+ * ice_eswitch_add_vf_sp_rule - add adv rule with VF's VSI index
* @pf: pointer to PF struct
* @vf: pointer to VF struct
- * @mac: VF's MAC address
*
* This function adds advanced rule that forwards packets with
- * VF's MAC address (src MAC) to the corresponding switchdev ctrl VSI queue.
+ * VF's VSI index to the corresponding switchdev ctrl VSI queue.
*/
-int
-ice_eswitch_add_vf_mac_rule(struct ice_pf *pf, struct ice_vf *vf, const u8 *mac)
+static int
+ice_eswitch_add_vf_sp_rule(struct ice_pf *pf, struct ice_vf *vf)
{
struct ice_vsi *ctrl_vsi = pf->switchdev.control_vsi;
struct ice_adv_rule_info rule_info = { 0 };
@@ -32,76 +31,41 @@ ice_eswitch_add_vf_mac_rule(struct ice_pf *pf, struct ice_vf *vf, const u8 *mac)
if (!list)
return -ENOMEM;
- list[0].type = ICE_MAC_OFOS;
- ether_addr_copy(list[0].h_u.eth_hdr.src_addr, mac);
- eth_broadcast_addr(list[0].m_u.eth_hdr.src_addr);
+ ice_rule_add_src_vsi_metadata(list);
- rule_info.sw_act.flag |= ICE_FLTR_TX;
+ rule_info.sw_act.flag = ICE_FLTR_TX;
rule_info.sw_act.vsi_handle = ctrl_vsi->idx;
rule_info.sw_act.fltr_act = ICE_FWD_TO_Q;
- rule_info.rx = false;
rule_info.sw_act.fwd_id.q_id = hw->func_caps.common_cap.rxq_first_id +
ctrl_vsi->rxq_map[vf->vf_id];
rule_info.flags_info.act |= ICE_SINGLE_ACT_LB_ENABLE;
rule_info.flags_info.act_valid = true;
rule_info.tun_type = ICE_SW_TUN_AND_NON_TUN;
+ rule_info.src_vsi = vf->lan_vsi_idx;
err = ice_add_adv_rule(hw, list, lkups_cnt, &rule_info,
- vf->repr->mac_rule);
+ &vf->repr->sp_rule);
if (err)
- dev_err(ice_pf_to_dev(pf), "Unable to add VF mac rule in switchdev mode for VF %d",
+ dev_err(ice_pf_to_dev(pf), "Unable to add VF slow-path rule in switchdev mode for VF %d",
vf->vf_id);
- else
- vf->repr->rule_added = true;
kfree(list);
return err;
}
/**
- * ice_eswitch_replay_vf_mac_rule - replay adv rule with VF's MAC
- * @vf: pointer to vF struct
- *
- * This function replays VF's MAC rule after reset.
- */
-void ice_eswitch_replay_vf_mac_rule(struct ice_vf *vf)
-{
- int err;
-
- if (!ice_is_switchdev_running(vf->pf))
- return;
-
- if (is_valid_ether_addr(vf->hw_lan_addr)) {
- err = ice_eswitch_add_vf_mac_rule(vf->pf, vf,
- vf->hw_lan_addr);
- if (err) {
- dev_err(ice_pf_to_dev(vf->pf), "Failed to add MAC %pM for VF %d\n, error %d\n",
- vf->hw_lan_addr, vf->vf_id, err);
- return;
- }
- vf->num_mac++;
-
- ether_addr_copy(vf->dev_lan_addr, vf->hw_lan_addr);
- }
-}
-
-/**
- * ice_eswitch_del_vf_mac_rule - delete adv rule with VF's MAC
+ * ice_eswitch_del_vf_sp_rule - delete adv rule with VF's VSI index
* @vf: pointer to the VF struct
*
- * Delete the advanced rule that was used to forward packets with the VF's MAC
- * address (src MAC) to the corresponding switchdev ctrl VSI queue.
+ * Delete the advanced rule that was used to forward packets with the VF's VSI
+ * index to the corresponding switchdev ctrl VSI queue.
*/
-void ice_eswitch_del_vf_mac_rule(struct ice_vf *vf)
+static void ice_eswitch_del_vf_sp_rule(struct ice_vf *vf)
{
- if (!ice_is_switchdev_running(vf->pf))
+ if (!vf->repr)
return;
- if (!vf->repr->rule_added)
- return;
-
- ice_rem_adv_rule_by_id(&vf->pf->hw, vf->repr->mac_rule);
- vf->repr->rule_added = false;
+ ice_rem_adv_rule_by_id(&vf->pf->hw, &vf->repr->sp_rule);
}
/**
@@ -237,6 +201,7 @@ ice_eswitch_release_reprs(struct ice_pf *pf, struct ice_vsi *ctrl_vsi)
ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);
metadata_dst_free(vf->repr->dst);
vf->repr->dst = NULL;
+ ice_eswitch_del_vf_sp_rule(vf);
ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr,
ICE_FWD_TO_VSI);
@@ -264,25 +229,30 @@ static int ice_eswitch_setup_reprs(struct ice_pf *pf)
vf->repr->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX,
GFP_KERNEL);
if (!vf->repr->dst) {
- ice_fltr_add_mac_and_broadcast(vsi,
- vf->hw_lan_addr,
+ ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr,
+ ICE_FWD_TO_VSI);
+ goto err;
+ }
+
+ if (ice_eswitch_add_vf_sp_rule(pf, vf)) {
+ ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr,
ICE_FWD_TO_VSI);
goto err;
}
if (ice_vsi_update_security(vsi, ice_vsi_ctx_clear_antispoof)) {
- ice_fltr_add_mac_and_broadcast(vsi,
- vf->hw_lan_addr,
+ ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr,
ICE_FWD_TO_VSI);
+ ice_eswitch_del_vf_sp_rule(vf);
metadata_dst_free(vf->repr->dst);
vf->repr->dst = NULL;
goto err;
}
if (ice_vsi_add_vlan_zero(vsi)) {
- ice_fltr_add_mac_and_broadcast(vsi,
- vf->hw_lan_addr,
+ ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr,
ICE_FWD_TO_VSI);
+ ice_eswitch_del_vf_sp_rule(vf);
metadata_dst_free(vf->repr->dst);
vf->repr->dst = NULL;
ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);
@@ -568,6 +538,12 @@ ice_eswitch_mode_set(struct devlink *devlink, u16 mode,
break;
case DEVLINK_ESWITCH_MODE_SWITCHDEV:
{
+ if (ice_is_adq_active(pf)) {
+ dev_err(ice_pf_to_dev(pf), "Couldn't change eswitch mode to switchdev - ADQ is active. Delete ADQ configs and try again, e.g. tc qdisc del dev $PF root");
+ NL_SET_ERR_MSG_MOD(extack, "Couldn't change eswitch mode to switchdev - ADQ is active. Delete ADQ configs and try again, e.g. tc qdisc del dev $PF root");
+ return -EOPNOTSUPP;
+ }
+
dev_info(ice_pf_to_dev(pf), "PF %d changed eswitch mode to switchdev",
pf->hw.pf_id);
NL_SET_ERR_MSG_MOD(extack, "Changed eswitch mode to switchdev");
diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.h b/drivers/net/ethernet/intel/ice/ice_eswitch.h
index 6a413331572b..b18bf83a2f5b 100644
--- a/drivers/net/ethernet/intel/ice/ice_eswitch.h
+++ b/drivers/net/ethernet/intel/ice/ice_eswitch.h
@@ -20,11 +20,6 @@ bool ice_is_eswitch_mode_switchdev(struct ice_pf *pf);
void ice_eswitch_update_repr(struct ice_vsi *vsi);
void ice_eswitch_stop_all_tx_queues(struct ice_pf *pf);
-int
-ice_eswitch_add_vf_mac_rule(struct ice_pf *pf, struct ice_vf *vf,
- const u8 *mac);
-void ice_eswitch_replay_vf_mac_rule(struct ice_vf *vf);
-void ice_eswitch_del_vf_mac_rule(struct ice_vf *vf);
void ice_eswitch_set_target_vsi(struct sk_buff *skb,
struct ice_tx_offload_params *off);
@@ -34,15 +29,6 @@ ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev);
static inline void ice_eswitch_release(struct ice_pf *pf) { }
static inline void ice_eswitch_stop_all_tx_queues(struct ice_pf *pf) { }
-static inline void ice_eswitch_replay_vf_mac_rule(struct ice_vf *vf) { }
-static inline void ice_eswitch_del_vf_mac_rule(struct ice_vf *vf) { }
-
-static inline int
-ice_eswitch_add_vf_mac_rule(struct ice_pf *pf, struct ice_vf *vf,
- const u8 *mac)
-{
- return -EOPNOTSUPP;
-}
static inline void
ice_eswitch_set_target_vsi(struct sk_buff *skb,
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c
index f86e814354a3..ad4d4702129f 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c
@@ -4,6 +4,7 @@
/* ethtool support for ice */
#include "ice.h"
+#include "ice_ethtool.h"
#include "ice_flow.h"
#include "ice_fltr.h"
#include "ice_lib.h"
@@ -956,7 +957,7 @@ static u64 ice_intr_test(struct net_device *netdev)
netdev_info(netdev, "interrupt test\n");
- wr32(&pf->hw, GLINT_DYN_CTL(pf->oicr_idx),
+ wr32(&pf->hw, GLINT_DYN_CTL(pf->oicr_irq.index),
GLINT_DYN_CTL_SW_ITR_INDX_M |
GLINT_DYN_CTL_INTENA_MSK_M |
GLINT_DYN_CTL_SWINT_TRIG_M);
@@ -1658,15 +1659,26 @@ ice_mask_min_supported_speeds(struct ice_hw *hw,
*phy_types_low &= ~ICE_PHY_TYPE_LOW_MASK_MIN_1G;
}
-#define ice_ethtool_advertise_link_mode(aq_link_speed, ethtool_link_mode) \
- do { \
- if (req_speeds & (aq_link_speed) || \
- (!req_speeds && \
- (advert_phy_type_lo & phy_type_mask_lo || \
- advert_phy_type_hi & phy_type_mask_hi))) \
- ethtool_link_ksettings_add_link_mode(ks, advertising,\
- ethtool_link_mode); \
- } while (0)
+/**
+ * ice_linkmode_set_bit - set link mode bit
+ * @phy_to_ethtool: PHY type to ethtool link mode struct to set
+ * @ks: ethtool link ksettings struct to fill out
+ * @req_speeds: speed requested by user
+ * @advert_phy_type: advertised PHY type
+ * @phy_type: PHY type
+ */
+static void
+ice_linkmode_set_bit(const struct ice_phy_type_to_ethtool *phy_to_ethtool,
+ struct ethtool_link_ksettings *ks, u32 req_speeds,
+ u64 advert_phy_type, u32 phy_type)
+{
+ linkmode_set_bit(phy_to_ethtool->link_mode, ks->link_modes.supported);
+
+ if (req_speeds & phy_to_ethtool->aq_link_speed ||
+ (!req_speeds && advert_phy_type & BIT(phy_type)))
+ linkmode_set_bit(phy_to_ethtool->link_mode,
+ ks->link_modes.advertising);
+}
/**
* ice_phy_type_to_ethtool - convert the phy_types to ethtool link modes
@@ -1682,11 +1694,10 @@ ice_phy_type_to_ethtool(struct net_device *netdev,
struct ice_pf *pf = vsi->back;
u64 advert_phy_type_lo = 0;
u64 advert_phy_type_hi = 0;
- u64 phy_type_mask_lo = 0;
- u64 phy_type_mask_hi = 0;
u64 phy_types_high = 0;
u64 phy_types_low = 0;
- u16 req_speeds;
+ u32 req_speeds;
+ u32 i;
req_speeds = vsi->port_info->phy.link_info.req_speeds;
@@ -1743,272 +1754,22 @@ ice_phy_type_to_ethtool(struct net_device *netdev,
advert_phy_type_hi = vsi->port_info->phy.phy_type_high;
}
- ethtool_link_ksettings_zero_link_mode(ks, supported);
- ethtool_link_ksettings_zero_link_mode(ks, advertising);
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_100BASE_TX |
- ICE_PHY_TYPE_LOW_100M_SGMII;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 100baseT_Full);
-
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100MB,
- 100baseT_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_1000BASE_T |
- ICE_PHY_TYPE_LOW_1G_SGMII;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 1000baseT_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_1000MB,
- 1000baseT_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_1000BASE_KX;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 1000baseKX_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_1000MB,
- 1000baseKX_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_1000BASE_SX |
- ICE_PHY_TYPE_LOW_1000BASE_LX;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 1000baseX_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_1000MB,
- 1000baseX_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_2500BASE_T;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 2500baseT_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_2500MB,
- 2500baseT_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_2500BASE_X |
- ICE_PHY_TYPE_LOW_2500BASE_KX;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 2500baseX_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_2500MB,
- 2500baseX_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_5GBASE_T |
- ICE_PHY_TYPE_LOW_5GBASE_KR;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 5000baseT_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_5GB,
- 5000baseT_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_10GBASE_T |
- ICE_PHY_TYPE_LOW_10G_SFI_DA |
- ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC |
- ICE_PHY_TYPE_LOW_10G_SFI_C2C;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 10000baseT_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_10GB,
- 10000baseT_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_10GBASE_KR_CR1;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 10000baseKR_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_10GB,
- 10000baseKR_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_10GBASE_SR;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 10000baseSR_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_10GB,
- 10000baseSR_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_10GBASE_LR;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 10000baseLR_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_10GB,
- 10000baseLR_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_25GBASE_T |
- ICE_PHY_TYPE_LOW_25GBASE_CR |
- ICE_PHY_TYPE_LOW_25GBASE_CR_S |
- ICE_PHY_TYPE_LOW_25GBASE_CR1 |
- ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC |
- ICE_PHY_TYPE_LOW_25G_AUI_C2C;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 25000baseCR_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_25GB,
- 25000baseCR_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_25GBASE_SR |
- ICE_PHY_TYPE_LOW_25GBASE_LR;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 25000baseSR_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_25GB,
- 25000baseSR_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_25GBASE_KR |
- ICE_PHY_TYPE_LOW_25GBASE_KR_S |
- ICE_PHY_TYPE_LOW_25GBASE_KR1;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 25000baseKR_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_25GB,
- 25000baseKR_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_40GBASE_KR4;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 40000baseKR4_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_40GB,
- 40000baseKR4_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_40GBASE_CR4 |
- ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC |
- ICE_PHY_TYPE_LOW_40G_XLAUI;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 40000baseCR4_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_40GB,
- 40000baseCR4_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_40GBASE_SR4;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 40000baseSR4_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_40GB,
- 40000baseSR4_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_40GBASE_LR4;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 40000baseLR4_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_40GB,
- 40000baseLR4_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_50GBASE_CR2 |
- ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC |
- ICE_PHY_TYPE_LOW_50G_LAUI2 |
- ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC |
- ICE_PHY_TYPE_LOW_50G_AUI2 |
- ICE_PHY_TYPE_LOW_50GBASE_CP |
- ICE_PHY_TYPE_LOW_50GBASE_SR |
- ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC |
- ICE_PHY_TYPE_LOW_50G_AUI1;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 50000baseCR2_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_50GB,
- 50000baseCR2_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_50GBASE_KR2 |
- ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 50000baseKR2_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_50GB,
- 50000baseKR2_Full);
- }
+ linkmode_zero(ks->link_modes.supported);
+ linkmode_zero(ks->link_modes.advertising);
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_50GBASE_SR2 |
- ICE_PHY_TYPE_LOW_50GBASE_LR2 |
- ICE_PHY_TYPE_LOW_50GBASE_FR |
- ICE_PHY_TYPE_LOW_50GBASE_LR;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 50000baseSR2_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_50GB,
- 50000baseSR2_Full);
+ for (i = 0; i < BITS_PER_TYPE(u64); i++) {
+ if (phy_types_low & BIT_ULL(i))
+ ice_linkmode_set_bit(&phy_type_low_lkup[i], ks,
+ req_speeds, advert_phy_type_lo,
+ i);
}
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_100GBASE_CR4 |
- ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC |
- ICE_PHY_TYPE_LOW_100G_CAUI4 |
- ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC |
- ICE_PHY_TYPE_LOW_100G_AUI4 |
- ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4;
- phy_type_mask_hi = ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC |
- ICE_PHY_TYPE_HIGH_100G_CAUI2 |
- ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC |
- ICE_PHY_TYPE_HIGH_100G_AUI2;
- if (phy_types_low & phy_type_mask_lo ||
- phy_types_high & phy_type_mask_hi) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 100000baseCR4_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
- 100000baseCR4_Full);
+ for (i = 0; i < BITS_PER_TYPE(u64); i++) {
+ if (phy_types_high & BIT_ULL(i))
+ ice_linkmode_set_bit(&phy_type_high_lkup[i], ks,
+ req_speeds, advert_phy_type_hi,
+ i);
}
-
- if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 100000baseCR2_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
- 100000baseCR2_Full);
- }
-
- if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR4) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 100000baseSR4_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
- 100000baseSR4_Full);
- }
-
- if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR2) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 100000baseSR2_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
- 100000baseSR2_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_100GBASE_LR4 |
- ICE_PHY_TYPE_LOW_100GBASE_DR;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 100000baseLR4_ER4_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
- 100000baseLR4_ER4_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_100GBASE_KR4 |
- ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 100000baseKR4_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
- 100000baseKR4_Full);
- }
-
- if (phy_types_high & ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 100000baseKR2_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
- 100000baseKR2_Full);
- }
-
}
#define TEST_SET_BITS_TIMEOUT 50
@@ -2920,8 +2681,13 @@ ice_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
ring->rx_max_pending = ICE_MAX_NUM_DESC;
ring->tx_max_pending = ICE_MAX_NUM_DESC;
- ring->rx_pending = vsi->rx_rings[0]->count;
- ring->tx_pending = vsi->tx_rings[0]->count;
+ if (vsi->tx_rings && vsi->rx_rings) {
+ ring->rx_pending = vsi->rx_rings[0]->count;
+ ring->tx_pending = vsi->tx_rings[0]->count;
+ } else {
+ ring->rx_pending = 0;
+ ring->tx_pending = 0;
+ }
/* Rx mini and jumbo rings are not supported */
ring->rx_mini_max_pending = 0;
@@ -2955,6 +2721,10 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
return -EINVAL;
}
+ /* Return if there is no rings (device is reloading) */
+ if (!vsi->tx_rings || !vsi->rx_rings)
+ return -EBUSY;
+
new_tx_cnt = ALIGN(ring->tx_pending, ICE_REQ_DESC_MULTIPLE);
if (new_tx_cnt != ring->tx_pending)
netdev_info(netdev, "Requested Tx descriptor count rounded up to %d\n",
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.h b/drivers/net/ethernet/intel/ice/ice_ethtool.h
new file mode 100644
index 000000000000..b403ee79cd5e
--- /dev/null
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (C) 2023 Intel Corporation */
+
+#ifndef _ICE_ETHTOOL_H_
+#define _ICE_ETHTOOL_H_
+
+struct ice_phy_type_to_ethtool {
+ u64 aq_link_speed;
+ u8 link_mode;
+};
+
+/* Macro to make PHY type to Ethtool link mode table entry.
+ * The index is the PHY type.
+ */
+#define ICE_PHY_TYPE(LINK_SPEED, ETHTOOL_LINK_MODE) {\
+ .aq_link_speed = ICE_AQ_LINK_SPEED_##LINK_SPEED, \
+ .link_mode = ETHTOOL_LINK_MODE_##ETHTOOL_LINK_MODE##_BIT, \
+}
+
+/* Lookup table mapping PHY type low to link speed and Ethtool link modes.
+ * Array index corresponds to HW PHY type bit, see
+ * ice_adminq_cmd.h:ICE_PHY_TYPE_LOW_*.
+ */
+static const struct ice_phy_type_to_ethtool
+phy_type_low_lkup[] = {
+ [0] = ICE_PHY_TYPE(100MB, 100baseT_Full),
+ [1] = ICE_PHY_TYPE(100MB, 100baseT_Full),
+ [2] = ICE_PHY_TYPE(1000MB, 1000baseT_Full),
+ [3] = ICE_PHY_TYPE(1000MB, 1000baseX_Full),
+ [4] = ICE_PHY_TYPE(1000MB, 1000baseX_Full),
+ [5] = ICE_PHY_TYPE(1000MB, 1000baseKX_Full),
+ [6] = ICE_PHY_TYPE(1000MB, 1000baseT_Full),
+ [7] = ICE_PHY_TYPE(2500MB, 2500baseT_Full),
+ [8] = ICE_PHY_TYPE(2500MB, 2500baseX_Full),
+ [9] = ICE_PHY_TYPE(2500MB, 2500baseX_Full),
+ [10] = ICE_PHY_TYPE(5GB, 5000baseT_Full),
+ [11] = ICE_PHY_TYPE(5GB, 5000baseT_Full),
+ [12] = ICE_PHY_TYPE(10GB, 10000baseT_Full),
+ [13] = ICE_PHY_TYPE(10GB, 10000baseCR_Full),
+ [14] = ICE_PHY_TYPE(10GB, 10000baseSR_Full),
+ [15] = ICE_PHY_TYPE(10GB, 10000baseLR_Full),
+ [16] = ICE_PHY_TYPE(10GB, 10000baseKR_Full),
+ [17] = ICE_PHY_TYPE(10GB, 10000baseCR_Full),
+ [18] = ICE_PHY_TYPE(10GB, 10000baseKR_Full),
+ [19] = ICE_PHY_TYPE(25GB, 25000baseCR_Full),
+ [20] = ICE_PHY_TYPE(25GB, 25000baseCR_Full),
+ [21] = ICE_PHY_TYPE(25GB, 25000baseCR_Full),
+ [22] = ICE_PHY_TYPE(25GB, 25000baseCR_Full),
+ [23] = ICE_PHY_TYPE(25GB, 25000baseSR_Full),
+ [24] = ICE_PHY_TYPE(25GB, 25000baseSR_Full),
+ [25] = ICE_PHY_TYPE(25GB, 25000baseKR_Full),
+ [26] = ICE_PHY_TYPE(25GB, 25000baseKR_Full),
+ [27] = ICE_PHY_TYPE(25GB, 25000baseKR_Full),
+ [28] = ICE_PHY_TYPE(25GB, 25000baseSR_Full),
+ [29] = ICE_PHY_TYPE(25GB, 25000baseCR_Full),
+ [30] = ICE_PHY_TYPE(40GB, 40000baseCR4_Full),
+ [31] = ICE_PHY_TYPE(40GB, 40000baseSR4_Full),
+ [32] = ICE_PHY_TYPE(40GB, 40000baseLR4_Full),
+ [33] = ICE_PHY_TYPE(40GB, 40000baseKR4_Full),
+ [34] = ICE_PHY_TYPE(40GB, 40000baseSR4_Full),
+ [35] = ICE_PHY_TYPE(40GB, 40000baseCR4_Full),
+ [36] = ICE_PHY_TYPE(50GB, 50000baseCR2_Full),
+ [37] = ICE_PHY_TYPE(50GB, 50000baseSR2_Full),
+ [38] = ICE_PHY_TYPE(50GB, 50000baseSR2_Full),
+ [39] = ICE_PHY_TYPE(50GB, 50000baseKR2_Full),
+ [40] = ICE_PHY_TYPE(50GB, 50000baseSR2_Full),
+ [41] = ICE_PHY_TYPE(50GB, 50000baseCR2_Full),
+ [42] = ICE_PHY_TYPE(50GB, 50000baseSR2_Full),
+ [43] = ICE_PHY_TYPE(50GB, 50000baseCR2_Full),
+ [44] = ICE_PHY_TYPE(50GB, 50000baseCR_Full),
+ [45] = ICE_PHY_TYPE(50GB, 50000baseSR_Full),
+ [46] = ICE_PHY_TYPE(50GB, 50000baseLR_ER_FR_Full),
+ [47] = ICE_PHY_TYPE(50GB, 50000baseLR_ER_FR_Full),
+ [48] = ICE_PHY_TYPE(50GB, 50000baseKR_Full),
+ [49] = ICE_PHY_TYPE(50GB, 50000baseSR_Full),
+ [50] = ICE_PHY_TYPE(50GB, 50000baseCR_Full),
+ [51] = ICE_PHY_TYPE(100GB, 100000baseCR4_Full),
+ [52] = ICE_PHY_TYPE(100GB, 100000baseSR4_Full),
+ [53] = ICE_PHY_TYPE(100GB, 100000baseLR4_ER4_Full),
+ [54] = ICE_PHY_TYPE(100GB, 100000baseKR4_Full),
+ [55] = ICE_PHY_TYPE(100GB, 100000baseCR4_Full),
+ [56] = ICE_PHY_TYPE(100GB, 100000baseCR4_Full),
+ [57] = ICE_PHY_TYPE(100GB, 100000baseSR4_Full),
+ [58] = ICE_PHY_TYPE(100GB, 100000baseCR4_Full),
+ [59] = ICE_PHY_TYPE(100GB, 100000baseCR4_Full),
+ [60] = ICE_PHY_TYPE(100GB, 100000baseKR4_Full),
+ [61] = ICE_PHY_TYPE(100GB, 100000baseCR2_Full),
+ [62] = ICE_PHY_TYPE(100GB, 100000baseSR2_Full),
+ [63] = ICE_PHY_TYPE(100GB, 100000baseLR4_ER4_Full),
+};
+
+/* Lookup table mapping PHY type high to link speed and Ethtool link modes.
+ * Array index corresponds to HW PHY type bit, see
+ * ice_adminq_cmd.h:ICE_PHY_TYPE_HIGH_*
+ */
+static const struct ice_phy_type_to_ethtool
+phy_type_high_lkup[] = {
+ [0] = ICE_PHY_TYPE(100GB, 100000baseKR2_Full),
+ [1] = ICE_PHY_TYPE(100GB, 100000baseSR2_Full),
+ [2] = ICE_PHY_TYPE(100GB, 100000baseCR2_Full),
+ [3] = ICE_PHY_TYPE(100GB, 100000baseSR2_Full),
+ [4] = ICE_PHY_TYPE(100GB, 100000baseCR2_Full),
+};
+
+#endif /* !_ICE_ETHTOOL_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
index ead6d50fc0ad..8c6e13f87b7d 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
@@ -1281,16 +1281,21 @@ ice_cfg_fdir_xtrct_seq(struct ice_pf *pf, struct ethtool_rx_flow_spec *fsp,
ICE_FLOW_FLD_OFF_INVAL);
}
- /* add filter for outer headers */
fltr_idx = ice_ethtool_flow_to_fltr(fsp->flow_type & ~FLOW_EXT);
+
+ assign_bit(fltr_idx, hw->fdir_perfect_fltr, perfect_filter);
+
+ /* add filter for outer headers */
ret = ice_fdir_set_hw_fltr_rule(pf, seg, fltr_idx,
ICE_FD_HW_SEG_NON_TUN);
- if (ret == -EEXIST)
- /* Rule already exists, free memory and continue */
- devm_kfree(dev, seg);
- else if (ret)
+ if (ret == -EEXIST) {
+ /* Rule already exists, free memory and count as success */
+ ret = 0;
+ goto err_exit;
+ } else if (ret) {
/* could not write filter, free memory */
goto err_exit;
+ }
/* make tunneled filter HW entries if possible */
memcpy(&tun_seg[1], seg, sizeof(*seg));
@@ -1305,18 +1310,13 @@ ice_cfg_fdir_xtrct_seq(struct ice_pf *pf, struct ethtool_rx_flow_spec *fsp,
devm_kfree(dev, tun_seg);
}
- if (perfect_filter)
- set_bit(fltr_idx, hw->fdir_perfect_fltr);
- else
- clear_bit(fltr_idx, hw->fdir_perfect_fltr);
-
return ret;
err_exit:
devm_kfree(dev, tun_seg);
devm_kfree(dev, seg);
- return -EOPNOTSUPP;
+ return ret;
}
/**
@@ -1914,7 +1914,9 @@ int ice_add_fdir_ethtool(struct ice_vsi *vsi, struct ethtool_rxnfc *cmd)
input->comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW_FAIL;
/* input struct is added to the HW filter list */
- ice_fdir_update_list_entry(pf, input, fsp->location);
+ ret = ice_fdir_update_list_entry(pf, input, fsp->location);
+ if (ret)
+ goto release_lock;
ret = ice_fdir_write_all_fltr(pf, input, true);
if (ret)
diff --git a/drivers/net/ethernet/intel/ice/ice_flow.c b/drivers/net/ethernet/intel/ice/ice_flow.c
index ef103e47a8dc..85cca572c22a 100644
--- a/drivers/net/ethernet/intel/ice/ice_flow.c
+++ b/drivers/net/ethernet/intel/ice/ice_flow.c
@@ -1304,23 +1304,6 @@ ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
}
/**
- * ice_dealloc_flow_entry - Deallocate flow entry memory
- * @hw: pointer to the HW struct
- * @entry: flow entry to be removed
- */
-static void
-ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
-{
- if (!entry)
- return;
-
- if (entry->entry)
- devm_kfree(ice_hw_to_dev(hw), entry->entry);
-
- devm_kfree(ice_hw_to_dev(hw), entry);
-}
-
-/**
* ice_flow_rem_entry_sync - Remove a flow entry
* @hw: pointer to the HW struct
* @blk: classification stage
@@ -1335,7 +1318,8 @@ ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,
list_del(&entry->l_entry);
- ice_dealloc_flow_entry(hw, entry);
+ devm_kfree(ice_hw_to_dev(hw), entry->entry);
+ devm_kfree(ice_hw_to_dev(hw), entry);
return 0;
}
@@ -1662,8 +1646,7 @@ ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
out:
if (status && e) {
- if (e->entry)
- devm_kfree(ice_hw_to_dev(hw), e->entry);
+ devm_kfree(ice_hw_to_dev(hw), e->entry);
devm_kfree(ice_hw_to_dev(hw), e);
}
diff --git a/drivers/net/ethernet/intel/ice/ice_idc.c b/drivers/net/ethernet/intel/ice/ice_idc.c
index e6bc2285071e..145b27f2a4ce 100644
--- a/drivers/net/ethernet/intel/ice/ice_idc.c
+++ b/drivers/net/ethernet/intel/ice/ice_idc.c
@@ -229,20 +229,34 @@ void ice_get_qos_params(struct ice_pf *pf, struct iidc_qos_params *qos)
EXPORT_SYMBOL_GPL(ice_get_qos_params);
/**
- * ice_reserve_rdma_qvector - Reserve vector resources for RDMA driver
+ * ice_alloc_rdma_qvectors - Allocate vector resources for RDMA driver
* @pf: board private structure to initialize
*/
-static int ice_reserve_rdma_qvector(struct ice_pf *pf)
+static int ice_alloc_rdma_qvectors(struct ice_pf *pf)
{
if (ice_is_rdma_ena(pf)) {
- int index;
-
- index = ice_get_res(pf, pf->irq_tracker, pf->num_rdma_msix,
- ICE_RES_RDMA_VEC_ID);
- if (index < 0)
- return index;
- pf->num_avail_sw_msix -= pf->num_rdma_msix;
- pf->rdma_base_vector = (u16)index;
+ int i;
+
+ pf->msix_entries = kcalloc(pf->num_rdma_msix,
+ sizeof(*pf->msix_entries),
+ GFP_KERNEL);
+ if (!pf->msix_entries)
+ return -ENOMEM;
+
+ /* RDMA is the only user of pf->msix_entries array */
+ pf->rdma_base_vector = 0;
+
+ for (i = 0; i < pf->num_rdma_msix; i++) {
+ struct msix_entry *entry = &pf->msix_entries[i];
+ struct msi_map map;
+
+ map = ice_alloc_irq(pf, false);
+ if (map.index < 0)
+ break;
+
+ entry->entry = map.index;
+ entry->vector = map.virq;
+ }
}
return 0;
}
@@ -253,9 +267,21 @@ static int ice_reserve_rdma_qvector(struct ice_pf *pf)
*/
static void ice_free_rdma_qvector(struct ice_pf *pf)
{
- pf->num_avail_sw_msix -= pf->num_rdma_msix;
- ice_free_res(pf->irq_tracker, pf->rdma_base_vector,
- ICE_RES_RDMA_VEC_ID);
+ int i;
+
+ if (!pf->msix_entries)
+ return;
+
+ for (i = 0; i < pf->num_rdma_msix; i++) {
+ struct msi_map map;
+
+ map.index = pf->msix_entries[i].entry;
+ map.virq = pf->msix_entries[i].vector;
+ ice_free_irq(pf, map);
+ }
+
+ kfree(pf->msix_entries);
+ pf->msix_entries = NULL;
}
/**
@@ -357,7 +383,7 @@ int ice_init_rdma(struct ice_pf *pf)
}
/* Reserve vector resources */
- ret = ice_reserve_rdma_qvector(pf);
+ ret = ice_alloc_rdma_qvectors(pf);
if (ret < 0) {
dev_err(dev, "failed to reserve vectors for RDMA\n");
goto err_reserve_rdma_qvector;
diff --git a/drivers/net/ethernet/intel/ice/ice_irq.c b/drivers/net/ethernet/intel/ice/ice_irq.c
new file mode 100644
index 000000000000..ad82ff7d1995
--- /dev/null
+++ b/drivers/net/ethernet/intel/ice/ice_irq.c
@@ -0,0 +1,378 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2023, Intel Corporation. */
+
+#include "ice.h"
+#include "ice_lib.h"
+#include "ice_irq.h"
+
+/**
+ * ice_init_irq_tracker - initialize interrupt tracker
+ * @pf: board private structure
+ * @max_vectors: maximum number of vectors that tracker can hold
+ * @num_static: number of preallocated interrupts
+ */
+static void
+ice_init_irq_tracker(struct ice_pf *pf, unsigned int max_vectors,
+ unsigned int num_static)
+{
+ pf->irq_tracker.num_entries = max_vectors;
+ pf->irq_tracker.num_static = num_static;
+ xa_init_flags(&pf->irq_tracker.entries, XA_FLAGS_ALLOC);
+}
+
+/**
+ * ice_deinit_irq_tracker - free xarray tracker
+ * @pf: board private structure
+ */
+static void ice_deinit_irq_tracker(struct ice_pf *pf)
+{
+ xa_destroy(&pf->irq_tracker.entries);
+}
+
+/**
+ * ice_free_irq_res - free a block of resources
+ * @pf: board private structure
+ * @index: starting index previously returned by ice_get_res
+ */
+static void ice_free_irq_res(struct ice_pf *pf, u16 index)
+{
+ struct ice_irq_entry *entry;
+
+ entry = xa_erase(&pf->irq_tracker.entries, index);
+ kfree(entry);
+}
+
+/**
+ * ice_get_irq_res - get an interrupt resource
+ * @pf: board private structure
+ * @dyn_only: force entry to be dynamically allocated
+ *
+ * Allocate new irq entry in the free slot of the tracker. Since xarray
+ * is used, always allocate new entry at the lowest possible index. Set
+ * proper allocation limit for maximum tracker entries.
+ *
+ * Returns allocated irq entry or NULL on failure.
+ */
+static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf, bool dyn_only)
+{
+ struct xa_limit limit = { .max = pf->irq_tracker.num_entries,
+ .min = 0 };
+ unsigned int num_static = pf->irq_tracker.num_static;
+ struct ice_irq_entry *entry;
+ unsigned int index;
+ int ret;
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return NULL;
+
+ /* skip preallocated entries if the caller says so */
+ if (dyn_only)
+ limit.min = num_static;
+
+ ret = xa_alloc(&pf->irq_tracker.entries, &index, entry, limit,
+ GFP_KERNEL);
+
+ if (ret) {
+ kfree(entry);
+ entry = NULL;
+ } else {
+ entry->index = index;
+ entry->dynamic = index >= num_static;
+ }
+
+ return entry;
+}
+
+/**
+ * ice_reduce_msix_usage - Reduce usage of MSI-X vectors
+ * @pf: board private structure
+ * @v_remain: number of remaining MSI-X vectors to be distributed
+ *
+ * Reduce the usage of MSI-X vectors when entire request cannot be fulfilled.
+ * pf->num_lan_msix and pf->num_rdma_msix values are set based on number of
+ * remaining vectors.
+ */
+static void ice_reduce_msix_usage(struct ice_pf *pf, int v_remain)
+{
+ int v_rdma;
+
+ if (!ice_is_rdma_ena(pf)) {
+ pf->num_lan_msix = v_remain;
+ return;
+ }
+
+ /* RDMA needs at least 1 interrupt in addition to AEQ MSIX */
+ v_rdma = ICE_RDMA_NUM_AEQ_MSIX + 1;
+
+ if (v_remain < ICE_MIN_LAN_TXRX_MSIX + ICE_MIN_RDMA_MSIX) {
+ dev_warn(ice_pf_to_dev(pf), "Not enough MSI-X vectors to support RDMA.\n");
+ clear_bit(ICE_FLAG_RDMA_ENA, pf->flags);
+
+ pf->num_rdma_msix = 0;
+ pf->num_lan_msix = ICE_MIN_LAN_TXRX_MSIX;
+ } else if ((v_remain < ICE_MIN_LAN_TXRX_MSIX + v_rdma) ||
+ (v_remain - v_rdma < v_rdma)) {
+ /* Support minimum RDMA and give remaining vectors to LAN MSIX
+ */
+ pf->num_rdma_msix = ICE_MIN_RDMA_MSIX;
+ pf->num_lan_msix = v_remain - ICE_MIN_RDMA_MSIX;
+ } else {
+ /* Split remaining MSIX with RDMA after accounting for AEQ MSIX
+ */
+ pf->num_rdma_msix = (v_remain - ICE_RDMA_NUM_AEQ_MSIX) / 2 +
+ ICE_RDMA_NUM_AEQ_MSIX;
+ pf->num_lan_msix = v_remain - pf->num_rdma_msix;
+ }
+}
+
+/**
+ * ice_ena_msix_range - Request a range of MSIX vectors from the OS
+ * @pf: board private structure
+ *
+ * Compute the number of MSIX vectors wanted and request from the OS. Adjust
+ * device usage if there are not enough vectors. Return the number of vectors
+ * reserved or negative on failure.
+ */
+static int ice_ena_msix_range(struct ice_pf *pf)
+{
+ int num_cpus, hw_num_msix, v_other, v_wanted, v_actual;
+ struct device *dev = ice_pf_to_dev(pf);
+ int err;
+
+ hw_num_msix = pf->hw.func_caps.common_cap.num_msix_vectors;
+ num_cpus = num_online_cpus();
+
+ /* LAN miscellaneous handler */
+ v_other = ICE_MIN_LAN_OICR_MSIX;
+
+ /* Flow Director */
+ if (test_bit(ICE_FLAG_FD_ENA, pf->flags))
+ v_other += ICE_FDIR_MSIX;
+
+ /* switchdev */
+ v_other += ICE_ESWITCH_MSIX;
+
+ v_wanted = v_other;
+
+ /* LAN traffic */
+ pf->num_lan_msix = num_cpus;
+ v_wanted += pf->num_lan_msix;
+
+ /* RDMA auxiliary driver */
+ if (ice_is_rdma_ena(pf)) {
+ pf->num_rdma_msix = num_cpus + ICE_RDMA_NUM_AEQ_MSIX;
+ v_wanted += pf->num_rdma_msix;
+ }
+
+ if (v_wanted > hw_num_msix) {
+ int v_remain;
+
+ dev_warn(dev, "not enough device MSI-X vectors. wanted = %d, available = %d\n",
+ v_wanted, hw_num_msix);
+
+ if (hw_num_msix < ICE_MIN_MSIX) {
+ err = -ERANGE;
+ goto exit_err;
+ }
+
+ v_remain = hw_num_msix - v_other;
+ if (v_remain < ICE_MIN_LAN_TXRX_MSIX) {
+ v_other = ICE_MIN_MSIX - ICE_MIN_LAN_TXRX_MSIX;
+ v_remain = ICE_MIN_LAN_TXRX_MSIX;
+ }
+
+ ice_reduce_msix_usage(pf, v_remain);
+ v_wanted = pf->num_lan_msix + pf->num_rdma_msix + v_other;
+
+ dev_notice(dev, "Reducing request to %d MSI-X vectors for LAN traffic.\n",
+ pf->num_lan_msix);
+ if (ice_is_rdma_ena(pf))
+ dev_notice(dev, "Reducing request to %d MSI-X vectors for RDMA.\n",
+ pf->num_rdma_msix);
+ }
+
+ /* actually reserve the vectors */
+ v_actual = pci_alloc_irq_vectors(pf->pdev, ICE_MIN_MSIX, v_wanted,
+ PCI_IRQ_MSIX);
+ if (v_actual < 0) {
+ dev_err(dev, "unable to reserve MSI-X vectors\n");
+ err = v_actual;
+ goto exit_err;
+ }
+
+ if (v_actual < v_wanted) {
+ dev_warn(dev, "not enough OS MSI-X vectors. requested = %d, obtained = %d\n",
+ v_wanted, v_actual);
+
+ if (v_actual < ICE_MIN_MSIX) {
+ /* error if we can't get minimum vectors */
+ pci_free_irq_vectors(pf->pdev);
+ err = -ERANGE;
+ goto exit_err;
+ } else {
+ int v_remain = v_actual - v_other;
+
+ if (v_remain < ICE_MIN_LAN_TXRX_MSIX)
+ v_remain = ICE_MIN_LAN_TXRX_MSIX;
+
+ ice_reduce_msix_usage(pf, v_remain);
+
+ dev_notice(dev, "Enabled %d MSI-X vectors for LAN traffic.\n",
+ pf->num_lan_msix);
+
+ if (ice_is_rdma_ena(pf))
+ dev_notice(dev, "Enabled %d MSI-X vectors for RDMA.\n",
+ pf->num_rdma_msix);
+ }
+ }
+
+ return v_actual;
+
+exit_err:
+ pf->num_rdma_msix = 0;
+ pf->num_lan_msix = 0;
+ return err;
+}
+
+/**
+ * ice_clear_interrupt_scheme - Undo things done by ice_init_interrupt_scheme
+ * @pf: board private structure
+ */
+void ice_clear_interrupt_scheme(struct ice_pf *pf)
+{
+ pci_free_irq_vectors(pf->pdev);
+ ice_deinit_irq_tracker(pf);
+}
+
+/**
+ * ice_init_interrupt_scheme - Determine proper interrupt scheme
+ * @pf: board private structure to initialize
+ */
+int ice_init_interrupt_scheme(struct ice_pf *pf)
+{
+ int total_vectors = pf->hw.func_caps.common_cap.num_msix_vectors;
+ int vectors, max_vectors;
+
+ vectors = ice_ena_msix_range(pf);
+
+ if (vectors < 0)
+ return -ENOMEM;
+
+ if (pci_msix_can_alloc_dyn(pf->pdev))
+ max_vectors = total_vectors;
+ else
+ max_vectors = vectors;
+
+ ice_init_irq_tracker(pf, max_vectors, vectors);
+
+ return 0;
+}
+
+/**
+ * ice_alloc_irq - Allocate new interrupt vector
+ * @pf: board private structure
+ * @dyn_only: force dynamic allocation of the interrupt
+ *
+ * Allocate new interrupt vector for a given owner id.
+ * return struct msi_map with interrupt details and track
+ * allocated interrupt appropriately.
+ *
+ * This function reserves new irq entry from the irq_tracker.
+ * if according to the tracker information all interrupts that
+ * were allocated with ice_pci_alloc_irq_vectors are already used
+ * and dynamically allocated interrupts are supported then new
+ * interrupt will be allocated with pci_msix_alloc_irq_at.
+ *
+ * Some callers may only support dynamically allocated interrupts.
+ * This is indicated with dyn_only flag.
+ *
+ * On failure, return map with negative .index. The caller
+ * is expected to check returned map index.
+ *
+ */
+struct msi_map ice_alloc_irq(struct ice_pf *pf, bool dyn_only)
+{
+ int sriov_base_vector = pf->sriov_base_vector;
+ struct msi_map map = { .index = -ENOENT };
+ struct device *dev = ice_pf_to_dev(pf);
+ struct ice_irq_entry *entry;
+
+ entry = ice_get_irq_res(pf, dyn_only);
+ if (!entry)
+ return map;
+
+ /* fail if we're about to violate SRIOV vectors space */
+ if (sriov_base_vector && entry->index >= sriov_base_vector)
+ goto exit_free_res;
+
+ if (pci_msix_can_alloc_dyn(pf->pdev) && entry->dynamic) {
+ map = pci_msix_alloc_irq_at(pf->pdev, entry->index, NULL);
+ if (map.index < 0)
+ goto exit_free_res;
+ dev_dbg(dev, "allocated new irq at index %d\n", map.index);
+ } else {
+ map.index = entry->index;
+ map.virq = pci_irq_vector(pf->pdev, map.index);
+ }
+
+ return map;
+
+exit_free_res:
+ dev_err(dev, "Could not allocate irq at idx %d\n", entry->index);
+ ice_free_irq_res(pf, entry->index);
+ return map;
+}
+
+/**
+ * ice_free_irq - Free interrupt vector
+ * @pf: board private structure
+ * @map: map with interrupt details
+ *
+ * Remove allocated interrupt from the interrupt tracker. If interrupt was
+ * allocated dynamically, free respective interrupt vector.
+ */
+void ice_free_irq(struct ice_pf *pf, struct msi_map map)
+{
+ struct ice_irq_entry *entry;
+
+ entry = xa_load(&pf->irq_tracker.entries, map.index);
+
+ if (!entry) {
+ dev_err(ice_pf_to_dev(pf), "Failed to get MSIX interrupt entry at index %d",
+ map.index);
+ return;
+ }
+
+ dev_dbg(ice_pf_to_dev(pf), "Free irq at index %d\n", map.index);
+
+ if (entry->dynamic)
+ pci_msix_free_irq(pf->pdev, map);
+
+ ice_free_irq_res(pf, map.index);
+}
+
+/**
+ * ice_get_max_used_msix_vector - Get the max used interrupt vector
+ * @pf: board private structure
+ *
+ * Return index of maximum used interrupt vectors with respect to the
+ * beginning of the MSIX table. Take into account that some interrupts
+ * may have been dynamically allocated after MSIX was initially enabled.
+ */
+int ice_get_max_used_msix_vector(struct ice_pf *pf)
+{
+ unsigned long start, index, max_idx;
+ void *entry;
+
+ /* Treat all preallocated interrupts as used */
+ start = pf->irq_tracker.num_static;
+ max_idx = start - 1;
+
+ xa_for_each_start(&pf->irq_tracker.entries, index, entry, start) {
+ if (index > max_idx)
+ max_idx = index;
+ }
+
+ return max_idx;
+}
diff --git a/drivers/net/ethernet/intel/ice/ice_irq.h b/drivers/net/ethernet/intel/ice/ice_irq.h
new file mode 100644
index 000000000000..f35efc08575e
--- /dev/null
+++ b/drivers/net/ethernet/intel/ice/ice_irq.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2023, Intel Corporation. */
+
+#ifndef _ICE_IRQ_H_
+#define _ICE_IRQ_H_
+
+struct ice_irq_entry {
+ unsigned int index;
+ bool dynamic; /* allocation type flag */
+};
+
+struct ice_irq_tracker {
+ struct xarray entries;
+ u16 num_entries; /* total vectors available */
+ u16 num_static; /* preallocated entries */
+};
+
+int ice_init_interrupt_scheme(struct ice_pf *pf);
+void ice_clear_interrupt_scheme(struct ice_pf *pf);
+
+struct msi_map ice_alloc_irq(struct ice_pf *pf, bool dyn_only);
+void ice_free_irq(struct ice_pf *pf, struct msi_map map);
+int ice_get_max_used_msix_vector(struct ice_pf *pf);
+
+#endif
diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c
index ee5b36941ba3..5a7753bda324 100644
--- a/drivers/net/ethernet/intel/ice/ice_lag.c
+++ b/drivers/net/ethernet/intel/ice/ice_lag.c
@@ -7,15 +7,6 @@
#include "ice_lag.h"
/**
- * ice_lag_nop_handler - no-op Rx handler to disable LAG
- * @pskb: pointer to skb pointer
- */
-rx_handler_result_t ice_lag_nop_handler(struct sk_buff __always_unused **pskb)
-{
- return RX_HANDLER_PASS;
-}
-
-/**
* ice_lag_set_primary - set PF LAG state as Primary
* @lag: LAG info struct
*/
@@ -158,7 +149,6 @@ ice_lag_link(struct ice_lag *lag, struct netdev_notifier_changeupper_info *info)
lag->upper_netdev = upper;
}
- ice_clear_sriov_cap(pf);
ice_clear_rdma_cap(pf);
lag->bonded = true;
@@ -205,7 +195,6 @@ ice_lag_unlink(struct ice_lag *lag,
}
lag->peer_netdev = NULL;
- ice_set_sriov_cap(pf);
ice_set_rdma_cap(pf);
lag->bonded = false;
lag->role = ICE_LAG_NONE;
@@ -229,7 +218,6 @@ static void ice_lag_unregister(struct ice_lag *lag, struct net_device *netdev)
if (lag->upper_netdev) {
dev_put(lag->upper_netdev);
lag->upper_netdev = NULL;
- ice_set_sriov_cap(pf);
ice_set_rdma_cap(pf);
}
/* perform some cleanup in case we come back */
diff --git a/drivers/net/ethernet/intel/ice/ice_lag.h b/drivers/net/ethernet/intel/ice/ice_lag.h
index 51b5cf467ce2..2c373676c42f 100644
--- a/drivers/net/ethernet/intel/ice/ice_lag.h
+++ b/drivers/net/ethernet/intel/ice/ice_lag.h
@@ -25,63 +25,9 @@ struct ice_lag {
struct notifier_block notif_block;
u8 bonded:1; /* currently bonded */
u8 primary:1; /* this is primary */
- u8 handler:1; /* did we register a rx_netdev_handler */
- /* each thing blocking bonding will increment this value by one.
- * If this value is zero, then bonding is allowed.
- */
- u16 dis_lag;
u8 role;
};
int ice_init_lag(struct ice_pf *pf);
void ice_deinit_lag(struct ice_pf *pf);
-rx_handler_result_t ice_lag_nop_handler(struct sk_buff **pskb);
-
-/**
- * ice_disable_lag - increment LAG disable count
- * @lag: LAG struct
- */
-static inline void ice_disable_lag(struct ice_lag *lag)
-{
- /* If LAG this PF is not already disabled, disable it */
- rtnl_lock();
- if (!netdev_is_rx_handler_busy(lag->netdev)) {
- if (!netdev_rx_handler_register(lag->netdev,
- ice_lag_nop_handler,
- NULL))
- lag->handler = true;
- }
- rtnl_unlock();
- lag->dis_lag++;
-}
-
-/**
- * ice_enable_lag - decrement disable count for a PF
- * @lag: LAG struct
- *
- * Decrement the disable counter for a port, and if that count reaches
- * zero, then remove the no-op Rx handler from that netdev
- */
-static inline void ice_enable_lag(struct ice_lag *lag)
-{
- if (lag->dis_lag)
- lag->dis_lag--;
- if (!lag->dis_lag && lag->handler) {
- rtnl_lock();
- netdev_rx_handler_unregister(lag->netdev);
- rtnl_unlock();
- lag->handler = false;
- }
-}
-
-/**
- * ice_is_lag_dis - is LAG disabled
- * @lag: LAG struct
- *
- * Return true if bonding is disabled
- */
-static inline bool ice_is_lag_dis(struct ice_lag *lag)
-{
- return !!(lag->dis_lag);
-}
#endif /* _ICE_LAG_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
index 11ae0e41f518..0054d7e64ec3 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -321,31 +321,19 @@ static void ice_vsi_free_arrays(struct ice_vsi *vsi)
dev = ice_pf_to_dev(pf);
- if (vsi->af_xdp_zc_qps) {
- bitmap_free(vsi->af_xdp_zc_qps);
- vsi->af_xdp_zc_qps = NULL;
- }
+ bitmap_free(vsi->af_xdp_zc_qps);
+ vsi->af_xdp_zc_qps = NULL;
/* free the ring and vector containers */
- if (vsi->q_vectors) {
- devm_kfree(dev, vsi->q_vectors);
- vsi->q_vectors = NULL;
- }
- if (vsi->tx_rings) {
- devm_kfree(dev, vsi->tx_rings);
- vsi->tx_rings = NULL;
- }
- if (vsi->rx_rings) {
- devm_kfree(dev, vsi->rx_rings);
- vsi->rx_rings = NULL;
- }
- if (vsi->txq_map) {
- devm_kfree(dev, vsi->txq_map);
- vsi->txq_map = NULL;
- }
- if (vsi->rxq_map) {
- devm_kfree(dev, vsi->rxq_map);
- vsi->rxq_map = NULL;
- }
+ devm_kfree(dev, vsi->q_vectors);
+ vsi->q_vectors = NULL;
+ devm_kfree(dev, vsi->tx_rings);
+ vsi->tx_rings = NULL;
+ devm_kfree(dev, vsi->rx_rings);
+ vsi->rx_rings = NULL;
+ devm_kfree(dev, vsi->txq_map);
+ vsi->txq_map = NULL;
+ devm_kfree(dev, vsi->rxq_map);
+ vsi->rxq_map = NULL;
}
/**
@@ -902,10 +890,8 @@ static void ice_rss_clean(struct ice_vsi *vsi)
dev = ice_pf_to_dev(pf);
- if (vsi->rss_hkey_user)
- devm_kfree(dev, vsi->rss_hkey_user);
- if (vsi->rss_lut_user)
- devm_kfree(dev, vsi->rss_lut_user);
+ devm_kfree(dev, vsi->rss_hkey_user);
+ devm_kfree(dev, vsi->rss_lut_user);
ice_vsi_clean_rss_flow_fld(vsi);
/* remove RSS replay list */
@@ -1371,190 +1357,6 @@ out:
}
/**
- * ice_free_res - free a block of resources
- * @res: pointer to the resource
- * @index: starting index previously returned by ice_get_res
- * @id: identifier to track owner
- *
- * Returns number of resources freed
- */
-int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id)
-{
- int count = 0;
- int i;
-
- if (!res || index >= res->end)
- return -EINVAL;
-
- id |= ICE_RES_VALID_BIT;
- for (i = index; i < res->end && res->list[i] == id; i++) {
- res->list[i] = 0;
- count++;
- }
-
- return count;
-}
-
-/**
- * ice_search_res - Search the tracker for a block of resources
- * @res: pointer to the resource
- * @needed: size of the block needed
- * @id: identifier to track owner
- *
- * Returns the base item index of the block, or -ENOMEM for error
- */
-static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id)
-{
- u16 start = 0, end = 0;
-
- if (needed > res->end)
- return -ENOMEM;
-
- id |= ICE_RES_VALID_BIT;
-
- do {
- /* skip already allocated entries */
- if (res->list[end++] & ICE_RES_VALID_BIT) {
- start = end;
- if ((start + needed) > res->end)
- break;
- }
-
- if (end == (start + needed)) {
- int i = start;
-
- /* there was enough, so assign it to the requestor */
- while (i != end)
- res->list[i++] = id;
-
- return start;
- }
- } while (end < res->end);
-
- return -ENOMEM;
-}
-
-/**
- * ice_get_free_res_count - Get free count from a resource tracker
- * @res: Resource tracker instance
- */
-static u16 ice_get_free_res_count(struct ice_res_tracker *res)
-{
- u16 i, count = 0;
-
- for (i = 0; i < res->end; i++)
- if (!(res->list[i] & ICE_RES_VALID_BIT))
- count++;
-
- return count;
-}
-
-/**
- * ice_get_res - get a block of resources
- * @pf: board private structure
- * @res: pointer to the resource
- * @needed: size of the block needed
- * @id: identifier to track owner
- *
- * Returns the base item index of the block, or negative for error
- */
-int
-ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id)
-{
- if (!res || !pf)
- return -EINVAL;
-
- if (!needed || needed > res->num_entries || id >= ICE_RES_VALID_BIT) {
- dev_err(ice_pf_to_dev(pf), "param err: needed=%d, num_entries = %d id=0x%04x\n",
- needed, res->num_entries, id);
- return -EINVAL;
- }
-
- return ice_search_res(res, needed, id);
-}
-
-/**
- * ice_get_vf_ctrl_res - Get VF control VSI resource
- * @pf: pointer to the PF structure
- * @vsi: the VSI to allocate a resource for
- *
- * Look up whether another VF has already allocated the control VSI resource.
- * If so, re-use this resource so that we share it among all VFs.
- *
- * Otherwise, allocate the resource and return it.
- */
-static int ice_get_vf_ctrl_res(struct ice_pf *pf, struct ice_vsi *vsi)
-{
- struct ice_vf *vf;
- unsigned int bkt;
- int base;
-
- rcu_read_lock();
- ice_for_each_vf_rcu(pf, bkt, vf) {
- if (vf != vsi->vf && vf->ctrl_vsi_idx != ICE_NO_VSI) {
- base = pf->vsi[vf->ctrl_vsi_idx]->base_vector;
- rcu_read_unlock();
- return base;
- }
- }
- rcu_read_unlock();
-
- return ice_get_res(pf, pf->irq_tracker, vsi->num_q_vectors,
- ICE_RES_VF_CTRL_VEC_ID);
-}
-
-/**
- * ice_vsi_setup_vector_base - Set up the base vector for the given VSI
- * @vsi: ptr to the VSI
- *
- * This should only be called after ice_vsi_alloc_def() which allocates the
- * corresponding SW VSI structure and initializes num_queue_pairs for the
- * newly allocated VSI.
- *
- * Returns 0 on success or negative on failure
- */
-static int ice_vsi_setup_vector_base(struct ice_vsi *vsi)
-{
- struct ice_pf *pf = vsi->back;
- struct device *dev;
- u16 num_q_vectors;
- int base;
-
- dev = ice_pf_to_dev(pf);
- /* SRIOV doesn't grab irq_tracker entries for each VSI */
- if (vsi->type == ICE_VSI_VF)
- return 0;
- if (vsi->type == ICE_VSI_CHNL)
- return 0;
-
- if (vsi->base_vector) {
- dev_dbg(dev, "VSI %d has non-zero base vector %d\n",
- vsi->vsi_num, vsi->base_vector);
- return -EEXIST;
- }
-
- num_q_vectors = vsi->num_q_vectors;
- /* reserve slots from OS requested IRQs */
- if (vsi->type == ICE_VSI_CTRL && vsi->vf) {
- base = ice_get_vf_ctrl_res(pf, vsi);
- } else {
- base = ice_get_res(pf, pf->irq_tracker, num_q_vectors,
- vsi->idx);
- }
-
- if (base < 0) {
- dev_err(dev, "%d MSI-X interrupts available. %s %d failed to get %d MSI-X vectors\n",
- ice_get_free_res_count(pf->irq_tracker),
- ice_vsi_type_str(vsi->type), vsi->idx, num_q_vectors);
- return -ENOENT;
- }
- vsi->base_vector = (u16)base;
- pf->num_avail_sw_msix -= num_q_vectors;
-
- return 0;
-}
-
-/**
* ice_vsi_clear_rings - Deallocates the Tx and Rx rings for VSI
* @vsi: the VSI having rings deallocated
*/
@@ -2410,50 +2212,6 @@ static void ice_vsi_set_tc_cfg(struct ice_vsi *vsi)
}
/**
- * ice_vsi_set_q_vectors_reg_idx - set the HW register index for all q_vectors
- * @vsi: VSI to set the q_vectors register index on
- */
-static int
-ice_vsi_set_q_vectors_reg_idx(struct ice_vsi *vsi)
-{
- u16 i;
-
- if (!vsi || !vsi->q_vectors)
- return -EINVAL;
-
- ice_for_each_q_vector(vsi, i) {
- struct ice_q_vector *q_vector = vsi->q_vectors[i];
-
- if (!q_vector) {
- dev_err(ice_pf_to_dev(vsi->back), "Failed to set reg_idx on q_vector %d VSI %d\n",
- i, vsi->vsi_num);
- goto clear_reg_idx;
- }
-
- if (vsi->type == ICE_VSI_VF) {
- struct ice_vf *vf = vsi->vf;
-
- q_vector->reg_idx = ice_calc_vf_reg_idx(vf, q_vector);
- } else {
- q_vector->reg_idx =
- q_vector->v_idx + vsi->base_vector;
- }
- }
-
- return 0;
-
-clear_reg_idx:
- ice_for_each_q_vector(vsi, i) {
- struct ice_q_vector *q_vector = vsi->q_vectors[i];
-
- if (q_vector)
- q_vector->reg_idx = 0;
- }
-
- return -EINVAL;
-}
-
-/**
* ice_cfg_sw_lldp - Config switch rules for LLDP packet handling
* @vsi: the VSI being configured
* @tx: bool to determine Tx or Rx rule
@@ -2611,37 +2369,6 @@ static void ice_set_agg_vsi(struct ice_vsi *vsi)
vsi->agg_node->num_vsis);
}
-/**
- * ice_free_vf_ctrl_res - Free the VF control VSI resource
- * @pf: pointer to PF structure
- * @vsi: the VSI to free resources for
- *
- * Check if the VF control VSI resource is still in use. If no VF is using it
- * any more, release the VSI resource. Otherwise, leave it to be cleaned up
- * once no other VF uses it.
- */
-static void ice_free_vf_ctrl_res(struct ice_pf *pf, struct ice_vsi *vsi)
-{
- struct ice_vf *vf;
- unsigned int bkt;
-
- rcu_read_lock();
- ice_for_each_vf_rcu(pf, bkt, vf) {
- if (vf != vsi->vf && vf->ctrl_vsi_idx != ICE_NO_VSI) {
- rcu_read_unlock();
- return;
- }
- }
- rcu_read_unlock();
-
- /* No other VFs left that have control VSI. It is now safe to reclaim
- * SW interrupts back to the common pool.
- */
- ice_free_res(pf->irq_tracker, vsi->base_vector,
- ICE_RES_VF_CTRL_VEC_ID);
- pf->num_avail_sw_msix += vsi->num_q_vectors;
-}
-
static int ice_vsi_cfg_tc_lan(struct ice_pf *pf, struct ice_vsi *vsi)
{
u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
@@ -2728,14 +2455,6 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params)
if (ret)
goto unroll_vsi_init;
- ret = ice_vsi_setup_vector_base(vsi);
- if (ret)
- goto unroll_alloc_q_vector;
-
- ret = ice_vsi_set_q_vectors_reg_idx(vsi);
- if (ret)
- goto unroll_vector_base;
-
ret = ice_vsi_alloc_rings(vsi);
if (ret)
goto unroll_vector_base;
@@ -2788,10 +2507,6 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params)
if (ret)
goto unroll_alloc_q_vector;
- ret = ice_vsi_set_q_vectors_reg_idx(vsi);
- if (ret)
- goto unroll_vector_base;
-
ret = ice_vsi_alloc_ring_stats(vsi);
if (ret)
goto unroll_vector_base;
@@ -2827,8 +2542,6 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params)
unroll_vector_base:
/* reclaim SW interrupts back to the common pool */
- ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
- pf->num_avail_sw_msix += vsi->num_q_vectors;
unroll_alloc_q_vector:
ice_vsi_free_q_vectors(vsi);
unroll_vsi_init:
@@ -2920,14 +2633,6 @@ void ice_vsi_decfg(struct ice_vsi *vsi)
* many interrupts each VF needs. SR-IOV MSIX resources are also
* cleared in the same manner.
*/
- if (vsi->type == ICE_VSI_CTRL && vsi->vf) {
- ice_free_vf_ctrl_res(pf, vsi);
- } else if (vsi->type != ICE_VSI_VF) {
- /* reclaim SW interrupts back to the common pool */
- ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
- pf->num_avail_sw_msix += vsi->num_q_vectors;
- vsi->base_vector = 0;
- }
if (vsi->type == ICE_VSI_VF &&
vsi->agg_node && vsi->agg_node->valid)
@@ -2993,8 +2698,6 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_vsi_cfg_params *params)
return vsi;
err_vsi_cfg:
- if (params->type == ICE_VSI_VF)
- ice_enable_lag(pf->lag);
ice_vsi_free(vsi);
return NULL;
@@ -3044,7 +2747,6 @@ static void ice_vsi_release_msix(struct ice_vsi *vsi)
void ice_vsi_free_irq(struct ice_vsi *vsi)
{
struct ice_pf *pf = vsi->back;
- int base = vsi->base_vector;
int i;
if (!vsi->q_vectors || !vsi->irqs_ready)
@@ -3058,10 +2760,9 @@ void ice_vsi_free_irq(struct ice_vsi *vsi)
ice_free_cpu_rx_rmap(vsi);
ice_for_each_q_vector(vsi, i) {
- u16 vector = i + base;
int irq_num;
- irq_num = pf->msix_entries[vector].vector;
+ irq_num = vsi->q_vectors[i]->irq.virq;
/* free only the irqs that were actually requested */
if (!vsi->q_vectors[i] ||
@@ -3193,7 +2894,6 @@ void ice_dis_vsi(struct ice_vsi *vsi, bool locked)
*/
void ice_vsi_dis_irq(struct ice_vsi *vsi)
{
- int base = vsi->base_vector;
struct ice_pf *pf = vsi->back;
struct ice_hw *hw = &pf->hw;
u32 val;
@@ -3240,7 +2940,7 @@ void ice_vsi_dis_irq(struct ice_vsi *vsi)
return;
ice_for_each_q_vector(vsi, i)
- synchronize_irq(pf->msix_entries[i + base].vector);
+ synchronize_irq(vsi->q_vectors[i]->irq.virq);
}
/**
@@ -3272,39 +2972,12 @@ int ice_vsi_release(struct ice_vsi *vsi)
return -ENODEV;
pf = vsi->back;
- /* do not unregister while driver is in the reset recovery pending
- * state. Since reset/rebuild happens through PF service task workqueue,
- * it's not a good idea to unregister netdev that is associated to the
- * PF that is running the work queue items currently. This is done to
- * avoid check_flush_dependency() warning on this wq
- */
- if (vsi->netdev && !ice_is_reset_in_progress(pf->state) &&
- (test_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state))) {
- unregister_netdev(vsi->netdev);
- clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
- }
-
- if (vsi->type == ICE_VSI_PF)
- ice_devlink_destroy_pf_port(pf);
-
if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
ice_rss_clean(vsi);
ice_vsi_close(vsi);
ice_vsi_decfg(vsi);
- if (vsi->netdev) {
- if (test_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state)) {
- unregister_netdev(vsi->netdev);
- clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
- }
- if (test_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state)) {
- free_netdev(vsi->netdev);
- vsi->netdev = NULL;
- clear_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
- }
- }
-
/* retain SW VSI data structure since it is needed to unregister and
* free VSI netdev when PF is not in reset recovery pending state,\
* for ex: during rmmod.
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h
index 75221478f2dc..e985766e6bb5 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.h
+++ b/drivers/net/ethernet/intel/ice/ice_lib.h
@@ -104,11 +104,6 @@ int ice_ena_vsi(struct ice_vsi *vsi, bool locked);
void ice_vsi_decfg(struct ice_vsi *vsi);
void ice_dis_vsi(struct ice_vsi *vsi, bool locked);
-int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id);
-
-int
-ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id);
-
int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags);
int ice_vsi_cfg(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params);
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 42c318ceff61..b40dfe6ae321 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -2490,7 +2490,6 @@ static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename)
{
int q_vectors = vsi->num_q_vectors;
struct ice_pf *pf = vsi->back;
- int base = vsi->base_vector;
struct device *dev;
int rx_int_idx = 0;
int tx_int_idx = 0;
@@ -2501,7 +2500,7 @@ static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename)
for (vector = 0; vector < q_vectors; vector++) {
struct ice_q_vector *q_vector = vsi->q_vectors[vector];
- irq_num = pf->msix_entries[base + vector].vector;
+ irq_num = q_vector->irq.virq;
if (q_vector->tx.tx_ring && q_vector->rx.rx_ring) {
snprintf(q_vector->name, sizeof(q_vector->name) - 1,
@@ -2555,9 +2554,8 @@ static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename)
return 0;
free_q_irqs:
- while (vector) {
- vector--;
- irq_num = pf->msix_entries[base + vector].vector;
+ while (vector--) {
+ irq_num = vsi->q_vectors[vector]->irq.virq;
if (!IS_ENABLED(CONFIG_RFS_ACCEL))
irq_set_affinity_notifier(irq_num, NULL);
irq_set_affinity_hint(irq_num, NULL);
@@ -2635,11 +2633,11 @@ static void ice_vsi_assign_bpf_prog(struct ice_vsi *vsi, struct bpf_prog *prog)
int i;
old_prog = xchg(&vsi->xdp_prog, prog);
- if (old_prog)
- bpf_prog_put(old_prog);
-
ice_for_each_rxq(vsi, i)
WRITE_ONCE(vsi->rx_rings[i]->xdp_prog, vsi->xdp_prog);
+
+ if (old_prog)
+ bpf_prog_put(old_prog);
}
/**
@@ -2924,6 +2922,12 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,
}
}
+ /* hot swap progs and avoid toggling link */
+ if (ice_is_xdp_ena_vsi(vsi) == !!prog) {
+ ice_vsi_assign_bpf_prog(vsi, prog);
+ return 0;
+ }
+
/* need to stop netdev while setting up the program for Rx rings */
if (if_running && !test_and_set_bit(ICE_VSI_DOWN, vsi->state)) {
ret = ice_down(vsi);
@@ -2956,13 +2960,6 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,
xdp_ring_err = ice_realloc_zc_buf(vsi, false);
if (xdp_ring_err)
NL_SET_ERR_MSG_MOD(extack, "Freeing XDP Rx resources failed");
- } else {
- /* safe to call even when prog == vsi->xdp_prog as
- * dev_xdp_install in net/core/dev.c incremented prog's
- * refcount so corresponding bpf_prog_put won't cause
- * underflow
- */
- ice_vsi_assign_bpf_prog(vsi, prog);
}
if (if_running)
@@ -3047,7 +3044,7 @@ static void ice_ena_misc_vector(struct ice_pf *pf)
wr32(hw, PFINT_OICR_ENA, val);
/* SW_ITR_IDX = 0, but don't change INTENA */
- wr32(hw, GLINT_DYN_CTL(pf->oicr_idx),
+ wr32(hw, GLINT_DYN_CTL(pf->oicr_irq.index),
GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M);
}
@@ -3060,7 +3057,6 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
{
struct ice_pf *pf = (struct ice_pf *)data;
struct ice_hw *hw = &pf->hw;
- irqreturn_t ret = IRQ_NONE;
struct device *dev;
u32 oicr, ena_mask;
@@ -3142,19 +3138,24 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
if (oicr & PFINT_OICR_TSYN_TX_M) {
ena_mask &= ~PFINT_OICR_TSYN_TX_M;
if (!hw->reset_ongoing)
- ret = IRQ_WAKE_THREAD;
+ set_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread);
}
if (oicr & PFINT_OICR_TSYN_EVNT_M) {
u8 tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
u32 gltsyn_stat = rd32(hw, GLTSYN_STAT(tmr_idx));
- /* Save EVENTs from GTSYN register */
- pf->ptp.ext_ts_irq |= gltsyn_stat & (GLTSYN_STAT_EVENT0_M |
- GLTSYN_STAT_EVENT1_M |
- GLTSYN_STAT_EVENT2_M);
ena_mask &= ~PFINT_OICR_TSYN_EVNT_M;
- kthread_queue_work(pf->ptp.kworker, &pf->ptp.extts_work);
+
+ if (hw->func_caps.ts_func_info.src_tmr_owned) {
+ /* Save EVENTs from GLTSYN register */
+ pf->ptp.ext_ts_irq |= gltsyn_stat &
+ (GLTSYN_STAT_EVENT0_M |
+ GLTSYN_STAT_EVENT1_M |
+ GLTSYN_STAT_EVENT2_M);
+
+ set_bit(ICE_MISC_THREAD_EXTTS_EVENT, pf->misc_thread);
+ }
}
#define ICE_AUX_CRIT_ERR (PFINT_OICR_PE_CRITERR_M | PFINT_OICR_HMC_ERR_M | PFINT_OICR_PE_PUSH_M)
@@ -3174,16 +3175,10 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
if (oicr & (PFINT_OICR_PCI_EXCEPTION_M |
PFINT_OICR_ECC_ERR_M)) {
set_bit(ICE_PFR_REQ, pf->state);
- ice_service_task_schedule(pf);
}
}
- if (!ret)
- ret = IRQ_HANDLED;
- ice_service_task_schedule(pf);
- ice_irq_dynamic_ena(hw, NULL, NULL);
-
- return ret;
+ return IRQ_WAKE_THREAD;
}
/**
@@ -3194,12 +3189,29 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
static irqreturn_t ice_misc_intr_thread_fn(int __always_unused irq, void *data)
{
struct ice_pf *pf = data;
+ struct ice_hw *hw;
+
+ hw = &pf->hw;
if (ice_is_reset_in_progress(pf->state))
return IRQ_HANDLED;
- while (!ice_ptp_process_ts(pf))
- usleep_range(50, 100);
+ ice_service_task_schedule(pf);
+
+ if (test_and_clear_bit(ICE_MISC_THREAD_EXTTS_EVENT, pf->misc_thread))
+ ice_ptp_extts_event(pf);
+
+ if (test_and_clear_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread)) {
+ /* Process outstanding Tx timestamps. If there is more work,
+ * re-arm the interrupt to trigger again.
+ */
+ if (ice_ptp_process_ts(pf) == ICE_TX_TSTAMP_WORK_PENDING) {
+ wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M);
+ ice_flush(hw);
+ }
+ }
+
+ ice_irq_dynamic_ena(hw, NULL, NULL);
return IRQ_HANDLED;
}
@@ -3234,6 +3246,7 @@ static void ice_dis_ctrlq_interrupts(struct ice_hw *hw)
*/
static void ice_free_irq_msix_misc(struct ice_pf *pf)
{
+ int misc_irq_num = pf->oicr_irq.virq;
struct ice_hw *hw = &pf->hw;
ice_dis_ctrlq_interrupts(hw);
@@ -3242,14 +3255,10 @@ static void ice_free_irq_msix_misc(struct ice_pf *pf)
wr32(hw, PFINT_OICR_ENA, 0);
ice_flush(hw);
- if (pf->msix_entries) {
- synchronize_irq(pf->msix_entries[pf->oicr_idx].vector);
- devm_free_irq(ice_pf_to_dev(pf),
- pf->msix_entries[pf->oicr_idx].vector, pf);
- }
+ synchronize_irq(misc_irq_num);
+ devm_free_irq(ice_pf_to_dev(pf), misc_irq_num, pf);
- pf->num_avail_sw_msix += 1;
- ice_free_res(pf->irq_tracker, pf->oicr_idx, ICE_RES_MISC_VEC_ID);
+ ice_free_irq(pf, pf->oicr_irq);
}
/**
@@ -3295,7 +3304,8 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf)
{
struct device *dev = ice_pf_to_dev(pf);
struct ice_hw *hw = &pf->hw;
- int oicr_idx, err = 0;
+ struct msi_map oicr_irq;
+ int err = 0;
if (!pf->int_name[0])
snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc",
@@ -3309,30 +3319,26 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf)
goto skip_req_irq;
/* reserve one vector in irq_tracker for misc interrupts */
- oicr_idx = ice_get_res(pf, pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID);
- if (oicr_idx < 0)
- return oicr_idx;
-
- pf->num_avail_sw_msix -= 1;
- pf->oicr_idx = (u16)oicr_idx;
-
- err = devm_request_threaded_irq(dev,
- pf->msix_entries[pf->oicr_idx].vector,
- ice_misc_intr, ice_misc_intr_thread_fn,
- 0, pf->int_name, pf);
+ oicr_irq = ice_alloc_irq(pf, false);
+ if (oicr_irq.index < 0)
+ return oicr_irq.index;
+
+ pf->oicr_irq = oicr_irq;
+ err = devm_request_threaded_irq(dev, pf->oicr_irq.virq, ice_misc_intr,
+ ice_misc_intr_thread_fn, 0,
+ pf->int_name, pf);
if (err) {
dev_err(dev, "devm_request_threaded_irq for %s failed: %d\n",
pf->int_name, err);
- ice_free_res(pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID);
- pf->num_avail_sw_msix += 1;
+ ice_free_irq(pf, pf->oicr_irq);
return err;
}
skip_req_irq:
ice_ena_misc_vector(pf);
- ice_ena_ctrlq_interrupts(hw, pf->oicr_idx);
- wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_idx),
+ ice_ena_ctrlq_interrupts(hw, pf->oicr_irq.index);
+ wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_irq.index),
ITR_REG_ALIGN(ICE_ITR_8K) >> ICE_ITR_GRAN_S);
ice_flush(hw);
@@ -3901,224 +3907,6 @@ static int ice_init_pf(struct ice_pf *pf)
}
/**
- * ice_reduce_msix_usage - Reduce usage of MSI-X vectors
- * @pf: board private structure
- * @v_remain: number of remaining MSI-X vectors to be distributed
- *
- * Reduce the usage of MSI-X vectors when entire request cannot be fulfilled.
- * pf->num_lan_msix and pf->num_rdma_msix values are set based on number of
- * remaining vectors.
- */
-static void ice_reduce_msix_usage(struct ice_pf *pf, int v_remain)
-{
- int v_rdma;
-
- if (!ice_is_rdma_ena(pf)) {
- pf->num_lan_msix = v_remain;
- return;
- }
-
- /* RDMA needs at least 1 interrupt in addition to AEQ MSIX */
- v_rdma = ICE_RDMA_NUM_AEQ_MSIX + 1;
-
- if (v_remain < ICE_MIN_LAN_TXRX_MSIX + ICE_MIN_RDMA_MSIX) {
- dev_warn(ice_pf_to_dev(pf), "Not enough MSI-X vectors to support RDMA.\n");
- clear_bit(ICE_FLAG_RDMA_ENA, pf->flags);
-
- pf->num_rdma_msix = 0;
- pf->num_lan_msix = ICE_MIN_LAN_TXRX_MSIX;
- } else if ((v_remain < ICE_MIN_LAN_TXRX_MSIX + v_rdma) ||
- (v_remain - v_rdma < v_rdma)) {
- /* Support minimum RDMA and give remaining vectors to LAN MSIX */
- pf->num_rdma_msix = ICE_MIN_RDMA_MSIX;
- pf->num_lan_msix = v_remain - ICE_MIN_RDMA_MSIX;
- } else {
- /* Split remaining MSIX with RDMA after accounting for AEQ MSIX
- */
- pf->num_rdma_msix = (v_remain - ICE_RDMA_NUM_AEQ_MSIX) / 2 +
- ICE_RDMA_NUM_AEQ_MSIX;
- pf->num_lan_msix = v_remain - pf->num_rdma_msix;
- }
-}
-
-/**
- * ice_ena_msix_range - Request a range of MSIX vectors from the OS
- * @pf: board private structure
- *
- * Compute the number of MSIX vectors wanted and request from the OS. Adjust
- * device usage if there are not enough vectors. Return the number of vectors
- * reserved or negative on failure.
- */
-static int ice_ena_msix_range(struct ice_pf *pf)
-{
- int num_cpus, hw_num_msix, v_other, v_wanted, v_actual;
- struct device *dev = ice_pf_to_dev(pf);
- int err, i;
-
- hw_num_msix = pf->hw.func_caps.common_cap.num_msix_vectors;
- num_cpus = num_online_cpus();
-
- /* LAN miscellaneous handler */
- v_other = ICE_MIN_LAN_OICR_MSIX;
-
- /* Flow Director */
- if (test_bit(ICE_FLAG_FD_ENA, pf->flags))
- v_other += ICE_FDIR_MSIX;
-
- /* switchdev */
- v_other += ICE_ESWITCH_MSIX;
-
- v_wanted = v_other;
-
- /* LAN traffic */
- pf->num_lan_msix = num_cpus;
- v_wanted += pf->num_lan_msix;
-
- /* RDMA auxiliary driver */
- if (ice_is_rdma_ena(pf)) {
- pf->num_rdma_msix = num_cpus + ICE_RDMA_NUM_AEQ_MSIX;
- v_wanted += pf->num_rdma_msix;
- }
-
- if (v_wanted > hw_num_msix) {
- int v_remain;
-
- dev_warn(dev, "not enough device MSI-X vectors. wanted = %d, available = %d\n",
- v_wanted, hw_num_msix);
-
- if (hw_num_msix < ICE_MIN_MSIX) {
- err = -ERANGE;
- goto exit_err;
- }
-
- v_remain = hw_num_msix - v_other;
- if (v_remain < ICE_MIN_LAN_TXRX_MSIX) {
- v_other = ICE_MIN_MSIX - ICE_MIN_LAN_TXRX_MSIX;
- v_remain = ICE_MIN_LAN_TXRX_MSIX;
- }
-
- ice_reduce_msix_usage(pf, v_remain);
- v_wanted = pf->num_lan_msix + pf->num_rdma_msix + v_other;
-
- dev_notice(dev, "Reducing request to %d MSI-X vectors for LAN traffic.\n",
- pf->num_lan_msix);
- if (ice_is_rdma_ena(pf))
- dev_notice(dev, "Reducing request to %d MSI-X vectors for RDMA.\n",
- pf->num_rdma_msix);
- }
-
- pf->msix_entries = devm_kcalloc(dev, v_wanted,
- sizeof(*pf->msix_entries), GFP_KERNEL);
- if (!pf->msix_entries) {
- err = -ENOMEM;
- goto exit_err;
- }
-
- for (i = 0; i < v_wanted; i++)
- pf->msix_entries[i].entry = i;
-
- /* actually reserve the vectors */
- v_actual = pci_enable_msix_range(pf->pdev, pf->msix_entries,
- ICE_MIN_MSIX, v_wanted);
- if (v_actual < 0) {
- dev_err(dev, "unable to reserve MSI-X vectors\n");
- err = v_actual;
- goto msix_err;
- }
-
- if (v_actual < v_wanted) {
- dev_warn(dev, "not enough OS MSI-X vectors. requested = %d, obtained = %d\n",
- v_wanted, v_actual);
-
- if (v_actual < ICE_MIN_MSIX) {
- /* error if we can't get minimum vectors */
- pci_disable_msix(pf->pdev);
- err = -ERANGE;
- goto msix_err;
- } else {
- int v_remain = v_actual - v_other;
-
- if (v_remain < ICE_MIN_LAN_TXRX_MSIX)
- v_remain = ICE_MIN_LAN_TXRX_MSIX;
-
- ice_reduce_msix_usage(pf, v_remain);
-
- dev_notice(dev, "Enabled %d MSI-X vectors for LAN traffic.\n",
- pf->num_lan_msix);
-
- if (ice_is_rdma_ena(pf))
- dev_notice(dev, "Enabled %d MSI-X vectors for RDMA.\n",
- pf->num_rdma_msix);
- }
- }
-
- return v_actual;
-
-msix_err:
- devm_kfree(dev, pf->msix_entries);
-
-exit_err:
- pf->num_rdma_msix = 0;
- pf->num_lan_msix = 0;
- return err;
-}
-
-/**
- * ice_dis_msix - Disable MSI-X interrupt setup in OS
- * @pf: board private structure
- */
-static void ice_dis_msix(struct ice_pf *pf)
-{
- pci_disable_msix(pf->pdev);
- devm_kfree(ice_pf_to_dev(pf), pf->msix_entries);
- pf->msix_entries = NULL;
-}
-
-/**
- * ice_clear_interrupt_scheme - Undo things done by ice_init_interrupt_scheme
- * @pf: board private structure
- */
-static void ice_clear_interrupt_scheme(struct ice_pf *pf)
-{
- ice_dis_msix(pf);
-
- if (pf->irq_tracker) {
- devm_kfree(ice_pf_to_dev(pf), pf->irq_tracker);
- pf->irq_tracker = NULL;
- }
-}
-
-/**
- * ice_init_interrupt_scheme - Determine proper interrupt scheme
- * @pf: board private structure to initialize
- */
-static int ice_init_interrupt_scheme(struct ice_pf *pf)
-{
- int vectors;
-
- vectors = ice_ena_msix_range(pf);
-
- if (vectors < 0)
- return vectors;
-
- /* set up vector assignment tracking */
- pf->irq_tracker = devm_kzalloc(ice_pf_to_dev(pf),
- struct_size(pf->irq_tracker, list, vectors),
- GFP_KERNEL);
- if (!pf->irq_tracker) {
- ice_dis_msix(pf);
- return -ENOMEM;
- }
-
- /* populate SW interrupts pool with number of OS granted IRQs. */
- pf->num_avail_sw_msix = (u16)vectors;
- pf->irq_tracker->num_entries = (u16)vectors;
- pf->irq_tracker->end = pf->irq_tracker->num_entries;
-
- return 0;
-}
-
-/**
* ice_is_wol_supported - check if WoL is supported
* @hw: pointer to hardware info
*
@@ -4642,9 +4430,9 @@ static int ice_start_eth(struct ice_vsi *vsi)
if (err)
return err;
- rtnl_lock();
err = ice_vsi_open(vsi);
- rtnl_unlock();
+ if (err)
+ ice_fltr_remove_all(vsi);
return err;
}
@@ -5107,6 +4895,7 @@ int ice_load(struct ice_pf *pf)
params = ice_vsi_to_params(vsi);
params.flags = ICE_VSI_FLAG_INIT;
+ rtnl_lock();
err = ice_vsi_cfg(vsi, &params);
if (err)
goto err_vsi_cfg;
@@ -5114,6 +4903,7 @@ int ice_load(struct ice_pf *pf)
err = ice_start_eth(ice_get_main_vsi(pf));
if (err)
goto err_start_eth;
+ rtnl_unlock();
err = ice_init_rdma(pf);
if (err)
@@ -5128,9 +4918,11 @@ int ice_load(struct ice_pf *pf)
err_init_rdma:
ice_vsi_close(ice_get_main_vsi(pf));
+ rtnl_lock();
err_start_eth:
ice_vsi_decfg(ice_get_main_vsi(pf));
err_vsi_cfg:
+ rtnl_unlock();
ice_deinit_dev(pf);
return err;
}
@@ -5143,8 +4935,10 @@ void ice_unload(struct ice_pf *pf)
{
ice_deinit_features(pf);
ice_deinit_rdma(pf);
+ rtnl_lock();
ice_stop_eth(ice_get_main_vsi(pf));
ice_vsi_decfg(ice_get_main_vsi(pf));
+ rtnl_unlock();
ice_deinit_dev(pf);
}
@@ -5835,11 +5629,6 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi)
if (!is_valid_ether_addr(mac))
return -EADDRNOTAVAIL;
- if (ether_addr_equal(netdev->dev_addr, mac)) {
- netdev_dbg(netdev, "already using mac %pM\n", mac);
- return 0;
- }
-
if (test_bit(ICE_DOWN, pf->state) ||
ice_is_reset_in_progress(pf->state)) {
netdev_err(netdev, "can't set mac %pM. device not ready\n",
@@ -5956,6 +5745,13 @@ ice_set_tx_maxrate(struct net_device *netdev, int queue_index, u32 maxrate)
q_handle = vsi->tx_rings[queue_index]->q_handle;
tc = ice_dcb_get_tc(vsi, queue_index);
+ vsi = ice_locate_vsi_using_queue(vsi, queue_index);
+ if (!vsi) {
+ netdev_err(netdev, "Invalid VSI for given queue %d\n",
+ queue_index);
+ return -EINVAL;
+ }
+
/* Set BW back to default, when user set maxrate to 0 */
if (!maxrate)
status = ice_cfg_q_bw_dflt_lmt(vsi->port_info, vsi->idx, tc,
@@ -7629,21 +7425,9 @@ static int ice_change_mtu(struct net_device *netdev, int new_mtu)
}
netdev->mtu = (unsigned int)new_mtu;
-
- /* if VSI is up, bring it down and then back up */
- if (!test_and_set_bit(ICE_VSI_DOWN, vsi->state)) {
- err = ice_down(vsi);
- if (err) {
- netdev_err(netdev, "change MTU if_down err %d\n", err);
- return err;
- }
-
- err = ice_up(vsi);
- if (err) {
- netdev_err(netdev, "change MTU if_up err %d\n", err);
- return err;
- }
- }
+ err = ice_down_up(vsi);
+ if (err)
+ return err;
netdev_dbg(netdev, "changed MTU to %d\n", new_mtu);
set_bit(ICE_FLAG_MTU_CHANGED, pf->flags);
@@ -8101,10 +7885,10 @@ static int
ice_validate_mqprio_qopt(struct ice_vsi *vsi,
struct tc_mqprio_qopt_offload *mqprio_qopt)
{
- u64 sum_max_rate = 0, sum_min_rate = 0;
int non_power_of_2_qcount = 0;
struct ice_pf *pf = vsi->back;
int max_rss_q_cnt = 0;
+ u64 sum_min_rate = 0;
struct device *dev;
int i, speed;
u8 num_tc;
@@ -8120,6 +7904,7 @@ ice_validate_mqprio_qopt(struct ice_vsi *vsi,
dev = ice_pf_to_dev(pf);
vsi->ch_rss_size = 0;
num_tc = mqprio_qopt->qopt.num_tc;
+ speed = ice_get_link_speed_kbps(vsi);
for (i = 0; num_tc; i++) {
int qcount = mqprio_qopt->qopt.count[i];
@@ -8160,7 +7945,6 @@ ice_validate_mqprio_qopt(struct ice_vsi *vsi,
*/
max_rate = mqprio_qopt->max_rate[i];
max_rate = div_u64(max_rate, ICE_BW_KBPS_DIVISOR);
- sum_max_rate += max_rate;
/* min_rate is minimum guaranteed rate and it can't be zero */
min_rate = mqprio_qopt->min_rate[i];
@@ -8173,6 +7957,12 @@ ice_validate_mqprio_qopt(struct ice_vsi *vsi,
return -EINVAL;
}
+ if (max_rate && max_rate > speed) {
+ dev_err(dev, "TC%d: max_rate(%llu Kbps) > link speed of %u Kbps\n",
+ i, max_rate, speed);
+ return -EINVAL;
+ }
+
iter_div_u64_rem(min_rate, ICE_MIN_BW_LIMIT, &rem);
if (rem) {
dev_err(dev, "TC%d: Min Rate not multiple of %u Kbps",
@@ -8210,12 +8000,6 @@ ice_validate_mqprio_qopt(struct ice_vsi *vsi,
(mqprio_qopt->qopt.offset[i] + mqprio_qopt->qopt.count[i]))
return -EINVAL;
- speed = ice_get_link_speed_kbps(vsi);
- if (sum_max_rate && sum_max_rate > (u64)speed) {
- dev_err(dev, "Invalid max Tx rate(%llu) Kbps > speed(%u) Kbps specified\n",
- sum_max_rate, speed);
- return -EINVAL;
- }
if (sum_min_rate && sum_min_rate > (u64)speed) {
dev_err(dev, "Invalid min Tx rate(%llu) Kbps > speed (%u) Kbps specified\n",
sum_min_rate, speed);
@@ -9029,6 +8813,7 @@ ice_setup_tc(struct net_device *netdev, enum tc_setup_type type,
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_pf *pf = np->vsi->back;
+ bool locked = false;
int err;
switch (type) {
@@ -9038,10 +8823,32 @@ ice_setup_tc(struct net_device *netdev, enum tc_setup_type type,
ice_setup_tc_block_cb,
np, np, true);
case TC_SETUP_QDISC_MQPRIO:
+ if (ice_is_eswitch_mode_switchdev(pf)) {
+ netdev_err(netdev, "TC MQPRIO offload not supported, switchdev is enabled\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (pf->adev) {
+ mutex_lock(&pf->adev_mutex);
+ device_lock(&pf->adev->dev);
+ locked = true;
+ if (pf->adev->dev.driver) {
+ netdev_err(netdev, "Cannot change qdisc when RDMA is active\n");
+ err = -EBUSY;
+ goto adev_unlock;
+ }
+ }
+
/* setup traffic classifier for receive side */
mutex_lock(&pf->tc_mutex);
err = ice_setup_tc_mqprio_qdisc(netdev, type_data);
mutex_unlock(&pf->tc_mutex);
+
+adev_unlock:
+ if (locked) {
+ device_unlock(&pf->adev->dev);
+ mutex_unlock(&pf->adev_mutex);
+ }
return err;
default:
return -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/intel/ice/ice_protocol_type.h b/drivers/net/ethernet/intel/ice/ice_protocol_type.h
index 02a4e1cf624e..6a9364761165 100644
--- a/drivers/net/ethernet/intel/ice/ice_protocol_type.h
+++ b/drivers/net/ethernet/intel/ice/ice_protocol_type.h
@@ -47,6 +47,7 @@ enum ice_protocol_type {
ICE_L2TPV3,
ICE_VLAN_EX,
ICE_VLAN_IN,
+ ICE_HW_METADATA,
ICE_VXLAN_GPE,
ICE_SCTP_IL,
ICE_PROTOCOL_LAST
@@ -115,17 +116,7 @@ enum ice_prot_id {
#define ICE_L2TPV3_HW 104
#define ICE_UDP_OF_HW 52 /* UDP Tunnels */
-#define ICE_META_DATA_ID_HW 255 /* this is used for tunnel and VLAN type */
-#define ICE_MDID_SIZE 2
-
-#define ICE_TUN_FLAG_MDID 21
-#define ICE_TUN_FLAG_MDID_OFF (ICE_MDID_SIZE * ICE_TUN_FLAG_MDID)
-#define ICE_TUN_FLAG_MASK 0xFF
-
-#define ICE_VLAN_FLAG_MDID 20
-#define ICE_VLAN_FLAG_MDID_OFF (ICE_MDID_SIZE * ICE_VLAN_FLAG_MDID)
-#define ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK 0xD000
#define ICE_TUN_FLAG_FV_IND 2
@@ -230,6 +221,191 @@ struct ice_nvgre_hdr {
__be32 tni_flow;
};
+/* Metadata information
+ *
+ * Not all MDIDs can be used by switch block. It depends on package version.
+ *
+ * MDID 16 (Rx offset)
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | A | B | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * A = Source port where the transaction came from (3b).
+ *
+ * B = Destination TC of the packet. The TC is relative to a port (5b).
+ *
+ * MDID 17
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PTYPE | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * PTYPE = Encodes the packet type (10b).
+ *
+ * MDID 18
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Packet length | R |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Packet length = Length of the packet in bytes
+ * (packet always carriers CRC) (14b).
+ * R = Reserved (2b).
+ *
+ * MDID 19
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Source VSI | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Source VSI = Source VSI of packet loopbacked in switch (for egress) (10b).
+ */
+#define ICE_MDID_SOURCE_VSI_MASK GENMASK(9, 0)
+
+/*
+ * MDID 20
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |A|B|C|D|E|F|R|R|G|H|I|J|K|L|M|N|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * A = DSI - set for DSI RX pkts.
+ * B = ipsec_decrypted - invalid on NIC.
+ * C = marker - this is a marker packet.
+ * D = from_network - for TX sets to 0
+ * for RX:
+ * * 1 - packet is from external link
+ * * 0 - packet source is from internal
+ * E = source_interface_is_rx - reflect the physical interface from where the
+ * packet was received:
+ * * 1 - Rx
+ * * 0 - Tx
+ * F = from_mng - The bit signals that the packet's origin is the management.
+ * G = ucast - Outer L2 MAC address is unicast.
+ * H = mcast - Outer L2 MAC address is multicast.
+ * I = bcast - Outer L2 MAC address is broadcast.
+ * J = second_outer_mac_present - 2 outer MAC headers are present in the packet.
+ * K = STAG or BVLAN - Outer L2 header has STAG (ethernet type 0x88a8) or
+ * BVLAN (ethernet type 0x88a8).
+ * L = ITAG - Outer L2 header has ITAG *ethernet type 0x88e7)
+ * M = EVLAN (0x8100) - Outer L2 header has EVLAN (ethernet type 0x8100)
+ * N = EVLAN (0x9100) - Outer L2 header has EVLAN (ethernet type 0x9100)
+ */
+#define ICE_PKT_VLAN_STAG BIT(12)
+#define ICE_PKT_VLAN_ITAG BIT(13)
+#define ICE_PKT_VLAN_EVLAN (BIT(14) | BIT(15))
+#define ICE_PKT_VLAN_MASK (ICE_PKT_VLAN_STAG | ICE_PKT_VLAN_ITAG | \
+ ICE_PKT_VLAN_EVLAN)
+/* MDID 21
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |A|B|C|D|E|F|G|H|I|J|R|R|K|L|M|N|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * A = VLAN (0x8100) - Outer L2 header has VLAN (ethernet type 0x8100)
+ * B = NSHoE - Outer L2 header has NSH (ethernet type 0x894f)
+ * C = MPLS (0x8847) - There is at least 1 MPLS tag in the outer header
+ * (ethernet type 0x8847)
+ * D = MPLS (0x8848) - There is at least 1 MPLS tag in the outer header
+ * (ethernet type 0x8848)
+ * E = multi MPLS - There is more than a single MPLS tag in the outer header
+ * F = inner MPLS - There is inner MPLS tag in the packet
+ * G = tunneled MAC - Set if the packet includes a tunneled MAC
+ * H = tunneled VLAN - Same as VLAN, but for a tunneled header
+ * I = pkt_is_frag - Packet is fragmented (ipv4 or ipv6)
+ * J = ipv6_ext - The packet has routing or destination ipv6 extension in inner
+ * or outer ipv6 headers
+ * K = RoCE - UDP packet detected as RoCEv2
+ * L = UDP_XSUM_0 - Set to 1 if L4 checksum is 0 in a UDP packet
+ * M = ESP - This is a ESP packet
+ * N = NAT_ESP - This is a ESP packet encapsulated in UDP NAT
+ */
+#define ICE_PKT_TUNNEL_MAC BIT(6)
+#define ICE_PKT_TUNNEL_VLAN BIT(7)
+#define ICE_PKT_TUNNEL_MASK (ICE_PKT_TUNNEL_MAC | ICE_PKT_TUNNEL_VLAN)
+
+/* MDID 22
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |A|B|C|D|E|F| G |H|I|J| K |L|M|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * A = fin - fin flag in tcp header
+ * B = sync - sync flag in tcp header
+ * C = rst - rst flag in tcp header
+ * D = psh - psh flag in tcp header
+ * E = ack - ack flag in tcp header
+ * F = urg - urg flag in tcp header
+ * G = tunnel type (3b) - Flags used to decode tunnel type:
+ * * b000 - not a VXLAN/Geneve/GRE tunnel
+ * * b001 - VXLAN-GPE
+ * * b010 - VXLAN (non-GPE)
+ * * b011 - Geneve
+ * * b100 - GRE (no key, no xsum)
+ * * b101 - GREK (key, no xsum)
+ * * b110 - GREC (no key, xsum)
+ * * b111 - GREKC (key, xsum)
+ * H = UDP_GRE - Packet is UDP (VXLAN or VLAN_GPE or Geneve or MPLSoUDP or GRE)
+ * tunnel
+ * I = OAM - VXLAN/Geneve/tunneled NSH packet with the OAM bit set
+ * J = tunneled NSH - Packet has NSHoGRE or NSHoUDP
+ * K = switch (2b) - Direction on switch
+ * * b00 - normal
+ * * b01 - TX force only LAN
+ * * b10 - TX disable LAN
+ * * b11 - direct to VSI
+ * L = swpe - Represents SWPE bit in TX command
+ * M = sw_cmd - Switch command
+ *
+ * MDID 23
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |A|B|C|D| R |E|F|R|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * A = MAC error - Produced by MAC according to L2 error conditions
+ * B = PPRS no offload - FIFO overflow in PPRS or any problematic condition in
+ * PPRS ANA
+ * C = abort - Set when malicious packet is detected
+ * D = partial analysis - ANA's analysing got cut in the middle
+ * (header > 504B etc.)
+ * E = FLM - Flow director hit indication
+ * F = FDLONG - Flow direector long bucket indication
+ *
+ */
+#define ICE_MDID_SIZE 2
+#define ICE_META_DATA_ID_HW 255
+
+enum ice_hw_metadata_id {
+ ICE_SOURCE_PORT_MDID = 16,
+ ICE_PTYPE_MDID = 17,
+ ICE_PACKET_LENGTH_MDID = 18,
+ ICE_SOURCE_VSI_MDID = 19,
+ ICE_PKT_VLAN_MDID = 20,
+ ICE_PKT_TUNNEL_MDID = 21,
+ ICE_PKT_TCP_MDID = 22,
+ ICE_PKT_ERROR_MDID = 23,
+};
+
+enum ice_hw_metadata_offset {
+ ICE_SOURCE_PORT_MDID_OFFSET = ICE_MDID_SIZE * ICE_SOURCE_PORT_MDID,
+ ICE_PTYPE_MDID_OFFSET = ICE_MDID_SIZE * ICE_PTYPE_MDID,
+ ICE_PACKET_LENGTH_MDID_OFFSET = ICE_MDID_SIZE * ICE_PACKET_LENGTH_MDID,
+ ICE_SOURCE_VSI_MDID_OFFSET = ICE_MDID_SIZE * ICE_SOURCE_VSI_MDID,
+ ICE_PKT_VLAN_MDID_OFFSET = ICE_MDID_SIZE * ICE_PKT_VLAN_MDID,
+ ICE_PKT_TUNNEL_MDID_OFFSET = ICE_MDID_SIZE * ICE_PKT_TUNNEL_MDID,
+ ICE_PKT_TCP_MDID_OFFSET = ICE_MDID_SIZE * ICE_PKT_TCP_MDID,
+ ICE_PKT_ERROR_MDID_OFFSET = ICE_MDID_SIZE * ICE_PKT_ERROR_MDID,
+};
+
+enum ice_pkt_flags {
+ ICE_PKT_FLAGS_VLAN = 0,
+ ICE_PKT_FLAGS_TUNNEL = 1,
+ ICE_PKT_FLAGS_TCP = 2,
+ ICE_PKT_FLAGS_ERROR = 3,
+};
+
+struct ice_hw_metadata {
+ __be16 source_port;
+ __be16 ptype;
+ __be16 packet_length;
+ __be16 source_vsi;
+ __be16 flags[4];
+};
+
union ice_prot_hdr {
struct ice_ether_hdr eth_hdr;
struct ice_ethtype_hdr ethertype;
@@ -243,6 +419,7 @@ union ice_prot_hdr {
struct ice_udp_gtp_hdr gtp_hdr;
struct ice_pppoe_hdr pppoe_hdr;
struct ice_l2tpv3_sess_hdr l2tpv3_sess_hdr;
+ struct ice_hw_metadata metadata;
};
/* This is mapping table entry that maps every word within a given protocol
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index ac6f06f9a2ed..81d96a40d5a7 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -617,7 +617,7 @@ ice_ptp_is_tx_tracker_up(struct ice_ptp_tx *tx)
}
/**
- * ice_ptp_tx_tstamp - Process Tx timestamps for a port
+ * ice_ptp_process_tx_tstamp - Process Tx timestamps for a port
* @tx: the PTP Tx timestamp tracker
*
* Process timestamps captured by the PHY associated with this port. To do
@@ -633,15 +633,6 @@ ice_ptp_is_tx_tracker_up(struct ice_ptp_tx *tx)
* 6) extend the 40 bit timestamp value to get a 64 bit timestamp value
* 7) send this 64 bit timestamp to the stack
*
- * Returns true if all timestamps were handled, and false if any slots remain
- * without a timestamp.
- *
- * After looping, if we still have waiting SKBs, return false. This may cause
- * us effectively poll even when not strictly necessary. We do this because
- * it's possible a new timestamp was requested around the same time as the
- * interrupt. In some cases hardware might not interrupt us again when the
- * timestamp is captured.
- *
* Note that we do not hold the tracking lock while reading the Tx timestamp.
* This is because reading the timestamp requires taking a mutex that might
* sleep.
@@ -673,10 +664,9 @@ ice_ptp_is_tx_tracker_up(struct ice_ptp_tx *tx)
* the packet will never be sent by hardware and discard it without reading
* the timestamp register.
*/
-static bool ice_ptp_tx_tstamp(struct ice_ptp_tx *tx)
+static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx)
{
struct ice_ptp_port *ptp_port;
- bool more_timestamps;
struct ice_pf *pf;
struct ice_hw *hw;
u64 tstamp_ready;
@@ -685,7 +675,7 @@ static bool ice_ptp_tx_tstamp(struct ice_ptp_tx *tx)
u8 idx;
if (!tx->init)
- return true;
+ return;
ptp_port = container_of(tx, struct ice_ptp_port, tx);
pf = ptp_port_to_pf(ptp_port);
@@ -694,7 +684,7 @@ static bool ice_ptp_tx_tstamp(struct ice_ptp_tx *tx)
/* Read the Tx ready status first */
err = ice_get_phy_tx_tstamp_ready(hw, tx->block, &tstamp_ready);
if (err)
- return false;
+ return;
/* Drop packets if the link went down */
link_up = ptp_port->link_up;
@@ -782,15 +772,34 @@ skip_ts_read:
skb_tstamp_tx(skb, &shhwtstamps);
dev_kfree_skb_any(skb);
}
+}
- /* Check if we still have work to do. If so, re-queue this task to
- * poll for remaining timestamps.
- */
+/**
+ * ice_ptp_tx_tstamp - Process Tx timestamps for this function.
+ * @tx: Tx tracking structure to initialize
+ *
+ * Returns: ICE_TX_TSTAMP_WORK_PENDING if there are any outstanding incomplete
+ * Tx timestamps, or ICE_TX_TSTAMP_WORK_DONE otherwise.
+ */
+static enum ice_tx_tstamp_work ice_ptp_tx_tstamp(struct ice_ptp_tx *tx)
+{
+ bool more_timestamps;
+
+ if (!tx->init)
+ return ICE_TX_TSTAMP_WORK_DONE;
+
+ /* Process the Tx timestamp tracker */
+ ice_ptp_process_tx_tstamp(tx);
+
+ /* Check if there are outstanding Tx timestamps */
spin_lock(&tx->lock);
more_timestamps = tx->init && !bitmap_empty(tx->in_use, tx->len);
spin_unlock(&tx->lock);
- return !more_timestamps;
+ if (more_timestamps)
+ return ICE_TX_TSTAMP_WORK_PENDING;
+
+ return ICE_TX_TSTAMP_WORK_DONE;
}
/**
@@ -911,7 +920,7 @@ ice_ptp_release_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx)
spin_unlock(&tx->lock);
/* wait for potentially outstanding interrupt to complete */
- synchronize_irq(pf->msix_entries[pf->oicr_idx].vector);
+ synchronize_irq(pf->oicr_irq.virq);
ice_ptp_flush_tx_tracker(pf, tx);
@@ -1458,15 +1467,11 @@ static int ice_ptp_adjfine(struct ptp_clock_info *info, long scaled_ppm)
}
/**
- * ice_ptp_extts_work - Workqueue task function
- * @work: external timestamp work structure
- *
- * Service for PTP external clock event
+ * ice_ptp_extts_event - Process PTP external clock event
+ * @pf: Board private structure
*/
-static void ice_ptp_extts_work(struct kthread_work *work)
+void ice_ptp_extts_event(struct ice_pf *pf)
{
- struct ice_ptp *ptp = container_of(work, struct ice_ptp, extts_work);
- struct ice_pf *pf = container_of(ptp, struct ice_pf, ptp);
struct ptp_clock_event event;
struct ice_hw *hw = &pf->hw;
u8 chan, tmr_idx;
@@ -2430,9 +2435,10 @@ s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb)
* ice_ptp_process_ts - Process the PTP Tx timestamps
* @pf: Board private structure
*
- * Returns true if timestamps are processed.
+ * Returns: ICE_TX_TSTAMP_WORK_PENDING if there are any outstanding Tx
+ * timestamps that need processing, and ICE_TX_TSTAMP_WORK_DONE otherwise.
*/
-bool ice_ptp_process_ts(struct ice_pf *pf)
+enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf)
{
return ice_ptp_tx_tstamp(&pf->ptp.port.tx);
}
@@ -2558,7 +2564,6 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf)
ice_ptp_cfg_timestamp(pf, false);
kthread_cancel_delayed_work_sync(&ptp->work);
- kthread_cancel_work_sync(&ptp->extts_work);
if (test_bit(ICE_PFR_REQ, pf->state))
return;
@@ -2656,7 +2661,6 @@ static int ice_ptp_init_work(struct ice_pf *pf, struct ice_ptp *ptp)
/* Initialize work functions */
kthread_init_delayed_work(&ptp->work, ice_ptp_periodic_work);
- kthread_init_work(&ptp->extts_work, ice_ptp_extts_work);
/* Allocate a kworker for handling work required for the ports
* connected to the PTP hardware clock.
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h
index 9cda2f43e0e5..995a57019ba7 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.h
@@ -109,6 +109,16 @@ struct ice_tx_tstamp {
};
/**
+ * enum ice_tx_tstamp_work - Status of Tx timestamp work function
+ * @ICE_TX_TSTAMP_WORK_DONE: Tx timestamp processing is complete
+ * @ICE_TX_TSTAMP_WORK_PENDING: More Tx timestamps are pending
+ */
+enum ice_tx_tstamp_work {
+ ICE_TX_TSTAMP_WORK_DONE = 0,
+ ICE_TX_TSTAMP_WORK_PENDING,
+};
+
+/**
* struct ice_ptp_tx - Tracking structure for all Tx timestamp requests on a port
* @lock: lock to prevent concurrent access to fields of this struct
* @tstamps: array of len to store outstanding requests
@@ -169,7 +179,6 @@ struct ice_ptp_port {
* struct ice_ptp - data used for integrating with CONFIG_PTP_1588_CLOCK
* @port: data for the PHY port initialization procedure
* @work: delayed work function for periodic tasks
- * @extts_work: work function for handling external Tx timestamps
* @cached_phc_time: a cached copy of the PHC time for timestamp extension
* @cached_phc_jiffies: jiffies when cached_phc_time was last updated
* @ext_ts_chan: the external timestamp channel in use
@@ -190,7 +199,6 @@ struct ice_ptp_port {
struct ice_ptp {
struct ice_ptp_port port;
struct kthread_delayed_work work;
- struct kthread_work extts_work;
u64 cached_phc_time;
unsigned long cached_phc_jiffies;
u8 ext_ts_chan;
@@ -256,8 +264,9 @@ int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr);
void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena);
int ice_get_ptp_clock_index(struct ice_pf *pf);
+void ice_ptp_extts_event(struct ice_pf *pf);
s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb);
-bool ice_ptp_process_ts(struct ice_pf *pf);
+enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf);
void
ice_ptp_rx_hwtstamp(struct ice_rx_ring *rx_ring,
@@ -284,6 +293,7 @@ static inline int ice_get_ptp_clock_index(struct ice_pf *pf)
return -1;
}
+static inline void ice_ptp_extts_event(struct ice_pf *pf) { }
static inline s8
ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb)
{
diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c
index fd1f8b0ad0ab..e30e12321abd 100644
--- a/drivers/net/ethernet/intel/ice/ice_repr.c
+++ b/drivers/net/ethernet/intel/ice/ice_repr.c
@@ -298,14 +298,6 @@ static int ice_repr_add(struct ice_vf *vf)
if (!repr)
return -ENOMEM;
-#ifdef CONFIG_ICE_SWITCHDEV
- repr->mac_rule = kzalloc(sizeof(*repr->mac_rule), GFP_KERNEL);
- if (!repr->mac_rule) {
- err = -ENOMEM;
- goto err_alloc_rule;
- }
-#endif
-
repr->netdev = alloc_etherdev(sizeof(struct ice_netdev_priv));
if (!repr->netdev) {
err = -ENOMEM;
@@ -351,11 +343,6 @@ err_alloc_q_vector:
free_netdev(repr->netdev);
repr->netdev = NULL;
err_alloc:
-#ifdef CONFIG_ICE_SWITCHDEV
- kfree(repr->mac_rule);
- repr->mac_rule = NULL;
-err_alloc_rule:
-#endif
kfree(repr);
vf->repr = NULL;
return err;
@@ -376,10 +363,6 @@ static void ice_repr_rem(struct ice_vf *vf)
ice_devlink_destroy_vf_port(vf);
free_netdev(vf->repr->netdev);
vf->repr->netdev = NULL;
-#ifdef CONFIG_ICE_SWITCHDEV
- kfree(vf->repr->mac_rule);
- vf->repr->mac_rule = NULL;
-#endif
kfree(vf->repr);
vf->repr = NULL;
diff --git a/drivers/net/ethernet/intel/ice/ice_repr.h b/drivers/net/ethernet/intel/ice/ice_repr.h
index 378a45bfa256..9c2a6f496b3b 100644
--- a/drivers/net/ethernet/intel/ice/ice_repr.h
+++ b/drivers/net/ethernet/intel/ice/ice_repr.h
@@ -13,9 +13,8 @@ struct ice_repr {
struct net_device *netdev;
struct metadata_dst *dst;
#ifdef CONFIG_ICE_SWITCHDEV
- /* info about slow path MAC rule */
- struct ice_rule_query_data *mac_rule;
- u8 rule_added;
+ /* info about slow path rule */
+ struct ice_rule_query_data sp_rule;
#endif
};
diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c
index b7682de0ae05..b664d60fd037 100644
--- a/drivers/net/ethernet/intel/ice/ice_sched.c
+++ b/drivers/net/ethernet/intel/ice/ice_sched.c
@@ -358,10 +358,7 @@ void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node)
node->sibling;
}
- /* leaf nodes have no children */
- if (node->children)
- devm_kfree(ice_hw_to_dev(hw), node->children);
-
+ devm_kfree(ice_hw_to_dev(hw), node->children);
kfree(node->name);
xa_erase(&pi->sched_node_ids, node->id);
devm_kfree(ice_hw_to_dev(hw), node);
@@ -859,10 +856,8 @@ void ice_sched_cleanup_all(struct ice_hw *hw)
if (!hw)
return;
- if (hw->layer_info) {
- devm_kfree(ice_hw_to_dev(hw), hw->layer_info);
- hw->layer_info = NULL;
- }
+ devm_kfree(ice_hw_to_dev(hw), hw->layer_info);
+ hw->layer_info = NULL;
ice_sched_clear_port(hw->port_info);
diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c
index 588ad8696756..31314e7540f8 100644
--- a/drivers/net/ethernet/intel/ice/ice_sriov.c
+++ b/drivers/net/ethernet/intel/ice/ice_sriov.c
@@ -135,18 +135,9 @@ static void ice_dis_vf_mappings(struct ice_vf *vf)
*/
static int ice_sriov_free_msix_res(struct ice_pf *pf)
{
- struct ice_res_tracker *res;
-
if (!pf)
return -EINVAL;
- res = pf->irq_tracker;
- if (!res)
- return -EINVAL;
-
- /* give back irq_tracker resources used */
- WARN_ON(pf->sriov_base_vector < res->num_entries);
-
pf->sriov_base_vector = 0;
return 0;
@@ -410,29 +401,6 @@ int ice_calc_vf_reg_idx(struct ice_vf *vf, struct ice_q_vector *q_vector)
}
/**
- * ice_get_max_valid_res_idx - Get the max valid resource index
- * @res: pointer to the resource to find the max valid index for
- *
- * Start from the end of the ice_res_tracker and return right when we find the
- * first res->list entry with the ICE_RES_VALID_BIT set. This function is only
- * valid for SR-IOV because it is the only consumer that manipulates the
- * res->end and this is always called when res->end is set to res->num_entries.
- */
-static int ice_get_max_valid_res_idx(struct ice_res_tracker *res)
-{
- int i;
-
- if (!res)
- return -EINVAL;
-
- for (i = res->num_entries - 1; i >= 0; i--)
- if (res->list[i] & ICE_RES_VALID_BIT)
- return i;
-
- return 0;
-}
-
-/**
* ice_sriov_set_msix_res - Set any used MSIX resources
* @pf: pointer to PF structure
* @num_msix_needed: number of MSIX vectors needed for all SR-IOV VFs
@@ -450,7 +418,7 @@ static int ice_get_max_valid_res_idx(struct ice_res_tracker *res)
static int ice_sriov_set_msix_res(struct ice_pf *pf, u16 num_msix_needed)
{
u16 total_vectors = pf->hw.func_caps.common_cap.num_msix_vectors;
- int vectors_used = pf->irq_tracker->num_entries;
+ int vectors_used = ice_get_max_used_msix_vector(pf);
int sriov_base_vector;
sriov_base_vector = total_vectors - num_msix_needed;
@@ -490,7 +458,7 @@ static int ice_sriov_set_msix_res(struct ice_pf *pf, u16 num_msix_needed)
*/
static int ice_set_per_vf_res(struct ice_pf *pf, u16 num_vfs)
{
- int max_valid_res_idx = ice_get_max_valid_res_idx(pf->irq_tracker);
+ int vectors_used = ice_get_max_used_msix_vector(pf);
u16 num_msix_per_vf, num_txq, num_rxq, avail_qs;
int msix_avail_per_vf, msix_avail_for_sriov;
struct device *dev = ice_pf_to_dev(pf);
@@ -501,12 +469,9 @@ static int ice_set_per_vf_res(struct ice_pf *pf, u16 num_vfs)
if (!num_vfs)
return -EINVAL;
- if (max_valid_res_idx < 0)
- return -ENOSPC;
-
/* determine MSI-X resources per VF */
msix_avail_for_sriov = pf->hw.func_caps.common_cap.num_msix_vectors -
- pf->irq_tracker->num_entries;
+ vectors_used;
msix_avail_per_vf = msix_avail_for_sriov / num_vfs;
if (msix_avail_per_vf >= ICE_NUM_VF_MSIX_MED) {
num_msix_per_vf = ICE_NUM_VF_MSIX_MED;
@@ -871,7 +836,7 @@ static int ice_ena_vfs(struct ice_pf *pf, u16 num_vfs)
int ret;
/* Disable global interrupt 0 so we don't try to handle the VFLR. */
- wr32(hw, GLINT_DYN_CTL(pf->oicr_idx),
+ wr32(hw, GLINT_DYN_CTL(pf->oicr_irq.index),
ICE_ITR_NONE << GLINT_DYN_CTL_ITR_INDX_S);
set_bit(ICE_OICR_INTR_DIS, pf->state);
ice_flush(hw);
@@ -940,14 +905,13 @@ err_unroll_intr:
*/
static int ice_pci_sriov_ena(struct ice_pf *pf, int num_vfs)
{
- int pre_existing_vfs = pci_num_vf(pf->pdev);
struct device *dev = ice_pf_to_dev(pf);
int err;
- if (pre_existing_vfs && pre_existing_vfs != num_vfs)
+ if (!num_vfs) {
ice_free_vfs(pf);
- else if (pre_existing_vfs && pre_existing_vfs == num_vfs)
return 0;
+ }
if (num_vfs > pf->vfs.num_supported) {
dev_err(dev, "Can't enable %d VFs, max VFs supported is %d\n",
@@ -1014,8 +978,6 @@ int ice_sriov_configure(struct pci_dev *pdev, int num_vfs)
if (!num_vfs) {
if (!pci_vfs_assigned(pdev)) {
ice_free_vfs(pf);
- if (pf->lag)
- ice_enable_lag(pf->lag);
return 0;
}
@@ -1027,8 +989,6 @@ int ice_sriov_configure(struct pci_dev *pdev, int num_vfs)
if (err)
return err;
- if (pf->lag)
- ice_disable_lag(pf->lag);
return num_vfs;
}
@@ -1171,7 +1131,7 @@ int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena)
if (!vf)
return -EINVAL;
- ret = ice_check_vf_ready_for_reset(vf);
+ ret = ice_check_vf_ready_for_cfg(vf);
if (ret)
goto out_put_vf;
@@ -1286,7 +1246,7 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
goto out_put_vf;
}
- ret = ice_check_vf_ready_for_reset(vf);
+ ret = ice_check_vf_ready_for_cfg(vf);
if (ret)
goto out_put_vf;
@@ -1340,7 +1300,7 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)
return -EOPNOTSUPP;
}
- ret = ice_check_vf_ready_for_reset(vf);
+ ret = ice_check_vf_ready_for_cfg(vf);
if (ret)
goto out_put_vf;
@@ -1653,7 +1613,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
if (!vf)
return -EINVAL;
- ret = ice_check_vf_ready_for_reset(vf);
+ ret = ice_check_vf_ready_for_cfg(vf);
if (ret)
goto out_put_vf;
diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c
index 46b36851af46..6db4ca7978cb 100644
--- a/drivers/net/ethernet/intel/ice/ice_switch.c
+++ b/drivers/net/ethernet/intel/ice/ice_switch.c
@@ -1636,21 +1636,16 @@ ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi)
*/
static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle)
{
- struct ice_vsi_ctx *vsi;
+ struct ice_vsi_ctx *vsi = ice_get_vsi_ctx(hw, vsi_handle);
u8 i;
- vsi = ice_get_vsi_ctx(hw, vsi_handle);
if (!vsi)
return;
ice_for_each_traffic_class(i) {
- if (vsi->lan_q_ctx[i]) {
- devm_kfree(ice_hw_to_dev(hw), vsi->lan_q_ctx[i]);
- vsi->lan_q_ctx[i] = NULL;
- }
- if (vsi->rdma_q_ctx[i]) {
- devm_kfree(ice_hw_to_dev(hw), vsi->rdma_q_ctx[i]);
- vsi->rdma_q_ctx[i] = NULL;
- }
+ devm_kfree(ice_hw_to_dev(hw), vsi->lan_q_ctx[i]);
+ vsi->lan_q_ctx[i] = NULL;
+ devm_kfree(ice_hw_to_dev(hw), vsi->rdma_q_ctx[i]);
+ vsi->rdma_q_ctx[i] = NULL;
}
}
@@ -4540,6 +4535,11 @@ ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
return status;
}
+#define ICE_PROTOCOL_ENTRY(id, ...) { \
+ .prot_type = id, \
+ .offs = {__VA_ARGS__}, \
+}
+
/* This is mapping table entry that maps every word within a given protocol
* structure to the real byte offset as per the specification of that
* protocol header.
@@ -4550,29 +4550,38 @@ ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
* structure is added to that union.
*/
static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = {
- { ICE_MAC_OFOS, { 0, 2, 4, 6, 8, 10, 12 } },
- { ICE_MAC_IL, { 0, 2, 4, 6, 8, 10, 12 } },
- { ICE_ETYPE_OL, { 0 } },
- { ICE_ETYPE_IL, { 0 } },
- { ICE_VLAN_OFOS, { 2, 0 } },
- { ICE_IPV4_OFOS, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } },
- { ICE_IPV4_IL, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } },
- { ICE_IPV6_OFOS, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
- 26, 28, 30, 32, 34, 36, 38 } },
- { ICE_IPV6_IL, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
- 26, 28, 30, 32, 34, 36, 38 } },
- { ICE_TCP_IL, { 0, 2 } },
- { ICE_UDP_OF, { 0, 2 } },
- { ICE_UDP_ILOS, { 0, 2 } },
- { ICE_VXLAN, { 8, 10, 12, 14 } },
- { ICE_GENEVE, { 8, 10, 12, 14 } },
- { ICE_NVGRE, { 0, 2, 4, 6 } },
- { ICE_GTP, { 8, 10, 12, 14, 16, 18, 20, 22 } },
- { ICE_GTP_NO_PAY, { 8, 10, 12, 14 } },
- { ICE_PPPOE, { 0, 2, 4, 6 } },
- { ICE_L2TPV3, { 0, 2, 4, 6, 8, 10 } },
- { ICE_VLAN_EX, { 2, 0 } },
- { ICE_VLAN_IN, { 2, 0 } },
+ ICE_PROTOCOL_ENTRY(ICE_MAC_OFOS, 0, 2, 4, 6, 8, 10, 12),
+ ICE_PROTOCOL_ENTRY(ICE_MAC_IL, 0, 2, 4, 6, 8, 10, 12),
+ ICE_PROTOCOL_ENTRY(ICE_ETYPE_OL, 0),
+ ICE_PROTOCOL_ENTRY(ICE_ETYPE_IL, 0),
+ ICE_PROTOCOL_ENTRY(ICE_VLAN_OFOS, 2, 0),
+ ICE_PROTOCOL_ENTRY(ICE_IPV4_OFOS, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18),
+ ICE_PROTOCOL_ENTRY(ICE_IPV4_IL, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18),
+ ICE_PROTOCOL_ENTRY(ICE_IPV6_OFOS, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18,
+ 20, 22, 24, 26, 28, 30, 32, 34, 36, 38),
+ ICE_PROTOCOL_ENTRY(ICE_IPV6_IL, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
+ 22, 24, 26, 28, 30, 32, 34, 36, 38),
+ ICE_PROTOCOL_ENTRY(ICE_TCP_IL, 0, 2),
+ ICE_PROTOCOL_ENTRY(ICE_UDP_OF, 0, 2),
+ ICE_PROTOCOL_ENTRY(ICE_UDP_ILOS, 0, 2),
+ ICE_PROTOCOL_ENTRY(ICE_VXLAN, 8, 10, 12, 14),
+ ICE_PROTOCOL_ENTRY(ICE_GENEVE, 8, 10, 12, 14),
+ ICE_PROTOCOL_ENTRY(ICE_NVGRE, 0, 2, 4, 6),
+ ICE_PROTOCOL_ENTRY(ICE_GTP, 8, 10, 12, 14, 16, 18, 20, 22),
+ ICE_PROTOCOL_ENTRY(ICE_GTP_NO_PAY, 8, 10, 12, 14),
+ ICE_PROTOCOL_ENTRY(ICE_PPPOE, 0, 2, 4, 6),
+ ICE_PROTOCOL_ENTRY(ICE_L2TPV3, 0, 2, 4, 6, 8, 10),
+ ICE_PROTOCOL_ENTRY(ICE_VLAN_EX, 2, 0),
+ ICE_PROTOCOL_ENTRY(ICE_VLAN_IN, 2, 0),
+ ICE_PROTOCOL_ENTRY(ICE_HW_METADATA,
+ ICE_SOURCE_PORT_MDID_OFFSET,
+ ICE_PTYPE_MDID_OFFSET,
+ ICE_PACKET_LENGTH_MDID_OFFSET,
+ ICE_SOURCE_VSI_MDID_OFFSET,
+ ICE_PKT_VLAN_MDID_OFFSET,
+ ICE_PKT_TUNNEL_MDID_OFFSET,
+ ICE_PKT_TCP_MDID_OFFSET,
+ ICE_PKT_ERROR_MDID_OFFSET),
};
static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
@@ -4597,6 +4606,7 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
{ ICE_L2TPV3, ICE_L2TPV3_HW },
{ ICE_VLAN_EX, ICE_VLAN_OF_HW },
{ ICE_VLAN_IN, ICE_VLAN_OL_HW },
+ { ICE_HW_METADATA, ICE_META_DATA_ID_HW },
};
/**
@@ -5255,71 +5265,6 @@ ice_create_recipe_group(struct ice_hw *hw, struct ice_sw_recipe *rm,
return status;
}
-/**
- * ice_tun_type_match_word - determine if tun type needs a match mask
- * @tun_type: tunnel type
- * @mask: mask to be used for the tunnel
- */
-static bool ice_tun_type_match_word(enum ice_sw_tunnel_type tun_type, u16 *mask)
-{
- switch (tun_type) {
- case ICE_SW_TUN_GENEVE:
- case ICE_SW_TUN_VXLAN:
- case ICE_SW_TUN_NVGRE:
- case ICE_SW_TUN_GTPU:
- case ICE_SW_TUN_GTPC:
- *mask = ICE_TUN_FLAG_MASK;
- return true;
-
- default:
- *mask = 0;
- return false;
- }
-}
-
-/**
- * ice_add_special_words - Add words that are not protocols, such as metadata
- * @rinfo: other information regarding the rule e.g. priority and action info
- * @lkup_exts: lookup word structure
- * @dvm_ena: is double VLAN mode enabled
- */
-static int
-ice_add_special_words(struct ice_adv_rule_info *rinfo,
- struct ice_prot_lkup_ext *lkup_exts, bool dvm_ena)
-{
- u16 mask;
-
- /* If this is a tunneled packet, then add recipe index to match the
- * tunnel bit in the packet metadata flags.
- */
- if (ice_tun_type_match_word(rinfo->tun_type, &mask)) {
- if (lkup_exts->n_val_words < ICE_MAX_CHAIN_WORDS) {
- u8 word = lkup_exts->n_val_words++;
-
- lkup_exts->fv_words[word].prot_id = ICE_META_DATA_ID_HW;
- lkup_exts->fv_words[word].off = ICE_TUN_FLAG_MDID_OFF;
- lkup_exts->field_mask[word] = mask;
- } else {
- return -ENOSPC;
- }
- }
-
- if (rinfo->vlan_type != 0 && dvm_ena) {
- if (lkup_exts->n_val_words < ICE_MAX_CHAIN_WORDS) {
- u8 word = lkup_exts->n_val_words++;
-
- lkup_exts->fv_words[word].prot_id = ICE_META_DATA_ID_HW;
- lkup_exts->fv_words[word].off = ICE_VLAN_FLAG_MDID_OFF;
- lkup_exts->field_mask[word] =
- ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK;
- } else {
- return -ENOSPC;
- }
- }
-
- return 0;
-}
-
/* ice_get_compat_fv_bitmap - Get compatible field vector bitmap for rule
* @hw: pointer to hardware structure
* @rinfo: other information regarding the rule e.g. priority and action info
@@ -5433,13 +5378,6 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
if (status)
goto err_unroll;
- /* Create any special protocol/offset pairs, such as looking at tunnel
- * bits by extracting metadata
- */
- status = ice_add_special_words(rinfo, lkup_exts, ice_is_dvm_ena(hw));
- if (status)
- goto err_unroll;
-
/* Group match words into recipes using preferred recipe grouping
* criteria.
*/
@@ -5525,9 +5463,7 @@ err_unroll:
devm_kfree(ice_hw_to_dev(hw), fvit);
}
- if (rm->root_buf)
- devm_kfree(ice_hw_to_dev(hw), rm->root_buf);
-
+ devm_kfree(ice_hw_to_dev(hw), rm->root_buf);
kfree(rm);
err_free_lkup_exts:
@@ -5725,6 +5661,10 @@ ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
* was already checked when search for the dummy packet
*/
type = lkups[i].type;
+ /* metadata isn't present in the packet */
+ if (type == ICE_HW_METADATA)
+ continue;
+
for (j = 0; offsets[j].type != ICE_PROTOCOL_LAST; j++) {
if (type == offsets[j].type) {
offset = offsets[j].offset;
@@ -5860,16 +5800,21 @@ ice_fill_adv_packet_tun(struct ice_hw *hw, enum ice_sw_tunnel_type tun_type,
/**
* ice_fill_adv_packet_vlan - fill dummy packet with VLAN tag type
+ * @hw: pointer to hw structure
* @vlan_type: VLAN tag type
* @pkt: dummy packet to fill in
* @offsets: offset info for the dummy packet
*/
static int
-ice_fill_adv_packet_vlan(u16 vlan_type, u8 *pkt,
+ice_fill_adv_packet_vlan(struct ice_hw *hw, u16 vlan_type, u8 *pkt,
const struct ice_dummy_pkt_offsets *offsets)
{
u16 i;
+ /* Check if there is something to do */
+ if (!vlan_type || !ice_is_dvm_ena(hw))
+ return 0;
+
/* Find VLAN header and insert VLAN TPID */
for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) {
if (offsets[i].type == ICE_VLAN_OFOS ||
@@ -5888,6 +5833,15 @@ ice_fill_adv_packet_vlan(u16 vlan_type, u8 *pkt,
return -EIO;
}
+static bool ice_rules_equal(const struct ice_adv_rule_info *first,
+ const struct ice_adv_rule_info *second)
+{
+ return first->sw_act.flag == second->sw_act.flag &&
+ first->tun_type == second->tun_type &&
+ first->vlan_type == second->vlan_type &&
+ first->src_vsi == second->src_vsi;
+}
+
/**
* ice_find_adv_rule_entry - Search a rule entry
* @hw: pointer to the hardware structure
@@ -5921,9 +5875,7 @@ ice_find_adv_rule_entry(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
lkups_matched = false;
break;
}
- if (rinfo->sw_act.flag == list_itr->rule_info.sw_act.flag &&
- rinfo->tun_type == list_itr->rule_info.tun_type &&
- rinfo->vlan_type == list_itr->rule_info.vlan_type &&
+ if (ice_rules_equal(rinfo, &list_itr->rule_info) &&
lkups_matched)
return list_itr;
}
@@ -6039,6 +5991,26 @@ ice_adv_add_update_vsi_list(struct ice_hw *hw,
return status;
}
+void ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup)
+{
+ lkup->type = ICE_HW_METADATA;
+ lkup->m_u.metadata.flags[ICE_PKT_FLAGS_TUNNEL] =
+ cpu_to_be16(ICE_PKT_TUNNEL_MASK);
+}
+
+void ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem *lkup)
+{
+ lkup->type = ICE_HW_METADATA;
+ lkup->m_u.metadata.flags[ICE_PKT_FLAGS_VLAN] =
+ cpu_to_be16(ICE_PKT_VLAN_MASK);
+}
+
+void ice_rule_add_src_vsi_metadata(struct ice_adv_lkup_elem *lkup)
+{
+ lkup->type = ICE_HW_METADATA;
+ lkup->m_u.metadata.source_vsi = cpu_to_be16(ICE_MDID_SOURCE_VSI_MASK);
+}
+
/**
* ice_add_adv_rule - helper function to create an advanced switch rule
* @hw: pointer to the hardware structure
@@ -6120,7 +6092,10 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI)
rinfo->sw_act.fwd_id.hw_vsi_id =
ice_get_hw_vsi_num(hw, vsi_handle);
- if (rinfo->sw_act.flag & ICE_FLTR_TX)
+
+ if (rinfo->src_vsi)
+ rinfo->sw_act.src = ice_get_hw_vsi_num(hw, rinfo->src_vsi);
+ else
rinfo->sw_act.src = ice_get_hw_vsi_num(hw, vsi_handle);
status = ice_add_adv_recipe(hw, lkups, lkups_cnt, rinfo, &rid);
@@ -6189,19 +6164,20 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
goto err_ice_add_adv_rule;
}
- /* set the rule LOOKUP type based on caller specified 'Rx'
- * instead of hardcoding it to be either LOOKUP_TX/RX
+ /* If there is no matching criteria for direction there
+ * is only one difference between Rx and Tx:
+ * - get switch id base on VSI number from source field (Tx)
+ * - get switch id base on port number (Rx)
*
- * for 'Rx' set the source to be the port number
- * for 'Tx' set the source to be the source HW VSI number (determined
- * by caller)
+ * If matching on direction metadata is chose rule direction is
+ * extracted from type value set here.
*/
- if (rinfo->rx) {
- s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX);
- s_rule->src = cpu_to_le16(hw->port_info->lport);
- } else {
+ if (rinfo->sw_act.flag & ICE_FLTR_TX) {
s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX);
s_rule->src = cpu_to_le16(rinfo->sw_act.src);
+ } else {
+ s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX);
+ s_rule->src = cpu_to_le16(hw->port_info->lport);
}
s_rule->recipe_id = cpu_to_le16(rid);
@@ -6211,22 +6187,16 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
if (status)
goto err_ice_add_adv_rule;
- if (rinfo->tun_type != ICE_NON_TUN &&
- rinfo->tun_type != ICE_SW_TUN_AND_NON_TUN) {
- status = ice_fill_adv_packet_tun(hw, rinfo->tun_type,
- s_rule->hdr_data,
- profile->offsets);
- if (status)
- goto err_ice_add_adv_rule;
- }
+ status = ice_fill_adv_packet_tun(hw, rinfo->tun_type, s_rule->hdr_data,
+ profile->offsets);
+ if (status)
+ goto err_ice_add_adv_rule;
- if (rinfo->vlan_type != 0 && ice_is_dvm_ena(hw)) {
- status = ice_fill_adv_packet_vlan(rinfo->vlan_type,
- s_rule->hdr_data,
- profile->offsets);
- if (status)
- goto err_ice_add_adv_rule;
- }
+ status = ice_fill_adv_packet_vlan(hw, rinfo->vlan_type,
+ s_rule->hdr_data,
+ profile->offsets);
+ if (status)
+ goto err_ice_add_adv_rule;
status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule,
rule_buf_sz, 1, ice_aqc_opc_add_sw_rules,
@@ -6469,13 +6439,6 @@ ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
return -EIO;
}
- /* Create any special protocol/offset pairs, such as looking at tunnel
- * bits by extracting metadata
- */
- status = ice_add_special_words(rinfo, &lkup_exts, ice_is_dvm_ena(hw));
- if (status)
- return status;
-
rid = ice_find_recp(hw, &lkup_exts, rinfo->tun_type);
/* If did not find a recipe that match the existing criteria */
if (rid == ICE_MAX_NUM_RECIPES)
diff --git a/drivers/net/ethernet/intel/ice/ice_switch.h b/drivers/net/ethernet/intel/ice/ice_switch.h
index 68d8e8a6a189..c84b56fe84a5 100644
--- a/drivers/net/ethernet/intel/ice/ice_switch.h
+++ b/drivers/net/ethernet/intel/ice/ice_switch.h
@@ -10,7 +10,6 @@
#define ICE_DFLT_VSI_INVAL 0xff
#define ICE_FLTR_RX BIT(0)
#define ICE_FLTR_TX BIT(1)
-#define ICE_FLTR_TX_RX (ICE_FLTR_RX | ICE_FLTR_TX)
#define ICE_VSI_INVAL_ID 0xffff
#define ICE_INVAL_Q_HANDLE 0xFFFF
@@ -187,12 +186,13 @@ struct ice_adv_rule_flags_info {
};
struct ice_adv_rule_info {
+ /* Store metadata values in rule info */
enum ice_sw_tunnel_type tun_type;
- struct ice_sw_act_ctrl sw_act;
- u32 priority;
- u8 rx; /* true means LOOKUP_RX otherwise LOOKUP_TX */
- u16 fltr_rule_id;
u16 vlan_type;
+ u16 fltr_rule_id;
+ u32 priority;
+ u16 src_vsi;
+ struct ice_sw_act_ctrl sw_act;
struct ice_adv_rule_flags_info flags_info;
};
@@ -342,6 +342,9 @@ ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
u16 counter_id);
/* Switch/bridge related commands */
+void ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup);
+void ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem *lkup);
+void ice_rule_add_src_vsi_metadata(struct ice_adv_lkup_elem *lkup);
int
ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
u16 lkups_cnt, struct ice_adv_rule_info *rinfo,
diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.c b/drivers/net/ethernet/intel/ice/ice_tc_lib.c
index d1a31f236d26..4a34ef5f58d3 100644
--- a/drivers/net/ethernet/intel/ice/ice_tc_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.c
@@ -54,6 +54,10 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
if (flags & (ICE_TC_FLWR_FIELD_VLAN | ICE_TC_FLWR_FIELD_VLAN_PRIO))
lkups_cnt++;
+ /* is VLAN TPID specified */
+ if (flags & ICE_TC_FLWR_FIELD_VLAN_TPID)
+ lkups_cnt++;
+
/* is CVLAN specified? */
if (flags & (ICE_TC_FLWR_FIELD_CVLAN | ICE_TC_FLWR_FIELD_CVLAN_PRIO))
lkups_cnt++;
@@ -80,6 +84,10 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
ICE_TC_FLWR_FIELD_SRC_L4_PORT))
lkups_cnt++;
+ /* matching for tunneled packets in metadata */
+ if (fltr->tunnel_type != TNL_LAST)
+ lkups_cnt++;
+
return lkups_cnt;
}
@@ -320,6 +328,10 @@ ice_tc_fill_tunnel_outer(u32 flags, struct ice_tc_flower_fltr *fltr,
i++;
}
+ /* always fill matching on tunneled packets in metadata */
+ ice_rule_add_tunnel_metadata(&list[i]);
+ i++;
+
return i;
}
@@ -390,10 +402,6 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
/* copy VLAN info */
if (flags & (ICE_TC_FLWR_FIELD_VLAN | ICE_TC_FLWR_FIELD_VLAN_PRIO)) {
- vlan_tpid = be16_to_cpu(headers->vlan_hdr.vlan_tpid);
- rule_info->vlan_type =
- ice_check_supported_vlan_tpid(vlan_tpid);
-
if (flags & ICE_TC_FLWR_FIELD_CVLAN)
list[i].type = ICE_VLAN_EX;
else
@@ -418,6 +426,15 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
i++;
}
+ if (flags & ICE_TC_FLWR_FIELD_VLAN_TPID) {
+ vlan_tpid = be16_to_cpu(headers->vlan_hdr.vlan_tpid);
+ rule_info->vlan_type =
+ ice_check_supported_vlan_tpid(vlan_tpid);
+
+ ice_rule_add_vlan_metadata(&list[i]);
+ i++;
+ }
+
if (flags & (ICE_TC_FLWR_FIELD_CVLAN | ICE_TC_FLWR_FIELD_CVLAN_PRIO)) {
list[i].type = ICE_VLAN_IN;
@@ -698,12 +715,10 @@ ice_eswitch_add_tc_fltr(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr)
if (fltr->direction == ICE_ESWITCH_FLTR_INGRESS) {
rule_info.sw_act.flag |= ICE_FLTR_RX;
rule_info.sw_act.src = hw->pf_id;
- rule_info.rx = true;
rule_info.flags_info.act = ICE_SINGLE_ACT_LB_ENABLE;
} else {
rule_info.sw_act.flag |= ICE_FLTR_TX;
rule_info.sw_act.src = vsi->idx;
- rule_info.rx = false;
rule_info.flags_info.act = ICE_SINGLE_ACT_LAN_ENABLE;
}
@@ -735,17 +750,16 @@ exit:
/**
* ice_locate_vsi_using_queue - locate VSI using queue (forward to queue action)
* @vsi: Pointer to VSI
- * @tc_fltr: Pointer to tc_flower_filter
+ * @queue: Queue index
*
- * Locate the VSI using specified queue. When ADQ is not enabled, always
- * return input VSI, otherwise locate corresponding VSI based on per channel
- * offset and qcount
+ * Locate the VSI using specified "queue". When ADQ is not enabled,
+ * always return input VSI, otherwise locate corresponding
+ * VSI based on per channel "offset" and "qcount"
*/
-static struct ice_vsi *
-ice_locate_vsi_using_queue(struct ice_vsi *vsi,
- struct ice_tc_flower_fltr *tc_fltr)
+struct ice_vsi *
+ice_locate_vsi_using_queue(struct ice_vsi *vsi, int queue)
{
- int num_tc, tc, queue;
+ int num_tc, tc;
/* if ADQ is not active, passed VSI is the candidate VSI */
if (!ice_is_adq_active(vsi->back))
@@ -755,7 +769,6 @@ ice_locate_vsi_using_queue(struct ice_vsi *vsi,
* upon queue number)
*/
num_tc = vsi->mqprio_qopt.qopt.num_tc;
- queue = tc_fltr->action.fwd.q.queue;
for (tc = 0; tc < num_tc; tc++) {
int qcount = vsi->mqprio_qopt.qopt.count[tc];
@@ -797,6 +810,7 @@ ice_tc_forward_action(struct ice_vsi *vsi, struct ice_tc_flower_fltr *tc_fltr)
struct ice_pf *pf = vsi->back;
struct device *dev;
u32 tc_class;
+ int q;
dev = ice_pf_to_dev(pf);
@@ -825,7 +839,8 @@ ice_tc_forward_action(struct ice_vsi *vsi, struct ice_tc_flower_fltr *tc_fltr)
/* Determine destination VSI even though the action is
* FWD_TO_QUEUE, because QUEUE is associated with VSI
*/
- dest_vsi = tc_fltr->dest_vsi;
+ q = tc_fltr->action.fwd.q.queue;
+ dest_vsi = ice_locate_vsi_using_queue(vsi, q);
break;
default:
dev_err(dev,
@@ -910,7 +925,6 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi,
rule_info.sw_act.vsi_handle = dest_vsi->idx;
rule_info.priority = ICE_SWITCH_FLTR_PRIO_VSI;
rule_info.sw_act.src = hw->pf_id;
- rule_info.rx = true;
dev_dbg(dev, "add switch rule for TC:%u vsi_idx:%u, lkups_cnt:%u\n",
tc_fltr->action.fwd.tc.tc_class,
rule_info.sw_act.vsi_handle, lkups_cnt);
@@ -921,7 +935,6 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi,
rule_info.sw_act.vsi_handle = dest_vsi->idx;
rule_info.priority = ICE_SWITCH_FLTR_PRIO_QUEUE;
rule_info.sw_act.src = hw->pf_id;
- rule_info.rx = true;
dev_dbg(dev, "add switch rule action to forward to queue:%u (HW queue %u), lkups_cnt:%u\n",
tc_fltr->action.fwd.q.queue,
tc_fltr->action.fwd.q.hw_queue, lkups_cnt);
@@ -929,7 +942,6 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi,
case ICE_DROP_PACKET:
rule_info.sw_act.flag |= ICE_FLTR_RX;
rule_info.sw_act.src = hw->pf_id;
- rule_info.rx = true;
rule_info.priority = ICE_SWITCH_FLTR_PRIO_VSI;
break;
default:
@@ -1460,8 +1472,10 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
VLAN_PRIO_MASK);
}
- if (match.mask->vlan_tpid)
+ if (match.mask->vlan_tpid) {
headers->vlan_hdr.vlan_tpid = match.key->vlan_tpid;
+ fltr->flags |= ICE_TC_FLWR_FIELD_VLAN_TPID;
+ }
}
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) {
@@ -1702,7 +1716,7 @@ ice_tc_forward_to_queue(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr,
/* If ADQ is configured, and the queue belongs to ADQ VSI, then prepare
* ADQ switch filter
*/
- ch_vsi = ice_locate_vsi_using_queue(vsi, fltr);
+ ch_vsi = ice_locate_vsi_using_queue(vsi, fltr->action.fwd.q.queue);
if (!ch_vsi)
return -EINVAL;
fltr->dest_vsi = ch_vsi;
diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.h b/drivers/net/ethernet/intel/ice/ice_tc_lib.h
index 8d5e22ac7023..65d387163a46 100644
--- a/drivers/net/ethernet/intel/ice/ice_tc_lib.h
+++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.h
@@ -33,6 +33,7 @@
#define ICE_TC_FLWR_FIELD_L2TPV3_SESSID BIT(26)
#define ICE_TC_FLWR_FIELD_VLAN_PRIO BIT(27)
#define ICE_TC_FLWR_FIELD_CVLAN_PRIO BIT(28)
+#define ICE_TC_FLWR_FIELD_VLAN_TPID BIT(29)
#define ICE_TC_FLOWER_MASK_32 0xFFFFFFFF
@@ -203,6 +204,7 @@ static inline int ice_chnl_dmac_fltr_cnt(struct ice_pf *pf)
return pf->num_dmac_chnl_fltrs;
}
+struct ice_vsi *ice_locate_vsi_using_queue(struct ice_vsi *vsi, int queue);
int
ice_add_cls_flower(struct net_device *netdev, struct ice_vsi *vsi,
struct flow_cls_offload *cls_flower);
diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
index bf74a2f3a4f8..ea3310be8354 100644
--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
@@ -186,25 +186,6 @@ int ice_check_vf_ready_for_cfg(struct ice_vf *vf)
}
/**
- * ice_check_vf_ready_for_reset - check if VF is ready to be reset
- * @vf: VF to check if it's ready to be reset
- *
- * The purpose of this function is to ensure that the VF is not in reset,
- * disabled, and is both initialized and active, thus enabling us to safely
- * initialize another reset.
- */
-int ice_check_vf_ready_for_reset(struct ice_vf *vf)
-{
- int ret;
-
- ret = ice_check_vf_ready_for_cfg(vf);
- if (!ret && !test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
- ret = -EAGAIN;
-
- return ret;
-}
-
-/**
* ice_trigger_vf_reset - Reset a VF on HW
* @vf: pointer to the VF structure
* @is_vflr: true if VFLR was issued, false if not
@@ -631,11 +612,17 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
return 0;
}
+ if (flags & ICE_VF_RESET_LOCK)
+ mutex_lock(&vf->cfg_lock);
+ else
+ lockdep_assert_held(&vf->cfg_lock);
+
if (ice_is_vf_disabled(vf)) {
vsi = ice_get_vf_vsi(vf);
if (!vsi) {
dev_dbg(dev, "VF is already removed\n");
- return -EINVAL;
+ err = -EINVAL;
+ goto out_unlock;
}
ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, vf->vf_id);
@@ -644,14 +631,9 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
dev_dbg(dev, "VF is already disabled, there is no need for resetting it, telling VM, all is fine %d\n",
vf->vf_id);
- return 0;
+ goto out_unlock;
}
- if (flags & ICE_VF_RESET_LOCK)
- mutex_lock(&vf->cfg_lock);
- else
- lockdep_assert_held(&vf->cfg_lock);
-
/* Set VF disable bit state here, before triggering reset */
set_bit(ICE_VF_STATE_DIS, vf->vf_states);
ice_trigger_vf_reset(vf, flags & ICE_VF_RESET_VFLR, false);
@@ -689,8 +671,6 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
*/
ice_vf_clear_all_promisc_modes(vf, vsi);
- ice_eswitch_del_vf_mac_rule(vf);
-
ice_vf_fdir_exit(vf);
ice_vf_fdir_init(vf);
/* clean VF control VSI when resetting VF since it should be setup
@@ -716,7 +696,6 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
}
ice_eswitch_update_repr(vsi);
- ice_eswitch_replay_vf_mac_rule(vf);
/* if the VF has been reset allow it to come up again */
ice_mbx_clear_malvf(&vf->mbx_info);
@@ -1329,3 +1308,35 @@ void ice_vf_set_initialized(struct ice_vf *vf)
set_bit(ICE_VF_STATE_INIT, vf->vf_states);
memset(&vf->vlan_v2_caps, 0, sizeof(vf->vlan_v2_caps));
}
+
+/**
+ * ice_get_vf_ctrl_vsi - Get first VF control VSI pointer
+ * @pf: the PF private structure
+ * @vsi: pointer to the VSI
+ *
+ * Return first found VF control VSI other than the vsi
+ * passed by parameter. This function is used to determine
+ * whether new resources have to be allocated for control VSI
+ * or they can be shared with existing one.
+ *
+ * Return found VF control VSI pointer other itself. Return
+ * NULL Otherwise.
+ *
+ */
+struct ice_vsi *ice_get_vf_ctrl_vsi(struct ice_pf *pf, struct ice_vsi *vsi)
+{
+ struct ice_vsi *ctrl_vsi = NULL;
+ struct ice_vf *vf;
+ unsigned int bkt;
+
+ rcu_read_lock();
+ ice_for_each_vf_rcu(pf, bkt, vf) {
+ if (vf != vsi->vf && vf->ctrl_vsi_idx != ICE_NO_VSI) {
+ ctrl_vsi = pf->vsi[vf->ctrl_vsi_idx];
+ break;
+ }
+ }
+
+ rcu_read_unlock();
+ return ctrl_vsi;
+}
diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.h b/drivers/net/ethernet/intel/ice/ice_vf_lib.h
index a38ef00a3679..48fea6fa0362 100644
--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.h
+++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.h
@@ -215,7 +215,6 @@ u16 ice_get_num_vfs(struct ice_pf *pf);
struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf);
bool ice_is_vf_disabled(struct ice_vf *vf);
int ice_check_vf_ready_for_cfg(struct ice_vf *vf);
-int ice_check_vf_ready_for_reset(struct ice_vf *vf);
void ice_set_vf_state_dis(struct ice_vf *vf);
bool ice_is_any_vf_in_unicast_promisc(struct ice_pf *pf);
void
@@ -227,6 +226,7 @@ int
ice_vf_clear_vsi_promisc(struct ice_vf *vf, struct ice_vsi *vsi, u8 promisc_m);
int ice_reset_vf(struct ice_vf *vf, u32 flags);
void ice_reset_all_vfs(struct ice_pf *pf);
+struct ice_vsi *ice_get_vf_ctrl_vsi(struct ice_pf *pf, struct ice_vsi *vsi);
#else /* CONFIG_PCI_IOV */
static inline struct ice_vf *ice_get_vf_by_id(struct ice_pf *pf, u16 vf_id)
{
@@ -291,6 +291,12 @@ static inline int ice_reset_vf(struct ice_vf *vf, u32 flags)
static inline void ice_reset_all_vfs(struct ice_pf *pf)
{
}
+
+static inline struct ice_vsi *
+ice_get_vf_ctrl_vsi(struct ice_pf *pf, struct ice_vsi *vsi)
+{
+ return NULL;
+}
#endif /* !CONFIG_PCI_IOV */
#endif /* _ICE_VF_LIB_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
index f4a524f80b11..dcf628b1fccd 100644
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
@@ -3730,7 +3730,6 @@ static int ice_vc_repr_add_mac(struct ice_vf *vf, u8 *msg)
for (i = 0; i < al->num_elements; i++) {
u8 *mac_addr = al->list[i].addr;
- int result;
if (!is_unicast_ether_addr(mac_addr) ||
ether_addr_equal(mac_addr, vf->hw_lan_addr))
@@ -3742,13 +3741,6 @@ static int ice_vc_repr_add_mac(struct ice_vf *vf, u8 *msg)
goto handle_mac_exit;
}
- result = ice_eswitch_add_vf_mac_rule(pf, vf, mac_addr);
- if (result) {
- dev_err(ice_pf_to_dev(pf), "Failed to add MAC %pM for VF %d\n, error %d\n",
- mac_addr, vf->vf_id, result);
- goto handle_mac_exit;
- }
-
ice_vfhw_mac_add(vf, &al->list[i]);
vf->num_mac++;
break;
@@ -3955,7 +3947,6 @@ error_handler:
ice_vc_notify_vf_link_state(vf);
break;
case VIRTCHNL_OP_RESET_VF:
- clear_bit(ICE_VF_STATE_ACTIVE, vf->vf_states);
ops->reset_vf(vf);
break;
case VIRTCHNL_OP_ADD_ETH_ADDR:
diff --git a/drivers/net/ethernet/intel/ice/ice_vlan_mode.c b/drivers/net/ethernet/intel/ice/ice_vlan_mode.c
index bcda2e004807..1279c1ffe31c 100644
--- a/drivers/net/ethernet/intel/ice/ice_vlan_mode.c
+++ b/drivers/net/ethernet/intel/ice/ice_vlan_mode.c
@@ -219,7 +219,7 @@ static struct ice_update_recipe_lkup_idx_params ice_dvm_dflt_recipes[] = {
.rid = ICE_SW_LKUP_VLAN,
.fv_idx = ICE_PKT_FLAGS_0_TO_15_FV_IDX,
.ignore_valid = false,
- .mask = ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK,
+ .mask = ICE_PKT_VLAN_MASK,
.mask_valid = true,
.lkup_idx = ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX,
},
diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c
index d1e489da7363..a7fe2b4ce655 100644
--- a/drivers/net/ethernet/intel/ice/ice_xsk.c
+++ b/drivers/net/ethernet/intel/ice/ice_xsk.c
@@ -90,7 +90,6 @@ ice_qvec_dis_irq(struct ice_vsi *vsi, struct ice_rx_ring *rx_ring,
{
struct ice_pf *pf = vsi->back;
struct ice_hw *hw = &pf->hw;
- int base = vsi->base_vector;
u16 reg;
u32 val;
@@ -103,11 +102,9 @@ ice_qvec_dis_irq(struct ice_vsi *vsi, struct ice_rx_ring *rx_ring,
wr32(hw, QINT_RQCTL(reg), val);
if (q_vector) {
- u16 v_idx = q_vector->v_idx;
-
wr32(hw, GLINT_DYN_CTL(q_vector->reg_idx), 0);
ice_flush(hw);
- synchronize_irq(pf->msix_entries[v_idx + base].vector);
+ synchronize_irq(q_vector->irq.virq);
}
}
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index bb3db387d49c..9a2561409b06 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -183,11 +183,13 @@ static int igb_resume(struct device *);
static int igb_runtime_suspend(struct device *dev);
static int igb_runtime_resume(struct device *dev);
static int igb_runtime_idle(struct device *dev);
+#ifdef CONFIG_PM
static const struct dev_pm_ops igb_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(igb_suspend, igb_resume)
SET_RUNTIME_PM_OPS(igb_runtime_suspend, igb_runtime_resume,
igb_runtime_idle)
};
+#endif
static void igb_shutdown(struct pci_dev *);
static int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs);
#ifdef CONFIG_IGB_DCA
@@ -9585,6 +9587,11 @@ static pci_ers_result_t igb_io_error_detected(struct pci_dev *pdev,
struct net_device *netdev = pci_get_drvdata(pdev);
struct igb_adapter *adapter = netdev_priv(netdev);
+ if (state == pci_channel_io_normal) {
+ dev_warn(&pdev->dev, "Non-correctable non-fatal error reported.\n");
+ return PCI_ERS_RESULT_CAN_RECOVER;
+ }
+
netif_device_detach(netdev);
if (state == pci_channel_io_perm_failure)
diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c
index 405886ee5261..319c544b9f04 100644
--- a/drivers/net/ethernet/intel/igb/igb_ptp.c
+++ b/drivers/net/ethernet/intel/igb/igb_ptp.c
@@ -1385,18 +1385,6 @@ void igb_ptp_init(struct igb_adapter *adapter)
return;
}
- spin_lock_init(&adapter->tmreg_lock);
- INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work);
-
- if (adapter->ptp_flags & IGB_PTP_OVERFLOW_CHECK)
- INIT_DELAYED_WORK(&adapter->ptp_overflow_work,
- igb_ptp_overflow_check);
-
- adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
- adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
-
- igb_ptp_reset(adapter);
-
adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps,
&adapter->pdev->dev);
if (IS_ERR(adapter->ptp_clock)) {
@@ -1406,6 +1394,18 @@ void igb_ptp_init(struct igb_adapter *adapter)
dev_info(&adapter->pdev->dev, "added PHC on %s\n",
adapter->netdev->name);
adapter->ptp_flags |= IGB_PTP_ENABLED;
+
+ spin_lock_init(&adapter->tmreg_lock);
+ INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work);
+
+ if (adapter->ptp_flags & IGB_PTP_OVERFLOW_CHECK)
+ INIT_DELAYED_WORK(&adapter->ptp_overflow_work,
+ igb_ptp_overflow_check);
+
+ adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
+ adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
+
+ igb_ptp_reset(adapter);
}
}
diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index 34aebf00a512..38901d2a4680 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -13,6 +13,8 @@
#include <linux/ptp_clock_kernel.h>
#include <linux/timecounter.h>
#include <linux/net_tstamp.h>
+#include <linux/bitfield.h>
+#include <linux/hrtimer.h>
#include "igc_hw.h"
@@ -100,6 +102,8 @@ struct igc_ring {
u32 start_time;
u32 end_time;
u32 max_sdu;
+ bool oper_gate_closed; /* Operating gate. True if the TX Queue is closed */
+ bool admin_gate_closed; /* Future gate. True if the TX Queue will be closed */
/* CBS parameters */
bool cbs_enable; /* indicates if CBS is enabled */
@@ -159,6 +163,7 @@ struct igc_adapter {
struct timer_list watchdog_timer;
struct timer_list dma_err_timer;
struct timer_list phy_info_timer;
+ struct hrtimer hrtimer;
u32 wol;
u32 en_mng_pt;
@@ -183,10 +188,17 @@ struct igc_adapter {
u32 max_frame_size;
u32 min_frame_size;
+ int tc_setup_type;
ktime_t base_time;
ktime_t cycle_time;
- bool qbv_enable;
+ bool taprio_offload_enable;
u32 qbv_config_change_errors;
+ bool qbv_transition;
+ unsigned int qbv_count;
+ /* Access to oper_gate_closed, admin_gate_closed and qbv_transition
+ * are protected by the qbv_tx_lock.
+ */
+ spinlock_t qbv_tx_lock;
/* OS defined structs */
struct pci_dev *pdev;
@@ -228,7 +240,10 @@ struct igc_adapter {
struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_caps;
- struct work_struct ptp_tx_work;
+ /* Access to ptp_tx_skb and ptp_tx_start are protected by the
+ * ptp_tx_lock.
+ */
+ spinlock_t ptp_tx_lock;
struct sk_buff *ptp_tx_skb;
struct hwtstamp_config tstamp_config;
unsigned long ptp_tx_start;
@@ -311,6 +326,33 @@ extern char igc_driver_name[];
#define IGC_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
#define IGC_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
+/* RX-desc Write-Back format RSS Type's */
+enum igc_rss_type_num {
+ IGC_RSS_TYPE_NO_HASH = 0,
+ IGC_RSS_TYPE_HASH_TCP_IPV4 = 1,
+ IGC_RSS_TYPE_HASH_IPV4 = 2,
+ IGC_RSS_TYPE_HASH_TCP_IPV6 = 3,
+ IGC_RSS_TYPE_HASH_IPV6_EX = 4,
+ IGC_RSS_TYPE_HASH_IPV6 = 5,
+ IGC_RSS_TYPE_HASH_TCP_IPV6_EX = 6,
+ IGC_RSS_TYPE_HASH_UDP_IPV4 = 7,
+ IGC_RSS_TYPE_HASH_UDP_IPV6 = 8,
+ IGC_RSS_TYPE_HASH_UDP_IPV6_EX = 9,
+ IGC_RSS_TYPE_MAX = 10,
+};
+#define IGC_RSS_TYPE_MAX_TABLE 16
+#define IGC_RSS_TYPE_MASK GENMASK(3,0) /* 4-bits (3:0) = mask 0x0F */
+
+/* igc_rss_type - Rx descriptor RSS type field */
+static inline u32 igc_rss_type(const union igc_adv_rx_desc *rx_desc)
+{
+ /* RSS Type 4-bits (3:0) number: 0-9 (above 9 is reserved)
+ * Accessing the same bits via u16 (wb.lower.lo_dword.hs_rss.pkt_info)
+ * is slightly slower than via u32 (wb.lower.lo_dword.data)
+ */
+ return le32_get_bits(rx_desc->wb.lower.lo_dword.data, IGC_RSS_TYPE_MASK);
+}
+
/* Interrupt defines */
#define IGC_START_ITR 648 /* ~6000 ints/sec */
#define IGC_4K_ITR 980
@@ -401,7 +443,6 @@ enum igc_state_t {
__IGC_TESTING,
__IGC_RESETTING,
__IGC_DOWN,
- __IGC_PTP_TX_IN_PROGRESS,
};
enum igc_tx_flags {
@@ -471,6 +512,13 @@ struct igc_rx_buffer {
};
};
+/* context wrapper around xdp_buff to provide access to descriptor metadata */
+struct igc_xdp_buff {
+ struct xdp_buff xdp;
+ union igc_adv_rx_desc *rx_desc;
+ ktime_t rx_ts; /* data indication bit IGC_RXDADV_STAT_TSIP */
+};
+
struct igc_q_vector {
struct igc_adapter *adapter; /* backlink */
void __iomem *itr_register;
@@ -578,6 +626,7 @@ enum igc_ring_flags_t {
IGC_RING_FLAG_TX_CTX_IDX,
IGC_RING_FLAG_TX_DETECT_HANG,
IGC_RING_FLAG_AF_XDP_ZC,
+ IGC_RING_FLAG_TX_HWTSTAMP,
};
#define ring_uses_large_buffer(ring) \
@@ -634,6 +683,7 @@ int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);
int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
void igc_ptp_tx_hang(struct igc_adapter *adapter);
void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts);
+void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter);
#define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring))
diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index 44a507029946..2f780cc90883 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -546,7 +546,7 @@
#define IGC_PTM_CTRL_START_NOW BIT(29) /* Start PTM Now */
#define IGC_PTM_CTRL_EN BIT(30) /* Enable PTM */
#define IGC_PTM_CTRL_TRIG BIT(31) /* PTM Cycle trigger */
-#define IGC_PTM_CTRL_SHRT_CYC(usec) (((usec) & 0x2f) << 2)
+#define IGC_PTM_CTRL_SHRT_CYC(usec) (((usec) & 0x3f) << 2)
#define IGC_PTM_CTRL_PTM_TO(usec) (((usec) & 0xff) << 8)
#define IGC_PTM_SHORT_CYC_DEFAULT 10 /* Default Short/interrupted cycle interval */
diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index 0e2cb00622d1..93bce729be76 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1708,6 +1708,8 @@ static int igc_ethtool_get_link_ksettings(struct net_device *netdev,
/* twisted pair */
cmd->base.port = PORT_TP;
cmd->base.phy_address = hw->phy.addr;
+ ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
/* advertising link modes */
if (hw->phy.autoneg_advertised & ADVERTISE_10_HALF)
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index fa764190f270..6f557e843e49 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -316,6 +316,33 @@ static void igc_clean_all_tx_rings(struct igc_adapter *adapter)
igc_clean_tx_ring(adapter->tx_ring[i]);
}
+static void igc_disable_tx_ring_hw(struct igc_ring *ring)
+{
+ struct igc_hw *hw = &ring->q_vector->adapter->hw;
+ u8 idx = ring->reg_idx;
+ u32 txdctl;
+
+ txdctl = rd32(IGC_TXDCTL(idx));
+ txdctl &= ~IGC_TXDCTL_QUEUE_ENABLE;
+ txdctl |= IGC_TXDCTL_SWFLUSH;
+ wr32(IGC_TXDCTL(idx), txdctl);
+}
+
+/**
+ * igc_disable_all_tx_rings_hw - Disable all transmit queue operation
+ * @adapter: board private structure
+ */
+static void igc_disable_all_tx_rings_hw(struct igc_adapter *adapter)
+{
+ int i;
+
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ struct igc_ring *tx_ring = adapter->tx_ring[i];
+
+ igc_disable_tx_ring_hw(tx_ring);
+ }
+}
+
/**
* igc_setup_tx_resources - allocate Tx resources (Descriptors)
* @tx_ring: tx descriptor ring (for a specific queue) to setup
@@ -711,7 +738,6 @@ static void igc_configure_tx_ring(struct igc_adapter *adapter,
/* disable the queue */
wr32(IGC_TXDCTL(reg_idx), 0);
wrfl();
- mdelay(10);
wr32(IGC_TDLEN(reg_idx),
ring->count * sizeof(union igc_adv_tx_desc));
@@ -1017,7 +1043,7 @@ static __le32 igc_tx_launchtime(struct igc_ring *ring, ktime_t txtime,
ktime_t base_time = adapter->base_time;
ktime_t now = ktime_get_clocktai();
ktime_t baset_est, end_of_cycle;
- u32 launchtime;
+ s32 launchtime;
s64 n;
n = div64_s64(ktime_sub_ns(now, base_time), cycle_time);
@@ -1030,7 +1056,7 @@ static __le32 igc_tx_launchtime(struct igc_ring *ring, ktime_t txtime,
*first_flag = true;
ring->last_ff_cycle = baset_est;
- if (ktime_compare(txtime, ring->last_tx_cycle) > 0)
+ if (ktime_compare(end_of_cycle, ring->last_tx_cycle) > 0)
*insert_empty = true;
}
}
@@ -1573,26 +1599,24 @@ done:
first->bytecount = skb->len;
first->gso_segs = 1;
- if (tx_ring->max_sdu > 0) {
- u32 max_sdu = 0;
-
- max_sdu = tx_ring->max_sdu +
- (skb_vlan_tagged(first->skb) ? VLAN_HLEN : 0);
+ if (adapter->qbv_transition || tx_ring->oper_gate_closed)
+ goto out_drop;
- if (first->bytecount > max_sdu) {
- adapter->stats.txdrop++;
- goto out_drop;
- }
+ if (tx_ring->max_sdu > 0 && first->bytecount > tx_ring->max_sdu) {
+ adapter->stats.txdrop++;
+ goto out_drop;
}
- if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
+ if (unlikely(test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags) &&
+ skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
/* FIXME: add support for retrieving timestamps from
* the other timer registers before skipping the
* timestamping request.
*/
- if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON &&
- !test_and_set_bit_lock(__IGC_PTP_TX_IN_PROGRESS,
- &adapter->state)) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
+ if (!adapter->ptp_tx_skb) {
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
tx_flags |= IGC_TX_FLAGS_TSTAMP;
@@ -1601,6 +1625,8 @@ done:
} else {
adapter->tx_hwtstamp_skipped++;
}
+
+ spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
}
if (skb_vlan_tag_present(skb)) {
@@ -1697,14 +1723,36 @@ static void igc_rx_checksum(struct igc_ring *ring,
le32_to_cpu(rx_desc->wb.upper.status_error));
}
+/* Mapping HW RSS Type to enum pkt_hash_types */
+static const enum pkt_hash_types igc_rss_type_table[IGC_RSS_TYPE_MAX_TABLE] = {
+ [IGC_RSS_TYPE_NO_HASH] = PKT_HASH_TYPE_L2,
+ [IGC_RSS_TYPE_HASH_TCP_IPV4] = PKT_HASH_TYPE_L4,
+ [IGC_RSS_TYPE_HASH_IPV4] = PKT_HASH_TYPE_L3,
+ [IGC_RSS_TYPE_HASH_TCP_IPV6] = PKT_HASH_TYPE_L4,
+ [IGC_RSS_TYPE_HASH_IPV6_EX] = PKT_HASH_TYPE_L3,
+ [IGC_RSS_TYPE_HASH_IPV6] = PKT_HASH_TYPE_L3,
+ [IGC_RSS_TYPE_HASH_TCP_IPV6_EX] = PKT_HASH_TYPE_L4,
+ [IGC_RSS_TYPE_HASH_UDP_IPV4] = PKT_HASH_TYPE_L4,
+ [IGC_RSS_TYPE_HASH_UDP_IPV6] = PKT_HASH_TYPE_L4,
+ [IGC_RSS_TYPE_HASH_UDP_IPV6_EX] = PKT_HASH_TYPE_L4,
+ [10] = PKT_HASH_TYPE_NONE, /* RSS Type above 9 "Reserved" by HW */
+ [11] = PKT_HASH_TYPE_NONE, /* keep array sized for SW bit-mask */
+ [12] = PKT_HASH_TYPE_NONE, /* to handle future HW revisons */
+ [13] = PKT_HASH_TYPE_NONE,
+ [14] = PKT_HASH_TYPE_NONE,
+ [15] = PKT_HASH_TYPE_NONE,
+};
+
static inline void igc_rx_hash(struct igc_ring *ring,
union igc_adv_rx_desc *rx_desc,
struct sk_buff *skb)
{
- if (ring->netdev->features & NETIF_F_RXHASH)
- skb_set_hash(skb,
- le32_to_cpu(rx_desc->wb.lower.hi_dword.rss),
- PKT_HASH_TYPE_L3);
+ if (ring->netdev->features & NETIF_F_RXHASH) {
+ u32 rss_hash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
+ u32 rss_type = igc_rss_type(rx_desc);
+
+ skb_set_hash(skb, rss_hash, igc_rss_type_table[rss_type]);
+ }
}
static void igc_rx_vlan(struct igc_ring *rx_ring,
@@ -2221,6 +2269,8 @@ static bool igc_alloc_rx_buffers_zc(struct igc_ring *ring, u16 count)
if (!count)
return ok;
+ XSK_CHECK_PRIV_TYPE(struct igc_xdp_buff);
+
desc = IGC_RX_DESC(ring, i);
bi = &ring->rx_buffer_info[i];
i -= ring->count;
@@ -2394,6 +2444,8 @@ static int igc_xdp_xmit_back(struct igc_adapter *adapter, struct xdp_buff *xdp)
nq = txring_txq(ring);
__netif_tx_lock(nq, cpu);
+ /* Avoid transmit queue timeout since we share it with the slow path */
+ txq_trans_cond_update(nq);
res = igc_xdp_init_tx_descriptor(ring, xdpf);
__netif_tx_unlock(nq);
return res;
@@ -2505,8 +2557,8 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
union igc_adv_rx_desc *rx_desc;
struct igc_rx_buffer *rx_buffer;
unsigned int size, truesize;
+ struct igc_xdp_buff ctx;
ktime_t timestamp = 0;
- struct xdp_buff xdp;
int pkt_offset = 0;
void *pktbuf;
@@ -2535,18 +2587,20 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
if (igc_test_staterr(rx_desc, IGC_RXDADV_STAT_TSIP)) {
timestamp = igc_ptp_rx_pktstamp(q_vector->adapter,
pktbuf);
+ ctx.rx_ts = timestamp;
pkt_offset = IGC_TS_HDR_LEN;
size -= IGC_TS_HDR_LEN;
}
if (!skb) {
- xdp_init_buff(&xdp, truesize, &rx_ring->xdp_rxq);
- xdp_prepare_buff(&xdp, pktbuf - igc_rx_offset(rx_ring),
+ xdp_init_buff(&ctx.xdp, truesize, &rx_ring->xdp_rxq);
+ xdp_prepare_buff(&ctx.xdp, pktbuf - igc_rx_offset(rx_ring),
igc_rx_offset(rx_ring) + pkt_offset,
size, true);
- xdp_buff_clear_frags_flag(&xdp);
+ xdp_buff_clear_frags_flag(&ctx.xdp);
+ ctx.rx_desc = rx_desc;
- skb = igc_xdp_run_prog(adapter, &xdp);
+ skb = igc_xdp_run_prog(adapter, &ctx.xdp);
}
if (IS_ERR(skb)) {
@@ -2568,9 +2622,9 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
} else if (skb)
igc_add_rx_frag(rx_ring, rx_buffer, skb, size);
else if (ring_uses_build_skb(rx_ring))
- skb = igc_build_skb(rx_ring, rx_buffer, &xdp);
+ skb = igc_build_skb(rx_ring, rx_buffer, &ctx.xdp);
else
- skb = igc_construct_skb(rx_ring, rx_buffer, &xdp,
+ skb = igc_construct_skb(rx_ring, rx_buffer, &ctx.xdp,
timestamp);
/* exit if we failed to retrieve a buffer */
@@ -2671,6 +2725,15 @@ static void igc_dispatch_skb_zc(struct igc_q_vector *q_vector,
napi_gro_receive(&q_vector->napi, skb);
}
+static struct igc_xdp_buff *xsk_buff_to_igc_ctx(struct xdp_buff *xdp)
+{
+ /* xdp_buff pointer used by ZC code path is alloc as xdp_buff_xsk. The
+ * igc_xdp_buff shares its layout with xdp_buff_xsk and private
+ * igc_xdp_buff fields fall into xdp_buff_xsk->cb
+ */
+ return (struct igc_xdp_buff *)xdp;
+}
+
static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget)
{
struct igc_adapter *adapter = q_vector->adapter;
@@ -2689,6 +2752,7 @@ static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget)
while (likely(total_packets < budget)) {
union igc_adv_rx_desc *desc;
struct igc_rx_buffer *bi;
+ struct igc_xdp_buff *ctx;
ktime_t timestamp = 0;
unsigned int size;
int res;
@@ -2706,9 +2770,13 @@ static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget)
bi = &ring->rx_buffer_info[ntc];
+ ctx = xsk_buff_to_igc_ctx(bi->xdp);
+ ctx->rx_desc = desc;
+
if (igc_test_staterr(desc, IGC_RXDADV_STAT_TSIP)) {
timestamp = igc_ptp_rx_pktstamp(q_vector->adapter,
bi->xdp->data);
+ ctx->rx_ts = timestamp;
bi->xdp->data += IGC_TS_HDR_LEN;
@@ -2787,15 +2855,18 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
struct netdev_queue *nq = txring_txq(ring);
union igc_adv_tx_desc *tx_desc = NULL;
int cpu = smp_processor_id();
- u16 ntu = ring->next_to_use;
struct xdp_desc xdp_desc;
- u16 budget;
+ u16 budget, ntu;
if (!netif_carrier_ok(ring->netdev))
return;
__netif_tx_lock(nq, cpu);
+ /* Avoid transmit queue timeout since we share it with the slow path */
+ txq_trans_cond_update(nq);
+
+ ntu = ring->next_to_use;
budget = igc_desc_unused(ring);
while (xsk_tx_peek_desc(pool, &xdp_desc) && budget--) {
@@ -2963,8 +3034,8 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
time_after(jiffies, tx_buffer->time_stamp +
(adapter->tx_timeout_factor * HZ)) &&
!(rd32(IGC_STATUS) & IGC_STATUS_TXOFF) &&
- (rd32(IGC_TDH(tx_ring->reg_idx)) !=
- readl(tx_ring->tail))) {
+ (rd32(IGC_TDH(tx_ring->reg_idx)) != readl(tx_ring->tail)) &&
+ !tx_ring->oper_gate_closed) {
/* detected Tx unit hang */
netdev_err(tx_ring->netdev,
"Detected Tx Unit Hang\n"
@@ -4730,6 +4801,7 @@ static int igc_sw_init(struct igc_adapter *adapter)
adapter->nfc_rule_count = 0;
spin_lock_init(&adapter->stats64_lock);
+ spin_lock_init(&adapter->qbv_tx_lock);
/* Assume MSI-X interrupts, will be checked during IRQ allocation */
adapter->flags |= IGC_FLAG_HAS_MSIX;
@@ -5014,6 +5086,7 @@ void igc_down(struct igc_adapter *adapter)
/* clear VLAN promisc flag so VFTA will be updated if necessary */
adapter->flags &= ~IGC_FLAG_VLAN_PROMISC;
+ igc_disable_all_tx_rings_hw(adapter);
igc_clean_all_tx_rings(adapter);
igc_clean_all_rx_rings(adapter);
}
@@ -5219,7 +5292,7 @@ static void igc_tsync_interrupt(struct igc_adapter *adapter)
if (tsicr & IGC_TSICR_TXTS) {
/* retrieve hardware timestamp */
- schedule_work(&adapter->ptp_tx_work);
+ igc_ptp_tx_tstamp_event(adapter);
ack |= IGC_TSICR_TXTS;
}
@@ -6047,13 +6120,16 @@ static int igc_tsn_enable_launchtime(struct igc_adapter *adapter,
return igc_tsn_offload_apply(adapter);
}
-static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
+static int igc_qbv_clear_schedule(struct igc_adapter *adapter)
{
+ unsigned long flags;
int i;
adapter->base_time = 0;
adapter->cycle_time = NSEC_PER_SEC;
+ adapter->taprio_offload_enable = false;
adapter->qbv_config_change_errors = 0;
+ adapter->qbv_count = 0;
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igc_ring *ring = adapter->tx_ring[i];
@@ -6063,6 +6139,26 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
ring->max_sdu = 0;
}
+ spin_lock_irqsave(&adapter->qbv_tx_lock, flags);
+
+ adapter->qbv_transition = false;
+
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ struct igc_ring *ring = adapter->tx_ring[i];
+
+ ring->oper_gate_closed = false;
+ ring->admin_gate_closed = false;
+ }
+
+ spin_unlock_irqrestore(&adapter->qbv_tx_lock, flags);
+
+ return 0;
+}
+
+static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
+{
+ igc_qbv_clear_schedule(adapter);
+
return 0;
}
@@ -6072,18 +6168,21 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
bool queue_configured[IGC_MAX_TX_QUEUES] = { };
struct igc_hw *hw = &adapter->hw;
u32 start_time = 0, end_time = 0;
+ struct timespec64 now;
+ unsigned long flags;
size_t n;
int i;
- adapter->qbv_enable = qopt->enable;
-
- if (!qopt->enable)
+ if (qopt->cmd == TAPRIO_CMD_DESTROY)
return igc_tsn_clear_schedule(adapter);
+ if (qopt->cmd != TAPRIO_CMD_REPLACE)
+ return -EOPNOTSUPP;
+
if (qopt->base_time < 0)
return -ERANGE;
- if (igc_is_device_id_i225(hw) && adapter->base_time)
+ if (igc_is_device_id_i225(hw) && adapter->taprio_offload_enable)
return -EALREADY;
if (!validate_schedule(adapter, qopt))
@@ -6091,6 +6190,9 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
adapter->cycle_time = qopt->cycle_time;
adapter->base_time = qopt->base_time;
+ adapter->taprio_offload_enable = true;
+
+ igc_ptp_read(adapter, &now);
for (n = 0; n < qopt->num_entries; n++) {
struct tc_taprio_sched_entry *e = &qopt->entries[n];
@@ -6126,30 +6228,49 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
ring->start_time = start_time;
ring->end_time = end_time;
- queue_configured[i] = true;
+ if (ring->start_time >= adapter->cycle_time)
+ queue_configured[i] = false;
+ else
+ queue_configured[i] = true;
}
start_time += e->interval;
}
+ spin_lock_irqsave(&adapter->qbv_tx_lock, flags);
+
/* Check whether a queue gets configured.
* If not, set the start and end time to be end time.
*/
for (i = 0; i < adapter->num_tx_queues; i++) {
+ struct igc_ring *ring = adapter->tx_ring[i];
+
+ if (!is_base_time_past(qopt->base_time, &now)) {
+ ring->admin_gate_closed = false;
+ } else {
+ ring->oper_gate_closed = false;
+ ring->admin_gate_closed = false;
+ }
+
if (!queue_configured[i]) {
- struct igc_ring *ring = adapter->tx_ring[i];
+ if (!is_base_time_past(qopt->base_time, &now))
+ ring->admin_gate_closed = true;
+ else
+ ring->oper_gate_closed = true;
ring->start_time = end_time;
ring->end_time = end_time;
}
}
+ spin_unlock_irqrestore(&adapter->qbv_tx_lock, flags);
+
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igc_ring *ring = adapter->tx_ring[i];
struct net_device *dev = adapter->netdev;
if (qopt->max_sdu[i])
- ring->max_sdu = qopt->max_sdu[i] + dev->hard_header_len;
+ ring->max_sdu = qopt->max_sdu[i] + dev->hard_header_len - ETH_TLEN;
else
ring->max_sdu = 0;
}
@@ -6269,6 +6390,8 @@ static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type,
{
struct igc_adapter *adapter = netdev_priv(dev);
+ adapter->tc_setup_type = type;
+
switch (type) {
case TC_QUERY_CAPS:
return igc_tc_query_caps(adapter, type_data);
@@ -6321,6 +6444,9 @@ static int igc_xdp_xmit(struct net_device *dev, int num_frames,
__netif_tx_lock(nq, cpu);
+ /* Avoid transmit queue timeout since we share it with the slow path */
+ txq_trans_cond_update(nq);
+
drops = 0;
for (i = 0; i < num_frames; i++) {
int err;
@@ -6461,6 +6587,85 @@ u32 igc_rd32(struct igc_hw *hw, u32 reg)
return value;
}
+/* Mapping HW RSS Type to enum xdp_rss_hash_type */
+static enum xdp_rss_hash_type igc_xdp_rss_type[IGC_RSS_TYPE_MAX_TABLE] = {
+ [IGC_RSS_TYPE_NO_HASH] = XDP_RSS_TYPE_L2,
+ [IGC_RSS_TYPE_HASH_TCP_IPV4] = XDP_RSS_TYPE_L4_IPV4_TCP,
+ [IGC_RSS_TYPE_HASH_IPV4] = XDP_RSS_TYPE_L3_IPV4,
+ [IGC_RSS_TYPE_HASH_TCP_IPV6] = XDP_RSS_TYPE_L4_IPV6_TCP,
+ [IGC_RSS_TYPE_HASH_IPV6_EX] = XDP_RSS_TYPE_L3_IPV6_EX,
+ [IGC_RSS_TYPE_HASH_IPV6] = XDP_RSS_TYPE_L3_IPV6,
+ [IGC_RSS_TYPE_HASH_TCP_IPV6_EX] = XDP_RSS_TYPE_L4_IPV6_TCP_EX,
+ [IGC_RSS_TYPE_HASH_UDP_IPV4] = XDP_RSS_TYPE_L4_IPV4_UDP,
+ [IGC_RSS_TYPE_HASH_UDP_IPV6] = XDP_RSS_TYPE_L4_IPV6_UDP,
+ [IGC_RSS_TYPE_HASH_UDP_IPV6_EX] = XDP_RSS_TYPE_L4_IPV6_UDP_EX,
+ [10] = XDP_RSS_TYPE_NONE, /* RSS Type above 9 "Reserved" by HW */
+ [11] = XDP_RSS_TYPE_NONE, /* keep array sized for SW bit-mask */
+ [12] = XDP_RSS_TYPE_NONE, /* to handle future HW revisons */
+ [13] = XDP_RSS_TYPE_NONE,
+ [14] = XDP_RSS_TYPE_NONE,
+ [15] = XDP_RSS_TYPE_NONE,
+};
+
+static int igc_xdp_rx_hash(const struct xdp_md *_ctx, u32 *hash,
+ enum xdp_rss_hash_type *rss_type)
+{
+ const struct igc_xdp_buff *ctx = (void *)_ctx;
+
+ if (!(ctx->xdp.rxq->dev->features & NETIF_F_RXHASH))
+ return -ENODATA;
+
+ *hash = le32_to_cpu(ctx->rx_desc->wb.lower.hi_dword.rss);
+ *rss_type = igc_xdp_rss_type[igc_rss_type(ctx->rx_desc)];
+
+ return 0;
+}
+
+static int igc_xdp_rx_timestamp(const struct xdp_md *_ctx, u64 *timestamp)
+{
+ const struct igc_xdp_buff *ctx = (void *)_ctx;
+
+ if (igc_test_staterr(ctx->rx_desc, IGC_RXDADV_STAT_TSIP)) {
+ *timestamp = ctx->rx_ts;
+
+ return 0;
+ }
+
+ return -ENODATA;
+}
+
+static const struct xdp_metadata_ops igc_xdp_metadata_ops = {
+ .xmo_rx_hash = igc_xdp_rx_hash,
+ .xmo_rx_timestamp = igc_xdp_rx_timestamp,
+};
+
+static enum hrtimer_restart igc_qbv_scheduling_timer(struct hrtimer *timer)
+{
+ struct igc_adapter *adapter = container_of(timer, struct igc_adapter,
+ hrtimer);
+ unsigned long flags;
+ unsigned int i;
+
+ spin_lock_irqsave(&adapter->qbv_tx_lock, flags);
+
+ adapter->qbv_transition = true;
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ struct igc_ring *tx_ring = adapter->tx_ring[i];
+
+ if (tx_ring->admin_gate_closed) {
+ tx_ring->admin_gate_closed = false;
+ tx_ring->oper_gate_closed = true;
+ } else {
+ tx_ring->oper_gate_closed = false;
+ }
+ }
+ adapter->qbv_transition = false;
+
+ spin_unlock_irqrestore(&adapter->qbv_tx_lock, flags);
+
+ return HRTIMER_NORESTART;
+}
+
/**
* igc_probe - Device Initialization Routine
* @pdev: PCI device information struct
@@ -6534,6 +6739,7 @@ static int igc_probe(struct pci_dev *pdev,
hw->hw_addr = adapter->io_addr;
netdev->netdev_ops = &igc_netdev_ops;
+ netdev->xdp_metadata_ops = &igc_xdp_metadata_ops;
igc_ethtool_set_ops(netdev);
netdev->watchdog_timeo = 5 * HZ;
@@ -6561,6 +6767,7 @@ static int igc_probe(struct pci_dev *pdev,
netdev->features |= NETIF_F_TSO;
netdev->features |= NETIF_F_TSO6;
netdev->features |= NETIF_F_TSO_ECN;
+ netdev->features |= NETIF_F_RXHASH;
netdev->features |= NETIF_F_RXCSUM;
netdev->features |= NETIF_F_HW_CSUM;
netdev->features |= NETIF_F_SCTP_CRC;
@@ -6637,6 +6844,9 @@ static int igc_probe(struct pci_dev *pdev,
INIT_WORK(&adapter->reset_task, igc_reset_task);
INIT_WORK(&adapter->watchdog_task, igc_watchdog_task);
+ hrtimer_init(&adapter->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ adapter->hrtimer.function = &igc_qbv_scheduling_timer;
+
/* Initialize link properties that are user-changeable */
adapter->fc_autoneg = true;
hw->mac.autoneg = true;
@@ -6740,6 +6950,7 @@ static void igc_remove(struct pci_dev *pdev)
cancel_work_sync(&adapter->reset_task);
cancel_work_sync(&adapter->watchdog_task);
+ hrtimer_cancel(&adapter->hrtimer);
/* Release control of h/w to f/w. If f/w is AMT enabled, this
* would have already happened in close and is redundant.
@@ -7137,18 +7348,6 @@ void igc_enable_rx_ring(struct igc_ring *ring)
igc_alloc_rx_buffers(ring, igc_desc_unused(ring));
}
-static void igc_disable_tx_ring_hw(struct igc_ring *ring)
-{
- struct igc_hw *hw = &ring->q_vector->adapter->hw;
- u8 idx = ring->reg_idx;
- u32 txdctl;
-
- txdctl = rd32(IGC_TXDCTL(idx));
- txdctl &= ~IGC_TXDCTL_QUEUE_ENABLE;
- txdctl |= IGC_TXDCTL_SWFLUSH;
- wr32(IGC_TXDCTL(idx), txdctl);
-}
-
void igc_disable_tx_ring(struct igc_ring *ring)
{
igc_disable_tx_ring_hw(ring);
diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c
index 4e10ced736db..f0b979a70655 100644
--- a/drivers/net/ethernet/intel/igc/igc_ptp.c
+++ b/drivers/net/ethernet/intel/igc/igc_ptp.c
@@ -356,16 +356,35 @@ static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp,
tsim &= ~IGC_TSICR_TT0;
}
if (on) {
+ struct timespec64 safe_start;
int i = rq->perout.index;
igc_pin_perout(igc, i, pin, use_freq);
- igc->perout[i].start.tv_sec = rq->perout.start.sec;
+ igc_ptp_read(igc, &safe_start);
+
+ /* PPS output start time is triggered by Target time(TT)
+ * register. Programming any past time value into TT
+ * register will cause PPS to never start. Need to make
+ * sure we program the TT register a time ahead in
+ * future. There isn't a stringent need to fire PPS out
+ * right away. Adding +2 seconds should take care of
+ * corner cases. Let's say if the SYSTIML is close to
+ * wrap up and the timer keeps ticking as we program the
+ * register, adding +2seconds is safe bet.
+ */
+ safe_start.tv_sec += 2;
+
+ if (rq->perout.start.sec < safe_start.tv_sec)
+ igc->perout[i].start.tv_sec = safe_start.tv_sec;
+ else
+ igc->perout[i].start.tv_sec = rq->perout.start.sec;
igc->perout[i].start.tv_nsec = rq->perout.start.nsec;
igc->perout[i].period.tv_sec = ts.tv_sec;
igc->perout[i].period.tv_nsec = ts.tv_nsec;
- wr32(trgttimh, rq->perout.start.sec);
+ wr32(trgttimh, (u32)igc->perout[i].start.tv_sec);
/* For now, always select timer 0 as source. */
- wr32(trgttiml, rq->perout.start.nsec | IGC_TT_IO_TIMER_SEL_SYSTIM0);
+ wr32(trgttiml, (u32)(igc->perout[i].start.tv_nsec |
+ IGC_TT_IO_TIMER_SEL_SYSTIM0));
if (use_freq)
wr32(freqout, ns);
tsauxc |= tsauxc_mask;
@@ -536,9 +555,34 @@ static void igc_ptp_enable_rx_timestamp(struct igc_adapter *adapter)
wr32(IGC_TSYNCRXCTL, val);
}
+static void igc_ptp_clear_tx_tstamp(struct igc_adapter *adapter)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
+
+ dev_kfree_skb_any(adapter->ptp_tx_skb);
+ adapter->ptp_tx_skb = NULL;
+
+ spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
+}
+
static void igc_ptp_disable_tx_timestamp(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
+ int i;
+
+ /* Clear the flags first to avoid new packets to be enqueued
+ * for TX timestamping.
+ */
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ struct igc_ring *tx_ring = adapter->tx_ring[i];
+
+ clear_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags);
+ }
+
+ /* Now we can clean the pending TX timestamp requests. */
+ igc_ptp_clear_tx_tstamp(adapter);
wr32(IGC_TSYNCTXCTL, 0);
}
@@ -546,12 +590,23 @@ static void igc_ptp_disable_tx_timestamp(struct igc_adapter *adapter)
static void igc_ptp_enable_tx_timestamp(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
+ int i;
wr32(IGC_TSYNCTXCTL, IGC_TSYNCTXCTL_ENABLED | IGC_TSYNCTXCTL_TXSYNSIG);
/* Read TXSTMP registers to discard any timestamp previously stored. */
rd32(IGC_TXSTMPL);
rd32(IGC_TXSTMPH);
+
+ /* The hardware is ready to accept TX timestamp requests,
+ * notify the transmit path.
+ */
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ struct igc_ring *tx_ring = adapter->tx_ring[i];
+
+ set_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags);
+ }
+
}
/**
@@ -603,6 +658,7 @@ static int igc_ptp_set_timestamp_mode(struct igc_adapter *adapter,
return 0;
}
+/* Requires adapter->ptp_tx_lock held by caller. */
static void igc_ptp_tx_timeout(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
@@ -610,7 +666,6 @@ static void igc_ptp_tx_timeout(struct igc_adapter *adapter)
dev_kfree_skb_any(adapter->ptp_tx_skb);
adapter->ptp_tx_skb = NULL;
adapter->tx_hwtstamp_timeouts++;
- clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
/* Clear the tx valid bit in TSYNCTXCTL register to enable interrupt. */
rd32(IGC_TXSTMPH);
netdev_warn(adapter->netdev, "Tx timestamp timeout\n");
@@ -618,20 +673,20 @@ static void igc_ptp_tx_timeout(struct igc_adapter *adapter)
void igc_ptp_tx_hang(struct igc_adapter *adapter)
{
- bool timeout = time_is_before_jiffies(adapter->ptp_tx_start +
- IGC_PTP_TX_TIMEOUT);
+ unsigned long flags;
- if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state))
- return;
+ spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
- /* If we haven't received a timestamp within the timeout, it is
- * reasonable to assume that it will never occur, so we can unlock the
- * timestamp bit when this occurs.
- */
- if (timeout) {
- cancel_work_sync(&adapter->ptp_tx_work);
- igc_ptp_tx_timeout(adapter);
- }
+ if (!adapter->ptp_tx_skb)
+ goto unlock;
+
+ if (time_is_after_jiffies(adapter->ptp_tx_start + IGC_PTP_TX_TIMEOUT))
+ goto unlock;
+
+ igc_ptp_tx_timeout(adapter);
+
+unlock:
+ spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
}
/**
@@ -641,20 +696,57 @@ void igc_ptp_tx_hang(struct igc_adapter *adapter)
* If we were asked to do hardware stamping and such a time stamp is
* available, then it must have been for this skb here because we only
* allow only one such packet into the queue.
+ *
+ * Context: Expects adapter->ptp_tx_lock to be held by caller.
*/
static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
{
struct sk_buff *skb = adapter->ptp_tx_skb;
struct skb_shared_hwtstamps shhwtstamps;
struct igc_hw *hw = &adapter->hw;
+ u32 tsynctxctl;
int adjust = 0;
u64 regval;
if (WARN_ON_ONCE(!skb))
return;
- regval = rd32(IGC_TXSTMPL);
- regval |= (u64)rd32(IGC_TXSTMPH) << 32;
+ tsynctxctl = rd32(IGC_TSYNCTXCTL);
+ tsynctxctl &= IGC_TSYNCTXCTL_TXTT_0;
+ if (tsynctxctl) {
+ regval = rd32(IGC_TXSTMPL);
+ regval |= (u64)rd32(IGC_TXSTMPH) << 32;
+ } else {
+ /* There's a bug in the hardware that could cause
+ * missing interrupts for TX timestamping. The issue
+ * is that for new interrupts to be triggered, the
+ * IGC_TXSTMPH_0 register must be read.
+ *
+ * To avoid discarding a valid timestamp that just
+ * happened at the "wrong" time, we need to confirm
+ * that there was no timestamp captured, we do that by
+ * assuming that no two timestamps in sequence have
+ * the same nanosecond value.
+ *
+ * So, we read the "low" register, read the "high"
+ * register (to latch a new timestamp) and read the
+ * "low" register again, if "old" and "new" versions
+ * of the "low" register are different, a valid
+ * timestamp was captured, we can read the "high"
+ * register again.
+ */
+ u32 txstmpl_old, txstmpl_new;
+
+ txstmpl_old = rd32(IGC_TXSTMPL);
+ rd32(IGC_TXSTMPH);
+ txstmpl_new = rd32(IGC_TXSTMPL);
+
+ if (txstmpl_old == txstmpl_new)
+ return;
+
+ regval = txstmpl_new;
+ regval |= (u64)rd32(IGC_TXSTMPH) << 32;
+ }
if (igc_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval))
return;
@@ -676,13 +768,7 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
shhwtstamps.hwtstamp =
ktime_add_ns(shhwtstamps.hwtstamp, adjust);
- /* Clear the lock early before calling skb_tstamp_tx so that
- * applications are not woken up before the lock bit is clear. We use
- * a copy of the skb pointer to ensure other threads can't change it
- * while we're notifying the stack.
- */
adapter->ptp_tx_skb = NULL;
- clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
/* Notify the stack and free the skb after we've unlocked */
skb_tstamp_tx(skb, &shhwtstamps);
@@ -690,27 +776,25 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
}
/**
- * igc_ptp_tx_work
- * @work: pointer to work struct
+ * igc_ptp_tx_tstamp_event
+ * @adapter: board private structure
*
- * This work function polls the TSYNCTXCTL valid bit to determine when a
- * timestamp has been taken for the current stored skb.
+ * Called when a TX timestamp interrupt happens to retrieve the
+ * timestamp and send it up to the socket.
*/
-static void igc_ptp_tx_work(struct work_struct *work)
+void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter)
{
- struct igc_adapter *adapter = container_of(work, struct igc_adapter,
- ptp_tx_work);
- struct igc_hw *hw = &adapter->hw;
- u32 tsynctxctl;
+ unsigned long flags;
- if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state))
- return;
+ spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
- tsynctxctl = rd32(IGC_TSYNCTXCTL);
- if (WARN_ON_ONCE(!(tsynctxctl & IGC_TSYNCTXCTL_TXTT_0)))
- return;
+ if (!adapter->ptp_tx_skb)
+ goto unlock;
igc_ptp_tx_hwtstamp(adapter);
+
+unlock:
+ spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
}
/**
@@ -959,8 +1043,8 @@ void igc_ptp_init(struct igc_adapter *adapter)
return;
}
+ spin_lock_init(&adapter->ptp_tx_lock);
spin_lock_init(&adapter->tmreg_lock);
- INIT_WORK(&adapter->ptp_tx_work, igc_ptp_tx_work);
adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
@@ -1020,10 +1104,7 @@ void igc_ptp_suspend(struct igc_adapter *adapter)
if (!(adapter->ptp_flags & IGC_PTP_ENABLED))
return;
- cancel_work_sync(&adapter->ptp_tx_work);
- dev_kfree_skb_any(adapter->ptp_tx_skb);
- adapter->ptp_tx_skb = NULL;
- clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
+ igc_ptp_clear_tx_tstamp(adapter);
if (pci_device_is_present(adapter->pdev)) {
igc_ptp_time_save(adapter);
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index 94a2b0dfb54d..a9c08321aca9 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -37,7 +37,7 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
{
unsigned int new_flags = adapter->flags & ~IGC_FLAG_TSN_ANY_ENABLED;
- if (adapter->qbv_enable)
+ if (adapter->taprio_offload_enable)
new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
if (is_any_launchtime(adapter))
@@ -114,7 +114,6 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
static int igc_tsn_enable_offload(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
- bool tsn_mode_reconfig = false;
u32 tqavctrl, baset_l, baset_h;
u32 sec, nsec, cycle;
ktime_t base_time, systim;
@@ -133,8 +132,28 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
wr32(IGC_STQT(i), ring->start_time);
wr32(IGC_ENDQT(i), ring->end_time);
- txqctl |= IGC_TXQCTL_STRICT_CYCLE |
- IGC_TXQCTL_STRICT_END;
+ if (adapter->taprio_offload_enable) {
+ /* If taprio_offload_enable is set we are in "taprio"
+ * mode and we need to be strict about the
+ * cycles: only transmit a packet if it can be
+ * completed during that cycle.
+ *
+ * If taprio_offload_enable is NOT true when
+ * enabling TSN offload, the cycle should have
+ * no external effects, but is only used internally
+ * to adapt the base time register after a second
+ * has passed.
+ *
+ * Enabling strict mode in this case would
+ * unnecessarily prevent the transmission of
+ * certain packets (i.e. at the boundary of a
+ * second) and thus interfere with the launchtime
+ * feature that promises transmission at a
+ * certain point in time.
+ */
+ txqctl |= IGC_TXQCTL_STRICT_CYCLE |
+ IGC_TXQCTL_STRICT_END;
+ }
if (ring->launchtime_enable)
txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;
@@ -228,11 +247,10 @@ skip_cbs:
tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS;
- if (tqavctrl & IGC_TQAVCTRL_TRANSMIT_MODE_TSN)
- tsn_mode_reconfig = true;
-
tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
+ adapter->qbv_count++;
+
cycle = adapter->cycle_time;
base_time = adapter->base_time;
@@ -249,17 +267,29 @@ skip_cbs:
* Gate Control List (GCL) is running.
*/
if ((rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) &&
- tsn_mode_reconfig)
+ (adapter->tc_setup_type == TC_SETUP_QDISC_TAPRIO) &&
+ (adapter->qbv_count > 1))
adapter->qbv_config_change_errors++;
} else {
- /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit
- * has to be configured before the cycle time and base time.
- * Tx won't hang if there is a GCL is already running,
- * so in this case we don't need to set FutScdDis.
- */
- if (igc_is_device_id_i226(hw) &&
- !(rd32(IGC_BASET_H) || rd32(IGC_BASET_L)))
- tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS;
+ if (igc_is_device_id_i226(hw)) {
+ ktime_t adjust_time, expires_time;
+
+ /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit
+ * has to be configured before the cycle time and base time.
+ * Tx won't hang if a GCL is already running,
+ * so in this case we don't need to set FutScdDis.
+ */
+ if (!(rd32(IGC_BASET_H) || rd32(IGC_BASET_L)))
+ tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS;
+
+ nsec = rd32(IGC_SYSTIML);
+ sec = rd32(IGC_SYSTIMH);
+ systim = ktime_set(sec, nsec);
+
+ adjust_time = adapter->base_time;
+ expires_time = ktime_sub_ns(adjust_time, systim);
+ hrtimer_start(&adapter->hrtimer, expires_time, HRTIMER_MODE_REL);
+ }
}
wr32(IGC_TQAVCTRL, tqavctrl);
@@ -305,7 +335,11 @@ int igc_tsn_offload_apply(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
- if (netif_running(adapter->netdev) && igc_is_device_id_i225(hw)) {
+ /* Per I225/6 HW Design Section 7.5.2.1, transmit mode
+ * cannot be changed dynamically. Require reset the adapter.
+ */
+ if (netif_running(adapter->netdev) &&
+ (igc_is_device_id_i225(hw) || !adapter->qbv_count)) {
schedule_work(&adapter->reset_task);
return 0;
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 1726297f2e0d..8eb9839a3ca6 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -8479,7 +8479,7 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
struct ixgbe_adapter *adapter = q_vector->adapter;
if (unlikely(skb_tail_pointer(skb) < hdr.network +
- VXLAN_HEADROOM))
+ vxlan_headroom(0)))
return;
/* verify the port is recognized as VXLAN */
diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index 2b9335cb4bb3..8537578e1cf1 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -1302,11 +1302,10 @@ static int korina_probe(struct platform_device *pdev)
else if (of_get_ethdev_address(pdev->dev.of_node, dev) < 0)
eth_hw_addr_random(dev);
- clk = devm_clk_get_optional(&pdev->dev, "mdioclk");
+ clk = devm_clk_get_optional_enabled(&pdev->dev, "mdioclk");
if (IS_ERR(clk))
return PTR_ERR(clk);
if (clk) {
- clk_prepare_enable(clk);
lp->mii_clock_freq = clk_get_rate(clk);
} else {
lp->mii_clock_freq = 200000000; /* max possible input clk */
diff --git a/drivers/net/ethernet/litex/litex_liteeth.c b/drivers/net/ethernet/litex/litex_liteeth.c
index 35f24e0f0934..ffa96059079c 100644
--- a/drivers/net/ethernet/litex/litex_liteeth.c
+++ b/drivers/net/ethernet/litex/litex_liteeth.c
@@ -78,8 +78,7 @@ static int liteeth_rx(struct net_device *netdev)
memcpy_fromio(data, priv->rx_base + rx_slot * priv->slot_size, len);
skb->protocol = eth_type_trans(skb, netdev);
- netdev->stats.rx_packets++;
- netdev->stats.rx_bytes += len;
+ dev_sw_netstats_rx_add(netdev, len);
return netif_rx(skb);
@@ -185,8 +184,7 @@ static netdev_tx_t liteeth_start_xmit(struct sk_buff *skb,
litex_write16(priv->base + LITEETH_READER_LENGTH, skb->len);
litex_write8(priv->base + LITEETH_READER_START, 1);
- netdev->stats.tx_bytes += skb->len;
- netdev->stats.tx_packets++;
+ dev_sw_netstats_tx_add(netdev, 1, skb->len);
priv->tx_slot = (priv->tx_slot + 1) % priv->num_tx_slots;
dev_kfree_skb_any(skb);
@@ -194,9 +192,17 @@ static netdev_tx_t liteeth_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
+static void
+liteeth_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
+{
+ netdev_stats_to_stats64(stats, &netdev->stats);
+ dev_fetch_sw_netstats(stats, netdev->tstats);
+}
+
static const struct net_device_ops liteeth_netdev_ops = {
.ndo_open = liteeth_open,
.ndo_stop = liteeth_stop,
+ .ndo_get_stats64 = liteeth_get_stats64,
.ndo_start_xmit = liteeth_start_xmit,
};
@@ -242,6 +248,11 @@ static int liteeth_probe(struct platform_device *pdev)
priv->netdev = netdev;
priv->dev = &pdev->dev;
+ netdev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev,
+ struct pcpu_sw_netstats);
+ if (!netdev->tstats)
+ return -ENOMEM;
+
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 2cad76d0a50e..acf4f6ba73a6 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -344,6 +344,15 @@
#define MVNETA_MAX_SKB_DESCS (MVNETA_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS)
+/* The size of a TSO header page */
+#define MVNETA_TSO_PAGE_SIZE (2 * PAGE_SIZE)
+
+/* Number of TSO headers per page. This should be a power of 2 */
+#define MVNETA_TSO_PER_PAGE (MVNETA_TSO_PAGE_SIZE / TSO_HEADER_SIZE)
+
+/* Maximum number of TSO header pages */
+#define MVNETA_MAX_TSO_PAGES (MVNETA_MAX_TXD / MVNETA_TSO_PER_PAGE)
+
/* descriptor aligned size */
#define MVNETA_DESC_ALIGNED_SIZE 32
@@ -364,10 +373,6 @@
MVNETA_SKB_HEADROOM))
#define MVNETA_MAX_RX_BUF_SIZE (PAGE_SIZE - MVNETA_SKB_PAD)
-#define IS_TSO_HEADER(txq, addr) \
- ((addr >= txq->tso_hdrs_phys) && \
- (addr < txq->tso_hdrs_phys + txq->size * TSO_HEADER_SIZE))
-
#define MVNETA_RX_GET_BM_POOL_ID(rxd) \
(((rxd)->status & MVNETA_RXD_BM_POOL_MASK) >> MVNETA_RXD_BM_POOL_SHIFT)
@@ -638,6 +643,7 @@ struct mvneta_rx_desc {
#endif
enum mvneta_tx_buf_type {
+ MVNETA_TYPE_TSO,
MVNETA_TYPE_SKB,
MVNETA_TYPE_XDP_TX,
MVNETA_TYPE_XDP_NDO,
@@ -690,10 +696,10 @@ struct mvneta_tx_queue {
int next_desc_to_proc;
/* DMA buffers for TSO headers */
- char *tso_hdrs;
+ char *tso_hdrs[MVNETA_MAX_TSO_PAGES];
/* DMA address of TSO headers */
- dma_addr_t tso_hdrs_phys;
+ dma_addr_t tso_hdrs_phys[MVNETA_MAX_TSO_PAGES];
/* Affinity mask for CPUs*/
cpumask_t affinity_mask;
@@ -1505,7 +1511,7 @@ static void mvneta_defaults_set(struct mvneta_port *pp)
*/
if (txq_number == 1)
txq_map = (cpu == pp->rxq_def) ?
- MVNETA_CPU_TXQ_ACCESS(1) : 0;
+ MVNETA_CPU_TXQ_ACCESS(0) : 0;
} else {
txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK;
@@ -1878,12 +1884,13 @@ static void mvneta_txq_bufs_free(struct mvneta_port *pp,
mvneta_txq_inc_get(txq);
- if (!IS_TSO_HEADER(txq, tx_desc->buf_phys_addr) &&
- buf->type != MVNETA_TYPE_XDP_TX)
+ if (buf->type == MVNETA_TYPE_XDP_NDO ||
+ buf->type == MVNETA_TYPE_SKB)
dma_unmap_single(pp->dev->dev.parent,
tx_desc->buf_phys_addr,
tx_desc->data_size, DMA_TO_DEVICE);
- if (buf->type == MVNETA_TYPE_SKB && buf->skb) {
+ if ((buf->type == MVNETA_TYPE_TSO ||
+ buf->type == MVNETA_TYPE_SKB) && buf->skb) {
bytes_compl += buf->skb->len;
pkts_compl++;
dev_kfree_skb_any(buf->skb);
@@ -2369,9 +2376,8 @@ mvneta_swbm_add_rx_fragment(struct mvneta_port *pp,
if (data_len > 0 && sinfo->nr_frags < MAX_SKB_FRAGS) {
skb_frag_t *frag = &sinfo->frags[sinfo->nr_frags++];
- skb_frag_off_set(frag, pp->rx_offset_correction);
- skb_frag_size_set(frag, data_len);
- __skb_frag_set_page(frag, page);
+ skb_frag_fill_page_desc(frag, page,
+ pp->rx_offset_correction, data_len);
if (!xdp_buff_has_frags(xdp)) {
sinfo->xdp_frags_size = *size;
@@ -2661,20 +2667,72 @@ err_drop_frame:
return rx_done;
}
-static inline void
-mvneta_tso_put_hdr(struct sk_buff *skb, struct mvneta_tx_queue *txq)
+static void mvneta_free_tso_hdrs(struct mvneta_port *pp,
+ struct mvneta_tx_queue *txq)
+{
+ struct device *dev = pp->dev->dev.parent;
+ int i;
+
+ for (i = 0; i < MVNETA_MAX_TSO_PAGES; i++) {
+ if (txq->tso_hdrs[i]) {
+ dma_free_coherent(dev, MVNETA_TSO_PAGE_SIZE,
+ txq->tso_hdrs[i],
+ txq->tso_hdrs_phys[i]);
+ txq->tso_hdrs[i] = NULL;
+ }
+ }
+}
+
+static int mvneta_alloc_tso_hdrs(struct mvneta_port *pp,
+ struct mvneta_tx_queue *txq)
+{
+ struct device *dev = pp->dev->dev.parent;
+ int i, num;
+
+ num = DIV_ROUND_UP(txq->size, MVNETA_TSO_PER_PAGE);
+ for (i = 0; i < num; i++) {
+ txq->tso_hdrs[i] = dma_alloc_coherent(dev, MVNETA_TSO_PAGE_SIZE,
+ &txq->tso_hdrs_phys[i],
+ GFP_KERNEL);
+ if (!txq->tso_hdrs[i]) {
+ mvneta_free_tso_hdrs(pp, txq);
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+static char *mvneta_get_tso_hdr(struct mvneta_tx_queue *txq, dma_addr_t *dma)
+{
+ int index, offset;
+
+ index = txq->txq_put_index / MVNETA_TSO_PER_PAGE;
+ offset = (txq->txq_put_index % MVNETA_TSO_PER_PAGE) * TSO_HEADER_SIZE;
+
+ *dma = txq->tso_hdrs_phys[index] + offset;
+
+ return txq->tso_hdrs[index] + offset;
+}
+
+static void mvneta_tso_put_hdr(struct sk_buff *skb, struct mvneta_tx_queue *txq,
+ struct tso_t *tso, int size, bool is_last)
{
struct mvneta_tx_buf *buf = &txq->buf[txq->txq_put_index];
int hdr_len = skb_tcp_all_headers(skb);
struct mvneta_tx_desc *tx_desc;
+ dma_addr_t hdr_phys;
+ char *hdr;
+
+ hdr = mvneta_get_tso_hdr(txq, &hdr_phys);
+ tso_build_hdr(skb, hdr, tso, size, is_last);
tx_desc = mvneta_txq_next_desc_get(txq);
tx_desc->data_size = hdr_len;
tx_desc->command = mvneta_skb_tx_csum(skb);
tx_desc->command |= MVNETA_TXD_F_DESC;
- tx_desc->buf_phys_addr = txq->tso_hdrs_phys +
- txq->txq_put_index * TSO_HEADER_SIZE;
- buf->type = MVNETA_TYPE_SKB;
+ tx_desc->buf_phys_addr = hdr_phys;
+ buf->type = MVNETA_TYPE_TSO;
buf->skb = NULL;
mvneta_txq_inc_put(txq);
@@ -2714,14 +2772,41 @@ mvneta_tso_put_data(struct net_device *dev, struct mvneta_tx_queue *txq,
return 0;
}
+static void mvneta_release_descs(struct mvneta_port *pp,
+ struct mvneta_tx_queue *txq,
+ int first, int num)
+{
+ int desc_idx, i;
+
+ desc_idx = first + num;
+ if (desc_idx >= txq->size)
+ desc_idx -= txq->size;
+
+ for (i = num; i >= 0; i--) {
+ struct mvneta_tx_desc *tx_desc = txq->descs + desc_idx;
+ struct mvneta_tx_buf *buf = &txq->buf[desc_idx];
+
+ if (buf->type == MVNETA_TYPE_SKB)
+ dma_unmap_single(pp->dev->dev.parent,
+ tx_desc->buf_phys_addr,
+ tx_desc->data_size,
+ DMA_TO_DEVICE);
+
+ mvneta_txq_desc_put(txq);
+
+ if (desc_idx == 0)
+ desc_idx = txq->size;
+ desc_idx -= 1;
+ }
+}
+
static int mvneta_tx_tso(struct sk_buff *skb, struct net_device *dev,
struct mvneta_tx_queue *txq)
{
int hdr_len, total_len, data_left;
- int desc_count = 0;
+ int first_desc, desc_count = 0;
struct mvneta_port *pp = netdev_priv(dev);
struct tso_t tso;
- int i;
/* Count needed descriptors */
if ((txq->count + tso_count_descs(skb)) >= txq->size)
@@ -2732,22 +2817,19 @@ static int mvneta_tx_tso(struct sk_buff *skb, struct net_device *dev,
return 0;
}
+ first_desc = txq->txq_put_index;
+
/* Initialize the TSO handler, and prepare the first payload */
hdr_len = tso_start(skb, &tso);
total_len = skb->len - hdr_len;
while (total_len > 0) {
- char *hdr;
-
data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len);
total_len -= data_left;
desc_count++;
/* prepare packet headers: MAC + IP + TCP */
- hdr = txq->tso_hdrs + txq->txq_put_index * TSO_HEADER_SIZE;
- tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0);
-
- mvneta_tso_put_hdr(skb, txq);
+ mvneta_tso_put_hdr(skb, txq, &tso, data_left, total_len == 0);
while (data_left > 0) {
int size;
@@ -2772,15 +2854,7 @@ err_release:
/* Release all used data descriptors; header descriptors must not
* be DMA-unmapped.
*/
- for (i = desc_count - 1; i >= 0; i--) {
- struct mvneta_tx_desc *tx_desc = txq->descs + i;
- if (!IS_TSO_HEADER(txq, tx_desc->buf_phys_addr))
- dma_unmap_single(pp->dev->dev.parent,
- tx_desc->buf_phys_addr,
- tx_desc->data_size,
- DMA_TO_DEVICE);
- mvneta_txq_desc_put(txq);
- }
+ mvneta_release_descs(pp, txq, first_desc, desc_count - 1);
return 0;
}
@@ -2790,6 +2864,7 @@ static int mvneta_tx_frag_process(struct mvneta_port *pp, struct sk_buff *skb,
{
struct mvneta_tx_desc *tx_desc;
int i, nr_frags = skb_shinfo(skb)->nr_frags;
+ int first_desc = txq->txq_put_index;
for (i = 0; i < nr_frags; i++) {
struct mvneta_tx_buf *buf = &txq->buf[txq->txq_put_index];
@@ -2828,15 +2903,7 @@ error:
/* Release all descriptors that were used to map fragments of
* this packet, as well as the corresponding DMA mappings
*/
- for (i = i - 1; i >= 0; i--) {
- tx_desc = txq->descs + i;
- dma_unmap_single(pp->dev->dev.parent,
- tx_desc->buf_phys_addr,
- tx_desc->data_size,
- DMA_TO_DEVICE);
- mvneta_txq_desc_put(txq);
- }
-
+ mvneta_release_descs(pp, txq, first_desc, i - 1);
return -ENOMEM;
}
@@ -3457,7 +3524,7 @@ static void mvneta_rxq_deinit(struct mvneta_port *pp,
static int mvneta_txq_sw_init(struct mvneta_port *pp,
struct mvneta_tx_queue *txq)
{
- int cpu;
+ int cpu, err;
txq->size = pp->tx_ring_size;
@@ -3482,11 +3549,9 @@ static int mvneta_txq_sw_init(struct mvneta_port *pp,
return -ENOMEM;
/* Allocate DMA buffers for TSO MAC/IP/TCP headers */
- txq->tso_hdrs = dma_alloc_coherent(pp->dev->dev.parent,
- txq->size * TSO_HEADER_SIZE,
- &txq->tso_hdrs_phys, GFP_KERNEL);
- if (!txq->tso_hdrs)
- return -ENOMEM;
+ err = mvneta_alloc_tso_hdrs(pp, txq);
+ if (err)
+ return err;
/* Setup XPS mapping */
if (pp->neta_armada3700)
@@ -3538,10 +3603,7 @@ static void mvneta_txq_sw_deinit(struct mvneta_port *pp,
kfree(txq->buf);
- if (txq->tso_hdrs)
- dma_free_coherent(pp->dev->dev.parent,
- txq->size * TSO_HEADER_SIZE,
- txq->tso_hdrs, txq->tso_hdrs_phys);
+ mvneta_free_tso_hdrs(pp, txq);
if (txq->descs)
dma_free_coherent(pp->dev->dev.parent,
txq->size * MVNETA_DESC_ALIGNED_SIZE,
@@ -3550,7 +3612,6 @@ static void mvneta_txq_sw_deinit(struct mvneta_port *pp,
netdev_tx_reset_queue(nq);
txq->buf = NULL;
- txq->tso_hdrs = NULL;
txq->descs = NULL;
txq->last_desc = 0;
txq->next_desc_to_proc = 0;
@@ -3941,8 +4002,8 @@ static void mvneta_pcs_get_state(struct phylink_pcs *pcs,
state->pause |= MLO_PAUSE_TX;
}
-static int mvneta_pcs_config(struct phylink_pcs *pcs,
- unsigned int mode, phy_interface_t interface,
+static int mvneta_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
+ phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
{
@@ -3955,7 +4016,7 @@ static int mvneta_pcs_config(struct phylink_pcs *pcs,
MVNETA_GMAC_AN_FLOW_CTRL_EN |
MVNETA_GMAC_AN_DUPLEX_EN;
- if (phylink_autoneg_inband(mode)) {
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
mask |= MVNETA_GMAC_CONFIG_MII_SPEED |
MVNETA_GMAC_CONFIG_GMII_SPEED |
MVNETA_GMAC_CONFIG_FULL_DUPLEX;
@@ -4295,7 +4356,7 @@ static void mvneta_percpu_elect(struct mvneta_port *pp)
*/
if (txq_number == 1)
txq_map = (cpu == elected_cpu) ?
- MVNETA_CPU_TXQ_ACCESS(1) : 0;
+ MVNETA_CPU_TXQ_ACCESS(0) : 0;
else
txq_map = mvreg_read(pp, MVNETA_CPU_MAP(cpu)) &
MVNETA_CPU_TXQ_ACCESS_ALL_MASK;
@@ -5457,6 +5518,7 @@ static int mvneta_probe(struct platform_device *pdev)
clk_prepare_enable(pp->clk_bus);
pp->phylink_pcs.ops = &mvneta_phylink_pcs_ops;
+ pp->phylink_pcs.neg_mode = true;
pp->phylink_config.dev = &dev->dev;
pp->phylink_config.type = PHYLINK_NETDEV;
@@ -5821,6 +5883,8 @@ static int __init mvneta_driver_init(void)
{
int ret;
+ BUILD_BUG_ON_NOT_POWER_OF_2(MVNETA_TSO_PER_PAGE);
+
ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "net/mvneta:online",
mvneta_cpu_online,
mvneta_cpu_down_prepare);
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index adc953611913..1fec84b4c068 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -6168,8 +6168,7 @@ static void mvpp2_xlg_pcs_get_state(struct phylink_pcs *pcs,
state->pause |= MLO_PAUSE_RX;
}
-static int mvpp2_xlg_pcs_config(struct phylink_pcs *pcs,
- unsigned int mode,
+static int mvpp2_xlg_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -6232,7 +6231,7 @@ static void mvpp2_gmac_pcs_get_state(struct phylink_pcs *pcs,
state->pause |= MLO_PAUSE_TX;
}
-static int mvpp2_gmac_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+static int mvpp2_gmac_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -6246,7 +6245,7 @@ static int mvpp2_gmac_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
MVPP2_GMAC_FLOW_CTRL_AUTONEG |
MVPP2_GMAC_AN_DUPLEX_EN;
- if (phylink_autoneg_inband(mode)) {
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
mask |= MVPP2_GMAC_CONFIG_MII_SPEED |
MVPP2_GMAC_CONFIG_GMII_SPEED |
MVPP2_GMAC_CONFIG_FULL_DUPLEX;
@@ -6649,8 +6648,9 @@ static void mvpp2_acpi_start(struct mvpp2_port *port)
mvpp2_mac_prepare(&port->phylink_config, MLO_AN_INBAND,
port->phy_interface);
mvpp2_mac_config(&port->phylink_config, MLO_AN_INBAND, &state);
- pcs->ops->pcs_config(pcs, MLO_AN_INBAND, port->phy_interface,
- state.advertising, false);
+ pcs->ops->pcs_config(pcs, PHYLINK_PCS_NEG_INBAND_ENABLED,
+ port->phy_interface, state.advertising,
+ false);
mvpp2_mac_finish(&port->phylink_config, MLO_AN_INBAND,
port->phy_interface);
mvpp2_mac_link_up(&port->phylink_config, NULL,
@@ -6896,7 +6896,9 @@ static int mvpp2_port_probe(struct platform_device *pdev,
dev->dev.of_node = port_node;
port->pcs_gmac.ops = &mvpp2_phylink_gmac_pcs_ops;
+ port->pcs_gmac.neg_mode = true;
port->pcs_xlg.ops = &mvpp2_phylink_xlg_pcs_ops;
+ port->pcs_xlg.neg_mode = true;
if (!mvpp2_use_acpi_compat_mode(port_fwnode)) {
port->phylink_config.dev = &dev->dev;
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c
index 035ead7935c7..dab61cc1acb5 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c
@@ -98,6 +98,9 @@ int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox)
writeq(OCTEP_CTRL_MBOX_STATUS_INIT,
OCTEP_CTRL_MBOX_INFO_HOST_STATUS(mbox->barmem));
+ mutex_init(&mbox->h2fq_lock);
+ mutex_init(&mbox->f2hq_lock);
+
mbox->h2fq.sz = readl(OCTEP_CTRL_MBOX_H2FQ_SZ(mbox->barmem));
mbox->h2fq.hw_prod = OCTEP_CTRL_MBOX_H2FQ_PROD(mbox->barmem);
mbox->h2fq.hw_cons = OCTEP_CTRL_MBOX_H2FQ_CONS(mbox->barmem);
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c
index 1cc6af2feb38..565320ec24f8 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c
@@ -55,7 +55,7 @@ static int octep_send_mbox_req(struct octep_device *oct,
list_add_tail(&d->list, &oct->ctrl_req_wait_list);
ret = wait_event_interruptible_timeout(oct->ctrl_req_wait_q,
(d->done != 0),
- jiffies + msecs_to_jiffies(500));
+ msecs_to_jiffies(500));
list_del(&d->list);
if (ret == 0 || ret == 1)
return -EAGAIN;
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
index 43eb6e871351..4424de2ffd70 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
@@ -1038,6 +1038,10 @@ static void octep_device_cleanup(struct octep_device *oct)
{
int i;
+ oct->poll_non_ioq_intr = false;
+ cancel_delayed_work_sync(&oct->intr_poll_task);
+ cancel_work_sync(&oct->ctrl_mbox_task);
+
dev_info(&oct->pdev->dev, "Cleaning up Octeon Device ...\n");
for (i = 0; i < OCTEP_MAX_VF; i++) {
@@ -1200,14 +1204,11 @@ static void octep_remove(struct pci_dev *pdev)
if (!oct)
return;
- cancel_work_sync(&oct->tx_timeout_task);
- cancel_work_sync(&oct->ctrl_mbox_task);
netdev = oct->netdev;
if (netdev->reg_state == NETREG_REGISTERED)
unregister_netdev(netdev);
- oct->poll_non_ioq_intr = false;
- cancel_delayed_work_sync(&oct->intr_poll_task);
+ cancel_work_sync(&oct->tx_timeout_task);
octep_device_cleanup(oct);
pci_release_mem_regions(pdev);
free_netdev(netdev);
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
index 392d9b0da0d7..3c43f8078528 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
@@ -158,7 +158,7 @@ static int octep_setup_oq(struct octep_device *oct, int q_no)
goto desc_dma_alloc_err;
}
- oq->buff_info = vzalloc(oq->max_count * OCTEP_OQ_RECVBUF_SIZE);
+ oq->buff_info = vcalloc(oq->max_count, OCTEP_OQ_RECVBUF_SIZE);
if (unlikely(!oq->buff_info)) {
dev_err(&oct->pdev->dev,
"Failed to allocate buffer info for OQ-%d\n", q_no);
diff --git a/drivers/net/ethernet/marvell/octeontx2/Kconfig b/drivers/net/ethernet/marvell/octeontx2/Kconfig
index 993ac180a5db..a32d85d6f599 100644
--- a/drivers/net/ethernet/marvell/octeontx2/Kconfig
+++ b/drivers/net/ethernet/marvell/octeontx2/Kconfig
@@ -32,6 +32,7 @@ config OCTEONTX2_PF
tristate "Marvell OcteonTX2 NIC Physical Function driver"
select OCTEONTX2_MBOX
select NET_DEVLINK
+ select PAGE_POOL
depends on (64BIT && COMPILE_TEST) || ARM64
select DIMLIB
depends on PCI
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
index bd77152bb8d7..592037f4e55b 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
@@ -169,6 +169,9 @@ void cgx_lmac_write(int cgx_id, int lmac_id, u64 offset, u64 val)
{
struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
+ /* Software must not access disabled LMAC registers */
+ if (!is_lmac_valid(cgx_dev, lmac_id))
+ return;
cgx_write(cgx_dev, lmac_id, offset, val);
}
@@ -176,6 +179,10 @@ u64 cgx_lmac_read(int cgx_id, int lmac_id, u64 offset)
{
struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
+ /* Software must not access disabled LMAC registers */
+ if (!is_lmac_valid(cgx_dev, lmac_id))
+ return 0;
+
return cgx_read(cgx_dev, lmac_id, offset);
}
@@ -530,14 +537,15 @@ static u32 cgx_get_lmac_fifo_len(void *cgxd, int lmac_id)
int cgx_lmac_internal_loopback(void *cgxd, int lmac_id, bool enable)
{
struct cgx *cgx = cgxd;
- u8 lmac_type;
+ struct lmac *lmac;
u64 cfg;
if (!is_lmac_valid(cgx, lmac_id))
return -ENODEV;
- lmac_type = cgx->mac_ops->get_lmac_type(cgx, lmac_id);
- if (lmac_type == LMAC_MODE_SGMII || lmac_type == LMAC_MODE_QSGMII) {
+ lmac = lmac_pdata(lmac_id, cgx);
+ if (lmac->lmac_type == LMAC_MODE_SGMII ||
+ lmac->lmac_type == LMAC_MODE_QSGMII) {
cfg = cgx_read(cgx, lmac_id, CGXX_GMP_PCS_MRX_CTL);
if (enable)
cfg |= CGXX_GMP_PCS_MRX_CTL_LBK;
@@ -1556,6 +1564,23 @@ int cgx_lmac_linkup_start(void *cgxd)
return 0;
}
+int cgx_lmac_reset(void *cgxd, int lmac_id, u8 pf_req_flr)
+{
+ struct cgx *cgx = cgxd;
+ u64 cfg;
+
+ if (!is_lmac_valid(cgx, lmac_id))
+ return -ENODEV;
+
+ /* Resetting PFC related CSRs */
+ cfg = 0xff;
+ cgx_write(cgxd, lmac_id, CGXX_CMRX_RX_LOGL_XON, cfg);
+
+ if (pf_req_flr)
+ cgx_lmac_internal_loopback(cgxd, lmac_id, false);
+ return 0;
+}
+
static int cgx_configure_interrupt(struct cgx *cgx, struct lmac *lmac,
int cnt, bool req_free)
{
@@ -1675,6 +1700,7 @@ static int cgx_lmac_init(struct cgx *cgx)
cgx->lmac_idmap[lmac->lmac_id] = lmac;
set_bit(lmac->lmac_id, &cgx->lmac_bmap);
cgx->mac_ops->mac_pause_frm_config(cgx, lmac->lmac_id, true);
+ lmac->lmac_type = cgx->mac_ops->get_lmac_type(cgx, lmac->lmac_id);
}
return cgx_lmac_verify_fwi_version(cgx);
@@ -1771,6 +1797,7 @@ static struct mac_ops cgx_mac_ops = {
.mac_tx_enable = cgx_lmac_tx_enable,
.pfc_config = cgx_lmac_pfc_config,
.mac_get_pfc_frm_cfg = cgx_lmac_get_pfc_frm_cfg,
+ .mac_reset = cgx_lmac_reset,
};
static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
index 5a20d93004c7..574114179688 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
@@ -35,6 +35,7 @@
#define CGXX_CMRX_INT_ENA_W1S 0x058
#define CGXX_CMRX_RX_ID_MAP 0x060
#define CGXX_CMRX_RX_STAT0 0x070
+#define CGXX_CMRX_RX_LOGL_XON 0x100
#define CGXX_CMRX_RX_LMACS 0x128
#define CGXX_CMRX_RX_DMAC_CTL0 (0x1F8 + mac_ops->csr_offset)
#define CGX_DMAC_CTL0_CAM_ENABLE BIT_ULL(3)
@@ -181,4 +182,5 @@ int cgx_lmac_get_pfc_frm_cfg(void *cgxd, int lmac_id, u8 *tx_pause,
u8 *rx_pause);
int verify_lmac_fc_cfg(void *cgxd, int lmac_id, u8 tx_pause, u8 rx_pause,
int pfvf_idx);
+int cgx_lmac_reset(void *cgxd, int lmac_id, u8 pf_req_flr);
#endif /* CGX_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/common.h b/drivers/net/ethernet/marvell/octeontx2/af/common.h
index 8931864ee110..2436c1ff9ba4 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/common.h
@@ -142,9 +142,16 @@ enum nix_scheduler {
#define TXSCH_RR_QTM_MAX ((1 << 24) - 1)
#define TXSCH_TL1_DFLT_RR_QTM TXSCH_RR_QTM_MAX
-#define TXSCH_TL1_DFLT_RR_PRIO (0x1ull)
+#define TXSCH_TL1_DFLT_RR_PRIO (0x7ull)
#define CN10K_MAX_DWRR_WEIGHT 16384 /* Weight is 14bit on CN10K */
+/* Don't change the order as on CN10K (except CN10KB)
+ * SMQX_CFG[SDP] value should be 1 for SDP flows.
+ */
+#define SMQ_LINK_TYPE_RPM 0
+#define SMQ_LINK_TYPE_SDP 1
+#define SMQ_LINK_TYPE_LBK 2
+
/* Min/Max packet sizes, excluding FCS */
#define NIC_HW_MIN_FRS 40
#define NIC_HW_MAX_FRS 9212
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
index 39aaf0e4467d..0b4cba03f2e8 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
@@ -24,6 +24,7 @@
* @cgx: parent cgx port
* @mcast_filters_count: Number of multicast filters installed
* @lmac_id: lmac port id
+ * @lmac_type: lmac type like SGMII/XAUI
* @cmd_pend: flag set before new command is started
* flag cleared after command response is received
* @name: lmac port name
@@ -43,6 +44,7 @@ struct lmac {
struct cgx *cgx;
u8 mcast_filters_count;
u8 lmac_id;
+ u8 lmac_type;
bool cmd_pend;
char *name;
};
@@ -125,6 +127,7 @@ struct mac_ops {
int (*mac_get_pfc_frm_cfg)(void *cgxd, int lmac_id,
u8 *tx_pause, u8 *rx_pause);
+ int (*mac_reset)(void *cgxd, int lmac_id, u8 pf_req_flr);
/* FEC stats */
int (*get_fec_stats)(void *cgxd, int lmac_id,
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
index 6389ed83637d..eba307eee2b2 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
@@ -1080,6 +1080,8 @@ struct nix_vtag_config_rsp {
*/
};
+#define NIX_FLOW_KEY_TYPE_L3_L4_MASK (~(0xf << 28))
+
struct nix_rss_flowkey_cfg {
struct mbox_msghdr hdr;
int mcam_index; /* MCAM entry index to modify */
@@ -1105,6 +1107,10 @@ struct nix_rss_flowkey_cfg {
#define NIX_FLOW_KEY_TYPE_IPV4_PROTO BIT(21)
#define NIX_FLOW_KEY_TYPE_AH BIT(22)
#define NIX_FLOW_KEY_TYPE_ESP BIT(23)
+#define NIX_FLOW_KEY_TYPE_L4_DST_ONLY BIT(28)
+#define NIX_FLOW_KEY_TYPE_L4_SRC_ONLY BIT(29)
+#define NIX_FLOW_KEY_TYPE_L3_DST_ONLY BIT(30)
+#define NIX_FLOW_KEY_TYPE_L3_SRC_ONLY BIT(31)
u32 flowkey_cfg; /* Flowkey types selected */
u8 group; /* RSS context or group */
};
@@ -1151,6 +1157,7 @@ struct nix_rx_cfg {
struct mbox_msghdr hdr;
#define NIX_RX_OL3_VERIFY BIT(0)
#define NIX_RX_OL4_VERIFY BIT(1)
+#define NIX_RX_DROP_RE BIT(2)
u8 len_verify; /* Outer L3/L4 len check */
#define NIX_RX_CSUM_OL4_VERIFY BIT(0)
u8 csum_verify; /* Outer L4 checksum verification */
@@ -1239,7 +1246,9 @@ struct nix_hw_info {
u16 min_mtu;
u32 rpm_dwrr_mtu;
u32 sdp_dwrr_mtu;
- u64 rsvd[16]; /* Add reserved fields for future expansion */
+ u32 lbk_dwrr_mtu;
+ u32 rsvd32[1];
+ u64 rsvd[15]; /* Add reserved fields for future expansion */
};
struct nix_bandprof_alloc_req {
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
index 3411e2e47d46..0ee420a489fc 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
@@ -208,7 +208,7 @@ struct ptp *ptp_get(void)
/* Check driver is bound to PTP block */
if (!ptp)
ptp = ERR_PTR(-EPROBE_DEFER);
- else
+ else if (!IS_ERR(ptp))
pci_dev_get(ptp->pdev);
return ptp;
@@ -388,11 +388,10 @@ static int ptp_extts_on(struct ptp *ptp, int on)
static int ptp_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- struct device *dev = &pdev->dev;
struct ptp *ptp;
int err;
- ptp = devm_kzalloc(dev, sizeof(*ptp), GFP_KERNEL);
+ ptp = kzalloc(sizeof(*ptp), GFP_KERNEL);
if (!ptp) {
err = -ENOMEM;
goto error;
@@ -428,20 +427,19 @@ static int ptp_probe(struct pci_dev *pdev,
return 0;
error_free:
- devm_kfree(dev, ptp);
+ kfree(ptp);
error:
/* For `ptp_get()` we need to differentiate between the case
* when the core has not tried to probe this device and the case when
- * the probe failed. In the later case we pretend that the
- * initialization was successful and keep the error in
+ * the probe failed. In the later case we keep the error in
* `dev->driver_data`.
*/
pci_set_drvdata(pdev, ERR_PTR(err));
if (!first_ptp_block)
first_ptp_block = ERR_PTR(err);
- return 0;
+ return err;
}
static void ptp_remove(struct pci_dev *pdev)
@@ -449,16 +447,17 @@ static void ptp_remove(struct pci_dev *pdev)
struct ptp *ptp = pci_get_drvdata(pdev);
u64 clock_cfg;
- if (cn10k_ptp_errata(ptp) && hrtimer_active(&ptp->hrtimer))
- hrtimer_cancel(&ptp->hrtimer);
-
if (IS_ERR_OR_NULL(ptp))
return;
+ if (cn10k_ptp_errata(ptp) && hrtimer_active(&ptp->hrtimer))
+ hrtimer_cancel(&ptp->hrtimer);
+
/* Disable PTP clock */
clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);
clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN;
writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);
+ kfree(ptp);
}
static const struct pci_device_id ptp_id_table[] = {
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
index de0d88dd10d6..b4fcb20c3f4f 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
@@ -37,6 +37,7 @@ static struct mac_ops rpm_mac_ops = {
.mac_tx_enable = rpm_lmac_tx_enable,
.pfc_config = rpm_lmac_pfc_config,
.mac_get_pfc_frm_cfg = rpm_lmac_get_pfc_frm_cfg,
+ .mac_reset = rpm_lmac_reset,
};
static struct mac_ops rpm2_mac_ops = {
@@ -47,7 +48,7 @@ static struct mac_ops rpm2_mac_ops = {
.int_set_reg = RPM2_CMRX_SW_INT_ENA_W1S,
.irq_offset = 1,
.int_ena_bit = BIT_ULL(0),
- .lmac_fwi = RPM_LMAC_FWI,
+ .lmac_fwi = RPM2_LMAC_FWI,
.non_contiguous_serdes_lane = true,
.rx_stats_cnt = 43,
.tx_stats_cnt = 34,
@@ -68,6 +69,7 @@ static struct mac_ops rpm2_mac_ops = {
.mac_tx_enable = rpm_lmac_tx_enable,
.pfc_config = rpm_lmac_pfc_config,
.mac_get_pfc_frm_cfg = rpm_lmac_get_pfc_frm_cfg,
+ .mac_reset = rpm_lmac_reset,
};
bool is_dev_rpm2(void *rpmd)
@@ -537,14 +539,15 @@ u32 rpm2_get_lmac_fifo_len(void *rpmd, int lmac_id)
int rpm_lmac_internal_loopback(void *rpmd, int lmac_id, bool enable)
{
rpm_t *rpm = rpmd;
- u8 lmac_type;
+ struct lmac *lmac;
u64 cfg;
if (!is_lmac_valid(rpm, lmac_id))
return -ENODEV;
- lmac_type = rpm->mac_ops->get_lmac_type(rpm, lmac_id);
- if (lmac_type == LMAC_MODE_QSGMII || lmac_type == LMAC_MODE_SGMII) {
+ lmac = lmac_pdata(lmac_id, rpm);
+ if (lmac->lmac_type == LMAC_MODE_QSGMII ||
+ lmac->lmac_type == LMAC_MODE_SGMII) {
dev_err(&rpm->pdev->dev, "loopback not supported for LPC mode\n");
return 0;
}
@@ -713,3 +716,24 @@ int rpm_get_fec_stats(void *rpmd, int lmac_id, struct cgx_fec_stats_rsp *rsp)
return 0;
}
+
+int rpm_lmac_reset(void *rpmd, int lmac_id, u8 pf_req_flr)
+{
+ u64 rx_logl_xon, cfg;
+ rpm_t *rpm = rpmd;
+
+ if (!is_lmac_valid(rpm, lmac_id))
+ return -ENODEV;
+
+ /* Resetting PFC related CSRs */
+ rx_logl_xon = is_dev_rpm2(rpm) ? RPM2_CMRX_RX_LOGL_XON :
+ RPMX_CMRX_RX_LOGL_XON;
+ cfg = 0xff;
+
+ rpm_write(rpm, lmac_id, rx_logl_xon, cfg);
+
+ if (pf_req_flr)
+ rpm_lmac_internal_loopback(rpm, lmac_id, false);
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
index 22147b4c2137..b79cfbc6f877 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
@@ -74,6 +74,7 @@
#define RPMX_MTI_MAC100X_CL01_PAUSE_QUANTA 0x80A8
#define RPMX_MTI_MAC100X_CL89_PAUSE_QUANTA 0x8108
#define RPM_DEFAULT_PAUSE_TIME 0x7FF
+#define RPMX_CMRX_RX_LOGL_XON 0x4100
#define RPMX_MTI_MAC100X_XIF_MODE 0x8100
#define RPMX_ONESTEP_ENABLE BIT_ULL(5)
@@ -94,7 +95,8 @@
/* CN10KB CSR Declaration */
#define RPM2_CMRX_SW_INT 0x1b0
-#define RPM2_CMRX_SW_INT_ENA_W1S 0x1b8
+#define RPM2_CMRX_SW_INT_ENA_W1S 0x1c8
+#define RPM2_LMAC_FWI 0x12
#define RPM2_CMR_CHAN_MSK_OR 0x3120
#define RPM2_CMR_RX_OVR_BP_EN BIT_ULL(2)
#define RPM2_CMR_RX_OVR_BP_BP BIT_ULL(1)
@@ -131,4 +133,5 @@ int rpm_lmac_get_pfc_frm_cfg(void *rpmd, int lmac_id, u8 *tx_pause,
int rpm2_get_nr_lmacs(void *rpmd);
bool is_dev_rpm2(void *rpmd);
int rpm_get_fec_stats(void *cgxd, int lmac_id, struct cgx_fec_stats_rsp *rsp);
+int rpm_lmac_reset(void *rpmd, int lmac_id, u8 pf_req_flr);
#endif /* RPM_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
index 9f673bda9dbd..73df2d564545 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
@@ -2629,6 +2629,7 @@ static void __rvu_flr_handler(struct rvu *rvu, u16 pcifunc)
* Since LF is detached use LF number as -1.
*/
rvu_npc_free_mcam_entries(rvu, pcifunc, -1);
+ rvu_mac_reset(rvu, pcifunc);
mutex_unlock(&rvu->flr_lock);
}
@@ -3044,9 +3045,8 @@ static int rvu_flr_init(struct rvu *rvu)
cfg | BIT_ULL(22));
}
- rvu->flr_wq = alloc_workqueue("rvu_afpf_flr",
- WQ_UNBOUND | WQ_HIGHPRI | WQ_MEM_RECLAIM,
- 1);
+ rvu->flr_wq = alloc_ordered_workqueue("rvu_afpf_flr",
+ WQ_HIGHPRI | WQ_MEM_RECLAIM);
if (!rvu->flr_wq)
return -ENOMEM;
@@ -3252,7 +3252,7 @@ static int rvu_probe(struct pci_dev *pdev, const struct pci_device_id *id)
rvu->ptp = ptp_get();
if (IS_ERR(rvu->ptp)) {
err = PTR_ERR(rvu->ptp);
- if (err == -EPROBE_DEFER)
+ if (err)
goto err_release_regions;
rvu->ptp = NULL;
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
index d655bf04a483..e8e65fd7888d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
@@ -23,6 +23,7 @@
#define PCI_DEVID_OCTEONTX2_LBK 0xA061
/* Subsystem Device ID */
+#define PCI_SUBSYS_DEVID_98XX 0xB100
#define PCI_SUBSYS_DEVID_96XX 0xB200
#define PCI_SUBSYS_DEVID_CN10K_A 0xB900
#define PCI_SUBSYS_DEVID_CNF10K_B 0xBC00
@@ -285,6 +286,22 @@ struct nix_mark_format {
u32 *cfg;
};
+/* smq(flush) to tl1 cir/pir info */
+struct nix_smq_tree_ctx {
+ u64 cir_off;
+ u64 cir_val;
+ u64 pir_off;
+ u64 pir_val;
+};
+
+/* smq flush context */
+struct nix_smq_flush_ctx {
+ int smq;
+ u16 tl1_schq;
+ u16 tl2_schq;
+ struct nix_smq_tree_ctx smq_tree_ctx[NIX_TXSCH_LVL_CNT];
+};
+
struct npc_pkind {
struct rsrc_bmap rsrc;
u32 *pfchan_map;
@@ -346,6 +363,7 @@ struct hw_cap {
bool per_pf_mbox_regs; /* PF mbox specified in per PF registers ? */
bool programmable_chans; /* Channels programmable ? */
bool ipolicer;
+ bool nix_multiple_dwrr_mtu; /* Multiple DWRR_MTU to choose from */
bool npc_hash_extract; /* Hash extract enabled ? */
bool npc_exact_match_enabled; /* Exact match supported ? */
};
@@ -669,6 +687,16 @@ static inline u16 rvu_nix_chan_cpt(struct rvu *rvu, u8 chan)
return rvu->hw->cpt_chan_base + chan;
}
+static inline bool is_rvu_supports_nix1(struct rvu *rvu)
+{
+ struct pci_dev *pdev = rvu->pdev;
+
+ if (pdev->subsystem_device == PCI_SUBSYS_DEVID_98XX)
+ return true;
+
+ return false;
+}
+
/* Function Prototypes
* RVU
*/
@@ -802,8 +830,11 @@ int nix_aq_context_read(struct rvu *rvu, struct nix_hw *nix_hw,
struct nix_cn10k_aq_enq_rsp *aq_rsp,
u16 pcifunc, u8 ctype, u32 qidx);
int rvu_get_nix_blkaddr(struct rvu *rvu, u16 pcifunc);
+int nix_get_dwrr_mtu_reg(struct rvu_hwinfo *hw, int smq_link_type);
u32 convert_dwrr_mtu_to_bytes(u8 dwrr_mtu);
u32 convert_bytes_to_dwrr_mtu(u32 bytes);
+void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, u16 pcifunc,
+ struct nix_txsch *txsch, bool enable);
/* NPC APIs */
void rvu_npc_freemem(struct rvu *rvu);
@@ -864,6 +895,7 @@ int rvu_cgx_config_tx(void *cgxd, int lmac_id, bool enable);
int rvu_cgx_prio_flow_ctrl_cfg(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_pause,
u16 pfc_en);
int rvu_cgx_cfg_pause_frm(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_pause);
+void rvu_mac_reset(struct rvu *rvu, u16 pcifunc);
u32 rvu_cgx_get_lmac_fifolen(struct rvu *rvu, int cgx, int lmac);
int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, u16 pcifunc, int nixlf,
int type);
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
index 83b342fa8d75..095b2cc4a699 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
@@ -114,7 +114,7 @@ static void rvu_map_cgx_nix_block(struct rvu *rvu, int pf,
p2x = cgx_lmac_get_p2x(cgx_id, lmac_id);
/* Firmware sets P2X_SELECT as either NIX0 or NIX1 */
pfvf->nix_blkaddr = BLKADDR_NIX0;
- if (p2x == CMR_P2X_SEL_NIX1)
+ if (is_rvu_supports_nix1(rvu) && p2x == CMR_P2X_SEL_NIX1)
pfvf->nix_blkaddr = BLKADDR_NIX1;
}
@@ -763,7 +763,7 @@ static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable)
cgxd = rvu_cgx_pdata(cgx_id, rvu);
mac_ops = get_mac_ops(cgxd);
- mac_ops->mac_enadis_ptp_config(cgxd, lmac_id, true);
+ mac_ops->mac_enadis_ptp_config(cgxd, lmac_id, enable);
/* If PTP is enabled then inform NPC that packets to be
* parsed by this PF will have their data shifted by 8 bytes
* and if PTP is disabled then no shift is required
@@ -1250,3 +1250,21 @@ int rvu_mbox_handler_cgx_prio_flow_ctrl_cfg(struct rvu *rvu,
mac_ops->mac_get_pfc_frm_cfg(cgxd, lmac_id, &rsp->tx_pause, &rsp->rx_pause);
return err;
}
+
+void rvu_mac_reset(struct rvu *rvu, u16 pcifunc)
+{
+ int pf = rvu_get_pf(pcifunc);
+ struct mac_ops *mac_ops;
+ struct cgx *cgxd;
+ u8 cgx, lmac;
+
+ if (!is_pf_cgxmapped(rvu, pf))
+ return;
+
+ rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx, &lmac);
+ cgxd = rvu_cgx_pdata(cgx, rvu);
+ mac_ops = get_mac_ops(cgxd);
+
+ if (mac_ops->mac_reset(cgxd, lmac, !is_vf(pcifunc)))
+ dev_err(rvu->dev, "Failed to reset MAC\n");
+}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
index 9533b1d92960..3b26893efdf8 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
@@ -1222,6 +1222,11 @@ static int rvu_dbg_npa_ctx_display(struct seq_file *m, void *unused, int ctype)
for (aura = id; aura < max_id; aura++) {
aq_req.aura_id = aura;
+
+ /* Skip if queue is uninitialized */
+ if (ctype == NPA_AQ_CTYPE_POOL && !test_bit(aura, pfvf->pool_bmap))
+ continue;
+
seq_printf(m, "======%s : %d=======\n",
(ctype == NPA_AQ_CTYPE_AURA) ? "AURA" : "POOL",
aq_req.aura_id);
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
index e4407f09c9d3..41df5ac23f92 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
@@ -1413,7 +1413,8 @@ static int rvu_af_dl_dwrr_mtu_set(struct devlink *devlink, u32 id,
u64 dwrr_mtu;
dwrr_mtu = convert_bytes_to_dwrr_mtu(ctx->val.vu32);
- rvu_write64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU, dwrr_mtu);
+ rvu_write64(rvu, BLKADDR_NIX0,
+ nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM), dwrr_mtu);
return 0;
}
@@ -1428,7 +1429,8 @@ static int rvu_af_dl_dwrr_mtu_get(struct devlink *devlink, u32 id,
if (!rvu->hw->cap.nix_common_dwrr_mtu)
return -EOPNOTSUPP;
- dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU);
+ dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0,
+ nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM));
ctx->val.vu32 = convert_dwrr_mtu_to_bytes(dwrr_mtu);
return 0;
@@ -1438,6 +1440,7 @@ enum rvu_af_dl_param_id {
RVU_AF_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU,
RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,
+ RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT,
};
static int rvu_af_npc_exact_feature_get(struct devlink *devlink, u32 id,
@@ -1494,6 +1497,67 @@ static int rvu_af_npc_exact_feature_validate(struct devlink *devlink, u32 id,
return -EFAULT;
}
+static int rvu_af_dl_npc_mcam_high_zone_percent_get(struct devlink *devlink, u32 id,
+ struct devlink_param_gset_ctx *ctx)
+{
+ struct rvu_devlink *rvu_dl = devlink_priv(devlink);
+ struct rvu *rvu = rvu_dl->rvu;
+ struct npc_mcam *mcam;
+ u32 percent;
+
+ mcam = &rvu->hw->mcam;
+ percent = (mcam->hprio_count * 100) / mcam->bmap_entries;
+ ctx->val.vu8 = (u8)percent;
+
+ return 0;
+}
+
+static int rvu_af_dl_npc_mcam_high_zone_percent_set(struct devlink *devlink, u32 id,
+ struct devlink_param_gset_ctx *ctx)
+{
+ struct rvu_devlink *rvu_dl = devlink_priv(devlink);
+ struct rvu *rvu = rvu_dl->rvu;
+ struct npc_mcam *mcam;
+ u32 percent;
+
+ percent = ctx->val.vu8;
+ mcam = &rvu->hw->mcam;
+ mcam->hprio_count = (mcam->bmap_entries * percent) / 100;
+ mcam->hprio_end = mcam->hprio_count;
+ mcam->lprio_count = (mcam->bmap_entries - mcam->hprio_count) / 2;
+ mcam->lprio_start = mcam->bmap_entries - mcam->lprio_count;
+
+ return 0;
+}
+
+static int rvu_af_dl_npc_mcam_high_zone_percent_validate(struct devlink *devlink, u32 id,
+ union devlink_param_value val,
+ struct netlink_ext_ack *extack)
+{
+ struct rvu_devlink *rvu_dl = devlink_priv(devlink);
+ struct rvu *rvu = rvu_dl->rvu;
+ struct npc_mcam *mcam;
+
+ /* The percent of high prio zone must range from 12% to 100% of unreserved mcam space */
+ if (val.vu8 < 12 || val.vu8 > 100) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "mcam high zone percent must be between 12% to 100%");
+ return -EINVAL;
+ }
+
+ /* Do not allow user to modify the high priority zone entries while mcam entries
+ * have already been assigned.
+ */
+ mcam = &rvu->hw->mcam;
+ if (mcam->bmap_fcnt < mcam->bmap_entries) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "mcam entries have already been assigned, can't resize");
+ return -EPERM;
+ }
+
+ return 0;
+}
+
static const struct devlink_param rvu_af_dl_params[] = {
DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU,
"dwrr_mtu", DEVLINK_PARAM_TYPE_U32,
@@ -1509,6 +1573,12 @@ static const struct devlink_param rvu_af_dl_param_exact_match[] = {
rvu_af_npc_exact_feature_get,
rvu_af_npc_exact_feature_disable,
rvu_af_npc_exact_feature_validate),
+ DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT,
+ "npc_mcam_high_zone_percent", DEVLINK_PARAM_TYPE_U8,
+ BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+ rvu_af_dl_npc_mcam_high_zone_percent_get,
+ rvu_af_dl_npc_mcam_high_zone_percent_set,
+ rvu_af_dl_npc_mcam_high_zone_percent_validate),
};
/* Devlink switch mode */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
index f01d057ad025..c2f68678e947 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
@@ -191,6 +191,18 @@ struct nix_hw *get_nix_hw(struct rvu_hwinfo *hw, int blkaddr)
return NULL;
}
+int nix_get_dwrr_mtu_reg(struct rvu_hwinfo *hw, int smq_link_type)
+{
+ if (hw->cap.nix_multiple_dwrr_mtu)
+ return NIX_AF_DWRR_MTUX(smq_link_type);
+
+ if (smq_link_type == SMQ_LINK_TYPE_SDP)
+ return NIX_AF_DWRR_SDP_MTU;
+
+ /* Here it's same reg for RPM and LBK */
+ return NIX_AF_DWRR_RPM_MTU;
+}
+
u32 convert_dwrr_mtu_to_bytes(u8 dwrr_mtu)
{
dwrr_mtu &= 0x1FULL;
@@ -1691,6 +1703,42 @@ exit:
return true;
}
+static void nix_reset_tx_schedule(struct rvu *rvu, int blkaddr,
+ int lvl, int schq)
+{
+ u64 tlx_parent = 0, tlx_schedule = 0;
+
+ switch (lvl) {
+ case NIX_TXSCH_LVL_TL2:
+ tlx_parent = NIX_AF_TL2X_PARENT(schq);
+ tlx_schedule = NIX_AF_TL2X_SCHEDULE(schq);
+ break;
+ case NIX_TXSCH_LVL_TL3:
+ tlx_parent = NIX_AF_TL3X_PARENT(schq);
+ tlx_schedule = NIX_AF_TL3X_SCHEDULE(schq);
+ break;
+ case NIX_TXSCH_LVL_TL4:
+ tlx_parent = NIX_AF_TL4X_PARENT(schq);
+ tlx_schedule = NIX_AF_TL4X_SCHEDULE(schq);
+ break;
+ case NIX_TXSCH_LVL_MDQ:
+ /* no need to reset SMQ_CFG as HW clears this CSR
+ * on SMQ flush
+ */
+ tlx_parent = NIX_AF_MDQX_PARENT(schq);
+ tlx_schedule = NIX_AF_MDQX_SCHEDULE(schq);
+ break;
+ default:
+ return;
+ }
+
+ if (tlx_parent)
+ rvu_write64(rvu, blkaddr, tlx_parent, 0x0);
+
+ if (tlx_schedule)
+ rvu_write64(rvu, blkaddr, tlx_schedule, 0x0);
+}
+
/* Disable shaping of pkts by a scheduler queue
* at a given scheduler level.
*/
@@ -2040,6 +2088,7 @@ int rvu_mbox_handler_nix_txsch_alloc(struct rvu *rvu,
pfvf_map[schq] = TXSCH_MAP(pcifunc, 0);
nix_reset_tx_linkcfg(rvu, blkaddr, lvl, schq);
nix_reset_tx_shaping(rvu, blkaddr, nixlf, lvl, schq);
+ nix_reset_tx_schedule(rvu, blkaddr, lvl, schq);
}
for (idx = 0; idx < req->schq[lvl]; idx++) {
@@ -2049,6 +2098,7 @@ int rvu_mbox_handler_nix_txsch_alloc(struct rvu *rvu,
pfvf_map[schq] = TXSCH_MAP(pcifunc, 0);
nix_reset_tx_linkcfg(rvu, blkaddr, lvl, schq);
nix_reset_tx_shaping(rvu, blkaddr, nixlf, lvl, schq);
+ nix_reset_tx_schedule(rvu, blkaddr, lvl, schq);
}
}
@@ -2065,9 +2115,121 @@ exit:
return rc;
}
+static void nix_smq_flush_fill_ctx(struct rvu *rvu, int blkaddr, int smq,
+ struct nix_smq_flush_ctx *smq_flush_ctx)
+{
+ struct nix_smq_tree_ctx *smq_tree_ctx;
+ u64 parent_off, regval;
+ u16 schq;
+ int lvl;
+
+ smq_flush_ctx->smq = smq;
+
+ schq = smq;
+ for (lvl = NIX_TXSCH_LVL_SMQ; lvl <= NIX_TXSCH_LVL_TL1; lvl++) {
+ smq_tree_ctx = &smq_flush_ctx->smq_tree_ctx[lvl];
+ if (lvl == NIX_TXSCH_LVL_TL1) {
+ smq_flush_ctx->tl1_schq = schq;
+ smq_tree_ctx->cir_off = NIX_AF_TL1X_CIR(schq);
+ smq_tree_ctx->pir_off = 0;
+ smq_tree_ctx->pir_val = 0;
+ parent_off = 0;
+ } else if (lvl == NIX_TXSCH_LVL_TL2) {
+ smq_flush_ctx->tl2_schq = schq;
+ smq_tree_ctx->cir_off = NIX_AF_TL2X_CIR(schq);
+ smq_tree_ctx->pir_off = NIX_AF_TL2X_PIR(schq);
+ parent_off = NIX_AF_TL2X_PARENT(schq);
+ } else if (lvl == NIX_TXSCH_LVL_TL3) {
+ smq_tree_ctx->cir_off = NIX_AF_TL3X_CIR(schq);
+ smq_tree_ctx->pir_off = NIX_AF_TL3X_PIR(schq);
+ parent_off = NIX_AF_TL3X_PARENT(schq);
+ } else if (lvl == NIX_TXSCH_LVL_TL4) {
+ smq_tree_ctx->cir_off = NIX_AF_TL4X_CIR(schq);
+ smq_tree_ctx->pir_off = NIX_AF_TL4X_PIR(schq);
+ parent_off = NIX_AF_TL4X_PARENT(schq);
+ } else if (lvl == NIX_TXSCH_LVL_MDQ) {
+ smq_tree_ctx->cir_off = NIX_AF_MDQX_CIR(schq);
+ smq_tree_ctx->pir_off = NIX_AF_MDQX_PIR(schq);
+ parent_off = NIX_AF_MDQX_PARENT(schq);
+ }
+ /* save cir/pir register values */
+ smq_tree_ctx->cir_val = rvu_read64(rvu, blkaddr, smq_tree_ctx->cir_off);
+ if (smq_tree_ctx->pir_off)
+ smq_tree_ctx->pir_val = rvu_read64(rvu, blkaddr, smq_tree_ctx->pir_off);
+
+ /* get parent txsch node */
+ if (parent_off) {
+ regval = rvu_read64(rvu, blkaddr, parent_off);
+ schq = (regval >> 16) & 0x1FF;
+ }
+ }
+}
+
+static void nix_smq_flush_enadis_xoff(struct rvu *rvu, int blkaddr,
+ struct nix_smq_flush_ctx *smq_flush_ctx, bool enable)
+{
+ struct nix_txsch *txsch;
+ struct nix_hw *nix_hw;
+ u64 regoff;
+ int tl2;
+
+ nix_hw = get_nix_hw(rvu->hw, blkaddr);
+ if (!nix_hw)
+ return;
+
+ /* loop through all TL2s with matching PF_FUNC */
+ txsch = &nix_hw->txsch[NIX_TXSCH_LVL_TL2];
+ for (tl2 = 0; tl2 < txsch->schq.max; tl2++) {
+ /* skip the smq(flush) TL2 */
+ if (tl2 == smq_flush_ctx->tl2_schq)
+ continue;
+ /* skip unused TL2s */
+ if (TXSCH_MAP_FLAGS(txsch->pfvf_map[tl2]) & NIX_TXSCHQ_FREE)
+ continue;
+ /* skip if PF_FUNC doesn't match */
+ if ((TXSCH_MAP_FUNC(txsch->pfvf_map[tl2]) & ~RVU_PFVF_FUNC_MASK) !=
+ (TXSCH_MAP_FUNC(txsch->pfvf_map[smq_flush_ctx->tl2_schq] &
+ ~RVU_PFVF_FUNC_MASK)))
+ continue;
+ /* enable/disable XOFF */
+ regoff = NIX_AF_TL2X_SW_XOFF(tl2);
+ if (enable)
+ rvu_write64(rvu, blkaddr, regoff, 0x1);
+ else
+ rvu_write64(rvu, blkaddr, regoff, 0x0);
+ }
+}
+
+static void nix_smq_flush_enadis_rate(struct rvu *rvu, int blkaddr,
+ struct nix_smq_flush_ctx *smq_flush_ctx, bool enable)
+{
+ u64 cir_off, pir_off, cir_val, pir_val;
+ struct nix_smq_tree_ctx *smq_tree_ctx;
+ int lvl;
+
+ for (lvl = NIX_TXSCH_LVL_SMQ; lvl <= NIX_TXSCH_LVL_TL1; lvl++) {
+ smq_tree_ctx = &smq_flush_ctx->smq_tree_ctx[lvl];
+ cir_off = smq_tree_ctx->cir_off;
+ cir_val = smq_tree_ctx->cir_val;
+ pir_off = smq_tree_ctx->pir_off;
+ pir_val = smq_tree_ctx->pir_val;
+
+ if (enable) {
+ rvu_write64(rvu, blkaddr, cir_off, cir_val);
+ if (lvl != NIX_TXSCH_LVL_TL1)
+ rvu_write64(rvu, blkaddr, pir_off, pir_val);
+ } else {
+ rvu_write64(rvu, blkaddr, cir_off, 0x0);
+ if (lvl != NIX_TXSCH_LVL_TL1)
+ rvu_write64(rvu, blkaddr, pir_off, 0x0);
+ }
+ }
+}
+
static int nix_smq_flush(struct rvu *rvu, int blkaddr,
int smq, u16 pcifunc, int nixlf)
{
+ struct nix_smq_flush_ctx *smq_flush_ctx;
int pf = rvu_get_pf(pcifunc);
u8 cgx_id = 0, lmac_id = 0;
int err, restore_tx_en = 0;
@@ -2087,6 +2249,14 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,
lmac_id, true);
}
+ /* XOFF all TL2s whose parent TL1 matches SMQ tree TL1 */
+ smq_flush_ctx = kzalloc(sizeof(*smq_flush_ctx), GFP_KERNEL);
+ if (!smq_flush_ctx)
+ return -ENOMEM;
+ nix_smq_flush_fill_ctx(rvu, blkaddr, smq, smq_flush_ctx);
+ nix_smq_flush_enadis_xoff(rvu, blkaddr, smq_flush_ctx, true);
+ nix_smq_flush_enadis_rate(rvu, blkaddr, smq_flush_ctx, false);
+
cfg = rvu_read64(rvu, blkaddr, NIX_AF_SMQX_CFG(smq));
/* Do SMQ flush and set enqueue xoff */
cfg |= BIT_ULL(50) | BIT_ULL(49);
@@ -2101,8 +2271,14 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,
err = rvu_poll_reg(rvu, blkaddr,
NIX_AF_SMQX_CFG(smq), BIT_ULL(49), true);
if (err)
- dev_err(rvu->dev,
- "NIXLF%d: SMQ%d flush failed\n", nixlf, smq);
+ dev_info(rvu->dev,
+ "NIXLF%d: SMQ%d flush failed, txlink might be busy\n",
+ nixlf, smq);
+
+ /* clear XOFF on TL2s */
+ nix_smq_flush_enadis_rate(rvu, blkaddr, smq_flush_ctx, true);
+ nix_smq_flush_enadis_xoff(rvu, blkaddr, smq_flush_ctx, false);
+ kfree(smq_flush_ctx);
rvu_cgx_enadis_rx_bp(rvu, pf, true);
/* restore cgx tx state */
@@ -2144,6 +2320,7 @@ static int nix_txschq_free(struct rvu *rvu, u16 pcifunc)
continue;
nix_reset_tx_linkcfg(rvu, blkaddr, lvl, schq);
nix_clear_tx_xoff(rvu, blkaddr, lvl, schq);
+ nix_reset_tx_shaping(rvu, blkaddr, nixlf, lvl, schq);
}
}
nix_clear_tx_xoff(rvu, blkaddr, NIX_TXSCH_LVL_TL1,
@@ -2182,6 +2359,7 @@ static int nix_txschq_free(struct rvu *rvu, u16 pcifunc)
for (schq = 0; schq < txsch->schq.max; schq++) {
if (TXSCH_MAP_FUNC(txsch->pfvf_map[schq]) != pcifunc)
continue;
+ nix_reset_tx_schedule(rvu, blkaddr, lvl, schq);
rvu_free_rsrc(&txsch->schq, schq);
txsch->pfvf_map[schq] = TXSCH_MAP(0, NIX_TXSCHQ_FREE);
}
@@ -2241,6 +2419,9 @@ static int nix_txschq_free_one(struct rvu *rvu,
*/
nix_clear_tx_xoff(rvu, blkaddr, lvl, schq);
+ nix_reset_tx_linkcfg(rvu, blkaddr, lvl, schq);
+ nix_reset_tx_shaping(rvu, blkaddr, nixlf, lvl, schq);
+
/* Flush if it is a SMQ. Onus of disabling
* TL2/3 queue links before SMQ flush is on user
*/
@@ -2250,6 +2431,8 @@ static int nix_txschq_free_one(struct rvu *rvu,
goto err;
}
+ nix_reset_tx_schedule(rvu, blkaddr, lvl, schq);
+
/* Free the resource */
rvu_free_rsrc(&txsch->schq, schq);
txsch->pfvf_map[schq] = TXSCH_MAP(0, NIX_TXSCHQ_FREE);
@@ -2404,17 +2587,19 @@ static int nix_txschq_cfg_read(struct rvu *rvu, struct nix_hw *nix_hw,
return 0;
}
-static void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr,
- u16 pcifunc, struct nix_txsch *txsch)
+void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, u16 pcifunc,
+ struct nix_txsch *txsch, bool enable)
{
struct rvu_hwinfo *hw = rvu->hw;
int lbk_link_start, lbk_links;
u8 pf = rvu_get_pf(pcifunc);
int schq;
+ u64 cfg;
if (!is_pf_cgxmapped(rvu, pf))
return;
+ cfg = enable ? (BIT_ULL(12) | RVU_SWITCH_LBK_CHAN) : 0;
lbk_link_start = hw->cgx_links;
for (schq = 0; schq < txsch->schq.max; schq++) {
@@ -2428,8 +2613,7 @@ static void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr,
rvu_write64(rvu, blkaddr,
NIX_AF_TL3_TL2X_LINKX_CFG(schq,
lbk_link_start +
- lbk_links),
- BIT_ULL(12) | RVU_SWITCH_LBK_CHAN);
+ lbk_links), cfg);
}
}
@@ -2535,8 +2719,6 @@ int rvu_mbox_handler_nix_txschq_cfg(struct rvu *rvu,
rvu_write64(rvu, blkaddr, reg, regval);
}
- rvu_nix_tx_tl2_cfg(rvu, blkaddr, pcifunc,
- &nix_hw->txsch[NIX_TXSCH_LVL_TL2]);
return 0;
}
@@ -3147,10 +3329,16 @@ static int nix_setup_txschq(struct rvu *rvu, struct nix_hw *nix_hw, int blkaddr)
}
/* Setup a default value of 8192 as DWRR MTU */
- if (rvu->hw->cap.nix_common_dwrr_mtu) {
- rvu_write64(rvu, blkaddr, NIX_AF_DWRR_RPM_MTU,
+ if (rvu->hw->cap.nix_common_dwrr_mtu ||
+ rvu->hw->cap.nix_multiple_dwrr_mtu) {
+ rvu_write64(rvu, blkaddr,
+ nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM),
convert_bytes_to_dwrr_mtu(8192));
- rvu_write64(rvu, blkaddr, NIX_AF_DWRR_SDP_MTU,
+ rvu_write64(rvu, blkaddr,
+ nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_LBK),
+ convert_bytes_to_dwrr_mtu(8192));
+ rvu_write64(rvu, blkaddr,
+ nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_SDP),
convert_bytes_to_dwrr_mtu(8192));
}
@@ -3248,19 +3436,28 @@ int rvu_mbox_handler_nix_get_hw_info(struct rvu *rvu, struct msg_req *req,
rsp->min_mtu = NIC_HW_MIN_FRS;
- if (!rvu->hw->cap.nix_common_dwrr_mtu) {
+ if (!rvu->hw->cap.nix_common_dwrr_mtu &&
+ !rvu->hw->cap.nix_multiple_dwrr_mtu) {
/* Return '1' on OTx2 */
rsp->rpm_dwrr_mtu = 1;
rsp->sdp_dwrr_mtu = 1;
+ rsp->lbk_dwrr_mtu = 1;
return 0;
}
- dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU);
+ /* Return DWRR_MTU for TLx_SCHEDULE[RR_WEIGHT] config */
+ dwrr_mtu = rvu_read64(rvu, blkaddr,
+ nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM));
rsp->rpm_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu);
- dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_SDP_MTU);
+ dwrr_mtu = rvu_read64(rvu, blkaddr,
+ nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_SDP));
rsp->sdp_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu);
+ dwrr_mtu = rvu_read64(rvu, blkaddr,
+ nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_LBK));
+ rsp->lbk_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu);
+
return 0;
}
@@ -3309,6 +3506,7 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
struct nix_rx_flowkey_alg *field;
struct nix_rx_flowkey_alg tmp;
u32 key_type, valid_key;
+ u32 l3_l4_src_dst;
int l4_key_offset = 0;
if (!alg)
@@ -3336,6 +3534,15 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
* group_member - Enabled when protocol is part of a group.
*/
+ /* Last 4 bits (31:28) are reserved to specify SRC, DST
+ * selection for L3, L4 i.e IPV[4,6]_SRC, IPV[4,6]_DST,
+ * [TCP,UDP,SCTP]_SRC, [TCP,UDP,SCTP]_DST
+ * 31 => L3_SRC, 30 => L3_DST, 29 => L4_SRC, 28 => L4_DST
+ */
+ l3_l4_src_dst = flow_cfg;
+ /* Reset these 4 bits, so that these won't be part of key */
+ flow_cfg &= NIX_FLOW_KEY_TYPE_L3_L4_MASK;
+
keyoff_marker = 0; max_key_off = 0; group_member = 0;
nr_field = 0; key_off = 0; field_marker = 1;
field = &tmp; max_bit_pos = fls(flow_cfg);
@@ -3373,6 +3580,22 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
}
field->hdr_offset = 12; /* SIP offset */
field->bytesm1 = 7; /* SIP + DIP, 8 bytes */
+
+ /* Only SIP */
+ if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_SRC_ONLY)
+ field->bytesm1 = 3; /* SIP, 4 bytes */
+
+ if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_DST_ONLY) {
+ /* Both SIP + DIP */
+ if (field->bytesm1 == 3) {
+ field->bytesm1 = 7; /* SIP + DIP, 8B */
+ } else {
+ /* Only DIP */
+ field->hdr_offset = 16; /* DIP off */
+ field->bytesm1 = 3; /* DIP, 4 bytes */
+ }
+ }
+
field->ltype_mask = 0xF; /* Match only IPv4 */
keyoff_marker = false;
break;
@@ -3386,6 +3609,22 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
}
field->hdr_offset = 8; /* SIP offset */
field->bytesm1 = 31; /* SIP + DIP, 32 bytes */
+
+ /* Only SIP */
+ if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_SRC_ONLY)
+ field->bytesm1 = 15; /* SIP, 16 bytes */
+
+ if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_DST_ONLY) {
+ /* Both SIP + DIP */
+ if (field->bytesm1 == 15) {
+ /* SIP + DIP, 32 bytes */
+ field->bytesm1 = 31;
+ } else {
+ /* Only DIP */
+ field->hdr_offset = 24; /* DIP off */
+ field->bytesm1 = 15; /* DIP,16 bytes */
+ }
+ }
field->ltype_mask = 0xF; /* Match only IPv6 */
break;
case NIX_FLOW_KEY_TYPE_TCP:
@@ -3401,6 +3640,21 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
field->lid = NPC_LID_LH;
field->bytesm1 = 3; /* Sport + Dport, 4 bytes */
+ if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L4_SRC_ONLY)
+ field->bytesm1 = 1; /* SRC, 2 bytes */
+
+ if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L4_DST_ONLY) {
+ /* Both SRC + DST */
+ if (field->bytesm1 == 1) {
+ /* SRC + DST, 4 bytes */
+ field->bytesm1 = 3;
+ } else {
+ /* Only DIP */
+ field->hdr_offset = 2; /* DST off */
+ field->bytesm1 = 1; /* DST, 2 bytes */
+ }
+ }
+
/* Enum values for NPC_LID_LD and NPC_LID_LG are same,
* so no need to change the ltype_match, just change
* the lid for inner protocols
@@ -3815,21 +4069,14 @@ int rvu_mbox_handler_nix_set_rx_mode(struct rvu *rvu, struct nix_rx_mode *req,
}
/* install/uninstall promisc entry */
- if (promisc) {
+ if (promisc)
rvu_npc_install_promisc_entry(rvu, pcifunc, nixlf,
pfvf->rx_chan_base,
pfvf->rx_chan_cnt);
-
- if (rvu_npc_exact_has_match_table(rvu))
- rvu_npc_exact_promisc_enable(rvu, pcifunc);
- } else {
+ else
if (!nix_rx_multicast)
rvu_npc_enable_promisc_entry(rvu, pcifunc, nixlf, false);
- if (rvu_npc_exact_has_match_table(rvu))
- rvu_npc_exact_promisc_disable(rvu, pcifunc);
- }
-
return 0;
}
@@ -4023,9 +4270,10 @@ rx_frscfg:
if (link < 0)
return NIX_AF_ERR_RX_LINK_INVALID;
- nix_find_link_frs(rvu, req, pcifunc);
linkcfg:
+ nix_find_link_frs(rvu, req, pcifunc);
+
cfg = rvu_read64(rvu, blkaddr, NIX_AF_RX_LINKX_CFG(link));
cfg = (cfg & ~(0xFFFFULL << 16)) | ((u64)req->maxlen << 16);
if (req->update_minlen)
@@ -4069,6 +4317,11 @@ int rvu_mbox_handler_nix_set_rx_cfg(struct rvu *rvu, struct nix_rx_cfg *req,
else
cfg &= ~BIT_ULL(40);
+ if (req->len_verify & NIX_RX_DROP_RE)
+ cfg |= BIT_ULL(32);
+ else
+ cfg &= ~BIT_ULL(32);
+
if (req->csum_verify & BIT(0))
cfg |= BIT_ULL(37);
else
@@ -4266,8 +4519,11 @@ static void rvu_nix_setup_capabilities(struct rvu *rvu, int blkaddr)
* Check if HW uses a common MTU for all DWRR quantum configs.
* On OcteonTx2 this register field is '0'.
*/
- if (((hw_const >> 56) & 0x10) == 0x10)
+ if ((((hw_const >> 56) & 0x10) == 0x10) && !(hw_const & BIT_ULL(61)))
hw->cap.nix_common_dwrr_mtu = true;
+
+ if (hw_const & BIT_ULL(61))
+ hw->cap.nix_multiple_dwrr_mtu = true;
}
static int rvu_nix_block_init(struct rvu *rvu, struct nix_hw *nix_hw)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c
index 9f11c1e40737..7e20282c12d0 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c
@@ -218,13 +218,54 @@ void npc_config_secret_key(struct rvu *rvu, int blkaddr)
void npc_program_mkex_hash(struct rvu *rvu, int blkaddr)
{
+ struct npc_mcam_kex_hash *mh = rvu->kpu.mkex_hash;
struct hw_cap *hwcap = &rvu->hw->cap;
+ u8 intf, ld, hdr_offset, byte_len;
struct rvu_hwinfo *hw = rvu->hw;
- u8 intf;
+ u64 cfg;
+ /* Check if hardware supports hash extraction */
if (!hwcap->npc_hash_extract)
return;
+ /* Check if IPv6 source/destination address
+ * should be hash enabled.
+ * Hashing reduces 128bit SIP/DIP fields to 32bit
+ * so that 224 bit X2 key can be used for IPv6 based filters as well,
+ * which in turn results in more number of MCAM entries available for
+ * use.
+ *
+ * Hashing of IPV6 SIP/DIP is enabled in below scenarios
+ * 1. If the silicon variant supports hashing feature
+ * 2. If the number of bytes of IP addr being extracted is 4 bytes ie
+ * 32bit. The assumption here is that if user wants 8bytes of LSB of
+ * IP addr or full 16 bytes then his intention is not to use 32bit
+ * hash.
+ */
+ for (intf = 0; intf < hw->npc_intfs; intf++) {
+ for (ld = 0; ld < NPC_MAX_LD; ld++) {
+ cfg = rvu_read64(rvu, blkaddr,
+ NPC_AF_INTFX_LIDX_LTX_LDX_CFG(intf,
+ NPC_LID_LC,
+ NPC_LT_LC_IP6,
+ ld));
+ hdr_offset = FIELD_GET(NPC_HDR_OFFSET, cfg);
+ byte_len = FIELD_GET(NPC_BYTESM, cfg);
+ /* Hashing of IPv6 source/destination address should be
+ * enabled if,
+ * hdr_offset == 8 (offset of source IPv6 address) or
+ * hdr_offset == 24 (offset of destination IPv6)
+ * address) and the number of byte to be
+ * extracted is 4. As per hardware configuration
+ * byte_len should be == actual byte_len - 1.
+ * Hence byte_len is checked against 3 but nor 4.
+ */
+ if ((hdr_offset == 8 || hdr_offset == 24) && byte_len == 3)
+ mh->lid_lt_ld_hash_en[intf][NPC_LID_LC][NPC_LT_LC_IP6][ld] = true;
+ }
+ }
+
+ /* Update hash configuration if the field is hash enabled */
for (intf = 0; intf < hw->npc_intfs; intf++) {
npc_program_mkex_hash_rx(rvu, blkaddr, intf);
npc_program_mkex_hash_tx(rvu, blkaddr, intf);
@@ -1164,8 +1205,10 @@ static u16 __rvu_npc_exact_cmd_rules_cnt_update(struct rvu *rvu, int drop_mcam_i
{
struct npc_exact_table *table;
u16 *cnt, old_cnt;
+ bool promisc;
table = rvu->hw->table;
+ promisc = table->promisc_mode[drop_mcam_idx];
cnt = &table->cnt_cmd_rules[drop_mcam_idx];
old_cnt = *cnt;
@@ -1177,13 +1220,18 @@ static u16 __rvu_npc_exact_cmd_rules_cnt_update(struct rvu *rvu, int drop_mcam_i
*enable_or_disable_cam = false;
- /* If all rules are deleted, disable cam */
+ if (promisc)
+ goto done;
+
+ /* If all rules are deleted and not already in promisc mode;
+ * disable cam
+ */
if (!*cnt && val < 0) {
*enable_or_disable_cam = true;
goto done;
}
- /* If rule got added, enable cam */
+ /* If rule got added and not already in promisc mode; enable cam */
if (!old_cnt && val > 0) {
*enable_or_disable_cam = true;
goto done;
@@ -1462,6 +1510,12 @@ int rvu_npc_exact_promisc_disable(struct rvu *rvu, u16 pcifunc)
*promisc = false;
mutex_unlock(&table->lock);
+ /* Enable drop rule */
+ rvu_npc_enable_mcam_by_entry_index(rvu, drop_mcam_idx, NIX_INTF_RX,
+ true);
+
+ dev_dbg(rvu->dev, "%s: disabled promisc mode (cgx=%d lmac=%d)\n",
+ __func__, cgx_id, lmac_id);
return 0;
}
@@ -1503,6 +1557,12 @@ int rvu_npc_exact_promisc_enable(struct rvu *rvu, u16 pcifunc)
*promisc = true;
mutex_unlock(&table->lock);
+ /* disable drop rule */
+ rvu_npc_enable_mcam_by_entry_index(rvu, drop_mcam_idx, NIX_INTF_RX,
+ false);
+
+ dev_dbg(rvu->dev, "%s: Enabled promisc mode (cgx=%d lmac=%d)\n",
+ __func__, cgx_id, lmac_id);
return 0;
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h
index a1c3d987b804..57a09328d46b 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h
@@ -70,8 +70,8 @@ static struct npc_mcam_kex_hash npc_mkex_hash_default __maybe_unused = {
[NIX_INTF_RX] = {
[NPC_LID_LC] = {
[NPC_LT_LC_IP6] = {
- true,
- true,
+ false,
+ false,
},
},
},
@@ -79,8 +79,8 @@ static struct npc_mcam_kex_hash npc_mkex_hash_default __maybe_unused = {
[NIX_INTF_TX] = {
[NPC_LID_LC] = {
[NPC_LT_LC_IP6] = {
- true,
- true,
+ false,
+ false,
},
},
},
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h
index 7007f0b8e659..b42e631e52d0 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h
@@ -272,7 +272,8 @@
#define NIX_AF_DEBUG_NPC_RESP_DATAX(a) (0x680 | (a) << 3)
#define NIX_AF_SMQX_CFG(a) (0x700 | (a) << 16)
#define NIX_AF_SQM_DBG_CTL_STATUS (0x750)
-#define NIX_AF_DWRR_SDP_MTU (0x790)
+#define NIX_AF_DWRR_SDP_MTU (0x790) /* All CN10K except CN10KB */
+#define NIX_AF_DWRR_MTUX(a) (0x790 | (a) << 16) /* Only for CN10KB */
#define NIX_AF_DWRR_RPM_MTU (0x7A0)
#define NIX_AF_PSE_CHANNEL_LEVEL (0x800)
#define NIX_AF_PSE_SHAPER_CFG (0x810)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c
index 3392487f6b47..592b317f4637 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c
@@ -8,6 +8,17 @@
#include <linux/bitfield.h>
#include "rvu.h"
+static void rvu_switch_enable_lbk_link(struct rvu *rvu, u16 pcifunc, bool enable)
+{
+ struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
+ struct nix_hw *nix_hw;
+
+ nix_hw = get_nix_hw(rvu->hw, pfvf->nix_blkaddr);
+ /* Enable LBK links with channel 63 for TX MCAM rule */
+ rvu_nix_tx_tl2_cfg(rvu, pfvf->nix_blkaddr, pcifunc,
+ &nix_hw->txsch[NIX_TXSCH_LVL_TL2], enable);
+}
+
static int rvu_switch_install_rx_rule(struct rvu *rvu, u16 pcifunc,
u16 chan_mask)
{
@@ -52,6 +63,8 @@ static int rvu_switch_install_tx_rule(struct rvu *rvu, u16 pcifunc, u16 entry)
if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags))
return 0;
+ rvu_switch_enable_lbk_link(rvu, pcifunc, true);
+
lbkid = pfvf->nix_blkaddr == BLKADDR_NIX0 ? 0 : 1;
ether_addr_copy(req.packet.dmac, pfvf->mac_addr);
eth_broadcast_addr((u8 *)&req.mask.dmac);
@@ -218,6 +231,9 @@ void rvu_switch_disable(struct rvu *rvu)
"Reverting RX rule for PF%d failed(%d)\n",
pf, err);
+ /* Disable LBK link */
+ rvu_switch_enable_lbk_link(rvu, pcifunc, false);
+
rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL);
for (vf = 0; vf < numvfs; vf++) {
pcifunc = pf << 10 | ((vf + 1) & 0x3FF);
@@ -226,6 +242,8 @@ void rvu_switch_disable(struct rvu *rvu)
dev_err(rvu->dev,
"Reverting RX rule for PF%dVF%d failed(%d)\n",
pf, vf, err);
+
+ rvu_switch_enable_lbk_link(rvu, pcifunc, false);
}
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
index 73fdb8798614..5664f768cb0c 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
@@ -8,7 +8,7 @@ obj-$(CONFIG_OCTEONTX2_VF) += rvu_nicvf.o otx2_ptp.o
rvu_nicpf-y := otx2_pf.o otx2_common.o otx2_txrx.o otx2_ethtool.o \
otx2_flows.o otx2_tc.o cn10k.o otx2_dmac_flt.o \
- otx2_devlink.o
+ otx2_devlink.o qos_sq.o qos.o
rvu_nicvf-y := otx2_vf.o otx2_devlink.o
rvu_nicpf-$(CONFIG_DCB) += otx2_dcbnl.o
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c
index a487a98eac88..59b138214af2 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c
@@ -4,9 +4,9 @@
* Copyright (C) 2022 Marvell.
*/
+#include <crypto/skcipher.h>
#include <linux/rtnetlink.h>
#include <linux/bitfield.h>
-#include <net/macsec.h>
#include "otx2_common.h"
#define MCS_TCAM0_MAC_DA_MASK GENMASK_ULL(47, 0)
@@ -43,6 +43,56 @@
#define MCS_TCI_E 0x08 /* encryption */
#define MCS_TCI_C 0x04 /* changed text */
+#define CN10K_MAX_HASH_LEN 16
+#define CN10K_MAX_SAK_LEN 32
+
+static int cn10k_ecb_aes_encrypt(struct otx2_nic *pfvf, u8 *sak,
+ u16 sak_len, u8 *hash)
+{
+ u8 data[CN10K_MAX_HASH_LEN] = { 0 };
+ struct skcipher_request *req = NULL;
+ struct scatterlist sg_src, sg_dst;
+ struct crypto_skcipher *tfm;
+ DECLARE_CRYPTO_WAIT(wait);
+ int err;
+
+ tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0);
+ if (IS_ERR(tfm)) {
+ dev_err(pfvf->dev, "failed to allocate transform for ecb-aes\n");
+ return PTR_ERR(tfm);
+ }
+
+ req = skcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ dev_err(pfvf->dev, "failed to allocate request for skcipher\n");
+ err = -ENOMEM;
+ goto free_tfm;
+ }
+
+ err = crypto_skcipher_setkey(tfm, sak, sak_len);
+ if (err) {
+ dev_err(pfvf->dev, "failed to set key for skcipher\n");
+ goto free_req;
+ }
+
+ /* build sg list */
+ sg_init_one(&sg_src, data, CN10K_MAX_HASH_LEN);
+ sg_init_one(&sg_dst, hash, CN10K_MAX_HASH_LEN);
+
+ skcipher_request_set_callback(req, 0, crypto_req_done, &wait);
+ skcipher_request_set_crypt(req, &sg_src, &sg_dst,
+ CN10K_MAX_HASH_LEN, NULL);
+
+ err = crypto_skcipher_encrypt(req);
+ err = crypto_wait_req(err, &wait);
+
+free_req:
+ skcipher_request_free(req);
+free_tfm:
+ crypto_free_skcipher(tfm);
+ return err;
+}
+
static struct cn10k_mcs_txsc *cn10k_mcs_get_txsc(struct cn10k_mcs_cfg *cfg,
struct macsec_secy *secy)
{
@@ -212,6 +262,7 @@ static int cn10k_mcs_write_rx_secy(struct otx2_nic *pfvf,
struct mcs_secy_plcy_write_req *req;
struct mbox *mbox = &pfvf->mbox;
u64 policy;
+ u8 cipher;
int ret;
mutex_lock(&mbox->lock);
@@ -227,7 +278,21 @@ static int cn10k_mcs_write_rx_secy(struct otx2_nic *pfvf,
policy |= MCS_RX_SECY_PLCY_RP;
policy |= MCS_RX_SECY_PLCY_AUTH_ENA;
- policy |= FIELD_PREP(MCS_RX_SECY_PLCY_CIP, MCS_GCM_AES_128);
+
+ switch (secy->key_len) {
+ case 16:
+ cipher = secy->xpn ? MCS_GCM_AES_XPN_128 : MCS_GCM_AES_128;
+ break;
+ case 32:
+ cipher = secy->xpn ? MCS_GCM_AES_XPN_256 : MCS_GCM_AES_256;
+ break;
+ default:
+ cipher = MCS_GCM_AES_128;
+ dev_warn(pfvf->dev, "Unsupported key length\n");
+ break;
+ }
+
+ policy |= FIELD_PREP(MCS_RX_SECY_PLCY_CIP, cipher);
policy |= FIELD_PREP(MCS_RX_SECY_PLCY_VAL, secy->validate_frames);
policy |= MCS_RX_SECY_PLCY_ENA;
@@ -316,16 +381,53 @@ fail:
return ret;
}
+static int cn10k_mcs_write_keys(struct otx2_nic *pfvf,
+ struct macsec_secy *secy,
+ struct mcs_sa_plcy_write_req *req,
+ u8 *sak, u8 *salt, ssci_t ssci)
+{
+ u8 hash_rev[CN10K_MAX_HASH_LEN];
+ u8 sak_rev[CN10K_MAX_SAK_LEN];
+ u8 salt_rev[MACSEC_SALT_LEN];
+ u8 hash[CN10K_MAX_HASH_LEN];
+ u32 ssci_63_32;
+ int err, i;
+
+ err = cn10k_ecb_aes_encrypt(pfvf, sak, secy->key_len, hash);
+ if (err) {
+ dev_err(pfvf->dev, "Generating hash using ECB(AES) failed\n");
+ return err;
+ }
+
+ for (i = 0; i < secy->key_len; i++)
+ sak_rev[i] = sak[secy->key_len - 1 - i];
+
+ for (i = 0; i < CN10K_MAX_HASH_LEN; i++)
+ hash_rev[i] = hash[CN10K_MAX_HASH_LEN - 1 - i];
+
+ for (i = 0; i < MACSEC_SALT_LEN; i++)
+ salt_rev[i] = salt[MACSEC_SALT_LEN - 1 - i];
+
+ ssci_63_32 = (__force u32)cpu_to_be32((__force u32)ssci);
+
+ memcpy(&req->plcy[0][0], sak_rev, secy->key_len);
+ memcpy(&req->plcy[0][4], hash_rev, CN10K_MAX_HASH_LEN);
+ memcpy(&req->plcy[0][6], salt_rev, MACSEC_SALT_LEN);
+ req->plcy[0][7] |= (u64)ssci_63_32 << 32;
+
+ return 0;
+}
+
static int cn10k_mcs_write_rx_sa_plcy(struct otx2_nic *pfvf,
struct macsec_secy *secy,
struct cn10k_mcs_rxsc *rxsc,
u8 assoc_num, bool sa_in_use)
{
- unsigned char *src = rxsc->sa_key[assoc_num];
struct mcs_sa_plcy_write_req *plcy_req;
+ u8 *sak = rxsc->sa_key[assoc_num];
+ u8 *salt = rxsc->salt[assoc_num];
struct mcs_rx_sc_sa_map *map_req;
struct mbox *mbox = &pfvf->mbox;
- u8 reg, key_len;
int ret;
mutex_lock(&mbox->lock);
@@ -343,11 +445,10 @@ static int cn10k_mcs_write_rx_sa_plcy(struct otx2_nic *pfvf,
goto fail;
}
- for (reg = 0, key_len = 0; key_len < secy->key_len; key_len += 8) {
- memcpy((u8 *)&plcy_req->plcy[0][reg],
- (src + reg * 8), 8);
- reg++;
- }
+ ret = cn10k_mcs_write_keys(pfvf, secy, plcy_req, sak,
+ salt, rxsc->ssci[assoc_num]);
+ if (ret)
+ goto fail;
plcy_req->sa_index[0] = rxsc->hw_sa_id[assoc_num];
plcy_req->sa_cnt = 1;
@@ -400,12 +501,16 @@ static int cn10k_mcs_write_tx_secy(struct otx2_nic *pfvf,
struct mcs_secy_plcy_write_req *req;
struct mbox *mbox = &pfvf->mbox;
struct macsec_tx_sc *sw_tx_sc;
- /* Insert SecTag after 12 bytes (DA+SA)*/
- u8 tag_offset = 12;
u8 sectag_tci = 0;
+ u8 tag_offset;
u64 policy;
+ u8 cipher;
int ret;
+ /* Insert SecTag after 12 bytes (DA+SA) or 16 bytes
+ * if VLAN tag needs to be sent in clear text.
+ */
+ tag_offset = txsc->vlan_dev ? 16 : 12;
sw_tx_sc = &secy->tx_sc;
mutex_lock(&mbox->lock);
@@ -434,7 +539,21 @@ static int cn10k_mcs_write_tx_secy(struct otx2_nic *pfvf,
policy |= FIELD_PREP(MCS_TX_SECY_PLCY_ST_OFFSET, tag_offset);
policy |= MCS_TX_SECY_PLCY_INS_MODE;
policy |= MCS_TX_SECY_PLCY_AUTH_ENA;
- policy |= FIELD_PREP(MCS_TX_SECY_PLCY_CIP, MCS_GCM_AES_128);
+
+ switch (secy->key_len) {
+ case 16:
+ cipher = secy->xpn ? MCS_GCM_AES_XPN_128 : MCS_GCM_AES_128;
+ break;
+ case 32:
+ cipher = secy->xpn ? MCS_GCM_AES_XPN_256 : MCS_GCM_AES_256;
+ break;
+ default:
+ cipher = MCS_GCM_AES_128;
+ dev_warn(pfvf->dev, "Unsupported key length\n");
+ break;
+ }
+
+ policy |= FIELD_PREP(MCS_TX_SECY_PLCY_CIP, cipher);
if (secy->protect_frames)
policy |= MCS_TX_SECY_PLCY_PROTECT;
@@ -542,10 +661,10 @@ static int cn10k_mcs_write_tx_sa_plcy(struct otx2_nic *pfvf,
struct cn10k_mcs_txsc *txsc,
u8 assoc_num)
{
- unsigned char *src = txsc->sa_key[assoc_num];
struct mcs_sa_plcy_write_req *plcy_req;
+ u8 *sak = txsc->sa_key[assoc_num];
+ u8 *salt = txsc->salt[assoc_num];
struct mbox *mbox = &pfvf->mbox;
- u8 reg, key_len;
int ret;
mutex_lock(&mbox->lock);
@@ -556,10 +675,10 @@ static int cn10k_mcs_write_tx_sa_plcy(struct otx2_nic *pfvf,
goto fail;
}
- for (reg = 0, key_len = 0; key_len < secy->key_len; key_len += 8) {
- memcpy((u8 *)&plcy_req->plcy[0][reg], (src + reg * 8), 8);
- reg++;
- }
+ ret = cn10k_mcs_write_keys(pfvf, secy, plcy_req, sak,
+ salt, txsc->ssci[assoc_num]);
+ if (ret)
+ goto fail;
plcy_req->plcy[0][8] = assoc_num;
plcy_req->sa_index[0] = txsc->hw_sa_id[assoc_num];
@@ -922,8 +1041,7 @@ static int cn10k_mcs_secy_tx_cfg(struct otx2_nic *pfvf, struct macsec_secy *secy
{
if (sw_tx_sa) {
cn10k_mcs_write_tx_sa_plcy(pfvf, secy, txsc, sa_num);
- cn10k_write_tx_sa_pn(pfvf, txsc, sa_num,
- sw_tx_sa->next_pn_halves.lower);
+ cn10k_write_tx_sa_pn(pfvf, txsc, sa_num, sw_tx_sa->next_pn);
cn10k_mcs_link_tx_sa2sc(pfvf, secy, txsc, sa_num,
sw_tx_sa->active);
}
@@ -959,7 +1077,7 @@ static int cn10k_mcs_secy_rx_cfg(struct otx2_nic *pfvf,
cn10k_mcs_write_rx_sa_plcy(pfvf, secy, mcs_rx_sc,
sa_num, sw_rx_sa->active);
cn10k_mcs_write_rx_sa_pn(pfvf, mcs_rx_sc, sa_num,
- sw_rx_sa->next_pn_halves.lower);
+ sw_rx_sa->next_pn);
}
cn10k_mcs_write_rx_flowid(pfvf, mcs_rx_sc, hw_secy_id);
@@ -1053,7 +1171,7 @@ static void cn10k_mcs_sync_stats(struct otx2_nic *pfvf, struct macsec_secy *secy
static int cn10k_mdo_open(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
struct macsec_tx_sa *sw_tx_sa;
@@ -1077,7 +1195,7 @@ static int cn10k_mdo_open(struct macsec_context *ctx)
static int cn10k_mdo_stop(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct cn10k_mcs_txsc *txsc;
int err;
@@ -1095,7 +1213,7 @@ static int cn10k_mdo_stop(struct macsec_context *ctx)
static int cn10k_mdo_add_secy(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
struct cn10k_mcs_txsc *txsc;
@@ -1103,13 +1221,6 @@ static int cn10k_mdo_add_secy(struct macsec_context *ctx)
if (secy->icv_len != MACSEC_DEFAULT_ICV_LEN)
return -EOPNOTSUPP;
- /* Stick to 16 bytes key len until XPN support is added */
- if (secy->key_len != 16)
- return -EOPNOTSUPP;
-
- if (secy->xpn)
- return -EOPNOTSUPP;
-
txsc = cn10k_mcs_create_txsc(pfvf);
if (IS_ERR(txsc))
return -ENOSPC;
@@ -1118,6 +1229,7 @@ static int cn10k_mdo_add_secy(struct macsec_context *ctx)
txsc->encoding_sa = secy->tx_sc.encoding_sa;
txsc->last_validate_frames = secy->validate_frames;
txsc->last_replay_protect = secy->replay_protect;
+ txsc->vlan_dev = is_vlan_dev(ctx->netdev);
list_add(&txsc->entry, &cfg->txsc_list);
@@ -1129,7 +1241,7 @@ static int cn10k_mdo_add_secy(struct macsec_context *ctx)
static int cn10k_mdo_upd_secy(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
struct macsec_tx_sa *sw_tx_sa;
@@ -1164,7 +1276,7 @@ static int cn10k_mdo_upd_secy(struct macsec_context *ctx)
static int cn10k_mdo_del_secy(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct cn10k_mcs_txsc *txsc;
@@ -1183,7 +1295,7 @@ static int cn10k_mdo_del_secy(struct macsec_context *ctx)
static int cn10k_mdo_add_txsa(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct macsec_tx_sa *sw_tx_sa = ctx->sa.tx_sa;
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
@@ -1202,6 +1314,9 @@ static int cn10k_mdo_add_txsa(struct macsec_context *ctx)
return -ENOSPC;
memcpy(&txsc->sa_key[sa_num], ctx->sa.key, secy->key_len);
+ memcpy(&txsc->salt[sa_num], sw_tx_sa->key.salt.bytes, MACSEC_SALT_LEN);
+ txsc->ssci[sa_num] = sw_tx_sa->ssci;
+
txsc->sa_bmap |= 1 << sa_num;
if (netif_running(secy->netdev)) {
@@ -1210,7 +1325,7 @@ static int cn10k_mdo_add_txsa(struct macsec_context *ctx)
return err;
err = cn10k_write_tx_sa_pn(pfvf, txsc, sa_num,
- sw_tx_sa->next_pn_halves.lower);
+ sw_tx_sa->next_pn);
if (err)
return err;
@@ -1225,7 +1340,7 @@ static int cn10k_mdo_add_txsa(struct macsec_context *ctx)
static int cn10k_mdo_upd_txsa(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct macsec_tx_sa *sw_tx_sa = ctx->sa.tx_sa;
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
@@ -1243,7 +1358,7 @@ static int cn10k_mdo_upd_txsa(struct macsec_context *ctx)
if (netif_running(secy->netdev)) {
/* Keys cannot be changed after creation */
err = cn10k_write_tx_sa_pn(pfvf, txsc, sa_num,
- sw_tx_sa->next_pn_halves.lower);
+ sw_tx_sa->next_pn);
if (err)
return err;
@@ -1258,7 +1373,7 @@ static int cn10k_mdo_upd_txsa(struct macsec_context *ctx)
static int cn10k_mdo_del_txsa(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
u8 sa_num = ctx->sa.assoc_num;
struct cn10k_mcs_txsc *txsc;
@@ -1278,7 +1393,7 @@ static int cn10k_mdo_del_txsa(struct macsec_context *ctx)
static int cn10k_mdo_add_rxsc(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
struct cn10k_mcs_rxsc *rxsc;
@@ -1312,7 +1427,7 @@ static int cn10k_mdo_add_rxsc(struct macsec_context *ctx)
static int cn10k_mdo_upd_rxsc(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
bool enable = ctx->rx_sc->active;
@@ -1331,7 +1446,7 @@ static int cn10k_mdo_upd_rxsc(struct macsec_context *ctx)
static int cn10k_mdo_del_rxsc(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct cn10k_mcs_rxsc *rxsc;
@@ -1349,11 +1464,10 @@ static int cn10k_mdo_del_rxsc(struct macsec_context *ctx)
static int cn10k_mdo_add_rxsa(struct macsec_context *ctx)
{
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct macsec_rx_sc *sw_rx_sc = ctx->sa.rx_sa->sc;
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_rx_sa *rx_sa = ctx->sa.rx_sa;
- u64 next_pn = rx_sa->next_pn_halves.lower;
struct macsec_secy *secy = ctx->secy;
bool sa_in_use = rx_sa->active;
u8 sa_num = ctx->sa.assoc_num;
@@ -1371,6 +1485,9 @@ static int cn10k_mdo_add_rxsa(struct macsec_context *ctx)
return -ENOSPC;
memcpy(&rxsc->sa_key[sa_num], ctx->sa.key, ctx->secy->key_len);
+ memcpy(&rxsc->salt[sa_num], rx_sa->key.salt.bytes, MACSEC_SALT_LEN);
+ rxsc->ssci[sa_num] = rx_sa->ssci;
+
rxsc->sa_bmap |= 1 << sa_num;
if (netif_running(secy->netdev)) {
@@ -1379,7 +1496,8 @@ static int cn10k_mdo_add_rxsa(struct macsec_context *ctx)
if (err)
return err;
- err = cn10k_mcs_write_rx_sa_pn(pfvf, rxsc, sa_num, next_pn);
+ err = cn10k_mcs_write_rx_sa_pn(pfvf, rxsc, sa_num,
+ rx_sa->next_pn);
if (err)
return err;
}
@@ -1389,11 +1507,10 @@ static int cn10k_mdo_add_rxsa(struct macsec_context *ctx)
static int cn10k_mdo_upd_rxsa(struct macsec_context *ctx)
{
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct macsec_rx_sc *sw_rx_sc = ctx->sa.rx_sa->sc;
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_rx_sa *rx_sa = ctx->sa.rx_sa;
- u64 next_pn = rx_sa->next_pn_halves.lower;
struct macsec_secy *secy = ctx->secy;
bool sa_in_use = rx_sa->active;
u8 sa_num = ctx->sa.assoc_num;
@@ -1412,7 +1529,8 @@ static int cn10k_mdo_upd_rxsa(struct macsec_context *ctx)
if (err)
return err;
- err = cn10k_mcs_write_rx_sa_pn(pfvf, rxsc, sa_num, next_pn);
+ err = cn10k_mcs_write_rx_sa_pn(pfvf, rxsc, sa_num,
+ rx_sa->next_pn);
if (err)
return err;
}
@@ -1422,8 +1540,8 @@ static int cn10k_mdo_upd_rxsa(struct macsec_context *ctx)
static int cn10k_mdo_del_rxsa(struct macsec_context *ctx)
{
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct macsec_rx_sc *sw_rx_sc = ctx->sa.rx_sa->sc;
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
u8 sa_num = ctx->sa.assoc_num;
struct cn10k_mcs_rxsc *rxsc;
@@ -1445,8 +1563,8 @@ static int cn10k_mdo_del_rxsa(struct macsec_context *ctx)
static int cn10k_mdo_get_dev_stats(struct macsec_context *ctx)
{
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct mcs_secy_stats tx_rsp = { 0 }, rx_rsp = { 0 };
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
struct cn10k_mcs_txsc *txsc;
@@ -1481,7 +1599,7 @@ static int cn10k_mdo_get_dev_stats(struct macsec_context *ctx)
static int cn10k_mdo_get_tx_sc_stats(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct mcs_sc_stats rsp = { 0 };
struct cn10k_mcs_txsc *txsc;
@@ -1502,7 +1620,7 @@ static int cn10k_mdo_get_tx_sc_stats(struct macsec_context *ctx)
static int cn10k_mdo_get_tx_sa_stats(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct mcs_sa_stats rsp = { 0 };
u8 sa_num = ctx->sa.assoc_num;
@@ -1525,7 +1643,7 @@ static int cn10k_mdo_get_tx_sa_stats(struct macsec_context *ctx)
static int cn10k_mdo_get_rx_sc_stats(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
struct mcs_sc_stats rsp = { 0 };
@@ -1567,8 +1685,8 @@ static int cn10k_mdo_get_rx_sc_stats(struct macsec_context *ctx)
static int cn10k_mdo_get_rx_sa_stats(struct macsec_context *ctx)
{
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct macsec_rx_sc *sw_rx_sc = ctx->sa.rx_sa->sc;
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct mcs_sa_stats rsp = { 0 };
u8 sa_num = ctx->sa.assoc_num;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
index 8a41ad8ca04f..77c8f650f7ac 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
@@ -8,6 +8,7 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <net/tso.h>
+#include <linux/bitfield.h>
#include "otx2_reg.h"
#include "otx2_common.h"
@@ -89,6 +90,11 @@ int otx2_update_sq_stats(struct otx2_nic *pfvf, int qidx)
if (!pfvf->qset.sq)
return 0;
+ if (qidx >= pfvf->hw.non_qos_queues) {
+ if (!test_bit(qidx - pfvf->hw.non_qos_queues, pfvf->qos.qos_sq_bmap))
+ return 0;
+ }
+
otx2_nix_sq_op_stats(&sq->stats, pfvf, qidx);
return 1;
}
@@ -513,11 +519,32 @@ void otx2_config_irq_coalescing(struct otx2_nic *pfvf, int qidx)
(pfvf->hw.cq_ecount_wait - 1));
}
-int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
- dma_addr_t *dma)
+static int otx2_alloc_pool_buf(struct otx2_nic *pfvf, struct otx2_pool *pool,
+ dma_addr_t *dma)
+{
+ unsigned int offset = 0;
+ struct page *page;
+ size_t sz;
+
+ sz = SKB_DATA_ALIGN(pool->rbsize);
+ sz = ALIGN(sz, OTX2_ALIGN);
+
+ page = page_pool_alloc_frag(pool->page_pool, &offset, sz, GFP_ATOMIC);
+ if (unlikely(!page))
+ return -ENOMEM;
+
+ *dma = page_pool_get_dma_addr(page) + offset;
+ return 0;
+}
+
+static int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
+ dma_addr_t *dma)
{
u8 *buf;
+ if (pool->page_pool)
+ return otx2_alloc_pool_buf(pfvf, pool, dma);
+
buf = napi_alloc_frag_align(pool->rbsize, OTX2_ALIGN);
if (unlikely(!buf))
return -ENOMEM;
@@ -532,8 +559,8 @@ int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
return 0;
}
-static int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
- dma_addr_t *dma)
+int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
+ dma_addr_t *dma)
{
int ret;
@@ -616,6 +643,10 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool txschq_for
req->regval[0] = ((u64)pfvf->tx_max_pktlen << 8) | OTX2_MIN_MTU;
req->regval[0] |= (0x20ULL << 51) | (0x80ULL << 39) |
(0x2ULL << 36);
+ /* Set link type for DWRR MTU selection on CN10K silicons */
+ if (!is_dev_otx2(pfvf->pdev))
+ req->regval[0] |= FIELD_PREP(GENMASK_ULL(58, 57),
+ (u64)hw->smq_link_type);
req->num_regs++;
/* MDQ config */
parent = schq_list[NIX_TXSCH_LVL_TL4][prio];
@@ -716,7 +747,8 @@ EXPORT_SYMBOL(otx2_smq_flush);
int otx2_txsch_alloc(struct otx2_nic *pfvf)
{
struct nix_txsch_alloc_req *req;
- int lvl;
+ struct nix_txsch_alloc_rsp *rsp;
+ int lvl, schq, rc;
/* Get memory to put this msg */
req = otx2_mbox_alloc_msg_nix_txsch_alloc(&pfvf->mbox);
@@ -726,43 +758,83 @@ int otx2_txsch_alloc(struct otx2_nic *pfvf)
/* Request one schq per level */
for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++)
req->schq[lvl] = 1;
+ rc = otx2_sync_mbox_msg(&pfvf->mbox);
+ if (rc)
+ return rc;
- return otx2_sync_mbox_msg(&pfvf->mbox);
+ rsp = (struct nix_txsch_alloc_rsp *)
+ otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
+ if (IS_ERR(rsp))
+ return PTR_ERR(rsp);
+
+ /* Setup transmit scheduler list */
+ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++)
+ for (schq = 0; schq < rsp->schq[lvl]; schq++)
+ pfvf->hw.txschq_list[lvl][schq] =
+ rsp->schq_list[lvl][schq];
+
+ pfvf->hw.txschq_link_cfg_lvl = rsp->link_cfg_lvl;
+
+ return 0;
}
-int otx2_txschq_stop(struct otx2_nic *pfvf)
+void otx2_txschq_free_one(struct otx2_nic *pfvf, u16 lvl, u16 schq)
{
struct nix_txsch_free_req *free_req;
- int lvl, schq, err;
+ int err;
mutex_lock(&pfvf->mbox.lock);
- /* Free the transmit schedulers */
+
free_req = otx2_mbox_alloc_msg_nix_txsch_free(&pfvf->mbox);
if (!free_req) {
mutex_unlock(&pfvf->mbox.lock);
- return -ENOMEM;
+ netdev_err(pfvf->netdev,
+ "Failed alloc txschq free req\n");
+ return;
}
- free_req->flags = TXSCHQ_FREE_ALL;
+ free_req->schq_lvl = lvl;
+ free_req->schq = schq;
+
err = otx2_sync_mbox_msg(&pfvf->mbox);
+ if (err) {
+ netdev_err(pfvf->netdev,
+ "Failed stop txschq %d at level %d\n", schq, lvl);
+ }
+
mutex_unlock(&pfvf->mbox.lock);
+}
+
+void otx2_txschq_stop(struct otx2_nic *pfvf)
+{
+ int lvl, schq;
+
+ /* free non QOS TLx nodes */
+ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++)
+ otx2_txschq_free_one(pfvf, lvl,
+ pfvf->hw.txschq_list[lvl][0]);
/* Clear the txschq list */
for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
for (schq = 0; schq < MAX_TXSCHQ_PER_FUNC; schq++)
pfvf->hw.txschq_list[lvl][schq] = 0;
}
- return err;
+
}
void otx2_sqb_flush(struct otx2_nic *pfvf)
{
int qidx, sqe_tail, sqe_head;
+ struct otx2_snd_queue *sq;
u64 incr, *ptr, val;
int timeout = 1000;
ptr = (u64 *)otx2_get_regaddr(pfvf, NIX_LF_SQ_OP_STATUS);
- for (qidx = 0; qidx < pfvf->hw.tot_tx_queues; qidx++) {
+ for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) {
+ sq = &pfvf->qset.sq[qidx];
+ if (!sq->sqb_ptrs)
+ continue;
+
incr = (u64)qidx << 32;
while (timeout) {
val = otx2_atomic64_add(incr, ptr);
@@ -862,7 +934,7 @@ int otx2_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura)
return otx2_sync_mbox_msg(&pfvf->mbox);
}
-static int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura)
+int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura)
{
struct otx2_qset *qset = &pfvf->qset;
struct otx2_snd_queue *sq;
@@ -935,9 +1007,17 @@ static int otx2_cq_init(struct otx2_nic *pfvf, u16 qidx)
cq->cint_idx = qidx - pfvf->hw.rx_queues;
cq->cqe_cnt = qset->sqe_cnt;
} else {
- cq->cq_type = CQ_XDP;
- cq->cint_idx = qidx - non_xdp_queues;
- cq->cqe_cnt = qset->sqe_cnt;
+ if (pfvf->hw.xdp_queues &&
+ qidx < non_xdp_queues + pfvf->hw.xdp_queues) {
+ cq->cq_type = CQ_XDP;
+ cq->cint_idx = qidx - non_xdp_queues;
+ cq->cqe_cnt = qset->sqe_cnt;
+ } else {
+ cq->cq_type = CQ_QOS;
+ cq->cint_idx = qidx - non_xdp_queues -
+ pfvf->hw.xdp_queues;
+ cq->cqe_cnt = qset->sqe_cnt;
+ }
}
cq->cqe_size = pfvf->qset.xqe_size;
@@ -1048,7 +1128,7 @@ int otx2_config_nix_queues(struct otx2_nic *pfvf)
}
/* Initialize TX queues */
- for (qidx = 0; qidx < pfvf->hw.tot_tx_queues; qidx++) {
+ for (qidx = 0; qidx < pfvf->hw.non_qos_queues; qidx++) {
u16 sqb_aura = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, qidx);
err = otx2_sq_init(pfvf, qidx, sqb_aura);
@@ -1095,7 +1175,7 @@ int otx2_config_nix(struct otx2_nic *pfvf)
/* Set RQ/SQ/CQ counts */
nixlf->rq_cnt = pfvf->hw.rx_queues;
- nixlf->sq_cnt = pfvf->hw.tot_tx_queues;
+ nixlf->sq_cnt = otx2_get_total_tx_queues(pfvf);
nixlf->cq_cnt = pfvf->qset.cq_cnt;
nixlf->rss_sz = MAX_RSS_INDIR_TBL_SIZE;
nixlf->rss_grps = MAX_RSS_GROUPS;
@@ -1133,7 +1213,7 @@ void otx2_sq_free_sqbs(struct otx2_nic *pfvf)
int sqb, qidx;
u64 iova, pa;
- for (qidx = 0; qidx < hw->tot_tx_queues; qidx++) {
+ for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) {
sq = &qset->sq[qidx];
if (!sq->sqb_ptrs)
continue;
@@ -1151,10 +1231,31 @@ void otx2_sq_free_sqbs(struct otx2_nic *pfvf)
}
}
+void otx2_free_bufs(struct otx2_nic *pfvf, struct otx2_pool *pool,
+ u64 iova, int size)
+{
+ struct page *page;
+ u64 pa;
+
+ pa = otx2_iova_to_phys(pfvf->iommu_domain, iova);
+ page = virt_to_head_page(phys_to_virt(pa));
+
+ if (pool->page_pool) {
+ page_pool_put_full_page(pool->page_pool, page, true);
+ } else {
+ dma_unmap_page_attrs(pfvf->dev, iova, size,
+ DMA_FROM_DEVICE,
+ DMA_ATTR_SKIP_CPU_SYNC);
+
+ put_page(page);
+ }
+}
+
void otx2_free_aura_ptr(struct otx2_nic *pfvf, int type)
{
int pool_id, pool_start = 0, pool_end = 0, size = 0;
- u64 iova, pa;
+ struct otx2_pool *pool;
+ u64 iova;
if (type == AURA_NIX_SQ) {
pool_start = otx2_get_pool_idx(pfvf, type, 0);
@@ -1170,15 +1271,13 @@ void otx2_free_aura_ptr(struct otx2_nic *pfvf, int type)
/* Free SQB and RQB pointers from the aura pool */
for (pool_id = pool_start; pool_id < pool_end; pool_id++) {
iova = otx2_aura_allocptr(pfvf, pool_id);
+ pool = &pfvf->qset.pool[pool_id];
while (iova) {
if (type == AURA_NIX_RQ)
iova -= OTX2_HEAD_ROOM;
- pa = otx2_iova_to_phys(pfvf->iommu_domain, iova);
- dma_unmap_page_attrs(pfvf->dev, iova, size,
- DMA_FROM_DEVICE,
- DMA_ATTR_SKIP_CPU_SYNC);
- put_page(virt_to_page(phys_to_virt(pa)));
+ otx2_free_bufs(pfvf, pool, iova, size);
+
iova = otx2_aura_allocptr(pfvf, pool_id);
}
}
@@ -1196,13 +1295,15 @@ void otx2_aura_pool_free(struct otx2_nic *pfvf)
pool = &pfvf->qset.pool[pool_id];
qmem_free(pfvf->dev, pool->stack);
qmem_free(pfvf->dev, pool->fc_addr);
+ page_pool_destroy(pool->page_pool);
+ pool->page_pool = NULL;
}
devm_kfree(pfvf->dev, pfvf->qset.pool);
pfvf->qset.pool = NULL;
}
-static int otx2_aura_init(struct otx2_nic *pfvf, int aura_id,
- int pool_id, int numptrs)
+int otx2_aura_init(struct otx2_nic *pfvf, int aura_id,
+ int pool_id, int numptrs)
{
struct npa_aq_enq_req *aq;
struct otx2_pool *pool;
@@ -1278,9 +1379,10 @@ static int otx2_aura_init(struct otx2_nic *pfvf, int aura_id,
return 0;
}
-static int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
- int stack_pages, int numptrs, int buf_size)
+int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
+ int stack_pages, int numptrs, int buf_size, int type)
{
+ struct page_pool_params pp_params = { 0 };
struct npa_aq_enq_req *aq;
struct otx2_pool *pool;
int err;
@@ -1324,6 +1426,22 @@ static int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
aq->ctype = NPA_AQ_CTYPE_POOL;
aq->op = NPA_AQ_INSTOP_INIT;
+ if (type != AURA_NIX_RQ) {
+ pool->page_pool = NULL;
+ return 0;
+ }
+
+ pp_params.flags = PP_FLAG_PAGE_FRAG | PP_FLAG_DMA_MAP;
+ pp_params.pool_size = numptrs;
+ pp_params.nid = NUMA_NO_NODE;
+ pp_params.dev = pfvf->dev;
+ pp_params.dma_dir = DMA_FROM_DEVICE;
+ pool->page_pool = page_pool_create(&pp_params);
+ if (IS_ERR(pool->page_pool)) {
+ netdev_err(pfvf->netdev, "Creation of page pool failed\n");
+ return PTR_ERR(pool->page_pool);
+ }
+
return 0;
}
@@ -1349,7 +1467,7 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf)
stack_pages =
(num_sqbs + hw->stack_pg_ptrs - 1) / hw->stack_pg_ptrs;
- for (qidx = 0; qidx < hw->tot_tx_queues; qidx++) {
+ for (qidx = 0; qidx < hw->non_qos_queues; qidx++) {
pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, qidx);
/* Initialize aura context */
err = otx2_aura_init(pfvf, pool_id, pool_id, num_sqbs);
@@ -1358,7 +1476,7 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf)
/* Initialize pool context */
err = otx2_pool_init(pfvf, pool_id, stack_pages,
- num_sqbs, hw->sqb_size);
+ num_sqbs, hw->sqb_size, AURA_NIX_SQ);
if (err)
goto fail;
}
@@ -1369,7 +1487,7 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf)
goto fail;
/* Allocate pointers and free them to aura/pool */
- for (qidx = 0; qidx < hw->tot_tx_queues; qidx++) {
+ for (qidx = 0; qidx < hw->non_qos_queues; qidx++) {
pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, qidx);
pool = &pfvf->qset.pool[pool_id];
@@ -1421,7 +1539,7 @@ int otx2_rq_aura_pool_init(struct otx2_nic *pfvf)
}
for (pool_id = 0; pool_id < hw->rqpool_cnt; pool_id++) {
err = otx2_pool_init(pfvf, pool_id, stack_pages,
- num_ptrs, pfvf->rbsize);
+ num_ptrs, pfvf->rbsize, AURA_NIX_RQ);
if (err)
goto fail;
}
@@ -1605,7 +1723,6 @@ int otx2_nix_config_bp(struct otx2_nic *pfvf, bool enable)
req->bpid_per_chan = 0;
#endif
-
return otx2_sync_mbox_msg(&pfvf->mbox);
}
EXPORT_SYMBOL(otx2_nix_config_bp);
@@ -1629,21 +1746,6 @@ void mbox_handler_cgx_fec_stats(struct otx2_nic *pfvf,
pfvf->hw.cgx_fec_uncorr_blks += rsp->fec_uncorr_blks;
}
-void mbox_handler_nix_txsch_alloc(struct otx2_nic *pf,
- struct nix_txsch_alloc_rsp *rsp)
-{
- int lvl, schq;
-
- /* Setup transmit scheduler list */
- for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++)
- for (schq = 0; schq < rsp->schq[lvl]; schq++)
- pf->hw.txschq_list[lvl][schq] =
- rsp->schq_list[lvl][schq];
-
- pf->hw.txschq_link_cfg_lvl = rsp->link_cfg_lvl;
-}
-EXPORT_SYMBOL(mbox_handler_nix_txsch_alloc);
-
void mbox_handler_npa_lf_alloc(struct otx2_nic *pfvf,
struct npa_lf_alloc_rsp *rsp)
{
@@ -1727,6 +1829,17 @@ void otx2_set_cints_affinity(struct otx2_nic *pfvf)
}
}
+static u32 get_dwrr_mtu(struct otx2_nic *pfvf, struct nix_hw_info *hw)
+{
+ if (is_otx2_lbkvf(pfvf->pdev)) {
+ pfvf->hw.smq_link_type = SMQ_LINK_TYPE_LBK;
+ return hw->lbk_dwrr_mtu;
+ }
+
+ pfvf->hw.smq_link_type = SMQ_LINK_TYPE_RPM;
+ return hw->rpm_dwrr_mtu;
+}
+
u16 otx2_get_max_mtu(struct otx2_nic *pfvf)
{
struct nix_hw_info *rsp;
@@ -1756,7 +1869,7 @@ u16 otx2_get_max_mtu(struct otx2_nic *pfvf)
max_mtu = rsp->max_mtu - 8 - OTX2_ETH_HLEN;
/* Also save DWRR MTU, needed for DWRR weight calculation */
- pfvf->hw.dwrr_mtu = rsp->rpm_dwrr_mtu;
+ pfvf->hw.dwrr_mtu = get_dwrr_mtu(pfvf, rsp);
if (!pfvf->hw.dwrr_mtu)
pfvf->hw.dwrr_mtu = 1;
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
index 0c8fc66ade82..ba8091131ec0 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
@@ -15,6 +15,7 @@
#include <linux/ptp_clock_kernel.h>
#include <linux/timecounter.h>
#include <linux/soc/marvell/octeontx2/asm.h>
+#include <net/macsec.h>
#include <net/pkt_cls.h>
#include <net/devlink.h>
#include <linux/time64.h>
@@ -27,6 +28,7 @@
#include "otx2_txrx.h"
#include "otx2_devlink.h"
#include <rvu_trace.h>
+#include "qos.h"
/* IPv4 flag more fragment bit */
#define IPV4_FLAG_MORE 0x20
@@ -183,13 +185,29 @@ struct mbox {
int up_num_msgs; /* mbox_up number of messages */
};
+/* Egress rate limiting definitions */
+#define MAX_BURST_EXPONENT 0x0FULL
+#define MAX_BURST_MANTISSA 0xFFULL
+#define MAX_BURST_SIZE 130816ULL
+#define MAX_RATE_DIVIDER_EXPONENT 12ULL
+#define MAX_RATE_EXPONENT 0x0FULL
+#define MAX_RATE_MANTISSA 0xFFULL
+
+/* Bitfields in NIX_TLX_PIR register */
+#define TLX_RATE_MANTISSA GENMASK_ULL(8, 1)
+#define TLX_RATE_EXPONENT GENMASK_ULL(12, 9)
+#define TLX_RATE_DIVIDER_EXPONENT GENMASK_ULL(16, 13)
+#define TLX_BURST_MANTISSA GENMASK_ULL(36, 29)
+#define TLX_BURST_EXPONENT GENMASK_ULL(40, 37)
+
struct otx2_hw {
struct pci_dev *pdev;
struct otx2_rss_info rss_info;
u16 rx_queues;
u16 tx_queues;
u16 xdp_queues;
- u16 tot_tx_queues;
+ u16 tc_tx_queues;
+ u16 non_qos_queues; /* tx queues plus xdp queues */
u16 max_queues;
u16 pool_cnt;
u16 rqpool_cnt;
@@ -209,6 +227,7 @@ struct otx2_hw {
u16 txschq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC];
u16 matchall_ipolicer;
u32 dwrr_mtu;
+ u8 smq_link_type;
/* HW settings, coalescing etc */
u16 rx_chan_base;
@@ -250,6 +269,7 @@ struct otx2_hw {
#define CN10K_RPM 3
#define CN10K_PTP_ONESTEP 4
#define CN10K_HW_MACSEC 5
+#define QOS_CIR_PIR_SUPPORT 6
unsigned long cap_flag;
#define LMT_LINE_SIZE 128
@@ -398,6 +418,9 @@ struct cn10k_mcs_txsc {
u8 sa_bmap;
u8 sa_key[CN10K_MCS_SA_PER_SC][MACSEC_MAX_KEY_LEN];
u8 encoding_sa;
+ u8 salt[CN10K_MCS_SA_PER_SC][MACSEC_SALT_LEN];
+ ssci_t ssci[CN10K_MCS_SA_PER_SC];
+ bool vlan_dev; /* macsec running on VLAN ? */
};
struct cn10k_mcs_rxsc {
@@ -410,6 +433,8 @@ struct cn10k_mcs_rxsc {
u16 hw_sa_id[CN10K_MCS_SA_PER_SC];
u8 sa_bmap;
u8 sa_key[CN10K_MCS_SA_PER_SC][MACSEC_MAX_KEY_LEN];
+ u8 salt[CN10K_MCS_SA_PER_SC][MACSEC_SALT_LEN];
+ ssci_t ssci[CN10K_MCS_SA_PER_SC];
};
struct cn10k_mcs_cfg {
@@ -501,6 +526,8 @@ struct otx2_nic {
u16 pfc_schq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC];
bool pfc_alloc_status[NIX_PF_PFC_PRIO_MAX];
#endif
+ /* qos */
+ struct otx2_qos qos;
/* napi event count. It is needed for adaptive irq coalescing. */
u32 napi_events;
@@ -582,6 +609,7 @@ static inline void otx2_setup_dev_hw_settings(struct otx2_nic *pfvf)
__set_bit(CN10K_LMTST, &hw->cap_flag);
__set_bit(CN10K_RPM, &hw->cap_flag);
__set_bit(CN10K_PTP_ONESTEP, &hw->cap_flag);
+ __set_bit(QOS_CIR_PIR_SUPPORT, &hw->cap_flag);
}
if (is_dev_cn10kb(pfvf->pdev))
@@ -745,8 +773,7 @@ static inline void cn10k_aura_freeptr(void *dev, int aura, u64 buf)
/* Alloc pointer from pool/aura */
static inline u64 otx2_aura_allocptr(struct otx2_nic *pfvf, int aura)
{
- u64 *ptr = (u64 *)otx2_get_regaddr(pfvf,
- NPA_LF_AURA_OP_ALLOCX(0));
+ u64 *ptr = (__force u64 *)otx2_get_regaddr(pfvf, NPA_LF_AURA_OP_ALLOCX(0));
u64 incr = (u64)aura | BIT_ULL(63);
return otx2_atomic64_add(incr, ptr);
@@ -888,12 +915,34 @@ static inline void otx2_dma_unmap_page(struct otx2_nic *pfvf,
static inline u16 otx2_get_smq_idx(struct otx2_nic *pfvf, u16 qidx)
{
+ u16 smq;
#ifdef CONFIG_DCB
if (qidx < NIX_PF_PFC_PRIO_MAX && pfvf->pfc_alloc_status[qidx])
return pfvf->pfc_schq_list[NIX_TXSCH_LVL_SMQ][qidx];
#endif
+ /* check if qidx falls under QOS queues */
+ if (qidx >= pfvf->hw.non_qos_queues)
+ smq = pfvf->qos.qid_to_sqmap[qidx - pfvf->hw.non_qos_queues];
+ else
+ smq = pfvf->hw.txschq_list[NIX_TXSCH_LVL_SMQ][0];
+
+ return smq;
+}
+
+static inline u16 otx2_get_total_tx_queues(struct otx2_nic *pfvf)
+{
+ return pfvf->hw.non_qos_queues + pfvf->hw.tc_tx_queues;
+}
+
+static inline u64 otx2_convert_rate(u64 rate)
+{
+ u64 converted_rate;
+
+ /* Convert bytes per second to Mbps */
+ converted_rate = rate * 8;
+ converted_rate = max_t(u64, converted_rate / 1000000, 1);
- return pfvf->hw.txschq_list[NIX_TXSCH_LVL_SMQ][0];
+ return converted_rate;
}
/* MSI-X APIs */
@@ -920,19 +969,25 @@ int otx2_config_nix(struct otx2_nic *pfvf);
int otx2_config_nix_queues(struct otx2_nic *pfvf);
int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool pfc_en);
int otx2_txsch_alloc(struct otx2_nic *pfvf);
-int otx2_txschq_stop(struct otx2_nic *pfvf);
+void otx2_txschq_stop(struct otx2_nic *pfvf);
+void otx2_txschq_free_one(struct otx2_nic *pfvf, u16 lvl, u16 schq);
void otx2_sqb_flush(struct otx2_nic *pfvf);
-int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
- dma_addr_t *dma);
+int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
+ dma_addr_t *dma);
int otx2_rxtx_enable(struct otx2_nic *pfvf, bool enable);
void otx2_ctx_disable(struct mbox *mbox, int type, bool npa);
int otx2_nix_config_bp(struct otx2_nic *pfvf, bool enable);
-void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq);
+void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, int qidx);
void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq);
+int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura);
int otx2_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura);
int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura);
int otx2_alloc_buffer(struct otx2_nic *pfvf, struct otx2_cq_queue *cq,
dma_addr_t *dma);
+int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
+ int stack_pages, int numptrs, int buf_size, int type);
+int otx2_aura_init(struct otx2_nic *pfvf, int aura_id,
+ int pool_id, int numptrs);
/* RSS configuration APIs*/
int otx2_rss_init(struct otx2_nic *pfvf);
@@ -1000,6 +1055,8 @@ u16 otx2_get_max_mtu(struct otx2_nic *pfvf);
int otx2_handle_ntuple_tc_features(struct net_device *netdev,
netdev_features_t features);
int otx2_smq_flush(struct otx2_nic *pfvf, int smq);
+void otx2_free_bufs(struct otx2_nic *pfvf, struct otx2_pool *pool,
+ u64 iova, int size);
/* tc support */
int otx2_init_tc(struct otx2_nic *nic);
@@ -1040,4 +1097,24 @@ static inline void cn10k_handle_mcs_event(struct otx2_nic *pfvf,
{}
#endif /* CONFIG_MACSEC */
+/* qos support */
+static inline void otx2_qos_init(struct otx2_nic *pfvf, int qos_txqs)
+{
+ struct otx2_hw *hw = &pfvf->hw;
+
+ hw->tc_tx_queues = qos_txqs;
+ INIT_LIST_HEAD(&pfvf->qos.qos_tree);
+ mutex_init(&pfvf->qos.qos_lock);
+}
+
+static inline void otx2_shutdown_qos(struct otx2_nic *pfvf)
+{
+ mutex_destroy(&pfvf->qos.qos_lock);
+}
+
+u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
+ struct net_device *sb_dev);
+int otx2_get_txq_by_classid(struct otx2_nic *pfvf, u16 classid);
+void otx2_qos_config_txschq(struct otx2_nic *pfvf);
+void otx2_clean_qos_queues(struct otx2_nic *pfvf);
#endif /* OTX2_COMMON_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
index 0f8d1a69139f..c47d91da32dc 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
@@ -92,10 +92,16 @@ static void otx2_get_qset_strings(struct otx2_nic *pfvf, u8 **data, int qset)
*data += ETH_GSTRING_LEN;
}
}
- for (qidx = 0; qidx < pfvf->hw.tx_queues; qidx++) {
+
+ for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) {
for (stats = 0; stats < otx2_n_queue_stats; stats++) {
- sprintf(*data, "txq%d: %s", qidx + start_qidx,
- otx2_queue_stats[stats].name);
+ if (qidx >= pfvf->hw.non_qos_queues)
+ sprintf(*data, "txq_qos%d: %s",
+ qidx + start_qidx - pfvf->hw.non_qos_queues,
+ otx2_queue_stats[stats].name);
+ else
+ sprintf(*data, "txq%d: %s", qidx + start_qidx,
+ otx2_queue_stats[stats].name);
*data += ETH_GSTRING_LEN;
}
}
@@ -159,7 +165,7 @@ static void otx2_get_qset_stats(struct otx2_nic *pfvf,
[otx2_queue_stats[stat].index];
}
- for (qidx = 0; qidx < pfvf->hw.tx_queues; qidx++) {
+ for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) {
if (!otx2_update_sq_stats(pfvf, qidx)) {
for (stat = 0; stat < otx2_n_queue_stats; stat++)
*((*data)++) = 0;
@@ -254,7 +260,7 @@ static int otx2_get_sset_count(struct net_device *netdev, int sset)
return -EINVAL;
qstats_count = otx2_n_queue_stats *
- (pfvf->hw.rx_queues + pfvf->hw.tx_queues);
+ (pfvf->hw.rx_queues + otx2_get_total_tx_queues(pfvf));
if (!test_bit(CN10K_RPM, &pfvf->hw.cap_flag))
mac_stats = CGX_RX_STATS_COUNT + CGX_TX_STATS_COUNT;
otx2_update_lmac_fec_stats(pfvf);
@@ -282,7 +288,7 @@ static int otx2_set_channels(struct net_device *dev,
{
struct otx2_nic *pfvf = netdev_priv(dev);
bool if_up = netif_running(dev);
- int err = 0;
+ int err, qos_txqs;
if (!channel->rx_count || !channel->tx_count)
return -EINVAL;
@@ -296,14 +302,19 @@ static int otx2_set_channels(struct net_device *dev,
if (if_up)
dev->netdev_ops->ndo_stop(dev);
- err = otx2_set_real_num_queues(dev, channel->tx_count,
+ qos_txqs = bitmap_weight(pfvf->qos.qos_sq_bmap,
+ OTX2_QOS_MAX_LEAF_NODES);
+
+ err = otx2_set_real_num_queues(dev, channel->tx_count + qos_txqs,
channel->rx_count);
if (err)
return err;
pfvf->hw.rx_queues = channel->rx_count;
pfvf->hw.tx_queues = channel->tx_count;
- pfvf->qset.cq_cnt = pfvf->hw.tx_queues + pfvf->hw.rx_queues;
+ if (pfvf->xdp_prog)
+ pfvf->hw.xdp_queues = channel->rx_count;
+ pfvf->hw.non_qos_queues = pfvf->hw.tx_queues + pfvf->hw.xdp_queues;
if (if_up)
err = dev->netdev_ops->ndo_open(dev);
@@ -1405,7 +1416,7 @@ static int otx2vf_get_sset_count(struct net_device *netdev, int sset)
return -EINVAL;
qstats_count = otx2_n_queue_stats *
- (vf->hw.rx_queues + vf->hw.tx_queues);
+ (vf->hw.rx_queues + otx2_get_total_tx_queues(vf));
return otx2_n_dev_stats + otx2_n_drv_stats + qstats_count + 1;
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
index 10e11262d48a..2d7713a1a153 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
@@ -872,6 +872,14 @@ static int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
return -EINVAL;
vlan_etype = be16_to_cpu(fsp->h_ext.vlan_etype);
+
+ /* Drop rule with vlan_etype == 802.1Q
+ * and vlan_id == 0 is not supported
+ */
+ if (vlan_etype == ETH_P_8021Q && !fsp->m_ext.vlan_tci &&
+ fsp->ring_cookie == RX_CLS_FLOW_DISC)
+ return -EINVAL;
+
/* Only ETH_P_8021Q and ETH_P_802AD types supported */
if (vlan_etype != ETH_P_8021Q &&
vlan_etype != ETH_P_8021AD)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index 18284ad75157..9551b422622a 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -23,6 +23,7 @@
#include "otx2_struct.h"
#include "otx2_ptp.h"
#include "cn10k.h"
+#include "qos.h"
#include <rvu_trace.h>
#define DRV_NAME "rvu_nicpf"
@@ -271,8 +272,7 @@ static int otx2_pf_flr_init(struct otx2_nic *pf, int num_vfs)
{
int vf;
- pf->flr_wq = alloc_workqueue("otx2_pf_flr_wq",
- WQ_UNBOUND | WQ_HIGHPRI, 1);
+ pf->flr_wq = alloc_ordered_workqueue("otx2_pf_flr_wq", WQ_HIGHPRI);
if (!pf->flr_wq)
return -ENOMEM;
@@ -593,9 +593,8 @@ static int otx2_pfvf_mbox_init(struct otx2_nic *pf, int numvfs)
if (!pf->mbox_pfvf)
return -ENOMEM;
- pf->mbox_pfvf_wq = alloc_workqueue("otx2_pfvf_mailbox",
- WQ_UNBOUND | WQ_HIGHPRI |
- WQ_MEM_RECLAIM, 1);
+ pf->mbox_pfvf_wq = alloc_ordered_workqueue("otx2_pfvf_mailbox",
+ WQ_HIGHPRI | WQ_MEM_RECLAIM);
if (!pf->mbox_pfvf_wq)
return -ENOMEM;
@@ -791,10 +790,6 @@ static void otx2_process_pfaf_mbox_msg(struct otx2_nic *pf,
case MBOX_MSG_NIX_LF_ALLOC:
mbox_handler_nix_lf_alloc(pf, (struct nix_lf_alloc_rsp *)msg);
break;
- case MBOX_MSG_NIX_TXSCH_ALLOC:
- mbox_handler_nix_txsch_alloc(pf,
- (struct nix_txsch_alloc_rsp *)msg);
- break;
case MBOX_MSG_NIX_BP_ENABLE:
mbox_handler_nix_bp_enable(pf, (struct nix_bp_cfg_rsp *)msg);
break;
@@ -1063,9 +1058,8 @@ static int otx2_pfaf_mbox_init(struct otx2_nic *pf)
int err;
mbox->pfvf = pf;
- pf->mbox_wq = alloc_workqueue("otx2_pfaf_mailbox",
- WQ_UNBOUND | WQ_HIGHPRI |
- WQ_MEM_RECLAIM, 1);
+ pf->mbox_wq = alloc_ordered_workqueue("otx2_pfaf_mailbox",
+ WQ_HIGHPRI | WQ_MEM_RECLAIM);
if (!pf->mbox_wq)
return -ENOMEM;
@@ -1228,6 +1222,7 @@ static char *nix_snd_status_e_str[NIX_SND_STATUS_MAX] = {
static irqreturn_t otx2_q_intr_handler(int irq, void *data)
{
struct otx2_nic *pf = data;
+ struct otx2_snd_queue *sq;
u64 val, *ptr;
u64 qidx = 0;
@@ -1257,10 +1252,14 @@ static irqreturn_t otx2_q_intr_handler(int irq, void *data)
}
/* SQ */
- for (qidx = 0; qidx < pf->hw.tot_tx_queues; qidx++) {
+ for (qidx = 0; qidx < otx2_get_total_tx_queues(pf); qidx++) {
u64 sq_op_err_dbg, mnq_err_dbg, snd_err_dbg;
u8 sq_op_err_code, mnq_err_code, snd_err_code;
+ sq = &pf->qset.sq[qidx];
+ if (!sq->sqb_ptrs)
+ continue;
+
/* Below debug registers captures first errors corresponding to
* those registers. We don't have to check against SQ qid as
* these are fatal errors.
@@ -1383,8 +1382,11 @@ static void otx2_free_sq_res(struct otx2_nic *pf)
otx2_ctx_disable(&pf->mbox, NIX_AQ_CTYPE_SQ, false);
/* Free SQB pointers */
otx2_sq_free_sqbs(pf);
- for (qidx = 0; qidx < pf->hw.tot_tx_queues; qidx++) {
+ for (qidx = 0; qidx < otx2_get_total_tx_queues(pf); qidx++) {
sq = &qset->sq[qidx];
+ /* Skip freeing Qos queues if they are not initialized */
+ if (!sq->sqe)
+ continue;
qmem_free(pf->dev, sq->sqe);
qmem_free(pf->dev, sq->tso_hdrs);
kfree(sq->sg);
@@ -1433,7 +1435,7 @@ static int otx2_init_hw_resources(struct otx2_nic *pf)
* so, aura count = pool count.
*/
hw->rqpool_cnt = hw->rx_queues;
- hw->sqpool_cnt = hw->tot_tx_queues;
+ hw->sqpool_cnt = otx2_get_total_tx_queues(pf);
hw->pool_cnt = hw->rqpool_cnt + hw->sqpool_cnt;
/* Maximum hardware supported transmit length */
@@ -1452,8 +1454,9 @@ static int otx2_init_hw_resources(struct otx2_nic *pf)
if (err)
goto err_free_npa_lf;
- /* Enable backpressure */
- otx2_nix_config_bp(pf, true);
+ /* Enable backpressure for CGX mapped PF/VFs */
+ if (!is_otx2_lbkvf(pf->pdev))
+ otx2_nix_config_bp(pf, true);
/* Init Auras and pools used by NIX RQ, for free buffer ptrs */
err = otx2_rq_aura_pool_init(pf);
@@ -1516,8 +1519,7 @@ err_free_nix_queues:
otx2_free_cq_res(pf);
otx2_ctx_disable(mbox, NIX_AQ_CTYPE_RQ, false);
err_free_txsch:
- if (otx2_txschq_stop(pf))
- dev_err(pf->dev, "%s failed to stop TX schedulers\n", __func__);
+ otx2_txschq_stop(pf);
err_free_sq_ptrs:
otx2_sq_free_sqbs(pf);
err_free_rq_ptrs:
@@ -1551,22 +1553,24 @@ static void otx2_free_hw_resources(struct otx2_nic *pf)
struct nix_lf_free_req *free_req;
struct mbox *mbox = &pf->mbox;
struct otx2_cq_queue *cq;
+ struct otx2_pool *pool;
struct msg_req *req;
- int qidx, err;
+ int pool_id;
+ int qidx;
/* Ensure all SQE are processed */
otx2_sqb_flush(pf);
/* Stop transmission */
- err = otx2_txschq_stop(pf);
- if (err)
- dev_err(pf->dev, "RVUPF: Failed to stop/free TX schedulers\n");
+ otx2_txschq_stop(pf);
#ifdef CONFIG_DCB
if (pf->pfc_en)
otx2_pfc_txschq_stop(pf);
#endif
+ otx2_clean_qos_queues(pf);
+
mutex_lock(&mbox->lock);
/* Disable backpressure */
if (!(pf->pcifunc & RVU_PFVF_FUNC_MASK))
@@ -1580,7 +1584,7 @@ static void otx2_free_hw_resources(struct otx2_nic *pf)
for (qidx = 0; qidx < qset->cq_cnt; qidx++) {
cq = &qset->cq[qidx];
if (cq->cq_type == CQ_RX)
- otx2_cleanup_rx_cqes(pf, cq);
+ otx2_cleanup_rx_cqes(pf, cq, qidx);
else
otx2_cleanup_tx_cqes(pf, cq);
}
@@ -1590,6 +1594,13 @@ static void otx2_free_hw_resources(struct otx2_nic *pf)
/* Free RQ buffer pointers*/
otx2_free_aura_ptr(pf, AURA_NIX_RQ);
+ for (qidx = 0; qidx < pf->hw.rx_queues; qidx++) {
+ pool_id = otx2_get_pool_idx(pf, AURA_NIX_RQ, qidx);
+ pool = &pf->qset.pool[pool_id];
+ page_pool_destroy(pool->page_pool);
+ pool->page_pool = NULL;
+ }
+
otx2_free_cq_res(pf);
/* Free all ingress bandwidth profiles allocated */
@@ -1688,11 +1699,14 @@ int otx2_open(struct net_device *netdev)
netif_carrier_off(netdev);
- pf->qset.cq_cnt = pf->hw.rx_queues + pf->hw.tot_tx_queues;
/* RQ and SQs are mapped to different CQs,
* so find out max CQ IRQs (i.e CINTs) needed.
*/
- pf->hw.cint_cnt = max(pf->hw.rx_queues, pf->hw.tx_queues);
+ pf->hw.cint_cnt = max3(pf->hw.rx_queues, pf->hw.tx_queues,
+ pf->hw.tc_tx_queues);
+
+ pf->qset.cq_cnt = pf->hw.rx_queues + otx2_get_total_tx_queues(pf);
+
qset->napi = kcalloc(pf->hw.cint_cnt, sizeof(*cq_poll), GFP_KERNEL);
if (!qset->napi)
return -ENOMEM;
@@ -1708,7 +1722,7 @@ int otx2_open(struct net_device *netdev)
if (!qset->cq)
goto err_free_mem;
- qset->sq = kcalloc(pf->hw.tot_tx_queues,
+ qset->sq = kcalloc(otx2_get_total_tx_queues(pf),
sizeof(struct otx2_snd_queue), GFP_KERNEL);
if (!qset->sq)
goto err_free_mem;
@@ -1743,6 +1757,11 @@ int otx2_open(struct net_device *netdev)
else
cq_poll->cq_ids[CQ_XDP] = CINT_INVALID_CQ;
+ cq_poll->cq_ids[CQ_QOS] = (qidx < pf->hw.tc_tx_queues) ?
+ (qidx + pf->hw.rx_queues +
+ pf->hw.non_qos_queues) :
+ CINT_INVALID_CQ;
+
cq_poll->dev = (void *)pf;
cq_poll->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_CQE;
INIT_WORK(&cq_poll->dim.work, otx2_dim_work);
@@ -1826,6 +1845,9 @@ int otx2_open(struct net_device *netdev)
/* 'intf_down' may be checked on any cpu */
smp_wmb();
+ /* Enable QoS configuration before starting tx queues */
+ otx2_qos_config_txschq(pf);
+
/* we have already received link status notification */
if (pf->linfo.link_up && !(pf->pcifunc & RVU_PFVF_FUNC_MASK))
otx2_handle_link_event(pf);
@@ -1947,6 +1969,12 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
int qidx = skb_get_queue_mapping(skb);
struct otx2_snd_queue *sq;
struct netdev_queue *txq;
+ int sq_idx;
+
+ /* XDP SQs are not mapped with TXQs
+ * advance qid to derive correct sq mapped with QOS
+ */
+ sq_idx = (qidx >= pf->hw.tx_queues) ? (qidx + pf->hw.xdp_queues) : qidx;
/* Check for minimum and maximum packet length */
if (skb->len <= ETH_HLEN ||
@@ -1955,7 +1983,7 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
}
- sq = &pf->qset.sq[qidx];
+ sq = &pf->qset.sq[sq_idx];
txq = netdev_get_tx_queue(netdev, qidx);
if (!otx2_sq_append_skb(netdev, sq, skb, qidx)) {
@@ -1973,14 +2001,48 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
}
-static u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
- struct net_device *sb_dev)
+static int otx2_qos_select_htb_queue(struct otx2_nic *pf, struct sk_buff *skb,
+ u16 htb_maj_id)
+{
+ u16 classid;
+
+ if ((TC_H_MAJ(skb->priority) >> 16) == htb_maj_id)
+ classid = TC_H_MIN(skb->priority);
+ else
+ classid = READ_ONCE(pf->qos.defcls);
+
+ if (!classid)
+ return 0;
+
+ return otx2_get_txq_by_classid(pf, classid);
+}
+
+u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
+ struct net_device *sb_dev)
{
-#ifdef CONFIG_DCB
struct otx2_nic *pf = netdev_priv(netdev);
+ bool qos_enabled;
+#ifdef CONFIG_DCB
u8 vlan_prio;
#endif
+ int txq;
+
+ qos_enabled = (netdev->real_num_tx_queues > pf->hw.tx_queues) ? true : false;
+ if (unlikely(qos_enabled)) {
+ /* This smp_load_acquire() pairs with smp_store_release() in
+ * otx2_qos_root_add() called from htb offload root creation
+ */
+ u16 htb_maj_id = smp_load_acquire(&pf->qos.maj_id);
+
+ if (unlikely(htb_maj_id)) {
+ txq = otx2_qos_select_htb_queue(pf, skb, htb_maj_id);
+ if (txq > 0)
+ return txq;
+ goto process_pfc;
+ }
+ }
+process_pfc:
#ifdef CONFIG_DCB
if (!skb_vlan_tag_present(skb))
goto pick_tx;
@@ -1994,8 +2056,13 @@ static u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
pick_tx:
#endif
- return netdev_pick_tx(netdev, skb, NULL);
+ txq = netdev_pick_tx(netdev, skb, NULL);
+ if (unlikely(qos_enabled))
+ return txq % pf->hw.tx_queues;
+
+ return txq;
}
+EXPORT_SYMBOL(otx2_select_queue);
static netdev_features_t otx2_fix_features(struct net_device *dev,
netdev_features_t features)
@@ -2529,7 +2596,7 @@ static int otx2_xdp_setup(struct otx2_nic *pf, struct bpf_prog *prog)
xdp_features_clear_redirect_target(dev);
}
- pf->hw.tot_tx_queues += pf->hw.xdp_queues;
+ pf->hw.non_qos_queues += pf->hw.xdp_queues;
if (if_up)
otx2_open(pf->netdev);
@@ -2712,10 +2779,10 @@ static void otx2_sriov_vfcfg_cleanup(struct otx2_nic *pf)
static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct device *dev = &pdev->dev;
+ int err, qcount, qos_txqs;
struct net_device *netdev;
struct otx2_nic *pf;
struct otx2_hw *hw;
- int err, qcount;
int num_vec;
err = pcim_enable_device(pdev);
@@ -2740,8 +2807,9 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* Set number of queues */
qcount = min_t(int, num_online_cpus(), OTX2_MAX_CQ_CNT);
+ qos_txqs = min_t(int, qcount, OTX2_QOS_MAX_LEAF_NODES);
- netdev = alloc_etherdev_mqs(sizeof(*pf), qcount, qcount);
+ netdev = alloc_etherdev_mqs(sizeof(*pf), qcount + qos_txqs, qcount);
if (!netdev) {
err = -ENOMEM;
goto err_release_regions;
@@ -2760,7 +2828,7 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hw->pdev = pdev;
hw->rx_queues = qcount;
hw->tx_queues = qcount;
- hw->tot_tx_queues = qcount;
+ hw->non_qos_queues = qcount;
hw->max_queues = qcount;
hw->rbuf_len = OTX2_DEFAULT_RBUF_LEN;
/* Use CQE of 128 byte descriptor size by default */
@@ -2929,6 +2997,8 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_pf_sriov_init;
#endif
+ otx2_qos_init(pf, qos_txqs);
+
return 0;
err_pf_sriov_init:
@@ -3104,6 +3174,7 @@ static void otx2_remove(struct pci_dev *pdev)
otx2_ptp_destroy(pf);
otx2_mcam_flow_del(pf);
otx2_shutdown_tc(pf);
+ otx2_shutdown_qos(pf);
otx2_detach_resources(&pf->mbox);
if (pf->hw.lmt_info)
free_percpu(pf->hw.lmt_info);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
index 1b967eaf948b..45a32e4b49d1 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
@@ -145,12 +145,25 @@
#define NIX_AF_TL1X_TOPOLOGY(a) (0xC80 | (a) << 16)
#define NIX_AF_TL2X_PARENT(a) (0xE88 | (a) << 16)
#define NIX_AF_TL2X_SCHEDULE(a) (0xE00 | (a) << 16)
+#define NIX_AF_TL2X_TOPOLOGY(a) (0xE80 | (a) << 16)
+#define NIX_AF_TL2X_CIR(a) (0xE20 | (a) << 16)
+#define NIX_AF_TL2X_PIR(a) (0xE30 | (a) << 16)
#define NIX_AF_TL3X_PARENT(a) (0x1088 | (a) << 16)
#define NIX_AF_TL3X_SCHEDULE(a) (0x1000 | (a) << 16)
+#define NIX_AF_TL3X_SHAPE(a) (0x1010 | (a) << 16)
+#define NIX_AF_TL3X_CIR(a) (0x1020 | (a) << 16)
+#define NIX_AF_TL3X_PIR(a) (0x1030 | (a) << 16)
+#define NIX_AF_TL3X_TOPOLOGY(a) (0x1080 | (a) << 16)
#define NIX_AF_TL4X_PARENT(a) (0x1288 | (a) << 16)
#define NIX_AF_TL4X_SCHEDULE(a) (0x1200 | (a) << 16)
+#define NIX_AF_TL4X_SHAPE(a) (0x1210 | (a) << 16)
+#define NIX_AF_TL4X_CIR(a) (0x1220 | (a) << 16)
#define NIX_AF_TL4X_PIR(a) (0x1230 | (a) << 16)
+#define NIX_AF_TL4X_TOPOLOGY(a) (0x1280 | (a) << 16)
#define NIX_AF_MDQX_SCHEDULE(a) (0x1400 | (a) << 16)
+#define NIX_AF_MDQX_SHAPE(a) (0x1410 | (a) << 16)
+#define NIX_AF_MDQX_CIR(a) (0x1420 | (a) << 16)
+#define NIX_AF_MDQX_PIR(a) (0x1430 | (a) << 16)
#define NIX_AF_MDQX_PARENT(a) (0x1480 | (a) << 16)
#define NIX_AF_TL3_TL2X_LINKX_CFG(a, b) (0x1700 | (a) << 16 | (b) << 3)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
index 8392f63e433f..5e56b6c3e60a 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
@@ -19,25 +19,11 @@
#include "cn10k.h"
#include "otx2_common.h"
-
-/* Egress rate limiting definitions */
-#define MAX_BURST_EXPONENT 0x0FULL
-#define MAX_BURST_MANTISSA 0xFFULL
-#define MAX_BURST_SIZE 130816ULL
-#define MAX_RATE_DIVIDER_EXPONENT 12ULL
-#define MAX_RATE_EXPONENT 0x0FULL
-#define MAX_RATE_MANTISSA 0xFFULL
+#include "qos.h"
#define CN10K_MAX_BURST_MANTISSA 0x7FFFULL
#define CN10K_MAX_BURST_SIZE 8453888ULL
-/* Bitfields in NIX_TLX_PIR register */
-#define TLX_RATE_MANTISSA GENMASK_ULL(8, 1)
-#define TLX_RATE_EXPONENT GENMASK_ULL(12, 9)
-#define TLX_RATE_DIVIDER_EXPONENT GENMASK_ULL(16, 13)
-#define TLX_BURST_MANTISSA GENMASK_ULL(36, 29)
-#define TLX_BURST_EXPONENT GENMASK_ULL(40, 37)
-
#define CN10K_TLX_BURST_MANTISSA GENMASK_ULL(43, 29)
#define CN10K_TLX_BURST_EXPONENT GENMASK_ULL(47, 44)
@@ -147,8 +133,8 @@ static void otx2_get_egress_rate_cfg(u64 maxrate, u32 *exp,
}
}
-static u64 otx2_get_txschq_rate_regval(struct otx2_nic *nic,
- u64 maxrate, u32 burst)
+u64 otx2_get_txschq_rate_regval(struct otx2_nic *nic,
+ u64 maxrate, u32 burst)
{
u32 burst_exp, burst_mantissa;
u32 exp, mantissa, div_exp;
@@ -264,7 +250,6 @@ static int otx2_tc_egress_matchall_install(struct otx2_nic *nic,
struct netlink_ext_ack *extack = cls->common.extack;
struct flow_action *actions = &cls->rule->action;
struct flow_action_entry *entry;
- u64 rate;
int err;
err = otx2_tc_validate_flow(nic, actions, extack);
@@ -288,10 +273,8 @@ static int otx2_tc_egress_matchall_install(struct otx2_nic *nic,
NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second");
return -EOPNOTSUPP;
}
- /* Convert bytes per second to Mbps */
- rate = entry->police.rate_bytes_ps * 8;
- rate = max_t(u64, rate / 1000000, 1);
- err = otx2_set_matchall_egress_rate(nic, entry->police.burst, rate);
+ err = otx2_set_matchall_egress_rate(nic, entry->police.burst,
+ otx2_convert_rate(entry->police.rate_bytes_ps));
if (err)
return err;
nic->flags |= OTX2_FLAG_TC_MATCHALL_EGRESS_ENABLED;
@@ -413,8 +396,12 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic,
return -EOPNOTSUPP;
}
req->vf = priv->pcifunc & RVU_PFVF_FUNC_MASK;
- req->op = NIX_RX_ACTION_DEFAULT;
- return 0;
+
+ /* if op is already set; avoid overwriting the same */
+ if (!req->op)
+ req->op = NIX_RX_ACTION_DEFAULT;
+ break;
+
case FLOW_ACTION_VLAN_POP:
req->vtag0_valid = true;
/* use RX_VTAG_TYPE7 which is initialized to strip vlan tag */
@@ -450,6 +437,12 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic,
case FLOW_ACTION_MARK:
mark = act->mark;
break;
+
+ case FLOW_ACTION_RX_QUEUE_MAPPING:
+ req->op = NIX_RX_ACTIONOP_UCAST;
+ req->index = act->rx_queue;
+ break;
+
default:
return -EOPNOTSUPP;
}
@@ -604,6 +597,21 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
return -EOPNOTSUPP;
}
+ if (!match.mask->vlan_id) {
+ struct flow_action_entry *act;
+ int i;
+
+ flow_action_for_each(i, act, &rule->action) {
+ if (act->id == FLOW_ACTION_DROP) {
+ netdev_err(nic->netdev,
+ "vlan tpid 0x%x with vlan_id %d is not supported for DROP rule.\n",
+ ntohs(match.key->vlan_tpid),
+ match.key->vlan_id);
+ return -EOPNOTSUPP;
+ }
+ }
+ }
+
if (match.mask->vlan_id ||
match.mask->vlan_dei ||
match.mask->vlan_priority) {
@@ -1127,6 +1135,8 @@ int otx2_setup_tc(struct net_device *netdev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
return otx2_setup_tc_block(netdev, type_data);
+ case TC_SETUP_QDISC_HTB:
+ return otx2_setup_tc_htb(netdev, type_data);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
index 7af223b0a37f..e369baf11530 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
@@ -217,9 +217,6 @@ static bool otx2_skb_add_frag(struct otx2_nic *pfvf, struct sk_buff *skb,
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
va - page_address(page) + off,
len - off, pfvf->rbsize);
-
- otx2_dma_unmap_page(pfvf, iova - OTX2_HEAD_ROOM,
- pfvf->rbsize, DMA_FROM_DEVICE);
return true;
}
@@ -382,6 +379,8 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
if (pfvf->netdev->features & NETIF_F_RXCSUM)
skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb_mark_for_recycle(skb);
+
napi_gro_frags(napi);
}
@@ -464,12 +463,13 @@ process_cqe:
break;
}
- if (cq->cq_type == CQ_XDP) {
+ qidx = cq->cq_idx - pfvf->hw.rx_queues;
+
+ if (cq->cq_type == CQ_XDP)
otx2_xdp_snd_pkt_handler(pfvf, sq, cqe);
- } else {
- otx2_snd_pkt_handler(pfvf, cq, sq, cqe, budget,
- &tx_pkts, &tx_bytes);
- }
+ else
+ otx2_snd_pkt_handler(pfvf, cq, &pfvf->qset.sq[qidx],
+ cqe, budget, &tx_pkts, &tx_bytes);
cqe->hdr.cqe_type = NIX_XQE_TYPE_INVALID;
processed_cqe++;
@@ -486,7 +486,11 @@ process_cqe:
if (likely(tx_pkts)) {
struct netdev_queue *txq;
- txq = netdev_get_tx_queue(pfvf->netdev, cq->cint_idx);
+ qidx = cq->cq_idx - pfvf->hw.rx_queues;
+
+ if (qidx >= pfvf->hw.tx_queues)
+ qidx -= pfvf->hw.xdp_queues;
+ txq = netdev_get_tx_queue(pfvf->netdev, qidx);
netdev_tx_completed_queue(txq, tx_pkts, tx_bytes);
/* Check if queue was stopped earlier due to ring full */
smp_mb();
@@ -734,7 +738,8 @@ static void otx2_sqe_add_hdr(struct otx2_nic *pfvf, struct otx2_snd_queue *sq,
sqe_hdr->aura = sq->aura_id;
/* Post a CQE Tx after pkt transmission */
sqe_hdr->pnc = 1;
- sqe_hdr->sq = qidx;
+ sqe_hdr->sq = (qidx >= pfvf->hw.tx_queues) ?
+ qidx + pfvf->hw.xdp_queues : qidx;
}
sqe_hdr->total = skb->len;
/* Set SQE identifier which will be used later for freeing SKB */
@@ -1178,11 +1183,13 @@ bool otx2_sq_append_skb(struct net_device *netdev, struct otx2_snd_queue *sq,
}
EXPORT_SYMBOL(otx2_sq_append_skb);
-void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
+void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, int qidx)
{
struct nix_cqe_rx_s *cqe;
+ struct otx2_pool *pool;
int processed_cqe = 0;
- u64 iova, pa;
+ u16 pool_id;
+ u64 iova;
if (pfvf->xdp_prog)
xdp_rxq_info_unreg(&cq->xdp_rxq);
@@ -1190,6 +1197,9 @@ void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
if (otx2_nix_cq_op_status(pfvf, cq) || !cq->pend_cqe)
return;
+ pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_RQ, qidx);
+ pool = &pfvf->qset.pool[pool_id];
+
while (cq->pend_cqe) {
cqe = (struct nix_cqe_rx_s *)otx2_get_next_cqe(cq);
processed_cqe++;
@@ -1202,9 +1212,8 @@ void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
continue;
}
iova = cqe->sg.seg_addr - OTX2_HEAD_ROOM;
- pa = otx2_iova_to_phys(pfvf->iommu_domain, iova);
- otx2_dma_unmap_page(pfvf, iova, pfvf->rbsize, DMA_FROM_DEVICE);
- put_page(virt_to_page(phys_to_virt(pa)));
+
+ otx2_free_bufs(pfvf, pool, iova, pfvf->rbsize);
}
/* Free CQEs to HW */
@@ -1219,8 +1228,10 @@ void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
struct nix_cqe_tx_s *cqe;
int processed_cqe = 0;
struct sg_list *sg;
+ int qidx;
- sq = &pfvf->qset.sq[cq->cint_idx];
+ qidx = cq->cq_idx - pfvf->hw.rx_queues;
+ sq = &pfvf->qset.sq[qidx];
if (otx2_nix_cq_op_status(pfvf, cq) || !cq->pend_cqe)
return;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
index 93cac2c2664c..b5d689eeff80 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
@@ -102,7 +102,8 @@ enum cq_type {
CQ_RX,
CQ_TX,
CQ_XDP,
- CQS_PER_CINT = 3, /* RQ + SQ + XDP */
+ CQ_QOS,
+ CQS_PER_CINT = 4, /* RQ + SQ + XDP + QOS_SQ */
};
struct otx2_cq_poll {
@@ -117,6 +118,7 @@ struct otx2_cq_poll {
struct otx2_pool {
struct qmem *stack;
struct qmem *fc_addr;
+ struct page_pool *page_pool;
u16 rbsize;
};
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
index 53366dbfbf27..35e06048356f 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
@@ -70,10 +70,6 @@ static void otx2vf_process_vfaf_mbox_msg(struct otx2_nic *vf,
case MBOX_MSG_NIX_LF_ALLOC:
mbox_handler_nix_lf_alloc(vf, (struct nix_lf_alloc_rsp *)msg);
break;
- case MBOX_MSG_NIX_TXSCH_ALLOC:
- mbox_handler_nix_txsch_alloc(vf,
- (struct nix_txsch_alloc_rsp *)msg);
- break;
case MBOX_MSG_NIX_BP_ENABLE:
mbox_handler_nix_bp_enable(vf, (struct nix_bp_cfg_rsp *)msg);
break;
@@ -297,9 +293,8 @@ static int otx2vf_vfaf_mbox_init(struct otx2_nic *vf)
int err;
mbox->pfvf = vf;
- vf->mbox_wq = alloc_workqueue("otx2_vfaf_mailbox",
- WQ_UNBOUND | WQ_HIGHPRI |
- WQ_MEM_RECLAIM, 1);
+ vf->mbox_wq = alloc_ordered_workqueue("otx2_vfaf_mailbox",
+ WQ_HIGHPRI | WQ_MEM_RECLAIM);
if (!vf->mbox_wq)
return -ENOMEM;
@@ -479,6 +474,7 @@ static const struct net_device_ops otx2vf_netdev_ops = {
.ndo_open = otx2vf_open,
.ndo_stop = otx2vf_stop,
.ndo_start_xmit = otx2vf_xmit,
+ .ndo_select_queue = otx2_select_queue,
.ndo_set_rx_mode = otx2vf_set_rx_mode,
.ndo_set_mac_address = otx2_set_mac_address,
.ndo_change_mtu = otx2vf_change_mtu,
@@ -524,10 +520,10 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
int num_vec = pci_msix_vec_count(pdev);
struct device *dev = &pdev->dev;
+ int err, qcount, qos_txqs;
struct net_device *netdev;
struct otx2_nic *vf;
struct otx2_hw *hw;
- int err, qcount;
err = pcim_enable_device(pdev);
if (err) {
@@ -550,7 +546,8 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_master(pdev);
qcount = num_online_cpus();
- netdev = alloc_etherdev_mqs(sizeof(*vf), qcount, qcount);
+ qos_txqs = min_t(int, qcount, OTX2_QOS_MAX_LEAF_NODES);
+ netdev = alloc_etherdev_mqs(sizeof(*vf), qcount + qos_txqs, qcount);
if (!netdev) {
err = -ENOMEM;
goto err_release_regions;
@@ -570,7 +567,7 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hw->rx_queues = qcount;
hw->tx_queues = qcount;
hw->max_queues = qcount;
- hw->tot_tx_queues = qcount;
+ hw->non_qos_queues = qcount;
hw->rbuf_len = OTX2_DEFAULT_RBUF_LEN;
/* Use CQE of 128 byte descriptor size by default */
hw->xqe_size = 128;
@@ -699,6 +696,7 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (err)
goto err_shutdown_tc;
#endif
+ otx2_qos_init(vf, qos_txqs);
return 0;
@@ -761,6 +759,7 @@ static void otx2vf_remove(struct pci_dev *pdev)
otx2_ptp_destroy(vf);
otx2_mcam_flow_del(vf);
otx2_shutdown_tc(vf);
+ otx2_shutdown_qos(vf);
otx2vf_disable_mbox_intr(vf);
otx2_detach_resources(&vf->mbox);
free_percpu(vf->hw.lmt_info);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c
new file mode 100644
index 000000000000..d3a76c5ccda8
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c
@@ -0,0 +1,1363 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Marvell RVU Ethernet driver
+ *
+ * Copyright (C) 2023 Marvell.
+ *
+ */
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/bitfield.h>
+
+#include "otx2_common.h"
+#include "cn10k.h"
+#include "qos.h"
+
+#define OTX2_QOS_QID_INNER 0xFFFFU
+#define OTX2_QOS_QID_NONE 0xFFFEU
+#define OTX2_QOS_ROOT_CLASSID 0xFFFFFFFF
+#define OTX2_QOS_CLASS_NONE 0
+#define OTX2_QOS_DEFAULT_PRIO 0xF
+#define OTX2_QOS_INVALID_SQ 0xFFFF
+
+static void otx2_qos_update_tx_netdev_queues(struct otx2_nic *pfvf)
+{
+ struct otx2_hw *hw = &pfvf->hw;
+ int tx_queues, qos_txqs, err;
+
+ qos_txqs = bitmap_weight(pfvf->qos.qos_sq_bmap,
+ OTX2_QOS_MAX_LEAF_NODES);
+
+ tx_queues = hw->tx_queues + qos_txqs;
+
+ err = netif_set_real_num_tx_queues(pfvf->netdev, tx_queues);
+ if (err) {
+ netdev_err(pfvf->netdev,
+ "Failed to set no of Tx queues: %d\n", tx_queues);
+ return;
+ }
+}
+
+static void otx2_qos_get_regaddr(struct otx2_qos_node *node,
+ struct nix_txschq_config *cfg,
+ int index)
+{
+ if (node->level == NIX_TXSCH_LVL_SMQ) {
+ cfg->reg[index++] = NIX_AF_MDQX_PARENT(node->schq);
+ cfg->reg[index++] = NIX_AF_MDQX_SCHEDULE(node->schq);
+ cfg->reg[index++] = NIX_AF_MDQX_PIR(node->schq);
+ cfg->reg[index] = NIX_AF_MDQX_CIR(node->schq);
+ } else if (node->level == NIX_TXSCH_LVL_TL4) {
+ cfg->reg[index++] = NIX_AF_TL4X_PARENT(node->schq);
+ cfg->reg[index++] = NIX_AF_TL4X_SCHEDULE(node->schq);
+ cfg->reg[index++] = NIX_AF_TL4X_PIR(node->schq);
+ cfg->reg[index] = NIX_AF_TL4X_CIR(node->schq);
+ } else if (node->level == NIX_TXSCH_LVL_TL3) {
+ cfg->reg[index++] = NIX_AF_TL3X_PARENT(node->schq);
+ cfg->reg[index++] = NIX_AF_TL3X_SCHEDULE(node->schq);
+ cfg->reg[index++] = NIX_AF_TL3X_PIR(node->schq);
+ cfg->reg[index] = NIX_AF_TL3X_CIR(node->schq);
+ } else if (node->level == NIX_TXSCH_LVL_TL2) {
+ cfg->reg[index++] = NIX_AF_TL2X_PARENT(node->schq);
+ cfg->reg[index++] = NIX_AF_TL2X_SCHEDULE(node->schq);
+ cfg->reg[index++] = NIX_AF_TL2X_PIR(node->schq);
+ cfg->reg[index] = NIX_AF_TL2X_CIR(node->schq);
+ }
+}
+
+static void otx2_config_sched_shaping(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct nix_txschq_config *cfg,
+ int *num_regs)
+{
+ u64 maxrate;
+
+ otx2_qos_get_regaddr(node, cfg, *num_regs);
+
+ /* configure parent txschq */
+ cfg->regval[*num_regs] = node->parent->schq << 16;
+ (*num_regs)++;
+
+ /* configure prio/quantum */
+ if (node->qid == OTX2_QOS_QID_NONE) {
+ cfg->regval[*num_regs] = node->prio << 24 |
+ mtu_to_dwrr_weight(pfvf, pfvf->tx_max_pktlen);
+ (*num_regs)++;
+ return;
+ }
+
+ /* configure priority */
+ cfg->regval[*num_regs] = (node->schq - node->parent->prio_anchor) << 24;
+ (*num_regs)++;
+
+ /* configure PIR */
+ maxrate = (node->rate > node->ceil) ? node->rate : node->ceil;
+
+ cfg->regval[*num_regs] =
+ otx2_get_txschq_rate_regval(pfvf, maxrate, 65536);
+ (*num_regs)++;
+
+ /* Don't configure CIR when both CIR+PIR not supported
+ * On 96xx, CIR + PIR + RED_ALGO=STALL causes deadlock
+ */
+ if (!test_bit(QOS_CIR_PIR_SUPPORT, &pfvf->hw.cap_flag))
+ return;
+
+ cfg->regval[*num_regs] =
+ otx2_get_txschq_rate_regval(pfvf, node->rate, 65536);
+ (*num_regs)++;
+}
+
+static void __otx2_qos_txschq_cfg(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct nix_txschq_config *cfg)
+{
+ struct otx2_hw *hw = &pfvf->hw;
+ int num_regs = 0;
+ u8 level;
+
+ level = node->level;
+
+ /* program txschq registers */
+ if (level == NIX_TXSCH_LVL_SMQ) {
+ cfg->reg[num_regs] = NIX_AF_SMQX_CFG(node->schq);
+ cfg->regval[num_regs] = ((u64)pfvf->tx_max_pktlen << 8) |
+ OTX2_MIN_MTU;
+ cfg->regval[num_regs] |= (0x20ULL << 51) | (0x80ULL << 39) |
+ (0x2ULL << 36);
+ num_regs++;
+
+ otx2_config_sched_shaping(pfvf, node, cfg, &num_regs);
+
+ } else if (level == NIX_TXSCH_LVL_TL4) {
+ otx2_config_sched_shaping(pfvf, node, cfg, &num_regs);
+ } else if (level == NIX_TXSCH_LVL_TL3) {
+ /* configure link cfg */
+ if (level == pfvf->qos.link_cfg_lvl) {
+ cfg->reg[num_regs] = NIX_AF_TL3_TL2X_LINKX_CFG(node->schq, hw->tx_link);
+ cfg->regval[num_regs] = BIT_ULL(13) | BIT_ULL(12);
+ num_regs++;
+ }
+
+ otx2_config_sched_shaping(pfvf, node, cfg, &num_regs);
+ } else if (level == NIX_TXSCH_LVL_TL2) {
+ /* configure link cfg */
+ if (level == pfvf->qos.link_cfg_lvl) {
+ cfg->reg[num_regs] = NIX_AF_TL3_TL2X_LINKX_CFG(node->schq, hw->tx_link);
+ cfg->regval[num_regs] = BIT_ULL(13) | BIT_ULL(12);
+ num_regs++;
+ }
+
+ /* check if node is root */
+ if (node->qid == OTX2_QOS_QID_INNER && !node->parent) {
+ cfg->reg[num_regs] = NIX_AF_TL2X_SCHEDULE(node->schq);
+ cfg->regval[num_regs] = TXSCH_TL1_DFLT_RR_PRIO << 24 |
+ mtu_to_dwrr_weight(pfvf,
+ pfvf->tx_max_pktlen);
+ num_regs++;
+ goto txschq_cfg_out;
+ }
+
+ otx2_config_sched_shaping(pfvf, node, cfg, &num_regs);
+ }
+
+txschq_cfg_out:
+ cfg->num_regs = num_regs;
+}
+
+static int otx2_qos_txschq_set_parent_topology(struct otx2_nic *pfvf,
+ struct otx2_qos_node *parent)
+{
+ struct mbox *mbox = &pfvf->mbox;
+ struct nix_txschq_config *cfg;
+ int rc;
+
+ if (parent->level == NIX_TXSCH_LVL_MDQ)
+ return 0;
+
+ mutex_lock(&mbox->lock);
+
+ cfg = otx2_mbox_alloc_msg_nix_txschq_cfg(&pfvf->mbox);
+ if (!cfg) {
+ mutex_unlock(&mbox->lock);
+ return -ENOMEM;
+ }
+
+ cfg->lvl = parent->level;
+
+ if (parent->level == NIX_TXSCH_LVL_TL4)
+ cfg->reg[0] = NIX_AF_TL4X_TOPOLOGY(parent->schq);
+ else if (parent->level == NIX_TXSCH_LVL_TL3)
+ cfg->reg[0] = NIX_AF_TL3X_TOPOLOGY(parent->schq);
+ else if (parent->level == NIX_TXSCH_LVL_TL2)
+ cfg->reg[0] = NIX_AF_TL2X_TOPOLOGY(parent->schq);
+ else if (parent->level == NIX_TXSCH_LVL_TL1)
+ cfg->reg[0] = NIX_AF_TL1X_TOPOLOGY(parent->schq);
+
+ cfg->regval[0] = (u64)parent->prio_anchor << 32;
+ if (parent->level == NIX_TXSCH_LVL_TL1)
+ cfg->regval[0] |= (u64)TXSCH_TL1_DFLT_RR_PRIO << 1;
+
+ cfg->num_regs++;
+
+ rc = otx2_sync_mbox_msg(&pfvf->mbox);
+
+ mutex_unlock(&mbox->lock);
+
+ return rc;
+}
+
+static void otx2_qos_free_hw_node_schq(struct otx2_nic *pfvf,
+ struct otx2_qos_node *parent)
+{
+ struct otx2_qos_node *node;
+
+ list_for_each_entry_reverse(node, &parent->child_schq_list, list)
+ otx2_txschq_free_one(pfvf, node->level, node->schq);
+}
+
+static void otx2_qos_free_hw_node(struct otx2_nic *pfvf,
+ struct otx2_qos_node *parent)
+{
+ struct otx2_qos_node *node, *tmp;
+
+ list_for_each_entry_safe(node, tmp, &parent->child_list, list) {
+ otx2_qos_free_hw_node(pfvf, node);
+ otx2_qos_free_hw_node_schq(pfvf, node);
+ otx2_txschq_free_one(pfvf, node->level, node->schq);
+ }
+}
+
+static void otx2_qos_free_hw_cfg(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node)
+{
+ mutex_lock(&pfvf->qos.qos_lock);
+
+ /* free child node hw mappings */
+ otx2_qos_free_hw_node(pfvf, node);
+ otx2_qos_free_hw_node_schq(pfvf, node);
+
+ /* free node hw mappings */
+ otx2_txschq_free_one(pfvf, node->level, node->schq);
+
+ mutex_unlock(&pfvf->qos.qos_lock);
+}
+
+static void otx2_qos_sw_node_delete(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node)
+{
+ hash_del_rcu(&node->hlist);
+
+ if (node->qid != OTX2_QOS_QID_INNER && node->qid != OTX2_QOS_QID_NONE) {
+ __clear_bit(node->qid, pfvf->qos.qos_sq_bmap);
+ otx2_qos_update_tx_netdev_queues(pfvf);
+ }
+
+ list_del(&node->list);
+ kfree(node);
+}
+
+static void otx2_qos_free_sw_node_schq(struct otx2_nic *pfvf,
+ struct otx2_qos_node *parent)
+{
+ struct otx2_qos_node *node, *tmp;
+
+ list_for_each_entry_safe(node, tmp, &parent->child_schq_list, list) {
+ list_del(&node->list);
+ kfree(node);
+ }
+}
+
+static void __otx2_qos_free_sw_node(struct otx2_nic *pfvf,
+ struct otx2_qos_node *parent)
+{
+ struct otx2_qos_node *node, *tmp;
+
+ list_for_each_entry_safe(node, tmp, &parent->child_list, list) {
+ __otx2_qos_free_sw_node(pfvf, node);
+ otx2_qos_free_sw_node_schq(pfvf, node);
+ otx2_qos_sw_node_delete(pfvf, node);
+ }
+}
+
+static void otx2_qos_free_sw_node(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node)
+{
+ mutex_lock(&pfvf->qos.qos_lock);
+
+ __otx2_qos_free_sw_node(pfvf, node);
+ otx2_qos_free_sw_node_schq(pfvf, node);
+ otx2_qos_sw_node_delete(pfvf, node);
+
+ mutex_unlock(&pfvf->qos.qos_lock);
+}
+
+static void otx2_qos_destroy_node(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node)
+{
+ otx2_qos_free_hw_cfg(pfvf, node);
+ otx2_qos_free_sw_node(pfvf, node);
+}
+
+static void otx2_qos_fill_cfg_schq(struct otx2_qos_node *parent,
+ struct otx2_qos_cfg *cfg)
+{
+ struct otx2_qos_node *node;
+
+ list_for_each_entry(node, &parent->child_schq_list, list)
+ cfg->schq[node->level]++;
+}
+
+static void otx2_qos_fill_cfg_tl(struct otx2_qos_node *parent,
+ struct otx2_qos_cfg *cfg)
+{
+ struct otx2_qos_node *node;
+
+ list_for_each_entry(node, &parent->child_list, list) {
+ otx2_qos_fill_cfg_tl(node, cfg);
+ cfg->schq_contig[node->level]++;
+ otx2_qos_fill_cfg_schq(node, cfg);
+ }
+}
+
+static void otx2_qos_prepare_txschq_cfg(struct otx2_nic *pfvf,
+ struct otx2_qos_node *parent,
+ struct otx2_qos_cfg *cfg)
+{
+ mutex_lock(&pfvf->qos.qos_lock);
+ otx2_qos_fill_cfg_tl(parent, cfg);
+ mutex_unlock(&pfvf->qos.qos_lock);
+}
+
+static void otx2_qos_read_txschq_cfg_schq(struct otx2_qos_node *parent,
+ struct otx2_qos_cfg *cfg)
+{
+ struct otx2_qos_node *node;
+ int cnt;
+
+ list_for_each_entry(node, &parent->child_schq_list, list) {
+ cnt = cfg->dwrr_node_pos[node->level];
+ cfg->schq_list[node->level][cnt] = node->schq;
+ cfg->schq[node->level]++;
+ cfg->dwrr_node_pos[node->level]++;
+ }
+}
+
+static void otx2_qos_read_txschq_cfg_tl(struct otx2_qos_node *parent,
+ struct otx2_qos_cfg *cfg)
+{
+ struct otx2_qos_node *node;
+ int cnt;
+
+ list_for_each_entry(node, &parent->child_list, list) {
+ otx2_qos_read_txschq_cfg_tl(node, cfg);
+ cnt = cfg->static_node_pos[node->level];
+ cfg->schq_contig_list[node->level][cnt] = node->schq;
+ cfg->schq_contig[node->level]++;
+ cfg->static_node_pos[node->level]++;
+ otx2_qos_read_txschq_cfg_schq(node, cfg);
+ }
+}
+
+static void otx2_qos_read_txschq_cfg(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ mutex_lock(&pfvf->qos.qos_lock);
+ otx2_qos_read_txschq_cfg_tl(node, cfg);
+ mutex_unlock(&pfvf->qos.qos_lock);
+}
+
+static struct otx2_qos_node *
+otx2_qos_alloc_root(struct otx2_nic *pfvf)
+{
+ struct otx2_qos_node *node;
+
+ node = kzalloc(sizeof(*node), GFP_KERNEL);
+ if (!node)
+ return ERR_PTR(-ENOMEM);
+
+ node->parent = NULL;
+ if (!is_otx2_vf(pfvf->pcifunc))
+ node->level = NIX_TXSCH_LVL_TL1;
+ else
+ node->level = NIX_TXSCH_LVL_TL2;
+
+ WRITE_ONCE(node->qid, OTX2_QOS_QID_INNER);
+ node->classid = OTX2_QOS_ROOT_CLASSID;
+
+ hash_add_rcu(pfvf->qos.qos_hlist, &node->hlist, node->classid);
+ list_add_tail(&node->list, &pfvf->qos.qos_tree);
+ INIT_LIST_HEAD(&node->child_list);
+ INIT_LIST_HEAD(&node->child_schq_list);
+
+ return node;
+}
+
+static int otx2_qos_add_child_node(struct otx2_qos_node *parent,
+ struct otx2_qos_node *node)
+{
+ struct list_head *head = &parent->child_list;
+ struct otx2_qos_node *tmp_node;
+ struct list_head *tmp;
+
+ for (tmp = head->next; tmp != head; tmp = tmp->next) {
+ tmp_node = list_entry(tmp, struct otx2_qos_node, list);
+ if (tmp_node->prio == node->prio)
+ return -EEXIST;
+ if (tmp_node->prio > node->prio) {
+ list_add_tail(&node->list, tmp);
+ return 0;
+ }
+ }
+
+ list_add_tail(&node->list, head);
+ return 0;
+}
+
+static int otx2_qos_alloc_txschq_node(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node)
+{
+ struct otx2_qos_node *txschq_node, *parent, *tmp;
+ int lvl;
+
+ parent = node;
+ for (lvl = node->level - 1; lvl >= NIX_TXSCH_LVL_MDQ; lvl--) {
+ txschq_node = kzalloc(sizeof(*txschq_node), GFP_KERNEL);
+ if (!txschq_node)
+ goto err_out;
+
+ txschq_node->parent = parent;
+ txschq_node->level = lvl;
+ txschq_node->classid = OTX2_QOS_CLASS_NONE;
+ WRITE_ONCE(txschq_node->qid, OTX2_QOS_QID_NONE);
+ txschq_node->rate = 0;
+ txschq_node->ceil = 0;
+ txschq_node->prio = 0;
+
+ mutex_lock(&pfvf->qos.qos_lock);
+ list_add_tail(&txschq_node->list, &node->child_schq_list);
+ mutex_unlock(&pfvf->qos.qos_lock);
+
+ INIT_LIST_HEAD(&txschq_node->child_list);
+ INIT_LIST_HEAD(&txschq_node->child_schq_list);
+ parent = txschq_node;
+ }
+
+ return 0;
+
+err_out:
+ list_for_each_entry_safe(txschq_node, tmp, &node->child_schq_list,
+ list) {
+ list_del(&txschq_node->list);
+ kfree(txschq_node);
+ }
+ return -ENOMEM;
+}
+
+static struct otx2_qos_node *
+otx2_qos_sw_create_leaf_node(struct otx2_nic *pfvf,
+ struct otx2_qos_node *parent,
+ u16 classid, u32 prio, u64 rate, u64 ceil,
+ u16 qid)
+{
+ struct otx2_qos_node *node;
+ int err;
+
+ node = kzalloc(sizeof(*node), GFP_KERNEL);
+ if (!node)
+ return ERR_PTR(-ENOMEM);
+
+ node->parent = parent;
+ node->level = parent->level - 1;
+ node->classid = classid;
+ WRITE_ONCE(node->qid, qid);
+
+ node->rate = otx2_convert_rate(rate);
+ node->ceil = otx2_convert_rate(ceil);
+ node->prio = prio;
+
+ __set_bit(qid, pfvf->qos.qos_sq_bmap);
+
+ hash_add_rcu(pfvf->qos.qos_hlist, &node->hlist, classid);
+
+ mutex_lock(&pfvf->qos.qos_lock);
+ err = otx2_qos_add_child_node(parent, node);
+ if (err) {
+ mutex_unlock(&pfvf->qos.qos_lock);
+ return ERR_PTR(err);
+ }
+ mutex_unlock(&pfvf->qos.qos_lock);
+
+ INIT_LIST_HEAD(&node->child_list);
+ INIT_LIST_HEAD(&node->child_schq_list);
+
+ err = otx2_qos_alloc_txschq_node(pfvf, node);
+ if (err) {
+ otx2_qos_sw_node_delete(pfvf, node);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ return node;
+}
+
+static struct otx2_qos_node *
+otx2_sw_node_find(struct otx2_nic *pfvf, u32 classid)
+{
+ struct otx2_qos_node *node = NULL;
+
+ hash_for_each_possible(pfvf->qos.qos_hlist, node, hlist, classid) {
+ if (node->classid == classid)
+ break;
+ }
+
+ return node;
+}
+
+static struct otx2_qos_node *
+otx2_sw_node_find_rcu(struct otx2_nic *pfvf, u32 classid)
+{
+ struct otx2_qos_node *node = NULL;
+
+ hash_for_each_possible_rcu(pfvf->qos.qos_hlist, node, hlist, classid) {
+ if (node->classid == classid)
+ break;
+ }
+
+ return node;
+}
+
+int otx2_get_txq_by_classid(struct otx2_nic *pfvf, u16 classid)
+{
+ struct otx2_qos_node *node;
+ u16 qid;
+ int res;
+
+ node = otx2_sw_node_find_rcu(pfvf, classid);
+ if (!node) {
+ res = -ENOENT;
+ goto out;
+ }
+ qid = READ_ONCE(node->qid);
+ if (qid == OTX2_QOS_QID_INNER) {
+ res = -EINVAL;
+ goto out;
+ }
+ res = pfvf->hw.tx_queues + qid;
+out:
+ return res;
+}
+
+static int
+otx2_qos_txschq_config(struct otx2_nic *pfvf, struct otx2_qos_node *node)
+{
+ struct mbox *mbox = &pfvf->mbox;
+ struct nix_txschq_config *req;
+ int rc;
+
+ mutex_lock(&mbox->lock);
+
+ req = otx2_mbox_alloc_msg_nix_txschq_cfg(&pfvf->mbox);
+ if (!req) {
+ mutex_unlock(&mbox->lock);
+ return -ENOMEM;
+ }
+
+ req->lvl = node->level;
+ __otx2_qos_txschq_cfg(pfvf, node, req);
+
+ rc = otx2_sync_mbox_msg(&pfvf->mbox);
+
+ mutex_unlock(&mbox->lock);
+
+ return rc;
+}
+
+static int otx2_qos_txschq_alloc(struct otx2_nic *pfvf,
+ struct otx2_qos_cfg *cfg)
+{
+ struct nix_txsch_alloc_req *req;
+ struct nix_txsch_alloc_rsp *rsp;
+ struct mbox *mbox = &pfvf->mbox;
+ int lvl, rc, schq;
+
+ mutex_lock(&mbox->lock);
+ req = otx2_mbox_alloc_msg_nix_txsch_alloc(&pfvf->mbox);
+ if (!req) {
+ mutex_unlock(&mbox->lock);
+ return -ENOMEM;
+ }
+
+ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
+ req->schq[lvl] = cfg->schq[lvl];
+ req->schq_contig[lvl] = cfg->schq_contig[lvl];
+ }
+
+ rc = otx2_sync_mbox_msg(&pfvf->mbox);
+ if (rc) {
+ mutex_unlock(&mbox->lock);
+ return rc;
+ }
+
+ rsp = (struct nix_txsch_alloc_rsp *)
+ otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
+
+ if (IS_ERR(rsp)) {
+ rc = PTR_ERR(rsp);
+ goto out;
+ }
+
+ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
+ for (schq = 0; schq < rsp->schq_contig[lvl]; schq++) {
+ cfg->schq_contig_list[lvl][schq] =
+ rsp->schq_contig_list[lvl][schq];
+ }
+ }
+
+ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
+ for (schq = 0; schq < rsp->schq[lvl]; schq++) {
+ cfg->schq_list[lvl][schq] =
+ rsp->schq_list[lvl][schq];
+ }
+ }
+
+ pfvf->qos.link_cfg_lvl = rsp->link_cfg_lvl;
+
+out:
+ mutex_unlock(&mbox->lock);
+ return rc;
+}
+
+static void otx2_qos_txschq_fill_cfg_schq(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ struct otx2_qos_node *tmp;
+ int cnt;
+
+ list_for_each_entry(tmp, &node->child_schq_list, list) {
+ cnt = cfg->dwrr_node_pos[tmp->level];
+ tmp->schq = cfg->schq_list[tmp->level][cnt];
+ cfg->dwrr_node_pos[tmp->level]++;
+ }
+}
+
+static void otx2_qos_txschq_fill_cfg_tl(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ struct otx2_qos_node *tmp;
+ int cnt;
+
+ list_for_each_entry(tmp, &node->child_list, list) {
+ otx2_qos_txschq_fill_cfg_tl(pfvf, tmp, cfg);
+ cnt = cfg->static_node_pos[tmp->level];
+ tmp->schq = cfg->schq_contig_list[tmp->level][cnt];
+ if (cnt == 0)
+ node->prio_anchor = tmp->schq;
+ cfg->static_node_pos[tmp->level]++;
+ otx2_qos_txschq_fill_cfg_schq(pfvf, tmp, cfg);
+ }
+}
+
+static void otx2_qos_txschq_fill_cfg(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ mutex_lock(&pfvf->qos.qos_lock);
+ otx2_qos_txschq_fill_cfg_tl(pfvf, node, cfg);
+ otx2_qos_txschq_fill_cfg_schq(pfvf, node, cfg);
+ mutex_unlock(&pfvf->qos.qos_lock);
+}
+
+static int otx2_qos_txschq_push_cfg_schq(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ struct otx2_qos_node *tmp;
+ int ret;
+
+ list_for_each_entry(tmp, &node->child_schq_list, list) {
+ ret = otx2_qos_txschq_config(pfvf, tmp);
+ if (ret)
+ return -EIO;
+ ret = otx2_qos_txschq_set_parent_topology(pfvf, tmp->parent);
+ if (ret)
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int otx2_qos_txschq_push_cfg_tl(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ struct otx2_qos_node *tmp;
+ int ret;
+
+ list_for_each_entry(tmp, &node->child_list, list) {
+ ret = otx2_qos_txschq_push_cfg_tl(pfvf, tmp, cfg);
+ if (ret)
+ return -EIO;
+ ret = otx2_qos_txschq_config(pfvf, tmp);
+ if (ret)
+ return -EIO;
+ ret = otx2_qos_txschq_push_cfg_schq(pfvf, tmp, cfg);
+ if (ret)
+ return -EIO;
+ }
+
+ ret = otx2_qos_txschq_set_parent_topology(pfvf, node);
+ if (ret)
+ return -EIO;
+
+ return 0;
+}
+
+static int otx2_qos_txschq_push_cfg(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ int ret;
+
+ mutex_lock(&pfvf->qos.qos_lock);
+ ret = otx2_qos_txschq_push_cfg_tl(pfvf, node, cfg);
+ if (ret)
+ goto out;
+ ret = otx2_qos_txschq_push_cfg_schq(pfvf, node, cfg);
+out:
+ mutex_unlock(&pfvf->qos.qos_lock);
+ return ret;
+}
+
+static int otx2_qos_txschq_update_config(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ otx2_qos_txschq_fill_cfg(pfvf, node, cfg);
+
+ return otx2_qos_txschq_push_cfg(pfvf, node, cfg);
+}
+
+static int otx2_qos_txschq_update_root_cfg(struct otx2_nic *pfvf,
+ struct otx2_qos_node *root,
+ struct otx2_qos_cfg *cfg)
+{
+ root->schq = cfg->schq_list[root->level][0];
+ return otx2_qos_txschq_config(pfvf, root);
+}
+
+static void otx2_qos_free_cfg(struct otx2_nic *pfvf, struct otx2_qos_cfg *cfg)
+{
+ int lvl, idx, schq;
+
+ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
+ for (idx = 0; idx < cfg->schq[lvl]; idx++) {
+ schq = cfg->schq_list[lvl][idx];
+ otx2_txschq_free_one(pfvf, lvl, schq);
+ }
+ }
+
+ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
+ for (idx = 0; idx < cfg->schq_contig[lvl]; idx++) {
+ schq = cfg->schq_contig_list[lvl][idx];
+ otx2_txschq_free_one(pfvf, lvl, schq);
+ }
+ }
+}
+
+static void otx2_qos_enadis_sq(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ u16 qid)
+{
+ if (pfvf->qos.qid_to_sqmap[qid] != OTX2_QOS_INVALID_SQ)
+ otx2_qos_disable_sq(pfvf, qid);
+
+ pfvf->qos.qid_to_sqmap[qid] = node->schq;
+ otx2_qos_enable_sq(pfvf, qid);
+}
+
+static void otx2_qos_update_smq_schq(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ bool action)
+{
+ struct otx2_qos_node *tmp;
+
+ if (node->qid == OTX2_QOS_QID_INNER)
+ return;
+
+ list_for_each_entry(tmp, &node->child_schq_list, list) {
+ if (tmp->level == NIX_TXSCH_LVL_MDQ) {
+ if (action == QOS_SMQ_FLUSH)
+ otx2_smq_flush(pfvf, tmp->schq);
+ else
+ otx2_qos_enadis_sq(pfvf, tmp, node->qid);
+ }
+ }
+}
+
+static void __otx2_qos_update_smq(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ bool action)
+{
+ struct otx2_qos_node *tmp;
+
+ list_for_each_entry(tmp, &node->child_list, list) {
+ __otx2_qos_update_smq(pfvf, tmp, action);
+ if (tmp->qid == OTX2_QOS_QID_INNER)
+ continue;
+ if (tmp->level == NIX_TXSCH_LVL_MDQ) {
+ if (action == QOS_SMQ_FLUSH)
+ otx2_smq_flush(pfvf, tmp->schq);
+ else
+ otx2_qos_enadis_sq(pfvf, tmp, tmp->qid);
+ } else {
+ otx2_qos_update_smq_schq(pfvf, tmp, action);
+ }
+ }
+}
+
+static void otx2_qos_update_smq(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ bool action)
+{
+ mutex_lock(&pfvf->qos.qos_lock);
+ __otx2_qos_update_smq(pfvf, node, action);
+ otx2_qos_update_smq_schq(pfvf, node, action);
+ mutex_unlock(&pfvf->qos.qos_lock);
+}
+
+static int otx2_qos_push_txschq_cfg(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ int ret;
+
+ ret = otx2_qos_txschq_alloc(pfvf, cfg);
+ if (ret)
+ return -ENOSPC;
+
+ if (!(pfvf->netdev->flags & IFF_UP)) {
+ otx2_qos_txschq_fill_cfg(pfvf, node, cfg);
+ return 0;
+ }
+
+ ret = otx2_qos_txschq_update_config(pfvf, node, cfg);
+ if (ret) {
+ otx2_qos_free_cfg(pfvf, cfg);
+ return -EIO;
+ }
+
+ otx2_qos_update_smq(pfvf, node, QOS_CFG_SQ);
+
+ return 0;
+}
+
+static int otx2_qos_update_tree(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ otx2_qos_prepare_txschq_cfg(pfvf, node->parent, cfg);
+ return otx2_qos_push_txschq_cfg(pfvf, node->parent, cfg);
+}
+
+static int otx2_qos_root_add(struct otx2_nic *pfvf, u16 htb_maj_id, u16 htb_defcls,
+ struct netlink_ext_ack *extack)
+{
+ struct otx2_qos_cfg *new_cfg;
+ struct otx2_qos_node *root;
+ int err;
+
+ netdev_dbg(pfvf->netdev,
+ "TC_HTB_CREATE: handle=0x%x defcls=0x%x\n",
+ htb_maj_id, htb_defcls);
+
+ root = otx2_qos_alloc_root(pfvf);
+ if (IS_ERR(root)) {
+ err = PTR_ERR(root);
+ return err;
+ }
+
+ /* allocate txschq queue */
+ new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL);
+ if (!new_cfg) {
+ NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
+ err = -ENOMEM;
+ goto free_root_node;
+ }
+ /* allocate htb root node */
+ new_cfg->schq[root->level] = 1;
+ err = otx2_qos_txschq_alloc(pfvf, new_cfg);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack, "Error allocating txschq");
+ goto free_root_node;
+ }
+
+ if (!(pfvf->netdev->flags & IFF_UP) ||
+ root->level == NIX_TXSCH_LVL_TL1) {
+ root->schq = new_cfg->schq_list[root->level][0];
+ goto out;
+ }
+
+ /* update the txschq configuration in hw */
+ err = otx2_qos_txschq_update_root_cfg(pfvf, root, new_cfg);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Error updating txschq configuration");
+ goto txschq_free;
+ }
+
+out:
+ WRITE_ONCE(pfvf->qos.defcls, htb_defcls);
+ /* Pairs with smp_load_acquire() in ndo_select_queue */
+ smp_store_release(&pfvf->qos.maj_id, htb_maj_id);
+ kfree(new_cfg);
+ return 0;
+
+txschq_free:
+ otx2_qos_free_cfg(pfvf, new_cfg);
+free_root_node:
+ kfree(new_cfg);
+ otx2_qos_sw_node_delete(pfvf, root);
+ return err;
+}
+
+static int otx2_qos_root_destroy(struct otx2_nic *pfvf)
+{
+ struct otx2_qos_node *root;
+
+ netdev_dbg(pfvf->netdev, "TC_HTB_DESTROY\n");
+
+ /* find root node */
+ root = otx2_sw_node_find(pfvf, OTX2_QOS_ROOT_CLASSID);
+ if (!root)
+ return -ENOENT;
+
+ /* free the hw mappings */
+ otx2_qos_destroy_node(pfvf, root);
+
+ return 0;
+}
+
+static int otx2_qos_validate_configuration(struct otx2_qos_node *parent,
+ struct netlink_ext_ack *extack,
+ struct otx2_nic *pfvf,
+ u64 prio)
+{
+ if (test_bit(prio, parent->prio_bmap)) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Static priority child with same priority exists");
+ return -EEXIST;
+ }
+
+ if (prio == TXSCH_TL1_DFLT_RR_PRIO) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Priority is reserved for Round Robin");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int otx2_qos_leaf_alloc_queue(struct otx2_nic *pfvf, u16 classid,
+ u32 parent_classid, u64 rate, u64 ceil,
+ u64 prio, struct netlink_ext_ack *extack)
+{
+ struct otx2_qos_cfg *old_cfg, *new_cfg;
+ struct otx2_qos_node *node, *parent;
+ int qid, ret, err;
+
+ netdev_dbg(pfvf->netdev,
+ "TC_HTB_LEAF_ALLOC_QUEUE: classid=0x%x parent_classid=0x%x rate=%lld ceil=%lld prio=%lld\n",
+ classid, parent_classid, rate, ceil, prio);
+
+ if (prio > OTX2_QOS_MAX_PRIO) {
+ NL_SET_ERR_MSG_MOD(extack, "Valid priority range 0 to 7");
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ /* get parent node */
+ parent = otx2_sw_node_find(pfvf, parent_classid);
+ if (!parent) {
+ NL_SET_ERR_MSG_MOD(extack, "parent node not found");
+ ret = -ENOENT;
+ goto out;
+ }
+ if (parent->level == NIX_TXSCH_LVL_MDQ) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB qos max levels reached");
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ ret = otx2_qos_validate_configuration(parent, extack, pfvf, prio);
+ if (ret)
+ goto out;
+
+ set_bit(prio, parent->prio_bmap);
+
+ /* read current txschq configuration */
+ old_cfg = kzalloc(sizeof(*old_cfg), GFP_KERNEL);
+ if (!old_cfg) {
+ NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
+ ret = -ENOMEM;
+ goto reset_prio;
+ }
+ otx2_qos_read_txschq_cfg(pfvf, parent, old_cfg);
+
+ /* allocate a new sq */
+ qid = otx2_qos_get_qid(pfvf);
+ if (qid < 0) {
+ NL_SET_ERR_MSG_MOD(extack, "Reached max supported QOS SQ's");
+ ret = -ENOMEM;
+ goto free_old_cfg;
+ }
+
+ /* Actual SQ mapping will be updated after SMQ alloc */
+ pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ;
+
+ /* allocate and initialize a new child node */
+ node = otx2_qos_sw_create_leaf_node(pfvf, parent, classid, prio, rate,
+ ceil, qid);
+ if (IS_ERR(node)) {
+ NL_SET_ERR_MSG_MOD(extack, "Unable to allocate leaf node");
+ ret = PTR_ERR(node);
+ goto free_old_cfg;
+ }
+
+ /* push new txschq config to hw */
+ new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL);
+ if (!new_cfg) {
+ NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
+ ret = -ENOMEM;
+ goto free_node;
+ }
+ ret = otx2_qos_update_tree(pfvf, node, new_cfg);
+ if (ret) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB HW configuration error");
+ kfree(new_cfg);
+ otx2_qos_sw_node_delete(pfvf, node);
+ /* restore the old qos tree */
+ err = otx2_qos_txschq_update_config(pfvf, parent, old_cfg);
+ if (err) {
+ netdev_err(pfvf->netdev,
+ "Failed to restore txcshq configuration");
+ goto free_old_cfg;
+ }
+
+ otx2_qos_update_smq(pfvf, parent, QOS_CFG_SQ);
+ goto free_old_cfg;
+ }
+
+ /* update tx_real_queues */
+ otx2_qos_update_tx_netdev_queues(pfvf);
+
+ /* free new txschq config */
+ kfree(new_cfg);
+
+ /* free old txschq config */
+ otx2_qos_free_cfg(pfvf, old_cfg);
+ kfree(old_cfg);
+
+ return pfvf->hw.tx_queues + qid;
+
+free_node:
+ otx2_qos_sw_node_delete(pfvf, node);
+free_old_cfg:
+ kfree(old_cfg);
+reset_prio:
+ clear_bit(prio, parent->prio_bmap);
+out:
+ return ret;
+}
+
+static int otx2_qos_leaf_to_inner(struct otx2_nic *pfvf, u16 classid,
+ u16 child_classid, u64 rate, u64 ceil, u64 prio,
+ struct netlink_ext_ack *extack)
+{
+ struct otx2_qos_cfg *old_cfg, *new_cfg;
+ struct otx2_qos_node *node, *child;
+ int ret, err;
+ u16 qid;
+
+ netdev_dbg(pfvf->netdev,
+ "TC_HTB_LEAF_TO_INNER classid %04x, child %04x, rate %llu, ceil %llu\n",
+ classid, child_classid, rate, ceil);
+
+ if (prio > OTX2_QOS_MAX_PRIO) {
+ NL_SET_ERR_MSG_MOD(extack, "Valid priority range 0 to 7");
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ /* find node related to classid */
+ node = otx2_sw_node_find(pfvf, classid);
+ if (!node) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB node not found");
+ ret = -ENOENT;
+ goto out;
+ }
+ /* check max qos txschq level */
+ if (node->level == NIX_TXSCH_LVL_MDQ) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB qos level not supported");
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ set_bit(prio, node->prio_bmap);
+
+ /* store the qid to assign to leaf node */
+ qid = node->qid;
+
+ /* read current txschq configuration */
+ old_cfg = kzalloc(sizeof(*old_cfg), GFP_KERNEL);
+ if (!old_cfg) {
+ NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
+ ret = -ENOMEM;
+ goto reset_prio;
+ }
+ otx2_qos_read_txschq_cfg(pfvf, node, old_cfg);
+
+ /* delete the txschq nodes allocated for this node */
+ otx2_qos_free_sw_node_schq(pfvf, node);
+
+ /* mark this node as htb inner node */
+ WRITE_ONCE(node->qid, OTX2_QOS_QID_INNER);
+
+ /* allocate and initialize a new child node */
+ child = otx2_qos_sw_create_leaf_node(pfvf, node, child_classid,
+ prio, rate, ceil, qid);
+ if (IS_ERR(child)) {
+ NL_SET_ERR_MSG_MOD(extack, "Unable to allocate leaf node");
+ ret = PTR_ERR(child);
+ goto free_old_cfg;
+ }
+
+ /* push new txschq config to hw */
+ new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL);
+ if (!new_cfg) {
+ NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
+ ret = -ENOMEM;
+ goto free_node;
+ }
+ ret = otx2_qos_update_tree(pfvf, child, new_cfg);
+ if (ret) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB HW configuration error");
+ kfree(new_cfg);
+ otx2_qos_sw_node_delete(pfvf, child);
+ /* restore the old qos tree */
+ WRITE_ONCE(node->qid, qid);
+ err = otx2_qos_alloc_txschq_node(pfvf, node);
+ if (err) {
+ netdev_err(pfvf->netdev,
+ "Failed to restore old leaf node");
+ goto free_old_cfg;
+ }
+ err = otx2_qos_txschq_update_config(pfvf, node, old_cfg);
+ if (err) {
+ netdev_err(pfvf->netdev,
+ "Failed to restore txcshq configuration");
+ goto free_old_cfg;
+ }
+ otx2_qos_update_smq(pfvf, node, QOS_CFG_SQ);
+ goto free_old_cfg;
+ }
+
+ /* free new txschq config */
+ kfree(new_cfg);
+
+ /* free old txschq config */
+ otx2_qos_free_cfg(pfvf, old_cfg);
+ kfree(old_cfg);
+
+ return 0;
+
+free_node:
+ otx2_qos_sw_node_delete(pfvf, child);
+free_old_cfg:
+ kfree(old_cfg);
+reset_prio:
+ clear_bit(prio, node->prio_bmap);
+out:
+ return ret;
+}
+
+static int otx2_qos_leaf_del(struct otx2_nic *pfvf, u16 *classid,
+ struct netlink_ext_ack *extack)
+{
+ struct otx2_qos_node *node, *parent;
+ u64 prio;
+ u16 qid;
+
+ netdev_dbg(pfvf->netdev, "TC_HTB_LEAF_DEL classid %04x\n", *classid);
+
+ /* find node related to classid */
+ node = otx2_sw_node_find(pfvf, *classid);
+ if (!node) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB node not found");
+ return -ENOENT;
+ }
+ parent = node->parent;
+ prio = node->prio;
+ qid = node->qid;
+
+ otx2_qos_disable_sq(pfvf, node->qid);
+
+ otx2_qos_destroy_node(pfvf, node);
+ pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ;
+
+ clear_bit(prio, parent->prio_bmap);
+
+ return 0;
+}
+
+static int otx2_qos_leaf_del_last(struct otx2_nic *pfvf, u16 classid, bool force,
+ struct netlink_ext_ack *extack)
+{
+ struct otx2_qos_node *node, *parent;
+ struct otx2_qos_cfg *new_cfg;
+ u64 prio;
+ int err;
+ u16 qid;
+
+ netdev_dbg(pfvf->netdev,
+ "TC_HTB_LEAF_DEL_LAST classid %04x\n", classid);
+
+ /* find node related to classid */
+ node = otx2_sw_node_find(pfvf, classid);
+ if (!node) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB node not found");
+ return -ENOENT;
+ }
+
+ /* save qid for use by parent */
+ qid = node->qid;
+ prio = node->prio;
+
+ parent = otx2_sw_node_find(pfvf, node->parent->classid);
+ if (!parent) {
+ NL_SET_ERR_MSG_MOD(extack, "parent node not found");
+ return -ENOENT;
+ }
+
+ /* destroy the leaf node */
+ otx2_qos_destroy_node(pfvf, node);
+ pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ;
+
+ clear_bit(prio, parent->prio_bmap);
+
+ /* create downstream txschq entries to parent */
+ err = otx2_qos_alloc_txschq_node(pfvf, parent);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB failed to create txsch configuration");
+ return err;
+ }
+ WRITE_ONCE(parent->qid, qid);
+ __set_bit(qid, pfvf->qos.qos_sq_bmap);
+
+ /* push new txschq config to hw */
+ new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL);
+ if (!new_cfg) {
+ NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
+ return -ENOMEM;
+ }
+ /* fill txschq cfg and push txschq cfg to hw */
+ otx2_qos_fill_cfg_schq(parent, new_cfg);
+ err = otx2_qos_push_txschq_cfg(pfvf, parent, new_cfg);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB HW configuration error");
+ kfree(new_cfg);
+ return err;
+ }
+ kfree(new_cfg);
+
+ /* update tx_real_queues */
+ otx2_qos_update_tx_netdev_queues(pfvf);
+
+ return 0;
+}
+
+void otx2_clean_qos_queues(struct otx2_nic *pfvf)
+{
+ struct otx2_qos_node *root;
+
+ root = otx2_sw_node_find(pfvf, OTX2_QOS_ROOT_CLASSID);
+ if (!root)
+ return;
+
+ otx2_qos_update_smq(pfvf, root, QOS_SMQ_FLUSH);
+}
+
+void otx2_qos_config_txschq(struct otx2_nic *pfvf)
+{
+ struct otx2_qos_node *root;
+ int err;
+
+ root = otx2_sw_node_find(pfvf, OTX2_QOS_ROOT_CLASSID);
+ if (!root)
+ return;
+
+ err = otx2_qos_txschq_config(pfvf, root);
+ if (err) {
+ netdev_err(pfvf->netdev, "Error update txschq configuration\n");
+ goto root_destroy;
+ }
+
+ err = otx2_qos_txschq_push_cfg_tl(pfvf, root, NULL);
+ if (err) {
+ netdev_err(pfvf->netdev, "Error update txschq configuration\n");
+ goto root_destroy;
+ }
+
+ otx2_qos_update_smq(pfvf, root, QOS_CFG_SQ);
+ return;
+
+root_destroy:
+ netdev_err(pfvf->netdev, "Failed to update Scheduler/Shaping config in Hardware\n");
+ /* Free resources allocated */
+ otx2_qos_root_destroy(pfvf);
+}
+
+int otx2_setup_tc_htb(struct net_device *ndev, struct tc_htb_qopt_offload *htb)
+{
+ struct otx2_nic *pfvf = netdev_priv(ndev);
+ int res;
+
+ switch (htb->command) {
+ case TC_HTB_CREATE:
+ return otx2_qos_root_add(pfvf, htb->parent_classid,
+ htb->classid, htb->extack);
+ case TC_HTB_DESTROY:
+ return otx2_qos_root_destroy(pfvf);
+ case TC_HTB_LEAF_ALLOC_QUEUE:
+ res = otx2_qos_leaf_alloc_queue(pfvf, htb->classid,
+ htb->parent_classid,
+ htb->rate, htb->ceil,
+ htb->prio, htb->extack);
+ if (res < 0)
+ return res;
+ htb->qid = res;
+ return 0;
+ case TC_HTB_LEAF_TO_INNER:
+ return otx2_qos_leaf_to_inner(pfvf, htb->parent_classid,
+ htb->classid, htb->rate,
+ htb->ceil, htb->prio,
+ htb->extack);
+ case TC_HTB_LEAF_DEL:
+ return otx2_qos_leaf_del(pfvf, &htb->classid, htb->extack);
+ case TC_HTB_LEAF_DEL_LAST:
+ case TC_HTB_LEAF_DEL_LAST_FORCE:
+ return otx2_qos_leaf_del_last(pfvf, htb->classid,
+ htb->command == TC_HTB_LEAF_DEL_LAST_FORCE,
+ htb->extack);
+ case TC_HTB_LEAF_QUERY_QUEUE:
+ res = otx2_get_txq_by_classid(pfvf, htb->classid);
+ htb->qid = res;
+ return 0;
+ case TC_HTB_NODE_MODIFY:
+ fallthrough;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.h b/drivers/net/ethernet/marvell/octeontx2/nic/qos.h
new file mode 100644
index 000000000000..19773284be27
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Marvell RVU Ethernet driver
+ *
+ * Copyright (C) 2023 Marvell.
+ *
+ */
+#ifndef OTX2_QOS_H
+#define OTX2_QOS_H
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/rhashtable.h>
+
+#define OTX2_QOS_MAX_LVL 4
+#define OTX2_QOS_MAX_PRIO 7
+#define OTX2_QOS_MAX_LEAF_NODES 16
+
+enum qos_smq_operations {
+ QOS_CFG_SQ,
+ QOS_SMQ_FLUSH,
+};
+
+u64 otx2_get_txschq_rate_regval(struct otx2_nic *nic, u64 maxrate, u32 burst);
+
+int otx2_setup_tc_htb(struct net_device *ndev, struct tc_htb_qopt_offload *htb);
+int otx2_qos_get_qid(struct otx2_nic *pfvf);
+void otx2_qos_free_qid(struct otx2_nic *pfvf, int qidx);
+int otx2_qos_enable_sq(struct otx2_nic *pfvf, int qidx);
+void otx2_qos_disable_sq(struct otx2_nic *pfvf, int qidx);
+
+struct otx2_qos_cfg {
+ u16 schq[NIX_TXSCH_LVL_CNT];
+ u16 schq_contig[NIX_TXSCH_LVL_CNT];
+ int static_node_pos[NIX_TXSCH_LVL_CNT];
+ int dwrr_node_pos[NIX_TXSCH_LVL_CNT];
+ u16 schq_contig_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC];
+ u16 schq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC];
+};
+
+struct otx2_qos {
+ DECLARE_HASHTABLE(qos_hlist, order_base_2(OTX2_QOS_MAX_LEAF_NODES));
+ struct mutex qos_lock; /* child list lock */
+ u16 qid_to_sqmap[OTX2_QOS_MAX_LEAF_NODES];
+ struct list_head qos_tree;
+ DECLARE_BITMAP(qos_sq_bmap, OTX2_QOS_MAX_LEAF_NODES);
+ u16 maj_id;
+ u16 defcls;
+ u8 link_cfg_lvl; /* LINKX_CFG CSRs mapped to TL3 or TL2's index ? */
+};
+
+struct otx2_qos_node {
+ struct list_head list; /* list management */
+ struct list_head child_list;
+ struct list_head child_schq_list;
+ struct hlist_node hlist;
+ DECLARE_BITMAP(prio_bmap, OTX2_QOS_MAX_PRIO + 1);
+ struct otx2_qos_node *parent; /* parent qos node */
+ u64 rate; /* htb params */
+ u64 ceil;
+ u32 classid;
+ u32 prio;
+ u16 schq; /* hw txschq */
+ u16 qid;
+ u16 prio_anchor;
+ u8 level;
+};
+
+
+#endif
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos_sq.c b/drivers/net/ethernet/marvell/octeontx2/nic/qos_sq.c
new file mode 100644
index 000000000000..9d887bfc3108
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos_sq.c
@@ -0,0 +1,296 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Marvell RVU Physical Function ethernet driver
+ *
+ * Copyright (C) 2023 Marvell.
+ *
+ */
+
+#include <linux/netdevice.h>
+#include <net/tso.h>
+
+#include "cn10k.h"
+#include "otx2_reg.h"
+#include "otx2_common.h"
+#include "otx2_txrx.h"
+#include "otx2_struct.h"
+
+#define OTX2_QOS_MAX_LEAF_NODES 16
+
+static void otx2_qos_aura_pool_free(struct otx2_nic *pfvf, int pool_id)
+{
+ struct otx2_pool *pool;
+
+ if (!pfvf->qset.pool)
+ return;
+
+ pool = &pfvf->qset.pool[pool_id];
+ qmem_free(pfvf->dev, pool->stack);
+ qmem_free(pfvf->dev, pool->fc_addr);
+ pool->stack = NULL;
+ pool->fc_addr = NULL;
+}
+
+static int otx2_qos_sq_aura_pool_init(struct otx2_nic *pfvf, int qidx)
+{
+ struct otx2_qset *qset = &pfvf->qset;
+ int pool_id, stack_pages, num_sqbs;
+ struct otx2_hw *hw = &pfvf->hw;
+ struct otx2_snd_queue *sq;
+ struct otx2_pool *pool;
+ dma_addr_t bufptr;
+ int err, ptr;
+ u64 iova, pa;
+
+ /* Calculate number of SQBs needed.
+ *
+ * For a 128byte SQE, and 4K size SQB, 31 SQEs will fit in one SQB.
+ * Last SQE is used for pointing to next SQB.
+ */
+ num_sqbs = (hw->sqb_size / 128) - 1;
+ num_sqbs = (qset->sqe_cnt + num_sqbs) / num_sqbs;
+
+ /* Get no of stack pages needed */
+ stack_pages =
+ (num_sqbs + hw->stack_pg_ptrs - 1) / hw->stack_pg_ptrs;
+
+ pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, qidx);
+ pool = &pfvf->qset.pool[pool_id];
+
+ /* Initialize aura context */
+ err = otx2_aura_init(pfvf, pool_id, pool_id, num_sqbs);
+ if (err)
+ return err;
+
+ /* Initialize pool context */
+ err = otx2_pool_init(pfvf, pool_id, stack_pages,
+ num_sqbs, hw->sqb_size, AURA_NIX_SQ);
+ if (err)
+ goto aura_free;
+
+ /* Flush accumulated messages */
+ err = otx2_sync_mbox_msg(&pfvf->mbox);
+ if (err)
+ goto pool_free;
+
+ /* Allocate pointers and free them to aura/pool */
+ sq = &qset->sq[qidx];
+ sq->sqb_count = 0;
+ sq->sqb_ptrs = kcalloc(num_sqbs, sizeof(*sq->sqb_ptrs), GFP_KERNEL);
+ if (!sq->sqb_ptrs) {
+ err = -ENOMEM;
+ goto pool_free;
+ }
+
+ for (ptr = 0; ptr < num_sqbs; ptr++) {
+ err = otx2_alloc_rbuf(pfvf, pool, &bufptr);
+ if (err)
+ goto sqb_free;
+ pfvf->hw_ops->aura_freeptr(pfvf, pool_id, bufptr);
+ sq->sqb_ptrs[sq->sqb_count++] = (u64)bufptr;
+ }
+
+ return 0;
+
+sqb_free:
+ while (ptr--) {
+ if (!sq->sqb_ptrs[ptr])
+ continue;
+ iova = sq->sqb_ptrs[ptr];
+ pa = otx2_iova_to_phys(pfvf->iommu_domain, iova);
+ dma_unmap_page_attrs(pfvf->dev, iova, hw->sqb_size,
+ DMA_FROM_DEVICE,
+ DMA_ATTR_SKIP_CPU_SYNC);
+ put_page(virt_to_page(phys_to_virt(pa)));
+ otx2_aura_allocptr(pfvf, pool_id);
+ }
+ sq->sqb_count = 0;
+ kfree(sq->sqb_ptrs);
+pool_free:
+ qmem_free(pfvf->dev, pool->stack);
+aura_free:
+ qmem_free(pfvf->dev, pool->fc_addr);
+ otx2_mbox_reset(&pfvf->mbox.mbox, 0);
+ return err;
+}
+
+static void otx2_qos_sq_free_sqbs(struct otx2_nic *pfvf, int qidx)
+{
+ struct otx2_qset *qset = &pfvf->qset;
+ struct otx2_hw *hw = &pfvf->hw;
+ struct otx2_snd_queue *sq;
+ u64 iova, pa;
+ int sqb;
+
+ sq = &qset->sq[qidx];
+ if (!sq->sqb_ptrs)
+ return;
+ for (sqb = 0; sqb < sq->sqb_count; sqb++) {
+ if (!sq->sqb_ptrs[sqb])
+ continue;
+ iova = sq->sqb_ptrs[sqb];
+ pa = otx2_iova_to_phys(pfvf->iommu_domain, iova);
+ dma_unmap_page_attrs(pfvf->dev, iova, hw->sqb_size,
+ DMA_FROM_DEVICE,
+ DMA_ATTR_SKIP_CPU_SYNC);
+ put_page(virt_to_page(phys_to_virt(pa)));
+ }
+
+ sq->sqb_count = 0;
+
+ sq = &qset->sq[qidx];
+ qmem_free(pfvf->dev, sq->sqe);
+ qmem_free(pfvf->dev, sq->tso_hdrs);
+ kfree(sq->sg);
+ kfree(sq->sqb_ptrs);
+ qmem_free(pfvf->dev, sq->timestamps);
+
+ memset((void *)sq, 0, sizeof(*sq));
+}
+
+/* send queue id */
+static void otx2_qos_sqb_flush(struct otx2_nic *pfvf, int qidx)
+{
+ int sqe_tail, sqe_head;
+ u64 incr, *ptr, val;
+
+ ptr = (__force u64 *)otx2_get_regaddr(pfvf, NIX_LF_SQ_OP_STATUS);
+ incr = (u64)qidx << 32;
+ val = otx2_atomic64_add(incr, ptr);
+ sqe_head = (val >> 20) & 0x3F;
+ sqe_tail = (val >> 28) & 0x3F;
+ if (sqe_head != sqe_tail)
+ usleep_range(50, 60);
+}
+
+static int otx2_qos_ctx_disable(struct otx2_nic *pfvf, u16 qidx, int aura_id)
+{
+ struct nix_cn10k_aq_enq_req *cn10k_sq_aq;
+ struct npa_aq_enq_req *aura_aq;
+ struct npa_aq_enq_req *pool_aq;
+ struct nix_aq_enq_req *sq_aq;
+
+ if (test_bit(CN10K_LMTST, &pfvf->hw.cap_flag)) {
+ cn10k_sq_aq = otx2_mbox_alloc_msg_nix_cn10k_aq_enq(&pfvf->mbox);
+ if (!cn10k_sq_aq)
+ return -ENOMEM;
+ cn10k_sq_aq->qidx = qidx;
+ cn10k_sq_aq->sq.ena = 0;
+ cn10k_sq_aq->sq_mask.ena = 1;
+ cn10k_sq_aq->ctype = NIX_AQ_CTYPE_SQ;
+ cn10k_sq_aq->op = NIX_AQ_INSTOP_WRITE;
+ } else {
+ sq_aq = otx2_mbox_alloc_msg_nix_aq_enq(&pfvf->mbox);
+ if (!sq_aq)
+ return -ENOMEM;
+ sq_aq->qidx = qidx;
+ sq_aq->sq.ena = 0;
+ sq_aq->sq_mask.ena = 1;
+ sq_aq->ctype = NIX_AQ_CTYPE_SQ;
+ sq_aq->op = NIX_AQ_INSTOP_WRITE;
+ }
+
+ aura_aq = otx2_mbox_alloc_msg_npa_aq_enq(&pfvf->mbox);
+ if (!aura_aq) {
+ otx2_mbox_reset(&pfvf->mbox.mbox, 0);
+ return -ENOMEM;
+ }
+
+ aura_aq->aura_id = aura_id;
+ aura_aq->aura.ena = 0;
+ aura_aq->aura_mask.ena = 1;
+ aura_aq->ctype = NPA_AQ_CTYPE_AURA;
+ aura_aq->op = NPA_AQ_INSTOP_WRITE;
+
+ pool_aq = otx2_mbox_alloc_msg_npa_aq_enq(&pfvf->mbox);
+ if (!pool_aq) {
+ otx2_mbox_reset(&pfvf->mbox.mbox, 0);
+ return -ENOMEM;
+ }
+
+ pool_aq->aura_id = aura_id;
+ pool_aq->pool.ena = 0;
+ pool_aq->pool_mask.ena = 1;
+
+ pool_aq->ctype = NPA_AQ_CTYPE_POOL;
+ pool_aq->op = NPA_AQ_INSTOP_WRITE;
+
+ return otx2_sync_mbox_msg(&pfvf->mbox);
+}
+
+int otx2_qos_get_qid(struct otx2_nic *pfvf)
+{
+ int qidx;
+
+ qidx = find_first_zero_bit(pfvf->qos.qos_sq_bmap,
+ pfvf->hw.tc_tx_queues);
+
+ return qidx == pfvf->hw.tc_tx_queues ? -ENOSPC : qidx;
+}
+
+void otx2_qos_free_qid(struct otx2_nic *pfvf, int qidx)
+{
+ clear_bit(qidx, pfvf->qos.qos_sq_bmap);
+}
+
+int otx2_qos_enable_sq(struct otx2_nic *pfvf, int qidx)
+{
+ struct otx2_hw *hw = &pfvf->hw;
+ int pool_id, sq_idx, err;
+
+ if (pfvf->flags & OTX2_FLAG_INTF_DOWN)
+ return -EPERM;
+
+ sq_idx = hw->non_qos_queues + qidx;
+
+ mutex_lock(&pfvf->mbox.lock);
+ err = otx2_qos_sq_aura_pool_init(pfvf, sq_idx);
+ if (err)
+ goto out;
+
+ pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, sq_idx);
+ err = otx2_sq_init(pfvf, sq_idx, pool_id);
+ if (err)
+ goto out;
+out:
+ mutex_unlock(&pfvf->mbox.lock);
+ return err;
+}
+
+void otx2_qos_disable_sq(struct otx2_nic *pfvf, int qidx)
+{
+ struct otx2_qset *qset = &pfvf->qset;
+ struct otx2_hw *hw = &pfvf->hw;
+ struct otx2_snd_queue *sq;
+ struct otx2_cq_queue *cq;
+ int pool_id, sq_idx;
+
+ sq_idx = hw->non_qos_queues + qidx;
+
+ /* If the DOWN flag is set SQs are already freed */
+ if (pfvf->flags & OTX2_FLAG_INTF_DOWN)
+ return;
+
+ sq = &pfvf->qset.sq[sq_idx];
+ if (!sq->sqb_ptrs)
+ return;
+
+ if (sq_idx < hw->non_qos_queues ||
+ sq_idx >= otx2_get_total_tx_queues(pfvf)) {
+ netdev_err(pfvf->netdev, "Send Queue is not a QoS queue\n");
+ return;
+ }
+
+ cq = &qset->cq[pfvf->hw.rx_queues + sq_idx];
+ pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, sq_idx);
+
+ otx2_qos_sqb_flush(pfvf, sq_idx);
+ otx2_smq_flush(pfvf, otx2_get_smq_idx(pfvf, sq_idx));
+ otx2_cleanup_tx_cqes(pfvf, cq);
+
+ mutex_lock(&pfvf->mbox.lock);
+ otx2_qos_ctx_disable(pfvf, sq_idx, pool_id);
+ mutex_unlock(&pfvf->mbox.lock);
+
+ otx2_qos_sq_free_sqbs(pfvf, sq_idx);
+ otx2_qos_aura_pool_free(pfvf, pool_id);
+}
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_flower.c b/drivers/net/ethernet/marvell/prestera/prestera_flower.c
index 91a478b75cbf..3e20e71b0f81 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_flower.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_flower.c
@@ -148,6 +148,12 @@ static int prestera_flower_parse_meta(struct prestera_acl_rule *rule,
__be16 key, mask;
flow_rule_match_meta(f_rule, &match);
+
+ if (match.mask->l2_miss) {
+ NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on \"l2_miss\"");
+ return -EOPNOTSUPP;
+ }
+
if (match.mask->ingress_ifindex != 0xFFFFFFFF) {
NL_SET_ERR_MSG_MOD(f->common.extack,
"Unsupported ingress ifindex mask");
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_main.c b/drivers/net/ethernet/marvell/prestera/prestera_main.c
index 9d504142e51a..4fb886c57cd7 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_main.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c
@@ -300,8 +300,7 @@ static void prestera_pcs_get_state(struct phylink_pcs *pcs,
}
}
-static int prestera_pcs_config(struct phylink_pcs *pcs,
- unsigned int mode,
+static int prestera_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -316,30 +315,25 @@ static int prestera_pcs_config(struct phylink_pcs *pcs,
cfg_mac.admin = true;
cfg_mac.fec = PRESTERA_PORT_FEC_OFF;
+ cfg_mac.inband = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED;
switch (interface) {
case PHY_INTERFACE_MODE_10GBASER:
cfg_mac.speed = SPEED_10000;
- cfg_mac.inband = 0;
cfg_mac.mode = PRESTERA_MAC_MODE_SR_LR;
break;
case PHY_INTERFACE_MODE_2500BASEX:
cfg_mac.speed = SPEED_2500;
cfg_mac.duplex = DUPLEX_FULL;
- cfg_mac.inband = test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
- advertising);
cfg_mac.mode = PRESTERA_MAC_MODE_SGMII;
break;
case PHY_INTERFACE_MODE_SGMII:
- cfg_mac.inband = 1;
cfg_mac.mode = PRESTERA_MAC_MODE_SGMII;
break;
case PHY_INTERFACE_MODE_1000BASEX:
default:
cfg_mac.speed = SPEED_1000;
cfg_mac.duplex = DUPLEX_FULL;
- cfg_mac.inband = test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
- advertising);
cfg_mac.mode = PRESTERA_MAC_MODE_1000BASE_X;
break;
}
@@ -401,6 +395,7 @@ static int prestera_port_sfp_bind(struct prestera_port *port)
continue;
port->phylink_pcs.ops = &prestera_pcs_ops;
+ port->phylink_pcs.neg_mode = true;
port->phy_config.dev = &port->dev->dev;
port->phy_config.type = PHYLINK_NETDEV;
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
index f328d957b2db..35857dc19542 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
@@ -727,7 +727,8 @@ pick_fw_ver:
err = request_firmware_direct(&fw->bin, fw_path, fw->dev.dev);
if (err) {
- if (ver_maj == PRESTERA_SUPP_FW_MAJ_VER) {
+ if (ver_maj != PRESTERA_PREV_FW_MAJ_VER ||
+ ver_min != PRESTERA_PREV_FW_MIN_VER) {
ver_maj = PRESTERA_PREV_FW_MAJ_VER;
ver_min = PRESTERA_PREV_FW_MIN_VER;
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_router.c b/drivers/net/ethernet/marvell/prestera/prestera_router.c
index a9a1028cb17b..de317179a7dc 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_router.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_router.c
@@ -166,11 +166,11 @@ prestera_util_neigh2nc_key(struct prestera_switch *sw, struct neighbour *n,
static bool __prestera_fi_is_direct(struct fib_info *fi)
{
- struct fib_nh *fib_nh;
+ struct fib_nh_common *fib_nhc;
if (fib_info_num_path(fi) == 1) {
- fib_nh = fib_info_nh(fi, 0);
- if (fib_nh->fib_nh_gw_family == AF_UNSPEC)
+ fib_nhc = fib_info_nhc(fi, 0);
+ if (fib_nhc->nhc_gw_family == AF_UNSPEC)
return true;
}
@@ -261,7 +261,7 @@ static bool
__prestera_util_kern_n_is_reachable_v4(u32 tb_id, __be32 *addr,
struct net_device *dev)
{
- struct fib_nh *fib_nh;
+ struct fib_nh_common *fib_nhc;
struct fib_result res;
bool reachable;
@@ -269,8 +269,8 @@ __prestera_util_kern_n_is_reachable_v4(u32 tb_id, __be32 *addr,
if (!prestera_util_kern_get_route(&res, tb_id, addr))
if (prestera_fi_is_direct(res.fi)) {
- fib_nh = fib_info_nh(res.fi, 0);
- if (dev == fib_nh->fib_nh_dev)
+ fib_nhc = fib_info_nhc(res.fi, 0);
+ if (dev == fib_nhc->nhc_dev)
reachable = true;
}
@@ -324,7 +324,7 @@ prestera_kern_fib_info_nhc(struct fib_notifier_info *info, int n)
if (info->family == AF_INET) {
fen4_info = container_of(info, struct fib_entry_notifier_info,
info);
- return &fib_info_nh(fen4_info->fi, n)->nh_common;
+ return fib_info_nhc(fen4_info->fi, n);
} else if (info->family == AF_INET6) {
fen6_info = container_of(info, struct fib6_entry_notifier_info,
info);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 834c644b67db..2d15342c260a 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -3846,23 +3846,6 @@ static int mtk_hw_deinit(struct mtk_eth *eth)
return 0;
}
-static int __init mtk_init(struct net_device *dev)
-{
- struct mtk_mac *mac = netdev_priv(dev);
- struct mtk_eth *eth = mac->hw;
- int ret;
-
- ret = of_get_ethdev_address(mac->of_node, dev);
- if (ret) {
- /* If the mac address is invalid, use random mac address */
- eth_hw_addr_random(dev);
- dev_err(eth->dev, "generated random MAC address %pM\n",
- dev->dev_addr);
- }
-
- return 0;
-}
-
static void mtk_uninit(struct net_device *dev)
{
struct mtk_mac *mac = netdev_priv(dev);
@@ -4278,7 +4261,6 @@ static const struct ethtool_ops mtk_ethtool_ops = {
};
static const struct net_device_ops mtk_netdev_ops = {
- .ndo_init = mtk_init,
.ndo_uninit = mtk_uninit,
.ndo_open = mtk_open,
.ndo_stop = mtk_stop,
@@ -4340,6 +4322,17 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
mac->hw = eth;
mac->of_node = np;
+ err = of_get_ethdev_address(mac->of_node, eth->netdev[id]);
+ if (err == -EPROBE_DEFER)
+ return err;
+
+ if (err) {
+ /* If the mac address is invalid, use random mac address */
+ eth_hw_addr_random(eth->netdev[id]);
+ dev_err(eth->dev, "generated random MAC address %pM\n",
+ eth->netdev[id]->dev_addr);
+ }
+
memset(mac->hwlro_ip, 0, sizeof(mac->hwlro_ip));
mac->hwlro_ip_cnt = 0;
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
index 316fe2e70fea..1a97feca77f2 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
@@ -98,7 +98,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file *m, void *private, bool bind)
acct = mtk_foe_entry_get_mib(ppe, i, NULL);
- type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1);
+ type = mtk_get_ib1_pkt_type(ppe->eth, entry->ib1);
seq_printf(m, "%05x %s %7s", i,
mtk_foe_entry_state_str(state),
mtk_foe_pkt_type_str(type));
diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
index 985cff910f30..3b651efcc25e 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed.c
+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
@@ -221,9 +221,13 @@ void mtk_wed_fe_reset(void)
for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
struct mtk_wed_hw *hw = hw_list[i];
- struct mtk_wed_device *dev = hw->wed_dev;
+ struct mtk_wed_device *dev;
int err;
+ if (!hw)
+ break;
+
+ dev = hw->wed_dev;
if (!dev || !dev->wlan.reset)
continue;
@@ -244,8 +248,12 @@ void mtk_wed_fe_reset_complete(void)
for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
struct mtk_wed_hw *hw = hw_list[i];
- struct mtk_wed_device *dev = hw->wed_dev;
+ struct mtk_wed_device *dev;
+
+ if (!hw)
+ break;
+ dev = hw->wed_dev;
if (!dev || !dev->wlan.reset_complete)
continue;
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 277738c50c56..61286b0d9b0c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -1374,16 +1374,13 @@ static int mlx4_mf_bond(struct mlx4_dev *dev)
int nvfs;
struct mlx4_slaves_pport slaves_port1;
struct mlx4_slaves_pport slaves_port2;
- DECLARE_BITMAP(slaves_port_1_2, MLX4_MFUNC_MAX);
slaves_port1 = mlx4_phys_to_slaves_pport(dev, 1);
slaves_port2 = mlx4_phys_to_slaves_pport(dev, 2);
- bitmap_and(slaves_port_1_2,
- slaves_port1.slaves, slaves_port2.slaves,
- dev->persist->num_vfs + 1);
/* only single port vfs are allowed */
- if (bitmap_weight(slaves_port_1_2, dev->persist->num_vfs + 1) > 1) {
+ if (bitmap_weight_and(slaves_port1.slaves, slaves_port2.slaves,
+ dev->persist->num_vfs + 1) > 1) {
mlx4_warn(dev, "HA mode unsupported for dual ported VFs\n");
return -EINVAL;
}
@@ -3027,13 +3024,43 @@ no_msi:
}
}
+static int mlx4_devlink_port_type_set(struct devlink_port *devlink_port,
+ enum devlink_port_type port_type)
+{
+ struct mlx4_port_info *info = container_of(devlink_port,
+ struct mlx4_port_info,
+ devlink_port);
+ enum mlx4_port_type mlx4_port_type;
+
+ switch (port_type) {
+ case DEVLINK_PORT_TYPE_AUTO:
+ mlx4_port_type = MLX4_PORT_TYPE_AUTO;
+ break;
+ case DEVLINK_PORT_TYPE_ETH:
+ mlx4_port_type = MLX4_PORT_TYPE_ETH;
+ break;
+ case DEVLINK_PORT_TYPE_IB:
+ mlx4_port_type = MLX4_PORT_TYPE_IB;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return __set_port_type(info, mlx4_port_type);
+}
+
+static const struct devlink_port_ops mlx4_devlink_port_ops = {
+ .port_type_set = mlx4_devlink_port_type_set,
+};
+
static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
{
struct devlink *devlink = priv_to_devlink(mlx4_priv(dev));
struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
int err;
- err = devl_port_register(devlink, &info->devlink_port, port);
+ err = devl_port_register_with_ops(devlink, &info->devlink_port, port,
+ &mlx4_devlink_port_ops);
if (err)
return err;
@@ -3877,31 +3904,6 @@ err_disable_pdev:
return err;
}
-static int mlx4_devlink_port_type_set(struct devlink_port *devlink_port,
- enum devlink_port_type port_type)
-{
- struct mlx4_port_info *info = container_of(devlink_port,
- struct mlx4_port_info,
- devlink_port);
- enum mlx4_port_type mlx4_port_type;
-
- switch (port_type) {
- case DEVLINK_PORT_TYPE_AUTO:
- mlx4_port_type = MLX4_PORT_TYPE_AUTO;
- break;
- case DEVLINK_PORT_TYPE_ETH:
- mlx4_port_type = MLX4_PORT_TYPE_ETH;
- break;
- case DEVLINK_PORT_TYPE_IB:
- mlx4_port_type = MLX4_PORT_TYPE_IB;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return __set_port_type(info, mlx4_port_type);
-}
-
static void mlx4_devlink_param_load_driverinit_values(struct devlink *devlink)
{
struct mlx4_priv *priv = devlink_priv(devlink);
@@ -3986,7 +3988,6 @@ static int mlx4_devlink_reload_up(struct devlink *devlink, enum devlink_reload_a
}
static const struct devlink_ops mlx4_devlink_ops = {
- .port_type_set = mlx4_devlink_port_type_set,
.reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT),
.reload_down = mlx4_devlink_reload_down,
.reload_up = mlx4_devlink_reload_up,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
index ddf1e352f51d..35f00700a4d6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
@@ -75,7 +75,8 @@ mlx5_core-$(CONFIG_MLX5_ESWITCH) += esw/acl/helper.o \
esw/acl/egress_lgcy.o esw/acl/egress_ofld.o \
esw/acl/ingress_lgcy.o esw/acl/ingress_ofld.o
-mlx5_core-$(CONFIG_MLX5_BRIDGE) += esw/bridge.o esw/bridge_mcast.o en/rep/bridge.o
+mlx5_core-$(CONFIG_MLX5_BRIDGE) += esw/bridge.o esw/bridge_mcast.o esw/bridge_debugfs.o \
+ en/rep/bridge.o
mlx5_core-$(CONFIG_THERMAL) += thermal.o
mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
index bb95b40d25eb..2138f28a2931 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
@@ -246,6 +246,7 @@ void mlx5_pages_debugfs_init(struct mlx5_core_dev *dev)
debugfs_create_u32("fw_pages_total", 0400, pages, &dev->priv.fw_pages);
debugfs_create_u32("fw_pages_vfs", 0400, pages, &dev->priv.page_counters[MLX5_VF]);
+ debugfs_create_u32("fw_pages_ec_vfs", 0400, pages, &dev->priv.page_counters[MLX5_EC_VF]);
debugfs_create_u32("fw_pages_sfs", 0400, pages, &dev->priv.page_counters[MLX5_SF]);
debugfs_create_u32("fw_pages_host_pf", 0400, pages, &dev->priv.page_counters[MLX5_HOST_PF]);
debugfs_create_u32("fw_pages_alloc_failed", 0400, pages, &dev->priv.fw_pages_alloc_failed);
@@ -513,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/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/dev.c
index 1b33533b15de..edb06fb9bbc5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/dev.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/dev.c
@@ -151,12 +151,6 @@ static bool is_ib_rep_supported(struct mlx5_core_dev *dev)
if (!is_eth_rep_supported(dev))
return false;
- if (!MLX5_ESWITCH_MANAGER(dev))
- return false;
-
- if (!is_mdev_switchdev_mode(dev))
- return false;
-
if (mlx5_core_mp_enabled(dev))
return false;
@@ -323,6 +317,18 @@ static void del_adev(struct auxiliary_device *adev)
auxiliary_device_uninit(adev);
}
+void mlx5_dev_set_lightweight(struct mlx5_core_dev *dev)
+{
+ mutex_lock(&mlx5_intf_mutex);
+ dev->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV;
+ mutex_unlock(&mlx5_intf_mutex);
+}
+
+bool mlx5_dev_is_lightweight(struct mlx5_core_dev *dev)
+{
+ return dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV;
+}
+
int mlx5_attach_device(struct mlx5_core_dev *dev)
{
struct mlx5_priv *priv = &dev->priv;
@@ -457,6 +463,10 @@ static int add_drivers(struct mlx5_core_dev *dev)
if (priv->adev[i])
continue;
+ if (mlx5_adev_devices[i].is_enabled &&
+ !(mlx5_adev_devices[i].is_enabled(dev)))
+ continue;
+
if (mlx5_adev_devices[i].is_supported)
is_supported = mlx5_adev_devices[i].is_supported(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
index 4b607785d694..3d82ec890666 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
@@ -7,7 +7,6 @@
#include "fw_reset.h"
#include "fs_core.h"
#include "eswitch.h"
-#include "lag/lag.h"
#include "esw/qos.h"
#include "sf/dev/dev.h"
#include "sf/sf.h"
@@ -142,6 +141,13 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
bool sf_dev_allocated;
int ret = 0;
+ if (mlx5_dev_is_lightweight(dev)) {
+ if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT)
+ return -EOPNOTSUPP;
+ mlx5_unload_one_light(dev);
+ return 0;
+ }
+
sf_dev_allocated = mlx5_sf_dev_allocated(dev);
if (sf_dev_allocated) {
/* Reload results in deleting SF device which further results in
@@ -162,9 +168,8 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
return -EOPNOTSUPP;
}
- if (pci_num_vf(pdev)) {
+ if (mlx5_core_is_pf(dev) && pci_num_vf(pdev))
NL_SET_ERR_MSG_MOD(extack, "reload while VFs are present is unfavorable");
- }
switch (action) {
case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
@@ -195,6 +200,10 @@ static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_a
*actions_performed = BIT(action);
switch (action) {
case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
+ if (mlx5_dev_is_lightweight(dev)) {
+ mlx5_fw_reporters_create(dev);
+ return mlx5_init_one_devl_locked(dev);
+ }
ret = mlx5_load_one_devl_locked(dev, false);
break;
case DEVLINK_RELOAD_ACTION_FW_ACTIVATE:
@@ -311,8 +320,6 @@ static const struct devlink_ops mlx5_devlink_ops = {
.eswitch_inline_mode_get = mlx5_devlink_eswitch_inline_mode_get,
.eswitch_encap_mode_set = mlx5_devlink_eswitch_encap_mode_set,
.eswitch_encap_mode_get = mlx5_devlink_eswitch_encap_mode_get,
- .port_function_hw_addr_get = mlx5_devlink_port_function_hw_addr_get,
- .port_function_hw_addr_set = mlx5_devlink_port_function_hw_addr_set,
.rate_leaf_tx_share_set = mlx5_esw_devlink_rate_leaf_tx_share_set,
.rate_leaf_tx_max_set = mlx5_esw_devlink_rate_leaf_tx_max_set,
.rate_node_tx_share_set = mlx5_esw_devlink_rate_node_tx_share_set,
@@ -320,16 +327,9 @@ static const struct devlink_ops mlx5_devlink_ops = {
.rate_node_new = mlx5_esw_devlink_rate_node_new,
.rate_node_del = mlx5_esw_devlink_rate_node_del,
.rate_leaf_parent_set = mlx5_esw_devlink_rate_parent_set,
- .port_fn_roce_get = mlx5_devlink_port_fn_roce_get,
- .port_fn_roce_set = mlx5_devlink_port_fn_roce_set,
- .port_fn_migratable_get = mlx5_devlink_port_fn_migratable_get,
- .port_fn_migratable_set = mlx5_devlink_port_fn_migratable_set,
#endif
#ifdef CONFIG_MLX5_SF_MANAGER
.port_new = mlx5_devlink_sf_port_new,
- .port_del = mlx5_devlink_sf_port_del,
- .port_fn_state_get = mlx5_devlink_sf_port_fn_state_get,
- .port_fn_state_set = mlx5_devlink_sf_port_fn_state_set,
#endif
.flash_update = mlx5_devlink_flash_update,
.info_get = mlx5_devlink_info_get,
@@ -437,54 +437,6 @@ static int mlx5_devlink_large_group_num_validate(struct devlink *devlink, u32 id
return 0;
}
-
-static int mlx5_devlink_esw_multiport_set(struct devlink *devlink, u32 id,
- struct devlink_param_gset_ctx *ctx)
-{
- struct mlx5_core_dev *dev = devlink_priv(devlink);
-
- if (!MLX5_ESWITCH_MANAGER(dev))
- return -EOPNOTSUPP;
-
- if (ctx->val.vbool)
- return mlx5_lag_mpesw_enable(dev);
-
- mlx5_lag_mpesw_disable(dev);
- return 0;
-}
-
-static int mlx5_devlink_esw_multiport_get(struct devlink *devlink, u32 id,
- struct devlink_param_gset_ctx *ctx)
-{
- struct mlx5_core_dev *dev = devlink_priv(devlink);
-
- if (!MLX5_ESWITCH_MANAGER(dev))
- return -EOPNOTSUPP;
-
- ctx->val.vbool = mlx5_lag_is_mpesw(dev);
- return 0;
-}
-
-static int mlx5_devlink_esw_multiport_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
- struct netlink_ext_ack *extack)
-{
- struct mlx5_core_dev *dev = devlink_priv(devlink);
-
- if (!MLX5_ESWITCH_MANAGER(dev)) {
- NL_SET_ERR_MSG_MOD(extack, "E-Switch is unsupported");
- return -EOPNOTSUPP;
- }
-
- if (mlx5_eswitch_mode(dev) != MLX5_ESWITCH_OFFLOADS) {
- NL_SET_ERR_MSG_MOD(extack,
- "E-Switch must be in switchdev mode");
- return -EBUSY;
- }
-
- return 0;
-}
-
#endif
static int mlx5_devlink_eq_depth_validate(struct devlink *devlink, u32 id,
@@ -558,12 +510,6 @@ static const struct devlink_param mlx5_devlink_params[] = {
BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
NULL, NULL,
mlx5_devlink_large_group_num_validate),
- DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_MULTIPORT,
- "esw_multiport", DEVLINK_PARAM_TYPE_BOOL,
- BIT(DEVLINK_PARAM_CMODE_RUNTIME),
- mlx5_devlink_esw_multiport_get,
- mlx5_devlink_esw_multiport_set,
- mlx5_devlink_esw_multiport_validate),
#endif
DEVLINK_PARAM_GENERIC(IO_EQ_SIZE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
NULL, NULL, mlx5_devlink_eq_depth_validate),
@@ -576,7 +522,7 @@ static void mlx5_devlink_set_params_init_values(struct devlink *devlink)
struct mlx5_core_dev *dev = devlink_priv(devlink);
union devlink_param_value value;
- value.vbool = MLX5_CAP_GEN(dev, roce);
+ value.vbool = MLX5_CAP_GEN(dev, roce) && !mlx5_dev_is_lightweight(dev);
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
value);
@@ -626,7 +572,7 @@ static int mlx5_devlink_eth_params_register(struct devlink *devlink)
if (err)
return err;
- value.vbool = true;
+ value.vbool = !mlx5_dev_is_lightweight(dev);
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH,
value);
@@ -666,6 +612,7 @@ static const struct devlink_param mlx5_devlink_rdma_params[] = {
static int mlx5_devlink_rdma_params_register(struct devlink *devlink)
{
+ struct mlx5_core_dev *dev = devlink_priv(devlink);
union devlink_param_value value;
int err;
@@ -677,7 +624,7 @@ static int mlx5_devlink_rdma_params_register(struct devlink *devlink)
if (err)
return err;
- value.vbool = true;
+ value.vbool = !mlx5_dev_is_lightweight(dev);
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA,
value);
@@ -712,7 +659,7 @@ static int mlx5_devlink_vnet_params_register(struct devlink *devlink)
if (err)
return err;
- value.vbool = true;
+ value.vbool = !mlx5_dev_is_lightweight(dev);
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET,
value);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c
index 9114661cd967..e869c65d8e90 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c
@@ -2,6 +2,7 @@
/* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. */
#include "reporter_vnic.h"
+#include "en_stats.h"
#include "devlink.h"
#define VNIC_ENV_GET64(vnic_env_stats, c) \
@@ -36,45 +37,72 @@ int mlx5_reporter_vnic_diagnose_counters(struct mlx5_core_dev *dev,
if (err)
return err;
- err = devlink_fmsg_u64_pair_put(fmsg, "total_error_queues",
- VNIC_ENV_GET64(&vnic, total_error_queues));
- if (err)
- return err;
-
- err = devlink_fmsg_u64_pair_put(fmsg, "send_queue_priority_update_flow",
- VNIC_ENV_GET64(&vnic, send_queue_priority_update_flow));
- if (err)
- return err;
-
- err = devlink_fmsg_u64_pair_put(fmsg, "comp_eq_overrun",
- VNIC_ENV_GET64(&vnic, comp_eq_overrun));
- if (err)
- return err;
-
- err = devlink_fmsg_u64_pair_put(fmsg, "async_eq_overrun",
- VNIC_ENV_GET64(&vnic, async_eq_overrun));
- if (err)
- return err;
-
- err = devlink_fmsg_u64_pair_put(fmsg, "cq_overrun",
- VNIC_ENV_GET64(&vnic, cq_overrun));
- if (err)
- return err;
-
- err = devlink_fmsg_u64_pair_put(fmsg, "invalid_command",
- VNIC_ENV_GET64(&vnic, invalid_command));
- if (err)
- return err;
-
- err = devlink_fmsg_u64_pair_put(fmsg, "quota_exceeded_command",
- VNIC_ENV_GET64(&vnic, quota_exceeded_command));
- if (err)
- return err;
-
- err = devlink_fmsg_u64_pair_put(fmsg, "nic_receive_steering_discard",
- VNIC_ENV_GET64(&vnic, nic_receive_steering_discard));
- if (err)
- return err;
+ if (MLX5_CAP_GEN(dev, vnic_env_queue_counters)) {
+ err = devlink_fmsg_u32_pair_put(fmsg, "total_error_queues",
+ VNIC_ENV_GET(&vnic, total_error_queues));
+ if (err)
+ return err;
+
+ err = devlink_fmsg_u32_pair_put(fmsg, "send_queue_priority_update_flow",
+ VNIC_ENV_GET(&vnic,
+ send_queue_priority_update_flow));
+ if (err)
+ return err;
+ }
+
+ if (MLX5_CAP_GEN(dev, eq_overrun_count)) {
+ err = devlink_fmsg_u32_pair_put(fmsg, "comp_eq_overrun",
+ VNIC_ENV_GET(&vnic, comp_eq_overrun));
+ if (err)
+ return err;
+
+ err = devlink_fmsg_u32_pair_put(fmsg, "async_eq_overrun",
+ VNIC_ENV_GET(&vnic, async_eq_overrun));
+ if (err)
+ return err;
+ }
+
+ if (MLX5_CAP_GEN(dev, vnic_env_cq_overrun)) {
+ err = devlink_fmsg_u32_pair_put(fmsg, "cq_overrun",
+ VNIC_ENV_GET(&vnic, cq_overrun));
+ if (err)
+ return err;
+ }
+
+ if (MLX5_CAP_GEN(dev, invalid_command_count)) {
+ err = devlink_fmsg_u32_pair_put(fmsg, "invalid_command",
+ VNIC_ENV_GET(&vnic, invalid_command));
+ if (err)
+ return err;
+ }
+
+ if (MLX5_CAP_GEN(dev, quota_exceeded_count)) {
+ err = devlink_fmsg_u32_pair_put(fmsg, "quota_exceeded_command",
+ VNIC_ENV_GET(&vnic, quota_exceeded_command));
+ if (err)
+ return err;
+ }
+
+ if (MLX5_CAP_GEN(dev, nic_receive_steering_discard)) {
+ err = devlink_fmsg_u64_pair_put(fmsg, "nic_receive_steering_discard",
+ VNIC_ENV_GET64(&vnic,
+ nic_receive_steering_discard));
+ if (err)
+ return err;
+ }
+
+ if (MLX5_CAP_GEN(dev, vnic_env_cnt_steering_fail)) {
+ err = devlink_fmsg_u64_pair_put(fmsg, "generated_pkt_steering_fail",
+ VNIC_ENV_GET64(&vnic,
+ generated_pkt_steering_fail));
+ if (err)
+ return err;
+
+ err = devlink_fmsg_u64_pair_put(fmsg, "handled_pkt_steering_fail",
+ VNIC_ENV_GET64(&vnic, handled_pkt_steering_fail));
+ if (err)
+ return err;
+ }
err = devlink_fmsg_obj_nest_end(fmsg);
if (err)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 8e999f238194..b1807bfb815f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -165,15 +165,6 @@ struct page_pool;
#define MLX5E_MAX_KLM_PER_WQE(mdev) \
MLX5E_KLM_ENTRIES_PER_WQE(MLX5_SEND_WQE_BB * mlx5e_get_max_sq_aligned_wqebbs(mdev))
-#define MLX5E_MSG_LEVEL NETIF_MSG_LINK
-
-#define mlx5e_dbg(mlevel, priv, format, ...) \
-do { \
- if (NETIF_MSG_##mlevel & (priv)->msglevel) \
- netdev_warn(priv->netdev, format, \
- ##__VA_ARGS__); \
-} while (0)
-
#define mlx5e_state_dereference(priv, p) \
rcu_dereference_protected((p), lockdep_is_held(&(priv)->state_lock))
@@ -594,13 +585,6 @@ struct mlx5e_mpw_info {
#define MLX5E_MAX_RX_FRAGS 4
-/* a single cache unit is capable to serve one napi call (for non-striding rq)
- * or a MPWQE (for striding rq).
- */
-#define MLX5E_CACHE_UNIT (MLX5_MPWRQ_MAX_PAGES_PER_WQE > NAPI_POLL_WEIGHT ? \
- MLX5_MPWRQ_MAX_PAGES_PER_WQE : NAPI_POLL_WEIGHT)
-#define MLX5E_CACHE_SIZE (4 * roundup_pow_of_two(MLX5E_CACHE_UNIT))
-
struct mlx5e_rq;
typedef void (*mlx5e_fp_handle_rx_cqe)(struct mlx5e_rq*, struct mlx5_cqe64*);
typedef struct sk_buff *
@@ -887,7 +871,6 @@ struct mlx5e_priv {
#endif
/* priv data path fields - end */
- u32 msglevel;
unsigned long state;
struct mutex state_lock; /* Protects Interface state */
struct mlx5e_rq drop_rq;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c b/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c
index 03cb79adf912..be83ad9db82a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c
@@ -594,7 +594,7 @@ int mlx5e_fs_tt_redirect_any_create(struct mlx5e_flow_steering *fs)
err = fs_any_create_table(fs);
if (err)
- return err;
+ goto err_free_any;
err = fs_any_enable(fs);
if (err)
@@ -606,8 +606,8 @@ int mlx5e_fs_tt_redirect_any_create(struct mlx5e_flow_steering *fs)
err_destroy_table:
fs_any_destroy_table(fs_any);
-
- kfree(fs_any);
+err_free_any:
mlx5e_fs_set_any(fs, NULL);
+ kfree(fs_any);
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
index 7e8e96cc5cd0..8e25f4ef5ccc 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
@@ -65,12 +65,13 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv,
MLX5_GET(bufferx_reg, buffer, xoff_threshold) * port_buff_cell_sz;
total_used += port_buffer->buffer[i].size;
- mlx5e_dbg(HW, priv, "buffer %d: size=%d, xon=%d, xoff=%d, epsb=%d, lossy=%d\n", i,
- port_buffer->buffer[i].size,
- port_buffer->buffer[i].xon,
- port_buffer->buffer[i].xoff,
- port_buffer->buffer[i].epsb,
- port_buffer->buffer[i].lossy);
+ netdev_dbg(priv->netdev, "buffer %d: size=%d, xon=%d, xoff=%d, epsb=%d, lossy=%d\n",
+ i,
+ port_buffer->buffer[i].size,
+ port_buffer->buffer[i].xon,
+ port_buffer->buffer[i].xoff,
+ port_buffer->buffer[i].epsb,
+ port_buffer->buffer[i].lossy);
}
port_buffer->internal_buffers_size = 0;
@@ -87,11 +88,11 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv,
port_buffer->internal_buffers_size -
port_buffer->headroom_size;
- mlx5e_dbg(HW, priv,
- "total buffer size=%u, headroom buffer size=%u, internal buffers size=%u, spare buffer size=%u\n",
- port_buffer->port_buffer_size, port_buffer->headroom_size,
- port_buffer->internal_buffers_size,
- port_buffer->spare_buffer_size);
+ netdev_dbg(priv->netdev,
+ "total buffer size=%u, headroom buffer size=%u, internal buffers size=%u, spare buffer size=%u\n",
+ port_buffer->port_buffer_size, port_buffer->headroom_size,
+ port_buffer->internal_buffers_size,
+ port_buffer->spare_buffer_size);
out:
kfree(out);
return err;
@@ -352,7 +353,7 @@ static u32 calculate_xoff(struct mlx5e_priv *priv, unsigned int mtu)
xoff = (301 + 216 * priv->dcbx.cable_len / 100) * speed / 1000 + 272 * mtu / 100;
- mlx5e_dbg(HW, priv, "%s: xoff=%d\n", __func__, xoff);
+ netdev_dbg(priv->netdev, "%s: xoff=%d\n", __func__, xoff);
return xoff;
}
@@ -484,6 +485,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
u8 *prio2buffer)
{
u16 port_buff_cell_sz = priv->dcbx.port_buff_cell_sz;
+ struct net_device *netdev = priv->netdev;
struct mlx5e_port_buffer port_buffer;
u32 xoff = calculate_xoff(priv, mtu);
bool update_prio2buffer = false;
@@ -495,7 +497,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
int err;
int i;
- mlx5e_dbg(HW, priv, "%s: change=%x\n", __func__, change);
+ netdev_dbg(netdev, "%s: change=%x\n", __func__, change);
max_mtu = max_t(unsigned int, priv->netdev->max_mtu, MINIMUM_MAX_MTU);
err = mlx5e_port_query_buffer(priv, &port_buffer);
@@ -510,8 +512,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
}
if (change & MLX5E_PORT_BUFFER_PFC) {
- mlx5e_dbg(HW, priv, "%s: requested PFC per priority bitmask: 0x%x\n",
- __func__, pfc->pfc_en);
+ netdev_dbg(netdev, "%s: requested PFC per priority bitmask: 0x%x\n",
+ __func__, pfc->pfc_en);
err = mlx5e_port_query_priority2buffer(priv->mdev, buffer);
if (err)
return err;
@@ -526,8 +528,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
if (change & MLX5E_PORT_BUFFER_PRIO2BUFFER) {
update_prio2buffer = true;
for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++)
- mlx5e_dbg(HW, priv, "%s: requested to map prio[%d] to buffer %d\n",
- __func__, i, prio2buffer[i]);
+ netdev_dbg(priv->netdev, "%s: requested to map prio[%d] to buffer %d\n",
+ __func__, i, prio2buffer[i]);
err = fill_pfc_en(priv->mdev, &curr_pfc_en);
if (err)
@@ -541,10 +543,10 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
if (change & MLX5E_PORT_BUFFER_SIZE) {
for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
- mlx5e_dbg(HW, priv, "%s: buffer[%d]=%d\n", __func__, i, buffer_size[i]);
+ netdev_dbg(priv->netdev, "%s: buffer[%d]=%d\n", __func__, i, buffer_size[i]);
if (!port_buffer.buffer[i].lossy && !buffer_size[i]) {
- mlx5e_dbg(HW, priv, "%s: lossless buffer[%d] size cannot be zero\n",
- __func__, i);
+ netdev_dbg(priv->netdev, "%s: lossless buffer[%d] size cannot be zero\n",
+ __func__, i);
return -EINVAL;
}
@@ -552,7 +554,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
total_used += buffer_size[i];
}
- mlx5e_dbg(HW, priv, "%s: total buffer requested=%d\n", __func__, total_used);
+ netdev_dbg(priv->netdev, "%s: total buffer requested=%d\n", __func__, total_used);
if (total_used > port_buffer.headroom_size &&
(total_used - port_buffer.headroom_size) >
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c
index 3cbebfba582b..b0b429a0321e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c
@@ -729,8 +729,10 @@ int mlx5e_ptp_open(struct mlx5e_priv *priv, struct mlx5e_params *params,
c = kvzalloc_node(sizeof(*c), GFP_KERNEL, dev_to_node(mlx5_core_dma_dev(mdev)));
cparams = kvzalloc(sizeof(*cparams), GFP_KERNEL);
- if (!c || !cparams)
- return -ENOMEM;
+ if (!c || !cparams) {
+ err = -ENOMEM;
+ goto err_free;
+ }
c->priv = priv;
c->mdev = priv->mdev;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
index 2842195ee548..1874c2f0587f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
@@ -379,6 +379,12 @@ int mlx5e_htb_setup_tc(struct mlx5e_priv *priv, struct tc_htb_qopt_offload *htb_
if (!htb && htb_qopt->command != TC_HTB_CREATE)
return -EINVAL;
+ if (htb_qopt->prio) {
+ NL_SET_ERR_MSG_MOD(htb_qopt->extack,
+ "prio parameter is not supported by device with HTB offload enabled.");
+ return -EOPNOTSUPP;
+ }
+
switch (htb_qopt->command) {
case TC_HTB_CREATE:
if (!mlx5_qos_is_supported(priv->mdev)) {
@@ -515,4 +521,3 @@ int mlx5e_mqprio_rl_get_node_hw_id(struct mlx5e_mqprio_rl *rl, int tc, u32 *hw_i
*hw_id = rl->leaves_id[tc];
return 0;
}
-
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c
index fd191925ab4b..560800246573 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c
@@ -136,7 +136,6 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr
struct mlx5_eswitch *esw = br_offloads->esw;
u16 vport_num, esw_owner_vhca_id;
struct netlink_ext_ack *extack;
- int ifindex = upper->ifindex;
int err = 0;
if (!netif_is_bridge_master(upper))
@@ -150,15 +149,15 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr
if (mlx5_esw_bridge_is_local(dev, rep, esw))
err = info->linking ?
- mlx5_esw_bridge_vport_link(ifindex, vport_num, esw_owner_vhca_id,
+ mlx5_esw_bridge_vport_link(upper, vport_num, esw_owner_vhca_id,
br_offloads, extack) :
- mlx5_esw_bridge_vport_unlink(ifindex, vport_num, esw_owner_vhca_id,
+ mlx5_esw_bridge_vport_unlink(upper, vport_num, esw_owner_vhca_id,
br_offloads, extack);
else if (mlx5_esw_bridge_dev_same_hw(rep, esw))
err = info->linking ?
- mlx5_esw_bridge_vport_peer_link(ifindex, vport_num, esw_owner_vhca_id,
+ mlx5_esw_bridge_vport_peer_link(upper, vport_num, esw_owner_vhca_id,
br_offloads, extack) :
- mlx5_esw_bridge_vport_peer_unlink(ifindex, vport_num, esw_owner_vhca_id,
+ mlx5_esw_bridge_vport_peer_unlink(upper, vport_num, esw_owner_vhca_id,
br_offloads, extack);
return err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c
index 07c1895a2b23..7aa926e542d3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c
@@ -25,8 +25,8 @@ struct mlx5e_tc_act_stats {
static const struct rhashtable_params act_counters_ht_params = {
.head_offset = offsetof(struct mlx5e_tc_act_stats, hash),
- .key_offset = 0,
- .key_len = offsetof(struct mlx5e_tc_act_stats, counter),
+ .key_offset = offsetof(struct mlx5e_tc_act_stats, tc_act_cookie),
+ .key_len = sizeof_field(struct mlx5e_tc_act_stats, tc_act_cookie),
.automatic_shrinking = true,
};
@@ -169,14 +169,11 @@ mlx5e_tc_act_stats_fill_stats(struct mlx5e_tc_act_stats_handle *handle,
{
struct rhashtable *ht = &handle->ht;
struct mlx5e_tc_act_stats *item;
- struct mlx5e_tc_act_stats key;
u64 pkts, bytes, lastused;
int err = 0;
- key.tc_act_cookie = fl_act->cookie;
-
rcu_read_lock();
- item = rhashtable_lookup(ht, &key, act_counters_ht_params);
+ item = rhashtable_lookup(ht, &fl_act->cookie, act_counters_ht_params);
if (!item) {
rcu_read_unlock();
err = -ENOENT;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c
index 0290e0dea539..4e923a2874ae 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c
@@ -112,10 +112,8 @@ mlx5e_tc_post_act_add(struct mlx5e_post_act *post_act, struct mlx5_flow_attr *po
int err;
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
- if (!handle) {
- kfree(handle);
+ if (!handle)
return ERR_PTR(-ENOMEM);
- }
post_attr->chain = 0;
post_attr->prio = 0;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
index a254e728ac95..fadfa8b50beb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
@@ -1545,7 +1545,8 @@ mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv,
attr->ct_attr.ct_action |= act->ct.action; /* So we can have clear + ct */
attr->ct_attr.zone = act->ct.zone;
- attr->ct_attr.nf_ft = act->ct.flow_table;
+ if (!(act->ct.action & TCA_CT_ACT_CLEAR))
+ attr->ct_attr.nf_ft = act->ct.flow_table;
attr->ct_attr.act_miss_cookie = act->miss_cookie;
return 0;
@@ -1990,6 +1991,9 @@ mlx5_tc_ct_flow_offload(struct mlx5_tc_ct_priv *priv, struct mlx5_flow_attr *att
if (!priv)
return -EOPNOTSUPP;
+ if (attr->ct_attr.offloaded)
+ return 0;
+
if (attr->ct_attr.ct_action & TCA_CT_ACT_CLEAR) {
err = mlx5_tc_ct_entry_set_registers(priv, &attr->parse_attr->mod_hdr_acts,
0, 0, 0, 0);
@@ -1999,11 +2003,15 @@ mlx5_tc_ct_flow_offload(struct mlx5_tc_ct_priv *priv, struct mlx5_flow_attr *att
attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
}
- if (!attr->ct_attr.nf_ft) /* means only ct clear action, and not ct_clear,ct() */
+ if (!attr->ct_attr.nf_ft) { /* means only ct clear action, and not ct_clear,ct() */
+ attr->ct_attr.offloaded = true;
return 0;
+ }
mutex_lock(&priv->control_lock);
err = __mlx5_tc_ct_flow_offload(priv, attr);
+ if (!err)
+ attr->ct_attr.offloaded = true;
mutex_unlock(&priv->control_lock);
return err;
@@ -2021,7 +2029,7 @@ void
mlx5_tc_ct_delete_flow(struct mlx5_tc_ct_priv *priv,
struct mlx5_flow_attr *attr)
{
- if (!attr->ct_attr.ft) /* no ct action, return */
+ if (!attr->ct_attr.offloaded) /* no ct action, return */
return;
if (!attr->ct_attr.nf_ft) /* means only ct clear action, and not ct_clear,ct() */
return;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h
index 8e9316fa46d4..b66c5f98067f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h
@@ -29,6 +29,7 @@ struct mlx5_ct_attr {
u32 ct_labels_id;
u32 act_miss_mapping;
u64 act_miss_cookie;
+ bool offloaded;
struct mlx5_ct_ft *ft;
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
index ba2b1f24ff14..6cc23af66b5b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
@@ -94,13 +94,13 @@ struct mlx5e_tc_flow {
* destinations.
*/
struct encap_flow_item encaps[MLX5_MAX_FLOW_FWD_VPORTS];
- struct mlx5e_tc_flow *peer_flow;
struct mlx5e_hairpin_entry *hpe; /* attached hairpin instance */
struct list_head hairpin; /* flows sharing the same hairpin */
- struct list_head peer; /* flows with peer flow */
+ struct list_head peer[MLX5_MAX_PORTS]; /* flows with peer flow */
struct list_head unready; /* flows not ready to be offloaded (e.g
* due to missing route)
*/
+ struct list_head peer_flows; /* flows on peer */
struct net_device *orig_dev; /* netdev adding flow first */
int tmp_entry_index;
struct list_head tmp_list; /* temporary flow list used by neigh update */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
index f0c3464f037f..1730f6a716ee 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
@@ -1030,9 +1030,6 @@ int mlx5e_tc_tun_encap_dests_set(struct mlx5e_priv *priv,
int out_index;
int err = 0;
- if (!mlx5e_is_eswitch_flow(flow))
- return 0;
-
parse_attr = attr->parse_attr;
esw_attr = attr->esw_attr;
*vf_tun = false;
@@ -1464,10 +1461,12 @@ static void mlx5e_invalidate_encap(struct mlx5e_priv *priv,
attr = mlx5e_tc_get_encap_attr(flow);
esw_attr = attr->esw_attr;
- if (flow_flag_test(flow, SLOW))
+ if (flow_flag_test(flow, SLOW)) {
mlx5e_tc_unoffload_from_slow_path(esw, flow);
- else
+ } else {
mlx5e_tc_unoffload_fdb_rules(esw, flow, flow->attr);
+ mlx5e_tc_unoffload_flow_post_acts(flow);
+ }
mlx5e_tc_detach_mod_hdr(priv, flow, attr);
attr->modify_hdr = NULL;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
index f0e6095809fa..40589cebb773 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
@@ -662,8 +662,7 @@ static void mlx5e_free_xdpsq_desc(struct mlx5e_xdpsq *sq,
/* No need to check ((page->pp_magic & ~0x3UL) == PP_SIGNATURE)
* as we know this is a page_pool page.
*/
- page_pool_put_defragged_page(page->pp,
- page, -1, true);
+ page_pool_recycle_direct(page->pp, page);
} while (++n < num);
break;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
index 9e8e6184f9e4..ecfe93a479da 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
@@ -84,6 +84,8 @@ enum mlx5e_xdp_xmit_mode {
* MLX5E_XDP_XMIT_MODE_XSK:
* none.
*/
+#define MLX5E_XDP_FIFO_ENTRIES2DS_MAX_RATIO 4
+
union mlx5e_xdp_info {
enum mlx5e_xdp_xmit_mode mode;
union {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c
index d97e6df66f45..b8dd74453655 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c
@@ -323,8 +323,11 @@ struct sk_buff *mlx5e_xsk_skb_from_cqe_linear(struct mlx5e_rq *rq,
net_prefetch(mxbuf->xdp.data);
prog = rcu_dereference(rq->xdp_prog);
- if (likely(prog && mlx5e_xdp_handle(rq, prog, mxbuf)))
+ if (likely(prog && mlx5e_xdp_handle(rq, prog, mxbuf))) {
+ if (likely(__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)))
+ wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
return NULL; /* page/packet was consumed by XDP */
+ }
/* XDP_PASS: copy the data from the UMEM to a new SKB. The frame reuse
* will be handled by mlx5e_free_rx_wqe.
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h
index c964644ee866..bac4717548c6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h
@@ -125,7 +125,7 @@ static inline bool mlx5e_accel_tx_begin(struct net_device *dev,
#ifdef CONFIG_MLX5_EN_TLS
/* May send WQEs. */
- if (mlx5e_ktls_skb_offloaded(skb))
+ if (tls_is_skb_tx_device_offloaded(skb))
if (unlikely(!mlx5e_ktls_handle_tx_skb(dev, sq, skb,
&state->tls)))
return false;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c
index 88a5aed9d678..c7d191f66ad1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c
@@ -190,6 +190,7 @@ static int accel_fs_tcp_create_groups(struct mlx5e_flow_table *ft,
in = kvzalloc(inlen, GFP_KERNEL);
if (!in || !ft->g) {
kfree(ft->g);
+ ft->g = NULL;
kvfree(in);
return -ENOMEM;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
index dbe87bf89c0d..832d36be4a17 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
@@ -808,9 +808,9 @@ static void setup_fte_upper_proto_match(struct mlx5_flow_spec *spec, struct upsp
}
if (upspec->sport) {
- MLX5_SET(fte_match_set_lyr_2_4, spec->match_criteria, udp_dport,
+ MLX5_SET(fte_match_set_lyr_2_4, spec->match_criteria, udp_sport,
upspec->sport_mask);
- MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, udp_dport, upspec->sport);
+ MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, udp_sport, upspec->sport);
}
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
index eab5bc718771..8d995e304869 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
@@ -58,7 +58,9 @@ static int mlx5e_ipsec_remove_trailer(struct sk_buff *skb, struct xfrm_state *x)
trailer_len = alen + plen + 2;
- pskb_trim(skb, skb->len - trailer_len);
+ ret = pskb_trim(skb, skb->len - trailer_len);
+ if (unlikely(ret))
+ return ret;
if (skb->protocol == htons(ETH_P_IP)) {
ipv4hdr->tot_len = htons(ntohs(ipv4hdr->tot_len) - trailer_len);
ip_send_check(ipv4hdr);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
index cf704f106b7c..984fa04bd331 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
@@ -188,7 +188,6 @@ static void mlx5e_tls_debugfs_init(struct mlx5e_tls *tls,
int mlx5e_ktls_init(struct mlx5e_priv *priv)
{
- struct mlx5_crypto_dek_pool *dek_pool;
struct mlx5e_tls *tls;
if (!mlx5e_is_ktls_device(priv->mdev))
@@ -199,12 +198,6 @@ int mlx5e_ktls_init(struct mlx5e_priv *priv)
return -ENOMEM;
tls->mdev = priv->mdev;
- dek_pool = mlx5_crypto_dek_pool_create(priv->mdev, MLX5_ACCEL_OBJ_TLS_KEY);
- if (IS_ERR(dek_pool)) {
- kfree(tls);
- return PTR_ERR(dek_pool);
- }
- tls->dek_pool = dek_pool;
priv->tls = tls;
mlx5e_tls_debugfs_init(tls, priv->dfs_root);
@@ -222,7 +215,6 @@ void mlx5e_ktls_cleanup(struct mlx5e_priv *priv)
debugfs_remove_recursive(tls->debugfs.dfs);
tls->debugfs.dfs = NULL;
- mlx5_crypto_dek_pool_destroy(tls->dek_pool);
kfree(priv->tls);
priv->tls = NULL;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
index 0e4c0a093293..d61be26a4df1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
@@ -846,7 +846,7 @@ bool mlx5e_ktls_handle_tx_skb(struct net_device *netdev, struct mlx5e_txqsq *sq,
tls_ctx = tls_get_ctx(skb->sk);
tls_netdev = rcu_dereference_bh(tls_ctx->netdev);
/* Don't WARN on NULL: if tls_device_down is running in parallel,
- * netdev might become NULL, even if tls_is_sk_tx_device_offloaded was
+ * netdev might become NULL, even if tls_is_skb_tx_device_offloaded was
* true. Rather continue processing this packet.
*/
if (WARN_ON_ONCE(tls_netdev && tls_netdev != netdev))
@@ -908,28 +908,51 @@ static void mlx5e_tls_tx_debugfs_init(struct mlx5e_tls *tls,
int mlx5e_ktls_init_tx(struct mlx5e_priv *priv)
{
+ struct mlx5_crypto_dek_pool *dek_pool;
struct mlx5e_tls *tls = priv->tls;
+ int err;
+
+ if (!mlx5e_is_ktls_device(priv->mdev))
+ return 0;
+
+ /* DEK pool could be used by either or both of TX and RX. But we have to
+ * put the creation here to avoid syndrome when doing devlink reload.
+ */
+ dek_pool = mlx5_crypto_dek_pool_create(priv->mdev, MLX5_ACCEL_OBJ_TLS_KEY);
+ if (IS_ERR(dek_pool))
+ return PTR_ERR(dek_pool);
+ tls->dek_pool = dek_pool;
if (!mlx5e_is_ktls_tx(priv->mdev))
return 0;
priv->tls->tx_pool = mlx5e_tls_tx_pool_init(priv->mdev, &priv->tls->sw_stats);
- if (!priv->tls->tx_pool)
- return -ENOMEM;
+ if (!priv->tls->tx_pool) {
+ err = -ENOMEM;
+ goto err_tx_pool_init;
+ }
mlx5e_tls_tx_debugfs_init(tls, tls->debugfs.dfs);
return 0;
+
+err_tx_pool_init:
+ mlx5_crypto_dek_pool_destroy(dek_pool);
+ return err;
}
void mlx5e_ktls_cleanup_tx(struct mlx5e_priv *priv)
{
if (!mlx5e_is_ktls_tx(priv->mdev))
- return;
+ goto dek_pool_destroy;
debugfs_remove_recursive(priv->tls->debugfs.dfs_tx);
priv->tls->debugfs.dfs_tx = NULL;
mlx5e_tls_tx_pool_cleanup(priv->tls->tx_pool);
priv->tls->tx_pool = NULL;
+
+dek_pool_destroy:
+ if (mlx5e_is_ktls_device(priv->mdev))
+ mlx5_crypto_dek_pool_destroy(priv->tls->dek_pool);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.h
index 2dd78dd4ad65..f87b65c560ea 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.h
@@ -49,11 +49,6 @@ mlx5e_ktls_rx_pending_resync_list(struct mlx5e_channel *c, int budget)
return budget && test_bit(MLX5E_SQ_STATE_PENDING_TLS_RX_RESYNC, &c->async_icosq.state);
}
-static inline bool mlx5e_ktls_skb_offloaded(struct sk_buff *skb)
-{
- return skb->sk && tls_is_sk_tx_device_offloaded(skb->sk);
-}
-
static inline void
mlx5e_ktls_handle_tx_wqe(struct mlx5_wqe_ctrl_seg *cseg,
struct mlx5e_accel_tx_tls_state *state)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
index 6b7b563f844a..592b165530ff 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
@@ -349,15 +349,6 @@ static void mlx5e_macsec_cleanup_sa(struct mlx5e_macsec *macsec,
sa->macsec_rule = NULL;
}
-static struct mlx5e_priv *macsec_netdev_priv(const struct net_device *dev)
-{
-#if IS_ENABLED(CONFIG_VLAN_8021Q)
- if (is_vlan_dev(dev))
- return netdev_priv(vlan_dev_priv(dev)->real_dev);
-#endif
- return netdev_priv(dev);
-}
-
static int mlx5e_macsec_init_sa(struct macsec_context *ctx,
struct mlx5e_macsec_sa *sa,
bool encrypt,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c
index 7fc901a6ec5f..414e28584881 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c
@@ -161,6 +161,7 @@ static int macsec_fs_tx_create_crypto_table_groups(struct mlx5e_flow_table *ft)
if (!in) {
kfree(ft->g);
+ ft->g = NULL;
return -ENOMEM;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
index bed0c2d043e7..5aa51d74f8b4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
@@ -135,6 +135,16 @@ static void arfs_del_rules(struct mlx5e_flow_steering *fs);
int mlx5e_arfs_disable(struct mlx5e_flow_steering *fs)
{
+ /* Moving to switchdev mode, fs->arfs is freed by mlx5e_nic_profile
+ * cleanup_rx callback and it is not recreated when
+ * mlx5e_uplink_rep_profile is loaded as mlx5e_create_flow_steering()
+ * is not called by the uplink_rep profile init_rx callback. Thus, if
+ * ntuple is set, moving to switchdev flow will enter this function
+ * with fs->arfs nullified.
+ */
+ if (!mlx5e_fs_get_arfs(fs))
+ return 0;
+
arfs_del_rules(fs);
return arfs_disable(fs);
@@ -570,10 +580,10 @@ static struct mlx5_flow_handle *arfs_add_rule(struct mlx5e_priv *priv,
if (IS_ERR(rule)) {
err = PTR_ERR(rule);
priv->channel_stats[arfs_rule->rxq]->rq.arfs_err++;
- mlx5e_dbg(HW, priv,
- "%s: add rule(filter id=%d, rq idx=%d, ip proto=0x%x) failed,err=%d\n",
- __func__, arfs_rule->filter_id, arfs_rule->rxq,
- tuple->ip_proto, err);
+ netdev_dbg(priv->netdev,
+ "%s: add rule(filter id=%d, rq idx=%d, ip proto=0x%x) failed,err=%d\n",
+ __func__, arfs_rule->filter_id, arfs_rule->rxq,
+ tuple->ip_proto, err);
}
out:
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
index ebee52a8361a..8705cffc747f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
@@ -275,10 +275,10 @@ static int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets
memcpy(priv->dcbx.tc_tsa, ets->tc_tsa, sizeof(ets->tc_tsa));
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
- mlx5e_dbg(HW, priv, "%s: prio_%d <=> tc_%d\n",
- __func__, i, ets->prio_tc[i]);
- mlx5e_dbg(HW, priv, "%s: tc_%d <=> tx_bw_%d%%, group_%d\n",
- __func__, i, tc_tx_bw[i], tc_group[i]);
+ netdev_dbg(priv->netdev, "%s: prio_%d <=> tc_%d\n",
+ __func__, i, ets->prio_tc[i]);
+ netdev_dbg(priv->netdev, "%s: tc_%d <=> tx_bw_%d%%, group_%d\n",
+ __func__, i, tc_tx_bw[i], tc_group[i]);
}
return err;
@@ -399,9 +399,9 @@ static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev,
}
if (!ret) {
- mlx5e_dbg(HW, priv,
- "%s: PFC per priority bit mask: 0x%x\n",
- __func__, pfc->pfc_en);
+ netdev_dbg(dev,
+ "%s: PFC per priority bit mask: 0x%x\n",
+ __func__, pfc->pfc_en);
}
return ret;
}
@@ -611,8 +611,8 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev,
}
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
- mlx5e_dbg(HW, priv, "%s: tc_%d <=> max_bw %d Gbps\n",
- __func__, i, max_bw_value[i]);
+ netdev_dbg(netdev, "%s: tc_%d <=> max_bw %d Gbps\n",
+ __func__, i, max_bw_value[i]);
}
return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit);
@@ -640,10 +640,10 @@ static u8 mlx5e_dcbnl_setall(struct net_device *netdev)
ets.tc_rx_bw[i] = cee_cfg->pg_bw_pct[i];
ets.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;
ets.prio_tc[i] = cee_cfg->prio_to_pg_map[i];
- mlx5e_dbg(HW, priv,
- "%s: Priority group %d: tx_bw %d, rx_bw %d, prio_tc %d\n",
- __func__, i, ets.tc_tx_bw[i], ets.tc_rx_bw[i],
- ets.prio_tc[i]);
+ netdev_dbg(netdev,
+ "%s: Priority group %d: tx_bw %d, rx_bw %d, prio_tc %d\n",
+ __func__, i, ets.tc_tx_bw[i], ets.tc_rx_bw[i],
+ ets.prio_tc[i]);
}
err = mlx5e_dbcnl_validate_ets(netdev, &ets, true);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 1f5a2110d31f..27861b68ced5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -1689,16 +1689,6 @@ static int mlx5e_set_fecparam(struct net_device *netdev,
return 0;
}
-static u32 mlx5e_get_msglevel(struct net_device *dev)
-{
- return ((struct mlx5e_priv *)netdev_priv(dev))->msglevel;
-}
-
-static void mlx5e_set_msglevel(struct net_device *dev, u32 val)
-{
- ((struct mlx5e_priv *)netdev_priv(dev))->msglevel = val;
-}
-
static int mlx5e_set_phys_id(struct net_device *dev,
enum ethtool_phys_id_state state)
{
@@ -1952,9 +1942,9 @@ int mlx5e_modify_rx_cqe_compression_locked(struct mlx5e_priv *priv, bool new_val
if (err)
return err;
- mlx5e_dbg(DRV, priv, "MLX5E: RxCqeCmprss was turned %s\n",
- MLX5E_GET_PFLAG(&priv->channels.params,
- MLX5E_PFLAG_RX_CQE_COMPRESS) ? "ON" : "OFF");
+ netdev_dbg(priv->netdev, "MLX5E: RxCqeCmprss was turned %s\n",
+ MLX5E_GET_PFLAG(&priv->channels.params,
+ MLX5E_PFLAG_RX_CQE_COMPRESS) ? "ON" : "OFF");
return 0;
}
@@ -2444,8 +2434,6 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
.get_priv_flags = mlx5e_get_priv_flags,
.set_priv_flags = mlx5e_set_priv_flags,
.self_test = mlx5e_self_test,
- .get_msglevel = mlx5e_get_msglevel,
- .set_msglevel = mlx5e_set_msglevel,
.get_fec_stats = mlx5e_get_fec_stats,
.get_fecparam = mlx5e_get_fecparam,
.set_fecparam = mlx5e_set_fecparam,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
index 33bfe4d7338b..934b0d5ce1b3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
@@ -283,7 +283,7 @@ static int __mlx5e_add_vlan_rule(struct mlx5e_flow_steering *fs,
if (IS_ERR(*rule_p)) {
err = PTR_ERR(*rule_p);
*rule_p = NULL;
- fs_err(fs, "%s: add rule failed\n", __func__);
+ fs_err(fs, "add rule failed\n");
}
return err;
@@ -395,8 +395,7 @@ int mlx5e_add_vlan_trap(struct mlx5e_flow_steering *fs, int trap_id, int tir_num
if (IS_ERR(rule)) {
err = PTR_ERR(rule);
fs->vlan->trap_rule = NULL;
- fs_err(fs, "%s: add VLAN trap rule failed, err %d\n",
- __func__, err);
+ fs_err(fs, "add VLAN trap rule failed, err %d\n", err);
return err;
}
fs->vlan->trap_rule = rule;
@@ -421,8 +420,7 @@ int mlx5e_add_mac_trap(struct mlx5e_flow_steering *fs, int trap_id, int tir_num)
if (IS_ERR(rule)) {
err = PTR_ERR(rule);
fs->l2.trap_rule = NULL;
- fs_err(fs, "%s: add MAC trap rule failed, err %d\n",
- __func__, err);
+ fs_err(fs, "add MAC trap rule failed, err %d\n", err);
return err;
}
fs->l2.trap_rule = rule;
@@ -763,7 +761,7 @@ static int mlx5e_add_promisc_rule(struct mlx5e_flow_steering *fs)
if (IS_ERR(*rule_p)) {
err = PTR_ERR(*rule_p);
*rule_p = NULL;
- fs_err(fs, "%s: add promiscuous rule failed\n", __func__);
+ fs_err(fs, "add promiscuous rule failed\n");
}
kvfree(spec);
return err;
@@ -995,7 +993,7 @@ static int mlx5e_add_l2_flow_rule(struct mlx5e_flow_steering *fs,
ai->rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
if (IS_ERR(ai->rule)) {
- fs_err(fs, "%s: add l2 rule(mac:%pM) failed\n", __func__, mv_dmac);
+ fs_err(fs, "add l2 rule(mac:%pM) failed\n", mv_dmac);
err = PTR_ERR(ai->rule);
ai->rule = NULL;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index a5bdf78955d7..f7b494125eee 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -1036,7 +1036,23 @@ static int mlx5e_modify_rq_state(struct mlx5e_rq *rq, int curr_state, int next_s
return err;
}
-static int mlx5e_rq_to_ready(struct mlx5e_rq *rq, int curr_state)
+static void mlx5e_flush_rq_cq(struct mlx5e_rq *rq)
+{
+ struct mlx5_cqwq *cqwq = &rq->cq.wq;
+ struct mlx5_cqe64 *cqe;
+
+ if (test_bit(MLX5E_RQ_STATE_MINI_CQE_ENHANCED, &rq->state)) {
+ while ((cqe = mlx5_cqwq_get_cqe_enahnced_comp(cqwq)))
+ mlx5_cqwq_pop(cqwq);
+ } else {
+ while ((cqe = mlx5_cqwq_get_cqe(cqwq)))
+ mlx5_cqwq_pop(cqwq);
+ }
+
+ mlx5_cqwq_update_db_record(cqwq);
+}
+
+int mlx5e_flush_rq(struct mlx5e_rq *rq, int curr_state)
{
struct net_device *dev = rq->netdev;
int err;
@@ -1046,6 +1062,10 @@ static int mlx5e_rq_to_ready(struct mlx5e_rq *rq, int curr_state)
netdev_err(dev, "Failed to move rq 0x%x to reset\n", rq->rqn);
return err;
}
+
+ mlx5e_free_rx_descs(rq);
+ mlx5e_flush_rq_cq(rq);
+
err = mlx5e_modify_rq_state(rq, MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY);
if (err) {
netdev_err(dev, "Failed to move rq 0x%x to ready\n", rq->rqn);
@@ -1055,13 +1075,6 @@ static int mlx5e_rq_to_ready(struct mlx5e_rq *rq, int curr_state)
return 0;
}
-int mlx5e_flush_rq(struct mlx5e_rq *rq, int curr_state)
-{
- mlx5e_free_rx_descs(rq);
-
- return mlx5e_rq_to_ready(rq, curr_state);
-}
-
static int mlx5e_modify_rq_vsd(struct mlx5e_rq *rq, bool vsd)
{
struct mlx5_core_dev *mdev = rq->mdev;
@@ -1285,11 +1298,13 @@ static int mlx5e_alloc_xdpsq_fifo(struct mlx5e_xdpsq *sq, int numa)
{
struct mlx5e_xdp_info_fifo *xdpi_fifo = &sq->db.xdpi_fifo;
int wq_sz = mlx5_wq_cyc_get_size(&sq->wq);
- int entries = wq_sz * MLX5_SEND_WQEBB_NUM_DS * 2; /* upper bound for maximum num of
- * entries of all xmit_modes.
- */
+ int entries;
size_t size;
+ /* upper bound for maximum num of entries of all xmit_modes. */
+ entries = roundup_pow_of_two(wq_sz * MLX5_SEND_WQEBB_NUM_DS *
+ MLX5E_XDP_FIFO_ENTRIES2DS_MAX_RATIO);
+
size = array_size(sizeof(*xdpi_fifo->xi), entries);
xdpi_fifo->xi = kvzalloc_node(size, GFP_KERNEL, numa);
if (!xdpi_fifo->xi)
@@ -2402,7 +2417,7 @@ static int mlx5e_channel_stats_alloc(struct mlx5e_priv *priv, int ix, int cpu)
/* Asymmetric dynamic memory allocation.
* Freed in mlx5e_priv_arrays_free, not on channel closure.
*/
- mlx5e_dbg(DRV, priv, "Creating channel stats %d\n", ix);
+ netdev_dbg(priv->netdev, "Creating channel stats %d\n", ix);
priv->channel_stats[ix] = kvzalloc_node(sizeof(**priv->channel_stats),
GFP_KERNEL, cpu_to_node(cpu));
if (!priv->channel_stats[ix])
@@ -2780,7 +2795,7 @@ int mlx5e_update_tx_netdev_queues(struct mlx5e_priv *priv)
if (MLX5E_GET_PFLAG(&priv->channels.params, MLX5E_PFLAG_TX_PORT_TS))
num_txqs += ntc;
- mlx5e_dbg(DRV, priv, "Setting num_txqs %d\n", num_txqs);
+ netdev_dbg(priv->netdev, "Setting num_txqs %d\n", num_txqs);
err = netif_set_real_num_tx_queues(priv->netdev, num_txqs);
if (err)
netdev_warn(priv->netdev, "netif_set_real_num_tx_queues failed, %d\n", err);
@@ -5253,6 +5268,7 @@ void mlx5e_destroy_q_counters(struct mlx5e_priv *priv)
static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
struct net_device *netdev)
{
+ const bool take_rtnl = netdev->reg_state == NETREG_REGISTERED;
struct mlx5e_priv *priv = netdev_priv(netdev);
struct mlx5e_flow_steering *fs;
int err;
@@ -5281,9 +5297,19 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
mlx5_core_err(mdev, "TLS initialization failed, %d\n", err);
mlx5e_health_create_reporters(priv);
+
+ /* If netdev is already registered (e.g. move from uplink to nic profile),
+ * RTNL lock must be held before triggering netdev notifiers.
+ */
+ if (take_rtnl)
+ rtnl_lock();
+
/* update XDP supported features */
mlx5e_set_xdp_feature(netdev);
+ if (take_rtnl)
+ rtnl_unlock();
+
return 0;
}
@@ -5586,7 +5612,6 @@ int mlx5e_priv_init(struct mlx5e_priv *priv,
/* priv init */
priv->mdev = mdev;
priv->netdev = netdev;
- priv->msglevel = MLX5E_MSG_LEVEL;
priv->max_nch = nch;
priv->max_opened_tc = 1;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 3e7041bd5705..99b3843396f3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -374,7 +374,9 @@ static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw,
struct mlx5_eswitch_rep *rep)
{
struct mlx5e_rep_sq *rep_sq, *tmp;
+ struct mlx5e_rep_sq_peer *sq_peer;
struct mlx5e_rep_priv *rpriv;
+ unsigned long i;
if (esw->mode != MLX5_ESWITCH_OFFLOADS)
return;
@@ -382,31 +384,78 @@ static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw,
rpriv = mlx5e_rep_to_rep_priv(rep);
list_for_each_entry_safe(rep_sq, tmp, &rpriv->vport_sqs_list, list) {
mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule);
- if (rep_sq->send_to_vport_rule_peer)
- mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule_peer);
+ xa_for_each(&rep_sq->sq_peer, i, sq_peer) {
+ if (sq_peer->rule)
+ mlx5_eswitch_del_send_to_vport_rule(sq_peer->rule);
+
+ xa_erase(&rep_sq->sq_peer, i);
+ kfree(sq_peer);
+ }
+
+ xa_destroy(&rep_sq->sq_peer);
list_del(&rep_sq->list);
kfree(rep_sq);
}
}
+static int mlx5e_sqs2vport_add_peers_rules(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep,
+ struct mlx5_devcom *devcom,
+ struct mlx5e_rep_sq *rep_sq, int i)
+{
+ struct mlx5_eswitch *peer_esw = NULL;
+ struct mlx5_flow_handle *flow_rule;
+ int tmp;
+
+ mlx5_devcom_for_each_peer_entry(devcom, MLX5_DEVCOM_ESW_OFFLOADS,
+ peer_esw, tmp) {
+ u16 peer_rule_idx = MLX5_CAP_GEN(peer_esw->dev, vhca_id);
+ struct mlx5e_rep_sq_peer *sq_peer;
+ int err;
+
+ sq_peer = kzalloc(sizeof(*sq_peer), GFP_KERNEL);
+ if (!sq_peer)
+ return -ENOMEM;
+
+ flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw,
+ rep, rep_sq->sqn);
+ if (IS_ERR(flow_rule)) {
+ kfree(sq_peer);
+ return PTR_ERR(flow_rule);
+ }
+
+ sq_peer->rule = flow_rule;
+ sq_peer->peer = peer_esw;
+ err = xa_insert(&rep_sq->sq_peer, peer_rule_idx, sq_peer, GFP_KERNEL);
+ if (err) {
+ kfree(sq_peer);
+ mlx5_eswitch_del_send_to_vport_rule(flow_rule);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw,
struct mlx5_eswitch_rep *rep,
u32 *sqns_array, int sqns_num)
{
- struct mlx5_eswitch *peer_esw = NULL;
struct mlx5_flow_handle *flow_rule;
struct mlx5e_rep_priv *rpriv;
struct mlx5e_rep_sq *rep_sq;
+ struct mlx5_devcom *devcom;
+ bool devcom_locked = false;
int err;
int i;
if (esw->mode != MLX5_ESWITCH_OFFLOADS)
return 0;
+ devcom = esw->dev->priv.devcom;
rpriv = mlx5e_rep_to_rep_priv(rep);
- if (mlx5_devcom_is_paired(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS))
- peer_esw = mlx5_devcom_get_peer_data(esw->dev->priv.devcom,
- MLX5_DEVCOM_ESW_OFFLOADS);
+ if (mlx5_devcom_comp_is_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS) &&
+ mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS))
+ devcom_locked = true;
for (i = 0; i < sqns_num; i++) {
rep_sq = kzalloc(sizeof(*rep_sq), GFP_KERNEL);
@@ -426,31 +475,30 @@ static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw,
rep_sq->send_to_vport_rule = flow_rule;
rep_sq->sqn = sqns_array[i];
- if (peer_esw) {
- flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw,
- rep, sqns_array[i]);
- if (IS_ERR(flow_rule)) {
- err = PTR_ERR(flow_rule);
+ xa_init(&rep_sq->sq_peer);
+ if (devcom_locked) {
+ err = mlx5e_sqs2vport_add_peers_rules(esw, rep, devcom, rep_sq, i);
+ if (err) {
mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule);
+ xa_destroy(&rep_sq->sq_peer);
kfree(rep_sq);
goto out_err;
}
- rep_sq->send_to_vport_rule_peer = flow_rule;
}
list_add(&rep_sq->list, &rpriv->vport_sqs_list);
}
- if (peer_esw)
- mlx5_devcom_release_peer_data(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ if (devcom_locked)
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
return 0;
out_err:
mlx5e_sqs2vport_stop(esw, rep);
- if (peer_esw)
- mlx5_devcom_release_peer_data(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ if (devcom_locked)
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
return err;
}
@@ -964,7 +1012,7 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv)
err = mlx5e_open_drop_rq(priv, &priv->drop_rq);
if (err) {
mlx5_core_err(mdev, "open drop rq failed, %d\n", err);
- return err;
+ goto err_rx_res_free;
}
err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, 0,
@@ -998,6 +1046,7 @@ err_destroy_rx_res:
mlx5e_rx_res_destroy(priv->rx_res);
err_close_drop_rq:
mlx5e_close_drop_rq(&priv->drop_rq);
+err_rx_res_free:
mlx5e_rx_res_free(priv->rx_res);
priv->rx_res = NULL;
err_free_fs:
@@ -1111,6 +1160,10 @@ static int mlx5e_init_rep_tx(struct mlx5e_priv *priv)
return err;
}
+ err = mlx5e_rep_neigh_init(rpriv);
+ if (err)
+ goto err_neigh_init;
+
if (rpriv->rep->vport == MLX5_VPORT_UPLINK) {
err = mlx5e_init_uplink_rep_tx(rpriv);
if (err)
@@ -1127,6 +1180,8 @@ err_ht_init:
if (rpriv->rep->vport == MLX5_VPORT_UPLINK)
mlx5e_cleanup_uplink_rep_tx(rpriv);
err_init_tx:
+ mlx5e_rep_neigh_cleanup(rpriv);
+err_neigh_init:
mlx5e_destroy_tises(priv);
return err;
}
@@ -1140,22 +1195,17 @@ static void mlx5e_cleanup_rep_tx(struct mlx5e_priv *priv)
if (rpriv->rep->vport == MLX5_VPORT_UPLINK)
mlx5e_cleanup_uplink_rep_tx(rpriv);
+ mlx5e_rep_neigh_cleanup(rpriv);
mlx5e_destroy_tises(priv);
}
static void mlx5e_rep_enable(struct mlx5e_priv *priv)
{
- struct mlx5e_rep_priv *rpriv = priv->ppriv;
-
mlx5e_set_netdev_mtu_boundaries(priv);
- mlx5e_rep_neigh_init(rpriv);
}
static void mlx5e_rep_disable(struct mlx5e_priv *priv)
{
- struct mlx5e_rep_priv *rpriv = priv->ppriv;
-
- mlx5e_rep_neigh_cleanup(rpriv);
}
static int mlx5e_update_rep_rx(struct mlx5e_priv *priv)
@@ -1205,7 +1255,6 @@ static int uplink_rep_async_event(struct notifier_block *nb, unsigned long event
static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
{
- struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct net_device *netdev = priv->netdev;
struct mlx5_core_dev *mdev = priv->mdev;
u16 max_mtu;
@@ -1227,7 +1276,6 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
mlx5_notifier_register(mdev, &priv->events_nb);
mlx5e_dcbnl_initialize(priv);
mlx5e_dcbnl_init_app(priv);
- mlx5e_rep_neigh_init(rpriv);
mlx5e_rep_bridge_init(priv);
netdev->wanted_features |= NETIF_F_HW_TC;
@@ -1242,7 +1290,6 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
{
- struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct mlx5_core_dev *mdev = priv->mdev;
rtnl_lock();
@@ -1252,7 +1299,6 @@ static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
rtnl_unlock();
mlx5e_rep_bridge_cleanup(priv);
- mlx5e_rep_neigh_cleanup(rpriv);
mlx5e_dcbnl_delete_app(priv);
mlx5_notifier_unregister(mdev, &priv->events_nb);
mlx5e_rep_tc_disable(priv);
@@ -1530,17 +1576,24 @@ static void *mlx5e_vport_rep_get_proto_dev(struct mlx5_eswitch_rep *rep)
return rpriv->netdev;
}
-static void mlx5e_vport_rep_event_unpair(struct mlx5_eswitch_rep *rep)
+static void mlx5e_vport_rep_event_unpair(struct mlx5_eswitch_rep *rep,
+ struct mlx5_eswitch *peer_esw)
{
+ u16 i = MLX5_CAP_GEN(peer_esw->dev, vhca_id);
struct mlx5e_rep_priv *rpriv;
struct mlx5e_rep_sq *rep_sq;
+ WARN_ON_ONCE(!peer_esw);
rpriv = mlx5e_rep_to_rep_priv(rep);
list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) {
- if (!rep_sq->send_to_vport_rule_peer)
+ struct mlx5e_rep_sq_peer *sq_peer = xa_load(&rep_sq->sq_peer, i);
+
+ if (!sq_peer || sq_peer->peer != peer_esw)
continue;
- mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule_peer);
- rep_sq->send_to_vport_rule_peer = NULL;
+
+ mlx5_eswitch_del_send_to_vport_rule(sq_peer->rule);
+ xa_erase(&rep_sq->sq_peer, i);
+ kfree(sq_peer);
}
}
@@ -1548,24 +1601,52 @@ static int mlx5e_vport_rep_event_pair(struct mlx5_eswitch *esw,
struct mlx5_eswitch_rep *rep,
struct mlx5_eswitch *peer_esw)
{
+ u16 i = MLX5_CAP_GEN(peer_esw->dev, vhca_id);
struct mlx5_flow_handle *flow_rule;
+ struct mlx5e_rep_sq_peer *sq_peer;
struct mlx5e_rep_priv *rpriv;
struct mlx5e_rep_sq *rep_sq;
+ int err;
rpriv = mlx5e_rep_to_rep_priv(rep);
list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) {
- if (rep_sq->send_to_vport_rule_peer)
+ sq_peer = xa_load(&rep_sq->sq_peer, i);
+
+ if (sq_peer && sq_peer->peer)
continue;
- flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, rep, rep_sq->sqn);
- if (IS_ERR(flow_rule))
+
+ flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, rep,
+ rep_sq->sqn);
+ if (IS_ERR(flow_rule)) {
+ err = PTR_ERR(flow_rule);
goto err_out;
- rep_sq->send_to_vport_rule_peer = flow_rule;
+ }
+
+ if (sq_peer) {
+ sq_peer->rule = flow_rule;
+ sq_peer->peer = peer_esw;
+ continue;
+ }
+ sq_peer = kzalloc(sizeof(*sq_peer), GFP_KERNEL);
+ if (!sq_peer) {
+ err = -ENOMEM;
+ goto err_sq_alloc;
+ }
+ err = xa_insert(&rep_sq->sq_peer, i, sq_peer, GFP_KERNEL);
+ if (err)
+ goto err_xa;
+ sq_peer->rule = flow_rule;
+ sq_peer->peer = peer_esw;
}
return 0;
+err_xa:
+ kfree(sq_peer);
+err_sq_alloc:
+ mlx5_eswitch_del_send_to_vport_rule(flow_rule);
err_out:
- mlx5e_vport_rep_event_unpair(rep);
- return PTR_ERR(flow_rule);
+ mlx5e_vport_rep_event_unpair(rep, peer_esw);
+ return err;
}
static int mlx5e_vport_rep_event(struct mlx5_eswitch *esw,
@@ -1578,7 +1659,7 @@ static int mlx5e_vport_rep_event(struct mlx5_eswitch *esw,
if (event == MLX5_SWITCHDEV_EVENT_PAIR)
err = mlx5e_vport_rep_event_pair(esw, rep, data);
else if (event == MLX5_SWITCHDEV_EVENT_UNPAIR)
- mlx5e_vport_rep_event_unpair(rep);
+ mlx5e_vport_rep_event_unpair(rep, data);
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
index 80b7f5079a5a..70640fa1ad7b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
@@ -225,9 +225,14 @@ struct mlx5e_encap_entry {
struct rcu_head rcu;
};
+struct mlx5e_rep_sq_peer {
+ struct mlx5_flow_handle *rule;
+ void *peer;
+};
+
struct mlx5e_rep_sq {
struct mlx5_flow_handle *send_to_vport_rule;
- struct mlx5_flow_handle *send_to_vport_rule_peer;
+ struct xarray sq_peer;
u32 sqn;
struct list_head list;
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 69634829558e..41d37159e027 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -390,10 +390,18 @@ static void mlx5e_dealloc_rx_wqe(struct mlx5e_rq *rq, u16 ix)
{
struct mlx5e_wqe_frag_info *wi = get_frag(rq, ix);
- if (rq->xsk_pool)
+ if (rq->xsk_pool) {
mlx5e_xsk_free_rx_wqe(wi);
- else
+ } else {
mlx5e_free_rx_wqe(rq, wi);
+
+ /* Avoid a second release of the wqe pages: dealloc is called
+ * for the same missing wqes on regular RQ flush and on regular
+ * RQ close. This happens when XSK RQs come into play.
+ */
+ for (int i = 0; i < rq->wqe.info.num_frags; i++, wi++)
+ wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
+ }
}
static void mlx5e_xsk_free_rx_wqes(struct mlx5e_rq *rq, u16 ix, int wqe_bulk)
@@ -491,9 +499,7 @@ mlx5e_add_skb_shared_info_frag(struct mlx5e_rq *rq, struct skb_shared_info *sinf
}
frag = &sinfo->frags[sinfo->nr_frags++];
- __skb_frag_set_page(frag, frag_page->page);
- skb_frag_off_set(frag, frag_offset);
- skb_frag_size_set(frag, len);
+ skb_frag_fill_page_desc(frag, frag_page->page, frag_offset, len);
if (page_is_pfmemalloc(frag_page->page))
xdp_buff_set_frag_pfmemalloc(xdp);
@@ -1745,11 +1751,11 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5e_wqe_frag_info *wi
prog = rcu_dereference(rq->xdp_prog);
if (prog && mlx5e_xdp_handle(rq, prog, &mxbuf)) {
- if (test_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
+ if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
struct mlx5e_wqe_frag_info *pwi;
for (pwi = head_wi; pwi < wi; pwi++)
- pwi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
+ pwi->frag_page->frags++;
}
return NULL; /* page/packet was consumed by XDP */
}
@@ -1819,12 +1825,8 @@ static void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
rq, wi, cqe, cqe_bcnt);
if (!skb) {
/* probably for XDP */
- if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
- /* do not return page to cache,
- * it will be returned on XDP_TX completion.
- */
- wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
- }
+ if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags))
+ wi->frag_page->frags++;
goto wq_cyc_pop;
}
@@ -1870,12 +1872,8 @@ static void mlx5e_handle_rx_cqe_rep(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
rq, wi, cqe, cqe_bcnt);
if (!skb) {
/* probably for XDP */
- if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
- /* do not return page to cache,
- * it will be returned on XDP_TX completion.
- */
- wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
- }
+ if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags))
+ wi->frag_page->frags++;
goto wq_cyc_pop;
}
@@ -2054,12 +2052,12 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
if (prog) {
if (mlx5e_xdp_handle(rq, prog, &mxbuf)) {
if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
- int i;
+ struct mlx5e_frag_page *pfp;
+
+ for (pfp = head_page; pfp < frag_page; pfp++)
+ pfp->frags++;
- for (i = 0; i < sinfo->nr_frags; i++)
- /* non-atomic */
- __set_bit(page_idx + i, wi->skip_release_bitmap);
- return NULL;
+ wi->linear_page.frags++;
}
mlx5e_page_release_fragmented(rq, &wi->linear_page);
return NULL; /* page/packet was consumed by XDP */
@@ -2157,7 +2155,7 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
cqe_bcnt, &mxbuf);
if (mlx5e_xdp_handle(rq, prog, &mxbuf)) {
if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags))
- __set_bit(page_idx, wi->skip_release_bitmap); /* non-atomic */
+ frag_page->frags++;
return NULL; /* page/packet was consumed by XDP */
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
index f1d9596905c6..4d77055abd4b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
@@ -30,7 +30,7 @@
* SOFTWARE.
*/
-#include "lib/mlx5.h"
+#include "lib/events.h"
#include "en.h"
#include "en_accel/ktls.h"
#include "en_accel/en_accel.h"
@@ -748,11 +748,22 @@ static const struct counter_desc vport_stats_desc[] = {
VPORT_COUNTER_OFF(transmitted_ib_multicast.octets) },
};
+static const struct counter_desc vport_loopback_stats_desc[] = {
+ { "vport_loopback_packets",
+ VPORT_COUNTER_OFF(local_loopback.packets) },
+ { "vport_loopback_bytes",
+ VPORT_COUNTER_OFF(local_loopback.octets) },
+};
+
#define NUM_VPORT_COUNTERS ARRAY_SIZE(vport_stats_desc)
+#define NUM_VPORT_LOOPBACK_COUNTERS(dev) \
+ (MLX5_CAP_GEN(dev, vport_counter_local_loopback) ? \
+ ARRAY_SIZE(vport_loopback_stats_desc) : 0)
static MLX5E_DECLARE_STATS_GRP_OP_NUM_STATS(vport)
{
- return NUM_VPORT_COUNTERS;
+ return NUM_VPORT_COUNTERS +
+ NUM_VPORT_LOOPBACK_COUNTERS(priv->mdev);
}
static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(vport)
@@ -761,6 +772,11 @@ static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(vport)
for (i = 0; i < NUM_VPORT_COUNTERS; i++)
strcpy(data + (idx++) * ETH_GSTRING_LEN, vport_stats_desc[i].format);
+
+ for (i = 0; i < NUM_VPORT_LOOPBACK_COUNTERS(priv->mdev); i++)
+ strcpy(data + (idx++) * ETH_GSTRING_LEN,
+ vport_loopback_stats_desc[i].format);
+
return idx;
}
@@ -771,6 +787,11 @@ static MLX5E_DECLARE_STATS_GRP_OP_FILL_STATS(vport)
for (i = 0; i < NUM_VPORT_COUNTERS; i++)
data[idx++] = MLX5E_READ_CTR64_BE(priv->stats.vport.query_vport_out,
vport_stats_desc, i);
+
+ for (i = 0; i < NUM_VPORT_LOOPBACK_COUNTERS(priv->mdev); i++)
+ data[idx++] = MLX5E_READ_CTR64_BE(priv->stats.vport.query_vport_out,
+ vport_loopback_stats_desc, i);
+
return idx;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index b9b1da751a3b..31708d5aa608 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -1639,7 +1639,8 @@ static void remove_unready_flow(struct mlx5e_tc_flow *flow)
uplink_priv = &rpriv->uplink_priv;
mutex_lock(&uplink_priv->unready_flows_lock);
- unready_flow_del(flow);
+ if (flow_flag_test(flow, NOT_READY))
+ unready_flow_del(flow);
mutex_unlock(&uplink_priv->unready_flows_lock);
}
@@ -1667,8 +1668,11 @@ int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *ro
{
struct mlx5e_priv *out_priv, *route_priv;
struct mlx5_core_dev *route_mdev;
+ struct mlx5_devcom *devcom;
struct mlx5_eswitch *esw;
u16 vhca_id;
+ int err;
+ int i;
out_priv = netdev_priv(out_dev);
esw = out_priv->mdev->priv.eswitch;
@@ -1676,28 +1680,25 @@ int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *ro
route_mdev = route_priv->mdev;
vhca_id = MLX5_CAP_GEN(route_mdev, vhca_id);
- if (mlx5_lag_is_active(out_priv->mdev)) {
- struct mlx5_devcom *devcom;
- int err;
-
- /* In lag case we may get devices from different eswitch instances.
- * If we failed to get vport num, it means, mostly, that we on the wrong
- * eswitch.
- */
- err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport);
- if (err != -ENOENT)
- return err;
-
- rcu_read_lock();
- devcom = out_priv->mdev->priv.devcom;
- esw = mlx5_devcom_get_peer_data_rcu(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
- err = esw ? mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport) : -ENODEV;
- rcu_read_unlock();
+ err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport);
+ if (!err)
+ return err;
+ if (!mlx5_lag_is_active(out_priv->mdev))
return err;
+
+ rcu_read_lock();
+ devcom = out_priv->mdev->priv.devcom;
+ err = -ENODEV;
+ mlx5_devcom_for_each_peer_entry_rcu(devcom, MLX5_DEVCOM_ESW_OFFLOADS,
+ esw, i) {
+ err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport);
+ if (!err)
+ break;
}
+ rcu_read_unlock();
- return mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport);
+ return err;
}
static int
@@ -1724,6 +1725,19 @@ verify_attr_actions(u32 actions, struct netlink_ext_ack *extack)
return 0;
}
+static bool
+has_encap_dests(struct mlx5_flow_attr *attr)
+{
+ struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
+ int out_index;
+
+ for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++)
+ if (esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)
+ return true;
+
+ return false;
+}
+
static int
post_process_attr(struct mlx5e_tc_flow *flow,
struct mlx5_flow_attr *attr,
@@ -1736,9 +1750,11 @@ post_process_attr(struct mlx5e_tc_flow *flow,
if (err)
goto err_out;
- err = mlx5e_tc_tun_encap_dests_set(flow->priv, flow, attr, extack, &vf_tun);
- if (err)
- goto err_out;
+ if (mlx5e_is_eswitch_flow(flow) && has_encap_dests(attr)) {
+ err = mlx5e_tc_tun_encap_dests_set(flow->priv, flow, attr, extack, &vf_tun);
+ if (err)
+ goto err_out;
+ }
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
err = mlx5e_tc_attach_mod_hdr(flow->priv, flow, attr);
@@ -1927,13 +1943,10 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
{
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
struct mlx5_flow_attr *attr = flow->attr;
- struct mlx5_esw_flow_attr *esw_attr;
- esw_attr = attr->esw_attr;
mlx5e_put_flow_tunnel_id(flow);
- if (flow_flag_test(flow, NOT_READY))
- remove_unready_flow(flow);
+ remove_unready_flow(flow);
if (mlx5e_is_offloaded_flow(flow)) {
if (flow_flag_test(flow, SLOW))
@@ -1951,12 +1964,6 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
mlx5_tc_ct_match_del(get_ct_priv(priv), &flow->attr->ct_attr);
- if (esw_attr->int_port)
- mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(priv), esw_attr->int_port);
-
- if (esw_attr->dest_int_port)
- mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(priv), esw_attr->dest_int_port);
-
if (flow_flag_test(flow, L3_TO_L2_DECAP))
mlx5e_detach_decap(priv, flow);
@@ -1987,47 +1994,59 @@ void mlx5e_put_flow_list(struct mlx5e_priv *priv, struct list_head *flow_list)
mlx5e_flow_put(priv, flow);
}
-static void __mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow)
+static void mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow,
+ int peer_index)
{
struct mlx5_eswitch *esw = flow->priv->mdev->priv.eswitch;
+ struct mlx5e_tc_flow *peer_flow;
+ struct mlx5e_tc_flow *tmp;
if (!flow_flag_test(flow, ESWITCH) ||
!flow_flag_test(flow, DUP))
return;
mutex_lock(&esw->offloads.peer_mutex);
- list_del(&flow->peer);
+ list_del(&flow->peer[peer_index]);
mutex_unlock(&esw->offloads.peer_mutex);
- flow_flag_clear(flow, DUP);
-
- if (refcount_dec_and_test(&flow->peer_flow->refcnt)) {
- mlx5e_tc_del_fdb_flow(flow->peer_flow->priv, flow->peer_flow);
- kfree(flow->peer_flow);
+ list_for_each_entry_safe(peer_flow, tmp, &flow->peer_flows, peer_flows) {
+ if (peer_index != mlx5_get_dev_index(peer_flow->priv->mdev))
+ continue;
+ if (refcount_dec_and_test(&peer_flow->refcnt)) {
+ mlx5e_tc_del_fdb_flow(peer_flow->priv, peer_flow);
+ list_del(&peer_flow->peer_flows);
+ kfree(peer_flow);
+ }
}
- flow->peer_flow = NULL;
+ if (list_empty(&flow->peer_flows))
+ flow_flag_clear(flow, DUP);
}
-static void mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow)
+static void mlx5e_tc_del_fdb_peers_flow(struct mlx5e_tc_flow *flow)
{
- struct mlx5_core_dev *dev = flow->priv->mdev;
- struct mlx5_devcom *devcom = dev->priv.devcom;
- struct mlx5_eswitch *peer_esw;
-
- peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
- if (!peer_esw)
- return;
+ int i;
- __mlx5e_tc_del_fdb_peer_flow(flow);
- mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ for (i = 0; i < MLX5_MAX_PORTS; i++) {
+ if (i == mlx5_get_dev_index(flow->priv->mdev))
+ continue;
+ mlx5e_tc_del_fdb_peer_flow(flow, i);
+ }
}
static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
struct mlx5e_tc_flow *flow)
{
if (mlx5e_is_eswitch_flow(flow)) {
- mlx5e_tc_del_fdb_peer_flow(flow);
+ struct mlx5_devcom *devcom = flow->priv->mdev->priv.devcom;
+
+ if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) {
+ mlx5e_tc_del_fdb_flow(priv, flow);
+ return;
+ }
+
+ mlx5e_tc_del_fdb_peers_flow(flow);
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
mlx5e_tc_del_fdb_flow(priv, flow);
} else {
mlx5e_tc_del_nic_flow(priv, flow);
@@ -2503,6 +2522,12 @@ static int mlx5e_flower_parse_meta(struct net_device *filter_dev,
return 0;
flow_rule_match_meta(rule, &match);
+
+ if (match.mask->l2_miss) {
+ NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on \"l2_miss\"");
+ return -EOPNOTSUPP;
+ }
+
if (!match.mask->ingress_ifindex)
return 0;
@@ -4198,8 +4223,8 @@ static bool is_peer_flow_needed(struct mlx5e_tc_flow *flow)
flow_flag_test(flow, INGRESS);
bool act_is_encap = !!(attr->action &
MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT);
- bool esw_paired = mlx5_devcom_is_paired(esw_attr->in_mdev->priv.devcom,
- MLX5_DEVCOM_ESW_OFFLOADS);
+ bool esw_paired = mlx5_devcom_comp_is_ready(esw_attr->in_mdev->priv.devcom,
+ MLX5_DEVCOM_ESW_OFFLOADS);
if (!esw_paired)
return false;
@@ -4235,6 +4260,7 @@ static void
mlx5_free_flow_attr_actions(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr)
{
struct mlx5_core_dev *counter_dev = get_flow_counter_dev(flow);
+ struct mlx5_esw_flow_attr *esw_attr;
if (!attr)
return;
@@ -4252,6 +4278,18 @@ mlx5_free_flow_attr_actions(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *a
mlx5e_tc_detach_mod_hdr(flow->priv, flow, attr);
}
+ if (mlx5e_is_eswitch_flow(flow)) {
+ esw_attr = attr->esw_attr;
+
+ if (esw_attr->int_port)
+ mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(flow->priv),
+ esw_attr->int_port);
+
+ if (esw_attr->dest_int_port)
+ mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(flow->priv),
+ esw_attr->dest_int_port);
+ }
+
mlx5_tc_ct_delete_flow(get_ct_priv(flow->priv), attr);
free_branch_attr(flow, attr->branch_true);
@@ -4290,6 +4328,7 @@ mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size,
INIT_LIST_HEAD(&flow->hairpin);
INIT_LIST_HEAD(&flow->l3_to_l2_reformat);
INIT_LIST_HEAD(&flow->attrs);
+ INIT_LIST_HEAD(&flow->peer_flows);
refcount_set(&flow->refcnt, 1);
init_completion(&flow->init_done);
init_completion(&flow->del_hw_done);
@@ -4398,22 +4437,19 @@ out:
static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f,
struct mlx5e_tc_flow *flow,
- unsigned long flow_flags)
+ unsigned long flow_flags,
+ struct mlx5_eswitch *peer_esw)
{
struct mlx5e_priv *priv = flow->priv, *peer_priv;
- struct mlx5_eswitch *esw = priv->mdev->priv.eswitch, *peer_esw;
+ struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
struct mlx5_esw_flow_attr *attr = flow->attr->esw_attr;
- struct mlx5_devcom *devcom = priv->mdev->priv.devcom;
struct mlx5e_tc_flow_parse_attr *parse_attr;
+ int i = mlx5_get_dev_index(peer_esw->dev);
struct mlx5e_rep_priv *peer_urpriv;
struct mlx5e_tc_flow *peer_flow;
struct mlx5_core_dev *in_mdev;
int err = 0;
- peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
- if (!peer_esw)
- return -ENODEV;
-
peer_urpriv = mlx5_eswitch_get_uplink_priv(peer_esw, REP_ETH);
peer_priv = netdev_priv(peer_urpriv->netdev);
@@ -4438,14 +4474,13 @@ static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f,
goto out;
}
- flow->peer_flow = peer_flow;
+ list_add_tail(&peer_flow->peer_flows, &flow->peer_flows);
flow_flag_set(flow, DUP);
mutex_lock(&esw->offloads.peer_mutex);
- list_add_tail(&flow->peer, &esw->offloads.peer_flows);
+ list_add_tail(&flow->peer[i], &esw->offloads.peer_flows[i]);
mutex_unlock(&esw->offloads.peer_mutex);
out:
- mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
return err;
}
@@ -4456,30 +4491,48 @@ mlx5e_add_fdb_flow(struct mlx5e_priv *priv,
struct net_device *filter_dev,
struct mlx5e_tc_flow **__flow)
{
+ struct mlx5_devcom *devcom = priv->mdev->priv.devcom;
struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct mlx5_eswitch_rep *in_rep = rpriv->rep;
struct mlx5_core_dev *in_mdev = priv->mdev;
+ struct mlx5_eswitch *peer_esw;
struct mlx5e_tc_flow *flow;
int err;
+ int i;
flow = __mlx5e_add_fdb_flow(priv, f, flow_flags, filter_dev, in_rep,
in_mdev);
if (IS_ERR(flow))
return PTR_ERR(flow);
- if (is_peer_flow_needed(flow)) {
- err = mlx5e_tc_add_fdb_peer_flow(f, flow, flow_flags);
- if (err) {
- mlx5e_tc_del_fdb_flow(priv, flow);
- goto out;
- }
+ if (!is_peer_flow_needed(flow)) {
+ *__flow = flow;
+ return 0;
}
- *__flow = flow;
+ if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) {
+ err = -ENODEV;
+ goto clean_flow;
+ }
+ mlx5_devcom_for_each_peer_entry(devcom,
+ MLX5_DEVCOM_ESW_OFFLOADS,
+ peer_esw, i) {
+ err = mlx5e_tc_add_fdb_peer_flow(f, flow, flow_flags, peer_esw);
+ if (err)
+ goto peer_clean;
+ }
+
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+
+ *__flow = flow;
return 0;
-out:
+peer_clean:
+ mlx5e_tc_del_fdb_peers_flow(flow);
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+clean_flow:
+ mlx5e_tc_del_fdb_flow(priv, flow);
return err;
}
@@ -4697,7 +4750,6 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
{
struct mlx5_devcom *devcom = priv->mdev->priv.devcom;
struct rhashtable *tc_ht = get_tc_ht(priv, flags);
- struct mlx5_eswitch *peer_esw;
struct mlx5e_tc_flow *flow;
struct mlx5_fc *counter;
u64 lastuse = 0;
@@ -4732,23 +4784,29 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
/* Under multipath it's possible for one rule to be currently
* un-offloaded while the other rule is offloaded.
*/
- peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
- if (!peer_esw)
+ if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS))
goto out;
- if (flow_flag_test(flow, DUP) &&
- flow_flag_test(flow->peer_flow, OFFLOADED)) {
- u64 bytes2;
- u64 packets2;
- u64 lastuse2;
+ if (flow_flag_test(flow, DUP)) {
+ struct mlx5e_tc_flow *peer_flow;
- if (flow_flag_test(flow, USE_ACT_STATS)) {
- f->use_act_stats = true;
- } else {
- counter = mlx5e_tc_get_counter(flow->peer_flow);
+ list_for_each_entry(peer_flow, &flow->peer_flows, peer_flows) {
+ u64 packets2;
+ u64 lastuse2;
+ u64 bytes2;
+
+ if (!flow_flag_test(peer_flow, OFFLOADED))
+ continue;
+ if (flow_flag_test(flow, USE_ACT_STATS)) {
+ f->use_act_stats = true;
+ break;
+ }
+
+ counter = mlx5e_tc_get_counter(peer_flow);
if (!counter)
goto no_peer_counter;
- mlx5_fc_query_cached(counter, &bytes2, &packets2, &lastuse2);
+ mlx5_fc_query_cached(counter, &bytes2, &packets2,
+ &lastuse2);
bytes += bytes2;
packets += packets2;
@@ -4757,7 +4815,7 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
}
no_peer_counter:
- mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
out:
flow_stats_update(&f->stats, bytes, packets, 0, lastuse,
FLOW_ACTION_HW_STATS_DELAYED);
@@ -5275,9 +5333,14 @@ int mlx5e_tc_num_filters(struct mlx5e_priv *priv, unsigned long flags)
void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw)
{
struct mlx5e_tc_flow *flow, *tmp;
+ int i;
- list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows, peer)
- __mlx5e_tc_del_fdb_peer_flow(flow);
+ for (i = 0; i < MLX5_MAX_PORTS; i++) {
+ if (i == mlx5_get_dev_index(esw->dev))
+ continue;
+ list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows[i], peer[i])
+ mlx5e_tc_del_fdb_peers_flow(flow);
+ }
}
void mlx5e_tc_reoffload_flows_work(struct work_struct *work)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
index fbb2d963fb7e..a7d9b7cb4297 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
@@ -207,7 +207,7 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget)
}
ch_stats->aff_change++;
aff_change = true;
- if (budget && work_done == budget)
+ if (work_done == budget)
work_done--;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c
index 2e504c7461c6..24b1ca4e4ff8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c
@@ -15,13 +15,27 @@ static void esw_acl_egress_ofld_fwd2vport_destroy(struct mlx5_vport *vport)
vport->egress.offloads.fwd_rule = NULL;
}
-static void esw_acl_egress_ofld_bounce_rule_destroy(struct mlx5_vport *vport)
+void esw_acl_egress_ofld_bounce_rule_destroy(struct mlx5_vport *vport, int rule_index)
{
- if (!vport->egress.offloads.bounce_rule)
+ struct mlx5_flow_handle *bounce_rule =
+ xa_load(&vport->egress.offloads.bounce_rules, rule_index);
+
+ if (!bounce_rule)
return;
- mlx5_del_flow_rules(vport->egress.offloads.bounce_rule);
- vport->egress.offloads.bounce_rule = NULL;
+ mlx5_del_flow_rules(bounce_rule);
+ xa_erase(&vport->egress.offloads.bounce_rules, rule_index);
+}
+
+static void esw_acl_egress_ofld_bounce_rules_destroy(struct mlx5_vport *vport)
+{
+ struct mlx5_flow_handle *bounce_rule;
+ unsigned long i;
+
+ xa_for_each(&vport->egress.offloads.bounce_rules, i, bounce_rule) {
+ mlx5_del_flow_rules(bounce_rule);
+ xa_erase(&vport->egress.offloads.bounce_rules, i);
+ }
}
static int esw_acl_egress_ofld_fwd2vport_create(struct mlx5_eswitch *esw,
@@ -96,7 +110,7 @@ static void esw_acl_egress_ofld_rules_destroy(struct mlx5_vport *vport)
{
esw_acl_egress_vlan_destroy(vport);
esw_acl_egress_ofld_fwd2vport_destroy(vport);
- esw_acl_egress_ofld_bounce_rule_destroy(vport);
+ esw_acl_egress_ofld_bounce_rules_destroy(vport);
}
static int esw_acl_egress_ofld_groups_create(struct mlx5_eswitch *esw,
@@ -194,6 +208,7 @@ int esw_acl_egress_ofld_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport
vport->egress.acl = NULL;
return err;
}
+ vport->egress.type = VPORT_EGRESS_ACL_TYPE_DEFAULT;
err = esw_acl_egress_ofld_groups_create(esw, vport);
if (err)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c
index 45b839116212..d599e50af346 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c
@@ -35,7 +35,8 @@ esw_acl_table_create(struct mlx5_eswitch *esw, struct mlx5_vport *vport, int ns,
}
ft_attr.max_fte = size;
- ft_attr.flags = MLX5_FLOW_TABLE_OTHER_VPORT;
+ if (vport_num || mlx5_core_is_ecpf(esw->dev))
+ ft_attr.flags = MLX5_FLOW_TABLE_OTHER_VPORT;
acl = mlx5_create_vport_flow_table(root_ns, &ft_attr, vport_num);
if (IS_ERR(acl)) {
err = PTR_ERR(acl);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h
index c9f8469e9a47..536b04e83618 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h
@@ -10,6 +10,7 @@
/* Eswitch acl egress external APIs */
int esw_acl_egress_ofld_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport);
void esw_acl_egress_ofld_cleanup(struct mlx5_vport *vport);
+void esw_acl_egress_ofld_bounce_rule_destroy(struct mlx5_vport *vport, int rule_index);
int mlx5_esw_acl_egress_vport_bond(struct mlx5_eswitch *esw, u16 active_vport_num,
u16 passive_vport_num);
int mlx5_esw_acl_egress_vport_unbond(struct mlx5_eswitch *esw, u16 vport_num);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
index 1ba03e219111..f4fe1daa4afd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
@@ -647,22 +647,35 @@ mlx5_esw_bridge_ingress_flow_create(u16 vport_num, const unsigned char *addr,
}
static struct mlx5_flow_handle *
-mlx5_esw_bridge_ingress_flow_peer_create(u16 vport_num, const unsigned char *addr,
+mlx5_esw_bridge_ingress_flow_peer_create(u16 vport_num, u16 esw_owner_vhca_id,
+ const unsigned char *addr,
struct mlx5_esw_bridge_vlan *vlan, u32 counter_id,
struct mlx5_esw_bridge *bridge)
{
struct mlx5_devcom *devcom = bridge->br_offloads->esw->dev->priv.devcom;
+ struct mlx5_eswitch *tmp, *peer_esw = NULL;
static struct mlx5_flow_handle *handle;
- struct mlx5_eswitch *peer_esw;
+ int i;
- peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
- if (!peer_esw)
+ if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS))
return ERR_PTR(-ENODEV);
+ mlx5_devcom_for_each_peer_entry(devcom,
+ MLX5_DEVCOM_ESW_OFFLOADS,
+ tmp, i) {
+ if (mlx5_esw_is_owner(tmp, vport_num, esw_owner_vhca_id)) {
+ peer_esw = tmp;
+ break;
+ }
+ }
+ if (!peer_esw) {
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ return ERR_PTR(-ENODEV);
+ }
+
handle = mlx5_esw_bridge_ingress_flow_with_esw_create(vport_num, addr, vlan, counter_id,
bridge, peer_esw);
-
- mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
return handle;
}
@@ -821,7 +834,7 @@ mlx5_esw_bridge_egress_miss_flow_create(struct mlx5_flow_table *egress_ft,
return handle;
}
-static struct mlx5_esw_bridge *mlx5_esw_bridge_create(int ifindex,
+static struct mlx5_esw_bridge *mlx5_esw_bridge_create(struct net_device *br_netdev,
struct mlx5_esw_bridge_offloads *br_offloads)
{
struct mlx5_esw_bridge *bridge;
@@ -845,11 +858,12 @@ static struct mlx5_esw_bridge *mlx5_esw_bridge_create(int ifindex,
goto err_mdb_ht;
INIT_LIST_HEAD(&bridge->fdb_list);
- bridge->ifindex = ifindex;
+ bridge->ifindex = br_netdev->ifindex;
bridge->refcnt = 1;
bridge->ageing_time = clock_t_to_jiffies(BR_DEFAULT_AGEING_TIME);
bridge->vlan_proto = ETH_P_8021Q;
list_add(&bridge->list, &br_offloads->bridges);
+ mlx5_esw_bridge_debugfs_init(br_netdev, bridge);
return bridge;
@@ -873,6 +887,7 @@ static void mlx5_esw_bridge_put(struct mlx5_esw_bridge_offloads *br_offloads,
if (--bridge->refcnt)
return;
+ mlx5_esw_bridge_debugfs_cleanup(bridge);
mlx5_esw_bridge_egress_table_cleanup(bridge);
mlx5_esw_bridge_mcast_disable(bridge);
list_del(&bridge->list);
@@ -885,14 +900,14 @@ static void mlx5_esw_bridge_put(struct mlx5_esw_bridge_offloads *br_offloads,
}
static struct mlx5_esw_bridge *
-mlx5_esw_bridge_lookup(int ifindex, struct mlx5_esw_bridge_offloads *br_offloads)
+mlx5_esw_bridge_lookup(struct net_device *br_netdev, struct mlx5_esw_bridge_offloads *br_offloads)
{
struct mlx5_esw_bridge *bridge;
ASSERT_RTNL();
list_for_each_entry(bridge, &br_offloads->bridges, list) {
- if (bridge->ifindex == ifindex) {
+ if (bridge->ifindex == br_netdev->ifindex) {
mlx5_esw_bridge_get(bridge);
return bridge;
}
@@ -905,7 +920,7 @@ mlx5_esw_bridge_lookup(int ifindex, struct mlx5_esw_bridge_offloads *br_offloads
return ERR_PTR(err);
}
- bridge = mlx5_esw_bridge_create(ifindex, br_offloads);
+ bridge = mlx5_esw_bridge_create(br_netdev, br_offloads);
if (IS_ERR(bridge) && list_empty(&br_offloads->bridges))
mlx5_esw_bridge_ingress_table_cleanup(br_offloads);
return bridge;
@@ -1369,8 +1384,9 @@ mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_ow
entry->ingress_counter = counter;
handle = peer ?
- mlx5_esw_bridge_ingress_flow_peer_create(vport_num, addr, vlan,
- mlx5_fc_id(counter), bridge) :
+ mlx5_esw_bridge_ingress_flow_peer_create(vport_num, esw_owner_vhca_id,
+ addr, vlan, mlx5_fc_id(counter),
+ bridge) :
mlx5_esw_bridge_ingress_flow_create(vport_num, addr, vlan,
mlx5_fc_id(counter), bridge);
if (IS_ERR(handle)) {
@@ -1587,15 +1603,15 @@ static int mlx5_esw_bridge_vport_cleanup(struct mlx5_esw_bridge_offloads *br_off
return 0;
}
-static int mlx5_esw_bridge_vport_link_with_flags(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
- u16 flags,
+static int mlx5_esw_bridge_vport_link_with_flags(struct net_device *br_netdev, u16 vport_num,
+ u16 esw_owner_vhca_id, u16 flags,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack)
{
struct mlx5_esw_bridge *bridge;
int err;
- bridge = mlx5_esw_bridge_lookup(ifindex, br_offloads);
+ bridge = mlx5_esw_bridge_lookup(br_netdev, br_offloads);
if (IS_ERR(bridge)) {
NL_SET_ERR_MSG_MOD(extack, "Error checking for existing bridge with same ifindex");
return PTR_ERR(bridge);
@@ -1613,15 +1629,16 @@ err_vport:
return err;
}
-int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
+int mlx5_esw_bridge_vport_link(struct net_device *br_netdev, u16 vport_num, u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack)
{
- return mlx5_esw_bridge_vport_link_with_flags(ifindex, vport_num, esw_owner_vhca_id, 0,
+ return mlx5_esw_bridge_vport_link_with_flags(br_netdev, vport_num, esw_owner_vhca_id, 0,
br_offloads, extack);
}
-int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
+int mlx5_esw_bridge_vport_unlink(struct net_device *br_netdev, u16 vport_num,
+ u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack)
{
@@ -1633,7 +1650,7 @@ int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_
NL_SET_ERR_MSG_MOD(extack, "Port is not attached to any bridge");
return -EINVAL;
}
- if (port->bridge->ifindex != ifindex) {
+ if (port->bridge->ifindex != br_netdev->ifindex) {
NL_SET_ERR_MSG_MOD(extack, "Port is attached to another bridge");
return -EINVAL;
}
@@ -1644,23 +1661,25 @@ int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_
return err;
}
-int mlx5_esw_bridge_vport_peer_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
+int mlx5_esw_bridge_vport_peer_link(struct net_device *br_netdev, u16 vport_num,
+ u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack)
{
if (!MLX5_CAP_ESW(br_offloads->esw->dev, merged_eswitch))
return 0;
- return mlx5_esw_bridge_vport_link_with_flags(ifindex, vport_num, esw_owner_vhca_id,
+ return mlx5_esw_bridge_vport_link_with_flags(br_netdev, vport_num, esw_owner_vhca_id,
MLX5_ESW_BRIDGE_PORT_FLAG_PEER,
br_offloads, extack);
}
-int mlx5_esw_bridge_vport_peer_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
+int mlx5_esw_bridge_vport_peer_unlink(struct net_device *br_netdev, u16 vport_num,
+ u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack)
{
- return mlx5_esw_bridge_vport_unlink(ifindex, vport_num, esw_owner_vhca_id, br_offloads,
+ return mlx5_esw_bridge_vport_unlink(br_netdev, vport_num, esw_owner_vhca_id, br_offloads,
extack);
}
@@ -1887,6 +1906,7 @@ struct mlx5_esw_bridge_offloads *mlx5_esw_bridge_init(struct mlx5_eswitch *esw)
xa_init(&br_offloads->ports);
br_offloads->esw = esw;
esw->br_offloads = br_offloads;
+ mlx5_esw_bridge_debugfs_offloads_init(br_offloads);
return br_offloads;
}
@@ -1902,6 +1922,7 @@ void mlx5_esw_bridge_cleanup(struct mlx5_eswitch *esw)
mlx5_esw_bridge_flush(br_offloads);
WARN_ON(!xa_empty(&br_offloads->ports));
+ mlx5_esw_bridge_debugfs_offloads_cleanup(br_offloads);
esw->br_offloads = NULL;
kvfree(br_offloads);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h
index a9dd18c73d6a..c2c7c70d99eb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h
@@ -10,6 +10,7 @@
#include <linux/xarray.h>
#include "eswitch.h"
+struct dentry;
struct mlx5_flow_table;
struct mlx5_flow_group;
@@ -17,6 +18,7 @@ struct mlx5_esw_bridge_offloads {
struct mlx5_eswitch *esw;
struct list_head bridges;
struct xarray ports;
+ struct dentry *debugfs_root;
struct notifier_block netdev_nb;
struct notifier_block nb_blk;
@@ -43,16 +45,18 @@ struct mlx5_esw_bridge_offloads {
struct mlx5_esw_bridge_offloads *mlx5_esw_bridge_init(struct mlx5_eswitch *esw);
void mlx5_esw_bridge_cleanup(struct mlx5_eswitch *esw);
-int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
+int mlx5_esw_bridge_vport_link(struct net_device *br_netdev, u16 vport_num, u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack);
-int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
+int mlx5_esw_bridge_vport_unlink(struct net_device *br_netdev, u16 vport_num, u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack);
-int mlx5_esw_bridge_vport_peer_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
+int mlx5_esw_bridge_vport_peer_link(struct net_device *br_netdev, u16 vport_num,
+ u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack);
-int mlx5_esw_bridge_vport_peer_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
+int mlx5_esw_bridge_vport_peer_unlink(struct net_device *br_netdev, u16 vport_num,
+ u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack);
void mlx5_esw_bridge_fdb_update_used(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_debugfs.c
new file mode 100644
index 000000000000..dbd7cbe6cbf3
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_debugfs.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
+
+#include <linux/debugfs.h>
+#include "bridge.h"
+#include "bridge_priv.h"
+
+static void *mlx5_esw_bridge_debugfs_start(struct seq_file *seq, loff_t *pos);
+static void *mlx5_esw_bridge_debugfs_next(struct seq_file *seq, void *v, loff_t *pos);
+static void mlx5_esw_bridge_debugfs_stop(struct seq_file *seq, void *v);
+static int mlx5_esw_bridge_debugfs_show(struct seq_file *seq, void *v);
+
+static const struct seq_operations mlx5_esw_bridge_debugfs_sops = {
+ .start = mlx5_esw_bridge_debugfs_start,
+ .next = mlx5_esw_bridge_debugfs_next,
+ .stop = mlx5_esw_bridge_debugfs_stop,
+ .show = mlx5_esw_bridge_debugfs_show,
+};
+DEFINE_SEQ_ATTRIBUTE(mlx5_esw_bridge_debugfs);
+
+static void *mlx5_esw_bridge_debugfs_start(struct seq_file *seq, loff_t *pos)
+{
+ struct mlx5_esw_bridge *bridge = seq->private;
+
+ rtnl_lock();
+ return *pos ? seq_list_start(&bridge->fdb_list, *pos - 1) : SEQ_START_TOKEN;
+}
+
+static void *mlx5_esw_bridge_debugfs_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct mlx5_esw_bridge *bridge = seq->private;
+
+ return seq_list_next(v == SEQ_START_TOKEN ? &bridge->fdb_list : v, &bridge->fdb_list, pos);
+}
+
+static void mlx5_esw_bridge_debugfs_stop(struct seq_file *seq, void *v)
+{
+ rtnl_unlock();
+}
+
+static int mlx5_esw_bridge_debugfs_show(struct seq_file *seq, void *v)
+{
+ struct mlx5_esw_bridge_fdb_entry *entry;
+ u64 packets, bytes, lastuse;
+
+ if (v == SEQ_START_TOKEN) {
+ seq_printf(seq, "%-16s %-17s %4s %20s %20s %20s %5s\n",
+ "DEV", "MAC", "VLAN", "PACKETS", "BYTES", "LASTUSE", "FLAGS");
+ return 0;
+ }
+
+ entry = list_entry(v, struct mlx5_esw_bridge_fdb_entry, list);
+ mlx5_fc_query_cached_raw(entry->ingress_counter, &bytes, &packets, &lastuse);
+ seq_printf(seq, "%-16s %-17pM %4d %20llu %20llu %20llu %#5x\n",
+ entry->dev->name, entry->key.addr, entry->key.vid, packets, bytes, lastuse,
+ entry->flags);
+ return 0;
+}
+
+void mlx5_esw_bridge_debugfs_init(struct net_device *br_netdev, struct mlx5_esw_bridge *bridge)
+{
+ if (!bridge->br_offloads->debugfs_root)
+ return;
+
+ bridge->debugfs_dir = debugfs_create_dir(br_netdev->name,
+ bridge->br_offloads->debugfs_root);
+ debugfs_create_file("fdb", 0400, bridge->debugfs_dir, bridge,
+ &mlx5_esw_bridge_debugfs_fops);
+}
+
+void mlx5_esw_bridge_debugfs_cleanup(struct mlx5_esw_bridge *bridge)
+{
+ debugfs_remove_recursive(bridge->debugfs_dir);
+ bridge->debugfs_dir = NULL;
+}
+
+void mlx5_esw_bridge_debugfs_offloads_init(struct mlx5_esw_bridge_offloads *br_offloads)
+{
+ if (!br_offloads->esw->debugfs_root)
+ return;
+
+ br_offloads->debugfs_root = debugfs_create_dir("bridge", br_offloads->esw->debugfs_root);
+}
+
+void mlx5_esw_bridge_debugfs_offloads_cleanup(struct mlx5_esw_bridge_offloads *br_offloads)
+{
+ debugfs_remove_recursive(br_offloads->debugfs_root);
+ br_offloads->debugfs_root = NULL;
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c
index 2eae594a5e80..2455f8b93c1e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c
@@ -540,16 +540,29 @@ static struct mlx5_flow_handle *
mlx5_esw_bridge_mcast_filter_flow_peer_create(struct mlx5_esw_bridge_port *port)
{
struct mlx5_devcom *devcom = port->bridge->br_offloads->esw->dev->priv.devcom;
+ struct mlx5_eswitch *tmp, *peer_esw = NULL;
static struct mlx5_flow_handle *handle;
- struct mlx5_eswitch *peer_esw;
+ int i;
- peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
- if (!peer_esw)
+ if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS))
return ERR_PTR(-ENODEV);
+ mlx5_devcom_for_each_peer_entry(devcom,
+ MLX5_DEVCOM_ESW_OFFLOADS,
+ tmp, i) {
+ if (mlx5_esw_is_owner(tmp, port->vport_num, port->esw_owner_vhca_id)) {
+ peer_esw = tmp;
+ break;
+ }
+ }
+ if (!peer_esw) {
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ return ERR_PTR(-ENODEV);
+ }
+
handle = mlx5_esw_bridge_mcast_flow_with_esw_create(port, peer_esw);
- mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
return handle;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h
index c9595801bdb4..4911cc32161b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h
@@ -199,6 +199,7 @@ struct mlx5_esw_bridge {
int refcnt;
struct list_head list;
struct mlx5_esw_bridge_offloads *br_offloads;
+ struct dentry *debugfs_dir;
struct list_head fdb_list;
struct rhashtable fdb_ht;
@@ -241,4 +242,9 @@ void mlx5_esw_bridge_port_mdb_vlan_flush(struct mlx5_esw_bridge_port *port,
struct mlx5_esw_bridge_vlan *vlan);
void mlx5_esw_bridge_mdb_flush(struct mlx5_esw_bridge *bridge);
+void mlx5_esw_bridge_debugfs_offloads_init(struct mlx5_esw_bridge_offloads *br_offloads);
+void mlx5_esw_bridge_debugfs_offloads_cleanup(struct mlx5_esw_bridge_offloads *br_offloads);
+void mlx5_esw_bridge_debugfs_init(struct net_device *br_netdev, struct mlx5_esw_bridge *bridge);
+void mlx5_esw_bridge_debugfs_cleanup(struct mlx5_esw_bridge *bridge);
+
#endif /* _MLX5_ESW_BRIDGE_PRIVATE_ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
index 084a910bb4e7..fdf2be548e85 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
@@ -18,7 +18,8 @@ static bool mlx5_esw_devlink_port_supported(struct mlx5_eswitch *esw, u16 vport_
{
return vport_num == MLX5_VPORT_UPLINK ||
(mlx5_core_is_ecpf(esw->dev) && vport_num == MLX5_VPORT_PF) ||
- mlx5_eswitch_is_vf_vport(esw, vport_num);
+ mlx5_eswitch_is_vf_vport(esw, vport_num) ||
+ mlx5_core_is_ec_vf_vport(esw->dev, vport_num);
}
static struct devlink_port *mlx5_esw_dl_port_alloc(struct mlx5_eswitch *esw, u16 vport_num)
@@ -56,6 +57,11 @@ static struct devlink_port *mlx5_esw_dl_port_alloc(struct mlx5_eswitch *esw, u16
dl_port->attrs.switch_id.id_len = ppid.id_len;
devlink_port_attrs_pci_vf_set(dl_port, controller_num, pfnum,
vport_num - 1, external);
+ } else if (mlx5_core_is_ec_vf_vport(esw->dev, vport_num)) {
+ memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len);
+ dl_port->attrs.switch_id.id_len = ppid.id_len;
+ devlink_port_attrs_pci_vf_set(dl_port, 0, pfnum,
+ vport_num - 1, false);
}
return dl_port;
}
@@ -65,6 +71,15 @@ static void mlx5_esw_dl_port_free(struct devlink_port *dl_port)
kfree(dl_port);
}
+static const struct devlink_port_ops mlx5_esw_dl_port_ops = {
+ .port_fn_hw_addr_get = mlx5_devlink_port_fn_hw_addr_get,
+ .port_fn_hw_addr_set = mlx5_devlink_port_fn_hw_addr_set,
+ .port_fn_roce_get = mlx5_devlink_port_fn_roce_get,
+ .port_fn_roce_set = mlx5_devlink_port_fn_roce_set,
+ .port_fn_migratable_get = mlx5_devlink_port_fn_migratable_get,
+ .port_fn_migratable_set = mlx5_devlink_port_fn_migratable_set,
+};
+
int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_num)
{
struct mlx5_core_dev *dev = esw->dev;
@@ -87,7 +102,8 @@ int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_
devlink = priv_to_devlink(dev);
dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num);
- err = devl_port_register(devlink, dl_port, dl_port_index);
+ err = devl_port_register_with_ops(devlink, dl_port, dl_port_index,
+ &mlx5_esw_dl_port_ops);
if (err)
goto reg_err;
@@ -134,6 +150,20 @@ struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u1
return IS_ERR(vport) ? ERR_CAST(vport) : vport->dl_port;
}
+static const struct devlink_port_ops mlx5_esw_dl_sf_port_ops = {
+#ifdef CONFIG_MLX5_SF_MANAGER
+ .port_del = mlx5_devlink_sf_port_del,
+#endif
+ .port_fn_hw_addr_get = mlx5_devlink_port_fn_hw_addr_get,
+ .port_fn_hw_addr_set = mlx5_devlink_port_fn_hw_addr_set,
+ .port_fn_roce_get = mlx5_devlink_port_fn_roce_get,
+ .port_fn_roce_set = mlx5_devlink_port_fn_roce_set,
+#ifdef CONFIG_MLX5_SF_MANAGER
+ .port_fn_state_get = mlx5_devlink_sf_port_fn_state_get,
+ .port_fn_state_set = mlx5_devlink_sf_port_fn_state_set,
+#endif
+};
+
int mlx5_esw_devlink_sf_port_register(struct mlx5_eswitch *esw, struct devlink_port *dl_port,
u16 vport_num, u32 controller, u32 sfnum)
{
@@ -156,7 +186,8 @@ int mlx5_esw_devlink_sf_port_register(struct mlx5_eswitch *esw, struct devlink_p
devlink_port_attrs_pci_sf_set(dl_port, controller, pfnum, sfnum, !!controller);
devlink = priv_to_devlink(dev);
dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num);
- err = devl_port_register(devlink, dl_port, dl_port_index);
+ err = devl_port_register_with_ops(devlink, dl_port, dl_port_index,
+ &mlx5_esw_dl_sf_port_ops);
if (err)
return err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c
index fabe49a35a5c..255bc8b749f9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c
@@ -285,9 +285,8 @@ static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
if (IS_ERR(flow_rule)) {
err = PTR_ERR(flow_rule);
goto out;
- } else {
- esw->fdb_table.legacy.vepa_uplink_rule = flow_rule;
}
+ esw->fdb_table.legacy.vepa_uplink_rule = flow_rule;
/* Star rule to forward all traffic to uplink vport */
memset(&dest, 0, sizeof(dest));
@@ -299,9 +298,8 @@ static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
if (IS_ERR(flow_rule)) {
err = PTR_ERR(flow_rule);
goto out;
- } else {
- esw->fdb_table.legacy.vepa_star_rule = flow_rule;
}
+ esw->fdb_table.legacy.vepa_star_rule = flow_rule;
out:
kvfree(spec);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
index 901c53751b0a..243c455f1029 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
@@ -31,6 +31,7 @@
*/
#include <linux/etherdevice.h>
+#include <linux/debugfs.h>
#include <linux/mlx5/driver.h>
#include <linux/mlx5/mlx5_ifc.h>
#include <linux/mlx5/vport.h>
@@ -41,6 +42,7 @@
#include "esw/qos.h"
#include "mlx5_core.h"
#include "lib/eq.h"
+#include "lag/lag.h"
#include "eswitch.h"
#include "fs_core.h"
#include "devlink.h"
@@ -92,7 +94,7 @@ mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num)
{
struct mlx5_vport *vport;
- if (!esw || !MLX5_CAP_GEN(esw->dev, vport_group_manager))
+ if (!esw)
return ERR_PTR(-EPERM);
vport = xa_load(&esw->vports, vport_num);
@@ -113,7 +115,8 @@ static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport,
opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
MLX5_SET(modify_nic_vport_context_in, in, field_select.change_event, 1);
MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
- MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
+ if (vport || mlx5_core_is_ecpf(dev))
+ MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in,
in, nic_vport_context);
@@ -309,11 +312,12 @@ static int esw_add_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
fdb_add:
/* SRIOV is enabled: Forward UC MAC to vport */
- if (esw->fdb_table.legacy.fdb && esw->mode == MLX5_ESWITCH_LEGACY)
+ if (esw->fdb_table.legacy.fdb && esw->mode == MLX5_ESWITCH_LEGACY) {
vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport);
- esw_debug(esw->dev, "\tADDED UC MAC: vport[%d] %pM fr(%p)\n",
- vport, mac, vaddr->flow_rule);
+ esw_debug(esw->dev, "\tADDED UC MAC: vport[%d] %pM fr(%p)\n",
+ vport, mac, vaddr->flow_rule);
+ }
return 0;
}
@@ -710,6 +714,9 @@ void esw_vport_change_handle_locked(struct mlx5_vport *vport)
struct mlx5_eswitch *esw = dev->priv.eswitch;
u8 mac[ETH_ALEN];
+ if (!MLX5_CAP_GEN(dev, log_max_l2_table))
+ return;
+
mlx5_query_nic_vport_mac_address(dev, vport->vport, true, mac);
esw_debug(dev, "vport[%d] Context Changed: perm mac: %pM\n",
vport->vport, mac);
@@ -800,6 +807,9 @@ static int mlx5_esw_vport_caps_get(struct mlx5_eswitch *esw, struct mlx5_vport *
hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
vport->info.roce_enabled = MLX5_GET(cmd_hca_cap, hca_caps, roce);
+ if (!MLX5_CAP_GEN_MAX(esw->dev, hca_cap_2))
+ goto out_free;
+
memset(query_ctx, 0, query_out_sz);
err = mlx5_vport_get_other_func_cap(esw->dev, vport->vport, query_ctx,
MLX5_CAP_GENERAL_2);
@@ -946,7 +956,8 @@ void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, u16 vport_num)
vport->enabled = false;
/* Disable events from this vport */
- arm_vport_context_events_cmd(esw->dev, vport->vport, 0);
+ if (MLX5_CAP_GEN(esw->dev, log_max_l2_table))
+ arm_vport_context_events_cmd(esw->dev, vport->vport, 0);
if (!mlx5_esw_is_manager_vport(esw, vport->vport) &&
MLX5_CAP_GEN(esw->dev, vhca_resource_manager))
@@ -1045,6 +1056,18 @@ static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw)
}
}
+static void mlx5_eswitch_clear_ec_vf_vports_info(struct mlx5_eswitch *esw)
+{
+ struct mlx5_vport *vport;
+ unsigned long i;
+
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) {
+ memset(&vport->qos, 0, sizeof(vport->qos));
+ memset(&vport->info, 0, sizeof(vport->info));
+ vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
+ }
+}
+
/* Public E-Switch API */
int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num,
enum mlx5_eswitch_vport_event enabled_events)
@@ -1084,6 +1107,19 @@ void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs)
}
}
+static void mlx5_eswitch_unload_ec_vf_vports(struct mlx5_eswitch *esw,
+ u16 num_ec_vfs)
+{
+ struct mlx5_vport *vport;
+ unsigned long i;
+
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) {
+ if (!vport->enabled)
+ continue;
+ mlx5_eswitch_unload_vport(esw, vport->vport);
+ }
+}
+
int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs,
enum mlx5_eswitch_vport_event enabled_events)
{
@@ -1104,6 +1140,26 @@ vf_err:
return err;
}
+static int mlx5_eswitch_load_ec_vf_vports(struct mlx5_eswitch *esw, u16 num_ec_vfs,
+ enum mlx5_eswitch_vport_event enabled_events)
+{
+ struct mlx5_vport *vport;
+ unsigned long i;
+ int err;
+
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) {
+ err = mlx5_eswitch_load_vport(esw, vport->vport, enabled_events);
+ if (err)
+ goto vf_err;
+ }
+
+ return 0;
+
+vf_err:
+ mlx5_eswitch_unload_ec_vf_vports(esw, num_ec_vfs);
+ return err;
+}
+
static int host_pf_enable_hca(struct mlx5_core_dev *dev)
{
if (!mlx5_core_is_ecpf(dev))
@@ -1148,6 +1204,12 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw,
ret = mlx5_eswitch_load_vport(esw, MLX5_VPORT_ECPF, enabled_events);
if (ret)
goto ecpf_err;
+ if (mlx5_core_ec_sriov_enabled(esw->dev)) {
+ ret = mlx5_eswitch_load_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs,
+ enabled_events);
+ if (ret)
+ goto ec_vf_err;
+ }
}
/* Enable VF vports */
@@ -1158,6 +1220,9 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw,
return 0;
vf_err:
+ if (mlx5_core_ec_sriov_enabled(esw->dev))
+ mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs);
+ec_vf_err:
if (mlx5_ecpf_vport_exists(esw->dev))
mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF);
ecpf_err:
@@ -1174,8 +1239,11 @@ void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw)
{
mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
- if (mlx5_ecpf_vport_exists(esw->dev))
+ if (mlx5_ecpf_vport_exists(esw->dev)) {
+ if (mlx5_core_ec_sriov_enabled(esw->dev))
+ mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_vfs);
mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF);
+ }
host_pf_disable_hca(esw->dev);
mlx5_eswitch_unload_vport(esw, MLX5_VPORT_PF);
@@ -1219,6 +1287,9 @@ mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, int num_vfs)
esw->esw_funcs.num_vfs = MLX5_GET(query_esw_functions_out, out,
host_params_context.host_num_of_vfs);
+ if (mlx5_core_ec_sriov_enabled(esw->dev))
+ esw->esw_funcs.num_ec_vfs = num_vfs;
+
kvfree(out);
}
@@ -1326,9 +1397,9 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs)
mlx5_eswitch_event_handlers_register(esw);
- esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), active vports(%d)\n",
+ esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n",
esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
- esw->esw_funcs.num_vfs, esw->enabled_vports);
+ esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports);
mlx5_esw_mode_change_notify(esw, esw->mode);
@@ -1350,7 +1421,7 @@ abort:
int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
{
bool toggle_lag;
- int ret;
+ int ret = 0;
if (!mlx5_esw_allowed(esw))
return 0;
@@ -1370,10 +1441,21 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
vport_events = (esw->mode == MLX5_ESWITCH_LEGACY) ?
MLX5_LEGACY_SRIOV_VPORT_EVENTS : MLX5_VPORT_UC_ADDR_CHANGE;
- ret = mlx5_eswitch_load_vf_vports(esw, num_vfs, vport_events);
- if (!ret)
- esw->esw_funcs.num_vfs = num_vfs;
+ /* If this is the ECPF the number of host VFs is managed via the
+ * eswitch function change event handler, and any num_vfs provided
+ * here are intended to be EC VFs.
+ */
+ if (!mlx5_core_is_ecpf(esw->dev)) {
+ ret = mlx5_eswitch_load_vf_vports(esw, num_vfs, vport_events);
+ if (!ret)
+ esw->esw_funcs.num_vfs = num_vfs;
+ } else if (mlx5_core_ec_sriov_enabled(esw->dev)) {
+ ret = mlx5_eswitch_load_ec_vf_vports(esw, num_vfs, vport_events);
+ if (!ret)
+ esw->esw_funcs.num_ec_vfs = num_vfs;
+ }
}
+
up_write(&esw->mode_lock);
if (toggle_lag)
@@ -1393,16 +1475,22 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf)
/* If driver is unloaded, this function is called twice by remove_one()
* and mlx5_unload(). Prevent the second call.
*/
- if (!esw->esw_funcs.num_vfs && !clear_vf)
+ if (!esw->esw_funcs.num_vfs && !esw->esw_funcs.num_ec_vfs && !clear_vf)
goto unlock;
- esw_info(esw->dev, "Unload vfs: mode(%s), nvfs(%d), active vports(%d)\n",
+ esw_info(esw->dev, "Unload vfs: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n",
esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
- esw->esw_funcs.num_vfs, esw->enabled_vports);
-
- mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
- if (clear_vf)
- mlx5_eswitch_clear_vf_vports_info(esw);
+ esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports);
+
+ if (!mlx5_core_is_ecpf(esw->dev)) {
+ mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
+ if (clear_vf)
+ mlx5_eswitch_clear_vf_vports_info(esw);
+ } else if (mlx5_core_ec_sriov_enabled(esw->dev)) {
+ mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs);
+ if (clear_vf)
+ mlx5_eswitch_clear_ec_vf_vports_info(esw);
+ }
if (esw->mode == MLX5_ESWITCH_OFFLOADS) {
struct devlink *devlink = priv_to_devlink(esw->dev);
@@ -1413,7 +1501,10 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf)
if (esw->mode == MLX5_ESWITCH_LEGACY)
mlx5_eswitch_disable_locked(esw);
- esw->esw_funcs.num_vfs = 0;
+ if (!mlx5_core_is_ecpf(esw->dev))
+ esw->esw_funcs.num_vfs = 0;
+ else
+ esw->esw_funcs.num_ec_vfs = 0;
unlock:
up_write(&esw->mode_lock);
@@ -1433,9 +1524,9 @@ void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw)
mlx5_eswitch_event_handlers_unregister(esw);
- esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), active vports(%d)\n",
+ esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n",
esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
- esw->esw_funcs.num_vfs, esw->enabled_vports);
+ esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports);
if (esw->fdb_table.flags & MLX5_ESW_FDB_CREATED) {
esw->fdb_table.flags &= ~MLX5_ESW_FDB_CREATED;
@@ -1595,7 +1686,19 @@ static int mlx5_esw_vports_init(struct mlx5_eswitch *esw)
idx++;
}
- if (mlx5_ecpf_vport_exists(dev)) {
+ if (mlx5_core_ec_sriov_enabled(esw->dev)) {
+ int ec_vf_base_num = mlx5_core_ec_vf_vport_base(dev);
+
+ for (i = 0; i < mlx5_core_max_ec_vfs(esw->dev); i++) {
+ err = mlx5_esw_vport_alloc(esw, idx, ec_vf_base_num + i);
+ if (err)
+ goto err;
+ idx++;
+ }
+ }
+
+ if (mlx5_ecpf_vport_exists(dev) ||
+ mlx5_core_is_ecpf_esw_manager(dev)) {
err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_ECPF);
if (err)
goto err;
@@ -1611,22 +1714,60 @@ err:
return err;
}
+static int mlx5_devlink_esw_multiport_set(struct devlink *devlink, u32 id,
+ struct devlink_param_gset_ctx *ctx)
+{
+ struct mlx5_core_dev *dev = devlink_priv(devlink);
+
+ if (!MLX5_ESWITCH_MANAGER(dev))
+ return -EOPNOTSUPP;
+
+ if (ctx->val.vbool)
+ return mlx5_lag_mpesw_enable(dev);
+
+ mlx5_lag_mpesw_disable(dev);
+ return 0;
+}
+
+static int mlx5_devlink_esw_multiport_get(struct devlink *devlink, u32 id,
+ struct devlink_param_gset_ctx *ctx)
+{
+ struct mlx5_core_dev *dev = devlink_priv(devlink);
+
+ ctx->val.vbool = mlx5_lag_is_mpesw(dev);
+ return 0;
+}
+
+static const struct devlink_param mlx5_eswitch_params[] = {
+ DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_MULTIPORT,
+ "esw_multiport", DEVLINK_PARAM_TYPE_BOOL,
+ BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+ mlx5_devlink_esw_multiport_get,
+ mlx5_devlink_esw_multiport_set, NULL),
+};
+
int mlx5_eswitch_init(struct mlx5_core_dev *dev)
{
struct mlx5_eswitch *esw;
int err;
- if (!MLX5_VPORT_MANAGER(dev))
+ if (!MLX5_VPORT_MANAGER(dev) && !MLX5_ESWITCH_MANAGER(dev))
return 0;
esw = kzalloc(sizeof(*esw), GFP_KERNEL);
if (!esw)
return -ENOMEM;
+ err = devl_params_register(priv_to_devlink(dev), mlx5_eswitch_params,
+ ARRAY_SIZE(mlx5_eswitch_params));
+ if (err)
+ goto free_esw;
+
esw->dev = dev;
esw->manager_vport = mlx5_eswitch_manager_vport(dev);
esw->first_host_vport = mlx5_eswitch_first_host_vport_num(dev);
+ esw->debugfs_root = debugfs_create_dir("esw", mlx5_debugfs_get_dev_root(dev));
esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq");
if (!esw->work_queue) {
err = -ENOMEM;
@@ -1680,13 +1821,17 @@ reps_err:
abort:
if (esw->work_queue)
destroy_workqueue(esw->work_queue);
+ debugfs_remove_recursive(esw->debugfs_root);
+ devl_params_unregister(priv_to_devlink(dev), mlx5_eswitch_params,
+ ARRAY_SIZE(mlx5_eswitch_params));
+free_esw:
kfree(esw);
return err;
}
void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
{
- if (!esw || !MLX5_VPORT_MANAGER(esw->dev))
+ if (!esw)
return;
esw_info(esw->dev, "cleanup\n");
@@ -1703,6 +1848,9 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
mutex_destroy(&esw->offloads.decap_tbl_lock);
esw_offloads_cleanup(esw);
mlx5_esw_vports_cleanup(esw);
+ debugfs_remove_recursive(esw->debugfs_root);
+ devl_params_unregister(priv_to_devlink(esw->dev), mlx5_eswitch_params,
+ ARRAY_SIZE(mlx5_eswitch_params));
kfree(esw);
}
@@ -1763,12 +1911,6 @@ int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
static bool mlx5_esw_check_port_type(struct mlx5_eswitch *esw, u16 vport_num, xa_mark_t mark)
{
- struct mlx5_vport *vport;
-
- vport = mlx5_eswitch_get_vport(esw, vport_num);
- if (IS_ERR(vport))
- return false;
-
return xa_get_mark(&esw->vports, vport_num, mark);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
index add6cfa432a5..ae0dc8a3060d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
@@ -123,8 +123,14 @@ struct vport_ingress {
} offloads;
};
+enum vport_egress_acl_type {
+ VPORT_EGRESS_ACL_TYPE_DEFAULT,
+ VPORT_EGRESS_ACL_TYPE_SHARED_FDB,
+};
+
struct vport_egress {
struct mlx5_flow_table *acl;
+ enum vport_egress_acl_type type;
struct mlx5_flow_handle *allowed_vlan;
struct mlx5_flow_group *vlan_grp;
union {
@@ -136,7 +142,7 @@ struct vport_egress {
struct {
struct mlx5_flow_group *fwd_grp;
struct mlx5_flow_handle *fwd_rule;
- struct mlx5_flow_handle *bounce_rule;
+ struct xarray bounce_rules;
struct mlx5_flow_group *bounce_grp;
} offloads;
};
@@ -218,7 +224,7 @@ struct mlx5_eswitch_fdb {
struct mlx5_flow_group *send_to_vport_grp;
struct mlx5_flow_group *send_to_vport_meta_grp;
struct mlx5_flow_group *peer_miss_grp;
- struct mlx5_flow_handle **peer_miss_rules;
+ struct mlx5_flow_handle **peer_miss_rules[MLX5_MAX_PORTS];
struct mlx5_flow_group *miss_grp;
struct mlx5_flow_handle **send_to_vport_meta_rules;
struct mlx5_flow_handle *miss_rule_uni;
@@ -249,7 +255,7 @@ struct mlx5_esw_offload {
struct mlx5_flow_group *vport_rx_drop_group;
struct mlx5_flow_handle *vport_rx_drop_rule;
struct xarray vport_reps;
- struct list_head peer_flows;
+ struct list_head peer_flows[MLX5_MAX_PORTS];
struct mutex peer_mutex;
struct mutex encap_tbl_lock; /* protects encap_tbl */
DECLARE_HASHTABLE(encap_tbl, 8);
@@ -283,6 +289,7 @@ struct mlx5_host_work {
struct mlx5_esw_functions {
struct mlx5_nb nb;
u16 num_vfs;
+ u16 num_ec_vfs;
};
enum {
@@ -297,6 +304,8 @@ enum {
MLX5_ESW_FDB_CREATED = BIT(0),
};
+struct dentry;
+
struct mlx5_eswitch {
struct mlx5_core_dev *dev;
struct mlx5_nb nb;
@@ -305,6 +314,7 @@ struct mlx5_eswitch {
struct hlist_head mc_table[MLX5_L2_ADDR_HASH_SIZE];
struct esw_mc_addr mc_promisc;
/* end of legacy */
+ struct dentry *debugfs_root;
struct workqueue_struct *work_queue;
struct xarray vports;
u32 flags;
@@ -337,12 +347,13 @@ struct mlx5_eswitch {
int mode;
u16 manager_vport;
u16 first_host_vport;
+ u8 num_peers;
struct mlx5_esw_functions esw_funcs;
struct {
u32 large_group_num;
} params;
struct blocking_notifier_head n_head;
- bool paired[MLX5_MAX_PORTS];
+ struct xarray paired;
};
void esw_offloads_disable(struct mlx5_eswitch *esw);
@@ -506,12 +517,12 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink,
struct netlink_ext_ack *extack);
int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink,
enum devlink_eswitch_encap_mode *encap);
-int mlx5_devlink_port_function_hw_addr_get(struct devlink_port *port,
- u8 *hw_addr, int *hw_addr_len,
- struct netlink_ext_ack *extack);
-int mlx5_devlink_port_function_hw_addr_set(struct devlink_port *port,
- const u8 *hw_addr, int hw_addr_len,
- struct netlink_ext_ack *extack);
+int mlx5_devlink_port_fn_hw_addr_get(struct devlink_port *port,
+ u8 *hw_addr, int *hw_addr_len,
+ struct netlink_ext_ack *extack);
+int mlx5_devlink_port_fn_hw_addr_set(struct devlink_port *port,
+ const u8 *hw_addr, int hw_addr_len,
+ struct netlink_ext_ack *extack);
int mlx5_devlink_port_fn_roce_get(struct devlink_port *port, bool *is_enabled,
struct netlink_ext_ack *extack);
int mlx5_devlink_port_fn_roce_set(struct devlink_port *port, bool enable,
@@ -578,6 +589,13 @@ mlx5_esw_is_manager_vport(const struct mlx5_eswitch *esw, u16 vport_num)
return esw->manager_vport == vport_num;
}
+static inline bool mlx5_esw_is_owner(struct mlx5_eswitch *esw, u16 vport_num,
+ u16 esw_owner_vhca_id)
+{
+ return esw_owner_vhca_id == MLX5_CAP_GEN(esw->dev, vhca_id) ||
+ (vport_num == MLX5_VPORT_UPLINK && mlx5_lag_is_master(esw->dev));
+}
+
static inline u16 mlx5_eswitch_first_host_vport_num(struct mlx5_core_dev *dev)
{
return mlx5_core_is_ecpf_esw_manager(dev) ?
@@ -640,6 +658,19 @@ void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw);
#define mlx5_esw_for_each_host_func_vport(esw, index, vport, last) \
mlx5_esw_for_each_vport_marked(esw, index, vport, last, MLX5_ESW_VPT_HOST_FN)
+/* This macro should only be used if EC SRIOV is enabled.
+ *
+ * Because there were no more marks available on the xarray this uses a
+ * for_each_range approach. The range is only valid when EC SRIOV is enabled
+ */
+#define mlx5_esw_for_each_ec_vf_vport(esw, index, vport, last) \
+ xa_for_each_range(&((esw)->vports), \
+ index, \
+ vport, \
+ MLX5_CAP_GEN_2((esw->dev), ec_vf_vport_base), \
+ MLX5_CAP_GEN_2((esw->dev), ec_vf_vport_base) +\
+ (last) - 1)
+
struct mlx5_eswitch *mlx5_devlink_eswitch_get(struct devlink *devlink);
struct mlx5_vport *__must_check
mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num);
@@ -686,6 +717,14 @@ mlx5_esw_vporttbl_put(struct mlx5_eswitch *esw, struct mlx5_vport_tbl_attr *attr
struct mlx5_flow_handle *
esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag);
+void mlx5_esw_set_flow_group_source_port(struct mlx5_eswitch *esw,
+ u32 *flow_group_in,
+ int match_params);
+
+void mlx5_esw_set_spec_source_port(struct mlx5_eswitch *esw,
+ u16 vport,
+ struct mlx5_flow_spec *spec);
+
int esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num);
void esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num);
@@ -740,9 +779,9 @@ void esw_vport_change_handle_locked(struct mlx5_vport *vport);
bool mlx5_esw_offloads_controller_valid(const struct mlx5_eswitch *esw, u32 controller);
-int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw,
- struct mlx5_eswitch *slave_esw);
-void mlx5_eswitch_offloads_destroy_single_fdb(struct mlx5_eswitch *master_esw,
+int mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw,
+ struct mlx5_eswitch *slave_esw, int max_slaves);
+void mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw,
struct mlx5_eswitch *slave_esw);
int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw);
@@ -757,6 +796,13 @@ static inline int mlx5_eswitch_num_vfs(struct mlx5_eswitch *esw)
return 0;
}
+static inline int mlx5_eswitch_get_npeers(struct mlx5_eswitch *esw)
+{
+ if (mlx5_esw_allowed(esw))
+ return esw->num_peers;
+ return 0;
+}
+
static inline struct mlx5_flow_table *
mlx5_eswitch_get_slow_fdb(struct mlx5_eswitch *esw)
{
@@ -794,16 +840,18 @@ mlx5_esw_vport_to_devlink_port_index(const struct mlx5_core_dev *dev,
}
static inline int
-mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw,
- struct mlx5_eswitch *slave_esw)
+mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw,
+ struct mlx5_eswitch *slave_esw, int max_slaves)
{
return 0;
}
static inline void
-mlx5_eswitch_offloads_destroy_single_fdb(struct mlx5_eswitch *master_esw,
+mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw,
struct mlx5_eswitch *slave_esw) {}
+static inline int mlx5_eswitch_get_npeers(struct mlx5_eswitch *esw) { return 0; }
+
static inline int
mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw)
{
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index 8d19c20d3447..e59380ee1ead 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -55,13 +55,6 @@
#define mlx5_esw_for_each_rep(esw, i, rep) \
xa_for_each(&((esw)->offloads.vport_reps), i, rep)
-#define mlx5_esw_for_each_sf_rep(esw, i, rep) \
- xa_for_each_marked(&((esw)->offloads.vport_reps), i, rep, MLX5_ESW_VPT_SF)
-
-#define mlx5_esw_for_each_vf_rep(esw, index, rep) \
- mlx5_esw_for_each_entry_marked(&((esw)->offloads.vport_reps), index, \
- rep, (esw)->esw_funcs.num_vfs, MLX5_ESW_VPT_VF)
-
/* There are two match-all miss flows, one for unicast dst mac and
* one for multicast.
*/
@@ -838,6 +831,7 @@ mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *on_esw,
struct mlx5_flow_handle *flow_rule;
struct mlx5_flow_spec *spec;
void *misc;
+ u16 vport;
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
if (!spec) {
@@ -847,20 +841,43 @@ mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *on_esw,
misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
MLX5_SET(fte_match_set_misc, misc, source_sqn, sqn);
- /* source vport is the esw manager */
- MLX5_SET(fte_match_set_misc, misc, source_port, from_esw->manager_vport);
- if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch))
- MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id,
- MLX5_CAP_GEN(from_esw->dev, vhca_id));
misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_sqn);
- MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
- if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch))
- MLX5_SET_TO_ONES(fte_match_set_misc, misc,
- source_eswitch_owner_vhca_id);
spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
+
+ /* source vport is the esw manager */
+ vport = from_esw->manager_vport;
+
+ if (mlx5_eswitch_vport_match_metadata_enabled(on_esw)) {
+ misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2);
+ MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
+ mlx5_eswitch_get_vport_metadata_for_match(from_esw, vport));
+
+ misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters_2);
+ MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
+ mlx5_eswitch_get_vport_metadata_mask());
+
+ spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2;
+ } else {
+ misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
+ MLX5_SET(fte_match_set_misc, misc, source_port, vport);
+
+ if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch))
+ MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id,
+ MLX5_CAP_GEN(from_esw->dev, vhca_id));
+
+ misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
+ MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
+
+ if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch))
+ MLX5_SET_TO_ONES(fte_match_set_misc, misc,
+ source_eswitch_owner_vhca_id);
+
+ spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS;
+ }
+
dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
dest.vport.num = rep->vport;
dest.vport.vhca_id = MLX5_CAP_GEN(rep->esw->dev, vhca_id);
@@ -1052,6 +1069,9 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
void *misc;
int err;
+ if (!MLX5_VPORT_MANAGER(esw->dev) && !mlx5_core_is_ecpf_esw_manager(esw->dev))
+ return 0;
+
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
if (!spec)
return -ENOMEM;
@@ -1108,11 +1128,32 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
flows[vport->index] = flow;
}
- esw->fdb_table.offloads.peer_miss_rules = flows;
+ if (mlx5_core_ec_sriov_enabled(esw->dev)) {
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) {
+ if (i >= mlx5_core_max_ec_vfs(peer_dev))
+ break;
+ esw_set_peer_miss_rule_source_port(esw, peer_dev->priv.eswitch,
+ spec, vport->vport);
+ flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
+ spec, &flow_act, &dest, 1);
+ if (IS_ERR(flow)) {
+ err = PTR_ERR(flow);
+ goto add_ec_vf_flow_err;
+ }
+ flows[vport->index] = flow;
+ }
+ }
+ esw->fdb_table.offloads.peer_miss_rules[mlx5_get_dev_index(peer_dev)] = flows;
kvfree(spec);
return 0;
+add_ec_vf_flow_err:
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) {
+ if (!flows[vport->index])
+ continue;
+ mlx5_del_flow_rules(flows[vport->index]);
+ }
add_vf_flow_err:
mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev)) {
if (!flows[vport->index])
@@ -1136,13 +1177,28 @@ alloc_flows_err:
return err;
}
-static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw)
+static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
+ struct mlx5_core_dev *peer_dev)
{
+ u16 peer_index = mlx5_get_dev_index(peer_dev);
struct mlx5_flow_handle **flows;
struct mlx5_vport *vport;
unsigned long i;
- flows = esw->fdb_table.offloads.peer_miss_rules;
+ flows = esw->fdb_table.offloads.peer_miss_rules[peer_index];
+ if (!flows)
+ return;
+
+ if (mlx5_core_ec_sriov_enabled(esw->dev)) {
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) {
+ /* The flow for a particular vport could be NULL if the other ECPF
+ * has fewer or no VFs enabled
+ */
+ if (!flows[vport->index])
+ continue;
+ mlx5_del_flow_rules(flows[vport->index]);
+ }
+ }
mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev))
mlx5_del_flow_rules(flows[vport->index]);
@@ -1156,7 +1212,9 @@ static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw)
vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF);
mlx5_del_flow_rules(flows[vport->index]);
}
+
kvfree(flows);
+ esw->fdb_table.offloads.peer_miss_rules[peer_index] = NULL;
}
static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw)
@@ -1269,8 +1327,10 @@ esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag)
#define MAX_PF_SQ 256
#define MAX_SQ_NVPORTS 32
-static void esw_set_flow_group_source_port(struct mlx5_eswitch *esw,
- u32 *flow_group_in)
+void
+mlx5_esw_set_flow_group_source_port(struct mlx5_eswitch *esw,
+ u32 *flow_group_in,
+ int match_params)
{
void *match_criteria = MLX5_ADDR_OF(create_flow_group_in,
flow_group_in,
@@ -1279,7 +1339,7 @@ static void esw_set_flow_group_source_port(struct mlx5_eswitch *esw,
if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
MLX5_SET(create_flow_group_in, flow_group_in,
match_criteria_enable,
- MLX5_MATCH_MISC_PARAMETERS_2);
+ MLX5_MATCH_MISC_PARAMETERS_2 | match_params);
MLX5_SET(fte_match_param, match_criteria,
misc_parameters_2.metadata_reg_c_0,
@@ -1287,7 +1347,7 @@ static void esw_set_flow_group_source_port(struct mlx5_eswitch *esw,
} else {
MLX5_SET(create_flow_group_in, flow_group_in,
match_criteria_enable,
- MLX5_MATCH_MISC_PARAMETERS);
+ MLX5_MATCH_MISC_PARAMETERS | match_params);
MLX5_SET_TO_ONES(fte_match_param, match_criteria,
misc_parameters.source_port);
@@ -1376,7 +1436,6 @@ esw_chains_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *miss_fdb)
esw_init_chains_offload_flags(esw, &attr.flags);
attr.ns = MLX5_FLOW_NAMESPACE_FDB;
- attr.fs_base_prio = FDB_TC_OFFLOAD;
attr.max_grp_num = esw->params.large_group_num;
attr.default_ft = miss_fdb;
attr.mapping = esw->offloads.reg_c0_obj_pool;
@@ -1463,14 +1522,13 @@ esw_create_send_to_vport_group(struct mlx5_eswitch *esw,
memset(flow_group_in, 0, inlen);
- MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
- MLX5_MATCH_MISC_PARAMETERS);
+ mlx5_esw_set_flow_group_source_port(esw, flow_group_in, MLX5_MATCH_MISC_PARAMETERS);
match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
-
MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_sqn);
- MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
- if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) {
+
+ if (!mlx5_eswitch_vport_match_metadata_enabled(esw) &&
+ MLX5_CAP_ESW(esw->dev, merged_eswitch)) {
MLX5_SET_TO_ONES(fte_match_param, match_criteria,
misc_parameters.source_eswitch_owner_vhca_id);
MLX5_SET(create_flow_group_in, flow_group_in,
@@ -1548,6 +1606,7 @@ esw_create_peer_esw_miss_group(struct mlx5_eswitch *esw,
u32 *flow_group_in,
int *ix)
{
+ int max_peer_ports = (esw->total_vports - 1) * (MLX5_MAX_PORTS - 1);
int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
struct mlx5_flow_group *g;
void *match_criteria;
@@ -1558,7 +1617,7 @@ esw_create_peer_esw_miss_group(struct mlx5_eswitch *esw,
memset(flow_group_in, 0, inlen);
- esw_set_flow_group_source_port(esw, flow_group_in);
+ mlx5_esw_set_flow_group_source_port(esw, flow_group_in, 0);
if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) {
match_criteria = MLX5_ADDR_OF(create_flow_group_in,
@@ -1574,8 +1633,8 @@ esw_create_peer_esw_miss_group(struct mlx5_eswitch *esw,
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, *ix);
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
- *ix + esw->total_vports - 1);
- *ix += esw->total_vports;
+ *ix + max_peer_ports);
+ *ix += max_peer_ports + 1;
g = mlx5_create_flow_group(fdb, flow_group_in);
if (IS_ERR(g)) {
@@ -1677,7 +1736,7 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw)
* total vports of the peer (currently is also uses esw->total_vports).
*/
table_size = MLX5_MAX_PORTS * (esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ) +
- esw->total_vports * 2 + MLX5_ESW_MISS_FLOWS;
+ esw->total_vports * MLX5_MAX_PORTS + MLX5_ESW_MISS_FLOWS;
/* create the slow path fdb with encap set, so further table instances
* can be created at run time while VFs are probed if the FW allows that.
@@ -1844,8 +1903,7 @@ static int esw_create_vport_rx_group(struct mlx5_eswitch *esw)
if (!flow_group_in)
return -ENOMEM;
- /* create vport rx group */
- esw_set_flow_group_source_port(esw, flow_group_in);
+ mlx5_esw_set_flow_group_source_port(esw, flow_group_in, 0);
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, nvports - 1);
@@ -1915,21 +1973,13 @@ static void esw_destroy_vport_rx_drop_group(struct mlx5_eswitch *esw)
mlx5_destroy_flow_group(esw->offloads.vport_rx_drop_group);
}
-struct mlx5_flow_handle *
-mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport,
- struct mlx5_flow_destination *dest)
+void
+mlx5_esw_set_spec_source_port(struct mlx5_eswitch *esw,
+ u16 vport,
+ struct mlx5_flow_spec *spec)
{
- struct mlx5_flow_act flow_act = {0};
- struct mlx5_flow_handle *flow_rule;
- struct mlx5_flow_spec *spec;
void *misc;
- spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
- if (!spec) {
- flow_rule = ERR_PTR(-ENOMEM);
- goto out;
- }
-
if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2);
MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
@@ -1949,6 +1999,23 @@ mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport,
spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
}
+}
+
+struct mlx5_flow_handle *
+mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport,
+ struct mlx5_flow_destination *dest)
+{
+ struct mlx5_flow_act flow_act = {0};
+ struct mlx5_flow_handle *flow_rule;
+ struct mlx5_flow_spec *spec;
+
+ spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
+ if (!spec) {
+ flow_rule = ERR_PTR(-ENOMEM);
+ goto out;
+ }
+
+ mlx5_esw_set_spec_source_port(esw, vport, spec);
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
flow_rule = mlx5_add_flow_rules(esw->offloads.ft_offloads, spec,
@@ -2142,6 +2209,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw,
"Failed setting eswitch to offloads");
esw->mode = MLX5_ESWITCH_LEGACY;
mlx5_rescan_drivers(esw->dev);
+ return err;
}
if (esw->offloads.inline_mode == MLX5_INLINE_MODE_NONE) {
if (mlx5_eswitch_inline_mode_get(esw,
@@ -2151,19 +2219,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw,
"Inline mode is different between vports");
}
}
- return err;
-}
-
-static void mlx5_esw_offloads_rep_mark_set(struct mlx5_eswitch *esw,
- struct mlx5_eswitch_rep *rep,
- xa_mark_t mark)
-{
- bool mark_set;
-
- /* Copy the mark from vport to its rep */
- mark_set = xa_get_mark(&esw->vports, rep->vport, mark);
- if (mark_set)
- xa_set_mark(&esw->offloads.vport_reps, rep->vport, mark);
+ return 0;
}
static int mlx5_esw_offloads_rep_init(struct mlx5_eswitch *esw, const struct mlx5_vport *vport)
@@ -2185,9 +2241,6 @@ static int mlx5_esw_offloads_rep_init(struct mlx5_eswitch *esw, const struct mlx
if (err)
goto insert_err;
- mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_HOST_FN);
- mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_VF);
- mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_SF);
return 0;
insert_err:
@@ -2328,37 +2381,13 @@ static void __esw_offloads_unload_rep(struct mlx5_eswitch *esw,
esw->offloads.rep_ops[rep_type]->unload(rep);
}
-static void __unload_reps_sf_vport(struct mlx5_eswitch *esw, u8 rep_type)
-{
- struct mlx5_eswitch_rep *rep;
- unsigned long i;
-
- mlx5_esw_for_each_sf_rep(esw, i, rep)
- __esw_offloads_unload_rep(esw, rep, rep_type);
-}
-
static void __unload_reps_all_vport(struct mlx5_eswitch *esw, u8 rep_type)
{
struct mlx5_eswitch_rep *rep;
unsigned long i;
- __unload_reps_sf_vport(esw, rep_type);
-
- mlx5_esw_for_each_vf_rep(esw, i, rep)
- __esw_offloads_unload_rep(esw, rep, rep_type);
-
- if (mlx5_ecpf_vport_exists(esw->dev)) {
- rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_ECPF);
- __esw_offloads_unload_rep(esw, rep, rep_type);
- }
-
- if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
- rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF);
+ mlx5_esw_for_each_rep(esw, i, rep)
__esw_offloads_unload_rep(esw, rep, rep_type);
- }
-
- rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
- __esw_offloads_unload_rep(esw, rep, rep_type);
}
int mlx5_esw_offloads_rep_load(struct mlx5_eswitch *esw, u16 vport_num)
@@ -2476,6 +2505,7 @@ static int __esw_set_master_egress_rule(struct mlx5_core_dev *master,
struct mlx5_vport *vport,
struct mlx5_flow_table *acl)
{
+ u16 slave_index = MLX5_CAP_GEN(slave, vhca_id);
struct mlx5_flow_handle *flow_rule = NULL;
struct mlx5_flow_destination dest = {};
struct mlx5_flow_act flow_act = {};
@@ -2491,8 +2521,7 @@ static int __esw_set_master_egress_rule(struct mlx5_core_dev *master,
misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
misc_parameters);
MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK);
- MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id,
- MLX5_CAP_GEN(slave, vhca_id));
+ MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id, slave_index);
misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
@@ -2507,49 +2536,43 @@ static int __esw_set_master_egress_rule(struct mlx5_core_dev *master,
flow_rule = mlx5_add_flow_rules(acl, spec, &flow_act,
&dest, 1);
- if (IS_ERR(flow_rule))
+ if (IS_ERR(flow_rule)) {
err = PTR_ERR(flow_rule);
- else
- vport->egress.offloads.bounce_rule = flow_rule;
+ } else {
+ err = xa_insert(&vport->egress.offloads.bounce_rules,
+ slave_index, flow_rule, GFP_KERNEL);
+ if (err)
+ mlx5_del_flow_rules(flow_rule);
+ }
kvfree(spec);
return err;
}
-static int esw_set_master_egress_rule(struct mlx5_core_dev *master,
- struct mlx5_core_dev *slave)
+static int esw_master_egress_create_resources(struct mlx5_eswitch *esw,
+ struct mlx5_flow_namespace *egress_ns,
+ struct mlx5_vport *vport, size_t count)
{
int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
- struct mlx5_eswitch *esw = master->priv.eswitch;
struct mlx5_flow_table_attr ft_attr = {
- .max_fte = 1, .prio = 0, .level = 0,
- .flags = MLX5_FLOW_TABLE_OTHER_VPORT,
+ .max_fte = count, .prio = 0, .level = 0,
};
- struct mlx5_flow_namespace *egress_ns;
struct mlx5_flow_table *acl;
struct mlx5_flow_group *g;
- struct mlx5_vport *vport;
void *match_criteria;
u32 *flow_group_in;
int err;
- vport = mlx5_eswitch_get_vport(esw, esw->manager_vport);
- if (IS_ERR(vport))
- return PTR_ERR(vport);
-
- egress_ns = mlx5_get_flow_vport_acl_namespace(master,
- MLX5_FLOW_NAMESPACE_ESW_EGRESS,
- vport->index);
- if (!egress_ns)
- return -EINVAL;
-
if (vport->egress.acl)
- return -EINVAL;
+ return 0;
flow_group_in = kvzalloc(inlen, GFP_KERNEL);
if (!flow_group_in)
return -ENOMEM;
+ if (vport->vport || mlx5_core_is_ecpf(esw->dev))
+ ft_attr.flags = MLX5_FLOW_TABLE_OTHER_VPORT;
+
acl = mlx5_create_vport_flow_table(egress_ns, &ft_attr, vport->vport);
if (IS_ERR(acl)) {
err = PTR_ERR(acl);
@@ -2568,7 +2591,7 @@ static int esw_set_master_egress_rule(struct mlx5_core_dev *master,
MLX5_SET(create_flow_group_in, flow_group_in,
source_eswitch_owner_vhca_id_valid, 1);
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
- MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
+ MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, count);
g = mlx5_create_flow_group(acl, flow_group_in);
if (IS_ERR(g)) {
@@ -2576,19 +2599,15 @@ static int esw_set_master_egress_rule(struct mlx5_core_dev *master,
goto err_group;
}
- err = __esw_set_master_egress_rule(master, slave, vport, acl);
- if (err)
- goto err_rule;
-
vport->egress.acl = acl;
vport->egress.offloads.bounce_grp = g;
+ vport->egress.type = VPORT_EGRESS_ACL_TYPE_SHARED_FDB;
+ xa_init_flags(&vport->egress.offloads.bounce_rules, XA_FLAGS_ALLOC);
kvfree(flow_group_in);
return 0;
-err_rule:
- mlx5_destroy_flow_group(g);
err_group:
mlx5_destroy_flow_table(acl);
out:
@@ -2596,18 +2615,74 @@ out:
return err;
}
-static void esw_unset_master_egress_rule(struct mlx5_core_dev *dev)
+static void esw_master_egress_destroy_resources(struct mlx5_vport *vport)
+{
+ if (!xa_empty(&vport->egress.offloads.bounce_rules))
+ return;
+ mlx5_destroy_flow_group(vport->egress.offloads.bounce_grp);
+ vport->egress.offloads.bounce_grp = NULL;
+ mlx5_destroy_flow_table(vport->egress.acl);
+ vport->egress.acl = NULL;
+}
+
+static int esw_set_master_egress_rule(struct mlx5_core_dev *master,
+ struct mlx5_core_dev *slave, size_t count)
+{
+ struct mlx5_eswitch *esw = master->priv.eswitch;
+ u16 slave_index = MLX5_CAP_GEN(slave, vhca_id);
+ struct mlx5_flow_namespace *egress_ns;
+ struct mlx5_vport *vport;
+ int err;
+
+ vport = mlx5_eswitch_get_vport(esw, esw->manager_vport);
+ if (IS_ERR(vport))
+ return PTR_ERR(vport);
+
+ egress_ns = mlx5_get_flow_vport_acl_namespace(master,
+ MLX5_FLOW_NAMESPACE_ESW_EGRESS,
+ vport->index);
+ if (!egress_ns)
+ return -EINVAL;
+
+ if (vport->egress.acl && vport->egress.type != VPORT_EGRESS_ACL_TYPE_SHARED_FDB)
+ return 0;
+
+ err = esw_master_egress_create_resources(esw, egress_ns, vport, count);
+ if (err)
+ return err;
+
+ if (xa_load(&vport->egress.offloads.bounce_rules, slave_index))
+ return -EINVAL;
+
+ err = __esw_set_master_egress_rule(master, slave, vport, vport->egress.acl);
+ if (err)
+ goto err_rule;
+
+ return 0;
+
+err_rule:
+ esw_master_egress_destroy_resources(vport);
+ return err;
+}
+
+static void esw_unset_master_egress_rule(struct mlx5_core_dev *dev,
+ struct mlx5_core_dev *slave_dev)
{
struct mlx5_vport *vport;
vport = mlx5_eswitch_get_vport(dev->priv.eswitch,
dev->priv.eswitch->manager_vport);
- esw_acl_egress_ofld_cleanup(vport);
+ esw_acl_egress_ofld_bounce_rule_destroy(vport, MLX5_CAP_GEN(slave_dev, vhca_id));
+
+ if (xa_empty(&vport->egress.offloads.bounce_rules)) {
+ esw_acl_egress_ofld_cleanup(vport);
+ xa_destroy(&vport->egress.offloads.bounce_rules);
+ }
}
-int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw,
- struct mlx5_eswitch *slave_esw)
+int mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw,
+ struct mlx5_eswitch *slave_esw, int max_slaves)
{
int err;
@@ -2617,7 +2692,7 @@ int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw,
return err;
err = esw_set_master_egress_rule(master_esw->dev,
- slave_esw->dev);
+ slave_esw->dev, max_slaves);
if (err)
goto err_acl;
@@ -2625,21 +2700,21 @@ int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw,
err_acl:
esw_set_slave_root_fdb(NULL, slave_esw->dev);
-
return err;
}
-void mlx5_eswitch_offloads_destroy_single_fdb(struct mlx5_eswitch *master_esw,
+void mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw,
struct mlx5_eswitch *slave_esw)
{
- esw_unset_master_egress_rule(master_esw->dev);
esw_set_slave_root_fdb(NULL, slave_esw->dev);
+ esw_unset_master_egress_rule(master_esw->dev, slave_esw->dev);
}
#define ESW_OFFLOADS_DEVCOM_PAIR (0)
#define ESW_OFFLOADS_DEVCOM_UNPAIR (1)
-static void mlx5_esw_offloads_rep_event_unpair(struct mlx5_eswitch *esw)
+static void mlx5_esw_offloads_rep_event_unpair(struct mlx5_eswitch *esw,
+ struct mlx5_eswitch *peer_esw)
{
const struct mlx5_eswitch_rep_ops *ops;
struct mlx5_eswitch_rep *rep;
@@ -2652,18 +2727,19 @@ static void mlx5_esw_offloads_rep_event_unpair(struct mlx5_eswitch *esw)
ops = esw->offloads.rep_ops[rep_type];
if (atomic_read(&rep->rep_data[rep_type].state) == REP_LOADED &&
ops->event)
- ops->event(esw, rep, MLX5_SWITCHDEV_EVENT_UNPAIR, NULL);
+ ops->event(esw, rep, MLX5_SWITCHDEV_EVENT_UNPAIR, peer_esw);
}
}
}
-static void mlx5_esw_offloads_unpair(struct mlx5_eswitch *esw)
+static void mlx5_esw_offloads_unpair(struct mlx5_eswitch *esw,
+ struct mlx5_eswitch *peer_esw)
{
#if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
mlx5e_tc_clean_fdb_peer_flows(esw);
#endif
- mlx5_esw_offloads_rep_event_unpair(esw);
- esw_del_fdb_peer_miss_rules(esw);
+ mlx5_esw_offloads_rep_event_unpair(esw, peer_esw);
+ esw_del_fdb_peer_miss_rules(esw, peer_esw->dev);
}
static int mlx5_esw_offloads_pair(struct mlx5_eswitch *esw,
@@ -2694,7 +2770,7 @@ static int mlx5_esw_offloads_pair(struct mlx5_eswitch *esw,
return 0;
err_out:
- mlx5_esw_offloads_unpair(esw);
+ mlx5_esw_offloads_unpair(esw, peer_esw);
return err;
}
@@ -2702,6 +2778,8 @@ static int mlx5_esw_offloads_set_ns_peer(struct mlx5_eswitch *esw,
struct mlx5_eswitch *peer_esw,
bool pair)
{
+ u16 peer_vhca_id = MLX5_CAP_GEN(peer_esw->dev, vhca_id);
+ u16 vhca_id = MLX5_CAP_GEN(esw->dev, vhca_id);
struct mlx5_flow_root_namespace *peer_ns;
struct mlx5_flow_root_namespace *ns;
int err;
@@ -2710,18 +2788,18 @@ static int mlx5_esw_offloads_set_ns_peer(struct mlx5_eswitch *esw,
ns = esw->dev->priv.steering->fdb_root_ns;
if (pair) {
- err = mlx5_flow_namespace_set_peer(ns, peer_ns);
+ err = mlx5_flow_namespace_set_peer(ns, peer_ns, peer_vhca_id);
if (err)
return err;
- err = mlx5_flow_namespace_set_peer(peer_ns, ns);
+ err = mlx5_flow_namespace_set_peer(peer_ns, ns, vhca_id);
if (err) {
- mlx5_flow_namespace_set_peer(ns, NULL);
+ mlx5_flow_namespace_set_peer(ns, NULL, peer_vhca_id);
return err;
}
} else {
- mlx5_flow_namespace_set_peer(ns, NULL);
- mlx5_flow_namespace_set_peer(peer_ns, NULL);
+ mlx5_flow_namespace_set_peer(ns, NULL, peer_vhca_id);
+ mlx5_flow_namespace_set_peer(peer_ns, NULL, vhca_id);
}
return 0;
@@ -2734,15 +2812,21 @@ static int mlx5_esw_offloads_devcom_event(int event,
struct mlx5_eswitch *esw = my_data;
struct mlx5_devcom *devcom = esw->dev->priv.devcom;
struct mlx5_eswitch *peer_esw = event_data;
+ u16 esw_i, peer_esw_i;
+ bool esw_paired;
int err;
+ peer_esw_i = MLX5_CAP_GEN(peer_esw->dev, vhca_id);
+ esw_i = MLX5_CAP_GEN(esw->dev, vhca_id);
+ esw_paired = !!xa_load(&esw->paired, peer_esw_i);
+
switch (event) {
case ESW_OFFLOADS_DEVCOM_PAIR:
if (mlx5_eswitch_vport_match_metadata_enabled(esw) !=
mlx5_eswitch_vport_match_metadata_enabled(peer_esw))
break;
- if (esw->paired[mlx5_get_dev_index(peer_esw->dev)])
+ if (esw_paired)
break;
err = mlx5_esw_offloads_set_ns_peer(esw, peer_esw, true);
@@ -2756,28 +2840,43 @@ static int mlx5_esw_offloads_devcom_event(int event,
if (err)
goto err_pair;
- esw->paired[mlx5_get_dev_index(peer_esw->dev)] = true;
- peer_esw->paired[mlx5_get_dev_index(esw->dev)] = true;
- mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true);
+ err = xa_insert(&esw->paired, peer_esw_i, peer_esw, GFP_KERNEL);
+ if (err)
+ goto err_xa;
+
+ err = xa_insert(&peer_esw->paired, esw_i, esw, GFP_KERNEL);
+ if (err)
+ goto err_peer_xa;
+
+ esw->num_peers++;
+ peer_esw->num_peers++;
+ mlx5_devcom_comp_set_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true);
break;
case ESW_OFFLOADS_DEVCOM_UNPAIR:
- if (!esw->paired[mlx5_get_dev_index(peer_esw->dev)])
+ if (!esw_paired)
break;
- mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false);
- esw->paired[mlx5_get_dev_index(peer_esw->dev)] = false;
- peer_esw->paired[mlx5_get_dev_index(esw->dev)] = false;
- mlx5_esw_offloads_unpair(peer_esw);
- mlx5_esw_offloads_unpair(esw);
+ peer_esw->num_peers--;
+ esw->num_peers--;
+ if (!esw->num_peers && !peer_esw->num_peers)
+ mlx5_devcom_comp_set_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false);
+ xa_erase(&peer_esw->paired, esw_i);
+ xa_erase(&esw->paired, peer_esw_i);
+ mlx5_esw_offloads_unpair(peer_esw, esw);
+ mlx5_esw_offloads_unpair(esw, peer_esw);
mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false);
break;
}
return 0;
+err_peer_xa:
+ xa_erase(&esw->paired, peer_esw_i);
+err_xa:
+ mlx5_esw_offloads_unpair(peer_esw, esw);
err_pair:
- mlx5_esw_offloads_unpair(esw);
+ mlx5_esw_offloads_unpair(esw, peer_esw);
err_peer:
mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false);
err_out:
@@ -2789,24 +2888,29 @@ err_out:
void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw)
{
struct mlx5_devcom *devcom = esw->dev->priv.devcom;
+ int i;
- INIT_LIST_HEAD(&esw->offloads.peer_flows);
+ for (i = 0; i < MLX5_MAX_PORTS; i++)
+ INIT_LIST_HEAD(&esw->offloads.peer_flows[i]);
mutex_init(&esw->offloads.peer_mutex);
if (!MLX5_CAP_ESW(esw->dev, merged_eswitch))
return;
- if (!mlx5_is_lag_supported(esw->dev))
+ if (!mlx5_lag_is_supported(esw->dev))
return;
+ xa_init(&esw->paired);
mlx5_devcom_register_component(devcom,
MLX5_DEVCOM_ESW_OFFLOADS,
mlx5_esw_offloads_devcom_event,
esw);
+ esw->num_peers = 0;
mlx5_devcom_send_event(devcom,
MLX5_DEVCOM_ESW_OFFLOADS,
- ESW_OFFLOADS_DEVCOM_PAIR, esw);
+ ESW_OFFLOADS_DEVCOM_PAIR,
+ ESW_OFFLOADS_DEVCOM_UNPAIR, esw);
}
void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw)
@@ -2816,13 +2920,15 @@ void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw)
if (!MLX5_CAP_ESW(esw->dev, merged_eswitch))
return;
- if (!mlx5_is_lag_supported(esw->dev))
+ if (!mlx5_lag_is_supported(esw->dev))
return;
mlx5_devcom_send_event(devcom, MLX5_DEVCOM_ESW_OFFLOADS,
+ ESW_OFFLOADS_DEVCOM_UNPAIR,
ESW_OFFLOADS_DEVCOM_UNPAIR, esw);
mlx5_devcom_unregister_component(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ xa_destroy(&esw->paired);
}
bool mlx5_esw_vport_match_metadata_supported(const struct mlx5_eswitch *esw)
@@ -2834,9 +2940,6 @@ bool mlx5_esw_vport_match_metadata_supported(const struct mlx5_eswitch *esw)
MLX5_FDB_TO_VPORT_REG_C_0))
return false;
- if (!MLX5_CAP_ESW_FLOWTABLE(esw->dev, flow_source))
- return false;
-
return true;
}
@@ -3247,6 +3350,9 @@ int esw_offloads_enable(struct mlx5_eswitch *esw)
/* Representor will control the vport link state */
mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
vport->info.link_state = MLX5_VPORT_ADMIN_STATE_DOWN;
+ if (mlx5_core_ec_sriov_enabled(esw->dev))
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs)
+ vport->info.link_state = MLX5_VPORT_ADMIN_STATE_DOWN;
/* Uplink vport rep must load first. */
err = esw_offloads_load_rep(esw, MLX5_VPORT_UPLINK);
@@ -3285,7 +3391,7 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw,
/* If changing from switchdev to legacy mode without sriov enabled,
* no need to create legacy fdb.
*/
- if (!mlx5_sriov_is_enabled(esw->dev))
+ if (!mlx5_core_is_pf(esw->dev) || !mlx5_sriov_is_enabled(esw->dev))
return 0;
err = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_IGNORE_NUM_VFS);
@@ -3484,8 +3590,27 @@ static int mlx5_esw_vports_inline_set(struct mlx5_eswitch *esw, u8 mlx5_mode,
goto revert_inline_mode;
}
}
+ if (mlx5_core_ec_sriov_enabled(esw->dev)) {
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) {
+ err = mlx5_modify_nic_vport_min_inline(dev, vport->vport, mlx5_mode);
+ if (err) {
+ err_vport_num = vport->vport;
+ NL_SET_ERR_MSG_MOD(extack,
+ "Failed to set min inline on vport");
+ goto revert_ec_vf_inline_mode;
+ }
+ }
+ }
return 0;
+revert_ec_vf_inline_mode:
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) {
+ if (vport->vport == err_vport_num)
+ break;
+ mlx5_modify_nic_vport_min_inline(dev,
+ vport->vport,
+ esw->offloads.inline_mode);
+ }
revert_inline_mode:
mlx5_esw_for_each_host_func_vport(esw, i, vport, esw->esw_funcs.num_vfs) {
if (vport->vport == err_vport_num)
@@ -3835,9 +3960,6 @@ static int mlx5_esw_query_vport_vhca_id(struct mlx5_eswitch *esw, u16 vport_num,
int err;
*vhca_id = 0;
- if (mlx5_esw_is_manager_vport(esw, vport_num) ||
- !MLX5_CAP_GEN(esw->dev, vhca_resource_manager))
- return -EPERM;
query_ctx = kzalloc(query_out_sz, GFP_KERNEL);
if (!query_ctx)
@@ -3926,9 +4048,9 @@ is_port_function_supported(struct mlx5_eswitch *esw, u16 vport_num)
mlx5_esw_is_sf_vport(esw, vport_num);
}
-int mlx5_devlink_port_function_hw_addr_get(struct devlink_port *port,
- u8 *hw_addr, int *hw_addr_len,
- struct netlink_ext_ack *extack)
+int mlx5_devlink_port_fn_hw_addr_get(struct devlink_port *port,
+ u8 *hw_addr, int *hw_addr_len,
+ struct netlink_ext_ack *extack)
{
struct mlx5_eswitch *esw;
struct mlx5_vport *vport;
@@ -3955,9 +4077,9 @@ int mlx5_devlink_port_function_hw_addr_get(struct devlink_port *port,
return 0;
}
-int mlx5_devlink_port_function_hw_addr_set(struct devlink_port *port,
- const u8 *hw_addr, int hw_addr_len,
- struct netlink_ext_ack *extack)
+int mlx5_devlink_port_fn_hw_addr_set(struct devlink_port *port,
+ const u8 *hw_addr, int hw_addr_len,
+ struct netlink_ext_ack *extack)
{
struct mlx5_eswitch *esw;
u16 vport_num;
@@ -4073,7 +4195,7 @@ int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable,
}
hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
- MLX5_SET(cmd_hca_cap_2, hca_caps, migratable, 1);
+ MLX5_SET(cmd_hca_cap_2, hca_caps, migratable, enable);
err = mlx5_vport_set_other_func_cap(esw->dev, hca_caps, vport->vport,
MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE2);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c b/drivers/net/ethernet/mellanox/mlx5/core/events.c
index 718cf09c28ce..3ec892d51f57 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/events.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c
@@ -5,7 +5,7 @@
#include "mlx5_core.h"
#include "lib/eq.h"
-#include "lib/mlx5.h"
+#include "lib/events.h"
struct mlx5_event_nb {
struct mlx5_nb nb;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
index ec83e6483d1a..244cfd470903 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
@@ -139,7 +139,8 @@ static void mlx5_cmd_stub_modify_header_dealloc(struct mlx5_flow_root_namespace
}
static int mlx5_cmd_stub_set_peer(struct mlx5_flow_root_namespace *ns,
- struct mlx5_flow_root_namespace *peer_ns)
+ struct mlx5_flow_root_namespace *peer_ns,
+ u16 peer_vhca_id)
{
return 0;
}
@@ -243,16 +244,30 @@ static int mlx5_cmd_update_root_ft(struct mlx5_flow_root_namespace *ns,
ft->type == FS_FT_FDB &&
mlx5_lag_is_shared_fdb(dev) &&
mlx5_lag_is_master(dev)) {
- err = mlx5_cmd_set_slave_root_fdb(dev,
- mlx5_lag_get_peer_mdev(dev),
- !disconnect, (!disconnect) ?
- ft->id : 0);
- if (err && !disconnect) {
- MLX5_SET(set_flow_table_root_in, in, op_mod, 0);
- MLX5_SET(set_flow_table_root_in, in, table_id,
- ns->root_ft->id);
- mlx5_cmd_exec_in(dev, set_flow_table_root, in);
+ struct mlx5_core_dev *peer_dev;
+ int i, j;
+
+ mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) {
+ err = mlx5_cmd_set_slave_root_fdb(dev, peer_dev, !disconnect,
+ (!disconnect) ? ft->id : 0);
+ if (err && !disconnect) {
+ mlx5_lag_for_each_peer_mdev(dev, peer_dev, j) {
+ if (j < i)
+ mlx5_cmd_set_slave_root_fdb(dev, peer_dev, 1,
+ ns->root_ft->id);
+ else
+ break;
+ }
+
+ MLX5_SET(set_flow_table_root_in, in, op_mod, 0);
+ MLX5_SET(set_flow_table_root_in, in, table_id,
+ ns->root_ft->id);
+ mlx5_cmd_exec_in(dev, set_flow_table_root, in);
+ }
+ if (err)
+ break;
}
+
}
return err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
index 8ef4254b9ea1..7790ae5531e1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
@@ -93,7 +93,8 @@ struct mlx5_flow_cmds {
struct mlx5_modify_hdr *modify_hdr);
int (*set_peer)(struct mlx5_flow_root_namespace *ns,
- struct mlx5_flow_root_namespace *peer_ns);
+ struct mlx5_flow_root_namespace *peer_ns,
+ u16 peer_vhca_id);
int (*create_ns)(struct mlx5_flow_root_namespace *ns);
int (*destroy_ns)(struct mlx5_flow_root_namespace *ns);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index 19da02c41616..6b069fa411c5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -889,7 +889,7 @@ static struct mlx5_flow_table *find_closest_ft_recursive(struct fs_node *root,
struct fs_node *iter = list_entry(start, struct fs_node, list);
struct mlx5_flow_table *ft = NULL;
- if (!root || root->type == FS_TYPE_PRIO_CHAINS)
+ if (!root)
return NULL;
list_for_each_advance_continue(iter, &root->children, reverse) {
@@ -905,20 +905,42 @@ static struct mlx5_flow_table *find_closest_ft_recursive(struct fs_node *root,
return ft;
}
-/* If reverse is false then return the first flow table in next priority of
- * prio in the tree, else return the last flow table in the previous priority
- * of prio in the tree.
+static struct fs_node *find_prio_chains_parent(struct fs_node *parent,
+ struct fs_node **child)
+{
+ struct fs_node *node = NULL;
+
+ while (parent && parent->type != FS_TYPE_PRIO_CHAINS) {
+ node = parent;
+ parent = parent->parent;
+ }
+
+ if (child)
+ *child = node;
+
+ return parent;
+}
+
+/* If reverse is false then return the first flow table next to the passed node
+ * in the tree, else return the last flow table before the node in the tree.
+ * If skip is true, skip the flow tables in the same prio_chains prio.
*/
-static struct mlx5_flow_table *find_closest_ft(struct fs_prio *prio, bool reverse)
+static struct mlx5_flow_table *find_closest_ft(struct fs_node *node, bool reverse,
+ bool skip)
{
+ struct fs_node *prio_chains_parent = NULL;
struct mlx5_flow_table *ft = NULL;
struct fs_node *curr_node;
struct fs_node *parent;
- parent = prio->node.parent;
- curr_node = &prio->node;
+ if (skip)
+ prio_chains_parent = find_prio_chains_parent(node, NULL);
+ parent = node->parent;
+ curr_node = node;
while (!ft && parent) {
- ft = find_closest_ft_recursive(parent, &curr_node->list, reverse);
+ if (parent != prio_chains_parent)
+ ft = find_closest_ft_recursive(parent, &curr_node->list,
+ reverse);
curr_node = parent;
parent = curr_node->parent;
}
@@ -926,15 +948,15 @@ static struct mlx5_flow_table *find_closest_ft(struct fs_prio *prio, bool revers
}
/* Assuming all the tree is locked by mutex chain lock */
-static struct mlx5_flow_table *find_next_chained_ft(struct fs_prio *prio)
+static struct mlx5_flow_table *find_next_chained_ft(struct fs_node *node)
{
- return find_closest_ft(prio, false);
+ return find_closest_ft(node, false, true);
}
/* Assuming all the tree is locked by mutex chain lock */
-static struct mlx5_flow_table *find_prev_chained_ft(struct fs_prio *prio)
+static struct mlx5_flow_table *find_prev_chained_ft(struct fs_node *node)
{
- return find_closest_ft(prio, true);
+ return find_closest_ft(node, true, true);
}
static struct mlx5_flow_table *find_next_fwd_ft(struct mlx5_flow_table *ft,
@@ -946,7 +968,7 @@ static struct mlx5_flow_table *find_next_fwd_ft(struct mlx5_flow_table *ft,
next_ns = flow_act->action & MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_NS;
fs_get_obj(prio, next_ns ? ft->ns->node.parent : ft->node.parent);
- return find_next_chained_ft(prio);
+ return find_next_chained_ft(&prio->node);
}
static int connect_fts_in_prio(struct mlx5_core_dev *dev,
@@ -970,21 +992,55 @@ static int connect_fts_in_prio(struct mlx5_core_dev *dev,
return 0;
}
+static struct mlx5_flow_table *find_closet_ft_prio_chains(struct fs_node *node,
+ struct fs_node *parent,
+ struct fs_node **child,
+ bool reverse)
+{
+ struct mlx5_flow_table *ft;
+
+ ft = find_closest_ft(node, reverse, false);
+
+ if (ft && parent == find_prio_chains_parent(&ft->node, child))
+ return ft;
+
+ return NULL;
+}
+
/* Connect flow tables from previous priority of prio to ft */
static int connect_prev_fts(struct mlx5_core_dev *dev,
struct mlx5_flow_table *ft,
struct fs_prio *prio)
{
+ struct fs_node *prio_parent, *parent = NULL, *child, *node;
struct mlx5_flow_table *prev_ft;
+ int err = 0;
+
+ prio_parent = find_prio_chains_parent(&prio->node, &child);
+
+ /* return directly if not under the first sub ns of prio_chains prio */
+ if (prio_parent && !list_is_first(&child->list, &prio_parent->children))
+ return 0;
- prev_ft = find_prev_chained_ft(prio);
- if (prev_ft) {
+ prev_ft = find_prev_chained_ft(&prio->node);
+ while (prev_ft) {
struct fs_prio *prev_prio;
fs_get_obj(prev_prio, prev_ft->node.parent);
- return connect_fts_in_prio(dev, prev_prio, ft);
+ err = connect_fts_in_prio(dev, prev_prio, ft);
+ if (err)
+ break;
+
+ if (!parent) {
+ parent = find_prio_chains_parent(&prev_prio->node, &child);
+ if (!parent)
+ break;
+ }
+
+ node = child;
+ prev_ft = find_closet_ft_prio_chains(node, parent, &child, true);
}
- return 0;
+ return err;
}
static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio
@@ -1123,7 +1179,7 @@ static int connect_flow_table(struct mlx5_core_dev *dev, struct mlx5_flow_table
if (err)
return err;
- next_ft = first_ft ? first_ft : find_next_chained_ft(prio);
+ next_ft = first_ft ? first_ft : find_next_chained_ft(&prio->node);
err = connect_fwd_rules(dev, ft, next_ft);
if (err)
return err;
@@ -1198,7 +1254,7 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa
tree_init_node(&ft->node, del_hw_flow_table, del_sw_flow_table);
next_ft = unmanaged ? ft_attr->next_ft :
- find_next_chained_ft(fs_prio);
+ find_next_chained_ft(&fs_prio->node);
ft->def_miss_action = ns->def_miss_action;
ft->ns = ns;
err = root->cmds->create_flow_table(root, ft, ft_attr, next_ft);
@@ -2195,13 +2251,20 @@ EXPORT_SYMBOL(mlx5_del_flow_rules);
/* Assuming prio->node.children(flow tables) is sorted by level */
static struct mlx5_flow_table *find_next_ft(struct mlx5_flow_table *ft)
{
+ struct fs_node *prio_parent, *child;
struct fs_prio *prio;
fs_get_obj(prio, ft->node.parent);
if (!list_is_last(&ft->node.list, &prio->node.children))
return list_next_entry(ft, node.list);
- return find_next_chained_ft(prio);
+
+ prio_parent = find_prio_chains_parent(&prio->node, &child);
+
+ if (prio_parent && list_is_first(&child->list, &prio_parent->children))
+ return find_closest_ft(&prio->node, false, false);
+
+ return find_next_chained_ft(&prio->node);
}
static int update_root_ft_destroy(struct mlx5_flow_table *ft)
@@ -3620,7 +3683,8 @@ void mlx5_destroy_match_definer(struct mlx5_core_dev *dev,
}
int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns,
- struct mlx5_flow_root_namespace *peer_ns)
+ struct mlx5_flow_root_namespace *peer_ns,
+ u16 peer_vhca_id)
{
if (peer_ns && ns->mode != peer_ns->mode) {
mlx5_core_err(ns->dev,
@@ -3628,7 +3692,7 @@ int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns,
return -EINVAL;
}
- return ns->cmds->set_peer(ns, peer_ns);
+ return ns->cmds->set_peer(ns, peer_ns, peer_vhca_id);
}
/* This function should be called only at init stage of the namespace.
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
index b043190e50a8..4aed1768b85f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
@@ -302,7 +302,8 @@ void mlx5_fc_update_sampling_interval(struct mlx5_core_dev *dev,
const struct mlx5_flow_cmds *mlx5_fs_cmd_get_fw_cmds(void);
int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns,
- struct mlx5_flow_root_namespace *peer_ns);
+ struct mlx5_flow_root_namespace *peer_ns,
+ u16 peer_vhca_id);
int mlx5_flow_namespace_set_mode(struct mlx5_flow_namespace *ns,
enum mlx5_flow_steering_mode mode);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw.c b/drivers/net/ethernet/mellanox/mlx5/core/fw.c
index 7bb7be01225a..fb2035a5ec99 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fw.c
@@ -196,14 +196,11 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev)
return err;
}
- if (MLX5_CAP_GEN(dev, vport_group_manager) &&
- MLX5_ESWITCH_MANAGER(dev)) {
+ if (MLX5_ESWITCH_MANAGER(dev)) {
err = mlx5_core_get_caps(dev, MLX5_CAP_ESWITCH_FLOW_TABLE);
if (err)
return err;
- }
- if (MLX5_ESWITCH_MANAGER(dev)) {
err = mlx5_core_get_caps(dev, MLX5_CAP_ESWITCH);
if (err)
return err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
index 50022e7565f1..4804990b7f22 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
@@ -21,6 +21,7 @@ struct mlx5_fw_reset {
struct workqueue_struct *wq;
struct work_struct fw_live_patch_work;
struct work_struct reset_request_work;
+ struct work_struct reset_unload_work;
struct work_struct reset_reload_work;
struct work_struct reset_now_work;
struct work_struct reset_abort_work;
@@ -30,6 +31,26 @@ struct mlx5_fw_reset {
int ret;
};
+enum {
+ MLX5_FW_RST_STATE_IDLE = 0,
+ MLX5_FW_RST_STATE_TOGGLE_REQ = 4,
+};
+
+enum {
+ MLX5_RST_STATE_BIT_NUM = 12,
+ MLX5_RST_ACK_BIT_NUM = 22,
+};
+
+static u8 mlx5_get_fw_rst_state(struct mlx5_core_dev *dev)
+{
+ return (ioread32be(&dev->iseg->initializing) >> MLX5_RST_STATE_BIT_NUM) & 0xF;
+}
+
+static void mlx5_set_fw_rst_ack(struct mlx5_core_dev *dev)
+{
+ iowrite32be(BIT(MLX5_RST_ACK_BIT_NUM), &dev->iseg->initializing);
+}
+
static int mlx5_fw_reset_enable_remote_dev_reset_set(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
{
@@ -155,7 +176,7 @@ int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev)
return mlx5_reg_mfrl_set(dev, MLX5_MFRL_REG_RESET_LEVEL0, 0, 0, false);
}
-static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev)
+static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev, bool unloaded)
{
struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
@@ -163,7 +184,8 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev)
if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) {
complete(&fw_reset->done);
} else {
- mlx5_unload_one(dev, false);
+ if (!unloaded)
+ mlx5_unload_one(dev, false);
if (mlx5_health_wait_pci_up(dev))
mlx5_core_err(dev, "reset reload flow aborted, PCI reads still not working\n");
else
@@ -204,7 +226,7 @@ static void mlx5_sync_reset_reload_work(struct work_struct *work)
mlx5_sync_reset_clear_reset_requested(dev, false);
mlx5_enter_error_state(dev, true);
- mlx5_fw_reset_complete_reload(dev);
+ mlx5_fw_reset_complete_reload(dev, false);
}
#define MLX5_RESET_POLL_INTERVAL (HZ / 10)
@@ -276,6 +298,44 @@ static void mlx5_fw_live_patch_event(struct work_struct *work)
mlx5_core_err(dev, "Failed to reload FW tracer\n");
}
+static int mlx5_check_dev_ids(struct mlx5_core_dev *dev, u16 dev_id)
+{
+ struct pci_bus *bridge_bus = dev->pdev->bus;
+ struct pci_dev *sdev;
+ u16 sdev_id;
+ int err;
+
+ /* Check that all functions under the pci bridge are PFs of
+ * this device otherwise fail this function.
+ */
+ list_for_each_entry(sdev, &bridge_bus->devices, bus_list) {
+ err = pci_read_config_word(sdev, PCI_DEVICE_ID, &sdev_id);
+ if (err)
+ return err;
+ if (sdev_id != dev_id) {
+ mlx5_core_warn(dev, "unrecognized dev_id (0x%x)\n", sdev_id);
+ return -EPERM;
+ }
+ }
+ return 0;
+}
+
+static bool mlx5_is_reset_now_capable(struct mlx5_core_dev *dev)
+{
+ u16 dev_id;
+ int err;
+
+ if (!MLX5_CAP_GEN(dev, fast_teardown)) {
+ mlx5_core_warn(dev, "fast teardown is not supported by firmware\n");
+ return false;
+ }
+
+ err = pci_read_config_word(dev->pdev, PCI_DEVICE_ID, &dev_id);
+ if (err)
+ return false;
+ return (!mlx5_check_dev_ids(dev, dev_id));
+}
+
static void mlx5_sync_reset_request_event(struct work_struct *work)
{
struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset,
@@ -283,7 +343,8 @@ static void mlx5_sync_reset_request_event(struct work_struct *work)
struct mlx5_core_dev *dev = fw_reset->dev;
int err;
- if (test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags)) {
+ if (test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags) ||
+ !mlx5_is_reset_now_capable(dev)) {
err = mlx5_fw_reset_set_reset_sync_nack(dev);
mlx5_core_warn(dev, "PCI Sync FW Update Reset Nack %s",
err ? "Failed" : "Sent");
@@ -303,26 +364,17 @@ static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev)
{
struct pci_bus *bridge_bus = dev->pdev->bus;
struct pci_dev *bridge = bridge_bus->self;
- u16 reg16, dev_id, sdev_id;
unsigned long timeout;
struct pci_dev *sdev;
+ u16 reg16, dev_id;
int cap, err;
- u32 reg32;
- /* Check that all functions under the pci bridge are PFs of
- * this device otherwise fail this function.
- */
err = pci_read_config_word(dev->pdev, PCI_DEVICE_ID, &dev_id);
if (err)
return err;
- list_for_each_entry(sdev, &bridge_bus->devices, bus_list) {
- err = pci_read_config_word(sdev, PCI_DEVICE_ID, &sdev_id);
- if (err)
- return err;
- if (sdev_id != dev_id)
- return -EPERM;
- }
-
+ err = mlx5_check_dev_ids(dev, dev_id);
+ if (err)
+ return err;
cap = pci_find_capability(bridge, PCI_CAP_ID_EXP);
if (!cap)
return -EOPNOTSUPP;
@@ -346,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;
}
@@ -427,7 +476,70 @@ static void mlx5_sync_reset_now_event(struct work_struct *work)
mlx5_enter_error_state(dev, true);
done:
fw_reset->ret = err;
- mlx5_fw_reset_complete_reload(dev);
+ mlx5_fw_reset_complete_reload(dev, false);
+}
+
+static void mlx5_sync_reset_unload_event(struct work_struct *work)
+{
+ struct mlx5_fw_reset *fw_reset;
+ struct mlx5_core_dev *dev;
+ unsigned long timeout;
+ bool reset_action;
+ u8 rst_state;
+ int err;
+
+ fw_reset = container_of(work, struct mlx5_fw_reset, reset_unload_work);
+ dev = fw_reset->dev;
+
+ if (mlx5_sync_reset_clear_reset_requested(dev, false))
+ return;
+
+ mlx5_core_warn(dev, "Sync Reset Unload. Function is forced down.\n");
+
+ err = mlx5_cmd_fast_teardown_hca(dev);
+ if (err)
+ mlx5_core_warn(dev, "Fast teardown failed, unloading, err %d\n", err);
+ else
+ mlx5_enter_error_state(dev, true);
+
+ if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags))
+ mlx5_unload_one_devl_locked(dev, false);
+ else
+ mlx5_unload_one(dev, false);
+
+ mlx5_set_fw_rst_ack(dev);
+ mlx5_core_warn(dev, "Sync Reset Unload done, device reset expected\n");
+
+ reset_action = false;
+ timeout = jiffies + msecs_to_jiffies(mlx5_tout_ms(dev, RESET_UNLOAD));
+ do {
+ rst_state = mlx5_get_fw_rst_state(dev);
+ if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ ||
+ rst_state == MLX5_FW_RST_STATE_IDLE) {
+ reset_action = true;
+ break;
+ }
+ msleep(20);
+ } while (!time_after(jiffies, timeout));
+
+ if (!reset_action) {
+ mlx5_core_err(dev, "Got timeout waiting for sync reset action, state = %u\n",
+ rst_state);
+ fw_reset->ret = -ETIMEDOUT;
+ goto done;
+ }
+
+ mlx5_core_warn(dev, "Sync Reset, got reset action. rst_state = %u\n", rst_state);
+ if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ) {
+ err = mlx5_pci_link_toggle(dev);
+ if (err) {
+ mlx5_core_warn(dev, "mlx5_pci_link_toggle failed, err %d\n", err);
+ fw_reset->ret = err;
+ }
+ }
+
+done:
+ mlx5_fw_reset_complete_reload(dev, true);
}
static void mlx5_sync_reset_abort_event(struct work_struct *work)
@@ -452,6 +564,9 @@ static void mlx5_sync_reset_events_handle(struct mlx5_fw_reset *fw_reset, struct
case MLX5_SYNC_RST_STATE_RESET_REQUEST:
queue_work(fw_reset->wq, &fw_reset->reset_request_work);
break;
+ case MLX5_SYNC_RST_STATE_RESET_UNLOAD:
+ queue_work(fw_reset->wq, &fw_reset->reset_unload_work);
+ break;
case MLX5_SYNC_RST_STATE_RESET_NOW:
queue_work(fw_reset->wq, &fw_reset->reset_now_work);
break;
@@ -486,10 +601,13 @@ static int fw_reset_event_notifier(struct notifier_block *nb, unsigned long acti
int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev)
{
unsigned long pci_sync_update_timeout = mlx5_tout_ms(dev, PCI_SYNC_UPDATE);
- unsigned long timeout = msecs_to_jiffies(pci_sync_update_timeout);
struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
+ unsigned long timeout;
int err;
+ if (MLX5_CAP_GEN(dev, pci_sync_for_fw_update_with_driver_unload))
+ pci_sync_update_timeout += mlx5_tout_ms(dev, RESET_UNLOAD);
+ timeout = msecs_to_jiffies(pci_sync_update_timeout);
if (!wait_for_completion_timeout(&fw_reset->done, timeout)) {
mlx5_core_warn(dev, "FW sync reset timeout after %lu seconds\n",
pci_sync_update_timeout / 1000);
@@ -526,6 +644,7 @@ void mlx5_drain_fw_reset(struct mlx5_core_dev *dev)
set_bit(MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, &fw_reset->reset_flags);
cancel_work_sync(&fw_reset->fw_live_patch_work);
cancel_work_sync(&fw_reset->reset_request_work);
+ cancel_work_sync(&fw_reset->reset_unload_work);
cancel_work_sync(&fw_reset->reset_reload_work);
cancel_work_sync(&fw_reset->reset_now_work);
cancel_work_sync(&fw_reset->reset_abort_work);
@@ -564,6 +683,7 @@ int mlx5_fw_reset_init(struct mlx5_core_dev *dev)
INIT_WORK(&fw_reset->fw_live_patch_work, mlx5_fw_live_patch_event);
INIT_WORK(&fw_reset->reset_request_work, mlx5_sync_reset_request_event);
+ INIT_WORK(&fw_reset->reset_unload_work, mlx5_sync_reset_unload_event);
INIT_WORK(&fw_reset->reset_reload_work, mlx5_sync_reset_reload_work);
INIT_WORK(&fw_reset->reset_now_work, mlx5_sync_reset_now_event);
INIT_WORK(&fw_reset->reset_abort_work, mlx5_sync_reset_abort_event);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c
index 871c32dda66e..187cb2c464f8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/health.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c
@@ -39,6 +39,7 @@
#include "mlx5_core.h"
#include "lib/eq.h"
#include "lib/mlx5.h"
+#include "lib/events.h"
#include "lib/pci_vsc.h"
#include "lib/tout.h"
#include "diag/fw_tracer.h"
@@ -719,7 +720,7 @@ static const struct devlink_health_reporter_ops mlx5_fw_fatal_reporter_ops = {
#define MLX5_FW_REPORTER_VF_GRACEFUL_PERIOD 30000
#define MLX5_FW_REPORTER_DEFAULT_GRACEFUL_PERIOD MLX5_FW_REPORTER_VF_GRACEFUL_PERIOD
-static void mlx5_fw_reporters_create(struct mlx5_core_dev *dev)
+void mlx5_fw_reporters_create(struct mlx5_core_dev *dev)
{
struct mlx5_core_health *health = &dev->priv.health;
struct devlink *devlink = priv_to_devlink(dev);
@@ -735,17 +736,17 @@ static void mlx5_fw_reporters_create(struct mlx5_core_dev *dev)
}
health->fw_reporter =
- devlink_health_reporter_create(devlink, &mlx5_fw_reporter_ops,
- 0, dev);
+ devl_health_reporter_create(devlink, &mlx5_fw_reporter_ops,
+ 0, dev);
if (IS_ERR(health->fw_reporter))
mlx5_core_warn(dev, "Failed to create fw reporter, err = %ld\n",
PTR_ERR(health->fw_reporter));
health->fw_fatal_reporter =
- devlink_health_reporter_create(devlink,
- &mlx5_fw_fatal_reporter_ops,
- grace_period,
- dev);
+ devl_health_reporter_create(devlink,
+ &mlx5_fw_fatal_reporter_ops,
+ grace_period,
+ dev);
if (IS_ERR(health->fw_fatal_reporter))
mlx5_core_warn(dev, "Failed to create fw fatal reporter, err = %ld\n",
PTR_ERR(health->fw_fatal_reporter));
@@ -777,7 +778,8 @@ void mlx5_trigger_health_work(struct mlx5_core_dev *dev)
{
struct mlx5_core_health *health = &dev->priv.health;
- queue_work(health->wq, &health->fatal_report_work);
+ if (!mlx5_dev_is_lightweight(dev))
+ queue_work(health->wq, &health->fatal_report_work);
}
#define MLX5_MSEC_PER_HOUR (MSEC_PER_SEC * 60 * 60)
@@ -905,10 +907,15 @@ void mlx5_health_cleanup(struct mlx5_core_dev *dev)
int mlx5_health_init(struct mlx5_core_dev *dev)
{
+ struct devlink *devlink = priv_to_devlink(dev);
struct mlx5_core_health *health;
char *name;
- mlx5_fw_reporters_create(dev);
+ if (!mlx5_dev_is_lightweight(dev)) {
+ devl_lock(devlink);
+ mlx5_fw_reporters_create(dev);
+ devl_unlock(devlink);
+ }
mlx5_reporter_vnic_create(dev);
health = &dev->priv.health;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
index 5d331b940f4d..f0a074b2fcdf 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
@@ -512,8 +512,11 @@ static void mlx5_lag_set_port_sel_mode_offloads(struct mlx5_lag *ldev,
return;
if (MLX5_CAP_PORT_SELECTION(dev0->dev, port_select_flow_table) &&
- tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH)
+ tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH) {
+ if (ldev->ports > 2)
+ ldev->buckets = MLX5_LAG_MAX_HASH_BUCKETS;
set_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, flags);
+ }
}
static int mlx5_lag_set_flags(struct mlx5_lag *ldev, enum mlx5_lag_mode mode,
@@ -550,6 +553,29 @@ char *mlx5_get_str_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags)
}
}
+static int mlx5_lag_create_single_fdb(struct mlx5_lag *ldev)
+{
+ struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
+ struct mlx5_eswitch *master_esw = dev0->priv.eswitch;
+ int err;
+ int i;
+
+ for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) {
+ struct mlx5_eswitch *slave_esw = ldev->pf[i].dev->priv.eswitch;
+
+ err = mlx5_eswitch_offloads_single_fdb_add_one(master_esw,
+ slave_esw, ldev->ports);
+ if (err)
+ goto err;
+ }
+ return 0;
+err:
+ for (; i > MLX5_LAG_P1; i--)
+ mlx5_eswitch_offloads_single_fdb_del_one(master_esw,
+ ldev->pf[i].dev->priv.eswitch);
+ return err;
+}
+
static int mlx5_create_lag(struct mlx5_lag *ldev,
struct lag_tracker *tracker,
enum mlx5_lag_mode mode,
@@ -557,7 +583,6 @@ static int mlx5_create_lag(struct mlx5_lag *ldev,
{
bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags);
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
- struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {};
int err;
@@ -575,8 +600,7 @@ static int mlx5_create_lag(struct mlx5_lag *ldev,
}
if (shared_fdb) {
- err = mlx5_eswitch_offloads_config_single_fdb(dev0->priv.eswitch,
- dev1->priv.eswitch);
+ err = mlx5_lag_create_single_fdb(ldev);
if (err)
mlx5_core_err(dev0, "Can't enable single FDB mode\n");
else
@@ -647,19 +671,21 @@ int mlx5_activate_lag(struct mlx5_lag *ldev,
int mlx5_deactivate_lag(struct mlx5_lag *ldev)
{
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
- struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
+ struct mlx5_eswitch *master_esw = dev0->priv.eswitch;
u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {};
bool roce_lag = __mlx5_lag_is_roce(ldev);
unsigned long flags = ldev->mode_flags;
int err;
+ int i;
ldev->mode = MLX5_LAG_MODE_NONE;
ldev->mode_flags = 0;
mlx5_lag_mp_reset(ldev);
if (test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags)) {
- mlx5_eswitch_offloads_destroy_single_fdb(dev0->priv.eswitch,
- dev1->priv.eswitch);
+ for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++)
+ mlx5_eswitch_offloads_single_fdb_del_one(master_esw,
+ ldev->pf[i].dev->priv.eswitch);
clear_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags);
}
@@ -685,7 +711,7 @@ int mlx5_deactivate_lag(struct mlx5_lag *ldev)
return 0;
}
-#define MLX5_LAG_OFFLOADS_SUPPORTED_PORTS 2
+#define MLX5_LAG_OFFLOADS_SUPPORTED_PORTS 4
bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
{
#ifdef CONFIG_MLX5_ESWITCH
@@ -711,7 +737,7 @@ bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
if (mlx5_eswitch_mode(ldev->pf[i].dev) != mode)
return false;
- if (mode == MLX5_ESWITCH_OFFLOADS && ldev->ports != MLX5_LAG_OFFLOADS_SUPPORTED_PORTS)
+ if (mode == MLX5_ESWITCH_OFFLOADS && ldev->ports > MLX5_LAG_OFFLOADS_SUPPORTED_PORTS)
return false;
#else
for (i = 0; i < ldev->ports; i++)
@@ -759,7 +785,6 @@ void mlx5_disable_lag(struct mlx5_lag *ldev)
{
bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &ldev->mode_flags);
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
- struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
bool roce_lag;
int err;
int i;
@@ -784,28 +809,35 @@ void mlx5_disable_lag(struct mlx5_lag *ldev)
if (shared_fdb || roce_lag)
mlx5_lag_add_devices(ldev);
- if (shared_fdb) {
- if (!(dev0->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV))
- mlx5_eswitch_reload_reps(dev0->priv.eswitch);
- if (!(dev1->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV))
- mlx5_eswitch_reload_reps(dev1->priv.eswitch);
- }
+ if (shared_fdb)
+ for (i = 0; i < ldev->ports; i++)
+ if (!(ldev->pf[i].dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV))
+ mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
}
-bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev)
+static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev)
{
- struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
- struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
-
- if (is_mdev_switchdev_mode(dev0) &&
- is_mdev_switchdev_mode(dev1) &&
- mlx5_eswitch_vport_match_metadata_enabled(dev0->priv.eswitch) &&
- mlx5_eswitch_vport_match_metadata_enabled(dev1->priv.eswitch) &&
- mlx5_devcom_is_paired(dev0->priv.devcom,
- MLX5_DEVCOM_ESW_OFFLOADS) &&
- MLX5_CAP_GEN(dev1, lag_native_fdb_selection) &&
- MLX5_CAP_ESW(dev1, root_ft_on_other_esw) &&
- MLX5_CAP_ESW(dev0, esw_shared_ingress_acl))
+ struct mlx5_core_dev *dev;
+ int i;
+
+ for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) {
+ dev = ldev->pf[i].dev;
+ if (is_mdev_switchdev_mode(dev) &&
+ mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) &&
+ MLX5_CAP_GEN(dev, lag_native_fdb_selection) &&
+ MLX5_CAP_ESW(dev, root_ft_on_other_esw) &&
+ mlx5_eswitch_get_npeers(dev->priv.eswitch) ==
+ MLX5_CAP_GEN(dev, num_lag_ports) - 1)
+ continue;
+ return false;
+ }
+
+ dev = ldev->pf[MLX5_LAG_P1].dev;
+ if (is_mdev_switchdev_mode(dev) &&
+ mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) &&
+ mlx5_devcom_comp_is_ready(dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS) &&
+ MLX5_CAP_ESW(dev, esw_shared_ingress_acl) &&
+ mlx5_eswitch_get_npeers(dev->priv.eswitch) == MLX5_CAP_GEN(dev, num_lag_ports) - 1)
return true;
return false;
@@ -842,7 +874,6 @@ static bool mlx5_lag_should_disable_lag(struct mlx5_lag *ldev, bool do_bond)
static void mlx5_do_bond(struct mlx5_lag *ldev)
{
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
- struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
struct lag_tracker tracker = { };
bool do_bond, roce_lag;
int err;
@@ -883,20 +914,24 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
for (i = 1; i < ldev->ports; i++)
mlx5_nic_vport_enable_roce(ldev->pf[i].dev);
} else if (shared_fdb) {
+ int i;
+
dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
mlx5_rescan_drivers_locked(dev0);
- err = mlx5_eswitch_reload_reps(dev0->priv.eswitch);
- if (!err)
- err = mlx5_eswitch_reload_reps(dev1->priv.eswitch);
+ for (i = 0; i < ldev->ports; i++) {
+ err = mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
+ if (err)
+ break;
+ }
if (err) {
dev0->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
mlx5_rescan_drivers_locked(dev0);
mlx5_deactivate_lag(ldev);
mlx5_lag_add_devices(ldev);
- mlx5_eswitch_reload_reps(dev0->priv.eswitch);
- mlx5_eswitch_reload_reps(dev1->priv.eswitch);
+ for (i = 0; i < ldev->ports; i++)
+ mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
mlx5_core_err(dev0, "Failed to enable lag\n");
return;
}
@@ -1233,14 +1268,21 @@ recheck:
mlx5_ldev_put(ldev);
}
+bool mlx5_lag_is_supported(struct mlx5_core_dev *dev)
+{
+ if (!MLX5_CAP_GEN(dev, vport_group_manager) ||
+ !MLX5_CAP_GEN(dev, lag_master) ||
+ MLX5_CAP_GEN(dev, num_lag_ports) < 2 ||
+ MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_MAX_PORTS)
+ return false;
+ return true;
+}
+
void mlx5_lag_add_mdev(struct mlx5_core_dev *dev)
{
int err;
- if (!MLX5_CAP_GEN(dev, vport_group_manager) ||
- !MLX5_CAP_GEN(dev, lag_master) ||
- (MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_MAX_PORTS ||
- MLX5_CAP_GEN(dev, num_lag_ports) <= 1))
+ if (!mlx5_lag_is_supported(dev))
return;
recheck:
@@ -1496,26 +1538,37 @@ u8 mlx5_lag_get_num_ports(struct mlx5_core_dev *dev)
}
EXPORT_SYMBOL(mlx5_lag_get_num_ports);
-struct mlx5_core_dev *mlx5_lag_get_peer_mdev(struct mlx5_core_dev *dev)
+struct mlx5_core_dev *mlx5_lag_get_next_peer_mdev(struct mlx5_core_dev *dev, int *i)
{
struct mlx5_core_dev *peer_dev = NULL;
struct mlx5_lag *ldev;
unsigned long flags;
+ int idx;
spin_lock_irqsave(&lag_lock, flags);
ldev = mlx5_lag_dev(dev);
if (!ldev)
goto unlock;
- peer_dev = ldev->pf[MLX5_LAG_P1].dev == dev ?
- ldev->pf[MLX5_LAG_P2].dev :
- ldev->pf[MLX5_LAG_P1].dev;
+ if (*i == ldev->ports)
+ goto unlock;
+ for (idx = *i; idx < ldev->ports; idx++)
+ if (ldev->pf[idx].dev != dev)
+ break;
+
+ if (idx == ldev->ports) {
+ *i = idx;
+ goto unlock;
+ }
+ *i = idx + 1;
+
+ peer_dev = ldev->pf[idx].dev;
unlock:
spin_unlock_irqrestore(&lag_lock, flags);
return peer_dev;
}
-EXPORT_SYMBOL(mlx5_lag_get_peer_mdev);
+EXPORT_SYMBOL(mlx5_lag_get_next_peer_mdev);
int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev,
u64 *values,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
index bc1f1dd3e283..a061b1873e27 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
@@ -74,15 +74,7 @@ struct mlx5_lag {
struct lag_mpesw lag_mpesw;
};
-static inline bool mlx5_is_lag_supported(struct mlx5_core_dev *dev)
-{
- if (!MLX5_CAP_GEN(dev, vport_group_manager) ||
- !MLX5_CAP_GEN(dev, lag_master) ||
- MLX5_CAP_GEN(dev, num_lag_ports) < 2 ||
- MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_MAX_PORTS)
- return false;
- return true;
-}
+bool mlx5_lag_is_supported(struct mlx5_core_dev *dev);
static inline struct mlx5_lag *
mlx5_lag_dev(struct mlx5_core_dev *dev)
@@ -111,7 +103,6 @@ int mlx5_activate_lag(struct mlx5_lag *ldev,
bool shared_fdb);
int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev,
struct net_device *ndev);
-bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev);
char *mlx5_get_str_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags);
void mlx5_infer_tx_enabled(struct lag_tracker *tracker, u8 num_ports,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
index d85a8dfc153d..b1aa494c76ba 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
@@ -7,13 +7,14 @@
#include "lag/mp.h"
#include "mlx5_core.h"
#include "eswitch.h"
-#include "lib/mlx5.h"
+#include "lib/events.h"
static bool __mlx5_lag_is_multipath(struct mlx5_lag *ldev)
{
return ldev->mode == MLX5_LAG_MODE_MULTIPATH;
}
+#define MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS 2
static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev)
{
if (!mlx5_lag_is_ready(ldev))
@@ -22,6 +23,9 @@ static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev)
if (__mlx5_lag_is_active(ldev) && !__mlx5_lag_is_multipath(ldev))
return false;
+ if (ldev->ports > MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS)
+ return false;
+
return mlx5_esw_multipath_prereq(ldev->pf[MLX5_LAG_P1].dev,
ldev->pf[MLX5_LAG_P2].dev);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
index 0c0ef600f643..4bf15391525c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
@@ -6,7 +6,7 @@
#include "lag/lag.h"
#include "eswitch.h"
#include "esw/acl/ofld.h"
-#include "lib/mlx5.h"
+#include "lib/events.h"
static void mlx5_mpesw_metadata_cleanup(struct mlx5_lag *ldev)
{
@@ -65,6 +65,7 @@ err_metadata:
return err;
}
+#define MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS 2
static int enable_mpesw(struct mlx5_lag *ldev)
{
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
@@ -74,6 +75,9 @@ static int enable_mpesw(struct mlx5_lag *ldev)
if (ldev->mode != MLX5_LAG_MODE_NONE)
return -EINVAL;
+ if (ldev->ports > MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS)
+ return -EOPNOTSUPP;
+
if (mlx5_eswitch_mode(dev0) != MLX5_ESWITCH_OFFLOADS ||
!MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table) ||
!MLX5_CAP_GEN(dev0, create_lag_when_not_master_up) ||
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
index d3a3fe4ce670..7d9bbb494d95 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
@@ -574,7 +574,7 @@ static int __mlx5_lag_modify_definers_destinations(struct mlx5_lag *ldev,
for (i = 0; i < ldev->ports; i++) {
for (j = 0; j < ldev->buckets; j++) {
idx = i * ldev->buckets + j;
- if (ldev->v2p_map[i] == ports[i])
+ if (ldev->v2p_map[idx] == ports[idx])
continue;
dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[ports[idx] - 1].dev,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
index 932fbc843c69..377372f0578a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
@@ -93,17 +93,23 @@ static bool mlx5_modify_mtutc_allowed(struct mlx5_core_dev *mdev)
return MLX5_CAP_MCAM_FEATURE(mdev, ptpcyc2realtime_modify);
}
-static bool mlx5_is_mtutc_time_adj_cap(struct mlx5_core_dev *mdev, s64 delta)
+static s32 mlx5_ptp_getmaxphase(struct ptp_clock_info *ptp)
{
- s64 min = MLX5_MTUTC_OPERATION_ADJUST_TIME_MIN;
- s64 max = MLX5_MTUTC_OPERATION_ADJUST_TIME_MAX;
+ struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info);
+ struct mlx5_core_dev *mdev;
- if (MLX5_CAP_MCAM_FEATURE(mdev, mtutc_time_adjustment_extended_range)) {
- min = MLX5_MTUTC_OPERATION_ADJUST_TIME_EXTENDED_MIN;
- max = MLX5_MTUTC_OPERATION_ADJUST_TIME_EXTENDED_MAX;
- }
+ mdev = container_of(clock, struct mlx5_core_dev, clock);
+
+ return MLX5_CAP_MCAM_FEATURE(mdev, mtutc_time_adjustment_extended_range) ?
+ MLX5_MTUTC_OPERATION_ADJUST_TIME_EXTENDED_MAX :
+ MLX5_MTUTC_OPERATION_ADJUST_TIME_MAX;
+}
+
+static bool mlx5_is_mtutc_time_adj_cap(struct mlx5_core_dev *mdev, s64 delta)
+{
+ s64 max = mlx5_ptp_getmaxphase(&mdev->clock.ptp_info);
- if (delta < min || delta > max)
+ if (delta < -max || delta > max)
return false;
return true;
@@ -221,10 +227,15 @@ static void mlx5_timestamp_overflow(struct work_struct *work)
clock = container_of(timer, struct mlx5_clock, timer);
mdev = container_of(clock, struct mlx5_core_dev, clock);
+ if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
+ goto out;
+
write_seqlock_irqsave(&clock->lock, flags);
timecounter_read(&timer->tc);
mlx5_update_clock_info_page(mdev);
write_sequnlock_irqrestore(&clock->lock, flags);
+
+out:
schedule_delayed_work(&timer->overflow_work, timer->overflow_period);
}
@@ -351,14 +362,6 @@ static int mlx5_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
static int mlx5_ptp_adjphase(struct ptp_clock_info *ptp, s32 delta)
{
- struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info);
- struct mlx5_core_dev *mdev;
-
- mdev = container_of(clock, struct mlx5_core_dev, clock);
-
- if (!mlx5_is_mtutc_time_adj_cap(mdev, delta))
- return -ERANGE;
-
return mlx5_ptp_adjtime(ptp, delta);
}
@@ -734,6 +737,7 @@ static const struct ptp_clock_info mlx5_ptp_clock_info = {
.pps = 0,
.adjfine = mlx5_ptp_adjfine,
.adjphase = mlx5_ptp_adjphase,
+ .getmaxphase = mlx5_ptp_getmaxphase,
.adjtime = mlx5_ptp_adjtime,
.gettimex64 = mlx5_ptp_gettimex,
.settime64 = mlx5_ptp_settime,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
index b7d779d08d83..78c94b22bdc0 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
@@ -19,7 +19,7 @@ struct mlx5_devcom_component {
mlx5_devcom_event_handler_t handler;
struct rw_semaphore sem;
- bool paired;
+ bool ready;
};
struct mlx5_devcom_list {
@@ -75,13 +75,14 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev)
if (!mlx5_core_is_pf(dev))
return NULL;
- if (MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_DEVCOM_PORTS_SUPPORTED)
+ if (MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_DEVCOM_PORTS_SUPPORTED)
return NULL;
mlx5_dev_list_lock();
sguid0 = mlx5_query_nic_system_image_guid(dev);
list_for_each_entry(iter, &devcom_list, list) {
- struct mlx5_core_dev *tmp_dev = NULL;
+ /* There is at least one device in iter */
+ struct mlx5_core_dev *tmp_dev;
idx = -1;
for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) {
@@ -193,7 +194,7 @@ void mlx5_devcom_unregister_component(struct mlx5_devcom *devcom,
int mlx5_devcom_send_event(struct mlx5_devcom *devcom,
enum mlx5_devcom_components id,
- int event,
+ int event, int rollback_event,
void *event_data)
{
struct mlx5_devcom_component *comp;
@@ -210,84 +211,134 @@ int mlx5_devcom_send_event(struct mlx5_devcom *devcom,
if (i != devcom->idx && data) {
err = comp->handler(event, data, event_data);
- break;
+ if (err)
+ goto rollback;
}
}
up_write(&comp->sem);
+ return 0;
+
+rollback:
+ while (i--) {
+ void *data = rcu_dereference_protected(comp->device[i].data,
+ lockdep_is_held(&comp->sem));
+
+ if (i != devcom->idx && data)
+ comp->handler(rollback_event, data, event_data);
+ }
+
+ up_write(&comp->sem);
return err;
}
-void mlx5_devcom_set_paired(struct mlx5_devcom *devcom,
- enum mlx5_devcom_components id,
- bool paired)
+void mlx5_devcom_comp_set_ready(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id,
+ bool ready)
{
struct mlx5_devcom_component *comp;
comp = &devcom->priv->components[id];
WARN_ON(!rwsem_is_locked(&comp->sem));
- WRITE_ONCE(comp->paired, paired);
+ WRITE_ONCE(comp->ready, ready);
}
-bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom,
- enum mlx5_devcom_components id)
+bool mlx5_devcom_comp_is_ready(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id)
{
if (IS_ERR_OR_NULL(devcom))
return false;
- return READ_ONCE(devcom->priv->components[id].paired);
+ return READ_ONCE(devcom->priv->components[id].ready);
}
-void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
- enum mlx5_devcom_components id)
+bool mlx5_devcom_for_each_peer_begin(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id)
{
struct mlx5_devcom_component *comp;
- int i;
if (IS_ERR_OR_NULL(devcom))
- return NULL;
+ return false;
comp = &devcom->priv->components[id];
down_read(&comp->sem);
- if (!READ_ONCE(comp->paired)) {
+ if (!READ_ONCE(comp->ready)) {
up_read(&comp->sem);
- return NULL;
+ return false;
}
- for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
- if (i != devcom->idx)
- break;
+ return true;
+}
+
+void mlx5_devcom_for_each_peer_end(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id)
+{
+ struct mlx5_devcom_component *comp = &devcom->priv->components[id];
- return rcu_dereference_protected(comp->device[i].data, lockdep_is_held(&comp->sem));
+ up_read(&comp->sem);
}
-void *mlx5_devcom_get_peer_data_rcu(struct mlx5_devcom *devcom, enum mlx5_devcom_components id)
+void *mlx5_devcom_get_next_peer_data(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id,
+ int *i)
{
struct mlx5_devcom_component *comp;
- int i;
+ void *ret;
+ int idx;
- if (IS_ERR_OR_NULL(devcom))
- return NULL;
+ comp = &devcom->priv->components[id];
- for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
- if (i != devcom->idx)
- break;
+ if (*i == MLX5_DEVCOM_PORTS_SUPPORTED)
+ return NULL;
+ for (idx = *i; idx < MLX5_DEVCOM_PORTS_SUPPORTED; idx++) {
+ if (idx != devcom->idx) {
+ ret = rcu_dereference_protected(comp->device[idx].data,
+ lockdep_is_held(&comp->sem));
+ if (ret)
+ break;
+ }
+ }
- comp = &devcom->priv->components[id];
- /* This can change concurrently, however 'data' pointer will remain
- * valid for the duration of RCU read section.
- */
- if (!READ_ONCE(comp->paired))
+ if (idx == MLX5_DEVCOM_PORTS_SUPPORTED) {
+ *i = idx;
return NULL;
+ }
+ *i = idx + 1;
- return rcu_dereference(comp->device[i].data);
+ return ret;
}
-void mlx5_devcom_release_peer_data(struct mlx5_devcom *devcom,
- enum mlx5_devcom_components id)
+void *mlx5_devcom_get_next_peer_data_rcu(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id,
+ int *i)
{
- struct mlx5_devcom_component *comp = &devcom->priv->components[id];
+ struct mlx5_devcom_component *comp;
+ void *ret;
+ int idx;
- up_read(&comp->sem);
+ comp = &devcom->priv->components[id];
+
+ if (*i == MLX5_DEVCOM_PORTS_SUPPORTED)
+ return NULL;
+ for (idx = *i; idx < MLX5_DEVCOM_PORTS_SUPPORTED; idx++) {
+ if (idx != devcom->idx) {
+ /* This can change concurrently, however 'data' pointer will remain
+ * valid for the duration of RCU read section.
+ */
+ if (!READ_ONCE(comp->ready))
+ return NULL;
+ ret = rcu_dereference(comp->device[idx].data);
+ if (ret)
+ break;
+ }
+ }
+
+ if (idx == MLX5_DEVCOM_PORTS_SUPPORTED) {
+ *i = idx;
+ return NULL;
+ }
+ *i = idx + 1;
+
+ return ret;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
index 9a496f4722da..d953a01b8eaa 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
@@ -6,7 +6,7 @@
#include <linux/mlx5/driver.h>
-#define MLX5_DEVCOM_PORTS_SUPPORTED 2
+#define MLX5_DEVCOM_PORTS_SUPPORTED 4
enum mlx5_devcom_components {
MLX5_DEVCOM_ESW_OFFLOADS,
@@ -30,20 +30,33 @@ void mlx5_devcom_unregister_component(struct mlx5_devcom *devcom,
int mlx5_devcom_send_event(struct mlx5_devcom *devcom,
enum mlx5_devcom_components id,
- int event,
+ int event, int rollback_event,
void *event_data);
-void mlx5_devcom_set_paired(struct mlx5_devcom *devcom,
- enum mlx5_devcom_components id,
- bool paired);
-bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom,
- enum mlx5_devcom_components id);
+void mlx5_devcom_comp_set_ready(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id,
+ bool ready);
+bool mlx5_devcom_comp_is_ready(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id);
-void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
- enum mlx5_devcom_components id);
-void *mlx5_devcom_get_peer_data_rcu(struct mlx5_devcom *devcom, enum mlx5_devcom_components id);
-void mlx5_devcom_release_peer_data(struct mlx5_devcom *devcom,
+bool mlx5_devcom_for_each_peer_begin(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id);
+void mlx5_devcom_for_each_peer_end(struct mlx5_devcom *devcom,
enum mlx5_devcom_components id);
+void *mlx5_devcom_get_next_peer_data(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id, int *i);
-#endif
+#define mlx5_devcom_for_each_peer_entry(devcom, id, data, i) \
+ for (i = 0, data = mlx5_devcom_get_next_peer_data(devcom, id, &i); \
+ data; \
+ data = mlx5_devcom_get_next_peer_data(devcom, id, &i))
+
+void *mlx5_devcom_get_next_peer_data_rcu(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id, int *i);
+#define mlx5_devcom_for_each_peer_entry_rcu(devcom, id, data, i) \
+ for (i = 0, data = mlx5_devcom_get_next_peer_data_rcu(devcom, id, &i); \
+ data; \
+ data = mlx5_devcom_get_next_peer_data_rcu(devcom, id, &i))
+
+#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/events.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/events.h
new file mode 100644
index 000000000000..a0f7faea317b
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/events.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
+
+#ifndef __LIB_EVENTS_H__
+#define __LIB_EVENTS_H__
+
+#include "mlx5_core.h"
+
+#define PORT_MODULE_EVENT_MODULE_STATUS_MASK 0xF
+#define PORT_MODULE_EVENT_ERROR_TYPE_MASK 0xF
+
+enum port_module_event_status_type {
+ MLX5_MODULE_STATUS_PLUGGED = 0x1,
+ MLX5_MODULE_STATUS_UNPLUGGED = 0x2,
+ MLX5_MODULE_STATUS_ERROR = 0x3,
+ MLX5_MODULE_STATUS_DISABLED = 0x4,
+ MLX5_MODULE_STATUS_NUM,
+};
+
+enum port_module_event_error_type {
+ MLX5_MODULE_EVENT_ERROR_POWER_BUDGET_EXCEEDED = 0x0,
+ MLX5_MODULE_EVENT_ERROR_LONG_RANGE_FOR_NON_MLNX = 0x1,
+ MLX5_MODULE_EVENT_ERROR_BUS_STUCK = 0x2,
+ MLX5_MODULE_EVENT_ERROR_NO_EEPROM_RETRY_TIMEOUT = 0x3,
+ MLX5_MODULE_EVENT_ERROR_ENFORCE_PART_NUMBER_LIST = 0x4,
+ MLX5_MODULE_EVENT_ERROR_UNKNOWN_IDENTIFIER = 0x5,
+ MLX5_MODULE_EVENT_ERROR_HIGH_TEMPERATURE = 0x6,
+ MLX5_MODULE_EVENT_ERROR_BAD_CABLE = 0x7,
+ MLX5_MODULE_EVENT_ERROR_PCIE_POWER_SLOT_EXCEEDED = 0xc,
+ MLX5_MODULE_EVENT_ERROR_NUM,
+};
+
+struct mlx5_pme_stats {
+ u64 status_counters[MLX5_MODULE_STATUS_NUM];
+ u64 error_counters[MLX5_MODULE_EVENT_ERROR_NUM];
+};
+
+void mlx5_get_pme_stats(struct mlx5_core_dev *dev, struct mlx5_pme_stats *stats);
+int mlx5_notifier_call_chain(struct mlx5_events *events, unsigned int event, void *data);
+#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c
index db9df9798ffa..a80ecb672f33 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c
@@ -178,7 +178,7 @@ mlx5_chains_create_table(struct mlx5_fs_chains *chains,
if (!mlx5_chains_ignore_flow_level_supported(chains) ||
(chain == 0 && prio == 1 && level == 0)) {
ft_attr.level = chains->fs_base_level;
- ft_attr.prio = chains->fs_base_prio;
+ ft_attr.prio = chains->fs_base_prio + prio - 1;
ns = (chains->ns == MLX5_FLOW_NAMESPACE_FDB) ?
mlx5_get_fdb_sub_ns(chains->dev, chain) :
mlx5_get_flow_namespace(chains->dev, chains->ns);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h
index ccf12f7db6f0..2b5826a785c4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h
@@ -45,40 +45,6 @@ int mlx5_crdump_enable(struct mlx5_core_dev *dev);
void mlx5_crdump_disable(struct mlx5_core_dev *dev);
int mlx5_crdump_collect(struct mlx5_core_dev *dev, u32 *cr_data);
-/* TODO move to lib/events.h */
-
-#define PORT_MODULE_EVENT_MODULE_STATUS_MASK 0xF
-#define PORT_MODULE_EVENT_ERROR_TYPE_MASK 0xF
-
-enum port_module_event_status_type {
- MLX5_MODULE_STATUS_PLUGGED = 0x1,
- MLX5_MODULE_STATUS_UNPLUGGED = 0x2,
- MLX5_MODULE_STATUS_ERROR = 0x3,
- MLX5_MODULE_STATUS_DISABLED = 0x4,
- MLX5_MODULE_STATUS_NUM,
-};
-
-enum port_module_event_error_type {
- MLX5_MODULE_EVENT_ERROR_POWER_BUDGET_EXCEEDED = 0x0,
- MLX5_MODULE_EVENT_ERROR_LONG_RANGE_FOR_NON_MLNX = 0x1,
- MLX5_MODULE_EVENT_ERROR_BUS_STUCK = 0x2,
- MLX5_MODULE_EVENT_ERROR_NO_EEPROM_RETRY_TIMEOUT = 0x3,
- MLX5_MODULE_EVENT_ERROR_ENFORCE_PART_NUMBER_LIST = 0x4,
- MLX5_MODULE_EVENT_ERROR_UNKNOWN_IDENTIFIER = 0x5,
- MLX5_MODULE_EVENT_ERROR_HIGH_TEMPERATURE = 0x6,
- MLX5_MODULE_EVENT_ERROR_BAD_CABLE = 0x7,
- MLX5_MODULE_EVENT_ERROR_PCIE_POWER_SLOT_EXCEEDED = 0xc,
- MLX5_MODULE_EVENT_ERROR_NUM,
-};
-
-struct mlx5_pme_stats {
- u64 status_counters[MLX5_MODULE_STATUS_NUM];
- u64 error_counters[MLX5_MODULE_EVENT_ERROR_NUM];
-};
-
-void mlx5_get_pme_stats(struct mlx5_core_dev *dev, struct mlx5_pme_stats *stats);
-int mlx5_notifier_call_chain(struct mlx5_events *events, unsigned int event, void *data);
-
static inline struct net *mlx5_core_net(struct mlx5_core_dev *dev)
{
return devlink_net(priv_to_devlink(dev));
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c
index 8ff16318e32d..4450091e181a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c
@@ -99,7 +99,7 @@ int mlx5_mpfs_init(struct mlx5_core_dev *dev)
int l2table_size = 1 << MLX5_CAP_GEN(dev, log_max_l2_table);
struct mlx5_mpfs *mpfs;
- if (!MLX5_ESWITCH_MANAGER(dev))
+ if (!MLX5_ESWITCH_MANAGER(dev) || l2table_size == 1)
return 0;
mpfs = kzalloc(sizeof(*mpfs), GFP_KERNEL);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c
index 696e45e2bd06..e223e0e46433 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c
@@ -24,7 +24,8 @@ static const u32 tout_def_sw_val[MAX_TIMEOUT_TYPES] = {
[MLX5_TO_TEARDOWN_MS] = 3000,
[MLX5_TO_FSM_REACTIVATE_MS] = 5000,
[MLX5_TO_RECLAIM_PAGES_MS] = 5000,
- [MLX5_TO_RECLAIM_VFS_PAGES_MS] = 120000
+ [MLX5_TO_RECLAIM_VFS_PAGES_MS] = 120000,
+ [MLX5_TO_RESET_UNLOAD_MS] = 300000
};
static void tout_set(struct mlx5_core_dev *dev, u64 val, enum mlx5_timeouts_types type)
@@ -118,7 +119,8 @@ u64 _mlx5_tout_ms(struct mlx5_core_dev *dev, enum mlx5_timeouts_types type)
#define MLX5_TIMEOUT_FILL(fld, reg_out, dev, to_type, to_extra) \
({ \
u64 fw_to = MLX5_TIMEOUT_QUERY(fld, reg_out); \
- tout_set(dev, fw_to + (to_extra), to_type); \
+ if (fw_to) \
+ tout_set(dev, fw_to + (to_extra), to_type); \
fw_to; \
})
@@ -146,6 +148,7 @@ static int tout_query_dtor(struct mlx5_core_dev *dev)
MLX5_TIMEOUT_FILL(fsm_reactivate_to, out, dev, MLX5_TO_FSM_REACTIVATE_MS, 0);
MLX5_TIMEOUT_FILL(reclaim_pages_to, out, dev, MLX5_TO_RECLAIM_PAGES_MS, 0);
MLX5_TIMEOUT_FILL(reclaim_vfs_pages_to, out, dev, MLX5_TO_RECLAIM_VFS_PAGES_MS, 0);
+ MLX5_TIMEOUT_FILL(reset_unload_to, out, dev, MLX5_TO_RESET_UNLOAD_MS, 0);
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h
index bc9e9aeda847..99e0a05526fe 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h
@@ -26,6 +26,7 @@ enum mlx5_timeouts_types {
MLX5_TO_FSM_REACTIVATE_MS,
MLX5_TO_RECLAIM_PAGES_MS,
MLX5_TO_RECLAIM_VFS_PAGES_MS,
+ MLX5_TO_RESET_UNLOAD_MS,
MAX_TIMEOUT_TYPES
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index d6ee016deae1..72ae560a1c68 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -619,6 +619,9 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx)
if (MLX5_CAP_GEN_MAX(dev, pci_sync_for_fw_update_event))
MLX5_SET(cmd_hca_cap, set_hca_cap, pci_sync_for_fw_update_event, 1);
+ if (MLX5_CAP_GEN_MAX(dev, pci_sync_for_fw_update_with_driver_unload))
+ MLX5_SET(cmd_hca_cap, set_hca_cap,
+ pci_sync_for_fw_update_with_driver_unload, 1);
if (MLX5_CAP_GEN_MAX(dev, num_vhca_ports))
MLX5_SET(cmd_hca_cap,
@@ -1118,7 +1121,7 @@ static void mlx5_cleanup_once(struct mlx5_core_dev *dev)
mlx5_devcom_unregister_device(dev->priv.devcom);
}
-static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout)
+static int mlx5_function_enable(struct mlx5_core_dev *dev, bool boot, u64 timeout)
{
int err;
@@ -1183,28 +1186,56 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout
goto reclaim_boot_pages;
}
+ return 0;
+
+reclaim_boot_pages:
+ mlx5_reclaim_startup_pages(dev);
+err_disable_hca:
+ mlx5_core_disable_hca(dev, 0);
+stop_health_poll:
+ mlx5_stop_health_poll(dev, boot);
+err_cmd_cleanup:
+ mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN);
+ mlx5_cmd_cleanup(dev);
+
+ return err;
+}
+
+static void mlx5_function_disable(struct mlx5_core_dev *dev, bool boot)
+{
+ mlx5_reclaim_startup_pages(dev);
+ mlx5_core_disable_hca(dev, 0);
+ mlx5_stop_health_poll(dev, boot);
+ mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN);
+ mlx5_cmd_cleanup(dev);
+}
+
+static int mlx5_function_open(struct mlx5_core_dev *dev)
+{
+ int err;
+
err = set_hca_ctrl(dev);
if (err) {
mlx5_core_err(dev, "set_hca_ctrl failed\n");
- goto reclaim_boot_pages;
+ return err;
}
err = set_hca_cap(dev);
if (err) {
mlx5_core_err(dev, "set_hca_cap failed\n");
- goto reclaim_boot_pages;
+ return err;
}
err = mlx5_satisfy_startup_pages(dev, 0);
if (err) {
mlx5_core_err(dev, "failed to allocate init pages\n");
- goto reclaim_boot_pages;
+ return err;
}
err = mlx5_cmd_init_hca(dev, sw_owner_id);
if (err) {
mlx5_core_err(dev, "init hca failed\n");
- goto reclaim_boot_pages;
+ return err;
}
mlx5_set_driver_version(dev);
@@ -1212,26 +1243,13 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout
err = mlx5_query_hca_caps(dev);
if (err) {
mlx5_core_err(dev, "query hca failed\n");
- goto reclaim_boot_pages;
+ return err;
}
mlx5_start_health_fw_log_up(dev);
-
return 0;
-
-reclaim_boot_pages:
- mlx5_reclaim_startup_pages(dev);
-err_disable_hca:
- mlx5_core_disable_hca(dev, 0);
-stop_health_poll:
- mlx5_stop_health_poll(dev, boot);
-err_cmd_cleanup:
- mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN);
- mlx5_cmd_cleanup(dev);
-
- return err;
}
-static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot)
+static int mlx5_function_close(struct mlx5_core_dev *dev)
{
int err;
@@ -1240,15 +1258,33 @@ static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot)
mlx5_core_err(dev, "tear_down_hca failed, skip cleanup\n");
return err;
}
- mlx5_reclaim_startup_pages(dev);
- mlx5_core_disable_hca(dev, 0);
- mlx5_stop_health_poll(dev, boot);
- mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN);
- mlx5_cmd_cleanup(dev);
return 0;
}
+static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout)
+{
+ int err;
+
+ err = mlx5_function_enable(dev, boot, timeout);
+ if (err)
+ return err;
+
+ err = mlx5_function_open(dev);
+ if (err)
+ mlx5_function_disable(dev, boot);
+ return err;
+}
+
+static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot)
+{
+ int err = mlx5_function_close(dev);
+
+ if (!err)
+ mlx5_function_disable(dev, boot);
+ return err;
+}
+
static int mlx5_load(struct mlx5_core_dev *dev)
{
int err;
@@ -1391,12 +1427,11 @@ static void mlx5_unload(struct mlx5_core_dev *dev)
mlx5_put_uars_page(dev, dev->priv.uar);
}
-int mlx5_init_one(struct mlx5_core_dev *dev)
+int mlx5_init_one_devl_locked(struct mlx5_core_dev *dev)
{
- struct devlink *devlink = priv_to_devlink(dev);
+ bool light_probe = mlx5_dev_is_lightweight(dev);
int err = 0;
- devl_lock(devlink);
mutex_lock(&dev->intf_state_mutex);
dev->state = MLX5_DEVICE_STATE_UP;
@@ -1410,9 +1445,14 @@ int mlx5_init_one(struct mlx5_core_dev *dev)
goto function_teardown;
}
- err = mlx5_devlink_params_register(priv_to_devlink(dev));
- if (err)
- goto err_devlink_params_reg;
+ /* In case of light_probe, mlx5_devlink is already registered.
+ * Hence, don't register devlink again.
+ */
+ if (!light_probe) {
+ err = mlx5_devlink_params_register(priv_to_devlink(dev));
+ if (err)
+ goto err_devlink_params_reg;
+ }
err = mlx5_load(dev);
if (err)
@@ -1425,14 +1465,14 @@ int mlx5_init_one(struct mlx5_core_dev *dev)
goto err_register;
mutex_unlock(&dev->intf_state_mutex);
- devl_unlock(devlink);
return 0;
err_register:
clear_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state);
mlx5_unload(dev);
err_load:
- mlx5_devlink_params_unregister(priv_to_devlink(dev));
+ if (!light_probe)
+ mlx5_devlink_params_unregister(priv_to_devlink(dev));
err_devlink_params_reg:
mlx5_cleanup_once(dev);
function_teardown:
@@ -1440,6 +1480,16 @@ function_teardown:
err_function:
dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
mutex_unlock(&dev->intf_state_mutex);
+ return err;
+}
+
+int mlx5_init_one(struct mlx5_core_dev *dev)
+{
+ struct devlink *devlink = priv_to_devlink(dev);
+ int err;
+
+ devl_lock(devlink);
+ err = mlx5_init_one_devl_locked(dev);
devl_unlock(devlink);
return err;
}
@@ -1456,6 +1506,7 @@ void mlx5_uninit_one(struct mlx5_core_dev *dev)
if (!test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) {
mlx5_core_warn(dev, "%s: interface is down, NOP\n",
__func__);
+ mlx5_devlink_params_unregister(priv_to_devlink(dev));
mlx5_cleanup_once(dev);
goto out;
}
@@ -1557,6 +1608,100 @@ void mlx5_unload_one(struct mlx5_core_dev *dev, bool suspend)
devl_unlock(devlink);
}
+/* In case of light probe, we don't need a full query of hca_caps, but only the bellow caps.
+ * A full query of hca_caps will be done when the device will reload.
+ */
+static int mlx5_query_hca_caps_light(struct mlx5_core_dev *dev)
+{
+ int err;
+
+ err = mlx5_core_get_caps(dev, MLX5_CAP_GENERAL);
+ if (err)
+ return err;
+
+ if (MLX5_CAP_GEN(dev, eth_net_offloads)) {
+ err = mlx5_core_get_caps(dev, MLX5_CAP_ETHERNET_OFFLOADS);
+ if (err)
+ return err;
+ }
+
+ if (MLX5_CAP_GEN(dev, nic_flow_table) ||
+ MLX5_CAP_GEN(dev, ipoib_enhanced_offloads)) {
+ err = mlx5_core_get_caps(dev, MLX5_CAP_FLOW_TABLE);
+ if (err)
+ return err;
+ }
+
+ if (MLX5_CAP_GEN_64(dev, general_obj_types) &
+ MLX5_GENERAL_OBJ_TYPES_CAP_VIRTIO_NET_Q) {
+ err = mlx5_core_get_caps(dev, MLX5_CAP_VDPA_EMULATION);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+int mlx5_init_one_light(struct mlx5_core_dev *dev)
+{
+ struct devlink *devlink = priv_to_devlink(dev);
+ int err;
+
+ dev->state = MLX5_DEVICE_STATE_UP;
+ err = mlx5_function_enable(dev, true, mlx5_tout_ms(dev, FW_PRE_INIT_TIMEOUT));
+ if (err) {
+ mlx5_core_warn(dev, "mlx5_function_enable err=%d\n", err);
+ goto out;
+ }
+
+ err = mlx5_query_hca_caps_light(dev);
+ if (err) {
+ mlx5_core_warn(dev, "mlx5_query_hca_caps_light err=%d\n", err);
+ goto query_hca_caps_err;
+ }
+
+ devl_lock(devlink);
+ err = mlx5_devlink_params_register(priv_to_devlink(dev));
+ devl_unlock(devlink);
+ if (err) {
+ mlx5_core_warn(dev, "mlx5_devlink_param_reg err = %d\n", err);
+ goto query_hca_caps_err;
+ }
+
+ return 0;
+
+query_hca_caps_err:
+ mlx5_function_disable(dev, true);
+out:
+ dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
+ return err;
+}
+
+void mlx5_uninit_one_light(struct mlx5_core_dev *dev)
+{
+ struct devlink *devlink = priv_to_devlink(dev);
+
+ devl_lock(devlink);
+ mlx5_devlink_params_unregister(priv_to_devlink(dev));
+ devl_unlock(devlink);
+ if (dev->state != MLX5_DEVICE_STATE_UP)
+ return;
+ mlx5_function_disable(dev, true);
+}
+
+/* xxx_light() function are used in order to configure the device without full
+ * init (light init). e.g.: There isn't a point in reload a device to light state.
+ * Hence, mlx5_load_one_light() isn't needed.
+ */
+
+void mlx5_unload_one_light(struct mlx5_core_dev *dev)
+{
+ if (dev->state != MLX5_DEVICE_STATE_UP)
+ return;
+ mlx5_function_disable(dev, false);
+ dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
+}
+
static const int types[] = {
MLX5_CAP_GENERAL,
MLX5_CAP_GENERAL_2,
@@ -1809,7 +1954,7 @@ static void remove_one(struct pci_dev *pdev)
mlx5_drain_fw_reset(dev);
mlx5_drain_health_wq(dev);
devlink_unregister(devlink);
- mlx5_sriov_disable(pdev);
+ mlx5_sriov_disable(pdev, false);
mlx5_thermal_uninit(dev);
mlx5_crdump_disable(dev);
mlx5_uninit_one(dev);
@@ -1844,7 +1989,7 @@ static pci_ers_result_t mlx5_pci_err_detected(struct pci_dev *pdev,
mlx5_enter_error_state(dev, false);
mlx5_error_sw_reset(dev);
- mlx5_unload_one(dev, true);
+ mlx5_unload_one(dev, false);
mlx5_drain_health_wq(dev);
mlx5_pci_disable_device(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
index 229520405d4a..682d3dc00dd1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
@@ -195,7 +195,7 @@ void mlx5_sriov_cleanup(struct mlx5_core_dev *dev);
int mlx5_sriov_attach(struct mlx5_core_dev *dev);
void mlx5_sriov_detach(struct mlx5_core_dev *dev);
int mlx5_core_sriov_configure(struct pci_dev *dev, int num_vfs);
-void mlx5_sriov_disable(struct pci_dev *pdev);
+void mlx5_sriov_disable(struct pci_dev *pdev, bool num_vf_change);
int mlx5_core_sriov_set_msix_vec_count(struct pci_dev *vf, int msix_vec_count);
int mlx5_core_enable_hca(struct mlx5_core_dev *dev, u16 func_id);
int mlx5_core_disable_hca(struct mlx5_core_dev *dev, u16 func_id);
@@ -240,11 +240,14 @@ int mlx5_attach_device(struct mlx5_core_dev *dev);
void mlx5_detach_device(struct mlx5_core_dev *dev, bool suspend);
int mlx5_register_device(struct mlx5_core_dev *dev);
void mlx5_unregister_device(struct mlx5_core_dev *dev);
+void mlx5_dev_set_lightweight(struct mlx5_core_dev *dev);
+bool mlx5_dev_is_lightweight(struct mlx5_core_dev *dev);
struct mlx5_core_dev *mlx5_get_next_phys_dev_lag(struct mlx5_core_dev *dev);
void mlx5_dev_list_lock(void);
void mlx5_dev_list_unlock(void);
int mlx5_dev_list_trylock(void);
+void mlx5_fw_reporters_create(struct mlx5_core_dev *dev);
int mlx5_query_mtpps(struct mlx5_core_dev *dev, u32 *mtpps, u32 mtpps_size);
int mlx5_set_mtpps(struct mlx5_core_dev *mdev, u32 *mtpps, u32 mtpps_size);
int mlx5_query_mtppse(struct mlx5_core_dev *mdev, u8 pin, u8 *arm, u8 *mode);
@@ -307,16 +310,20 @@ static inline bool mlx5_core_is_sf(const struct mlx5_core_dev *dev)
int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx);
void mlx5_mdev_uninit(struct mlx5_core_dev *dev);
int mlx5_init_one(struct mlx5_core_dev *dev);
+int mlx5_init_one_devl_locked(struct mlx5_core_dev *dev);
void mlx5_uninit_one(struct mlx5_core_dev *dev);
void mlx5_unload_one(struct mlx5_core_dev *dev, bool suspend);
void mlx5_unload_one_devl_locked(struct mlx5_core_dev *dev, bool suspend);
int mlx5_load_one(struct mlx5_core_dev *dev, bool recovery);
int mlx5_load_one_devl_locked(struct mlx5_core_dev *dev, bool recovery);
+int mlx5_init_one_light(struct mlx5_core_dev *dev);
+void mlx5_uninit_one_light(struct mlx5_core_dev *dev);
+void mlx5_unload_one_light(struct mlx5_core_dev *dev);
-int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap, u16 function_id,
+int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap, u16 vport,
u16 opmod);
-#define mlx5_vport_get_other_func_general_cap(dev, fid, out) \
- mlx5_vport_get_other_func_cap(dev, fid, out, MLX5_CAP_GENERAL)
+#define mlx5_vport_get_other_func_general_cap(dev, vport, out) \
+ mlx5_vport_get_other_func_cap(dev, vport, out, MLX5_CAP_GENERAL)
void mlx5_events_work_enqueue(struct mlx5_core_dev *dev, struct work_struct *work);
static inline u32 mlx5_sriov_get_vf_total_msix(struct pci_dev *pdev)
@@ -331,4 +338,31 @@ bool mlx5_rdma_supported(struct mlx5_core_dev *dev);
bool mlx5_vnet_supported(struct mlx5_core_dev *dev);
bool mlx5_same_hw_devs(struct mlx5_core_dev *dev, struct mlx5_core_dev *peer_dev);
+static inline u16 mlx5_core_ec_vf_vport_base(const struct mlx5_core_dev *dev)
+{
+ return MLX5_CAP_GEN_2(dev, ec_vf_vport_base);
+}
+
+static inline u16 mlx5_core_ec_sriov_enabled(const struct mlx5_core_dev *dev)
+{
+ return mlx5_core_is_ecpf(dev) && mlx5_core_ec_vf_vport_base(dev);
+}
+
+static inline bool mlx5_core_is_ec_vf_vport(const struct mlx5_core_dev *dev, u16 vport_num)
+{
+ int base_vport = mlx5_core_ec_vf_vport_base(dev);
+ int max_vport = base_vport + mlx5_core_max_ec_vfs(dev);
+
+ if (!mlx5_core_ec_sriov_enabled(dev))
+ return false;
+
+ return (vport_num >= base_vport && vport_num < max_vport);
+}
+
+static inline int mlx5_vport_to_func_id(const struct mlx5_core_dev *dev, u16 vport, bool ec_vf_func)
+{
+ return ec_vf_func ? vport - mlx5_core_ec_vf_vport_base(dev) + 1
+ : vport;
+}
+
#endif /* __MLX5_CORE_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
index 95dc67fb3001..dcf58efac159 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
@@ -79,7 +79,13 @@ static u16 func_id_to_type(struct mlx5_core_dev *dev, u16 func_id, bool ec_funct
if (!func_id)
return mlx5_core_is_ecpf(dev) && !ec_function ? MLX5_HOST_PF : MLX5_PF;
- return func_id <= mlx5_core_max_vfs(dev) ? MLX5_VF : MLX5_SF;
+ if (func_id <= max(mlx5_core_max_vfs(dev), mlx5_core_max_ec_vfs(dev))) {
+ if (ec_function)
+ return MLX5_EC_VF;
+ else
+ return MLX5_VF;
+ }
+ return MLX5_SF;
}
static u32 mlx5_get_ec_function(u32 function)
@@ -730,6 +736,9 @@ int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev)
WARN(dev->priv.page_counters[MLX5_HOST_PF],
"External host PF FW pages counter is %d after reclaiming all pages\n",
dev->priv.page_counters[MLX5_HOST_PF]);
+ WARN(dev->priv.page_counters[MLX5_EC_VF],
+ "EC VFs FW pages counter is %d after reclaiming all pages\n",
+ dev->priv.page_counters[MLX5_EC_VF]);
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
index 98412bd5a696..cba2a4afb5fd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
@@ -41,6 +41,15 @@ struct mlx5_irq_table {
struct mlx5_irq_pool *sf_comp_pool;
};
+static int mlx5_core_func_to_vport(const struct mlx5_core_dev *dev,
+ int func,
+ bool ec_vf_func)
+{
+ if (!ec_vf_func)
+ return func;
+ return mlx5_core_ec_vf_vport_base(dev) + func - 1;
+}
+
/**
* mlx5_get_default_msix_vec_count - Get the default number of MSI-X vectors
* to be ssigned to each VF.
@@ -79,6 +88,8 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id,
int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in);
void *hca_cap = NULL, *query_cap = NULL, *cap;
int num_vf_msix, min_msix, max_msix;
+ bool ec_vf_function;
+ int vport;
int ret;
num_vf_msix = MLX5_CAP_GEN_MAX(dev, num_total_dynamic_vf_msix);
@@ -104,7 +115,9 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id,
goto out;
}
- ret = mlx5_vport_get_other_func_general_cap(dev, function_id, query_cap);
+ ec_vf_function = mlx5_core_ec_sriov_enabled(dev);
+ vport = mlx5_core_func_to_vport(dev, function_id, ec_vf_function);
+ ret = mlx5_vport_get_other_func_general_cap(dev, vport, query_cap);
if (ret)
goto out;
@@ -115,6 +128,7 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id,
MLX5_SET(set_hca_cap_in, hca_cap, opcode, MLX5_CMD_OP_SET_HCA_CAP);
MLX5_SET(set_hca_cap_in, hca_cap, other_function, 1);
+ MLX5_SET(set_hca_cap_in, hca_cap, ec_vf_function, ec_vf_function);
MLX5_SET(set_hca_cap_in, hca_cap, function_id, function_id);
MLX5_SET(set_hca_cap_in, hca_cap, op_mod,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/rdma.c b/drivers/net/ethernet/mellanox/mlx5/core/rdma.c
index 540cf05f6373..a42f6cd99b74 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/rdma.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/rdma.c
@@ -30,9 +30,8 @@ static int mlx5_rdma_enable_roce_steering(struct mlx5_core_dev *dev)
struct mlx5_flow_spec *spec;
struct mlx5_flow_table *ft;
struct mlx5_flow_group *fg;
- void *match_criteria;
+ struct mlx5_eswitch *esw;
u32 *flow_group_in;
- void *misc;
int err;
if (!(MLX5_CAP_FLOWTABLE_RDMA_RX(dev, ft_support) &&
@@ -63,12 +62,8 @@ static int mlx5_rdma_enable_roce_steering(struct mlx5_core_dev *dev)
goto free;
}
- MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
- MLX5_MATCH_MISC_PARAMETERS);
- match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in,
- match_criteria);
- MLX5_SET_TO_ONES(fte_match_param, match_criteria,
- misc_parameters.source_port);
+ esw = dev->priv.eswitch;
+ mlx5_esw_set_flow_group_source_port(esw, flow_group_in, 0);
fg = mlx5_create_flow_group(ft, flow_group_in);
if (IS_ERR(fg)) {
@@ -77,14 +72,7 @@ static int mlx5_rdma_enable_roce_steering(struct mlx5_core_dev *dev)
goto destroy_flow_table;
}
- spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
- misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
- misc_parameters);
- MLX5_SET(fte_match_set_misc, misc, source_port,
- dev->priv.eswitch->manager_vport);
- misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
- misc_parameters);
- MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
+ mlx5_esw_set_spec_source_port(esw, esw->manager_vport, spec);
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
flow_rule = mlx5_add_flow_rules(ft, spec, &flow_act, NULL, 0);
@@ -115,7 +103,7 @@ free:
static void mlx5_rdma_del_roce_addr(struct mlx5_core_dev *dev)
{
- mlx5_core_roce_gid_set(dev, 0, 0, 0,
+ mlx5_core_roce_gid_set(dev, 0, MLX5_ROCE_VERSION_2, 0,
NULL, NULL, false, 0, 1);
}
@@ -135,7 +123,7 @@ static int mlx5_rdma_add_roce_addr(struct mlx5_core_dev *dev)
mlx5_rdma_make_default_gid(dev, &gid);
return mlx5_core_roce_gid_set(dev, 0,
- MLX5_ROCE_VERSION_1,
+ MLX5_ROCE_VERSION_2,
0, gid.raw, mac,
false, 0, 1);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
index 0692363cf80e..8fe82f1191bb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
@@ -3,6 +3,7 @@
#include <linux/mlx5/driver.h>
#include <linux/mlx5/device.h>
+#include <linux/mlx5/eswitch.h>
#include "mlx5_core.h"
#include "dev.h"
#include "devlink.h"
@@ -28,6 +29,10 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia
mdev->priv.adev_idx = adev->id;
sf_dev->mdev = mdev;
+ /* Only local SFs do light probe */
+ if (MLX5_ESWITCH_MANAGER(sf_dev->parent_mdev))
+ mlx5_dev_set_lightweight(mdev);
+
err = mlx5_mdev_init(mdev, MLX5_SF_PROF);
if (err) {
mlx5_core_warn(mdev, "mlx5_mdev_init on err=%d\n", err);
@@ -41,7 +46,10 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia
goto remap_err;
}
- err = mlx5_init_one(mdev);
+ if (MLX5_ESWITCH_MANAGER(sf_dev->parent_mdev))
+ err = mlx5_init_one_light(mdev);
+ else
+ err = mlx5_init_one(mdev);
if (err) {
mlx5_core_warn(mdev, "mlx5_init_one err=%d\n", err);
goto init_one_err;
@@ -65,7 +73,10 @@ static void mlx5_sf_dev_remove(struct auxiliary_device *adev)
mlx5_drain_health_wq(sf_dev->mdev);
devlink_unregister(devlink);
- mlx5_uninit_one(sf_dev->mdev);
+ if (mlx5_dev_is_lightweight(sf_dev->mdev))
+ mlx5_uninit_one_light(sf_dev->mdev);
+ else
+ mlx5_uninit_one(sf_dev->mdev);
iounmap(sf_dev->mdev->iseg);
mlx5_mdev_uninit(sf_dev->mdev);
mlx5_devlink_free(devlink);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
index 7d955a4d9f14..6a3fa30b2bf2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
@@ -28,7 +28,6 @@ struct mlx5_sf_table {
struct mutex sf_state_lock; /* Serializes sf state among user cmds & vhca event handler. */
struct notifier_block esw_nb;
struct notifier_block vhca_nb;
- u8 ecpu: 1;
};
static struct mlx5_sf *
@@ -283,7 +282,7 @@ out:
static int mlx5_sf_add(struct mlx5_core_dev *dev, struct mlx5_sf_table *table,
const struct devlink_port_new_attrs *new_attr,
struct netlink_ext_ack *extack,
- unsigned int *new_port_index)
+ struct devlink_port **dl_port)
{
struct mlx5_eswitch *esw = dev->priv.eswitch;
struct mlx5_sf *sf;
@@ -297,7 +296,7 @@ static int mlx5_sf_add(struct mlx5_core_dev *dev, struct mlx5_sf_table *table,
new_attr->controller, new_attr->sfnum);
if (err)
goto esw_err;
- *new_port_index = sf->port_index;
+ *dl_port = &sf->dl_port;
trace_mlx5_sf_add(dev, sf->port_index, sf->controller, sf->hw_fn_id, new_attr->sfnum);
return 0;
@@ -339,7 +338,7 @@ mlx5_sf_new_check_attr(struct mlx5_core_dev *dev, const struct devlink_port_new_
int mlx5_devlink_sf_port_new(struct devlink *devlink,
const struct devlink_port_new_attrs *new_attr,
struct netlink_ext_ack *extack,
- unsigned int *new_port_index)
+ struct devlink_port **dl_port)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
struct mlx5_sf_table *table;
@@ -355,7 +354,7 @@ int mlx5_devlink_sf_port_new(struct devlink *devlink,
"Port add is only supported in eswitch switchdev mode or SF ports are disabled.");
return -EOPNOTSUPP;
}
- err = mlx5_sf_add(dev, table, new_attr, extack, new_port_index);
+ err = mlx5_sf_add(dev, table, new_attr, extack, dl_port);
mlx5_sf_table_put(table);
return err;
}
@@ -379,7 +378,8 @@ static void mlx5_sf_dealloc(struct mlx5_sf_table *table, struct mlx5_sf *sf)
}
}
-int mlx5_devlink_sf_port_del(struct devlink *devlink, unsigned int port_index,
+int mlx5_devlink_sf_port_del(struct devlink *devlink,
+ struct devlink_port *dl_port,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
@@ -394,7 +394,7 @@ int mlx5_devlink_sf_port_del(struct devlink *devlink, unsigned int port_index,
"Port del is only supported in eswitch switchdev mode or SF ports are disabled.");
return -EOPNOTSUPP;
}
- sf = mlx5_sf_lookup_by_index(table, port_index);
+ sf = mlx5_sf_lookup_by_index(table, dl_port->index);
if (!sf) {
err = -ENODEV;
goto sf_err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h b/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h
index 3a480e06ecc0..860f9ddb7107 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h
@@ -21,8 +21,9 @@ void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev);
int mlx5_devlink_sf_port_new(struct devlink *devlink,
const struct devlink_port_new_attrs *add_attr,
struct netlink_ext_ack *extack,
- unsigned int *new_port_index);
-int mlx5_devlink_sf_port_del(struct devlink *devlink, unsigned int port_index,
+ struct devlink_port **dl_port);
+int mlx5_devlink_sf_port_del(struct devlink *devlink,
+ struct devlink_port *dl_port,
struct netlink_ext_ack *extack);
int mlx5_devlink_sf_port_fn_state_get(struct devlink_port *dl_port,
enum devlink_port_fn_state *state,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c
index 20d7662c10fb..a2fc937d5461 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c
@@ -37,7 +37,7 @@
#include "mlx5_irq.h"
#include "eswitch.h"
-static int sriov_restore_guids(struct mlx5_core_dev *dev, int vf)
+static int sriov_restore_guids(struct mlx5_core_dev *dev, int vf, u16 func_id)
{
struct mlx5_core_sriov *sriov = &dev->priv.sriov;
struct mlx5_hca_vport_context *in;
@@ -59,7 +59,7 @@ static int sriov_restore_guids(struct mlx5_core_dev *dev, int vf)
!!(in->node_guid) * MLX5_HCA_VPORT_SEL_NODE_GUID |
!!(in->policy) * MLX5_HCA_VPORT_SEL_STATE_POLICY;
- err = mlx5_core_modify_hca_vport_context(dev, 1, 1, vf + 1, in);
+ err = mlx5_core_modify_hca_vport_context(dev, 1, 1, func_id, in);
if (err)
mlx5_core_warn(dev, "modify vport context failed, unable to restore VF %d settings\n", vf);
@@ -73,9 +73,7 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs)
{
struct mlx5_core_sriov *sriov = &dev->priv.sriov;
int err, vf, num_msix_count;
-
- if (!MLX5_ESWITCH_MANAGER(dev))
- goto enable_vfs_hca;
+ int vport_num;
err = mlx5_eswitch_enable(dev->priv.eswitch, num_vfs);
if (err) {
@@ -84,7 +82,6 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs)
return err;
}
-enable_vfs_hca:
num_msix_count = mlx5_get_default_msix_vec_count(dev, num_vfs);
for (vf = 0; vf < num_vfs; vf++) {
/* Notify the VF before its enablement to let it set
@@ -108,7 +105,10 @@ enable_vfs_hca:
sriov->vfs_ctx[vf].enabled = 1;
if (MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) {
- err = sriov_restore_guids(dev, vf);
+ vport_num = mlx5_core_ec_sriov_enabled(dev) ?
+ mlx5_core_ec_vf_vport_base(dev) + vf
+ : vf + 1;
+ err = sriov_restore_guids(dev, vf, vport_num);
if (err) {
mlx5_core_warn(dev,
"failed to restore VF %d settings, err %d\n",
@@ -123,9 +123,11 @@ enable_vfs_hca:
}
static void
-mlx5_device_disable_sriov(struct mlx5_core_dev *dev, int num_vfs, bool clear_vf)
+mlx5_device_disable_sriov(struct mlx5_core_dev *dev, int num_vfs, bool clear_vf, bool num_vf_change)
{
struct mlx5_core_sriov *sriov = &dev->priv.sriov;
+ bool wait_for_ec_vf_pages = true;
+ bool wait_for_vf_pages = true;
int err;
int vf;
@@ -147,11 +149,30 @@ mlx5_device_disable_sriov(struct mlx5_core_dev *dev, int num_vfs, bool clear_vf)
mlx5_eswitch_disable_sriov(dev->priv.eswitch, clear_vf);
+ /* There are a number of scenarios when SRIOV is being disabled:
+ * 1. VFs or ECVFs had been created, and now set back to 0 (num_vf_change == true).
+ * - If EC SRIOV is enabled then this flow is happening on the
+ * embedded platform, wait for only EC VF pages.
+ * - If EC SRIOV is not enabled this flow is happening on non-embedded
+ * platform, wait for the VF pages.
+ *
+ * 2. The driver is being unloaded. In this case wait for all pages.
+ */
+ if (num_vf_change) {
+ if (mlx5_core_ec_sriov_enabled(dev))
+ wait_for_vf_pages = false;
+ else
+ wait_for_ec_vf_pages = false;
+ }
+
+ if (wait_for_ec_vf_pages && mlx5_wait_for_pages(dev, &dev->priv.page_counters[MLX5_EC_VF]))
+ mlx5_core_warn(dev, "timeout reclaiming EC VFs pages\n");
+
/* For ECPFs, skip waiting for host VF pages until ECPF is destroyed */
if (mlx5_core_is_ecpf(dev))
return;
- if (mlx5_wait_for_pages(dev, &dev->priv.page_counters[MLX5_VF]))
+ if (wait_for_vf_pages && mlx5_wait_for_pages(dev, &dev->priv.page_counters[MLX5_VF]))
mlx5_core_warn(dev, "timeout reclaiming VFs pages\n");
}
@@ -172,12 +193,12 @@ static int mlx5_sriov_enable(struct pci_dev *pdev, int num_vfs)
err = pci_enable_sriov(pdev, num_vfs);
if (err) {
mlx5_core_warn(dev, "pci_enable_sriov failed : %d\n", err);
- mlx5_device_disable_sriov(dev, num_vfs, true);
+ mlx5_device_disable_sriov(dev, num_vfs, true, true);
}
return err;
}
-void mlx5_sriov_disable(struct pci_dev *pdev)
+void mlx5_sriov_disable(struct pci_dev *pdev, bool num_vf_change)
{
struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
struct devlink *devlink = priv_to_devlink(dev);
@@ -185,7 +206,7 @@ void mlx5_sriov_disable(struct pci_dev *pdev)
pci_disable_sriov(pdev);
devl_lock(devlink);
- mlx5_device_disable_sriov(dev, num_vfs, true);
+ mlx5_device_disable_sriov(dev, num_vfs, true, num_vf_change);
devl_unlock(devlink);
}
@@ -200,7 +221,7 @@ int mlx5_core_sriov_configure(struct pci_dev *pdev, int num_vfs)
if (num_vfs)
err = mlx5_sriov_enable(pdev, num_vfs);
else
- mlx5_sriov_disable(pdev);
+ mlx5_sriov_disable(pdev, true);
if (!err)
sriov->num_vfs = num_vfs;
@@ -245,7 +266,7 @@ void mlx5_sriov_detach(struct mlx5_core_dev *dev)
if (!mlx5_core_is_pf(dev))
return;
- mlx5_device_disable_sriov(dev, pci_num_vf(dev->pdev), false);
+ mlx5_device_disable_sriov(dev, pci_num_vf(dev->pdev), false, false);
}
static u16 mlx5_get_max_vfs(struct mlx5_core_dev *dev)
@@ -264,8 +285,7 @@ static u16 mlx5_get_max_vfs(struct mlx5_core_dev *dev)
host_total_vfs = MLX5_GET(query_esw_functions_out, out,
host_params_context.host_total_vfs);
kvfree(out);
- if (host_total_vfs)
- return host_total_vfs;
+ return host_total_vfs;
}
done:
@@ -284,6 +304,7 @@ int mlx5_sriov_init(struct mlx5_core_dev *dev)
total_vfs = pci_sriov_get_totalvfs(pdev);
sriov->max_vfs = mlx5_get_max_vfs(dev);
sriov->num_vfs = pci_num_vf(pdev);
+ sriov->max_ec_vfs = mlx5_core_ec_sriov_enabled(dev) ? pci_sriov_get_totalvfs(dev->pdev) : 0;
sriov->vfs_ctx = kcalloc(total_vfs, sizeof(*sriov->vfs_ctx), GFP_KERNEL);
if (!sriov->vfs_ctx)
return -ENOMEM;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
index 0f783e7906cb..54bb0866ed72 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
@@ -2077,8 +2077,9 @@ mlx5dr_action_create_dest_vport(struct mlx5dr_domain *dmn,
struct mlx5dr_action *action;
u8 peer_vport;
- peer_vport = vhca_id_valid && (vhca_id != dmn->info.caps.gvmi);
- vport_dmn = peer_vport ? dmn->peer_dmn : dmn;
+ peer_vport = vhca_id_valid && mlx5_core_is_pf(dmn->mdev) &&
+ (vhca_id != dmn->info.caps.gvmi);
+ vport_dmn = peer_vport ? xa_load(&dmn->peer_dmn_xa, vhca_id) : dmn;
if (!vport_dmn) {
mlx5dr_dbg(dmn, "No peer vport domain for given vhca_id\n");
return NULL;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c
index 1aa525e509f1..8c2a34a0d6be 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c
@@ -34,6 +34,7 @@ int mlx5dr_cmd_query_esw_vport_context(struct mlx5_core_dev *mdev,
int mlx5dr_cmd_query_gvmi(struct mlx5_core_dev *mdev, bool other_vport,
u16 vport_number, u16 *gvmi)
{
+ bool ec_vf_func = other_vport ? mlx5_core_is_ec_vf_vport(mdev, vport_number) : false;
u32 in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {};
int out_size;
void *out;
@@ -46,7 +47,8 @@ int mlx5dr_cmd_query_gvmi(struct mlx5_core_dev *mdev, bool other_vport,
MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
MLX5_SET(query_hca_cap_in, in, other_function, other_vport);
- MLX5_SET(query_hca_cap_in, in, function_id, vport_number);
+ MLX5_SET(query_hca_cap_in, in, function_id, mlx5_vport_to_func_id(mdev, vport_number, ec_vf_func));
+ MLX5_SET(query_hca_cap_in, in, ec_vf_function, ec_vf_func);
MLX5_SET(query_hca_cap_in, in, op_mod,
MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE << 1 |
HCA_CAP_OPMOD_GET_CUR);
@@ -562,11 +564,12 @@ int mlx5dr_cmd_create_reformat_ctx(struct mlx5_core_dev *mdev,
err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
if (err)
- return err;
+ goto err_free_in;
*reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id);
- kvfree(in);
+err_free_in:
+ kvfree(in);
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
index 9a2dfe6ebe31..3d74109f8230 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
@@ -475,6 +475,7 @@ mlx5dr_domain_create(struct mlx5_core_dev *mdev, enum mlx5dr_domain_type type)
mutex_init(&dmn->info.rx.mutex);
mutex_init(&dmn->info.tx.mutex);
xa_init(&dmn->definers_xa);
+ xa_init(&dmn->peer_dmn_xa);
if (dr_domain_caps_init(mdev, dmn)) {
mlx5dr_err(dmn, "Failed init domain, no caps\n");
@@ -507,6 +508,7 @@ mlx5dr_domain_create(struct mlx5_core_dev *mdev, enum mlx5dr_domain_type type)
uninit_caps:
dr_domain_caps_uninit(dmn);
def_xa_destroy:
+ xa_destroy(&dmn->peer_dmn_xa);
xa_destroy(&dmn->definers_xa);
kfree(dmn);
return NULL;
@@ -547,6 +549,7 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *dmn)
dr_domain_uninit_csum_recalc_fts(dmn);
dr_domain_uninit_resources(dmn);
dr_domain_caps_uninit(dmn);
+ xa_destroy(&dmn->peer_dmn_xa);
xa_destroy(&dmn->definers_xa);
mutex_destroy(&dmn->info.tx.mutex);
mutex_destroy(&dmn->info.rx.mutex);
@@ -555,17 +558,22 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *dmn)
}
void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn,
- struct mlx5dr_domain *peer_dmn)
+ struct mlx5dr_domain *peer_dmn,
+ u16 peer_vhca_id)
{
+ struct mlx5dr_domain *peer;
+
mlx5dr_domain_lock(dmn);
- if (dmn->peer_dmn)
- refcount_dec(&dmn->peer_dmn->refcount);
+ peer = xa_load(&dmn->peer_dmn_xa, peer_vhca_id);
+ if (peer)
+ refcount_dec(&peer->refcount);
- dmn->peer_dmn = peer_dmn;
+ WARN_ON(xa_err(xa_store(&dmn->peer_dmn_xa, peer_vhca_id, peer_dmn, GFP_KERNEL)));
- if (dmn->peer_dmn)
- refcount_inc(&dmn->peer_dmn->refcount);
+ peer = xa_load(&dmn->peer_dmn_xa, peer_vhca_id);
+ if (peer)
+ refcount_inc(&peer->refcount);
mlx5dr_domain_unlock(dmn);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c
index d6947fe13d56..8ca534ef5d03 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c
@@ -82,7 +82,7 @@ dr_ptrn_alloc_pattern(struct mlx5dr_ptrn_mgr *mgr,
u32 chunk_size;
u32 index;
- chunk_size = ilog2(num_of_actions);
+ chunk_size = ilog2(roundup_pow_of_two(num_of_actions));
/* HW modify action index granularity is at least 64B */
chunk_size = max_t(u32, chunk_size, DR_CHUNK_SIZE_8);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c
index 2010d4ac6519..f708b029425a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c
@@ -1647,21 +1647,23 @@ dr_ste_v0_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
u8 *tag)
{
struct mlx5dr_match_misc *misc = &value->misc;
+ int id = misc->source_eswitch_owner_vhca_id;
struct mlx5dr_cmd_vport_cap *vport_cap;
struct mlx5dr_domain *dmn = sb->dmn;
struct mlx5dr_domain *vport_dmn;
u8 *bit_mask = sb->bit_mask;
+ struct mlx5dr_domain *peer;
bool source_gvmi_set;
DR_STE_SET_TAG(src_gvmi_qp, tag, source_qp, misc, source_sqn);
if (sb->vhca_id_valid) {
+ peer = xa_load(&dmn->peer_dmn_xa, id);
/* Find port GVMI based on the eswitch_owner_vhca_id */
- if (misc->source_eswitch_owner_vhca_id == dmn->info.caps.gvmi)
+ if (id == dmn->info.caps.gvmi)
vport_dmn = dmn;
- else if (dmn->peer_dmn && (misc->source_eswitch_owner_vhca_id ==
- dmn->peer_dmn->info.caps.gvmi))
- vport_dmn = dmn->peer_dmn;
+ else if (peer && (id == peer->info.caps.gvmi))
+ vport_dmn = peer;
else
return -EINVAL;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c
index 4c0704ad166b..dd856cde188d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c
@@ -1979,20 +1979,22 @@ static int dr_ste_v1_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
u8 *tag)
{
struct mlx5dr_match_misc *misc = &value->misc;
+ int id = misc->source_eswitch_owner_vhca_id;
struct mlx5dr_cmd_vport_cap *vport_cap;
struct mlx5dr_domain *dmn = sb->dmn;
struct mlx5dr_domain *vport_dmn;
u8 *bit_mask = sb->bit_mask;
+ struct mlx5dr_domain *peer;
DR_STE_SET_TAG(src_gvmi_qp_v1, tag, source_qp, misc, source_sqn);
if (sb->vhca_id_valid) {
+ peer = xa_load(&dmn->peer_dmn_xa, id);
/* Find port GVMI based on the eswitch_owner_vhca_id */
- if (misc->source_eswitch_owner_vhca_id == dmn->info.caps.gvmi)
+ if (id == dmn->info.caps.gvmi)
vport_dmn = dmn;
- else if (dmn->peer_dmn && (misc->source_eswitch_owner_vhca_id ==
- dmn->peer_dmn->info.caps.gvmi))
- vport_dmn = dmn->peer_dmn;
+ else if (peer && (id == peer->info.caps.gvmi))
+ vport_dmn = peer;
else
return -EINVAL;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
index 678a993ab053..6c59de3e28f6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
@@ -935,7 +935,6 @@ struct mlx5dr_domain_info {
};
struct mlx5dr_domain {
- struct mlx5dr_domain *peer_dmn;
struct mlx5_core_dev *mdev;
u32 pdn;
struct mlx5_uars_page *uar;
@@ -956,6 +955,7 @@ struct mlx5dr_domain {
struct list_head dbg_tbl_list;
struct mlx5dr_dbg_dump_info dump_info;
struct xarray definers_xa;
+ struct xarray peer_dmn_xa;
/* memory management statistics */
u32 num_buddies[DR_ICM_TYPE_MAX];
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
index cc215beb7436..feb307fb3440 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
@@ -780,14 +780,15 @@ restore_fte:
}
static int mlx5_cmd_dr_set_peer(struct mlx5_flow_root_namespace *ns,
- struct mlx5_flow_root_namespace *peer_ns)
+ struct mlx5_flow_root_namespace *peer_ns,
+ u16 peer_vhca_id)
{
struct mlx5dr_domain *peer_domain = NULL;
if (peer_ns)
peer_domain = peer_ns->fs_dr_domain.dr_domain;
mlx5dr_domain_set_peer(ns->fs_dr_domain.dr_domain,
- peer_domain);
+ peer_domain, peer_vhca_id);
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h
index d1c04f43d86d..89fced86936f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h
@@ -48,7 +48,8 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *domain);
int mlx5dr_domain_sync(struct mlx5dr_domain *domain, u32 flags);
void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn,
- struct mlx5dr_domain *peer_dmn);
+ struct mlx5dr_domain *peer_dmn,
+ u16 peer_vhca_id);
struct mlx5dr_table *
mlx5dr_table_create(struct mlx5dr_domain *domain, u32 level, u32 flags,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/thermal.c b/drivers/net/ethernet/mellanox/mlx5/core/thermal.c
index e47fa6fb836f..52199d39657e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/thermal.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/thermal.c
@@ -45,7 +45,7 @@ static int mlx5_thermal_get_mtmp_temp(struct mlx5_core_dev *mdev, u32 id, int *p
static int mlx5_thermal_get_temp(struct thermal_zone_device *tzdev,
int *p_temp)
{
- struct mlx5_thermal *thermal = tzdev->devdata;
+ struct mlx5_thermal *thermal = thermal_zone_device_priv(tzdev);
struct mlx5_core_dev *mdev = thermal->mdev;
int err;
@@ -68,30 +68,36 @@ static struct thermal_zone_device_ops mlx5_thermal_ops = {
int mlx5_thermal_init(struct mlx5_core_dev *mdev)
{
+ char data[THERMAL_NAME_LENGTH];
struct mlx5_thermal *thermal;
- struct thermal_zone_device *tzd;
- const char *data = "mlx5";
+ int err;
- tzd = thermal_zone_get_zone_by_name(data);
- if (!IS_ERR(tzd))
+ if (!mlx5_core_is_pf(mdev) && !mlx5_core_is_ecpf(mdev))
return 0;
+ err = snprintf(data, sizeof(data), "mlx5_%s", dev_name(mdev->device));
+ if (err < 0 || err >= sizeof(data)) {
+ mlx5_core_err(mdev, "Failed to setup thermal zone name, %d\n", err);
+ return -EINVAL;
+ }
+
thermal = kzalloc(sizeof(*thermal), GFP_KERNEL);
if (!thermal)
return -ENOMEM;
thermal->mdev = mdev;
- thermal->tzdev = thermal_zone_device_register(data,
- MLX5_THERMAL_NUM_TRIPS,
- MLX5_THERMAL_TRIP_MASK,
- thermal,
- &mlx5_thermal_ops,
- NULL, 0, MLX5_THERMAL_POLL_INT_MSEC);
+ thermal->tzdev = thermal_zone_device_register_with_trips(data,
+ NULL,
+ MLX5_THERMAL_NUM_TRIPS,
+ MLX5_THERMAL_TRIP_MASK,
+ thermal,
+ &mlx5_thermal_ops,
+ NULL, 0, MLX5_THERMAL_POLL_INT_MSEC);
if (IS_ERR(thermal->tzdev)) {
- dev_err(mdev->device, "Failed to register thermal zone device (%s) %ld\n",
- data, PTR_ERR(thermal->tzdev));
+ err = PTR_ERR(thermal->tzdev);
+ mlx5_core_err(mdev, "Failed to register thermal zone device (%s) %d\n", data, err);
kfree(thermal);
- return -EINVAL;
+ return err;
}
mdev->thermal = thermal;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
index ba7e3df22413..5a31fb47ffa5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
@@ -288,7 +288,8 @@ int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev,
MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
MLX5_SET(query_nic_vport_context_in, in, allowed_list_type, list_type);
MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
- MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
+ if (vport || mlx5_core_is_ecpf(dev))
+ MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz);
if (err)
@@ -1160,23 +1161,26 @@ u64 mlx5_query_nic_system_image_guid(struct mlx5_core_dev *mdev)
}
EXPORT_SYMBOL_GPL(mlx5_query_nic_system_image_guid);
-int mlx5_vport_get_other_func_cap(struct mlx5_core_dev *dev, u16 function_id, void *out,
+int mlx5_vport_get_other_func_cap(struct mlx5_core_dev *dev, u16 vport, void *out,
u16 opmod)
{
+ bool ec_vf_func = mlx5_core_is_ec_vf_vport(dev, vport);
u8 in[MLX5_ST_SZ_BYTES(query_hca_cap_in)] = {};
opmod = (opmod << 1) | (HCA_CAP_OPMOD_GET_MAX & 0x01);
MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
MLX5_SET(query_hca_cap_in, in, op_mod, opmod);
- MLX5_SET(query_hca_cap_in, in, function_id, function_id);
+ MLX5_SET(query_hca_cap_in, in, function_id, mlx5_vport_to_func_id(dev, vport, ec_vf_func));
MLX5_SET(query_hca_cap_in, in, other_function, true);
+ MLX5_SET(query_hca_cap_in, in, ec_vf_function, ec_vf_func);
return mlx5_cmd_exec_inout(dev, query_hca_cap, in, out);
}
EXPORT_SYMBOL_GPL(mlx5_vport_get_other_func_cap);
int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap,
- u16 function_id, u16 opmod)
+ u16 vport, u16 opmod)
{
+ bool ec_vf_func = mlx5_core_is_ec_vf_vport(dev, vport);
int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in);
void *set_hca_cap;
void *set_ctx;
@@ -1190,8 +1194,10 @@ int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap
MLX5_SET(set_hca_cap_in, set_ctx, op_mod, opmod << 1);
set_hca_cap = MLX5_ADDR_OF(set_hca_cap_in, set_ctx, capability);
memcpy(set_hca_cap, hca_cap, MLX5_ST_SZ_BYTES(cmd_hca_cap));
- MLX5_SET(set_hca_cap_in, set_ctx, function_id, function_id);
+ MLX5_SET(set_hca_cap_in, set_ctx, function_id,
+ mlx5_vport_to_func_id(dev, vport, ec_vf_func));
MLX5_SET(set_hca_cap_in, set_ctx, other_function, true);
+ MLX5_SET(set_hca_cap_in, set_ctx, ec_vf_function, ec_vf_func);
ret = mlx5_cmd_exec_in(dev, set_hca_cap, set_ctx);
kfree(set_ctx);
diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h
index b001e5258091..47f6cc0401c3 100644
--- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h
+++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h
@@ -44,7 +44,7 @@ MLXFW_MFA2_TLV(multi, struct mlxfw_mfa2_tlv_multi,
MLXFW_MFA2_TLV_MULTI_PART);
struct mlxfw_mfa2_tlv_psid {
- u8 psid[0];
+ DECLARE_FLEX_ARRAY(u8, psid);
} __packed;
MLXFW_MFA2_TLV_VARSIZE(psid, struct mlxfw_mfa2_tlv_psid,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index 22db0bb15c45..1ccf3b73ed72 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -1723,8 +1723,6 @@ static const struct devlink_ops mlxsw_devlink_ops = {
BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
.reload_down = mlxsw_devlink_core_bus_device_reload_down,
.reload_up = mlxsw_devlink_core_bus_device_reload_up,
- .port_split = mlxsw_devlink_port_split,
- .port_unsplit = mlxsw_devlink_port_unsplit,
.sb_pool_get = mlxsw_devlink_sb_pool_get,
.sb_pool_set = mlxsw_devlink_sb_pool_set,
.sb_port_pool_get = mlxsw_devlink_sb_port_pool_get,
@@ -3116,6 +3114,11 @@ u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core,
}
EXPORT_SYMBOL(mlxsw_core_res_get);
+static const struct devlink_port_ops mlxsw_devlink_port_ops = {
+ .port_split = mlxsw_devlink_port_split,
+ .port_unsplit = mlxsw_devlink_port_unsplit,
+};
+
static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port,
enum devlink_port_flavour flavour,
u8 slot_index, u32 port_number, bool split,
@@ -3150,7 +3153,8 @@ static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port,
devlink_port_linecard_set(devlink_port,
linecard->devlink_linecard);
}
- err = devl_port_register(devlink, devlink_port, local_port);
+ err = devl_port_register_with_ops(devlink, devlink_port, local_port,
+ &mlxsw_devlink_port_ops);
if (err)
memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port));
return err;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
index bd1a51a0a540..973de2adc943 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
@@ -32,8 +32,8 @@ static const struct mlxsw_afk_element_info mlxsw_afk_element_infos[] = {
MLXSW_AFK_ELEMENT_INFO_U32(IP_TTL_, 0x18, 0, 8),
MLXSW_AFK_ELEMENT_INFO_U32(IP_ECN, 0x18, 9, 2),
MLXSW_AFK_ELEMENT_INFO_U32(IP_DSCP, 0x18, 11, 6),
- MLXSW_AFK_ELEMENT_INFO_U32(VIRT_ROUTER_MSB, 0x18, 17, 3),
- MLXSW_AFK_ELEMENT_INFO_U32(VIRT_ROUTER_LSB, 0x18, 20, 8),
+ MLXSW_AFK_ELEMENT_INFO_U32(VIRT_ROUTER_MSB, 0x18, 17, 4),
+ MLXSW_AFK_ELEMENT_INFO_U32(VIRT_ROUTER_LSB, 0x18, 21, 8),
MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP_96_127, 0x20, 4),
MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP_64_95, 0x24, 4),
MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP_32_63, 0x28, 4),
@@ -42,6 +42,7 @@ static const struct mlxsw_afk_element_info mlxsw_afk_element_infos[] = {
MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_64_95, 0x34, 4),
MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_32_63, 0x38, 4),
MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_0_31, 0x3C, 4),
+ MLXSW_AFK_ELEMENT_INFO_U32(FDB_MISS, 0x40, 0, 1),
};
struct mlxsw_afk {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h
index 3a037fe47211..65a4abadc7db 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h
@@ -35,6 +35,7 @@ enum mlxsw_afk_element {
MLXSW_AFK_ELEMENT_IP_DSCP,
MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB,
MLXSW_AFK_ELEMENT_VIRT_ROUTER_LSB,
+ MLXSW_AFK_ELEMENT_FDB_MISS,
MLXSW_AFK_ELEMENT_MAX,
};
@@ -69,7 +70,7 @@ struct mlxsw_afk_element_info {
MLXSW_AFK_ELEMENT_INFO(MLXSW_AFK_ELEMENT_TYPE_BUF, \
_element, _offset, 0, _size)
-#define MLXSW_AFK_ELEMENT_STORAGE_SIZE 0x40
+#define MLXSW_AFK_ELEMENT_STORAGE_SIZE 0x44
struct mlxsw_afk_element_inst { /* element instance in actual block */
enum mlxsw_afk_element element;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
index 2c586c2308ae..41298835a11e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
@@ -751,7 +751,7 @@ static void mlxsw_i2c_remove(struct i2c_client *client)
int mlxsw_i2c_driver_register(struct i2c_driver *i2c_driver)
{
- i2c_driver->probe_new = mlxsw_i2c_probe;
+ i2c_driver->probe = mlxsw_i2c_probe;
i2c_driver->remove = mlxsw_i2c_remove;
return i2c_add_driver(i2c_driver);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
index 6b56eadd736e..6b98c3287b49 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
@@ -417,6 +417,7 @@ static int mlxsw_m_linecards_init(struct mlxsw_m *mlxsw_m)
err_kmalloc_array:
for (i--; i >= 0; i--)
kfree(mlxsw_m->line_cards[i]);
+ kfree(mlxsw_m->line_cards);
err_kcalloc:
kfree(mlxsw_m->ports);
return err;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c
index c968309657dd..51eea1f0529c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/pci.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c
@@ -517,11 +517,15 @@ static void mlxsw_pci_skb_cb_ts_set(struct mlxsw_pci *mlxsw_pci,
struct sk_buff *skb,
enum mlxsw_pci_cqe_v cqe_v, char *cqe)
{
+ u8 ts_type;
+
if (cqe_v != MLXSW_PCI_CQE_V2)
return;
- if (mlxsw_pci_cqe2_time_stamp_type_get(cqe) !=
- MLXSW_PCI_CQE_TIME_STAMP_TYPE_UTC)
+ ts_type = mlxsw_pci_cqe2_time_stamp_type_get(cqe);
+
+ if (ts_type != MLXSW_PCI_CQE_TIME_STAMP_TYPE_UTC &&
+ ts_type != MLXSW_PCI_CQE_TIME_STAMP_TYPE_MIRROR_UTC)
return;
mlxsw_skb_cb(skb)->cqe_ts.sec = mlxsw_pci_cqe2_time_stamp_sec_get(cqe);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 8165bf31a99a..17160e867bef 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -97,14 +97,6 @@ MLXSW_ITEM32(reg, sspr, m, 0x00, 31, 1);
*/
MLXSW_ITEM32_LP(reg, sspr, 0x00, 16, 0x00, 12);
-/* reg_sspr_sub_port
- * Virtual port within the physical port.
- * Should be set to 0 when virtual ports are not enabled on the port.
- *
- * Access: RW
- */
-MLXSW_ITEM32(reg, sspr, sub_port, 0x00, 8, 8);
-
/* reg_sspr_system_port
* Unique identifier within the stacking domain that represents all the ports
* that are available in the system (external ports).
@@ -120,7 +112,6 @@ static inline void mlxsw_reg_sspr_pack(char *payload, u16 local_port)
MLXSW_REG_ZERO(sspr, payload);
mlxsw_reg_sspr_m_set(payload, 1);
mlxsw_reg_sspr_local_port_set(payload, local_port);
- mlxsw_reg_sspr_sub_port_set(payload, 0);
mlxsw_reg_sspr_system_port_set(payload, local_port);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 02a327744a61..25a01dafde1b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -4337,8 +4337,8 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port->default_vlan);
/* Join a router interface configured on the LAG, if exists */
- err = mlxsw_sp_port_vlan_router_join(mlxsw_sp_port->default_vlan,
- lag_dev, extack);
+ err = mlxsw_sp_router_port_join_lag(mlxsw_sp_port, lag_dev,
+ extack);
if (err)
goto err_router_join;
@@ -5139,14 +5139,6 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *nb,
return notifier_from_errno(err);
}
-static struct notifier_block mlxsw_sp_inetaddr_valid_nb __read_mostly = {
- .notifier_call = mlxsw_sp_inetaddr_valid_event,
-};
-
-static struct notifier_block mlxsw_sp_inet6addr_valid_nb __read_mostly = {
- .notifier_call = mlxsw_sp_inet6addr_valid_event,
-};
-
static const struct pci_device_id mlxsw_sp1_pci_id_table[] = {
{PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM), 0},
{0, },
@@ -5191,12 +5183,9 @@ static int __init mlxsw_sp_module_init(void)
{
int err;
- register_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
- register_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
-
err = mlxsw_core_driver_register(&mlxsw_sp1_driver);
if (err)
- goto err_sp1_core_driver_register;
+ return err;
err = mlxsw_core_driver_register(&mlxsw_sp2_driver);
if (err)
@@ -5242,9 +5231,6 @@ err_sp3_core_driver_register:
mlxsw_core_driver_unregister(&mlxsw_sp2_driver);
err_sp2_core_driver_register:
mlxsw_core_driver_unregister(&mlxsw_sp1_driver);
-err_sp1_core_driver_register:
- unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
- unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
return err;
}
@@ -5258,8 +5244,6 @@ static void __exit mlxsw_sp_module_exit(void)
mlxsw_core_driver_unregister(&mlxsw_sp3_driver);
mlxsw_core_driver_unregister(&mlxsw_sp2_driver);
mlxsw_core_driver_unregister(&mlxsw_sp1_driver);
- unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
- unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
}
module_init(mlxsw_sp_module_init);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 4c22f8004514..231e364cbb7c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -755,14 +755,6 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp,
const struct net_device *macvlan_dev);
-int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
- unsigned long event, void *ptr);
-int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
- unsigned long event, void *ptr);
-int
-mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
- struct net_device *l3_dev,
- struct netlink_ext_ack *extack);
void
mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan);
void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c
index e4f4cded2b6f..b1178b7a7f51 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c
@@ -193,7 +193,7 @@ mlxsw_sp2_mr_tcam_rule_parse(struct mlxsw_sp_acl_rule *rule,
key->vrid, GENMASK(7, 0));
mlxsw_sp_acl_rulei_keymask_u32(rulei,
MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB,
- key->vrid >> 8, GENMASK(2, 0));
+ key->vrid >> 8, GENMASK(3, 0));
switch (key->proto) {
case MLXSW_SP_L3_PROTO_IPV4:
return mlxsw_sp2_mr_tcam_rule_parse4(rulei, key);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
index 00c32320f891..ae2d6f12b799 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
@@ -123,10 +123,12 @@ const struct mlxsw_afk_ops mlxsw_sp1_afk_ops = {
};
static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_0[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(FDB_MISS, 0x00, 3, 1),
MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x04, 4),
};
static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_1[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(FDB_MISS, 0x00, 3, 1),
MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4),
};
@@ -169,7 +171,7 @@ static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_2[] = {
static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_4[] = {
MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_LSB, 0x04, 24, 8),
- MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_MSB, 0x00, 0, 3),
+ MLXSW_AFK_ELEMENT_INST_EXT_U32(VIRT_ROUTER_MSB, 0x00, 0, 3, 0, true),
};
static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_0[] = {
@@ -319,7 +321,7 @@ static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5b[] = {
static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_4b[] = {
MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_LSB, 0x04, 13, 8),
- MLXSW_AFK_ELEMENT_INST_EXT_U32(VIRT_ROUTER_MSB, 0x04, 21, 4, 0, true),
+ MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_MSB, 0x04, 21, 4),
};
static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2b[] = {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
index 5416093c0e35..c8a356accdf8 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
@@ -221,7 +221,7 @@ start_again:
for (; i < rif_count; i++) {
struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i);
- if (!rif || !mlxsw_sp_rif_dev(rif))
+ if (!rif || !mlxsw_sp_rif_has_dev(rif))
continue;
err = mlxsw_sp_erif_entry_get(mlxsw_sp, &entry, rif,
counters_enabled);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
index 594cdcb90b3d..72917f09e806 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
@@ -281,39 +281,38 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
return 0;
}
-static int mlxsw_sp_flower_parse_meta(struct mlxsw_sp_acl_rule_info *rulei,
- struct flow_cls_offload *f,
- struct mlxsw_sp_flow_block *block)
+static int
+mlxsw_sp_flower_parse_meta_iif(struct mlxsw_sp_acl_rule_info *rulei,
+ const struct mlxsw_sp_flow_block *block,
+ const struct flow_match_meta *match,
+ struct netlink_ext_ack *extack)
{
- struct flow_rule *rule = flow_cls_offload_flow_rule(f);
struct mlxsw_sp_port *mlxsw_sp_port;
struct net_device *ingress_dev;
- struct flow_match_meta match;
- if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META))
+ if (!match->mask->ingress_ifindex)
return 0;
- flow_rule_match_meta(rule, &match);
- if (match.mask->ingress_ifindex != 0xFFFFFFFF) {
- NL_SET_ERR_MSG_MOD(f->common.extack, "Unsupported ingress ifindex mask");
+ if (match->mask->ingress_ifindex != 0xFFFFFFFF) {
+ NL_SET_ERR_MSG_MOD(extack, "Unsupported ingress ifindex mask");
return -EINVAL;
}
ingress_dev = __dev_get_by_index(block->net,
- match.key->ingress_ifindex);
+ match->key->ingress_ifindex);
if (!ingress_dev) {
- NL_SET_ERR_MSG_MOD(f->common.extack, "Can't find specified ingress port to match on");
+ NL_SET_ERR_MSG_MOD(extack, "Can't find specified ingress port to match on");
return -EINVAL;
}
if (!mlxsw_sp_port_dev_check(ingress_dev)) {
- NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on non-mlxsw ingress port");
+ NL_SET_ERR_MSG_MOD(extack, "Can't match on non-mlxsw ingress port");
return -EINVAL;
}
mlxsw_sp_port = netdev_priv(ingress_dev);
if (mlxsw_sp_port->mlxsw_sp != block->mlxsw_sp) {
- NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on a port from different device");
+ NL_SET_ERR_MSG_MOD(extack, "Can't match on a port from different device");
return -EINVAL;
}
@@ -321,9 +320,29 @@ static int mlxsw_sp_flower_parse_meta(struct mlxsw_sp_acl_rule_info *rulei,
MLXSW_AFK_ELEMENT_SRC_SYS_PORT,
mlxsw_sp_port->local_port,
0xFFFFFFFF);
+
return 0;
}
+static int mlxsw_sp_flower_parse_meta(struct mlxsw_sp_acl_rule_info *rulei,
+ struct flow_cls_offload *f,
+ struct mlxsw_sp_flow_block *block)
+{
+ struct flow_rule *rule = flow_cls_offload_flow_rule(f);
+ struct flow_match_meta match;
+
+ if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META))
+ return 0;
+
+ flow_rule_match_meta(rule, &match);
+
+ mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_FDB_MISS,
+ match.key->l2_miss, match.mask->l2_miss);
+
+ return mlxsw_sp_flower_parse_meta_iif(rulei, block, &match,
+ f->common.extack);
+}
+
static void mlxsw_sp_flower_parse_ipv4(struct mlxsw_sp_acl_rule_info *rulei,
struct flow_cls_offload *f)
{
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c
index 1f6bc0c7e91d..69cd689dbc83 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c
@@ -704,12 +704,12 @@ void mlxsw_sp_mr_vif_del(struct mlxsw_sp_mr_table *mr_table, vifi_t vif_index)
static struct mlxsw_sp_mr_vif *
mlxsw_sp_mr_dev_vif_lookup(struct mlxsw_sp_mr_table *mr_table,
- const struct net_device *dev)
+ const struct mlxsw_sp_rif *rif)
{
vifi_t vif_index;
for (vif_index = 0; vif_index < MAXVIFS; vif_index++)
- if (mr_table->vifs[vif_index].dev == dev)
+ if (mlxsw_sp_rif_dev_is(rif, mr_table->vifs[vif_index].dev))
return &mr_table->vifs[vif_index];
return NULL;
}
@@ -717,13 +717,12 @@ mlxsw_sp_mr_dev_vif_lookup(struct mlxsw_sp_mr_table *mr_table,
int mlxsw_sp_mr_rif_add(struct mlxsw_sp_mr_table *mr_table,
const struct mlxsw_sp_rif *rif)
{
- const struct net_device *rif_dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp_mr_vif *mr_vif;
- if (!rif_dev)
+ if (!mlxsw_sp_rif_has_dev(rif))
return 0;
- mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif_dev);
+ mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif);
if (!mr_vif)
return 0;
return mlxsw_sp_mr_vif_resolve(mr_table, mr_vif->dev, mr_vif,
@@ -733,13 +732,12 @@ int mlxsw_sp_mr_rif_add(struct mlxsw_sp_mr_table *mr_table,
void mlxsw_sp_mr_rif_del(struct mlxsw_sp_mr_table *mr_table,
const struct mlxsw_sp_rif *rif)
{
- const struct net_device *rif_dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp_mr_vif *mr_vif;
- if (!rif_dev)
+ if (!mlxsw_sp_rif_has_dev(rif))
return;
- mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif_dev);
+ mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif);
if (!mr_vif)
return;
mlxsw_sp_mr_vif_unresolve(mr_table, mr_vif->dev, mr_vif);
@@ -748,17 +746,16 @@ void mlxsw_sp_mr_rif_del(struct mlxsw_sp_mr_table *mr_table,
void mlxsw_sp_mr_rif_mtu_update(struct mlxsw_sp_mr_table *mr_table,
const struct mlxsw_sp_rif *rif, int mtu)
{
- const struct net_device *rif_dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp *mlxsw_sp = mr_table->mlxsw_sp;
struct mlxsw_sp_mr_route_vif_entry *rve;
struct mlxsw_sp_mr *mr = mlxsw_sp->mr;
struct mlxsw_sp_mr_vif *mr_vif;
- if (!rif_dev)
+ if (!mlxsw_sp_rif_has_dev(rif))
return;
/* Search for a VIF that use that RIF */
- mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif_dev);
+ mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif);
if (!mr_vif)
return;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
index d309b77a0194..bb8eeb86edf7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
@@ -11,10 +11,12 @@
#include "spectrum_nve.h"
#define MLXSW_SP_NVE_VXLAN_IPV4_SUPPORTED_FLAGS (VXLAN_F_UDP_ZERO_CSUM_TX | \
- VXLAN_F_LEARN)
+ VXLAN_F_LEARN | \
+ VXLAN_F_LOCALBYPASS)
#define MLXSW_SP_NVE_VXLAN_IPV6_SUPPORTED_FLAGS (VXLAN_F_IPV6 | \
VXLAN_F_UDP_ZERO_CSUM6_TX | \
- VXLAN_F_UDP_ZERO_CSUM6_RX)
+ VXLAN_F_UDP_ZERO_CSUM6_RX | \
+ VXLAN_F_LOCALBYPASS)
static bool mlxsw_sp_nve_vxlan_ipv4_flags_check(const struct vxlan_config *cfg,
struct netlink_ext_ack *extack)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 4a73e2fe95ef..b32adf277a22 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -51,10 +51,27 @@ struct mlxsw_sp_vr;
struct mlxsw_sp_lpm_tree;
struct mlxsw_sp_rif_ops;
-struct mlxsw_sp_rif {
+struct mlxsw_sp_crif_key {
+ struct net_device *dev;
+};
+
+struct mlxsw_sp_crif {
+ struct mlxsw_sp_crif_key key;
+ struct rhash_head ht_node;
+ bool can_destroy;
struct list_head nexthop_list;
+ struct mlxsw_sp_rif *rif;
+};
+
+static const struct rhashtable_params mlxsw_sp_crif_ht_params = {
+ .key_offset = offsetof(struct mlxsw_sp_crif, key),
+ .key_len = sizeof_field(struct mlxsw_sp_crif, key),
+ .head_offset = offsetof(struct mlxsw_sp_crif, ht_node),
+};
+
+struct mlxsw_sp_rif {
+ struct mlxsw_sp_crif *crif; /* NULL for underlay RIF */
struct list_head neigh_list;
- struct net_device *dev; /* NULL for underlay RIF */
struct mlxsw_sp_fid *fid;
unsigned char addr[ETH_ALEN];
int mtu;
@@ -71,6 +88,13 @@ struct mlxsw_sp_rif {
bool counter_egress_valid;
};
+static struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif)
+{
+ if (!rif->crif)
+ return NULL;
+ return rif->crif->key.dev;
+}
+
struct mlxsw_sp_rif_params {
struct net_device *dev;
union {
@@ -96,8 +120,8 @@ struct mlxsw_sp_rif_subport {
struct mlxsw_sp_rif_ipip_lb {
struct mlxsw_sp_rif common;
struct mlxsw_sp_rif_ipip_lb_config lb_config;
- u16 ul_vr_id; /* Reserved for Spectrum-2. */
- u16 ul_rif_id; /* Reserved for Spectrum. */
+ u16 ul_vr_id; /* Spectrum-1. */
+ u16 ul_rif_id; /* Spectrum-2+. */
};
struct mlxsw_sp_rif_params_ipip_lb {
@@ -748,10 +772,11 @@ static bool mlxsw_sp_vr_is_used(const struct mlxsw_sp_vr *vr)
static struct mlxsw_sp_vr *mlxsw_sp_vr_find_unused(struct mlxsw_sp *mlxsw_sp)
{
+ int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
struct mlxsw_sp_vr *vr;
int i;
- for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
+ for (i = 0; i < max_vrs; i++) {
vr = &mlxsw_sp->router->vrs[i];
if (!mlxsw_sp_vr_is_used(vr))
return vr;
@@ -792,12 +817,13 @@ static u32 mlxsw_sp_fix_tb_id(u32 tb_id)
static struct mlxsw_sp_vr *mlxsw_sp_vr_find(struct mlxsw_sp *mlxsw_sp,
u32 tb_id)
{
+ int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
struct mlxsw_sp_vr *vr;
int i;
tb_id = mlxsw_sp_fix_tb_id(tb_id);
- for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
+ for (i = 0; i < max_vrs; i++) {
vr = &mlxsw_sp->router->vrs[i];
if (mlxsw_sp_vr_is_used(vr) && vr->tb_id == tb_id)
return vr;
@@ -959,6 +985,7 @@ static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib *fib,
struct mlxsw_sp_lpm_tree *new_tree)
{
+ int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
enum mlxsw_sp_l3proto proto = fib->proto;
struct mlxsw_sp_lpm_tree *old_tree;
u8 old_id, new_id = new_tree->id;
@@ -968,7 +995,7 @@ static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp,
old_tree = mlxsw_sp->router->lpm.proto_trees[proto];
old_id = old_tree->id;
- for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
+ for (i = 0; i < max_vrs; i++) {
vr = &mlxsw_sp->router->vrs[i];
if (!mlxsw_sp_vr_lpm_tree_should_replace(vr, proto, old_id))
continue;
@@ -1052,6 +1079,61 @@ u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev)
return tb_id;
}
+static void
+mlxsw_sp_crif_init(struct mlxsw_sp_crif *crif, struct net_device *dev)
+{
+ crif->key.dev = dev;
+ INIT_LIST_HEAD(&crif->nexthop_list);
+}
+
+static struct mlxsw_sp_crif *
+mlxsw_sp_crif_alloc(struct net_device *dev)
+{
+ struct mlxsw_sp_crif *crif;
+
+ crif = kzalloc(sizeof(*crif), GFP_KERNEL);
+ if (!crif)
+ return NULL;
+
+ mlxsw_sp_crif_init(crif, dev);
+ return crif;
+}
+
+static void mlxsw_sp_crif_free(struct mlxsw_sp_crif *crif)
+{
+ if (WARN_ON(crif->rif))
+ return;
+
+ WARN_ON(!list_empty(&crif->nexthop_list));
+ kfree(crif);
+}
+
+static int mlxsw_sp_crif_insert(struct mlxsw_sp_router *router,
+ struct mlxsw_sp_crif *crif)
+{
+ return rhashtable_insert_fast(&router->crif_ht, &crif->ht_node,
+ mlxsw_sp_crif_ht_params);
+}
+
+static void mlxsw_sp_crif_remove(struct mlxsw_sp_router *router,
+ struct mlxsw_sp_crif *crif)
+{
+ rhashtable_remove_fast(&router->crif_ht, &crif->ht_node,
+ mlxsw_sp_crif_ht_params);
+}
+
+static struct mlxsw_sp_crif *
+mlxsw_sp_crif_lookup(struct mlxsw_sp_router *router,
+ const struct net_device *dev)
+{
+ struct mlxsw_sp_crif_key key = {
+ .dev = (struct net_device *)dev,
+ };
+
+ return rhashtable_lookup_fast(&router->crif_ht, &key,
+ mlxsw_sp_crif_ht_params);
+}
+
static struct mlxsw_sp_rif *
mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_rif_params *params,
@@ -1557,6 +1639,7 @@ mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, u16 ul_vr_id,
u16 ul_rif_id, bool enable)
{
struct mlxsw_sp_rif_ipip_lb_config lb_cf = lb_rif->lb_config;
+ struct net_device *dev = mlxsw_sp_rif_dev(&lb_rif->common);
enum mlxsw_reg_ritr_loopback_ipip_options ipip_options;
struct mlxsw_sp_rif *rif = &lb_rif->common;
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
@@ -1569,7 +1652,7 @@ mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, u16 ul_vr_id,
case MLXSW_SP_L3_PROTO_IPV4:
saddr4 = be32_to_cpu(lb_cf.saddr.addr4);
mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
- rif->rif_index, rif->vr_id, rif->dev->mtu);
+ rif->rif_index, rif->vr_id, dev->mtu);
mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl, lb_cf.lb_ipipt,
ipip_options, ul_vr_id,
ul_rif_id, saddr4,
@@ -1579,7 +1662,7 @@ mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, u16 ul_vr_id,
case MLXSW_SP_L3_PROTO_IPV6:
saddr6 = &lb_cf.saddr.addr6;
mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
- rif->rif_index, rif->vr_id, rif->dev->mtu);
+ rif->rif_index, rif->vr_id, dev->mtu);
mlxsw_reg_ritr_loopback_ipip6_pack(ritr_pl, lb_cf.lb_ipipt,
ipip_options, ul_vr_id,
ul_rif_id, saddr6,
@@ -1639,9 +1722,29 @@ static void mlxsw_sp_netdevice_ipip_ol_down_event(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp, ipip_entry);
}
-static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp *mlxsw_sp,
+static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_rif *rif);
+
+static void mlxsw_sp_rif_migrate_destroy(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_rif *old_rif,
- struct mlxsw_sp_rif *new_rif);
+ struct mlxsw_sp_rif *new_rif,
+ bool migrate_nhs)
+{
+ struct mlxsw_sp_crif *crif = old_rif->crif;
+ struct mlxsw_sp_crif mock_crif = {};
+
+ if (migrate_nhs)
+ mlxsw_sp_nexthop_rif_update(mlxsw_sp, new_rif);
+
+ /* Plant a mock CRIF so that destroying the old RIF doesn't unoffload
+ * our nexthops and IPIP tunnels, and doesn't sever the crif->rif link.
+ */
+ mlxsw_sp_crif_init(&mock_crif, crif->key.dev);
+ old_rif->crif = &mock_crif;
+ mock_crif.rif = old_rif;
+ mlxsw_sp_rif_destroy(old_rif);
+}
+
static int
mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_ipip_entry *ipip_entry,
@@ -1659,18 +1762,11 @@ mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp *mlxsw_sp,
return PTR_ERR(new_lb_rif);
ipip_entry->ol_lb = new_lb_rif;
- if (keep_encap)
- mlxsw_sp_nexthop_rif_migrate(mlxsw_sp, &old_lb_rif->common,
- &new_lb_rif->common);
-
- mlxsw_sp_rif_destroy(&old_lb_rif->common);
-
+ mlxsw_sp_rif_migrate_destroy(mlxsw_sp, &old_lb_rif->common,
+ &new_lb_rif->common, keep_encap);
return 0;
}
-static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_rif *rif);
-
/**
* __mlxsw_sp_ipip_entry_update_tunnel - Update offload related to IPIP entry.
* @mlxsw_sp: mlxsw_sp.
@@ -2329,7 +2425,7 @@ static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp *mlxsw_sp,
}
dipn = htonl(dip);
- dev = mlxsw_sp->router->rifs[rif]->dev;
+ dev = mlxsw_sp_rif_dev(mlxsw_sp->router->rifs[rif]);
n = neigh_lookup(&arp_tbl, &dipn, dev);
if (!n)
return;
@@ -2357,7 +2453,7 @@ static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp,
return;
}
- dev = mlxsw_sp->router->rifs[rif]->dev;
+ dev = mlxsw_sp_rif_dev(mlxsw_sp->router->rifs[rif]);
n = neigh_lookup(&nd_tbl, &dip, dev);
if (!n)
return;
@@ -2745,13 +2841,12 @@ static void mlxsw_sp_router_update_priority_work(struct work_struct *work)
}
static int mlxsw_sp_router_schedule_work(struct net *net,
- struct notifier_block *nb,
+ struct mlxsw_sp_router *router,
+ struct neighbour *n,
void (*cb)(struct work_struct *))
{
struct mlxsw_sp_netevent_work *net_work;
- struct mlxsw_sp_router *router;
- router = container_of(nb, struct mlxsw_sp_router, netevent_nb);
if (!net_eq(net, mlxsw_sp_net(router->mlxsw_sp)))
return NOTIFY_DONE;
@@ -2761,19 +2856,31 @@ static int mlxsw_sp_router_schedule_work(struct net *net,
INIT_WORK(&net_work->work, cb);
net_work->mlxsw_sp = router->mlxsw_sp;
+ net_work->n = n;
mlxsw_core_schedule_work(&net_work->work);
return NOTIFY_DONE;
}
+static bool mlxsw_sp_dev_lower_is_port(struct net_device *dev)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port;
+
+ rcu_read_lock();
+ mlxsw_sp_port = mlxsw_sp_port_dev_lower_find_rcu(dev);
+ rcu_read_unlock();
+ return !!mlxsw_sp_port;
+}
+
static int mlxsw_sp_router_netevent_event(struct notifier_block *nb,
unsigned long event, void *ptr)
{
- struct mlxsw_sp_netevent_work *net_work;
- struct mlxsw_sp_port *mlxsw_sp_port;
- struct mlxsw_sp *mlxsw_sp;
+ struct mlxsw_sp_router *router;
unsigned long interval;
struct neigh_parms *p;
struct neighbour *n;
+ struct net *net;
+
+ router = container_of(nb, struct mlxsw_sp_router, netevent_nb);
switch (event) {
case NETEVENT_DELAY_PROBE_TIME_UPDATE:
@@ -2787,51 +2894,37 @@ static int mlxsw_sp_router_netevent_event(struct notifier_block *nb,
/* We are in atomic context and can't take RTNL mutex,
* so use RCU variant to walk the device chain.
*/
- mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(p->dev);
- if (!mlxsw_sp_port)
+ if (!mlxsw_sp_dev_lower_is_port(p->dev))
return NOTIFY_DONE;
- mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
interval = jiffies_to_msecs(NEIGH_VAR(p, DELAY_PROBE_TIME));
- mlxsw_sp->router->neighs_update.interval = interval;
-
- mlxsw_sp_port_dev_put(mlxsw_sp_port);
+ router->neighs_update.interval = interval;
break;
case NETEVENT_NEIGH_UPDATE:
n = ptr;
+ net = neigh_parms_net(n->parms);
if (n->tbl->family != AF_INET && n->tbl->family != AF_INET6)
return NOTIFY_DONE;
- mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(n->dev);
- if (!mlxsw_sp_port)
+ if (!mlxsw_sp_dev_lower_is_port(n->dev))
return NOTIFY_DONE;
- net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC);
- if (!net_work) {
- mlxsw_sp_port_dev_put(mlxsw_sp_port);
- return NOTIFY_BAD;
- }
-
- INIT_WORK(&net_work->work, mlxsw_sp_router_neigh_event_work);
- net_work->mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
- net_work->n = n;
-
/* Take a reference to ensure the neighbour won't be
* destructed until we drop the reference in delayed
* work.
*/
neigh_clone(n);
- mlxsw_core_schedule_work(&net_work->work);
- mlxsw_sp_port_dev_put(mlxsw_sp_port);
- break;
+ return mlxsw_sp_router_schedule_work(net, router, n,
+ mlxsw_sp_router_neigh_event_work);
+
case NETEVENT_IPV4_MPATH_HASH_UPDATE:
case NETEVENT_IPV6_MPATH_HASH_UPDATE:
- return mlxsw_sp_router_schedule_work(ptr, nb,
+ return mlxsw_sp_router_schedule_work(ptr, router, NULL,
mlxsw_sp_router_mp_hash_event_work);
case NETEVENT_IPV4_FWD_UPDATE_PRIORITY_UPDATE:
- return mlxsw_sp_router_schedule_work(ptr, nb,
+ return mlxsw_sp_router_schedule_work(ptr, router, NULL,
mlxsw_sp_router_update_priority_work);
}
@@ -2902,7 +2995,7 @@ struct mlxsw_sp_nexthop_key {
struct mlxsw_sp_nexthop {
struct list_head neigh_list_node; /* member of neigh entry list */
- struct list_head rif_list_node;
+ struct list_head crif_list_node;
struct list_head router_list_node;
struct mlxsw_sp_nexthop_group_info *nhgi; /* pointer back to the group
* this nexthop belongs to
@@ -2915,7 +3008,7 @@ struct mlxsw_sp_nexthop {
int nh_weight;
int norm_nh_weight;
int num_adj_entries;
- struct mlxsw_sp_rif *rif;
+ struct mlxsw_sp_crif *crif;
u8 should_offload:1, /* set indicates this nexthop should be written
* to the adjacency table.
*/
@@ -2935,6 +3028,14 @@ struct mlxsw_sp_nexthop {
bool counter_valid;
};
+static struct net_device *
+mlxsw_sp_nexthop_dev(const struct mlxsw_sp_nexthop *nh)
+{
+ if (!nh->crif)
+ return NULL;
+ return nh->crif->key.dev;
+}
+
enum mlxsw_sp_nexthop_group_type {
MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4,
MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6,
@@ -2952,9 +3053,18 @@ struct mlxsw_sp_nexthop_group_info {
is_resilient:1;
struct list_head list; /* member in nh_res_grp_list */
struct mlxsw_sp_nexthop nexthops[];
-#define nh_rif nexthops[0].rif
};
+static struct mlxsw_sp_rif *
+mlxsw_sp_nhgi_rif(const struct mlxsw_sp_nexthop_group_info *nhgi)
+{
+ struct mlxsw_sp_crif *crif = nhgi->nexthops[0].crif;
+
+ if (!crif)
+ return NULL;
+ return crif->rif;
+}
+
struct mlxsw_sp_nexthop_group_vr_key {
u16 vr_id;
enum mlxsw_sp_l3proto proto;
@@ -3076,7 +3186,9 @@ int mlxsw_sp_nexthop_indexes(struct mlxsw_sp_nexthop *nh, u32 *p_adj_index,
struct mlxsw_sp_rif *mlxsw_sp_nexthop_rif(struct mlxsw_sp_nexthop *nh)
{
- return nh->rif;
+ if (WARN_ON(!nh->crif))
+ return NULL;
+ return nh->crif->rif;
}
bool mlxsw_sp_nexthop_group_has_ipip(struct mlxsw_sp_nexthop *nh)
@@ -3461,11 +3573,12 @@ static int __mlxsw_sp_nexthop_eth_update(struct mlxsw_sp *mlxsw_sp,
bool force, char *ratr_pl)
{
struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
+ struct mlxsw_sp_rif *rif = mlxsw_sp_nexthop_rif(nh);
enum mlxsw_reg_ratr_op op;
u16 rif_index;
- rif_index = nh->rif ? nh->rif->rif_index :
- mlxsw_sp->router->lb_rif_index;
+ rif_index = rif ? rif->rif_index :
+ mlxsw_sp->router->lb_crif->rif->rif_index;
op = force ? MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY :
MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY_ON_ACTIVITY;
mlxsw_reg_ratr_pack(ratr_pl, op, true, MLXSW_REG_RATR_TYPE_ETHERNET,
@@ -4008,16 +4121,18 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp,
{
struct neighbour *n, *old_n = neigh_entry->key.n;
struct mlxsw_sp_nexthop *nh;
+ struct net_device *dev;
bool entry_connected;
u8 nud_state, dead;
int err;
nh = list_first_entry(&neigh_entry->nexthop_list,
struct mlxsw_sp_nexthop, neigh_list_node);
+ dev = mlxsw_sp_nexthop_dev(nh);
- n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev);
+ n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, dev);
if (!n) {
- n = neigh_create(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev);
+ n = neigh_create(nh->neigh_tbl, &nh->gw_addr, dev);
if (IS_ERR(n))
return PTR_ERR(n);
neigh_event_send(n, NULL);
@@ -4081,44 +4196,49 @@ mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp,
}
}
-static void mlxsw_sp_nexthop_rif_init(struct mlxsw_sp_nexthop *nh,
- struct mlxsw_sp_rif *rif)
+static void mlxsw_sp_nexthop_crif_init(struct mlxsw_sp_nexthop *nh,
+ struct mlxsw_sp_crif *crif)
{
- if (nh->rif)
+ if (nh->crif)
return;
- nh->rif = rif;
- list_add(&nh->rif_list_node, &rif->nexthop_list);
+ nh->crif = crif;
+ list_add(&nh->crif_list_node, &crif->nexthop_list);
}
-static void mlxsw_sp_nexthop_rif_fini(struct mlxsw_sp_nexthop *nh)
+static void mlxsw_sp_nexthop_crif_fini(struct mlxsw_sp_nexthop *nh)
{
- if (!nh->rif)
+ if (!nh->crif)
return;
- list_del(&nh->rif_list_node);
- nh->rif = NULL;
+ list_del(&nh->crif_list_node);
+ nh->crif = NULL;
}
static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_nexthop *nh)
{
struct mlxsw_sp_neigh_entry *neigh_entry;
+ struct net_device *dev;
struct neighbour *n;
u8 nud_state, dead;
int err;
+ if (WARN_ON(!nh->crif->rif))
+ return 0;
+
if (!nh->nhgi->gateway || nh->neigh_entry)
return 0;
+ dev = mlxsw_sp_nexthop_dev(nh);
/* Take a reference of neigh here ensuring that neigh would
* not be destructed before the nexthop entry is finished.
* The reference is taken either in neigh_lookup() or
* in neigh_create() in case n is not found.
*/
- n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev);
+ n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, dev);
if (!n) {
- n = neigh_create(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev);
+ n = neigh_create(nh->neigh_tbl, &nh->gw_addr, dev);
if (IS_ERR(n))
return PTR_ERR(n);
neigh_event_send(n, NULL);
@@ -4197,15 +4317,20 @@ static void mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_nexthop *nh,
struct mlxsw_sp_ipip_entry *ipip_entry)
{
+ struct mlxsw_sp_crif *crif;
bool removing;
if (!nh->nhgi->gateway || nh->ipip_entry)
return;
+ crif = mlxsw_sp_crif_lookup(mlxsw_sp->router, ipip_entry->ol_dev);
+ if (WARN_ON(!crif))
+ return;
+
nh->ipip_entry = ipip_entry;
removing = !mlxsw_sp_ipip_netdev_ul_up(ipip_entry->ol_dev);
__mlxsw_sp_nexthop_neigh_update(nh, removing);
- mlxsw_sp_nexthop_rif_init(nh, &ipip_entry->ol_lb->common);
+ mlxsw_sp_nexthop_crif_init(nh, crif);
}
static void mlxsw_sp_nexthop_ipip_fini(struct mlxsw_sp *mlxsw_sp,
@@ -4237,7 +4362,7 @@ static int mlxsw_sp_nexthop_type_init(struct mlxsw_sp *mlxsw_sp,
{
const struct mlxsw_sp_ipip_ops *ipip_ops;
struct mlxsw_sp_ipip_entry *ipip_entry;
- struct mlxsw_sp_rif *rif;
+ struct mlxsw_sp_crif *crif;
int err;
ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, dev);
@@ -4251,11 +4376,15 @@ static int mlxsw_sp_nexthop_type_init(struct mlxsw_sp *mlxsw_sp,
}
nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH;
- rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
- if (!rif)
+ crif = mlxsw_sp_crif_lookup(mlxsw_sp->router, dev);
+ if (!crif)
+ return 0;
+
+ mlxsw_sp_nexthop_crif_init(nh, crif);
+
+ if (!crif->rif)
return 0;
- mlxsw_sp_nexthop_rif_init(nh, rif);
err = mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh);
if (err)
goto err_neigh_init;
@@ -4263,25 +4392,30 @@ static int mlxsw_sp_nexthop_type_init(struct mlxsw_sp *mlxsw_sp,
return 0;
err_neigh_init:
- mlxsw_sp_nexthop_rif_fini(nh);
+ mlxsw_sp_nexthop_crif_fini(nh);
return err;
}
-static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_nexthop *nh)
+static void mlxsw_sp_nexthop_type_rif_gone(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_nexthop *nh)
{
switch (nh->type) {
case MLXSW_SP_NEXTHOP_TYPE_ETH:
mlxsw_sp_nexthop_neigh_fini(mlxsw_sp, nh);
- mlxsw_sp_nexthop_rif_fini(nh);
break;
case MLXSW_SP_NEXTHOP_TYPE_IPIP:
- mlxsw_sp_nexthop_rif_fini(nh);
mlxsw_sp_nexthop_ipip_fini(mlxsw_sp, nh);
break;
}
}
+static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_nexthop *nh)
+{
+ mlxsw_sp_nexthop_type_rif_gone(mlxsw_sp, nh);
+ mlxsw_sp_nexthop_crif_fini(nh);
+}
+
static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_nexthop_group *nh_grp,
struct mlxsw_sp_nexthop *nh,
@@ -4368,16 +4502,17 @@ static void mlxsw_sp_nexthop4_event(struct mlxsw_sp *mlxsw_sp,
static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_rif *rif)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp_nexthop *nh;
bool removing;
- list_for_each_entry(nh, &rif->nexthop_list, rif_list_node) {
+ list_for_each_entry(nh, &rif->crif->nexthop_list, crif_list_node) {
switch (nh->type) {
case MLXSW_SP_NEXTHOP_TYPE_ETH:
removing = false;
break;
case MLXSW_SP_NEXTHOP_TYPE_IPIP:
- removing = !mlxsw_sp_ipip_netdev_ul_up(rif->dev);
+ removing = !mlxsw_sp_ipip_netdev_ul_up(dev);
break;
default:
WARN_ON(1);
@@ -4389,25 +4524,14 @@ static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
}
}
-static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_rif *old_rif,
- struct mlxsw_sp_rif *new_rif)
-{
- struct mlxsw_sp_nexthop *nh;
-
- list_splice_init(&old_rif->nexthop_list, &new_rif->nexthop_list);
- list_for_each_entry(nh, &new_rif->nexthop_list, rif_list_node)
- nh->rif = new_rif;
- mlxsw_sp_nexthop_rif_update(mlxsw_sp, new_rif);
-}
-
static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_rif *rif)
{
struct mlxsw_sp_nexthop *nh, *tmp;
- list_for_each_entry_safe(nh, tmp, &rif->nexthop_list, rif_list_node) {
- mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
+ list_for_each_entry_safe(nh, tmp, &rif->crif->nexthop_list,
+ crif_list_node) {
+ mlxsw_sp_nexthop_type_rif_gone(mlxsw_sp, nh);
mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp);
}
}
@@ -4427,7 +4551,7 @@ static int mlxsw_sp_adj_trap_entry_init(struct mlxsw_sp *mlxsw_sp)
mlxsw_reg_ratr_pack(ratr_pl, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY, true,
MLXSW_REG_RATR_TYPE_ETHERNET,
mlxsw_sp->router->adj_trap_index,
- mlxsw_sp->router->lb_rif_index);
+ mlxsw_sp->router->lb_crif->rif->rif_index);
mlxsw_reg_ratr_trap_action_set(ratr_pl, trap_action);
mlxsw_reg_ratr_trap_id_set(ratr_pl, MLXSW_TRAP_ID_RTR_EGRESS0);
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl);
@@ -4743,21 +4867,19 @@ static bool mlxsw_sp_nexthop_obj_is_gateway(struct mlxsw_sp *mlxsw_sp,
static void mlxsw_sp_nexthop_obj_blackhole_init(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_nexthop *nh)
{
- u16 lb_rif_index = mlxsw_sp->router->lb_rif_index;
-
nh->action = MLXSW_SP_NEXTHOP_ACTION_DISCARD;
nh->should_offload = 1;
/* While nexthops that discard packets do not forward packets
* via an egress RIF, they still need to be programmed using a
* valid RIF, so use the loopback RIF created during init.
*/
- nh->rif = mlxsw_sp->router->rifs[lb_rif_index];
+ nh->crif = mlxsw_sp->router->lb_crif;
}
static void mlxsw_sp_nexthop_obj_blackhole_fini(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_nexthop *nh)
{
- nh->rif = NULL;
+ nh->crif = NULL;
nh->should_offload = 0;
}
@@ -5491,7 +5613,7 @@ mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry)
case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE:
return !!nh_group->nhgi->adj_index_valid;
case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL:
- return !!nh_group->nhgi->nh_rif;
+ return !!mlxsw_sp_nhgi_rif(nh_group->nhgi);
case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE:
case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
case MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP:
@@ -5509,9 +5631,10 @@ mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp,
for (i = 0; i < nh_grp->nhgi->count; i++) {
struct mlxsw_sp_nexthop *nh = &nh_grp->nhgi->nexthops[i];
+ struct net_device *dev = mlxsw_sp_nexthop_dev(nh);
struct fib6_info *rt = mlxsw_sp_rt6->rt;
- if (nh->rif && nh->rif->dev == rt->fib6_nh->fib_nh_dev &&
+ if (dev && dev == rt->fib6_nh->fib_nh_dev &&
ipv6_addr_equal((const struct in6_addr *) &nh->gw_addr,
&rt->fib6_nh->fib_nh_gw6))
return nh;
@@ -5752,7 +5875,8 @@ static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp *mlxsw_sp,
trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
adjacency_index = nhgi->adj_index;
ecmp_size = nhgi->ecmp_size;
- } else if (!nhgi->adj_index_valid && nhgi->count && nhgi->nh_rif) {
+ } else if (!nhgi->adj_index_valid && nhgi->count &&
+ mlxsw_sp_nhgi_rif(nhgi)) {
trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
adjacency_index = mlxsw_sp->router->adj_trap_index;
ecmp_size = 1;
@@ -5771,7 +5895,7 @@ static int mlxsw_sp_fib_entry_op_local(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib_entry *fib_entry,
enum mlxsw_reg_ralue_op op)
{
- struct mlxsw_sp_rif *rif = fib_entry->nh_group->nhgi->nh_rif;
+ struct mlxsw_sp_rif *rif = mlxsw_sp_nhgi_rif(fib_entry->nh_group->nhgi);
enum mlxsw_reg_ralue_trap_action trap_action;
char ralue_pl[MLXSW_REG_RALUE_LEN];
u16 trap_id = 0;
@@ -7298,9 +7422,10 @@ static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp *mlxsw_sp,
static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp)
{
+ int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
int i, j;
- for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
+ for (i = 0; i < max_vrs; i++) {
struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i];
if (!mlxsw_sp_vr_is_used(vr))
@@ -7699,11 +7824,12 @@ static struct mlxsw_sp_rif *
mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
const struct net_device *dev)
{
+ int max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
int i;
- for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
+ for (i = 0; i < max_rifs; i++)
if (mlxsw_sp->router->rifs[i] &&
- mlxsw_sp->router->rifs[i]->dev == dev)
+ mlxsw_sp_rif_dev_is(mlxsw_sp->router->rifs[i], dev))
return mlxsw_sp->router->rifs[i];
return NULL;
@@ -7761,33 +7887,52 @@ static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif)
static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_rif *rif)
{
+ /* Signal to nexthop cleanup that the RIF is going away. */
+ rif->crif->rif = NULL;
+
mlxsw_sp_router_rif_disable(mlxsw_sp, rif->rif_index);
mlxsw_sp_nexthop_rif_gone_sync(mlxsw_sp, rif);
mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp, rif);
}
+static bool __mlxsw_sp_dev_addr_list_empty(const struct net_device *dev)
+{
+ struct inet6_dev *inet6_dev;
+ struct in_device *idev;
+
+ idev = __in_dev_get_rcu(dev);
+ if (idev && idev->ifa_list)
+ return false;
+
+ inet6_dev = __in6_dev_get(dev);
+ if (inet6_dev && !list_empty(&inet6_dev->addr_list))
+ return false;
+
+ return true;
+}
+
+static bool mlxsw_sp_dev_addr_list_empty(const struct net_device *dev)
+{
+ bool addr_list_empty;
+
+ rcu_read_lock();
+ addr_list_empty = __mlxsw_sp_dev_addr_list_empty(dev);
+ rcu_read_unlock();
+
+ return addr_list_empty;
+}
+
static bool
mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif, struct net_device *dev,
unsigned long event)
{
- struct inet6_dev *inet6_dev;
- bool addr_list_empty = true;
- struct in_device *idev;
+ bool addr_list_empty;
switch (event) {
case NETDEV_UP:
return rif == NULL;
case NETDEV_DOWN:
- rcu_read_lock();
- idev = __in_dev_get_rcu(dev);
- if (idev && idev->ifa_list)
- addr_list_empty = false;
-
- inet6_dev = __in6_dev_get(dev);
- if (addr_list_empty && inet6_dev &&
- !list_empty(&inet6_dev->addr_list))
- addr_list_empty = false;
- rcu_read_unlock();
+ addr_list_empty = mlxsw_sp_dev_addr_list_empty(dev);
/* macvlans do not have a RIF, but rather piggy back on the
* RIF of their lower device.
@@ -7796,7 +7941,7 @@ mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif, struct net_device *dev,
return true;
if (rif && addr_list_empty &&
- !netif_is_l3_slave(rif->dev))
+ !netif_is_l3_slave(mlxsw_sp_rif_dev(rif)))
return true;
/* It is possible we already removed the RIF ourselves
* if it was assigned to a netdev that is now a bridge
@@ -7854,27 +7999,39 @@ static void mlxsw_sp_rif_index_free(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index,
u16 vr_id,
- struct net_device *l3_dev)
+ struct mlxsw_sp_crif *crif)
{
+ struct net_device *l3_dev = crif ? crif->key.dev : NULL;
struct mlxsw_sp_rif *rif;
rif = kzalloc(rif_size, GFP_KERNEL);
if (!rif)
return NULL;
- INIT_LIST_HEAD(&rif->nexthop_list);
INIT_LIST_HEAD(&rif->neigh_list);
if (l3_dev) {
ether_addr_copy(rif->addr, l3_dev->dev_addr);
rif->mtu = l3_dev->mtu;
- rif->dev = l3_dev;
}
rif->vr_id = vr_id;
rif->rif_index = rif_index;
+ if (crif) {
+ rif->crif = crif;
+ crif->rif = rif;
+ }
return rif;
}
+static void mlxsw_sp_rif_free(struct mlxsw_sp_rif *rif)
+{
+ WARN_ON(!list_empty(&rif->neigh_list));
+
+ if (rif->crif)
+ rif->crif->rif = NULL;
+ kfree(rif);
+}
+
struct mlxsw_sp_rif *mlxsw_sp_rif_by_index(const struct mlxsw_sp *mlxsw_sp,
u16 rif_index)
{
@@ -7893,7 +8050,8 @@ u16 mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
{
- u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(lb_rif->common.dev);
+ struct net_device *dev = mlxsw_sp_rif_dev(&lb_rif->common);
+ u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(dev);
struct mlxsw_sp_vr *ul_vr;
ul_vr = mlxsw_sp_vr_get(lb_rif->common.mlxsw_sp, ul_tb_id, NULL);
@@ -8070,12 +8228,18 @@ mlxsw_sp_router_hwstats_notify_schedule(struct net_device *dev)
int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif)
{
- return rif->dev->ifindex;
+ return mlxsw_sp_rif_dev(rif)->ifindex;
}
-const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif)
+bool mlxsw_sp_rif_has_dev(const struct mlxsw_sp_rif *rif)
+{
+ return !!mlxsw_sp_rif_dev(rif);
+}
+
+bool mlxsw_sp_rif_dev_is(const struct mlxsw_sp_rif *rif,
+ const struct net_device *dev)
{
- return rif->dev;
+ return mlxsw_sp_rif_dev(rif) == dev;
}
static void mlxsw_sp_rif_push_l3_stats(struct mlxsw_sp_rif *rif)
@@ -8083,7 +8247,7 @@ static void mlxsw_sp_rif_push_l3_stats(struct mlxsw_sp_rif *rif)
struct rtnl_hw_stats64 stats = {};
if (!mlxsw_sp_router_port_l3_stats_fetch(rif, &stats))
- netdev_offload_xstats_push_delta(rif->dev,
+ netdev_offload_xstats_push_delta(mlxsw_sp_rif_dev(rif),
NETDEV_OFFLOAD_XSTATS_TYPE_L3,
&stats);
}
@@ -8098,6 +8262,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_rif_ops *ops;
struct mlxsw_sp_fid *fid = NULL;
enum mlxsw_sp_rif_type type;
+ struct mlxsw_sp_crif *crif;
struct mlxsw_sp_rif *rif;
struct mlxsw_sp_vr *vr;
u16 rif_index;
@@ -8117,12 +8282,18 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
goto err_rif_index_alloc;
}
- rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, params->dev);
+ crif = mlxsw_sp_crif_lookup(mlxsw_sp->router, params->dev);
+ if (WARN_ON(!crif)) {
+ err = -ENOENT;
+ goto err_crif_lookup;
+ }
+
+ rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, crif);
if (!rif) {
err = -ENOMEM;
goto err_rif_alloc;
}
- dev_hold(rif->dev);
+ dev_hold(params->dev);
mlxsw_sp->router->rifs[rif_index] = rif;
rif->mlxsw_sp = mlxsw_sp;
rif->ops = ops;
@@ -8150,12 +8321,12 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
goto err_mr_rif_add;
}
- if (netdev_offload_xstats_enabled(rif->dev,
+ if (netdev_offload_xstats_enabled(params->dev,
NETDEV_OFFLOAD_XSTATS_TYPE_L3)) {
err = mlxsw_sp_router_port_l3_stats_enable(rif);
if (err)
goto err_stats_enable;
- mlxsw_sp_router_hwstats_notify_schedule(rif->dev);
+ mlxsw_sp_router_hwstats_notify_schedule(params->dev);
} else {
mlxsw_sp_rif_counters_alloc(rif);
}
@@ -8173,9 +8344,10 @@ err_configure:
mlxsw_sp_fid_put(fid);
err_fid_get:
mlxsw_sp->router->rifs[rif_index] = NULL;
- dev_put(rif->dev);
- kfree(rif);
+ dev_put(params->dev);
+ mlxsw_sp_rif_free(rif);
err_rif_alloc:
+err_crif_lookup:
mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
err_rif_index_alloc:
vr->rif_count--;
@@ -8185,8 +8357,10 @@ err_rif_index_alloc:
static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
const struct mlxsw_sp_rif_ops *ops = rif->ops;
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
+ struct mlxsw_sp_crif *crif = rif->crif;
struct mlxsw_sp_fid *fid = rif->fid;
u8 rif_entries = rif->rif_entries;
u16 rif_index = rif->rif_index;
@@ -8197,11 +8371,10 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif);
vr = &mlxsw_sp->router->vrs[rif->vr_id];
- if (netdev_offload_xstats_enabled(rif->dev,
- NETDEV_OFFLOAD_XSTATS_TYPE_L3)) {
+ if (netdev_offload_xstats_enabled(dev, NETDEV_OFFLOAD_XSTATS_TYPE_L3)) {
mlxsw_sp_rif_push_l3_stats(rif);
mlxsw_sp_router_port_l3_stats_disable(rif);
- mlxsw_sp_router_hwstats_notify_schedule(rif->dev);
+ mlxsw_sp_router_hwstats_notify_schedule(dev);
} else {
mlxsw_sp_rif_counters_free(rif);
}
@@ -8213,11 +8386,14 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
/* Loopback RIFs are not associated with a FID. */
mlxsw_sp_fid_put(fid);
mlxsw_sp->router->rifs[rif->rif_index] = NULL;
- dev_put(rif->dev);
- kfree(rif);
+ dev_put(dev);
+ mlxsw_sp_rif_free(rif);
mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
vr->rif_count--;
mlxsw_sp_vr_put(mlxsw_sp, vr);
+
+ if (crif->can_destroy)
+ mlxsw_sp_crif_free(crif);
}
void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp,
@@ -8549,25 +8725,20 @@ __mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
mlxsw_sp_rif_subport_put(rif);
}
-int
-mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
- struct net_device *l3_dev,
- struct netlink_ext_ack *extack)
+static int
+mlxsw_sp_port_vlan_router_join_existing(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
+ struct net_device *l3_dev,
+ struct netlink_ext_ack *extack)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port_vlan->mlxsw_sp_port->mlxsw_sp;
- struct mlxsw_sp_rif *rif;
- int err = 0;
- mutex_lock(&mlxsw_sp->router->lock);
- rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
- if (!rif)
- goto out;
+ lockdep_assert_held(&mlxsw_sp->router->lock);
- err = __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan, l3_dev,
- extack);
-out:
- mutex_unlock(&mlxsw_sp->router->lock);
- return err;
+ if (!mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev))
+ return 0;
+
+ return __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan, l3_dev,
+ extack);
}
void
@@ -8874,8 +9045,8 @@ out:
return notifier_from_errno(err);
}
-int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
- unsigned long event, void *ptr)
+static int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
{
struct in_validator_info *ivi = (struct in_validator_info *) ptr;
struct net_device *dev = ivi->ivi_dev->dev;
@@ -8957,8 +9128,8 @@ static int mlxsw_sp_inet6addr_event(struct notifier_block *nb,
return NOTIFY_DONE;
}
-int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
- unsigned long event, void *ptr)
+static int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
{
struct in6_validator_info *i6vi = (struct in6_validator_info *) ptr;
struct net_device *dev = i6vi->i6vi_dev->dev;
@@ -9004,7 +9175,7 @@ mlxsw_sp_router_port_change_event(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_rif *rif,
struct netlink_ext_ack *extack)
{
- struct net_device *dev = rif->dev;
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
u8 old_mac_profile;
u16 fid_index;
int err;
@@ -9088,6 +9259,104 @@ static int mlxsw_sp_router_port_pre_changeaddr_event(struct mlxsw_sp_rif *rif,
return -ENOBUFS;
}
+static bool mlxsw_sp_router_netdevice_interesting(struct mlxsw_sp *mlxsw_sp,
+ struct net_device *dev)
+{
+ struct vlan_dev_priv *vlan;
+
+ if (netif_is_lag_master(dev) ||
+ netif_is_bridge_master(dev) ||
+ mlxsw_sp_port_dev_check(dev) ||
+ mlxsw_sp_netdev_is_ipip_ol(mlxsw_sp, dev) ||
+ netif_is_l3_master(dev))
+ return true;
+
+ if (!is_vlan_dev(dev))
+ return false;
+
+ vlan = vlan_dev_priv(dev);
+ return netif_is_lag_master(vlan->real_dev) ||
+ netif_is_bridge_master(vlan->real_dev) ||
+ mlxsw_sp_port_dev_check(vlan->real_dev);
+}
+
+static struct mlxsw_sp_crif *
+mlxsw_sp_crif_register(struct mlxsw_sp_router *router, struct net_device *dev)
+{
+ struct mlxsw_sp_crif *crif;
+ int err;
+
+ if (WARN_ON(mlxsw_sp_crif_lookup(router, dev)))
+ return NULL;
+
+ crif = mlxsw_sp_crif_alloc(dev);
+ if (!crif)
+ return ERR_PTR(-ENOMEM);
+
+ err = mlxsw_sp_crif_insert(router, crif);
+ if (err)
+ goto err_netdev_insert;
+
+ return crif;
+
+err_netdev_insert:
+ mlxsw_sp_crif_free(crif);
+ return ERR_PTR(err);
+}
+
+static void mlxsw_sp_crif_unregister(struct mlxsw_sp_router *router,
+ struct mlxsw_sp_crif *crif)
+{
+ struct mlxsw_sp_nexthop *nh, *tmp;
+
+ mlxsw_sp_crif_remove(router, crif);
+
+ list_for_each_entry_safe(nh, tmp, &crif->nexthop_list, crif_list_node)
+ mlxsw_sp_nexthop_type_fini(router->mlxsw_sp, nh);
+
+ if (crif->rif)
+ crif->can_destroy = true;
+ else
+ mlxsw_sp_crif_free(crif);
+}
+
+static int mlxsw_sp_netdevice_register(struct mlxsw_sp_router *router,
+ struct net_device *dev)
+{
+ struct mlxsw_sp_crif *crif;
+
+ if (!mlxsw_sp_router_netdevice_interesting(router->mlxsw_sp, dev))
+ return 0;
+
+ crif = mlxsw_sp_crif_register(router, dev);
+ return PTR_ERR_OR_ZERO(crif);
+}
+
+static void mlxsw_sp_netdevice_unregister(struct mlxsw_sp_router *router,
+ struct net_device *dev)
+{
+ struct mlxsw_sp_crif *crif;
+
+ if (!mlxsw_sp_router_netdevice_interesting(router->mlxsw_sp, dev))
+ return;
+
+ /* netdev_run_todo(), by way of netdev_wait_allrefs_any(), rebroadcasts
+ * the NETDEV_UNREGISTER message, so we can get here twice. If that's
+ * what happened, the netdevice state is NETREG_UNREGISTERED. In that
+ * case, we expect to have collected the CRIF already, and warn if it
+ * still exists. Otherwise we expect the CRIF to exist.
+ */
+ crif = mlxsw_sp_crif_lookup(router, dev);
+ if (dev->reg_state == NETREG_UNREGISTERED) {
+ if (!WARN_ON(crif))
+ return;
+ }
+ if (WARN_ON(!crif))
+ return;
+
+ mlxsw_sp_crif_unregister(router, crif);
+}
+
static bool mlxsw_sp_is_offload_xstats_event(unsigned long event)
{
switch (event) {
@@ -9254,6 +9523,46 @@ mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
return err;
}
+static int
+mlxsw_sp_port_vid_router_join_existing(struct mlxsw_sp_port *mlxsw_sp_port,
+ u16 vid, struct net_device *dev,
+ struct netlink_ext_ack *extack)
+{
+ struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
+
+ mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port,
+ vid);
+ if (WARN_ON(!mlxsw_sp_port_vlan))
+ return -EINVAL;
+
+ return mlxsw_sp_port_vlan_router_join_existing(mlxsw_sp_port_vlan,
+ dev, extack);
+}
+
+static int __mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct net_device *lag_dev,
+ struct netlink_ext_ack *extack)
+{
+ u16 default_vid = MLXSW_SP_DEFAULT_VID;
+
+ return mlxsw_sp_port_vid_router_join_existing(mlxsw_sp_port,
+ default_vid, lag_dev,
+ extack);
+}
+
+int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct net_device *lag_dev,
+ struct netlink_ext_ack *extack)
+{
+ int err;
+
+ mutex_lock(&mlxsw_sp_port->mlxsw_sp->router->lock);
+ err = __mlxsw_sp_router_port_join_lag(mlxsw_sp_port, lag_dev, extack);
+ mutex_unlock(&mlxsw_sp_port->mlxsw_sp->router->lock);
+
+ return err;
+}
+
static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb,
unsigned long event, void *ptr)
{
@@ -9267,6 +9576,15 @@ static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb,
mutex_lock(&mlxsw_sp->router->lock);
+ if (event == NETDEV_REGISTER) {
+ err = mlxsw_sp_netdevice_register(router, dev);
+ if (err)
+ /* No need to roll this back, UNREGISTER will collect it
+ * anyhow.
+ */
+ goto out;
+ }
+
if (mlxsw_sp_is_offload_xstats_event(event))
err = mlxsw_sp_netdevice_offload_xstats_cmd(mlxsw_sp, dev,
event, ptr);
@@ -9281,6 +9599,10 @@ static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb,
else if (mlxsw_sp_is_vrf_event(event, ptr))
err = mlxsw_sp_netdevice_vrf_event(dev, event, ptr);
+ if (event == NETDEV_UNREGISTER)
+ mlxsw_sp_netdevice_unregister(router, dev);
+
+out:
mutex_unlock(&mlxsw_sp->router->lock);
return notifier_from_errno(err);
@@ -9300,15 +9622,16 @@ static int __mlxsw_sp_rif_macvlan_flush(struct net_device *dev,
static int mlxsw_sp_rif_macvlan_flush(struct mlxsw_sp_rif *rif)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
struct netdev_nested_priv priv = {
.data = (void *)rif,
};
- if (!netif_is_macvlan_port(rif->dev))
+ if (!netif_is_macvlan_port(dev))
return 0;
- netdev_warn(rif->dev, "Router interface is deleted. Upper macvlans will not work\n");
- return netdev_walk_all_upper_dev_rcu(rif->dev,
+ netdev_warn(dev, "Router interface is deleted. Upper macvlans will not work\n");
+ return netdev_walk_all_upper_dev_rcu(dev,
__mlxsw_sp_rif_macvlan_flush, &priv);
}
@@ -9329,6 +9652,7 @@ static void mlxsw_sp_rif_subport_setup(struct mlxsw_sp_rif *rif,
static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
struct mlxsw_sp_rif_subport *rif_subport;
char ritr_pl[MLXSW_REG_RITR_LEN];
@@ -9336,8 +9660,8 @@ static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable)
rif_subport = mlxsw_sp_rif_subport_rif(rif);
mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_SP_IF,
- rif->rif_index, rif->vr_id, rif->dev->mtu);
- mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr);
+ rif->rif_index, rif->vr_id, dev->mtu);
+ mlxsw_reg_ritr_mac_pack(ritr_pl, dev->dev_addr);
mlxsw_reg_ritr_if_mac_profile_id_set(ritr_pl, rif->mac_profile_id);
efid = mlxsw_sp_fid_index(rif->fid);
mlxsw_reg_ritr_sp_if_pack(ritr_pl, rif_subport->lag,
@@ -9350,6 +9674,7 @@ static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable)
static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif,
struct netlink_ext_ack *extack)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
u8 mac_profile;
int err;
@@ -9363,7 +9688,7 @@ static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif,
if (err)
goto err_rif_subport_op;
- err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(rif->fid), true);
if (err)
goto err_rif_fdb_op;
@@ -9375,7 +9700,7 @@ static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif,
return 0;
err_fid_rif_set:
- mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(rif->fid), false);
err_rif_fdb_op:
mlxsw_sp_rif_subport_op(rif, false);
@@ -9386,10 +9711,11 @@ err_rif_subport_op:
static void mlxsw_sp_rif_subport_deconfigure(struct mlxsw_sp_rif *rif)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp_fid *fid = rif->fid;
mlxsw_sp_fid_rif_unset(fid);
- mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(fid), false);
mlxsw_sp_rif_macvlan_flush(rif);
mlxsw_sp_rif_subport_op(rif, false);
@@ -9415,12 +9741,13 @@ static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_subport_ops = {
static int mlxsw_sp_rif_fid_op(struct mlxsw_sp_rif *rif, u16 fid, bool enable)
{
enum mlxsw_reg_ritr_if_type type = MLXSW_REG_RITR_FID_IF;
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
char ritr_pl[MLXSW_REG_RITR_LEN];
mlxsw_reg_ritr_pack(ritr_pl, enable, type, rif->rif_index, rif->vr_id,
- rif->dev->mtu);
- mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr);
+ dev->mtu);
+ mlxsw_reg_ritr_mac_pack(ritr_pl, dev->dev_addr);
mlxsw_reg_ritr_if_mac_profile_id_set(ritr_pl, rif->mac_profile_id);
mlxsw_reg_ritr_fid_if_fid_set(ritr_pl, fid);
@@ -9435,6 +9762,7 @@ u16 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp)
static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif,
struct netlink_ext_ack *extack)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
u16 fid_index = mlxsw_sp_fid_index(rif->fid);
u8 mac_profile;
@@ -9460,7 +9788,7 @@ static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif,
if (err)
goto err_fid_bc_flood_set;
- err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(rif->fid), true);
if (err)
goto err_rif_fdb_op;
@@ -9472,7 +9800,7 @@ static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif,
return 0;
err_fid_rif_set:
- mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(rif->fid), false);
err_rif_fdb_op:
mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
@@ -9489,12 +9817,13 @@ err_rif_fid_op:
static void mlxsw_sp_rif_fid_deconfigure(struct mlxsw_sp_rif *rif)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
u16 fid_index = mlxsw_sp_fid_index(rif->fid);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
struct mlxsw_sp_fid *fid = rif->fid;
mlxsw_sp_fid_rif_unset(fid);
- mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(fid), false);
mlxsw_sp_rif_macvlan_flush(rif);
mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
@@ -9509,7 +9838,9 @@ static struct mlxsw_sp_fid *
mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif *rif,
struct netlink_ext_ack *extack)
{
- return mlxsw_sp_fid_8021d_get(rif->mlxsw_sp, rif->dev->ifindex);
+ int rif_ifindex = mlxsw_sp_rif_dev_ifindex(rif);
+
+ return mlxsw_sp_fid_8021d_get(rif->mlxsw_sp, rif_ifindex);
}
static void mlxsw_sp_rif_fid_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
@@ -9517,7 +9848,7 @@ static void mlxsw_sp_rif_fid_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
struct switchdev_notifier_fdb_info info = {};
struct net_device *dev;
- dev = br_fdb_find_port(rif->dev, mac, 0);
+ dev = br_fdb_find_port(mlxsw_sp_rif_dev(rif), mac, 0);
if (!dev)
return;
@@ -9540,17 +9871,18 @@ static struct mlxsw_sp_fid *
mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif,
struct netlink_ext_ack *extack)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
struct net_device *br_dev;
u16 vid;
int err;
- if (is_vlan_dev(rif->dev)) {
- vid = vlan_dev_vlan_id(rif->dev);
- br_dev = vlan_dev_real_dev(rif->dev);
+ if (is_vlan_dev(dev)) {
+ vid = vlan_dev_vlan_id(dev);
+ br_dev = vlan_dev_real_dev(dev);
if (WARN_ON(!netif_is_bridge_master(br_dev)))
return ERR_PTR(-EINVAL);
} else {
- err = br_vlan_get_pvid(rif->dev, &vid);
+ err = br_vlan_get_pvid(dev, &vid);
if (err < 0 || !vid) {
NL_SET_ERR_MSG_MOD(extack, "Couldn't determine bridge PVID");
return ERR_PTR(-EINVAL);
@@ -9562,12 +9894,13 @@ mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif,
static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
{
+ struct net_device *rif_dev = mlxsw_sp_rif_dev(rif);
struct switchdev_notifier_fdb_info info = {};
u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
struct net_device *br_dev;
struct net_device *dev;
- br_dev = is_vlan_dev(rif->dev) ? vlan_dev_real_dev(rif->dev) : rif->dev;
+ br_dev = is_vlan_dev(rif_dev) ? vlan_dev_real_dev(rif_dev) : rif_dev;
dev = br_fdb_find_port(br_dev, mac, vid);
if (!dev)
return;
@@ -9581,11 +9914,12 @@ static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
static int mlxsw_sp_rif_vlan_op(struct mlxsw_sp_rif *rif, u16 vid, u16 efid,
bool enable)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
char ritr_pl[MLXSW_REG_RITR_LEN];
mlxsw_reg_ritr_vlan_if_pack(ritr_pl, enable, rif->rif_index, rif->vr_id,
- rif->dev->mtu, rif->dev->dev_addr,
+ dev->mtu, dev->dev_addr,
rif->mac_profile_id, vid, efid);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
@@ -9594,6 +9928,7 @@ static int mlxsw_sp_rif_vlan_op(struct mlxsw_sp_rif *rif, u16 vid, u16 efid,
static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif, u16 efid,
struct netlink_ext_ack *extack)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
u8 mac_profile;
@@ -9619,7 +9954,7 @@ static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif, u16 efid,
if (err)
goto err_fid_bc_flood_set;
- err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(rif->fid), true);
if (err)
goto err_rif_fdb_op;
@@ -9631,7 +9966,7 @@ static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif, u16 efid,
return 0;
err_fid_rif_set:
- mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(rif->fid), false);
err_rif_fdb_op:
mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
@@ -9648,11 +9983,12 @@ err_rif_vlan_fid_op:
static void mlxsw_sp_rif_vlan_deconfigure(struct mlxsw_sp_rif *rif)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
mlxsw_sp_fid_rif_unset(rif->fid);
- mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(rif->fid), false);
mlxsw_sp_rif_macvlan_flush(rif);
mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
@@ -9719,12 +10055,13 @@ mlxsw_sp1_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif,
struct netlink_ext_ack *extack)
{
struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
- u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev);
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
+ u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(dev);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
struct mlxsw_sp_vr *ul_vr;
int err;
- ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id, NULL);
+ ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id, extack);
if (IS_ERR(ul_vr))
return PTR_ERR(ul_vr);
@@ -9786,6 +10123,7 @@ mlxsw_sp_rif_ipip_lb_ul_rif_op(struct mlxsw_sp_rif *ul_rif, bool enable)
static struct mlxsw_sp_rif *
mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr,
+ struct mlxsw_sp_crif *ul_crif,
struct netlink_ext_ack *extack)
{
struct mlxsw_sp_rif *ul_rif;
@@ -9799,7 +10137,8 @@ mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr,
return ERR_PTR(err);
}
- ul_rif = mlxsw_sp_rif_alloc(sizeof(*ul_rif), rif_index, vr->id, NULL);
+ ul_rif = mlxsw_sp_rif_alloc(sizeof(*ul_rif), rif_index, vr->id,
+ ul_crif);
if (!ul_rif) {
err = -ENOMEM;
goto err_rif_alloc;
@@ -9817,7 +10156,7 @@ mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr,
ul_rif_op_err:
mlxsw_sp->router->rifs[rif_index] = NULL;
- kfree(ul_rif);
+ mlxsw_sp_rif_free(ul_rif);
err_rif_alloc:
mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
return ERR_PTR(err);
@@ -9832,12 +10171,13 @@ static void mlxsw_sp_ul_rif_destroy(struct mlxsw_sp_rif *ul_rif)
atomic_sub(rif_entries, &mlxsw_sp->router->rifs_count);
mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif, false);
mlxsw_sp->router->rifs[ul_rif->rif_index] = NULL;
- kfree(ul_rif);
+ mlxsw_sp_rif_free(ul_rif);
mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
}
static struct mlxsw_sp_rif *
mlxsw_sp_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
+ struct mlxsw_sp_crif *ul_crif,
struct netlink_ext_ack *extack)
{
struct mlxsw_sp_vr *vr;
@@ -9850,7 +10190,7 @@ mlxsw_sp_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
if (refcount_inc_not_zero(&vr->ul_rif_refcnt))
return vr->ul_rif;
- vr->ul_rif = mlxsw_sp_ul_rif_create(mlxsw_sp, vr, extack);
+ vr->ul_rif = mlxsw_sp_ul_rif_create(mlxsw_sp, vr, ul_crif, extack);
if (IS_ERR(vr->ul_rif)) {
err = PTR_ERR(vr->ul_rif);
goto err_ul_rif_create;
@@ -9888,7 +10228,7 @@ int mlxsw_sp_router_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
int err = 0;
mutex_lock(&mlxsw_sp->router->lock);
- ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL);
+ ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL, NULL);
if (IS_ERR(ul_rif)) {
err = PTR_ERR(ul_rif);
goto out;
@@ -9918,12 +10258,13 @@ mlxsw_sp2_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif,
struct netlink_ext_ack *extack)
{
struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
- u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev);
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
+ u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(dev);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
struct mlxsw_sp_rif *ul_rif;
int err;
- ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL);
+ ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL, extack);
if (IS_ERR(ul_rif))
return PTR_ERR(ul_rif);
@@ -10041,11 +10382,12 @@ err_rifs_table_init:
static void mlxsw_sp_rifs_fini(struct mlxsw_sp *mlxsw_sp)
{
+ int max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
int i;
WARN_ON_ONCE(atomic_read(&mlxsw_sp->router->rifs_count));
- for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
+ for (i = 0; i < max_rifs; i++)
WARN_ON_ONCE(mlxsw_sp->router->rifs[i]);
devl_resource_occ_get_unregister(devlink, MLXSW_SP_RESOURCE_RIFS);
@@ -10444,28 +10786,41 @@ static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
}
-static int mlxsw_sp_lb_rif_init(struct mlxsw_sp *mlxsw_sp)
+static int mlxsw_sp_lb_rif_init(struct mlxsw_sp *mlxsw_sp,
+ struct netlink_ext_ack *extack)
{
- u16 lb_rif_index;
+ struct mlxsw_sp_router *router = mlxsw_sp->router;
+ struct mlxsw_sp_rif *lb_rif;
int err;
+ router->lb_crif = mlxsw_sp_crif_alloc(NULL);
+ if (!router->lb_crif)
+ return -ENOMEM;
+
/* Create a generic loopback RIF associated with the main table
* (default VRF). Any table can be used, but the main table exists
- * anyway, so we do not waste resources.
+ * anyway, so we do not waste resources. Loopback RIFs are usually
+ * created with a NULL CRIF, but this RIF is used as a fallback RIF
+ * for blackhole nexthops, and nexthops expect to have a valid CRIF.
*/
- err = mlxsw_sp_router_ul_rif_get(mlxsw_sp, RT_TABLE_MAIN,
- &lb_rif_index);
- if (err)
- return err;
-
- mlxsw_sp->router->lb_rif_index = lb_rif_index;
+ lb_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, RT_TABLE_MAIN, router->lb_crif,
+ extack);
+ if (IS_ERR(lb_rif)) {
+ err = PTR_ERR(lb_rif);
+ goto err_ul_rif_get;
+ }
return 0;
+
+err_ul_rif_get:
+ mlxsw_sp_crif_free(router->lb_crif);
+ return err;
}
static void mlxsw_sp_lb_rif_fini(struct mlxsw_sp *mlxsw_sp)
{
- mlxsw_sp_router_ul_rif_put(mlxsw_sp, mlxsw_sp->router->lb_rif_index);
+ mlxsw_sp_ul_rif_put(mlxsw_sp->router->lb_crif->rif);
+ mlxsw_sp_crif_free(mlxsw_sp->router->lb_crif);
}
static int mlxsw_sp1_router_init(struct mlxsw_sp *mlxsw_sp)
@@ -10504,6 +10859,7 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
struct netlink_ext_ack *extack)
{
struct mlxsw_sp_router *router;
+ struct notifier_block *nb;
int err;
router = kzalloc(sizeof(*mlxsw_sp->router), GFP_KERNEL);
@@ -10525,14 +10881,19 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
if (err)
goto err_router_init;
- err = mlxsw_sp_rifs_init(mlxsw_sp);
- if (err)
- goto err_rifs_init;
-
err = mlxsw_sp->router_ops->ipips_init(mlxsw_sp);
if (err)
goto err_ipips_init;
+ err = rhashtable_init(&mlxsw_sp->router->crif_ht,
+ &mlxsw_sp_crif_ht_params);
+ if (err)
+ goto err_crif_ht_init;
+
+ err = mlxsw_sp_rifs_init(mlxsw_sp);
+ if (err)
+ goto err_rifs_init;
+
err = rhashtable_init(&mlxsw_sp->router->nexthop_ht,
&mlxsw_sp_nexthop_ht_params);
if (err)
@@ -10556,7 +10917,7 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
if (err)
goto err_vrs_init;
- err = mlxsw_sp_lb_rif_init(mlxsw_sp);
+ err = mlxsw_sp_lb_rif_init(mlxsw_sp, extack);
if (err)
goto err_lb_rif_init;
@@ -10582,6 +10943,17 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
if (err)
goto err_register_inet6addr_notifier;
+ router->inetaddr_valid_nb.notifier_call = mlxsw_sp_inetaddr_valid_event;
+ err = register_inetaddr_validator_notifier(&router->inetaddr_valid_nb);
+ if (err)
+ goto err_register_inetaddr_valid_notifier;
+
+ nb = &router->inet6addr_valid_nb;
+ nb->notifier_call = mlxsw_sp_inet6addr_valid_event;
+ err = register_inet6addr_validator_notifier(nb);
+ if (err)
+ goto err_register_inet6addr_valid_notifier;
+
mlxsw_sp->router->netevent_nb.notifier_call =
mlxsw_sp_router_netevent_event;
err = register_netevent_notifier(&mlxsw_sp->router->netevent_nb);
@@ -10621,6 +10993,10 @@ err_register_fib_notifier:
err_register_nexthop_notifier:
unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb);
err_register_netevent_notifier:
+ unregister_inet6addr_validator_notifier(&router->inet6addr_valid_nb);
+err_register_inet6addr_valid_notifier:
+ unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb);
+err_register_inetaddr_valid_notifier:
unregister_inet6addr_notifier(&router->inet6addr_nb);
err_register_inet6addr_notifier:
unregister_inetaddr_notifier(&router->inetaddr_nb);
@@ -10643,10 +11019,12 @@ err_lpm_init:
err_nexthop_group_ht_init:
rhashtable_destroy(&mlxsw_sp->router->nexthop_ht);
err_nexthop_ht_init:
- mlxsw_sp_ipips_fini(mlxsw_sp);
-err_ipips_init:
mlxsw_sp_rifs_fini(mlxsw_sp);
err_rifs_init:
+ rhashtable_destroy(&mlxsw_sp->router->crif_ht);
+err_crif_ht_init:
+ mlxsw_sp_ipips_fini(mlxsw_sp);
+err_ipips_init:
__mlxsw_sp_router_fini(mlxsw_sp);
err_router_init:
cancel_delayed_work_sync(&mlxsw_sp->router->nh_grp_activity_dw);
@@ -10658,15 +11036,18 @@ err_router_ops_init:
void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
{
+ struct mlxsw_sp_router *router = mlxsw_sp->router;
+
unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
- &mlxsw_sp->router->netdevice_nb);
- unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp),
- &mlxsw_sp->router->fib_nb);
+ &router->netdevice_nb);
+ unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp), &router->fib_nb);
unregister_nexthop_notifier(mlxsw_sp_net(mlxsw_sp),
- &mlxsw_sp->router->nexthop_nb);
- unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb);
- unregister_inet6addr_notifier(&mlxsw_sp->router->inet6addr_nb);
- unregister_inetaddr_notifier(&mlxsw_sp->router->inetaddr_nb);
+ &router->nexthop_nb);
+ unregister_netevent_notifier(&router->netevent_nb);
+ unregister_inet6addr_validator_notifier(&router->inet6addr_valid_nb);
+ unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb);
+ unregister_inet6addr_notifier(&router->inet6addr_nb);
+ unregister_inetaddr_notifier(&router->inetaddr_nb);
mlxsw_core_flush_owq();
mlxsw_sp_mp_hash_fini(mlxsw_sp);
mlxsw_sp_neigh_fini(mlxsw_sp);
@@ -10674,12 +11055,13 @@ void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
mlxsw_sp_vrs_fini(mlxsw_sp);
mlxsw_sp_mr_fini(mlxsw_sp);
mlxsw_sp_lpm_fini(mlxsw_sp);
- rhashtable_destroy(&mlxsw_sp->router->nexthop_group_ht);
- rhashtable_destroy(&mlxsw_sp->router->nexthop_ht);
- mlxsw_sp_ipips_fini(mlxsw_sp);
+ rhashtable_destroy(&router->nexthop_group_ht);
+ rhashtable_destroy(&router->nexthop_ht);
mlxsw_sp_rifs_fini(mlxsw_sp);
+ rhashtable_destroy(&mlxsw_sp->router->crif_ht);
+ mlxsw_sp_ipips_fini(mlxsw_sp);
__mlxsw_sp_router_fini(mlxsw_sp);
- cancel_delayed_work_sync(&mlxsw_sp->router->nh_grp_activity_dw);
- mutex_destroy(&mlxsw_sp->router->lock);
- kfree(mlxsw_sp->router);
+ cancel_delayed_work_sync(&router->nh_grp_activity_dw);
+ mutex_destroy(&router->lock);
+ kfree(router);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
index 37d6e4c80e6a..9a2669a08480 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
@@ -20,6 +20,7 @@ struct mlxsw_sp_router_nve_decap {
struct mlxsw_sp_router {
struct mlxsw_sp *mlxsw_sp;
+ struct rhashtable crif_ht;
struct gen_pool *rifs_table;
struct mlxsw_sp_rif **rifs;
struct idr rif_mac_profiles_idr;
@@ -52,12 +53,14 @@ struct mlxsw_sp_router {
struct notifier_block inetaddr_nb;
struct notifier_block inet6addr_nb;
struct notifier_block netdevice_nb;
+ struct notifier_block inetaddr_valid_nb;
+ struct notifier_block inet6addr_valid_nb;
const struct mlxsw_sp_rif_ops **rif_ops_arr;
const struct mlxsw_sp_ipip_ops **ipip_ops_arr;
struct mlxsw_sp_router_nve_decap nve_decap_config;
struct mutex lock; /* Protects shared router resources */
struct mlxsw_sp_fib_entry_op_ctx *ll_op_ctx;
- u16 lb_rif_index;
+ struct mlxsw_sp_crif *lb_crif;
const struct mlxsw_sp_adj_grp_size_range *adj_grp_size_ranges;
size_t adj_grp_size_ranges_count;
struct delayed_work nh_grp_activity_dw;
@@ -91,7 +94,9 @@ u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *rif);
u16 mlxsw_sp_ipip_lb_ul_rif_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif);
u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev);
int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif);
-const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif);
+bool mlxsw_sp_rif_has_dev(const struct mlxsw_sp_rif *rif);
+bool mlxsw_sp_rif_dev_is(const struct mlxsw_sp_rif *rif,
+ const struct net_device *dev);
int mlxsw_sp_rif_counter_value_get(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_rif *rif,
enum mlxsw_sp_rif_counter_dir dir,
@@ -166,5 +171,8 @@ int mlxsw_sp_ipip_ecn_encap_init(struct mlxsw_sp *mlxsw_sp);
int mlxsw_sp_ipip_ecn_decap_init(struct mlxsw_sp *mlxsw_sp);
struct net_device *
mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device *ol_dev);
+int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct net_device *lag_dev,
+ struct netlink_ext_ack *extack);
#endif /* _MLXSW_ROUTER_H_*/
diff --git a/drivers/net/ethernet/microchip/Kconfig b/drivers/net/ethernet/microchip/Kconfig
index 24c994baad13..329e374b9539 100644
--- a/drivers/net/ethernet/microchip/Kconfig
+++ b/drivers/net/ethernet/microchip/Kconfig
@@ -46,7 +46,7 @@ config LAN743X
tristate "LAN743x support"
depends on PCI
depends on PTP_1588_CLOCK_OPTIONAL
- select PHYLIB
+ select FIXED_PHY
select CRC16
select CRC32
help
diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c
index 176efbeae127..d6c9491537e4 100644
--- a/drivers/net/ethernet/microchip/enc28j60.c
+++ b/drivers/net/ethernet/microchip/enc28j60.c
@@ -58,7 +58,6 @@ struct enc28j60_net {
struct mutex lock;
struct sk_buff *tx_skb;
struct work_struct tx_work;
- struct work_struct irq_work;
struct work_struct setrx_work;
struct work_struct restart_work;
u8 bank; /* current register bank selected */
@@ -1118,10 +1117,9 @@ static int enc28j60_rx_interrupt(struct net_device *ndev)
return ret;
}
-static void enc28j60_irq_work_handler(struct work_struct *work)
+static irqreturn_t enc28j60_irq(int irq, void *dev_id)
{
- struct enc28j60_net *priv =
- container_of(work, struct enc28j60_net, irq_work);
+ struct enc28j60_net *priv = dev_id;
struct net_device *ndev = priv->netdev;
int intflags, loop;
@@ -1225,6 +1223,8 @@ static void enc28j60_irq_work_handler(struct work_struct *work)
/* re-enable interrupts */
locked_reg_bfset(priv, EIE, EIE_INTIE);
+
+ return IRQ_HANDLED;
}
/*
@@ -1309,22 +1309,6 @@ static void enc28j60_tx_work_handler(struct work_struct *work)
enc28j60_hw_tx(priv);
}
-static irqreturn_t enc28j60_irq(int irq, void *dev_id)
-{
- struct enc28j60_net *priv = dev_id;
-
- /*
- * Can't do anything in interrupt context because we need to
- * block (spi_sync() is blocking) so fire of the interrupt
- * handling workqueue.
- * Remember that we access enc28j60 registers through SPI bus
- * via spi_sync() call.
- */
- schedule_work(&priv->irq_work);
-
- return IRQ_HANDLED;
-}
-
static void enc28j60_tx_timeout(struct net_device *ndev, unsigned int txqueue)
{
struct enc28j60_net *priv = netdev_priv(ndev);
@@ -1559,7 +1543,6 @@ static int enc28j60_probe(struct spi_device *spi)
mutex_init(&priv->lock);
INIT_WORK(&priv->tx_work, enc28j60_tx_work_handler);
INIT_WORK(&priv->setrx_work, enc28j60_setrx_work_handler);
- INIT_WORK(&priv->irq_work, enc28j60_irq_work_handler);
INIT_WORK(&priv->restart_work, enc28j60_restart_work_handler);
spi_set_drvdata(spi, priv); /* spi to priv reference */
SET_NETDEV_DEV(dev, &spi->dev);
@@ -1578,7 +1561,8 @@ static int enc28j60_probe(struct spi_device *spi)
/* Board setup must set the relevant edge trigger type;
* level triggers won't currently work.
*/
- ret = request_irq(spi->irq, enc28j60_irq, 0, DRV_NAME, priv);
+ ret = request_threaded_irq(spi->irq, NULL, enc28j60_irq, IRQF_ONESHOT,
+ DRV_NAME, priv);
if (ret < 0) {
if (netif_msg_probe(priv))
dev_err(&spi->dev, "request irq %d failed (ret = %d)\n",
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index 957d96a91a8a..a36f6369f132 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -144,6 +144,18 @@ static int lan743x_csr_light_reset(struct lan743x_adapter *adapter)
!(data & HW_CFG_LRST_), 100000, 10000000);
}
+static int lan743x_csr_wait_for_bit_atomic(struct lan743x_adapter *adapter,
+ int offset, u32 bit_mask,
+ int target_value, int udelay_min,
+ int udelay_max, int count)
+{
+ u32 data;
+
+ return readx_poll_timeout_atomic(LAN743X_CSR_READ_OP, offset, data,
+ target_value == !!(data & bit_mask),
+ udelay_max, udelay_min * count);
+}
+
static int lan743x_csr_wait_for_bit(struct lan743x_adapter *adapter,
int offset, u32 bit_mask,
int target_value, int usleep_min,
@@ -152,7 +164,7 @@ static int lan743x_csr_wait_for_bit(struct lan743x_adapter *adapter,
u32 data;
return readx_poll_timeout(LAN743X_CSR_READ_OP, offset, data,
- target_value == ((data & bit_mask) ? 1 : 0),
+ target_value == !!(data & bit_mask),
usleep_max, usleep_min * count);
}
@@ -160,16 +172,13 @@ static int lan743x_csr_init(struct lan743x_adapter *adapter)
{
struct lan743x_csr *csr = &adapter->csr;
resource_size_t bar_start, bar_length;
- int result;
bar_start = pci_resource_start(adapter->pdev, 0);
bar_length = pci_resource_len(adapter->pdev, 0);
csr->csr_address = devm_ioremap(&adapter->pdev->dev,
bar_start, bar_length);
- if (!csr->csr_address) {
- result = -ENOMEM;
- goto clean_up;
- }
+ if (!csr->csr_address)
+ return -ENOMEM;
csr->id_rev = lan743x_csr_read(adapter, ID_REV);
csr->fpga_rev = lan743x_csr_read(adapter, FPGA_REV);
@@ -177,10 +186,8 @@ static int lan743x_csr_init(struct lan743x_adapter *adapter)
"ID_REV = 0x%08X, FPGA_REV = %d.%d\n",
csr->id_rev, FPGA_REV_GET_MAJOR_(csr->fpga_rev),
FPGA_REV_GET_MINOR_(csr->fpga_rev));
- if (!ID_REV_IS_VALID_CHIP_ID_(csr->id_rev)) {
- result = -ENODEV;
- goto clean_up;
- }
+ if (!ID_REV_IS_VALID_CHIP_ID_(csr->id_rev))
+ return -ENODEV;
csr->flags = LAN743X_CSR_FLAG_SUPPORTS_INTR_AUTO_SET_CLR;
switch (csr->id_rev & ID_REV_CHIP_REV_MASK_) {
@@ -193,12 +200,7 @@ static int lan743x_csr_init(struct lan743x_adapter *adapter)
break;
}
- result = lan743x_csr_light_reset(adapter);
- if (result)
- goto clean_up;
- return 0;
-clean_up:
- return result;
+ return lan743x_csr_light_reset(adapter);
}
static void lan743x_intr_software_isr(struct lan743x_adapter *adapter)
@@ -746,8 +748,8 @@ static int lan743x_dp_write(struct lan743x_adapter *adapter,
u32 dp_sel;
int i;
- if (lan743x_csr_wait_for_bit(adapter, DP_SEL, DP_SEL_DPRDY_,
- 1, 40, 100, 100))
+ if (lan743x_csr_wait_for_bit_atomic(adapter, DP_SEL, DP_SEL_DPRDY_,
+ 1, 40, 100, 100))
return -EIO;
dp_sel = lan743x_csr_read(adapter, DP_SEL);
dp_sel &= ~DP_SEL_MASK_;
@@ -758,8 +760,9 @@ static int lan743x_dp_write(struct lan743x_adapter *adapter,
lan743x_csr_write(adapter, DP_ADDR, addr + i);
lan743x_csr_write(adapter, DP_DATA_0, buf[i]);
lan743x_csr_write(adapter, DP_CMD, DP_CMD_WRITE_);
- if (lan743x_csr_wait_for_bit(adapter, DP_SEL, DP_SEL_DPRDY_,
- 1, 40, 100, 100))
+ if (lan743x_csr_wait_for_bit_atomic(adapter, DP_SEL,
+ DP_SEL_DPRDY_,
+ 1, 40, 100, 100))
return -EIO;
}
diff --git a/drivers/net/ethernet/microchip/lan966x/Kconfig b/drivers/net/ethernet/microchip/lan966x/Kconfig
index 571e6d4da1e9..f9ebffc04eb8 100644
--- a/drivers/net/ethernet/microchip/lan966x/Kconfig
+++ b/drivers/net/ethernet/microchip/lan966x/Kconfig
@@ -10,3 +10,14 @@ config LAN966X_SWITCH
select VCAP
help
This driver supports the Lan966x network switch device.
+
+config LAN966X_DCB
+ bool "Data Center Bridging (DCB) support"
+ depends on LAN966X_SWITCH && DCB
+ default y
+ help
+ Say Y here if you want to use Data Center Bridging (DCB) in the
+ driver. This can be used to assign priority to traffic, based on
+ DSCP and PCP.
+
+ If unsure, set to Y.
diff --git a/drivers/net/ethernet/microchip/lan966x/Makefile b/drivers/net/ethernet/microchip/lan966x/Makefile
index 7b0cda4ffa6b..3b6ac331691d 100644
--- a/drivers/net/ethernet/microchip/lan966x/Makefile
+++ b/drivers/net/ethernet/microchip/lan966x/Makefile
@@ -15,6 +15,7 @@ lan966x-switch-objs := lan966x_main.o lan966x_phylink.o lan966x_port.o \
lan966x_xdp.o lan966x_vcap_impl.o lan966x_vcap_ag_api.o \
lan966x_tc_flower.o lan966x_goto.o
+lan966x-switch-$(CONFIG_LAN966X_DCB) += lan966x_dcb.o
lan966x-switch-$(CONFIG_DEBUG_FS) += lan966x_vcap_debugfs.o
# Provide include files
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_dcb.c b/drivers/net/ethernet/microchip/lan966x/lan966x_dcb.c
new file mode 100644
index 000000000000..ed2d96d7908e
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_dcb.c
@@ -0,0 +1,365 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include "lan966x_main.h"
+
+enum lan966x_dcb_apptrust_values {
+ LAN966X_DCB_APPTRUST_EMPTY,
+ LAN966X_DCB_APPTRUST_DSCP,
+ LAN966X_DCB_APPTRUST_PCP,
+ LAN966X_DCB_APPTRUST_DSCP_PCP,
+ __LAN966X_DCB_APPTRUST_MAX
+};
+
+static const struct lan966x_dcb_apptrust {
+ u8 selectors[IEEE_8021QAZ_APP_SEL_MAX + 1];
+ int nselectors;
+} *lan966x_port_apptrust[NUM_PHYS_PORTS];
+
+static const char *lan966x_dcb_apptrust_names[__LAN966X_DCB_APPTRUST_MAX] = {
+ [LAN966X_DCB_APPTRUST_EMPTY] = "empty",
+ [LAN966X_DCB_APPTRUST_DSCP] = "dscp",
+ [LAN966X_DCB_APPTRUST_PCP] = "pcp",
+ [LAN966X_DCB_APPTRUST_DSCP_PCP] = "dscp pcp"
+};
+
+/* Lan966x supported apptrust policies */
+static const struct lan966x_dcb_apptrust
+ lan966x_dcb_apptrust_policies[__LAN966X_DCB_APPTRUST_MAX] = {
+ /* Empty *must* be first */
+ [LAN966X_DCB_APPTRUST_EMPTY] = { { 0 }, 0 },
+ [LAN966X_DCB_APPTRUST_DSCP] = { { IEEE_8021QAZ_APP_SEL_DSCP }, 1 },
+ [LAN966X_DCB_APPTRUST_PCP] = { { DCB_APP_SEL_PCP }, 1 },
+ [LAN966X_DCB_APPTRUST_DSCP_PCP] = { { IEEE_8021QAZ_APP_SEL_DSCP,
+ DCB_APP_SEL_PCP }, 2 },
+};
+
+static bool lan966x_dcb_apptrust_contains(int portno, u8 selector)
+{
+ const struct lan966x_dcb_apptrust *conf = lan966x_port_apptrust[portno];
+
+ for (int i = 0; i < conf->nselectors; i++)
+ if (conf->selectors[i] == selector)
+ return true;
+
+ return false;
+}
+
+static void lan966x_dcb_app_update(struct net_device *dev)
+{
+ struct dcb_ieee_app_prio_map dscp_rewr_map = {0};
+ struct dcb_rewr_prio_pcp_map pcp_rewr_map = {0};
+ struct lan966x_port *port = netdev_priv(dev);
+ struct lan966x_port_qos qos = {0};
+ struct dcb_app app_itr;
+ bool dscp_rewr = false;
+ bool pcp_rewr = false;
+
+ /* Get pcp ingress mapping */
+ for (int i = 0; i < ARRAY_SIZE(qos.pcp.map); i++) {
+ app_itr.selector = DCB_APP_SEL_PCP;
+ app_itr.protocol = i;
+ qos.pcp.map[i] = dcb_getapp(dev, &app_itr);
+ }
+
+ /* Get dscp ingress mapping */
+ for (int i = 0; i < ARRAY_SIZE(qos.dscp.map); i++) {
+ app_itr.selector = IEEE_8021QAZ_APP_SEL_DSCP;
+ app_itr.protocol = i;
+ qos.dscp.map[i] = dcb_getapp(dev, &app_itr);
+ }
+
+ /* Get default prio */
+ qos.default_prio = dcb_ieee_getapp_default_prio_mask(dev);
+ if (qos.default_prio)
+ qos.default_prio = fls(qos.default_prio) - 1;
+
+ /* Get pcp rewrite mapping */
+ dcb_getrewr_prio_pcp_mask_map(dev, &pcp_rewr_map);
+ for (int i = 0; i < ARRAY_SIZE(pcp_rewr_map.map); i++) {
+ if (!pcp_rewr_map.map[i])
+ continue;
+
+ pcp_rewr = true;
+ qos.pcp_rewr.map[i] = fls(pcp_rewr_map.map[i]) - 1;
+ }
+
+ /* Get dscp rewrite mapping */
+ dcb_getrewr_prio_dscp_mask_map(dev, &dscp_rewr_map);
+ for (int i = 0; i < ARRAY_SIZE(dscp_rewr_map.map); i++) {
+ if (!dscp_rewr_map.map[i])
+ continue;
+
+ dscp_rewr = true;
+ qos.dscp_rewr.map[i] = fls64(dscp_rewr_map.map[i]) - 1;
+ }
+
+ /* Enable use of pcp for queue classification */
+ if (lan966x_dcb_apptrust_contains(port->chip_port, DCB_APP_SEL_PCP)) {
+ qos.pcp.enable = true;
+
+ if (pcp_rewr)
+ qos.pcp_rewr.enable = true;
+ }
+
+ /* Enable use of dscp for queue classification */
+ if (lan966x_dcb_apptrust_contains(port->chip_port, IEEE_8021QAZ_APP_SEL_DSCP)) {
+ qos.dscp.enable = true;
+
+ if (dscp_rewr)
+ qos.dscp_rewr.enable = true;
+ }
+
+ lan966x_port_qos_set(port, &qos);
+}
+
+/* DSCP mapping is global for all ports, so set and delete app entries are
+ * replicated for each port.
+ */
+static int lan966x_dcb_ieee_dscp_setdel(struct net_device *dev,
+ struct dcb_app *app,
+ int (*setdel)(struct net_device *,
+ struct dcb_app *))
+{
+ struct lan966x_port *port = netdev_priv(dev);
+ struct lan966x *lan966x = port->lan966x;
+ int err;
+
+ for (int i = 0; i < NUM_PHYS_PORTS; i++) {
+ port = lan966x->ports[i];
+ if (!port)
+ continue;
+
+ err = setdel(port->dev, app);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int lan966x_dcb_app_validate(struct net_device *dev,
+ const struct dcb_app *app)
+{
+ int err = 0;
+
+ switch (app->selector) {
+ /* Default priority checks */
+ case IEEE_8021QAZ_APP_SEL_ETHERTYPE:
+ if (app->protocol)
+ err = -EINVAL;
+ else if (app->priority >= NUM_PRIO_QUEUES)
+ err = -ERANGE;
+ break;
+ /* Dscp checks */
+ case IEEE_8021QAZ_APP_SEL_DSCP:
+ if (app->protocol >= LAN966X_PORT_QOS_DSCP_COUNT)
+ err = -EINVAL;
+ else if (app->priority >= NUM_PRIO_QUEUES)
+ err = -ERANGE;
+ break;
+ /* Pcp checks */
+ case DCB_APP_SEL_PCP:
+ if (app->protocol >= LAN966X_PORT_QOS_PCP_DEI_COUNT)
+ err = -EINVAL;
+ else if (app->priority >= NUM_PRIO_QUEUES)
+ err = -ERANGE;
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+
+ if (err)
+ netdev_err(dev, "Invalid entry: %d:%d\n", app->protocol,
+ app->priority);
+
+ return err;
+}
+
+static int lan966x_dcb_ieee_delapp(struct net_device *dev, struct dcb_app *app)
+{
+ int err;
+
+ if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
+ err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_ieee_delapp);
+ else
+ err = dcb_ieee_delapp(dev, app);
+
+ if (err)
+ return err;
+
+ lan966x_dcb_app_update(dev);
+
+ return 0;
+}
+
+static int lan966x_dcb_ieee_setapp(struct net_device *dev, struct dcb_app *app)
+{
+ struct dcb_app app_itr;
+ int err;
+ u8 prio;
+
+ err = lan966x_dcb_app_validate(dev, app);
+ if (err)
+ return err;
+
+ /* Delete current mapping, if it exists */
+ prio = dcb_getapp(dev, app);
+ if (prio) {
+ app_itr = *app;
+ app_itr.priority = prio;
+ lan966x_dcb_ieee_delapp(dev, &app_itr);
+ }
+
+ if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
+ err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_ieee_setapp);
+ else
+ err = dcb_ieee_setapp(dev, app);
+
+ if (err)
+ return err;
+
+ lan966x_dcb_app_update(dev);
+
+ return 0;
+}
+
+static int lan966x_dcb_apptrust_validate(struct net_device *dev,
+ u8 *selectors,
+ int nselectors)
+{
+ for (int i = 0; i < ARRAY_SIZE(lan966x_dcb_apptrust_policies); i++) {
+ bool match;
+
+ if (lan966x_dcb_apptrust_policies[i].nselectors != nselectors)
+ continue;
+
+ match = true;
+ for (int j = 0; j < nselectors; j++) {
+ if (lan966x_dcb_apptrust_policies[i].selectors[j] !=
+ *(selectors + j)) {
+ match = false;
+ break;
+ }
+ }
+ if (match)
+ return i;
+ }
+
+ netdev_err(dev, "Valid apptrust configurations are:\n");
+ for (int i = 0; i < ARRAY_SIZE(lan966x_dcb_apptrust_names); i++)
+ pr_info("order: %s\n", lan966x_dcb_apptrust_names[i]);
+
+ return -EOPNOTSUPP;
+}
+
+static int lan966x_dcb_setapptrust(struct net_device *dev,
+ u8 *selectors,
+ int nselectors)
+{
+ struct lan966x_port *port = netdev_priv(dev);
+ int idx;
+
+ idx = lan966x_dcb_apptrust_validate(dev, selectors, nselectors);
+ if (idx < 0)
+ return idx;
+
+ lan966x_port_apptrust[port->chip_port] = &lan966x_dcb_apptrust_policies[idx];
+ lan966x_dcb_app_update(dev);
+
+ return 0;
+}
+
+static int lan966x_dcb_getapptrust(struct net_device *dev, u8 *selectors,
+ int *nselectors)
+{
+ struct lan966x_port *port = netdev_priv(dev);
+ const struct lan966x_dcb_apptrust *trust;
+
+ trust = lan966x_port_apptrust[port->chip_port];
+
+ memcpy(selectors, trust->selectors, trust->nselectors);
+ *nselectors = trust->nselectors;
+
+ return 0;
+}
+
+static int lan966x_dcb_delrewr(struct net_device *dev, struct dcb_app *app)
+{
+ int err;
+
+ if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
+ err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_delrewr);
+ else
+ err = dcb_delrewr(dev, app);
+
+ if (err < 0)
+ return err;
+
+ lan966x_dcb_app_update(dev);
+
+ return 0;
+}
+
+static int lan966x_dcb_setrewr(struct net_device *dev, struct dcb_app *app)
+{
+ struct dcb_app app_itr;
+ u16 proto;
+ int err;
+
+ err = lan966x_dcb_app_validate(dev, app);
+ if (err)
+ goto out;
+
+ /* Delete current mapping, if it exists. */
+ proto = dcb_getrewr(dev, app);
+ if (proto) {
+ app_itr = *app;
+ app_itr.protocol = proto;
+ lan966x_dcb_delrewr(dev, &app_itr);
+ }
+
+ if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
+ err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_setrewr);
+ else
+ err = dcb_setrewr(dev, app);
+
+ if (err)
+ goto out;
+
+ lan966x_dcb_app_update(dev);
+
+out:
+ return err;
+}
+
+static const struct dcbnl_rtnl_ops lan966x_dcbnl_ops = {
+ .ieee_setapp = lan966x_dcb_ieee_setapp,
+ .ieee_delapp = lan966x_dcb_ieee_delapp,
+ .dcbnl_setapptrust = lan966x_dcb_setapptrust,
+ .dcbnl_getapptrust = lan966x_dcb_getapptrust,
+ .dcbnl_setrewr = lan966x_dcb_setrewr,
+ .dcbnl_delrewr = lan966x_dcb_delrewr,
+};
+
+void lan966x_dcb_init(struct lan966x *lan966x)
+{
+ for (int p = 0; p < lan966x->num_phys_ports; ++p) {
+ struct lan966x_port *port;
+
+ port = lan966x->ports[p];
+ if (!port)
+ continue;
+
+ port->dev->dcbnl_ops = &lan966x_dcbnl_ops;
+
+ lan966x_port_apptrust[port->chip_port] =
+ &lan966x_dcb_apptrust_policies[LAN966X_DCB_APPTRUST_DSCP_PCP];
+
+ /* Enable DSCP classification based on classified QoS class and
+ * DP, for all DSCP values, for all ports.
+ */
+ lan966x_port_qos_dscp_rewr_mode_set(port,
+ LAN966X_PORT_QOS_REWR_DSCP_ALL);
+ }
+}
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
index ee2698698d71..fbb0bb4594cd 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
@@ -818,6 +818,7 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p,
port->phylink_config.type = PHYLINK_NETDEV;
port->phylink_pcs.poll = true;
port->phylink_pcs.ops = &lan966x_phylink_pcs_ops;
+ port->phylink_pcs.neg_mode = true;
port->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
MAC_10 | MAC_100 | MAC_1000FD | MAC_2500FD;
@@ -1223,6 +1224,8 @@ static int lan966x_probe(struct platform_device *pdev)
if (err)
goto cleanup_fdma;
+ lan966x_dcb_init(lan966x);
+
return 0;
cleanup_fdma:
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h
index c977c70abc3d..27f272831ea5 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h
@@ -101,6 +101,25 @@
#define LAN966X_VCAP_CID_IS2_L1 VCAP_CID_INGRESS_STAGE2_L1 /* IS2 lookup 1 */
#define LAN966X_VCAP_CID_IS2_MAX (VCAP_CID_INGRESS_STAGE2_L2 - 1) /* IS2 Max */
+#define LAN966X_VCAP_CID_ES0_L0 VCAP_CID_EGRESS_L0 /* ES0 lookup 0 */
+#define LAN966X_VCAP_CID_ES0_MAX (VCAP_CID_EGRESS_L1 - 1) /* ES0 Max */
+
+#define LAN966X_PORT_QOS_PCP_COUNT 8
+#define LAN966X_PORT_QOS_DEI_COUNT 8
+#define LAN966X_PORT_QOS_PCP_DEI_COUNT \
+ (LAN966X_PORT_QOS_PCP_COUNT + LAN966X_PORT_QOS_DEI_COUNT)
+
+#define LAN966X_PORT_QOS_DSCP_COUNT 64
+
+/* Port PCP rewrite mode */
+#define LAN966X_PORT_REW_TAG_CTRL_CLASSIFIED 0
+#define LAN966X_PORT_REW_TAG_CTRL_MAPPED 2
+
+/* Port DSCP rewrite mode */
+#define LAN966X_PORT_REW_DSCP_FRAME 0
+#define LAN966X_PORT_REW_DSCP_ANALIZER 1
+#define LAN966X_PORT_QOS_REWR_DSCP_ALL 3
+
/* MAC table entry types.
* ENTRYTYPE_NORMAL is subject to aging.
* ENTRYTYPE_LOCKED is not subject to aging.
@@ -389,6 +408,34 @@ struct lan966x_port_tc {
struct flow_stats mirror_stat;
};
+struct lan966x_port_qos_pcp {
+ u8 map[LAN966X_PORT_QOS_PCP_DEI_COUNT];
+ bool enable;
+};
+
+struct lan966x_port_qos_dscp {
+ u8 map[LAN966X_PORT_QOS_DSCP_COUNT];
+ bool enable;
+};
+
+struct lan966x_port_qos_pcp_rewr {
+ u16 map[NUM_PRIO_QUEUES];
+ bool enable;
+};
+
+struct lan966x_port_qos_dscp_rewr {
+ u16 map[LAN966X_PORT_QOS_DSCP_COUNT];
+ bool enable;
+};
+
+struct lan966x_port_qos {
+ struct lan966x_port_qos_pcp pcp;
+ struct lan966x_port_qos_dscp dscp;
+ struct lan966x_port_qos_pcp_rewr pcp_rewr;
+ struct lan966x_port_qos_dscp_rewr dscp_rewr;
+ u8 default_prio;
+};
+
struct lan966x_port {
struct net_device *dev;
struct lan966x *lan966x;
@@ -453,6 +500,11 @@ int lan966x_port_pcs_set(struct lan966x_port *port,
struct lan966x_port_config *config);
void lan966x_port_init(struct lan966x_port *port);
+void lan966x_port_qos_set(struct lan966x_port *port,
+ struct lan966x_port_qos *qos);
+void lan966x_port_qos_dscp_rewr_mode_set(struct lan966x_port *port,
+ int mode);
+
int lan966x_mac_ip_learn(struct lan966x *lan966x,
bool cpu_copy,
const unsigned char mac[ETH_ALEN],
@@ -677,6 +729,14 @@ int lan966x_goto_port_del(struct lan966x_port *port,
unsigned long goto_id,
struct netlink_ext_ack *extack);
+#ifdef CONFIG_LAN966X_DCB
+void lan966x_dcb_init(struct lan966x *lan966x);
+#else
+static inline void lan966x_dcb_init(struct lan966x *lan966x)
+{
+}
+#endif
+
static inline void __iomem *lan_addr(void __iomem *base[],
int id, int tinst, int tcnt,
int gbase, int ginst,
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c b/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c
index c5f9803e6e63..1d63903f9006 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c
@@ -95,8 +95,7 @@ static void lan966x_pcs_get_state(struct phylink_pcs *pcs,
lan966x_port_status_get(port, state);
}
-static int lan966x_pcs_config(struct phylink_pcs *pcs,
- unsigned int mode,
+static int lan966x_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -107,8 +106,8 @@ static int lan966x_pcs_config(struct phylink_pcs *pcs,
config = port->config;
config.portmode = interface;
- config.inband = phylink_autoneg_inband(mode);
- config.autoneg = phylink_test(advertising, Autoneg);
+ config.inband = neg_mode & PHYLINK_PCS_NEG_INBAND;
+ config.autoneg = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED;
config.advertising = advertising;
ret = lan966x_port_pcs_set(port, &config);
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_port.c b/drivers/net/ethernet/microchip/lan966x/lan966x_port.c
index 0050fcb988b7..92108d354051 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_port.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_port.c
@@ -394,6 +394,155 @@ int lan966x_port_pcs_set(struct lan966x_port *port,
return 0;
}
+static void lan966x_port_qos_pcp_set(struct lan966x_port *port,
+ struct lan966x_port_qos_pcp *qos)
+{
+ u8 *pcp_itr = qos->map;
+ u8 pcp, dp;
+
+ lan_rmw(ANA_QOS_CFG_QOS_PCP_ENA_SET(qos->enable),
+ ANA_QOS_CFG_QOS_PCP_ENA,
+ port->lan966x, ANA_QOS_CFG(port->chip_port));
+
+ /* Map PCP and DEI to priority */
+ for (int i = 0; i < ARRAY_SIZE(qos->map); i++) {
+ pcp = *(pcp_itr + i);
+ dp = (i < LAN966X_PORT_QOS_PCP_COUNT) ? 0 : 1;
+
+ lan_rmw(ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL_SET(pcp) |
+ ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL_SET(dp),
+ ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL |
+ ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL,
+ port->lan966x,
+ ANA_PCP_DEI_CFG(port->chip_port, i));
+ }
+}
+
+static void lan966x_port_qos_dscp_set(struct lan966x_port *port,
+ struct lan966x_port_qos_dscp *qos)
+{
+ struct lan966x *lan966x = port->lan966x;
+
+ /* Enable/disable dscp for qos classification. */
+ lan_rmw(ANA_QOS_CFG_QOS_DSCP_ENA_SET(qos->enable),
+ ANA_QOS_CFG_QOS_DSCP_ENA,
+ lan966x, ANA_QOS_CFG(port->chip_port));
+
+ /* Map each dscp value to priority and dp */
+ for (int i = 0; i < ARRAY_SIZE(qos->map); i++)
+ lan_rmw(ANA_DSCP_CFG_DP_DSCP_VAL_SET(0) |
+ ANA_DSCP_CFG_QOS_DSCP_VAL_SET(*(qos->map + i)),
+ ANA_DSCP_CFG_DP_DSCP_VAL |
+ ANA_DSCP_CFG_QOS_DSCP_VAL,
+ lan966x, ANA_DSCP_CFG(i));
+
+ /* Set per-dscp trust */
+ for (int i = 0; i < ARRAY_SIZE(qos->map); i++)
+ lan_rmw(ANA_DSCP_CFG_DSCP_TRUST_ENA_SET(qos->enable),
+ ANA_DSCP_CFG_DSCP_TRUST_ENA,
+ lan966x, ANA_DSCP_CFG(i));
+}
+
+static int lan966x_port_qos_default_set(struct lan966x_port *port,
+ struct lan966x_port_qos *qos)
+{
+ /* Set default prio and dp level */
+ lan_rmw(ANA_QOS_CFG_DP_DEFAULT_VAL_SET(0) |
+ ANA_QOS_CFG_QOS_DEFAULT_VAL_SET(qos->default_prio),
+ ANA_QOS_CFG_DP_DEFAULT_VAL |
+ ANA_QOS_CFG_QOS_DEFAULT_VAL,
+ port->lan966x, ANA_QOS_CFG(port->chip_port));
+
+ /* Set default pcp and dei for untagged frames */
+ lan_rmw(ANA_VLAN_CFG_VLAN_DEI_SET(0) |
+ ANA_VLAN_CFG_VLAN_PCP_SET(0),
+ ANA_VLAN_CFG_VLAN_DEI |
+ ANA_VLAN_CFG_VLAN_PCP,
+ port->lan966x, ANA_VLAN_CFG(port->chip_port));
+
+ return 0;
+}
+
+static void lan966x_port_qos_pcp_rewr_set(struct lan966x_port *port,
+ struct lan966x_port_qos_pcp_rewr *qos)
+{
+ u8 mode = LAN966X_PORT_REW_TAG_CTRL_CLASSIFIED;
+ u8 pcp, dei;
+
+ if (qos->enable)
+ mode = LAN966X_PORT_REW_TAG_CTRL_MAPPED;
+
+ /* Map the values only if it is enabled otherwise will be the classified
+ * value
+ */
+ lan_rmw(REW_TAG_CFG_TAG_PCP_CFG_SET(mode) |
+ REW_TAG_CFG_TAG_DEI_CFG_SET(mode),
+ REW_TAG_CFG_TAG_PCP_CFG |
+ REW_TAG_CFG_TAG_DEI_CFG,
+ port->lan966x, REW_TAG_CFG(port->chip_port));
+
+ /* Map each value to pcp and dei */
+ for (int i = 0; i < ARRAY_SIZE(qos->map); i++) {
+ pcp = qos->map[i];
+ if (pcp > LAN966X_PORT_QOS_PCP_COUNT)
+ dei = 1;
+ else
+ dei = 0;
+
+ lan_rmw(REW_PCP_DEI_CFG_DEI_QOS_VAL_SET(dei) |
+ REW_PCP_DEI_CFG_PCP_QOS_VAL_SET(pcp),
+ REW_PCP_DEI_CFG_DEI_QOS_VAL |
+ REW_PCP_DEI_CFG_PCP_QOS_VAL,
+ port->lan966x,
+ REW_PCP_DEI_CFG(port->chip_port,
+ i + dei * LAN966X_PORT_QOS_PCP_COUNT));
+ }
+}
+
+static void lan966x_port_qos_dscp_rewr_set(struct lan966x_port *port,
+ struct lan966x_port_qos_dscp_rewr *qos)
+{
+ u16 dscp;
+ u8 mode;
+
+ if (qos->enable)
+ mode = LAN966X_PORT_REW_DSCP_ANALIZER;
+ else
+ mode = LAN966X_PORT_REW_DSCP_FRAME;
+
+ /* Enable the rewrite otherwise will use the values from the frame */
+ lan_rmw(REW_DSCP_CFG_DSCP_REWR_CFG_SET(mode),
+ REW_DSCP_CFG_DSCP_REWR_CFG,
+ port->lan966x, REW_DSCP_CFG(port->chip_port));
+
+ /* Map each classified Qos class and DP to classified DSCP value */
+ for (int i = 0; i < ARRAY_SIZE(qos->map); i++) {
+ dscp = qos->map[i];
+
+ lan_rmw(ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL_SET(dscp),
+ ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL,
+ port->lan966x, ANA_DSCP_REWR_CFG(i));
+ }
+}
+
+void lan966x_port_qos_dscp_rewr_mode_set(struct lan966x_port *port,
+ int mode)
+{
+ lan_rmw(ANA_QOS_CFG_DSCP_REWR_CFG_SET(mode),
+ ANA_QOS_CFG_DSCP_REWR_CFG,
+ port->lan966x, ANA_QOS_CFG(port->chip_port));
+}
+
+void lan966x_port_qos_set(struct lan966x_port *port,
+ struct lan966x_port_qos *qos)
+{
+ lan966x_port_qos_pcp_set(port, &qos->pcp);
+ lan966x_port_qos_dscp_set(port, &qos->dscp);
+ lan966x_port_qos_default_set(port, qos);
+ lan966x_port_qos_pcp_rewr_set(port, &qos->pcp_rewr);
+ lan966x_port_qos_dscp_rewr_set(port, &qos->dscp_rewr);
+}
+
void lan966x_port_init(struct lan966x_port *port)
{
struct lan966x_port_config *config = &port->config;
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h b/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h
index f99f88b5caa8..4b553927d2e0 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h
@@ -283,6 +283,18 @@ enum lan966x_target {
#define ANA_VLAN_CFG_VLAN_POP_CNT_GET(x)\
FIELD_GET(ANA_VLAN_CFG_VLAN_POP_CNT, x)
+#define ANA_VLAN_CFG_VLAN_PCP GENMASK(15, 13)
+#define ANA_VLAN_CFG_VLAN_PCP_SET(x)\
+ FIELD_PREP(ANA_VLAN_CFG_VLAN_PCP, x)
+#define ANA_VLAN_CFG_VLAN_PCP_GET(x)\
+ FIELD_GET(ANA_VLAN_CFG_VLAN_PCP, x)
+
+#define ANA_VLAN_CFG_VLAN_DEI BIT(12)
+#define ANA_VLAN_CFG_VLAN_DEI_SET(x)\
+ FIELD_PREP(ANA_VLAN_CFG_VLAN_DEI, x)
+#define ANA_VLAN_CFG_VLAN_DEI_GET(x)\
+ FIELD_GET(ANA_VLAN_CFG_VLAN_DEI, x)
+
#define ANA_VLAN_CFG_VLAN_VID GENMASK(11, 0)
#define ANA_VLAN_CFG_VLAN_VID_SET(x)\
FIELD_PREP(ANA_VLAN_CFG_VLAN_VID, x)
@@ -316,6 +328,39 @@ enum lan966x_target {
#define ANA_DROP_CFG_DROP_MC_SMAC_ENA_GET(x)\
FIELD_GET(ANA_DROP_CFG_DROP_MC_SMAC_ENA, x)
+/* ANA:PORT:QOS_CFG */
+#define ANA_QOS_CFG(g) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 8, 0, 1, 4)
+
+#define ANA_QOS_CFG_DP_DEFAULT_VAL BIT(8)
+#define ANA_QOS_CFG_DP_DEFAULT_VAL_SET(x)\
+ FIELD_PREP(ANA_QOS_CFG_DP_DEFAULT_VAL, x)
+#define ANA_QOS_CFG_DP_DEFAULT_VAL_GET(x)\
+ FIELD_GET(ANA_QOS_CFG_DP_DEFAULT_VAL, x)
+
+#define ANA_QOS_CFG_QOS_DEFAULT_VAL GENMASK(7, 5)
+#define ANA_QOS_CFG_QOS_DEFAULT_VAL_SET(x)\
+ FIELD_PREP(ANA_QOS_CFG_QOS_DEFAULT_VAL, x)
+#define ANA_QOS_CFG_QOS_DEFAULT_VAL_GET(x)\
+ FIELD_GET(ANA_QOS_CFG_QOS_DEFAULT_VAL, x)
+
+#define ANA_QOS_CFG_QOS_DSCP_ENA BIT(4)
+#define ANA_QOS_CFG_QOS_DSCP_ENA_SET(x)\
+ FIELD_PREP(ANA_QOS_CFG_QOS_DSCP_ENA, x)
+#define ANA_QOS_CFG_QOS_DSCP_ENA_GET(x)\
+ FIELD_GET(ANA_QOS_CFG_QOS_DSCP_ENA, x)
+
+#define ANA_QOS_CFG_QOS_PCP_ENA BIT(3)
+#define ANA_QOS_CFG_QOS_PCP_ENA_SET(x)\
+ FIELD_PREP(ANA_QOS_CFG_QOS_PCP_ENA, x)
+#define ANA_QOS_CFG_QOS_PCP_ENA_GET(x)\
+ FIELD_GET(ANA_QOS_CFG_QOS_PCP_ENA, x)
+
+#define ANA_QOS_CFG_DSCP_REWR_CFG GENMASK(1, 0)
+#define ANA_QOS_CFG_DSCP_REWR_CFG_SET(x)\
+ FIELD_PREP(ANA_QOS_CFG_DSCP_REWR_CFG, x)
+#define ANA_QOS_CFG_DSCP_REWR_CFG_GET(x)\
+ FIELD_GET(ANA_QOS_CFG_DSCP_REWR_CFG, x)
+
/* ANA:PORT:VCAP_CFG */
#define ANA_VCAP_CFG(g) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 12, 0, 1, 4)
@@ -415,6 +460,21 @@ enum lan966x_target {
#define ANA_VCAP_S2_CFG_OAM_DIS_GET(x)\
FIELD_GET(ANA_VCAP_S2_CFG_OAM_DIS, x)
+/* ANA:PORT:QOS_PCP_DEI_MAP_CFG */
+#define ANA_PCP_DEI_CFG(g, r) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 32, r, 16, 4)
+
+#define ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL BIT(3)
+#define ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL_SET(x)\
+ FIELD_PREP(ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL, x)
+#define ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL_GET(x)\
+ FIELD_GET(ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL, x)
+
+#define ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL GENMASK(2, 0)
+#define ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL_SET(x)\
+ FIELD_PREP(ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL, x)
+#define ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL_GET(x)\
+ FIELD_GET(ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL, x)
+
/* ANA:PORT:CPU_FWD_CFG */
#define ANA_CPU_FWD_CFG(g) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 96, 0, 1, 4)
@@ -478,6 +538,15 @@ enum lan966x_target {
#define ANA_PORT_CFG_PORTID_VAL_GET(x)\
FIELD_GET(ANA_PORT_CFG_PORTID_VAL, x)
+/* ANA:COMMON:DSCP_REWR_CFG */
+#define ANA_DSCP_REWR_CFG(r) __REG(TARGET_ANA, 0, 1, 31232, 0, 1, 552, 332, r, 16, 4)
+
+#define ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL GENMASK(5, 0)
+#define ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL_SET(x)\
+ FIELD_PREP(ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL, x)
+#define ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL_GET(x)\
+ FIELD_GET(ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL, x)
+
/* ANA:PORT:POL_CFG */
#define ANA_POL_CFG(g) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 116, 0, 1, 4)
@@ -547,6 +616,33 @@ enum lan966x_target {
#define ANA_AGGR_CFG_AC_IP4_TCPUDP_ENA_GET(x)\
FIELD_GET(ANA_AGGR_CFG_AC_IP4_TCPUDP_ENA, x)
+/* ANA:COMMON:DSCP_CFG */
+#define ANA_DSCP_CFG(r) __REG(TARGET_ANA, 0, 1, 31232, 0, 1, 552, 76, r, 64, 4)
+
+#define ANA_DSCP_CFG_DP_DSCP_VAL BIT(11)
+#define ANA_DSCP_CFG_DP_DSCP_VAL_SET(x)\
+ FIELD_PREP(ANA_DSCP_CFG_DP_DSCP_VAL, x)
+#define ANA_DSCP_CFG_DP_DSCP_VAL_GET(x)\
+ FIELD_GET(ANA_DSCP_CFG_DP_DSCP_VAL, x)
+
+#define ANA_DSCP_CFG_QOS_DSCP_VAL GENMASK(10, 8)
+#define ANA_DSCP_CFG_QOS_DSCP_VAL_SET(x)\
+ FIELD_PREP(ANA_DSCP_CFG_QOS_DSCP_VAL, x)
+#define ANA_DSCP_CFG_QOS_DSCP_VAL_GET(x)\
+ FIELD_GET(ANA_DSCP_CFG_QOS_DSCP_VAL, x)
+
+#define ANA_DSCP_CFG_DSCP_TRUST_ENA BIT(1)
+#define ANA_DSCP_CFG_DSCP_TRUST_ENA_SET(x)\
+ FIELD_PREP(ANA_DSCP_CFG_DSCP_TRUST_ENA, x)
+#define ANA_DSCP_CFG_DSCP_TRUST_ENA_GET(x)\
+ FIELD_GET(ANA_DSCP_CFG_DSCP_TRUST_ENA, x)
+
+#define ANA_DSCP_CFG_DSCP_REWR_ENA BIT(0)
+#define ANA_DSCP_CFG_DSCP_REWR_ENA_SET(x)\
+ FIELD_PREP(ANA_DSCP_CFG_DSCP_REWR_ENA, x)
+#define ANA_DSCP_CFG_DSCP_REWR_ENA_GET(x)\
+ FIELD_GET(ANA_DSCP_CFG_DSCP_REWR_ENA, x)
+
/* ANA:POL:POL_PIR_CFG */
#define ANA_POL_PIR_CFG(g) __REG(TARGET_ANA, 0, 1, 16384, g, 345, 32, 0, 0, 1, 4)
@@ -1468,15 +1564,66 @@ enum lan966x_target {
#define REW_TAG_CFG_TAG_TPID_CFG_GET(x)\
FIELD_GET(REW_TAG_CFG_TAG_TPID_CFG, x)
+#define REW_TAG_CFG_TAG_PCP_CFG GENMASK(3, 2)
+#define REW_TAG_CFG_TAG_PCP_CFG_SET(x)\
+ FIELD_PREP(REW_TAG_CFG_TAG_PCP_CFG, x)
+#define REW_TAG_CFG_TAG_PCP_CFG_GET(x)\
+ FIELD_GET(REW_TAG_CFG_TAG_PCP_CFG, x)
+
+#define REW_TAG_CFG_TAG_DEI_CFG GENMASK(1, 0)
+#define REW_TAG_CFG_TAG_DEI_CFG_SET(x)\
+ FIELD_PREP(REW_TAG_CFG_TAG_DEI_CFG, x)
+#define REW_TAG_CFG_TAG_DEI_CFG_GET(x)\
+ FIELD_GET(REW_TAG_CFG_TAG_DEI_CFG, x)
+
/* REW:PORT:PORT_CFG */
#define REW_PORT_CFG(g) __REG(TARGET_REW, 0, 1, 0, g, 10, 128, 8, 0, 1, 4)
+#define REW_PORT_CFG_ES0_EN BIT(4)
+#define REW_PORT_CFG_ES0_EN_SET(x)\
+ FIELD_PREP(REW_PORT_CFG_ES0_EN, x)
+#define REW_PORT_CFG_ES0_EN_GET(x)\
+ FIELD_GET(REW_PORT_CFG_ES0_EN, x)
+
#define REW_PORT_CFG_NO_REWRITE BIT(0)
#define REW_PORT_CFG_NO_REWRITE_SET(x)\
FIELD_PREP(REW_PORT_CFG_NO_REWRITE, x)
#define REW_PORT_CFG_NO_REWRITE_GET(x)\
FIELD_GET(REW_PORT_CFG_NO_REWRITE, x)
+/* REW:PORT:DSCP_CFG */
+#define REW_DSCP_CFG(g) __REG(TARGET_REW, 0, 1, 0, g, 10, 128, 12, 0, 1, 4)
+
+#define REW_DSCP_CFG_DSCP_REWR_CFG GENMASK(1, 0)
+#define REW_DSCP_CFG_DSCP_REWR_CFG_SET(x)\
+ FIELD_PREP(REW_DSCP_CFG_DSCP_REWR_CFG, x)
+#define REW_DSCP_CFG_DSCP_REWR_CFG_GET(x)\
+ FIELD_GET(REW_DSCP_CFG_DSCP_REWR_CFG, x)
+
+/* REW:PORT:PCP_DEI_QOS_MAP_CFG */
+#define REW_PCP_DEI_CFG(g, r) __REG(TARGET_REW, 0, 1, 0, g, 10, 128, 16, r, 16, 4)
+
+#define REW_PCP_DEI_CFG_DEI_QOS_VAL BIT(3)
+#define REW_PCP_DEI_CFG_DEI_QOS_VAL_SET(x)\
+ FIELD_PREP(REW_PCP_DEI_CFG_DEI_QOS_VAL, x)
+#define REW_PCP_DEI_CFG_DEI_QOS_VAL_GET(x)\
+ FIELD_GET(REW_PCP_DEI_CFG_DEI_QOS_VAL, x)
+
+#define REW_PCP_DEI_CFG_PCP_QOS_VAL GENMASK(2, 0)
+#define REW_PCP_DEI_CFG_PCP_QOS_VAL_SET(x)\
+ FIELD_PREP(REW_PCP_DEI_CFG_PCP_QOS_VAL, x)
+#define REW_PCP_DEI_CFG_PCP_QOS_VAL_GET(x)\
+ FIELD_GET(REW_PCP_DEI_CFG_PCP_QOS_VAL, x)
+
+/* REW:COMMON:STAT_CFG */
+#define REW_STAT_CFG __REG(TARGET_REW, 0, 1, 3072, 0, 1, 528, 520, 0, 1, 4)
+
+#define REW_STAT_CFG_STAT_MODE GENMASK(1, 0)
+#define REW_STAT_CFG_STAT_MODE_SET(x)\
+ FIELD_PREP(REW_STAT_CFG_STAT_MODE, x)
+#define REW_STAT_CFG_STAT_MODE_GET(x)\
+ FIELD_GET(REW_STAT_CFG_STAT_MODE, x)
+
/* SYS:SYSTEM:RESET_CFG */
#define SYS_RESET_CFG __REG(TARGET_SYS, 0, 1, 4128, 0, 1, 168, 0, 0, 1, 4)
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c b/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c
index cf0cc7562d04..ee652f2d2359 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c
@@ -21,8 +21,14 @@ static int lan966x_tc_setup_qdisc_mqprio(struct lan966x_port *port,
static int lan966x_tc_setup_qdisc_taprio(struct lan966x_port *port,
struct tc_taprio_qopt_offload *taprio)
{
- return taprio->enable ? lan966x_taprio_add(port, taprio) :
- lan966x_taprio_del(port);
+ switch (taprio->cmd) {
+ case TAPRIO_CMD_REPLACE:
+ return lan966x_taprio_add(port, taprio);
+ case TAPRIO_CMD_DESTROY:
+ return lan966x_taprio_del(port);
+ default:
+ return -EOPNOTSUPP;
+ }
}
static int lan966x_tc_setup_qdisc_tbf(struct lan966x_port *port,
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c b/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c
index 47b2f7579dd2..96b3def6c474 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c
@@ -5,6 +5,8 @@
#include "vcap_api_client.h"
#include "vcap_tc.h"
+#define LAN966X_FORCE_UNTAGED 3
+
static bool lan966x_tc_is_known_etype(struct vcap_tc_flower_parse_usage *st,
u16 etype)
{
@@ -29,6 +31,8 @@ static bool lan966x_tc_is_known_etype(struct vcap_tc_flower_parse_usage *st,
return true;
}
break;
+ case VCAP_TYPE_ES0:
+ return true;
default:
NL_SET_ERR_MSG_MOD(st->fco->common.extack,
"VCAP type not supported");
@@ -318,6 +322,9 @@ static int lan966x_tc_set_actionset(struct vcap_admin *admin,
case VCAP_TYPE_IS2:
aset = VCAP_AFS_BASE_TYPE;
break;
+ case VCAP_TYPE_ES0:
+ aset = VCAP_AFS_VID;
+ break;
default:
return -EINVAL;
}
@@ -353,6 +360,10 @@ static int lan966x_tc_add_rule_link_target(struct vcap_admin *admin,
/* Add IS2 specific PAG key (for chaining rules from IS1) */
return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_PAG,
link_val, ~0);
+ case VCAP_TYPE_ES0:
+ /* Add ES0 specific ISDX key (for chaining rules from IS1) */
+ return vcap_rule_add_key_u32(vrule, VCAP_KF_ISDX_CLS,
+ link_val, ~0);
default:
break;
}
@@ -389,6 +400,18 @@ static int lan966x_tc_add_rule_link(struct vcap_control *vctrl,
0xff);
if (err)
return err;
+ } else if (admin->vtype == VCAP_TYPE_IS1 &&
+ to_admin->vtype == VCAP_TYPE_ES0) {
+ /* This works for IS1->ES0 */
+ err = vcap_rule_add_action_u32(vrule, VCAP_AF_ISDX_ADD_VAL,
+ diff);
+ if (err)
+ return err;
+
+ err = vcap_rule_add_action_bit(vrule, VCAP_AF_ISDX_REPLACE_ENA,
+ VCAP_BIT_1);
+ if (err)
+ return err;
} else {
NL_SET_ERR_MSG_MOD(f->common.extack,
"Unsupported chain destination");
@@ -398,6 +421,23 @@ static int lan966x_tc_add_rule_link(struct vcap_control *vctrl,
return err;
}
+static int lan966x_tc_add_rule_counter(struct vcap_admin *admin,
+ struct vcap_rule *vrule)
+{
+ int err = 0;
+
+ switch (admin->vtype) {
+ case VCAP_TYPE_ES0:
+ err = vcap_rule_mod_action_u32(vrule, VCAP_AF_ESDX,
+ vrule->id);
+ break;
+ default:
+ break;
+ }
+
+ return err;
+}
+
static int lan966x_tc_flower_add(struct lan966x_port *port,
struct flow_cls_offload *f,
struct vcap_admin *admin,
@@ -466,6 +506,21 @@ static int lan966x_tc_flower_add(struct lan966x_port *port,
goto out;
break;
+ case FLOW_ACTION_VLAN_POP:
+ if (admin->vtype != VCAP_TYPE_ES0) {
+ NL_SET_ERR_MSG_MOD(f->common.extack,
+ "Cannot use vlan pop on non es0");
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ /* Force untag */
+ err = vcap_rule_add_action_u32(vrule, VCAP_AF_PUSH_OUTER_TAG,
+ LAN966X_FORCE_UNTAGED);
+ if (err)
+ goto out;
+
+ break;
default:
NL_SET_ERR_MSG_MOD(f->common.extack,
"Unsupported TC action");
@@ -474,6 +529,12 @@ static int lan966x_tc_flower_add(struct lan966x_port *port,
}
}
+ err = lan966x_tc_add_rule_counter(admin, vrule);
+ if (err) {
+ vcap_set_tc_exterr(f, vrule);
+ goto out;
+ }
+
err = vcap_val_rule(vrule, l3_proto);
if (err) {
vcap_set_tc_exterr(f, vrule);
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c
index 66400a082d02..fb6851b94528 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c
@@ -2121,6 +2121,69 @@ static const struct vcap_field is2_smac_sip6_keyfield[] = {
},
};
+static const struct vcap_field es0_vid_keyfield[] = {
+ [VCAP_KF_IF_EGR_PORT_NO] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 0,
+ .width = 4,
+ },
+ [VCAP_KF_IF_IGR_PORT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 4,
+ .width = 4,
+ },
+ [VCAP_KF_ISDX_GT0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 8,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 9,
+ .width = 8,
+ },
+ [VCAP_KF_L2_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 17,
+ .width = 1,
+ },
+ [VCAP_KF_L2_BC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 18,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 19,
+ .width = 12,
+ },
+ [VCAP_KF_8021Q_DEI_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 31,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_PCP_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 32,
+ .width = 3,
+ },
+ [VCAP_KF_L3_DPL_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 35,
+ .width = 1,
+ },
+ [VCAP_KF_RTP_ID] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 36,
+ .width = 10,
+ },
+ [VCAP_KF_PDU_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 46,
+ .width = 4,
+ },
+};
+
/* keyfield_set */
static const struct vcap_set is1_keyfield_set[] = {
[VCAP_KFS_NORMAL] = {
@@ -2228,6 +2291,14 @@ static const struct vcap_set is2_keyfield_set[] = {
},
};
+static const struct vcap_set es0_keyfield_set[] = {
+ [VCAP_KFS_VID] = {
+ .type_id = -1,
+ .sw_per_item = 1,
+ .sw_cnt = 1,
+ },
+};
+
/* keyfield_set map */
static const struct vcap_field *is1_keyfield_set_map[] = {
[VCAP_KFS_NORMAL] = is1_normal_keyfield,
@@ -2255,6 +2326,10 @@ static const struct vcap_field *is2_keyfield_set_map[] = {
[VCAP_KFS_SMAC_SIP6] = is2_smac_sip6_keyfield,
};
+static const struct vcap_field *es0_keyfield_set_map[] = {
+ [VCAP_KFS_VID] = es0_vid_keyfield,
+};
+
/* keyfield_set map sizes */
static int is1_keyfield_set_map_size[] = {
[VCAP_KFS_NORMAL] = ARRAY_SIZE(is1_normal_keyfield),
@@ -2282,6 +2357,10 @@ static int is2_keyfield_set_map_size[] = {
[VCAP_KFS_SMAC_SIP6] = ARRAY_SIZE(is2_smac_sip6_keyfield),
};
+static int es0_keyfield_set_map_size[] = {
+ [VCAP_KFS_VID] = ARRAY_SIZE(es0_vid_keyfield),
+};
+
/* actionfields */
static const struct vcap_field is1_s1_actionfield[] = {
[VCAP_AF_TYPE] = {
@@ -2522,6 +2601,94 @@ static const struct vcap_field is2_smac_sip_actionfield[] = {
},
};
+static const struct vcap_field es0_vid_actionfield[] = {
+ [VCAP_AF_PUSH_OUTER_TAG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 0,
+ .width = 2,
+ },
+ [VCAP_AF_PUSH_INNER_TAG] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 2,
+ .width = 1,
+ },
+ [VCAP_AF_TAG_A_TPID_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 3,
+ .width = 2,
+ },
+ [VCAP_AF_TAG_A_VID_SEL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 5,
+ .width = 1,
+ },
+ [VCAP_AF_TAG_A_PCP_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 6,
+ .width = 2,
+ },
+ [VCAP_AF_TAG_A_DEI_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 8,
+ .width = 2,
+ },
+ [VCAP_AF_TAG_B_TPID_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 10,
+ .width = 2,
+ },
+ [VCAP_AF_TAG_B_VID_SEL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 12,
+ .width = 1,
+ },
+ [VCAP_AF_TAG_B_PCP_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 13,
+ .width = 2,
+ },
+ [VCAP_AF_TAG_B_DEI_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 15,
+ .width = 2,
+ },
+ [VCAP_AF_VID_A_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 17,
+ .width = 12,
+ },
+ [VCAP_AF_PCP_A_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 29,
+ .width = 3,
+ },
+ [VCAP_AF_DEI_A_VAL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 32,
+ .width = 1,
+ },
+ [VCAP_AF_VID_B_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 33,
+ .width = 12,
+ },
+ [VCAP_AF_PCP_B_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 45,
+ .width = 3,
+ },
+ [VCAP_AF_DEI_B_VAL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 48,
+ .width = 1,
+ },
+ [VCAP_AF_ESDX] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 49,
+ .width = 8,
+ },
+};
+
/* actionfield_set */
static const struct vcap_set is1_actionfield_set[] = {
[VCAP_AFS_S1] = {
@@ -2544,6 +2711,14 @@ static const struct vcap_set is2_actionfield_set[] = {
},
};
+static const struct vcap_set es0_actionfield_set[] = {
+ [VCAP_AFS_VID] = {
+ .type_id = -1,
+ .sw_per_item = 1,
+ .sw_cnt = 1,
+ },
+};
+
/* actionfield_set map */
static const struct vcap_field *is1_actionfield_set_map[] = {
[VCAP_AFS_S1] = is1_s1_actionfield,
@@ -2554,6 +2729,10 @@ static const struct vcap_field *is2_actionfield_set_map[] = {
[VCAP_AFS_SMAC_SIP] = is2_smac_sip_actionfield,
};
+static const struct vcap_field *es0_actionfield_set_map[] = {
+ [VCAP_AFS_VID] = es0_vid_actionfield,
+};
+
/* actionfield_set map size */
static int is1_actionfield_set_map_size[] = {
[VCAP_AFS_S1] = ARRAY_SIZE(is1_s1_actionfield),
@@ -2564,6 +2743,10 @@ static int is2_actionfield_set_map_size[] = {
[VCAP_AFS_SMAC_SIP] = ARRAY_SIZE(is2_smac_sip_actionfield),
};
+static int es0_actionfield_set_map_size[] = {
+ [VCAP_AFS_VID] = ARRAY_SIZE(es0_vid_actionfield),
+};
+
/* Type Groups */
static const struct vcap_typegroup is1_x4_keyfield_set_typegroups[] = {
{
@@ -2659,6 +2842,10 @@ static const struct vcap_typegroup is2_x1_keyfield_set_typegroups[] = {
{}
};
+static const struct vcap_typegroup es0_x1_keyfield_set_typegroups[] = {
+ {}
+};
+
static const struct vcap_typegroup *is1_keyfield_set_typegroups[] = {
[4] = is1_x4_keyfield_set_typegroups,
[2] = is1_x2_keyfield_set_typegroups,
@@ -2673,6 +2860,11 @@ static const struct vcap_typegroup *is2_keyfield_set_typegroups[] = {
[5] = NULL,
};
+static const struct vcap_typegroup *es0_keyfield_set_typegroups[] = {
+ [1] = es0_x1_keyfield_set_typegroups,
+ [2] = NULL,
+};
+
static const struct vcap_typegroup is1_x1_actionfield_set_typegroups[] = {
{}
};
@@ -2700,6 +2892,10 @@ static const struct vcap_typegroup is2_x1_actionfield_set_typegroups[] = {
{}
};
+static const struct vcap_typegroup es0_x1_actionfield_set_typegroups[] = {
+ {}
+};
+
static const struct vcap_typegroup *is1_actionfield_set_typegroups[] = {
[1] = is1_x1_actionfield_set_typegroups,
[5] = NULL,
@@ -2711,6 +2907,11 @@ static const struct vcap_typegroup *is2_actionfield_set_typegroups[] = {
[5] = NULL,
};
+static const struct vcap_typegroup *es0_actionfield_set_typegroups[] = {
+ [1] = es0_x1_actionfield_set_typegroups,
+ [2] = NULL,
+};
+
/* Keyfieldset names */
static const char * const vcap_keyfield_set_names[] = {
[VCAP_KFS_NO_VALUE] = "(None)",
@@ -2743,6 +2944,7 @@ static const char * const vcap_keyfield_set_names[] = {
[VCAP_KFS_RT] = "VCAP_KFS_RT",
[VCAP_KFS_SMAC_SIP4] = "VCAP_KFS_SMAC_SIP4",
[VCAP_KFS_SMAC_SIP6] = "VCAP_KFS_SMAC_SIP6",
+ [VCAP_KFS_VID] = "VCAP_KFS_VID",
};
/* Actionfieldset names */
@@ -2751,9 +2953,11 @@ static const char * const vcap_actionfield_set_names[] = {
[VCAP_AFS_BASE_TYPE] = "VCAP_AFS_BASE_TYPE",
[VCAP_AFS_CLASSIFICATION] = "VCAP_AFS_CLASSIFICATION",
[VCAP_AFS_CLASS_REDUCED] = "VCAP_AFS_CLASS_REDUCED",
+ [VCAP_AFS_ES0] = "VCAP_AFS_ES0",
[VCAP_AFS_FULL] = "VCAP_AFS_FULL",
[VCAP_AFS_S1] = "VCAP_AFS_S1",
[VCAP_AFS_SMAC_SIP] = "VCAP_AFS_SMAC_SIP",
+ [VCAP_AFS_VID] = "VCAP_AFS_VID",
};
/* Keyfield names */
@@ -2774,6 +2978,7 @@ static const char * const vcap_keyfield_names[] = {
[VCAP_KF_8021Q_PCP1] = "8021Q_PCP1",
[VCAP_KF_8021Q_PCP2] = "8021Q_PCP2",
[VCAP_KF_8021Q_PCP_CLS] = "8021Q_PCP_CLS",
+ [VCAP_KF_8021Q_TPID] = "8021Q_TPID",
[VCAP_KF_8021Q_TPID0] = "8021Q_TPID0",
[VCAP_KF_8021Q_TPID1] = "8021Q_TPID1",
[VCAP_KF_8021Q_TPID2] = "8021Q_TPID2",
@@ -2799,6 +3004,7 @@ static const char * const vcap_keyfield_names[] = {
[VCAP_KF_HOST_MATCH] = "HOST_MATCH",
[VCAP_KF_IF_EGR_PORT_MASK] = "IF_EGR_PORT_MASK",
[VCAP_KF_IF_EGR_PORT_MASK_RNG] = "IF_EGR_PORT_MASK_RNG",
+ [VCAP_KF_IF_EGR_PORT_NO] = "IF_EGR_PORT_NO",
[VCAP_KF_IF_IGR_PORT] = "IF_IGR_PORT",
[VCAP_KF_IF_IGR_PORT_MASK] = "IF_IGR_PORT_MASK",
[VCAP_KF_IF_IGR_PORT_MASK_L3] = "IF_IGR_PORT_MASK_L3",
@@ -2873,7 +3079,9 @@ static const char * const vcap_keyfield_names[] = {
[VCAP_KF_OAM_OPCODE] = "OAM_OPCODE",
[VCAP_KF_OAM_VER] = "OAM_VER",
[VCAP_KF_OAM_Y1731_IS] = "OAM_Y1731_IS",
+ [VCAP_KF_PDU_TYPE] = "PDU_TYPE",
[VCAP_KF_PROT_ACTIVE] = "PROT_ACTIVE",
+ [VCAP_KF_RTP_ID] = "RTP_ID",
[VCAP_KF_RT_FRMID] = "RT_FRMID",
[VCAP_KF_RT_TYPE] = "RT_TYPE",
[VCAP_KF_RT_VLAN_IDX] = "RT_VLAN_IDX",
@@ -2891,18 +3099,25 @@ static const char * const vcap_actionfield_names[] = {
[VCAP_AF_COPY_PORT_NUM] = "COPY_PORT_NUM",
[VCAP_AF_COPY_QUEUE_NUM] = "COPY_QUEUE_NUM",
[VCAP_AF_CPU_COPY_ENA] = "CPU_COPY_ENA",
+ [VCAP_AF_CPU_QU] = "CPU_QU",
[VCAP_AF_CPU_QUEUE_NUM] = "CPU_QUEUE_NUM",
[VCAP_AF_CUSTOM_ACE_TYPE_ENA] = "CUSTOM_ACE_TYPE_ENA",
+ [VCAP_AF_DEI_A_VAL] = "DEI_A_VAL",
+ [VCAP_AF_DEI_B_VAL] = "DEI_B_VAL",
+ [VCAP_AF_DEI_C_VAL] = "DEI_C_VAL",
[VCAP_AF_DEI_ENA] = "DEI_ENA",
[VCAP_AF_DEI_VAL] = "DEI_VAL",
[VCAP_AF_DLR_SEL] = "DLR_SEL",
[VCAP_AF_DP_ENA] = "DP_ENA",
[VCAP_AF_DP_VAL] = "DP_VAL",
[VCAP_AF_DSCP_ENA] = "DSCP_ENA",
+ [VCAP_AF_DSCP_SEL] = "DSCP_SEL",
[VCAP_AF_DSCP_VAL] = "DSCP_VAL",
[VCAP_AF_ES2_REW_CMD] = "ES2_REW_CMD",
+ [VCAP_AF_ESDX] = "ESDX",
[VCAP_AF_FWD_KILL_ENA] = "FWD_KILL_ENA",
[VCAP_AF_FWD_MODE] = "FWD_MODE",
+ [VCAP_AF_FWD_SEL] = "FWD_SEL",
[VCAP_AF_HIT_ME_ONCE] = "HIT_ME_ONCE",
[VCAP_AF_HOST_MATCH] = "HOST_MATCH",
[VCAP_AF_IGNORE_PIPELINE_CTRL] = "IGNORE_PIPELINE_CTRL",
@@ -2912,6 +3127,7 @@ static const char * const vcap_actionfield_names[] = {
[VCAP_AF_ISDX_ENA] = "ISDX_ENA",
[VCAP_AF_ISDX_REPLACE_ENA] = "ISDX_REPLACE_ENA",
[VCAP_AF_ISDX_VAL] = "ISDX_VAL",
+ [VCAP_AF_LOOP_ENA] = "LOOP_ENA",
[VCAP_AF_LRN_DIS] = "LRN_DIS",
[VCAP_AF_MAP_IDX] = "MAP_IDX",
[VCAP_AF_MAP_KEY] = "MAP_KEY",
@@ -2928,15 +3144,23 @@ static const char * const vcap_actionfield_names[] = {
[VCAP_AF_OAM_SEL] = "OAM_SEL",
[VCAP_AF_PAG_OVERRIDE_MASK] = "PAG_OVERRIDE_MASK",
[VCAP_AF_PAG_VAL] = "PAG_VAL",
+ [VCAP_AF_PCP_A_VAL] = "PCP_A_VAL",
+ [VCAP_AF_PCP_B_VAL] = "PCP_B_VAL",
+ [VCAP_AF_PCP_C_VAL] = "PCP_C_VAL",
[VCAP_AF_PCP_ENA] = "PCP_ENA",
[VCAP_AF_PCP_VAL] = "PCP_VAL",
+ [VCAP_AF_PIPELINE_ACT] = "PIPELINE_ACT",
[VCAP_AF_PIPELINE_FORCE_ENA] = "PIPELINE_FORCE_ENA",
[VCAP_AF_PIPELINE_PT] = "PIPELINE_PT",
[VCAP_AF_POLICE_ENA] = "POLICE_ENA",
[VCAP_AF_POLICE_IDX] = "POLICE_IDX",
[VCAP_AF_POLICE_REMARK] = "POLICE_REMARK",
[VCAP_AF_POLICE_VCAP_ONLY] = "POLICE_VCAP_ONLY",
+ [VCAP_AF_POP_VAL] = "POP_VAL",
[VCAP_AF_PORT_MASK] = "PORT_MASK",
+ [VCAP_AF_PUSH_CUSTOMER_TAG] = "PUSH_CUSTOMER_TAG",
+ [VCAP_AF_PUSH_INNER_TAG] = "PUSH_INNER_TAG",
+ [VCAP_AF_PUSH_OUTER_TAG] = "PUSH_OUTER_TAG",
[VCAP_AF_QOS_ENA] = "QOS_ENA",
[VCAP_AF_QOS_VAL] = "QOS_VAL",
[VCAP_AF_REW_OP] = "REW_OP",
@@ -2945,7 +3169,24 @@ static const char * const vcap_actionfield_names[] = {
[VCAP_AF_SFID_VAL] = "SFID_VAL",
[VCAP_AF_SGID_ENA] = "SGID_ENA",
[VCAP_AF_SGID_VAL] = "SGID_VAL",
+ [VCAP_AF_SWAP_MACS_ENA] = "SWAP_MACS_ENA",
+ [VCAP_AF_TAG_A_DEI_SEL] = "TAG_A_DEI_SEL",
+ [VCAP_AF_TAG_A_PCP_SEL] = "TAG_A_PCP_SEL",
+ [VCAP_AF_TAG_A_TPID_SEL] = "TAG_A_TPID_SEL",
+ [VCAP_AF_TAG_A_VID_SEL] = "TAG_A_VID_SEL",
+ [VCAP_AF_TAG_B_DEI_SEL] = "TAG_B_DEI_SEL",
+ [VCAP_AF_TAG_B_PCP_SEL] = "TAG_B_PCP_SEL",
+ [VCAP_AF_TAG_B_TPID_SEL] = "TAG_B_TPID_SEL",
+ [VCAP_AF_TAG_B_VID_SEL] = "TAG_B_VID_SEL",
+ [VCAP_AF_TAG_C_DEI_SEL] = "TAG_C_DEI_SEL",
+ [VCAP_AF_TAG_C_PCP_SEL] = "TAG_C_PCP_SEL",
+ [VCAP_AF_TAG_C_TPID_SEL] = "TAG_C_TPID_SEL",
+ [VCAP_AF_TAG_C_VID_SEL] = "TAG_C_VID_SEL",
[VCAP_AF_TYPE] = "TYPE",
+ [VCAP_AF_UNTAG_VID_ENA] = "UNTAG_VID_ENA",
+ [VCAP_AF_VID_A_VAL] = "VID_A_VAL",
+ [VCAP_AF_VID_B_VAL] = "VID_B_VAL",
+ [VCAP_AF_VID_C_VAL] = "VID_C_VAL",
[VCAP_AF_VID_REPLACE_ENA] = "VID_REPLACE_ENA",
[VCAP_AF_VID_VAL] = "VID_VAL",
[VCAP_AF_VLAN_POP_CNT] = "VLAN_POP_CNT",
@@ -2996,11 +3237,32 @@ const struct vcap_info lan966x_vcaps[] = {
.keyfield_set_typegroups = is2_keyfield_set_typegroups,
.actionfield_set_typegroups = is2_actionfield_set_typegroups,
},
+ [VCAP_TYPE_ES0] = {
+ .name = "es0",
+ .rows = 256,
+ .sw_count = 1,
+ .sw_width = 96,
+ .sticky_width = 1,
+ .act_width = 65,
+ .default_cnt = 8,
+ .require_cnt_dis = 0,
+ .version = 1,
+ .keyfield_set = es0_keyfield_set,
+ .keyfield_set_size = ARRAY_SIZE(es0_keyfield_set),
+ .actionfield_set = es0_actionfield_set,
+ .actionfield_set_size = ARRAY_SIZE(es0_actionfield_set),
+ .keyfield_set_map = es0_keyfield_set_map,
+ .keyfield_set_map_size = es0_keyfield_set_map_size,
+ .actionfield_set_map = es0_actionfield_set_map,
+ .actionfield_set_map_size = es0_actionfield_set_map_size,
+ .keyfield_set_typegroups = es0_keyfield_set_typegroups,
+ .actionfield_set_typegroups = es0_actionfield_set_typegroups,
+ },
};
const struct vcap_statistics lan966x_vcap_stats = {
.name = "lan966x",
- .count = 2,
+ .count = 3,
.keyfield_set_names = vcap_keyfield_set_names,
.actionfield_set_names = vcap_actionfield_set_names,
.keyfield_names = vcap_keyfield_names,
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c
index d90c08cfcf14..ac525ff1503e 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c
@@ -190,6 +190,26 @@ static void lan966x_vcap_is2_port_keys(struct lan966x_port *port,
out->prf(out->dst, "\n");
}
+static void lan966x_vcap_es0_port_keys(struct lan966x_port *port,
+ struct vcap_admin *admin,
+ struct vcap_output_print *out)
+{
+ struct lan966x *lan966x = port->lan966x;
+ u32 val;
+
+ out->prf(out->dst, " port[%d] (%s): ", port->chip_port,
+ netdev_name(port->dev));
+
+ val = lan_rd(lan966x, REW_PORT_CFG(port->chip_port));
+ out->prf(out->dst, "\n state: ");
+ if (REW_PORT_CFG_ES0_EN_GET(val))
+ out->prf(out->dst, "on");
+ else
+ out->prf(out->dst, "off");
+
+ out->prf(out->dst, "\n");
+}
+
int lan966x_vcap_port_info(struct net_device *dev,
struct vcap_admin *admin,
struct vcap_output_print *out)
@@ -210,6 +230,9 @@ int lan966x_vcap_port_info(struct net_device *dev,
case VCAP_TYPE_IS1:
lan966x_vcap_is1_port_keys(port, admin, out);
break;
+ case VCAP_TYPE_ES0:
+ lan966x_vcap_es0_port_keys(port, admin, out);
+ break;
default:
out->prf(out->dst, " no info\n");
break;
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c
index 7ea8e8633609..a4414f63c9b1 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c
@@ -10,6 +10,12 @@
#define LAN966X_IS1_LOOKUPS 3
#define LAN966X_IS2_LOOKUPS 2
+#define LAN966X_ES0_LOOKUPS 1
+
+#define LAN966X_STAT_ESDX_GRN_BYTES 0x300
+#define LAN966X_STAT_ESDX_GRN_PKTS 0x301
+#define LAN966X_STAT_ESDX_YEL_BYTES 0x302
+#define LAN966X_STAT_ESDX_YEL_PKTS 0x303
static struct lan966x_vcap_inst {
enum vcap_type vtype; /* type of vcap */
@@ -21,6 +27,14 @@ static struct lan966x_vcap_inst {
bool ingress; /* is vcap in the ingress path */
} lan966x_vcap_inst_cfg[] = {
{
+ .vtype = VCAP_TYPE_ES0,
+ .tgt_inst = 0,
+ .lookups = LAN966X_ES0_LOOKUPS,
+ .first_cid = LAN966X_VCAP_CID_ES0_L0,
+ .last_cid = LAN966X_VCAP_CID_ES0_MAX,
+ .count = 64,
+ },
+ {
.vtype = VCAP_TYPE_IS1, /* IS1-0 */
.tgt_inst = 1,
.lookups = LAN966X_IS1_LOOKUPS,
@@ -279,6 +293,8 @@ lan966x_vcap_validate_keyset(struct net_device *dev,
err = lan966x_vcap_is2_get_port_keysets(dev, lookup, &keysetlist,
l3_proto);
break;
+ case VCAP_TYPE_ES0:
+ return kslist->keysets[0];
default:
pr_err("vcap type: %s not supported\n",
lan966x_vcaps[admin->vtype].name);
@@ -338,6 +354,14 @@ static void lan966x_vcap_is2_add_default_fields(struct lan966x_port *port,
VCAP_BIT_0);
}
+static void lan966x_vcap_es0_add_default_fields(struct lan966x_port *port,
+ struct vcap_admin *admin,
+ struct vcap_rule *rule)
+{
+ vcap_rule_add_key_u32(rule, VCAP_KF_IF_EGR_PORT_NO,
+ port->chip_port, GENMASK(4, 0));
+}
+
static void lan966x_vcap_add_default_fields(struct net_device *dev,
struct vcap_admin *admin,
struct vcap_rule *rule)
@@ -351,6 +375,9 @@ static void lan966x_vcap_add_default_fields(struct net_device *dev,
case VCAP_TYPE_IS2:
lan966x_vcap_is2_add_default_fields(port, admin, rule);
break;
+ case VCAP_TYPE_ES0:
+ lan966x_vcap_es0_add_default_fields(port, admin, rule);
+ break;
default:
pr_err("vcap type: %s not supported\n",
lan966x_vcaps[admin->vtype].name);
@@ -366,6 +393,40 @@ static void lan966x_vcap_cache_erase(struct vcap_admin *admin)
memset(&admin->cache.counter, 0, sizeof(admin->cache.counter));
}
+/* The ESDX counter is only used/incremented if the frame has been classified
+ * with an ISDX > 0 (e.g by a rule in IS0). This is not mentioned in the
+ * datasheet.
+ */
+static void lan966x_es0_read_esdx_counter(struct lan966x *lan966x,
+ struct vcap_admin *admin, u32 id)
+{
+ u32 counter;
+
+ id = id & 0xff; /* counter limit */
+ mutex_lock(&lan966x->stats_lock);
+ lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(id), lan966x, SYS_STAT_CFG);
+ counter = lan_rd(lan966x, SYS_CNT(LAN966X_STAT_ESDX_GRN_PKTS)) +
+ lan_rd(lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_PKTS));
+ mutex_unlock(&lan966x->stats_lock);
+ if (counter)
+ admin->cache.counter = counter;
+}
+
+static void lan966x_es0_write_esdx_counter(struct lan966x *lan966x,
+ struct vcap_admin *admin, u32 id)
+{
+ id = id & 0xff; /* counter limit */
+
+ mutex_lock(&lan966x->stats_lock);
+ lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(id), lan966x, SYS_STAT_CFG);
+ lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_GRN_BYTES));
+ lan_wr(admin->cache.counter, lan966x,
+ SYS_CNT(LAN966X_STAT_ESDX_GRN_PKTS));
+ lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_BYTES));
+ lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_PKTS));
+ mutex_unlock(&lan966x->stats_lock);
+}
+
static void lan966x_vcap_cache_write(struct net_device *dev,
struct vcap_admin *admin,
enum vcap_selection sel,
@@ -398,6 +459,9 @@ static void lan966x_vcap_cache_write(struct net_device *dev,
admin->cache.sticky = admin->cache.counter > 0;
lan_wr(admin->cache.counter, lan966x,
VCAP_CNT_DAT(admin->tgt_inst, 0));
+
+ if (admin->vtype == VCAP_TYPE_ES0)
+ lan966x_es0_write_esdx_counter(lan966x, admin, start);
break;
default:
break;
@@ -437,6 +501,9 @@ static void lan966x_vcap_cache_read(struct net_device *dev,
admin->cache.counter =
lan_rd(lan966x, VCAP_CNT_DAT(instance, 0));
admin->cache.sticky = admin->cache.counter > 0;
+
+ if (admin->vtype == VCAP_TYPE_ES0)
+ lan966x_es0_read_esdx_counter(lan966x, admin, start);
}
}
@@ -625,6 +692,12 @@ static void lan966x_vcap_port_key_deselection(struct lan966x *lan966x,
lan_wr(0, lan966x, ANA_VCAP_S2_CFG(p));
break;
+ case VCAP_TYPE_ES0:
+ for (int p = 0; p < lan966x->num_phys_ports; ++p)
+ lan_rmw(REW_PORT_CFG_ES0_EN_SET(false),
+ REW_PORT_CFG_ES0_EN, lan966x,
+ REW_PORT_CFG(p));
+ break;
default:
pr_err("vcap type: %s not supported\n",
lan966x_vcaps[admin->vtype].name);
@@ -674,9 +747,18 @@ int lan966x_vcap_init(struct lan966x *lan966x)
lan_rmw(ANA_VCAP_CFG_S1_ENA_SET(true),
ANA_VCAP_CFG_S1_ENA, lan966x,
ANA_VCAP_CFG(lan966x->ports[p]->chip_port));
+
+ lan_rmw(REW_PORT_CFG_ES0_EN_SET(true),
+ REW_PORT_CFG_ES0_EN, lan966x,
+ REW_PORT_CFG(lan966x->ports[p]->chip_port));
}
}
+ /* Statistics: Use ESDX from ES0 if hit, otherwise no counting */
+ lan_rmw(REW_STAT_CFG_STAT_MODE_SET(1),
+ REW_STAT_CFG_STAT_MODE, lan966x,
+ REW_STAT_CFG);
+
lan966x->vcap_ctrl = ctrl;
return 0;
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
index a7edf524eedb..dc9af480bfea 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
@@ -281,6 +281,7 @@ static int sparx5_create_port(struct sparx5 *sparx5,
spx5_port->custom_etype = 0x8880; /* Vitesse */
spx5_port->phylink_pcs.poll = true;
spx5_port->phylink_pcs.ops = &sparx5_phylink_pcs_ops;
+ spx5_port->phylink_pcs.neg_mode = true;
spx5_port->is_mrouter = false;
INIT_LIST_HEAD(&spx5_port->tc_templates);
sparx5->ports[config->portno] = spx5_port;
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c
index bb97d27a1da4..f8562c1a894d 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c
@@ -91,8 +91,7 @@ static void sparx5_pcs_get_state(struct phylink_pcs *pcs,
state->pause = status.pause;
}
-static int sparx5_pcs_config(struct phylink_pcs *pcs,
- unsigned int mode,
+static int sparx5_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -104,8 +103,9 @@ static int sparx5_pcs_config(struct phylink_pcs *pcs,
conf = port->conf;
conf.power_down = false;
conf.portmode = interface;
- conf.inband = phylink_autoneg_inband(mode);
- conf.autoneg = phylink_test(advertising, Autoneg);
+ conf.inband = neg_mode == PHYLINK_PCS_NEG_INBAND_DISABLED ||
+ neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED;
+ conf.autoneg = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED;
conf.pause_adv = 0;
if (phylink_test(advertising, Pause))
conf.pause_adv |= ADVERTISE_1000XPAUSE;
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_ag_api.h b/drivers/net/ethernet/microchip/vcap/vcap_ag_api.h
index a556c4419986..c3569a4c7b69 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_ag_api.h
+++ b/drivers/net/ethernet/microchip/vcap/vcap_ag_api.h
@@ -3,8 +3,8 @@
* Microchip VCAP API
*/
-/* This file is autogenerated by cml-utils 2023-02-16 11:41:14 +0100.
- * Commit ID: be85f176b3a151fa748dcaf97c8824a5c2e065f3
+/* This file is autogenerated by cml-utils 2023-03-13 10:16:42 +0100.
+ * Commit ID: 259f0efd6d6d91bfbf62858de153cc757b6bffa3 (dirty)
*/
#ifndef __VCAP_AG_API__
@@ -51,6 +51,7 @@ enum vcap_keyfield_set {
VCAP_KFS_RT, /* lan966x is1 X1 */
VCAP_KFS_SMAC_SIP4, /* lan966x is2 X1 */
VCAP_KFS_SMAC_SIP6, /* lan966x is2 X2 */
+ VCAP_KFS_VID, /* lan966x es0 X1 */
};
/* List of keyfields with description
@@ -79,7 +80,7 @@ enum vcap_keyfield_set {
* Second DEI in multiple vlan tags (inner tag)
* VCAP_KF_8021Q_DEI2: W1, sparx5: is0
* Third DEI in multiple vlan tags (not always available)
- * VCAP_KF_8021Q_DEI_CLS: W1, sparx5: is2/es2, lan966x: is2
+ * VCAP_KF_8021Q_DEI_CLS: W1, sparx5: is2/es2, lan966x: is2/es0
* Classified DEI
* VCAP_KF_8021Q_PCP0: W3, sparx5: is0, lan966x: is1
* First PCP in multiple vlan tags (outer tag or default port tag)
@@ -87,7 +88,7 @@ enum vcap_keyfield_set {
* Second PCP in multiple vlan tags (inner tag)
* VCAP_KF_8021Q_PCP2: W3, sparx5: is0
* Third PCP in multiple vlan tags (not always available)
- * VCAP_KF_8021Q_PCP_CLS: W3, sparx5: is2/es2, lan966x: is2
+ * VCAP_KF_8021Q_PCP_CLS: W3, sparx5: is2/es2, lan966x: is2/es0
* Classified PCP
* VCAP_KF_8021Q_TPID: W3, sparx5: es0
* TPID for outer tag: 0: Customer TPID 1: Service TPID (88A8 or programmable)
@@ -104,7 +105,7 @@ enum vcap_keyfield_set {
* VCAP_KF_8021Q_VID2: W12, sparx5: is0
* Third VID in multiple vlan tags (not always available)
* VCAP_KF_8021Q_VID_CLS: sparx5 is2 W13, sparx5 es0 W13, sparx5 es2 W13,
- * lan966x is2 W12
+ * lan966x is2 W12, lan966x es0 W12
* Classified VID
* VCAP_KF_8021Q_VLAN_DBL_TAGGED_IS: W1, lan966x: is1
* Set if frame has two or more Q-tags. Independent of port VLAN awareness
@@ -146,10 +147,10 @@ enum vcap_keyfield_set {
* VCAP_KF_IF_EGR_PORT_MASK_RNG: W3, sparx5: es2
* Select which 32 port group is available in IF_EGR_PORT (or virtual ports or
* CPU queue)
- * VCAP_KF_IF_EGR_PORT_NO: W7, sparx5: es0
+ * VCAP_KF_IF_EGR_PORT_NO: sparx5 es0 W7, lan966x es0 W4
* Egress port number
* VCAP_KF_IF_IGR_PORT: sparx5 is0 W7, sparx5 es2 W9, lan966x is1 W3, lan966x
- * is2 W4
+ * is2 W4, lan966x es0 W4
* Sparx5: Logical ingress port number retrieved from
* ANA_CL::PORT_ID_CFG.LPORT_NUM or ERLEG, LAN966x: ingress port nunmber
* VCAP_KF_IF_IGR_PORT_MASK: sparx5 is0 W65, sparx5 is2 W32, sparx5 is2 W65,
@@ -178,11 +179,12 @@ enum vcap_keyfield_set {
* Payload after IPv6 header
* VCAP_KF_IP_SNAP_IS: W1, sparx5: is0, lan966x: is1
* Set if frame is IPv4, IPv6, or SNAP frame
- * VCAP_KF_ISDX_CLS: W12, sparx5: is2/es0/es2
+ * VCAP_KF_ISDX_CLS: sparx5 is2 W12, sparx5 es0 W12, sparx5 es2 W12, lan966x es0
+ * W8
* Classified ISDX
- * VCAP_KF_ISDX_GT0_IS: W1, sparx5: is2/es0/es2, lan966x: is2
+ * VCAP_KF_ISDX_GT0_IS: W1, sparx5: is2/es0/es2, lan966x: is2/es0
* Set if classified ISDX > 0
- * VCAP_KF_L2_BC_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2
+ * VCAP_KF_L2_BC_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2/es0
* Set if frame's destination MAC address is the broadcast address
* (FF-FF-FF-FF-FF-FF).
* VCAP_KF_L2_DMAC: W48, sparx5: is0/is2/es2, lan966x: is1/is2
@@ -195,7 +197,7 @@ enum vcap_keyfield_set {
* LLC header and data after up to two VLAN tags and the type/length field
* VCAP_KF_L2_MAC: W48, lan966x: is1
* MAC address (FIRST=1: SMAC, FIRST=0: DMAC)
- * VCAP_KF_L2_MC_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2
+ * VCAP_KF_L2_MC_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2/es0
* Set if frame's destination MAC address is a multicast address (bit 40 = 1).
* VCAP_KF_L2_PAYLOAD0: W16, lan966x: is2
* Payload bytes 0-1 after the frame's EtherType
@@ -213,7 +215,7 @@ enum vcap_keyfield_set {
* SNAP header after LLC header (AA-AA-03)
* VCAP_KF_L3_DIP_EQ_SIP_IS: W1, sparx5: is2/es2, lan966x: is2
* Set if Src IP matches Dst IP address
- * VCAP_KF_L3_DPL_CLS: W1, sparx5: es0/es2
+ * VCAP_KF_L3_DPL_CLS: W1, sparx5: es0/es2, lan966x: es0
* The frames drop precedence level
* VCAP_KF_L3_DSCP: W6, sparx5: is0, lan966x: is1
* Frame's DSCP value
@@ -330,8 +332,12 @@ enum vcap_keyfield_set {
* Frame's OAM version
* VCAP_KF_OAM_Y1731_IS: W1, sparx5: is2/es2, lan966x: is2
* Set if frame's EtherType = 0x8902
+ * VCAP_KF_PDU_TYPE: W4, lan966x: es0
+ * PDU type value (none, OAM CCM, MRP, DLR, RTE, IPv4, IPv6, OAM non-CCM)
* VCAP_KF_PROT_ACTIVE: W1, sparx5: es0/es2
* Protection is active
+ * VCAP_KF_RTP_ID: W10, lan966x: es0
+ * Classified RTP_ID
* VCAP_KF_RT_FRMID: W32, lan966x: is1
* Profinet or OPC-UA FrameId
* VCAP_KF_RT_TYPE: W2, lan966x: is1
@@ -470,7 +476,9 @@ enum vcap_key_field {
VCAP_KF_OAM_OPCODE,
VCAP_KF_OAM_VER,
VCAP_KF_OAM_Y1731_IS,
+ VCAP_KF_PDU_TYPE,
VCAP_KF_PROT_ACTIVE,
+ VCAP_KF_RTP_ID,
VCAP_KF_RT_FRMID,
VCAP_KF_RT_TYPE,
VCAP_KF_RT_VLAN_IDX,
@@ -489,6 +497,7 @@ enum vcap_actionfield_set {
VCAP_AFS_FULL, /* sparx5 is0 X3 */
VCAP_AFS_S1, /* lan966x is1 X1 */
VCAP_AFS_SMAC_SIP, /* lan966x is2 X1 */
+ VCAP_AFS_VID, /* lan966x es0 X1 */
};
/* List of actionfields with description
@@ -523,9 +532,9 @@ enum vcap_actionfield_set {
* while bits 1:0 control first lookup. Encoding per lookup: 0: Disabled. 1:
* Extract 40 bytes after position corresponding to the location of the IPv4
* header and use as key. 2: Extract 40 bytes after SMAC and use as key
- * VCAP_AF_DEI_A_VAL: W1, sparx5: es0
+ * VCAP_AF_DEI_A_VAL: W1, sparx5: es0, lan966x: es0
* DEI used in ES0 tag A. See TAG_A_DEI_SEL.
- * VCAP_AF_DEI_B_VAL: W1, sparx5: es0
+ * VCAP_AF_DEI_B_VAL: W1, sparx5: es0, lan966x: es0
* DEI used in ES0 tag B. See TAG_B_DEI_SEL.
* VCAP_AF_DEI_C_VAL: W1, sparx5: es0
* DEI used in ES0 tag C. See TAG_C_DEI_SEL.
@@ -556,7 +565,7 @@ enum vcap_actionfield_set {
* VCAP_AF_ES2_REW_CMD: W3, sparx5: es2
* Command forwarded to REW: 0: No action. 1: SWAP MAC addresses. 2: Do L2CP
* DMAC translation when entering or leaving a tunnel.
- * VCAP_AF_ESDX: W13, sparx5: es0
+ * VCAP_AF_ESDX: sparx5 es0 W13, lan966x es0 W8
* Egress counter index. Used to index egress counter set as defined in
* REW::STAT_CFG.
* VCAP_AF_FWD_KILL_ENA: W1, lan966x: is2
@@ -652,9 +661,9 @@ enum vcap_actionfield_set {
* (input) AND ~PAG_OVERRIDE_MASK) OR (PAG_VAL AND PAG_OVERRIDE_MASK)
* VCAP_AF_PAG_VAL: W8, sparx5: is0, lan966x: is1
* See PAG_OVERRIDE_MASK.
- * VCAP_AF_PCP_A_VAL: W3, sparx5: es0
+ * VCAP_AF_PCP_A_VAL: W3, sparx5: es0, lan966x: es0
* PCP used in ES0 tag A. See TAG_A_PCP_SEL.
- * VCAP_AF_PCP_B_VAL: W3, sparx5: es0
+ * VCAP_AF_PCP_B_VAL: W3, sparx5: es0, lan966x: es0
* PCP used in ES0 tag B. See TAG_B_PCP_SEL.
* VCAP_AF_PCP_C_VAL: W3, sparx5: es0
* PCP used in ES0 tag C. See TAG_C_PCP_SEL.
@@ -691,10 +700,10 @@ enum vcap_actionfield_set {
* Selects tag C mode: 0: Do not push tag C. 1: Push tag C if
* IFH.VSTAX.TAG.WAS_TAGGED = 1. 2: Push tag C if IFH.VSTAX.TAG.WAS_TAGGED = 0.
* 3: Push tag C if UNTAG_VID_ENA = 0 or (C-TAG.VID ! = VID_C_VAL).
- * VCAP_AF_PUSH_INNER_TAG: W1, sparx5: es0
+ * VCAP_AF_PUSH_INNER_TAG: W1, sparx5: es0, lan966x: es0
* Controls inner tagging. 0: Do not push ES0 tag B as inner tag. 1: Push ES0
* tag B as inner tag.
- * VCAP_AF_PUSH_OUTER_TAG: W2, sparx5: es0
+ * VCAP_AF_PUSH_OUTER_TAG: W2, sparx5: es0, lan966x: es0
* Controls outer tagging. 0: No ES0 tag A: Port tag is allowed if enabled on
* port. 1: ES0 tag A: Push ES0 tag A. No port tag. 2: Force port tag: Always
* push port tag. No ES0 tag A. 3: Force untag: Never push port tag or ES0 tag
@@ -720,29 +729,29 @@ enum vcap_actionfield_set {
* VCAP_AF_SWAP_MACS_ENA: W1, sparx5: es0
* This setting is only active when FWD_SEL = 1 or FWD_SEL = 2 and PIPELINE_ACT
* = LBK_ASM. 0: No action. 1: Swap MACs and clear bit 40 in new SMAC.
- * VCAP_AF_TAG_A_DEI_SEL: W3, sparx5: es0
+ * VCAP_AF_TAG_A_DEI_SEL: sparx5 es0 W3, lan966x es0 W2
* Selects PCP for ES0 tag A. 0: Classified DEI. 1: DEI_A_VAL. 2: DP and QoS
* mapped to PCP (per port table). 3: DP.
- * VCAP_AF_TAG_A_PCP_SEL: W3, sparx5: es0
+ * VCAP_AF_TAG_A_PCP_SEL: sparx5 es0 W3, lan966x es0 W2
* Selects PCP for ES0 tag A. 0: Classified PCP. 1: PCP_A_VAL. 2: DP and QoS
* mapped to PCP (per port table). 3: QoS class.
- * VCAP_AF_TAG_A_TPID_SEL: W3, sparx5: es0
+ * VCAP_AF_TAG_A_TPID_SEL: sparx5 es0 W3, lan966x es0 W2
* Selects TPID for ES0 tag A: 0: 0x8100. 1: 0x88A8. 2: Custom
* (REW:PORT:PORT_VLAN_CFG.PORT_TPID). 3: If IFH.TAG_TYPE = 0 then 0x8100 else
* custom.
- * VCAP_AF_TAG_A_VID_SEL: W2, sparx5: es0
+ * VCAP_AF_TAG_A_VID_SEL: sparx5 es0 W2, lan966x es0 W1
* Selects VID for ES0 tag A. 0: Classified VID + VID_A_VAL. 1: VID_A_VAL.
- * VCAP_AF_TAG_B_DEI_SEL: W3, sparx5: es0
+ * VCAP_AF_TAG_B_DEI_SEL: sparx5 es0 W3, lan966x es0 W2
* Selects PCP for ES0 tag B. 0: Classified DEI. 1: DEI_B_VAL. 2: DP and QoS
* mapped to PCP (per port table). 3: DP.
- * VCAP_AF_TAG_B_PCP_SEL: W3, sparx5: es0
+ * VCAP_AF_TAG_B_PCP_SEL: sparx5 es0 W3, lan966x es0 W2
* Selects PCP for ES0 tag B. 0: Classified PCP. 1: PCP_B_VAL. 2: DP and QoS
* mapped to PCP (per port table). 3: QoS class.
- * VCAP_AF_TAG_B_TPID_SEL: W3, sparx5: es0
+ * VCAP_AF_TAG_B_TPID_SEL: sparx5 es0 W3, lan966x es0 W2
* Selects TPID for ES0 tag B. 0: 0x8100. 1: 0x88A8. 2: Custom
* (REW:PORT:PORT_VLAN_CFG.PORT_TPID). 3: If IFH.TAG_TYPE = 0 then 0x8100 else
* custom.
- * VCAP_AF_TAG_B_VID_SEL: W2, sparx5: es0
+ * VCAP_AF_TAG_B_VID_SEL: sparx5 es0 W2, lan966x es0 W1
* Selects VID for ES0 tag B. 0: Classified VID + VID_B_VAL. 1: VID_B_VAL.
* VCAP_AF_TAG_C_DEI_SEL: W3, sparx5: es0
* Selects DEI source for ES0 tag C. 0: Classified DEI. 1: DEI_C_VAL. 2:
@@ -770,9 +779,9 @@ enum vcap_actionfield_set {
* VCAP_AF_UNTAG_VID_ENA: W1, sparx5: es0
* Controls insertion of tag C. Untag or insert mode can be selected. See
* PUSH_CUSTOMER_TAG.
- * VCAP_AF_VID_A_VAL: W12, sparx5: es0
+ * VCAP_AF_VID_A_VAL: W12, sparx5: es0, lan966x: es0
* VID used in ES0 tag A. See TAG_A_VID_SEL.
- * VCAP_AF_VID_B_VAL: W12, sparx5: es0
+ * VCAP_AF_VID_B_VAL: W12, sparx5: es0, lan966x: es0
* VID used in ES0 tag B. See TAG_B_VID_SEL.
* VCAP_AF_VID_C_VAL: W12, sparx5: es0
* VID used in ES0 tag C. See TAG_C_VID_SEL.
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.c b/drivers/net/ethernet/microchip/vcap/vcap_api.c
index 5675b0962bc3..a418ad8e8770 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api.c
@@ -1121,7 +1121,7 @@ static void vcap_copy_to_client_actionfield(struct vcap_rule_internal *ri,
vcap_copy_from_w32be(field->data.u128.value, value,
field_size, width);
break;
- };
+ }
} else {
switch (field->ctrl.type) {
case VCAP_FIELD_BIT:
@@ -1162,7 +1162,7 @@ static void vcap_copy_to_client_actionfield(struct vcap_rule_internal *ri,
value,
width, field_size);
break;
- };
+ }
}
}
@@ -1236,7 +1236,7 @@ static void vcap_copy_to_client_keyfield(struct vcap_rule_internal *ri,
vcap_copy_from_w32be(field->data.u128.mask, mask,
field_size, width);
break;
- };
+ }
} else {
switch (field->ctrl.type) {
case VCAP_FIELD_BIT:
@@ -1284,7 +1284,7 @@ static void vcap_copy_to_client_keyfield(struct vcap_rule_internal *ri,
value, mask,
width, field_size);
break;
- };
+ }
}
}
diff --git a/drivers/net/ethernet/microsoft/mana/hw_channel.c b/drivers/net/ethernet/microsoft/mana/hw_channel.c
index 9d1507eba5b9..2bd1d74021f7 100644
--- a/drivers/net/ethernet/microsoft/mana/hw_channel.c
+++ b/drivers/net/ethernet/microsoft/mana/hw_channel.c
@@ -627,7 +627,7 @@ static int mana_hwc_establish_channel(struct gdma_context *gc, u16 *q_depth,
if (WARN_ON(cq->id >= gc->max_num_cqs))
return -EPROTO;
- gc->cq_table = vzalloc(gc->max_num_cqs * sizeof(struct gdma_queue *));
+ gc->cq_table = vcalloc(gc->max_num_cqs, sizeof(struct gdma_queue *));
if (!gc->cq_table)
return -ENOMEM;
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index d907727c7b7a..c2ad0921e893 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -8,6 +8,7 @@
#include <linux/ethtool.h>
#include <linux/filter.h>
#include <linux/mm.h>
+#include <linux/pci.h>
#include <net/checksum.h>
#include <net/ip6_checksum.h>
@@ -179,6 +180,14 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
pkg.tx_oob.s_oob.short_vp_offset = txq->vp_offset;
}
+ if (skb_vlan_tag_present(skb)) {
+ pkt_fmt = MANA_LONG_PKT_FMT;
+ pkg.tx_oob.l_oob.inject_vlan_pri_tag = 1;
+ pkg.tx_oob.l_oob.pcp = skb_vlan_tag_get_prio(skb);
+ pkg.tx_oob.l_oob.dei = skb_vlan_tag_get_cfi(skb);
+ pkg.tx_oob.l_oob.vlan_id = skb_vlan_tag_get_id(skb);
+ }
+
pkg.tx_oob.s_oob.pkt_fmt = pkt_fmt;
if (pkt_fmt == MANA_SHORT_PKT_FMT) {
@@ -972,7 +981,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;
@@ -987,6 +996,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);
@@ -996,6 +1007,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);
@@ -1457,6 +1469,12 @@ static void mana_rx_skb(void *buf_va, struct mana_rxcomp_oob *cqe,
skb_set_hash(skb, hash_value, PKT_HASH_TYPE_L3);
}
+ if (cqe->rx_vlantag_present) {
+ u16 vlan_tci = cqe->rx_vlan_id;
+
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci);
+ }
+
u64_stats_update_begin(&rx_stats->syncp);
rx_stats->packets++;
rx_stats->bytes += pkt_len;
@@ -2328,9 +2346,12 @@ int mana_attach(struct net_device *ndev)
static int mana_dealloc_queues(struct net_device *ndev)
{
struct mana_port_context *apc = netdev_priv(ndev);
+ unsigned long timeout = jiffies + 120 * HZ;
struct gdma_dev *gd = apc->ac->gdma_dev;
struct mana_txq *txq;
+ struct sk_buff *skb;
int i, err;
+ u32 tsleep;
if (apc->port_is_up)
return -EINVAL;
@@ -2346,15 +2367,40 @@ static int mana_dealloc_queues(struct net_device *ndev)
* to false, but it doesn't matter since mana_start_xmit() drops any
* new packets due to apc->port_is_up being false.
*
- * Drain all the in-flight TX packets
+ * Drain all the in-flight TX packets.
+ * A timeout of 120 seconds for all the queues is used.
+ * This will break the while loop when h/w is not responding.
+ * This value of 120 has been decided here considering max
+ * number of queues.
*/
+
for (i = 0; i < apc->num_queues; i++) {
txq = &apc->tx_qp[i].txq;
-
- while (atomic_read(&txq->pending_sends) > 0)
- usleep_range(1000, 2000);
+ tsleep = 1000;
+ while (atomic_read(&txq->pending_sends) > 0 &&
+ time_before(jiffies, timeout)) {
+ usleep_range(tsleep, tsleep + 1000);
+ tsleep <<= 1;
+ }
+ if (atomic_read(&txq->pending_sends)) {
+ err = pcie_flr(to_pci_dev(gd->gdma_context->dev));
+ if (err) {
+ netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
+ err, atomic_read(&txq->pending_sends),
+ txq->gdma_txq_id);
+ }
+ break;
+ }
}
+ for (i = 0; i < apc->num_queues; i++) {
+ txq = &apc->tx_qp[i].txq;
+ while ((skb = skb_dequeue(&txq->pending_skbs))) {
+ mana_unmap_skb(skb, apc);
+ dev_kfree_skb_any(skb);
+ }
+ atomic_set(&txq->pending_sends, 0);
+ }
/* We're 100% sure the queues can no longer be woken up, because
* we're sure now mana_poll_tx_cq() can't be running.
*/
@@ -2451,8 +2497,9 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
ndev->hw_features |= NETIF_F_RXCSUM;
ndev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
ndev->hw_features |= NETIF_F_RXHASH;
- ndev->features = ndev->hw_features;
- ndev->vlan_features = 0;
+ ndev->features = ndev->hw_features | NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_CTAG_RX;
+ ndev->vlan_features = ndev->features;
ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
NETDEV_XDP_ACT_NDO_XMIT;
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 1f5f00b30441..56ccbd4c37fe 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -2925,10 +2925,8 @@ int ocelot_init(struct ocelot *ocelot)
}
}
- mutex_init(&ocelot->ptp_lock);
mutex_init(&ocelot->mact_lock);
mutex_init(&ocelot->fwd_domain_lock);
- mutex_init(&ocelot->tas_lock);
spin_lock_init(&ocelot->ptp_clock_lock);
spin_lock_init(&ocelot->ts_id_lock);
diff --git a/drivers/net/ethernet/mscc/ocelot_fdma.c b/drivers/net/ethernet/mscc/ocelot_fdma.c
index 8e3894cf5f7c..83a3ce0c568e 100644
--- a/drivers/net/ethernet/mscc/ocelot_fdma.c
+++ b/drivers/net/ethernet/mscc/ocelot_fdma.c
@@ -368,7 +368,8 @@ static bool ocelot_fdma_receive_skb(struct ocelot *ocelot, struct sk_buff *skb)
if (unlikely(!ndev))
return false;
- pskb_trim(skb, skb->len - ETH_FCS_LEN);
+ if (pskb_trim(skb, skb->len - ETH_FCS_LEN))
+ return false;
skb->dev = ndev;
skb->protocol = eth_type_trans(skb, skb->dev);
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index ee052404eb55..e0916afcddfb 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -592,6 +592,16 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress,
return -EOPNOTSUPP;
}
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) {
+ struct flow_match_meta match;
+
+ flow_rule_match_meta(rule, &match);
+ if (match.mask->l2_miss) {
+ NL_SET_ERR_MSG_MOD(extack, "Can't match on \"l2_miss\"");
+ return -EOPNOTSUPP;
+ }
+ }
+
/* For VCAP ES0 (egress rewriter) we can match on the ingress port */
if (!ingress) {
ret = ocelot_flower_parse_indev(ocelot, port, f, filter);
diff --git a/drivers/net/ethernet/mscc/ocelot_mm.c b/drivers/net/ethernet/mscc/ocelot_mm.c
index fb3145118d68..c815ae64e39d 100644
--- a/drivers/net/ethernet/mscc/ocelot_mm.c
+++ b/drivers/net/ethernet/mscc/ocelot_mm.c
@@ -67,10 +67,13 @@ void ocelot_port_update_active_preemptible_tcs(struct ocelot *ocelot, int port)
val = mm->preemptible_tcs;
/* Cut through switching doesn't work for preemptible priorities,
- * so first make sure it is disabled.
+ * so first make sure it is disabled. Also, changing the preemptible
+ * TCs affects the oversized frame dropping logic, so that needs to be
+ * re-triggered. And since tas_guard_bands_update() also implicitly
+ * calls cut_through_fwd(), we don't need to explicitly call it.
*/
mm->active_preemptible_tcs = val;
- ocelot->ops->cut_through_fwd(ocelot);
+ ocelot->ops->tas_guard_bands_update(ocelot, port);
dev_dbg(ocelot->dev,
"port %d %s/%s, MM TX %s, preemptible TCs 0x%x, active 0x%x\n",
@@ -89,17 +92,14 @@ void ocelot_port_change_fp(struct ocelot *ocelot, int port,
{
struct ocelot_mm_state *mm = &ocelot->mm[port];
- mutex_lock(&ocelot->fwd_domain_lock);
+ lockdep_assert_held(&ocelot->fwd_domain_lock);
if (mm->preemptible_tcs == preemptible_tcs)
- goto out_unlock;
+ return;
mm->preemptible_tcs = preemptible_tcs;
ocelot_port_update_active_preemptible_tcs(ocelot, port);
-
-out_unlock:
- mutex_unlock(&ocelot->fwd_domain_lock);
}
static void ocelot_mm_update_port_status(struct ocelot *ocelot, int port)
diff --git a/drivers/net/ethernet/mscc/ocelot_ptp.c b/drivers/net/ethernet/mscc/ocelot_ptp.c
index 2180ae94c744..cb32234a5bf1 100644
--- a/drivers/net/ethernet/mscc/ocelot_ptp.c
+++ b/drivers/net/ethernet/mscc/ocelot_ptp.c
@@ -439,8 +439,12 @@ static int ocelot_ipv6_ptp_trap_del(struct ocelot *ocelot, int port)
static int ocelot_setup_ptp_traps(struct ocelot *ocelot, int port,
bool l2, bool l4)
{
+ struct ocelot_port *ocelot_port = ocelot->ports[port];
int err;
+ ocelot_port->trap_proto &= ~(OCELOT_PROTO_PTP_L2 |
+ OCELOT_PROTO_PTP_L4);
+
if (l2)
err = ocelot_l2_ptp_trap_add(ocelot, port);
else
@@ -464,6 +468,11 @@ static int ocelot_setup_ptp_traps(struct ocelot *ocelot, int port,
if (err)
return err;
+ if (l2)
+ ocelot_port->trap_proto |= OCELOT_PROTO_PTP_L2;
+ if (l4)
+ ocelot_port->trap_proto |= OCELOT_PROTO_PTP_L4;
+
return 0;
err_ipv6:
@@ -474,10 +483,38 @@ err_ipv4:
return err;
}
+static int ocelot_traps_to_ptp_rx_filter(unsigned int proto)
+{
+ if ((proto & OCELOT_PROTO_PTP_L2) && (proto & OCELOT_PROTO_PTP_L4))
+ return HWTSTAMP_FILTER_PTP_V2_EVENT;
+ else if (proto & OCELOT_PROTO_PTP_L2)
+ return HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
+ else if (proto & OCELOT_PROTO_PTP_L4)
+ return HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
+
+ return HWTSTAMP_FILTER_NONE;
+}
+
int ocelot_hwstamp_get(struct ocelot *ocelot, int port, struct ifreq *ifr)
{
- return copy_to_user(ifr->ifr_data, &ocelot->hwtstamp_config,
- sizeof(ocelot->hwtstamp_config)) ? -EFAULT : 0;
+ struct ocelot_port *ocelot_port = ocelot->ports[port];
+ struct hwtstamp_config cfg = {};
+
+ switch (ocelot_port->ptp_cmd) {
+ case IFH_REW_OP_TWO_STEP_PTP:
+ cfg.tx_type = HWTSTAMP_TX_ON;
+ break;
+ case IFH_REW_OP_ORIGIN_PTP:
+ cfg.tx_type = HWTSTAMP_TX_ONESTEP_SYNC;
+ break;
+ default:
+ cfg.tx_type = HWTSTAMP_TX_OFF;
+ break;
+ }
+
+ cfg.rx_filter = ocelot_traps_to_ptp_rx_filter(ocelot_port->trap_proto);
+
+ return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
}
EXPORT_SYMBOL(ocelot_hwstamp_get);
@@ -509,8 +546,6 @@ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
return -ERANGE;
}
- mutex_lock(&ocelot->ptp_lock);
-
switch (cfg.rx_filter) {
case HWTSTAMP_FILTER_NONE:
break;
@@ -531,28 +566,14 @@ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
l4 = true;
break;
default:
- mutex_unlock(&ocelot->ptp_lock);
return -ERANGE;
}
err = ocelot_setup_ptp_traps(ocelot, port, l2, l4);
- if (err) {
- mutex_unlock(&ocelot->ptp_lock);
+ if (err)
return err;
- }
- if (l2 && l4)
- cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
- else if (l2)
- cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
- else if (l4)
- cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
- else
- cfg.rx_filter = HWTSTAMP_FILTER_NONE;
-
- /* Commit back the result & save it */
- memcpy(&ocelot->hwtstamp_config, &cfg, sizeof(cfg));
- mutex_unlock(&ocelot->ptp_lock);
+ cfg.rx_filter = ocelot_traps_to_ptp_rx_filter(ocelot_port->trap_proto);
return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
}
@@ -824,11 +845,6 @@ int ocelot_init_timestamp(struct ocelot *ocelot,
ocelot_write(ocelot, PTP_CFG_MISC_PTP_EN, PTP_CFG_MISC);
- /* There is no device reconfiguration, PTP Rx stamping is always
- * enabled.
- */
- ocelot->hwtstamp_config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
-
return 0;
}
EXPORT_SYMBOL(ocelot_init_timestamp);
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index c5687d94ea88..7b7e1c5b00f4 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -66,6 +66,7 @@
#include <linux/slab.h>
#include <linux/prefetch.h>
#include <net/checksum.h>
+#include <net/gso.h>
#include <net/ip.h>
#include <net/tcp.h>
#include <asm/byteorder.h>
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
index bf6bae557158..8c6954c58a88 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
@@ -311,8 +311,6 @@ nfp_devlink_flash_update(struct devlink *devlink,
}
const struct devlink_ops nfp_devlink_ops = {
- .port_split = nfp_devlink_port_split,
- .port_unsplit = nfp_devlink_port_unsplit,
.sb_pool_get = nfp_devlink_sb_pool_get,
.sb_pool_set = nfp_devlink_sb_pool_set,
.eswitch_mode_get = nfp_devlink_eswitch_mode_get,
@@ -321,6 +319,11 @@ const struct devlink_ops nfp_devlink_ops = {
.flash_update = nfp_devlink_flash_update,
};
+static const struct devlink_port_ops nfp_devlink_port_ops = {
+ .port_split = nfp_devlink_port_split,
+ .port_unsplit = nfp_devlink_port_unsplit,
+};
+
int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port)
{
struct devlink_port_attrs attrs = {};
@@ -351,7 +354,8 @@ int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port)
devlink = priv_to_devlink(app->pf);
- return devl_port_register(devlink, &port->dl_port, port->eth_id);
+ return devl_port_register_with_ops(devlink, &port->dl_port,
+ port->eth_id, &nfp_devlink_port_ops);
}
void nfp_devlink_port_unregister(struct nfp_port *port)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 62f0bf91d1e1..6b1fb5708434 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -53,6 +53,8 @@
#include "crypto/crypto.h"
#include "crypto/fw.h"
+static int nfp_net_mc_unsync(struct net_device *netdev, const unsigned char *addr);
+
/**
* nfp_net_get_fw_version() - Read and parse the FW version
* @fw_ver: Output fw_version structure to read to
@@ -598,7 +600,7 @@ nfp_net_tls_tx(struct nfp_net_dp *dp, struct nfp_net_r_vector *r_vec,
if (likely(!dp->ktls_tx))
return skb;
- if (!skb->sk || !tls_is_sk_tx_device_offloaded(skb->sk))
+ if (!tls_is_skb_tx_device_offloaded(skb))
return skb;
datalen = skb->len - skb_tcp_all_headers(skb);
@@ -666,7 +668,7 @@ void nfp_net_tls_tx_undo(struct sk_buff *skb, u64 tls_handle)
if (!tls_handle)
return;
- if (WARN_ON_ONCE(!skb->sk || !tls_is_sk_tx_device_offloaded(skb->sk)))
+ if (WARN_ON_ONCE(!tls_is_skb_tx_device_offloaded(skb)))
return;
datalen = skb->len - skb_tcp_all_headers(skb);
@@ -1084,6 +1086,9 @@ static int nfp_net_netdev_close(struct net_device *netdev)
/* Step 2: Tell NFP
*/
+ if (nn->cap_w1 & NFP_NET_CFG_CTRL_MCAST_FILTER)
+ __dev_mc_unsync(netdev, nfp_net_mc_unsync);
+
nfp_net_clear_config_and_disable(nn);
nfp_port_configure(netdev, false);
@@ -2418,6 +2423,8 @@ static void nfp_net_rss_init(struct nfp_net *nn)
/* Enable IPv4/IPv6 TCP by default */
nn->rss_cfg = NFP_NET_CFG_RSS_IPV4_TCP |
NFP_NET_CFG_RSS_IPV6_TCP |
+ NFP_NET_CFG_RSS_IPV4_UDP |
+ NFP_NET_CFG_RSS_IPV6_UDP |
FIELD_PREP(NFP_NET_CFG_RSS_HFUNC, nn->rss_hfunc) |
NFP_NET_CFG_RSS_MASK;
}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
index dfedb52b7e70..e75cbb287625 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
@@ -436,49 +436,41 @@ static void nfp_add_media_link_mode(struct nfp_port *port,
struct nfp_eth_table_port *eth_port,
struct ethtool_link_ksettings *cmd)
{
- u64 supported_modes[2], advertised_modes[2];
- struct nfp_eth_media_buf ethm = {
- .eth_index = eth_port->eth_index,
- };
- struct nfp_cpp *cpp = port->app->cpp;
-
- if (nfp_eth_read_media(cpp, &ethm)) {
- bitmap_fill(port->speed_bitmap, NFP_SUP_SPEED_NUMBER);
- return;
- }
-
bitmap_zero(port->speed_bitmap, NFP_SUP_SPEED_NUMBER);
- for (u32 i = 0; i < 2; i++) {
- supported_modes[i] = le64_to_cpu(ethm.supported_modes[i]);
- advertised_modes[i] = le64_to_cpu(ethm.advertised_modes[i]);
- }
-
for (u32 i = 0; i < NFP_MEDIA_LINK_MODES_NUMBER; i++) {
if (i < 64) {
- if (supported_modes[0] & BIT_ULL(i)) {
+ if (eth_port->link_modes_supp[0] & BIT_ULL(i)) {
__set_bit(nfp_eth_media_table[i].ethtool_link_mode,
cmd->link_modes.supported);
__set_bit(nfp_eth_media_table[i].speed,
port->speed_bitmap);
}
- if (advertised_modes[0] & BIT_ULL(i))
+ if (eth_port->link_modes_ad[0] & BIT_ULL(i))
__set_bit(nfp_eth_media_table[i].ethtool_link_mode,
cmd->link_modes.advertising);
} else {
- if (supported_modes[1] & BIT_ULL(i - 64)) {
+ if (eth_port->link_modes_supp[1] & BIT_ULL(i - 64)) {
__set_bit(nfp_eth_media_table[i].ethtool_link_mode,
cmd->link_modes.supported);
__set_bit(nfp_eth_media_table[i].speed,
port->speed_bitmap);
}
- if (advertised_modes[1] & BIT_ULL(i - 64))
+ if (eth_port->link_modes_ad[1] & BIT_ULL(i - 64))
__set_bit(nfp_eth_media_table[i].ethtool_link_mode,
cmd->link_modes.advertising);
}
}
+
+ /* We take all speeds as supported when it fails to read
+ * link modes due to old management firmware that doesn't
+ * support link modes reading or error occurring, so that
+ * speed change of this port is allowed.
+ */
+ if (bitmap_empty(port->speed_bitmap, NFP_SUP_SPEED_NUMBER))
+ bitmap_fill(port->speed_bitmap, NFP_SUP_SPEED_NUMBER);
}
/**
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h
index 781edc451bd4..6e044ac04917 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h
@@ -196,6 +196,9 @@ enum nfp_ethtool_link_mode_list {
* subports)
* @ports.is_split: is interface part of a split port
* @ports.fec_modes_supported: bitmap of FEC modes supported
+ *
+ * @ports.link_modes_supp: bitmap of link modes supported
+ * @ports.link_modes_ad: bitmap of link modes advertised
*/
struct nfp_eth_table {
unsigned int count;
@@ -235,6 +238,9 @@ struct nfp_eth_table {
bool is_split;
unsigned int fec_modes_supported;
+
+ u64 link_modes_supp[2];
+ u64 link_modes_ad[2];
} ports[];
};
@@ -313,7 +319,6 @@ struct nfp_eth_media_buf {
};
int nfp_nsp_read_media(struct nfp_nsp *state, void *buf, unsigned int size);
-int nfp_eth_read_media(struct nfp_cpp *cpp, struct nfp_eth_media_buf *ethm);
#define NFP_NSP_VERSION_BUFSZ 1024 /* reasonable size, not in the ABI */
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c
index 570ac1bb2122..9d62085d772a 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c
@@ -227,6 +227,30 @@ nfp_eth_calc_port_type(struct nfp_cpp *cpp, struct nfp_eth_table_port *entry)
entry->port_type = PORT_DA;
}
+static void
+nfp_eth_read_media(struct nfp_cpp *cpp, struct nfp_nsp *nsp, struct nfp_eth_table_port *entry)
+{
+ struct nfp_eth_media_buf ethm = {
+ .eth_index = entry->eth_index,
+ };
+ unsigned int i;
+ int ret;
+
+ if (!nfp_nsp_has_read_media(nsp))
+ return;
+
+ ret = nfp_nsp_read_media(nsp, &ethm, sizeof(ethm));
+ if (ret) {
+ nfp_err(cpp, "Reading media link modes failed: %d\n", ret);
+ return;
+ }
+
+ for (i = 0; i < 2; i++) {
+ entry->link_modes_supp[i] = le64_to_cpu(ethm.supported_modes[i]);
+ entry->link_modes_ad[i] = le64_to_cpu(ethm.advertised_modes[i]);
+ }
+}
+
/**
* nfp_eth_read_ports() - retrieve port information
* @cpp: NFP CPP handle
@@ -293,8 +317,10 @@ __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp)
&table->ports[j++]);
nfp_eth_calc_port_geometry(cpp, table);
- for (i = 0; i < table->count; i++)
+ for (i = 0; i < table->count; i++) {
nfp_eth_calc_port_type(cpp, &table->ports[i]);
+ nfp_eth_read_media(cpp, nsp, &table->ports[i]);
+ }
kfree(entries);
@@ -647,29 +673,3 @@ int __nfp_eth_set_split(struct nfp_nsp *nsp, unsigned int lanes)
return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_PORT, NSP_ETH_PORT_LANES,
lanes, NSP_ETH_CTRL_SET_LANES);
}
-
-int nfp_eth_read_media(struct nfp_cpp *cpp, struct nfp_eth_media_buf *ethm)
-{
- struct nfp_nsp *nsp;
- int ret;
-
- nsp = nfp_nsp_open(cpp);
- if (IS_ERR(nsp)) {
- nfp_err(cpp, "Failed to access the NSP: %pe\n", nsp);
- return PTR_ERR(nsp);
- }
-
- if (!nfp_nsp_has_read_media(nsp)) {
- nfp_warn(cpp, "Reading media link modes not supported. Please update flash\n");
- ret = -EOPNOTSUPP;
- goto exit_close_nsp;
- }
-
- ret = nfp_nsp_read_media(nsp, ethm, sizeof(*ethm));
- if (ret)
- nfp_err(cpp, "Reading media link modes failed: %pe\n", ERR_PTR(ret));
-
-exit_close_nsp:
- nfp_nsp_close(nsp);
- return ret;
-}
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
index 4e18b64dceb9..9651cc714ef2 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
@@ -5,7 +5,7 @@
config PCH_GBE
tristate "OKI SEMICONDUCTOR IOH(ML7223/ML7831) GbE"
- depends on PCI && (X86_32 || COMPILE_TEST)
+ depends on PCI && (MIPS_GENERIC || X86_32 || COMPILE_TEST)
depends on PTP_1588_CLOCK
select MII
select PTP_1588_CLOCK_PCH
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
index b8678da1cce5..ab7d217b98b3 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
@@ -353,12 +353,6 @@ err_out_reset:
ionic_reset(ionic);
err_out_teardown:
ionic_dev_teardown(ionic);
- pci_clear_master(pdev);
- /* Don't fail the probe for these errors, keep
- * the hw interface around for inspection
- */
- return 0;
-
err_out_unmap_bars:
ionic_unmap_bars(ionic);
err_out_pci_release_regions:
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
index 9b2b96fa36af..3a6b0a9bc241 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
@@ -104,6 +104,15 @@ static void ionic_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
memcpy_fromio(p + offset, lif->ionic->idev.dev_cmd_regs->words, size);
}
+static void ionic_get_link_ext_stats(struct net_device *netdev,
+ struct ethtool_link_ext_stats *stats)
+{
+ struct ionic_lif *lif = netdev_priv(netdev);
+
+ if (lif->ionic->pdev->is_physfn)
+ stats->link_down_events = lif->link_down_count;
+}
+
static int ionic_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *ks)
{
@@ -1074,6 +1083,7 @@ static const struct ethtool_ops ionic_ethtool_ops = {
.get_regs_len = ionic_get_regs_len,
.get_regs = ionic_get_regs,
.get_link = ethtool_op_get_link,
+ .get_link_ext_stats = ionic_get_link_ext_stats,
.get_link_ksettings = ionic_get_link_ksettings,
.set_link_ksettings = ionic_set_link_ksettings,
.get_coalesce = ionic_get_coalesce,
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 957027e546b3..432fb93aa801 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -168,6 +168,7 @@ static void ionic_link_status_check(struct ionic_lif *lif)
}
} else {
if (netif_carrier_ok(netdev)) {
+ lif->link_down_count++;
netdev_info(netdev, "Link down\n");
netif_carrier_off(netdev);
}
@@ -474,11 +475,6 @@ static void ionic_qcqs_free(struct ionic_lif *lif)
static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq,
struct ionic_qcq *n_qcq)
{
- if (WARN_ON(n_qcq->flags & IONIC_QCQ_F_INTR)) {
- ionic_intr_free(n_qcq->cq.lif->ionic, n_qcq->intr.index);
- n_qcq->flags &= ~IONIC_QCQ_F_INTR;
- }
-
n_qcq->intr.vector = src_qcq->intr.vector;
n_qcq->intr.index = src_qcq->intr.index;
n_qcq->napi_qcq = src_qcq->napi_qcq;
@@ -560,7 +556,7 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
new->q.dev = dev;
new->flags = flags;
- new->q.info = vzalloc(num_descs * sizeof(*new->q.info));
+ new->q.info = vcalloc(num_descs, sizeof(*new->q.info));
if (!new->q.info) {
netdev_err(lif->netdev, "Cannot allocate queue info\n");
err = -ENOMEM;
@@ -581,7 +577,7 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
if (err)
goto err_out;
- new->cq.info = vzalloc(num_descs * sizeof(*new->cq.info));
+ new->cq.info = vcalloc(num_descs, sizeof(*new->cq.info));
if (!new->cq.info) {
netdev_err(lif->netdev, "Cannot allocate completion queue info\n");
err = -ENOMEM;
@@ -1821,6 +1817,7 @@ static int ionic_change_mtu(struct net_device *netdev, int new_mtu)
static void ionic_tx_timeout_work(struct work_struct *ws)
{
struct ionic_lif *lif = container_of(ws, struct ionic_lif, tx_timeout_work);
+ int err;
if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))
return;
@@ -1833,8 +1830,11 @@ static void ionic_tx_timeout_work(struct work_struct *ws)
mutex_lock(&lif->queue_lock);
ionic_stop_queues_reconfig(lif);
- ionic_start_queues_reconfig(lif);
+ err = ionic_start_queues_reconfig(lif);
mutex_unlock(&lif->queue_lock);
+
+ if (err)
+ dev_err(lif->ionic->dev, "%s: Restarting queues failed\n", __func__);
}
static void ionic_tx_timeout(struct net_device *netdev, unsigned int txqueue)
@@ -2804,17 +2804,22 @@ static int ionic_cmb_reconfig(struct ionic_lif *lif,
if (err) {
dev_err(lif->ionic->dev,
"CMB restore failed: %d\n", err);
- goto errout;
+ goto err_out;
}
}
- ionic_start_queues_reconfig(lif);
- } else {
- /* This was detached in ionic_stop_queues_reconfig() */
- netif_device_attach(lif->netdev);
+ err = ionic_start_queues_reconfig(lif);
+ if (err) {
+ dev_err(lif->ionic->dev,
+ "CMB reconfig failed: %d\n", err);
+ goto err_out;
+ }
}
-errout:
+err_out:
+ /* This was detached in ionic_stop_queues_reconfig() */
+ netif_device_attach(lif->netdev);
+
return err;
}
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
index c9c4c46d5a16..fd2ea670e7d8 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
@@ -201,6 +201,7 @@ struct ionic_lif {
u64 hw_features;
bool registered;
u16 lif_type;
+ unsigned int link_down_count;
unsigned int nmcast;
unsigned int nucast;
unsigned int nvlans;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h
index f8682356d0cf..94d4f9413ab7 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h
@@ -194,6 +194,22 @@ void qed_hw_remove(struct qed_dev *cdev);
struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn);
/**
+ * qed_ptt_acquire_context(): Allocate a PTT window honoring the context
+ * atomicy.
+ *
+ * @p_hwfn: HW device data.
+ * @is_atomic: Hint from the caller - if the func can sleep or not.
+ *
+ * Context: The function should not sleep in case is_atomic == true.
+ * Return: struct qed_ptt.
+ *
+ * Should be called at the entry point to the driver
+ * (at the beginning of an exported function).
+ */
+struct qed_ptt *qed_ptt_acquire_context(struct qed_hwfn *p_hwfn,
+ bool is_atomic);
+
+/**
* qed_ptt_release(): Release PTT Window.
*
* @p_hwfn: HW device data.
diff --git a/drivers/net/ethernet/qlogic/qed/qed_fcoe.c b/drivers/net/ethernet/qlogic/qed/qed_fcoe.c
index 3764190b948e..04602ac94708 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_fcoe.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_fcoe.c
@@ -693,13 +693,14 @@ static void _qed_fcoe_get_pstats(struct qed_hwfn *p_hwfn,
}
static int qed_fcoe_get_stats(struct qed_hwfn *p_hwfn,
- struct qed_fcoe_stats *p_stats)
+ struct qed_fcoe_stats *p_stats,
+ bool is_atomic)
{
struct qed_ptt *p_ptt;
memset(p_stats, 0, sizeof(*p_stats));
- p_ptt = qed_ptt_acquire(p_hwfn);
+ p_ptt = qed_ptt_acquire_context(p_hwfn, is_atomic);
if (!p_ptt) {
DP_ERR(p_hwfn, "Failed to acquire ptt\n");
@@ -973,19 +974,27 @@ static int qed_fcoe_destroy_conn(struct qed_dev *cdev,
QED_SPQ_MODE_EBLOCK, NULL);
}
+static int qed_fcoe_stats_context(struct qed_dev *cdev,
+ struct qed_fcoe_stats *stats,
+ bool is_atomic)
+{
+ return qed_fcoe_get_stats(QED_AFFIN_HWFN(cdev), stats, is_atomic);
+}
+
static int qed_fcoe_stats(struct qed_dev *cdev, struct qed_fcoe_stats *stats)
{
- return qed_fcoe_get_stats(QED_AFFIN_HWFN(cdev), stats);
+ return qed_fcoe_stats_context(cdev, stats, false);
}
void qed_get_protocol_stats_fcoe(struct qed_dev *cdev,
- struct qed_mcp_fcoe_stats *stats)
+ struct qed_mcp_fcoe_stats *stats,
+ bool is_atomic)
{
struct qed_fcoe_stats proto_stats;
/* Retrieve FW statistics */
memset(&proto_stats, 0, sizeof(proto_stats));
- if (qed_fcoe_stats(cdev, &proto_stats)) {
+ if (qed_fcoe_stats_context(cdev, &proto_stats, is_atomic)) {
DP_VERBOSE(cdev, QED_MSG_STORAGE,
"Failed to collect FCoE statistics\n");
return;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_fcoe.h b/drivers/net/ethernet/qlogic/qed/qed_fcoe.h
index 19c85adf4ceb..214e8299ecb4 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_fcoe.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_fcoe.h
@@ -28,8 +28,20 @@ int qed_fcoe_alloc(struct qed_hwfn *p_hwfn);
void qed_fcoe_setup(struct qed_hwfn *p_hwfn);
void qed_fcoe_free(struct qed_hwfn *p_hwfn);
+/**
+ * qed_get_protocol_stats_fcoe(): Fills provided statistics
+ * struct with statistics.
+ *
+ * @cdev: Qed dev pointer.
+ * @stats: Points to struct that will be filled with statistics.
+ * @is_atomic: Hint from the caller - if the func can sleep or not.
+ *
+ * Context: The function should not sleep in case is_atomic == true.
+ * Return: Void.
+ */
void qed_get_protocol_stats_fcoe(struct qed_dev *cdev,
- struct qed_mcp_fcoe_stats *stats);
+ struct qed_mcp_fcoe_stats *stats,
+ bool is_atomic);
#else /* CONFIG_QED_FCOE */
static inline int qed_fcoe_alloc(struct qed_hwfn *p_hwfn)
{
@@ -40,7 +52,8 @@ static inline void qed_fcoe_setup(struct qed_hwfn *p_hwfn) {}
static inline void qed_fcoe_free(struct qed_hwfn *p_hwfn) {}
static inline void qed_get_protocol_stats_fcoe(struct qed_dev *cdev,
- struct qed_mcp_fcoe_stats *stats)
+ struct qed_mcp_fcoe_stats *stats,
+ bool is_atomic)
{
}
#endif /* CONFIG_QED_FCOE */
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hw.c b/drivers/net/ethernet/qlogic/qed/qed_hw.c
index 554f30b0cfd5..6263f847b6b9 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_hw.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_hw.c
@@ -23,7 +23,10 @@
#include "qed_reg_addr.h"
#include "qed_sriov.h"
-#define QED_BAR_ACQUIRE_TIMEOUT 1000
+#define QED_BAR_ACQUIRE_TIMEOUT_USLEEP_CNT 1000
+#define QED_BAR_ACQUIRE_TIMEOUT_USLEEP 1000
+#define QED_BAR_ACQUIRE_TIMEOUT_UDELAY_CNT 100000
+#define QED_BAR_ACQUIRE_TIMEOUT_UDELAY 10
/* Invalid values */
#define QED_BAR_INVALID_OFFSET (cpu_to_le32(-1))
@@ -85,11 +88,21 @@ void qed_ptt_pool_free(struct qed_hwfn *p_hwfn)
struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn)
{
+ return qed_ptt_acquire_context(p_hwfn, false);
+}
+
+struct qed_ptt *qed_ptt_acquire_context(struct qed_hwfn *p_hwfn, bool is_atomic)
+{
struct qed_ptt *p_ptt;
- unsigned int i;
+ unsigned int i, count;
+
+ if (is_atomic)
+ count = QED_BAR_ACQUIRE_TIMEOUT_UDELAY_CNT;
+ else
+ count = QED_BAR_ACQUIRE_TIMEOUT_USLEEP_CNT;
/* Take the free PTT from the list */
- for (i = 0; i < QED_BAR_ACQUIRE_TIMEOUT; i++) {
+ for (i = 0; i < count; i++) {
spin_lock_bh(&p_hwfn->p_ptt_pool->lock);
if (!list_empty(&p_hwfn->p_ptt_pool->free_list)) {
@@ -105,7 +118,12 @@ struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn)
}
spin_unlock_bh(&p_hwfn->p_ptt_pool->lock);
- usleep_range(1000, 2000);
+
+ if (is_atomic)
+ udelay(QED_BAR_ACQUIRE_TIMEOUT_UDELAY);
+ else
+ usleep_range(QED_BAR_ACQUIRE_TIMEOUT_USLEEP,
+ QED_BAR_ACQUIRE_TIMEOUT_USLEEP * 2);
}
DP_NOTICE(p_hwfn, "PTT acquire timeout - failed to allocate PTT\n");
diff --git a/drivers/net/ethernet/qlogic/qed/qed_iscsi.c b/drivers/net/ethernet/qlogic/qed/qed_iscsi.c
index 511ab214eb9c..980e7289b481 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_iscsi.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_iscsi.c
@@ -999,13 +999,14 @@ static void _qed_iscsi_get_pstats(struct qed_hwfn *p_hwfn,
}
static int qed_iscsi_get_stats(struct qed_hwfn *p_hwfn,
- struct qed_iscsi_stats *stats)
+ struct qed_iscsi_stats *stats,
+ bool is_atomic)
{
struct qed_ptt *p_ptt;
memset(stats, 0, sizeof(*stats));
- p_ptt = qed_ptt_acquire(p_hwfn);
+ p_ptt = qed_ptt_acquire_context(p_hwfn, is_atomic);
if (!p_ptt) {
DP_ERR(p_hwfn, "Failed to acquire ptt\n");
return -EAGAIN;
@@ -1336,9 +1337,16 @@ static int qed_iscsi_destroy_conn(struct qed_dev *cdev,
QED_SPQ_MODE_EBLOCK, NULL);
}
+static int qed_iscsi_stats_context(struct qed_dev *cdev,
+ struct qed_iscsi_stats *stats,
+ bool is_atomic)
+{
+ return qed_iscsi_get_stats(QED_AFFIN_HWFN(cdev), stats, is_atomic);
+}
+
static int qed_iscsi_stats(struct qed_dev *cdev, struct qed_iscsi_stats *stats)
{
- return qed_iscsi_get_stats(QED_AFFIN_HWFN(cdev), stats);
+ return qed_iscsi_stats_context(cdev, stats, false);
}
static int qed_iscsi_change_mac(struct qed_dev *cdev,
@@ -1358,13 +1366,14 @@ static int qed_iscsi_change_mac(struct qed_dev *cdev,
}
void qed_get_protocol_stats_iscsi(struct qed_dev *cdev,
- struct qed_mcp_iscsi_stats *stats)
+ struct qed_mcp_iscsi_stats *stats,
+ bool is_atomic)
{
struct qed_iscsi_stats proto_stats;
/* Retrieve FW statistics */
memset(&proto_stats, 0, sizeof(proto_stats));
- if (qed_iscsi_stats(cdev, &proto_stats)) {
+ if (qed_iscsi_stats_context(cdev, &proto_stats, is_atomic)) {
DP_VERBOSE(cdev, QED_MSG_STORAGE,
"Failed to collect ISCSI statistics\n");
return;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_iscsi.h b/drivers/net/ethernet/qlogic/qed/qed_iscsi.h
index dec2b00259d4..974cb8d26608 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_iscsi.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_iscsi.h
@@ -39,11 +39,14 @@ void qed_iscsi_free(struct qed_hwfn *p_hwfn);
*
* @cdev: Qed dev pointer.
* @stats: Points to struct that will be filled with statistics.
+ * @is_atomic: Hint from the caller - if the func can sleep or not.
*
+ * Context: The function should not sleep in case is_atomic == true.
* Return: Void.
*/
void qed_get_protocol_stats_iscsi(struct qed_dev *cdev,
- struct qed_mcp_iscsi_stats *stats);
+ struct qed_mcp_iscsi_stats *stats,
+ bool is_atomic);
#else /* IS_ENABLED(CONFIG_QED_ISCSI) */
static inline int qed_iscsi_alloc(struct qed_hwfn *p_hwfn)
{
@@ -56,7 +59,8 @@ static inline void qed_iscsi_free(struct qed_hwfn *p_hwfn) {}
static inline void
qed_get_protocol_stats_iscsi(struct qed_dev *cdev,
- struct qed_mcp_iscsi_stats *stats) {}
+ struct qed_mcp_iscsi_stats *stats,
+ bool is_atomic) {}
#endif /* IS_ENABLED(CONFIG_QED_ISCSI) */
#endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c
index 7776d3bdd459..970b9aabbc3d 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_l2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c
@@ -1863,7 +1863,8 @@ static void __qed_get_vport_stats(struct qed_hwfn *p_hwfn,
}
static void _qed_get_vport_stats(struct qed_dev *cdev,
- struct qed_eth_stats *stats)
+ struct qed_eth_stats *stats,
+ bool is_atomic)
{
u8 fw_vport = 0;
int i;
@@ -1872,10 +1873,11 @@ static void _qed_get_vport_stats(struct qed_dev *cdev,
for_each_hwfn(cdev, i) {
struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
- struct qed_ptt *p_ptt = IS_PF(cdev) ? qed_ptt_acquire(p_hwfn)
- : NULL;
+ struct qed_ptt *p_ptt;
bool b_get_port_stats;
+ p_ptt = IS_PF(cdev) ? qed_ptt_acquire_context(p_hwfn, is_atomic)
+ : NULL;
if (IS_PF(cdev)) {
/* The main vport index is relative first */
if (qed_fw_vport(p_hwfn, 0, &fw_vport)) {
@@ -1901,6 +1903,13 @@ out:
void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats)
{
+ qed_get_vport_stats_context(cdev, stats, false);
+}
+
+void qed_get_vport_stats_context(struct qed_dev *cdev,
+ struct qed_eth_stats *stats,
+ bool is_atomic)
+{
u32 i;
if (!cdev || cdev->recov_in_prog) {
@@ -1908,7 +1917,7 @@ void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats)
return;
}
- _qed_get_vport_stats(cdev, stats);
+ _qed_get_vport_stats(cdev, stats, is_atomic);
if (!cdev->reset_stats)
return;
@@ -1960,7 +1969,7 @@ void qed_reset_vport_stats(struct qed_dev *cdev)
if (!cdev->reset_stats) {
DP_INFO(cdev, "Reset stats not allocated\n");
} else {
- _qed_get_vport_stats(cdev, cdev->reset_stats);
+ _qed_get_vport_stats(cdev, cdev->reset_stats, false);
cdev->reset_stats->common.link_change_count = 0;
}
}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.h b/drivers/net/ethernet/qlogic/qed/qed_l2.h
index a538cf478c14..2d2f82c785ad 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_l2.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_l2.h
@@ -249,8 +249,32 @@ qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn,
enum spq_mode comp_mode,
struct qed_spq_comp_cb *p_comp_data);
+/**
+ * qed_get_vport_stats(): Fills provided statistics
+ * struct with statistics.
+ *
+ * @cdev: Qed dev pointer.
+ * @stats: Points to struct that will be filled with statistics.
+ *
+ * Return: Void.
+ */
void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats);
+/**
+ * qed_get_vport_stats_context(): Fills provided statistics
+ * struct with statistics.
+ *
+ * @cdev: Qed dev pointer.
+ * @stats: Points to struct that will be filled with statistics.
+ * @is_atomic: Hint from the caller - if the func can sleep or not.
+ *
+ * Context: The function should not sleep in case is_atomic == true.
+ * Return: Void.
+ */
+void qed_get_vport_stats_context(struct qed_dev *cdev,
+ struct qed_eth_stats *stats,
+ bool is_atomic);
+
void qed_reset_vport_stats(struct qed_dev *cdev);
/**
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index f5af83342856..c278f8893042 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -3092,7 +3092,7 @@ void qed_get_protocol_stats(struct qed_dev *cdev,
switch (type) {
case QED_MCP_LAN_STATS:
- qed_get_vport_stats(cdev, &eth_stats);
+ qed_get_vport_stats_context(cdev, &eth_stats, true);
stats->lan_stats.ucast_rx_pkts =
eth_stats.common.rx_ucast_pkts;
stats->lan_stats.ucast_tx_pkts =
@@ -3100,10 +3100,10 @@ void qed_get_protocol_stats(struct qed_dev *cdev,
stats->lan_stats.fcs_err = -1;
break;
case QED_MCP_FCOE_STATS:
- qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats);
+ qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats, true);
break;
case QED_MCP_ISCSI_STATS:
- qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats);
+ qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats, true);
break;
default:
DP_VERBOSE(cdev, QED_MSG_SP,
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 4b004a728190..99df00c30b8c 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -176,6 +176,15 @@ static int qede_sriov_configure(struct pci_dev *pdev, int num_vfs_param)
}
#endif
+static int __maybe_unused qede_suspend(struct device *dev)
+{
+ dev_info(dev, "Device does not support suspend operation\n");
+
+ return -EOPNOTSUPP;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(qede_pm_ops, qede_suspend, NULL);
+
static const struct pci_error_handlers qede_err_handler = {
.error_detected = qede_io_error_detected,
};
@@ -190,6 +199,7 @@ static struct pci_driver qede_pci_driver = {
.sriov_configure = qede_sriov_configure,
#endif
.err_handler = &qede_err_handler,
+ .driver.pm = &qede_pm_ops,
};
static struct qed_eth_cb_ops qede_ll_ops = {
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-mac.c b/drivers/net/ethernet/qualcomm/emac/emac-mac.c
index 0d80447d4d3b..d5c688a8d7be 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-mac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-mac.c
@@ -1260,8 +1260,11 @@ static int emac_tso_csum(struct emac_adapter *adpt,
if (skb->protocol == htons(ETH_P_IP)) {
u32 pkt_len = ((unsigned char *)ip_hdr(skb) - skb->data)
+ ntohs(ip_hdr(skb)->tot_len);
- if (skb->len > pkt_len)
- pskb_trim(skb, pkt_len);
+ if (skb->len > pkt_len) {
+ ret = pskb_trim(skb, pkt_len);
+ if (unlikely(ret))
+ return ret;
+ }
}
hdr_len = skb_tcp_all_headers(skb);
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 4b19803a7dd0..5eb50b265c0b 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -623,6 +623,7 @@ struct rtl8169_private {
int cfg9346_usage_count;
unsigned supports_gmii:1;
+ unsigned aspm_manageable:1;
dma_addr_t counters_phys_addr;
struct rtl8169_counters *counters;
struct rtl8169_tc_offsets tc_offset;
@@ -2746,7 +2747,15 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
if (tp->mac_version < RTL_GIGA_MAC_VER_32)
return;
- if (enable) {
+ /* Don't enable ASPM in the chip if OS can't control ASPM */
+ if (enable && tp->aspm_manageable) {
+ /* On these chip versions ASPM can even harm
+ * bus communication of other PCI devices.
+ */
+ if (tp->mac_version == RTL_GIGA_MAC_VER_42 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_43)
+ return;
+
rtl_mod_config5(tp, 0, ASPM_en);
rtl_mod_config2(tp, 0, ClkReqEn);
@@ -4514,10 +4523,6 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
}
if (napi_schedule_prep(&tp->napi)) {
- rtl_unlock_config_regs(tp);
- rtl_hw_aspm_clkreq_enable(tp, false);
- rtl_lock_config_regs(tp);
-
rtl_irq_disable(tp);
__napi_schedule(&tp->napi);
}
@@ -4577,14 +4582,9 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
work_done = rtl_rx(dev, tp, budget);
- if (work_done < budget && napi_complete_done(napi, work_done)) {
+ if (work_done < budget && napi_complete_done(napi, work_done))
rtl_irq_enable(tp);
- rtl_unlock_config_regs(tp);
- rtl_hw_aspm_clkreq_enable(tp, true);
- rtl_lock_config_regs(tp);
- }
-
return work_done;
}
@@ -5158,12 +5158,23 @@ done:
rtl_rar_set(tp, mac_addr);
}
+/* register is set if system vendor successfully tested ASPM 1.2 */
+static bool rtl_aspm_is_safe(struct rtl8169_private *tp)
+{
+ if (tp->mac_version >= RTL_GIGA_MAC_VER_61 &&
+ r8168_mac_ocp_read(tp, 0xc0b2) & 0xf)
+ return true;
+
+ return false;
+}
+
static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct rtl8169_private *tp;
int jumbo_max, region, rc;
enum mac_version chipset;
struct net_device *dev;
+ u32 txconfig;
u16 xid;
dev = devm_alloc_etherdev(&pdev->dev, sizeof (*tp));
@@ -5195,40 +5206,50 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* enable device (incl. PCI PM wakeup and hotplug setup) */
rc = pcim_enable_device(pdev);
- if (rc < 0) {
- dev_err(&pdev->dev, "enable failure\n");
- return rc;
- }
+ if (rc < 0)
+ return dev_err_probe(&pdev->dev, rc, "enable failure\n");
if (pcim_set_mwi(pdev) < 0)
dev_info(&pdev->dev, "Mem-Wr-Inval unavailable\n");
/* use first MMIO region */
region = ffs(pci_select_bars(pdev, IORESOURCE_MEM)) - 1;
- if (region < 0) {
- dev_err(&pdev->dev, "no MMIO resource found\n");
- return -ENODEV;
- }
+ if (region < 0)
+ return dev_err_probe(&pdev->dev, -ENODEV, "no MMIO resource found\n");
rc = pcim_iomap_regions(pdev, BIT(region), KBUILD_MODNAME);
- if (rc < 0) {
- dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
- return rc;
- }
+ if (rc < 0)
+ return dev_err_probe(&pdev->dev, rc, "cannot remap MMIO, aborting\n");
tp->mmio_addr = pcim_iomap_table(pdev)[region];
- xid = (RTL_R32(tp, TxConfig) >> 20) & 0xfcf;
+ txconfig = RTL_R32(tp, TxConfig);
+ if (txconfig == ~0U)
+ return dev_err_probe(&pdev->dev, -EIO, "PCI read failed\n");
+
+ xid = (txconfig >> 20) & 0xfcf;
/* Identify chip attached to board */
chipset = rtl8169_get_mac_version(xid, tp->supports_gmii);
- if (chipset == RTL_GIGA_MAC_NONE) {
- dev_err(&pdev->dev, "unknown chip XID %03x, contact r8169 maintainers (see MAINTAINERS file)\n", xid);
- return -ENODEV;
- }
-
+ if (chipset == RTL_GIGA_MAC_NONE)
+ return dev_err_probe(&pdev->dev, -ENODEV,
+ "unknown chip XID %03x, contact r8169 maintainers (see MAINTAINERS file)\n",
+ xid);
tp->mac_version = chipset;
+ /* Disable ASPM L1 as that cause random device stop working
+ * problems as well as full system hangs for some PCIe devices users.
+ * Chips from RTL8168h partially have issues with L1.2, but seem
+ * to work fine with L1 and L1.1.
+ */
+ if (rtl_aspm_is_safe(tp))
+ rc = 0;
+ else if (tp->mac_version >= RTL_GIGA_MAC_VER_46)
+ rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_2);
+ else
+ rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1);
+ tp->aspm_manageable = !rc;
+
tp->dash_type = rtl_check_dash(tp);
tp->cp_cmd = RTL_R16(tp, CPlusCmd) & CPCMD_MASK;
@@ -5246,10 +5267,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
rtl_hw_reset(tp);
rc = rtl_alloc_irq(tp);
- if (rc < 0) {
- dev_err(&pdev->dev, "Can't allocate interrupt\n");
- return rc;
- }
+ if (rc < 0)
+ return dev_err_probe(&pdev->dev, rc, "Can't allocate interrupt\n");
+
tp->irq = pci_irq_vector(pdev, 0);
INIT_WORK(&tp->wk.work, rtl_task);
diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c
index fa6d6202b129..4e412ac0965a 100644
--- a/drivers/net/ethernet/renesas/rswitch.c
+++ b/drivers/net/ethernet/renesas/rswitch.c
@@ -90,6 +90,11 @@ static int rswitch_bpool_config(struct rswitch_private *priv)
return rswitch_reg_wait(priv->addr, CABPIRM, CABPIRM_BPR, CABPIRM_BPR);
}
+static void rswitch_coma_init(struct rswitch_private *priv)
+{
+ iowrite32(CABPPFLC_INIT_VALUE, priv->addr + CABPPFLC0);
+}
+
/* R-Switch-2 block (TOP) */
static void rswitch_top_init(struct rswitch_private *priv)
{
@@ -156,24 +161,6 @@ static int rswitch_gwca_axi_ram_reset(struct rswitch_private *priv)
return rswitch_reg_wait(priv->addr, GWARIRM, GWARIRM_ARR, GWARIRM_ARR);
}
-static void rswitch_gwca_set_rate_limit(struct rswitch_private *priv, int rate)
-{
- u32 gwgrlulc, gwgrlc;
-
- switch (rate) {
- case 1000:
- gwgrlulc = 0x0000005f;
- gwgrlc = 0x00010260;
- break;
- default:
- dev_err(&priv->pdev->dev, "%s: This rate is not supported (%d)\n", __func__, rate);
- return;
- }
-
- iowrite32(gwgrlulc, priv->addr + GWGRLULC);
- iowrite32(gwgrlc, priv->addr + GWGRLC);
-}
-
static bool rswitch_is_any_data_irq(struct rswitch_private *priv, u32 *dis, bool tx)
{
u32 *mask = tx ? priv->gwca.tx_irq_bits : priv->gwca.rx_irq_bits;
@@ -391,7 +378,7 @@ static int rswitch_gwca_queue_format(struct net_device *ndev,
linkfix->die_dt = DT_LINKFIX;
rswitch_desc_set_dptr(linkfix, gq->ring_dma);
- iowrite32(GWDCC_BALR | (gq->dir_tx ? GWDCC_DQT : 0) | GWDCC_EDE,
+ iowrite32(GWDCC_BALR | (gq->dir_tx ? GWDCC_DCP(GWCA_IPV_NUM) | GWDCC_DQT : 0) | GWDCC_EDE,
priv->addr + GWDCC_OFFS(gq->index));
return 0;
@@ -489,7 +476,8 @@ static int rswitch_gwca_queue_ext_ts_format(struct net_device *ndev,
linkfix->die_dt = DT_LINKFIX;
rswitch_desc_set_dptr(linkfix, gq->ring_dma);
- iowrite32(GWDCC_BALR | (gq->dir_tx ? GWDCC_DQT : 0) | GWDCC_ETS | GWDCC_EDE,
+ iowrite32(GWDCC_BALR | (gq->dir_tx ? GWDCC_DCP(GWCA_IPV_NUM) | GWDCC_DQT : 0) |
+ GWDCC_ETS | GWDCC_EDE,
priv->addr + GWDCC_OFFS(gq->index));
return 0;
@@ -660,7 +648,8 @@ static int rswitch_gwca_hw_init(struct rswitch_private *priv)
iowrite32(lower_32_bits(priv->gwca.ts_queue.ring_dma), priv->addr + GWTDCAC10);
iowrite32(upper_32_bits(priv->gwca.ts_queue.ring_dma), priv->addr + GWTDCAC00);
iowrite32(GWCA_TS_IRQ_BIT, priv->addr + GWTSDCC0);
- rswitch_gwca_set_rate_limit(priv, priv->gwca.speed);
+
+ iowrite32(GWTPC_PPPL(GWCA_IPV_NUM), priv->addr + GWTPC0);
for (i = 0; i < RSWITCH_NUM_PORTS; i++) {
err = rswitch_rxdmac_init(priv, i);
@@ -740,7 +729,7 @@ static bool rswitch_rx(struct net_device *ndev, int *quota)
}
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, ndev);
- netif_receive_skb(skb);
+ napi_gro_receive(&rdev->napi, skb);
rdev->ndev->stats.rx_packets++;
rdev->ndev->stats.rx_bytes += pkt_len;
@@ -1513,7 +1502,8 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd
rswitch_desc_set_dptr(&desc->desc, dma_addr);
desc->desc.info_ds = cpu_to_le16(skb->len);
- desc->info1 = cpu_to_le64(INFO1_DV(BIT(rdev->etha->index)) | INFO1_FMT);
+ desc->info1 = cpu_to_le64(INFO1_DV(BIT(rdev->etha->index)) |
+ INFO1_IPV(GWCA_IPV_NUM) | INFO1_FMT);
if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
struct rswitch_gwca_ts_info *ts_info;
@@ -1783,6 +1773,8 @@ static int rswitch_init(struct rswitch_private *priv)
if (err < 0)
return err;
+ rswitch_coma_init(priv);
+
err = rswitch_gwca_linkfix_alloc(priv);
if (err < 0)
return -ENOMEM;
diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h
index b3e0411b408e..bb9ed971a97c 100644
--- a/drivers/net/ethernet/renesas/rswitch.h
+++ b/drivers/net/ethernet/renesas/rswitch.h
@@ -48,6 +48,7 @@
#define GWCA_NUM_IRQS 8
#define GWCA_INDEX 0
#define AGENT_INDEX_GWCA 3
+#define GWCA_IPV_NUM 0
#define GWRO RSWITCH_GWCA0_OFFSET
#define GWCA_TS_IRQ_RESOURCE_NAME "gwca0_rxts0"
@@ -768,11 +769,14 @@ enum rswitch_gwca_mode {
#define GWARIRM_ARR BIT(1)
#define GWDCC_BALR BIT(24)
+#define GWDCC_DCP_MASK GENMASK(18, 16)
+#define GWDCC_DCP(prio) FIELD_PREP(GWDCC_DCP_MASK, (prio))
#define GWDCC_DQT BIT(11)
#define GWDCC_ETS BIT(9)
#define GWDCC_EDE BIT(8)
#define GWTRC(queue) (GWTRC0 + (queue) / 32 * 4)
+#define GWTPC_PPPL(ipv) BIT(ipv)
#define GWDCC_OFFS(queue) (GWDCC0 + (queue) * 4)
#define GWDIS(i) (GWDIS0 + (i) * 0x10)
@@ -789,6 +793,8 @@ enum rswitch_gwca_mode {
#define CABPIRM_BPIOG BIT(0)
#define CABPIRM_BPR BIT(1)
+#define CABPPFLC_INIT_VALUE 0x00800080
+
/* MFWD */
#define FWPC0_LTHTA BIT(0)
#define FWPC0_IP4UE BIT(3)
@@ -863,6 +869,7 @@ enum DIE_DT {
/* For transmission */
#define INFO1_TSUN(val) ((u64)(val) << 8ULL)
+#define INFO1_IPV(prio) ((u64)(prio) << 28ULL)
#define INFO1_CSD0(index) ((u64)(index) << 32ULL)
#define INFO1_CSD1(index) ((u64)(index) << 40ULL)
#define INFO1_DV(port_vector) ((u64)(port_vector) << 48ULL)
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
index 0f45107db8dd..d14e0cfc3a6b 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
@@ -511,7 +511,7 @@ struct sxgbe_priv_data {
struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device,
struct sxgbe_plat_data *plat_dat,
void __iomem *addr);
-int sxgbe_drv_remove(struct net_device *ndev);
+void sxgbe_drv_remove(struct net_device *ndev);
void sxgbe_set_ethtool_ops(struct net_device *netdev);
int sxgbe_mdio_unregister(struct net_device *ndev);
int sxgbe_mdio_register(struct net_device *ndev);
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index 9664f029fa16..71439825ea4e 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -2203,7 +2203,7 @@ error_free_netdev:
* Description: this function resets the TX/RX processes, disables the MAC RX/TX
* changes the link status, releases the DMA descriptor rings.
*/
-int sxgbe_drv_remove(struct net_device *ndev)
+void sxgbe_drv_remove(struct net_device *ndev)
{
struct sxgbe_priv_data *priv = netdev_priv(ndev);
u8 queue_num;
@@ -2231,8 +2231,6 @@ int sxgbe_drv_remove(struct net_device *ndev)
kfree(priv->hw);
free_netdev(ndev);
-
- return 0;
}
#ifdef CONFIG_PM
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c
index 4e5526303f07..fb59ff94509a 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c
@@ -172,9 +172,10 @@ err_out:
static int sxgbe_platform_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
- int ret = sxgbe_drv_remove(ndev);
- return ret;
+ sxgbe_drv_remove(ndev);
+
+ return 0;
}
#ifdef CONFIG_PM
diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig
index 4af36ba8906b..3eb55dcfa8a6 100644
--- a/drivers/net/ethernet/sfc/Kconfig
+++ b/drivers/net/ethernet/sfc/Kconfig
@@ -50,6 +50,7 @@ config SFC_MCDI_MON
config SFC_SRIOV
bool "Solarflare SFC9100-family SR-IOV support"
depends on SFC && PCI_IOV
+ depends on INET
default y
help
This enables support for the Single Root I/O Virtualization
diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile
index 55b9c73cd8ef..16293b58e0a8 100644
--- a/drivers/net/ethernet/sfc/Makefile
+++ b/drivers/net/ethernet/sfc/Makefile
@@ -10,7 +10,8 @@ sfc-y += efx.o efx_common.o efx_channels.o nic.o \
efx_devlink.o
sfc-$(CONFIG_SFC_MTD) += mtd.o
sfc-$(CONFIG_SFC_SRIOV) += sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o \
- mae.o tc.o tc_bindings.o tc_counters.o
+ mae.o tc.o tc_bindings.o tc_counters.o \
+ tc_encap_actions.o
obj-$(CONFIG_SFC) += sfc.o
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index b63e47af6365..8c019f382a7f 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1297,8 +1297,10 @@ static void efx_ef10_fini_nic(struct efx_nic *efx)
{
struct efx_ef10_nic_data *nic_data = efx->nic_data;
+ spin_lock_bh(&efx->stats_lock);
kfree(nic_data->mc_stats);
nic_data->mc_stats = NULL;
+ spin_unlock_bh(&efx->stats_lock);
}
static int efx_ef10_init_nic(struct efx_nic *efx)
@@ -1852,9 +1854,14 @@ static size_t efx_ef10_update_stats_pf(struct efx_nic *efx, u64 *full_stats,
efx_ef10_get_stat_mask(efx, mask);
- efx_nic_copy_stats(efx, nic_data->mc_stats);
- efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT,
- mask, stats, nic_data->mc_stats, false);
+ /* If NIC was fini'd (probably resetting), then we can't read
+ * updated stats right now.
+ */
+ if (nic_data->mc_stats) {
+ efx_nic_copy_stats(efx, nic_data->mc_stats);
+ efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT,
+ mask, stats, nic_data->mc_stats, false);
+ }
/* Update derived statistics */
efx_nic_fix_nodesc_drop_stat(efx,
diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c
index be395cd8770b..7f7d560cb2b4 100644
--- a/drivers/net/ethernet/sfc/ef100_netdev.c
+++ b/drivers/net/ethernet/sfc/ef100_netdev.c
@@ -24,6 +24,7 @@
#include "rx_common.h"
#include "ef100_sriov.h"
#include "tc_bindings.h"
+#include "tc_encap_actions.h"
#include "efx_devlink.h"
static void ef100_update_name(struct efx_nic *efx)
@@ -40,19 +41,26 @@ static int ef100_alloc_vis(struct efx_nic *efx, unsigned int *allocated_vis)
unsigned int tx_vis = efx->n_tx_channels + efx->n_extra_tx_channels;
unsigned int rx_vis = efx->n_rx_channels;
unsigned int min_vis, max_vis;
+ int rc;
EFX_WARN_ON_PARANOID(efx->tx_queues_per_channel != 1);
tx_vis += efx->n_xdp_channels * efx->xdp_tx_per_channel;
max_vis = max(rx_vis, tx_vis);
- /* Currently don't handle resource starvation and only accept
- * our maximum needs and no less.
+ /* We require at least a single complete TX channel worth of queues. */
+ min_vis = efx->tx_queues_per_channel;
+
+ rc = efx_mcdi_alloc_vis(efx, min_vis, max_vis,
+ NULL, allocated_vis);
+
+ /* We retry allocating VIs by reallocating channels when we have not
+ * been able to allocate the maximum VIs.
*/
- min_vis = max_vis;
+ if (!rc && *allocated_vis < max_vis)
+ rc = -EAGAIN;
- return efx_mcdi_alloc_vis(efx, min_vis, max_vis,
- NULL, allocated_vis);
+ return rc;
}
static int ef100_remap_bar(struct efx_nic *efx, int max_vis)
@@ -133,9 +141,41 @@ static int ef100_net_open(struct net_device *net_dev)
goto fail;
rc = ef100_alloc_vis(efx, &allocated_vis);
- if (rc)
+ if (rc && rc != -EAGAIN)
goto fail;
+ /* Try one more time but with the maximum number of channels
+ * equal to the allocated VIs, which would more likely succeed.
+ */
+ if (rc == -EAGAIN) {
+ rc = efx_mcdi_free_vis(efx);
+ if (rc)
+ goto fail;
+
+ efx_remove_interrupts(efx);
+ efx->max_channels = allocated_vis;
+
+ rc = efx_probe_interrupts(efx);
+ if (rc)
+ goto fail;
+
+ rc = efx_set_channels(efx);
+ if (rc)
+ goto fail;
+
+ rc = ef100_alloc_vis(efx, &allocated_vis);
+ if (rc && rc != -EAGAIN)
+ goto fail;
+
+ /* It should be very unlikely that we failed here again, but in
+ * such a case we return ENOSPC.
+ */
+ if (rc == -EAGAIN) {
+ rc = -ENOSPC;
+ goto fail;
+ }
+ }
+
rc = efx_probe_channels(efx);
if (rc)
return rc;
@@ -261,14 +301,38 @@ int ef100_netdev_event(struct notifier_block *this,
{
struct efx_nic *efx = container_of(this, struct efx_nic, netdev_notifier);
struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
+ struct ef100_nic_data *nic_data = efx->nic_data;
+ int err;
if (efx->net_dev == net_dev &&
(event == NETDEV_CHANGENAME || event == NETDEV_REGISTER))
ef100_update_name(efx);
+ if (!nic_data->grp_mae)
+ return NOTIFY_DONE;
+ err = efx_tc_netdev_event(efx, event, net_dev);
+ if (err & NOTIFY_STOP_MASK)
+ return err;
+
return NOTIFY_DONE;
}
+static int ef100_netevent_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct efx_nic *efx = container_of(this, struct efx_nic, netevent_notifier);
+ struct ef100_nic_data *nic_data = efx->nic_data;
+ int err;
+
+ if (!nic_data->grp_mae)
+ return NOTIFY_DONE;
+ err = efx_tc_netevent_event(efx, event, ptr);
+ if (err & NOTIFY_STOP_MASK)
+ return err;
+
+ return NOTIFY_DONE;
+};
+
static int ef100_register_netdev(struct efx_nic *efx)
{
struct net_device *net_dev = efx->net_dev;
@@ -328,6 +392,7 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
rtnl_unlock();
unregister_netdevice_notifier(&efx->netdev_notifier);
+ unregister_netevent_notifier(&efx->netevent_notifier);
#if defined(CONFIG_SFC_SRIOV)
if (!efx->type->is_vf)
efx_ef100_pci_sriov_disable(efx, true);
@@ -448,6 +513,14 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
goto fail;
}
+ efx->netevent_notifier.notifier_call = ef100_netevent_event;
+ rc = register_netevent_notifier(&efx->netevent_notifier);
+ if (rc) {
+ netif_err(efx, probe, efx->net_dev,
+ "Failed to register netevent notifier, rc=%d\n", rc);
+ goto fail;
+ }
+
efx_probe_devlink_unlock(efx);
return rc;
fail:
diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index 7adde9639c8a..35d8e9811998 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -1194,7 +1194,7 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)
net_dev->features |= NETIF_F_HW_TC;
efx->fixed_features |= NETIF_F_HW_TC;
}
- return rc;
+ return 0;
}
int ef100_probe_vf(struct efx_nic *efx)
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index a4f22d8e6ac7..d670a319b379 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -32,6 +32,7 @@
#include "io.h"
#include "selftest.h"
#include "sriov.h"
+#include "efx_devlink.h"
#include "mcdi_port_common.h"
#include "mcdi_pcol.h"
@@ -877,6 +878,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
if (efx->type->sriov_fini)
efx->type->sriov_fini(efx);
+ efx_fini_devlink_lock(efx);
efx_unregister_netdev(efx);
efx_mtd_remove(efx);
@@ -886,6 +888,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
efx_fini_io(efx);
pci_dbg(efx->pci_dev, "shutdown successful\n");
+ efx_fini_devlink_and_unlock(efx);
efx_fini_struct(efx);
free_netdev(efx->net_dev);
probe_data = container_of(efx, struct efx_probe_data, efx);
@@ -1025,7 +1028,13 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
NETDEV_XDP_ACT_REDIRECT |
NETDEV_XDP_ACT_NDO_XMIT;
+ /* devlink creation, registration and lock */
+ rc = efx_probe_devlink_and_lock(efx);
+ if (rc)
+ pci_err(efx->pci_dev, "devlink registration failed");
+
rc = efx_register_netdev(efx);
+ efx_probe_devlink_unlock(efx);
if (!rc)
return 0;
diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
index ef9971cbb695..3cd750820fdd 100644
--- a/drivers/net/ethernet/sfc/efx_devlink.c
+++ b/drivers/net/ethernet/sfc/efx_devlink.c
@@ -25,40 +25,6 @@ struct efx_devlink {
};
#ifdef CONFIG_SFC_SRIOV
-static void efx_devlink_del_port(struct devlink_port *dl_port)
-{
- if (!dl_port)
- return;
- devl_port_unregister(dl_port);
-}
-
-static int efx_devlink_add_port(struct efx_nic *efx,
- struct mae_mport_desc *mport)
-{
- bool external = false;
-
- if (!ef100_mport_on_local_intf(efx, mport))
- external = true;
-
- switch (mport->mport_type) {
- case MAE_MPORT_DESC_MPORT_TYPE_VNIC:
- if (mport->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL)
- devlink_port_attrs_pci_vf_set(&mport->dl_port, 0, mport->pf_idx,
- mport->vf_idx,
- external);
- else
- devlink_port_attrs_pci_pf_set(&mport->dl_port, 0, mport->pf_idx,
- external);
- break;
- default:
- /* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */
- return 0;
- }
-
- mport->dl_port.index = mport->mport_id;
-
- return devl_port_register(efx->devlink, &mport->dl_port, mport->mport_id);
-}
static int efx_devlink_port_addr_get(struct devlink_port *port, u8 *hw_addr,
int *hw_addr_len,
@@ -158,6 +124,48 @@ static int efx_devlink_port_addr_set(struct devlink_port *port,
return rc;
}
+static const struct devlink_port_ops sfc_devlink_port_ops = {
+ .port_fn_hw_addr_get = efx_devlink_port_addr_get,
+ .port_fn_hw_addr_set = efx_devlink_port_addr_set,
+};
+
+static void efx_devlink_del_port(struct devlink_port *dl_port)
+{
+ if (!dl_port)
+ return;
+ devl_port_unregister(dl_port);
+}
+
+static int efx_devlink_add_port(struct efx_nic *efx,
+ struct mae_mport_desc *mport)
+{
+ bool external = false;
+
+ if (!ef100_mport_on_local_intf(efx, mport))
+ external = true;
+
+ switch (mport->mport_type) {
+ case MAE_MPORT_DESC_MPORT_TYPE_VNIC:
+ if (mport->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL)
+ devlink_port_attrs_pci_vf_set(&mport->dl_port, 0, mport->pf_idx,
+ mport->vf_idx,
+ external);
+ else
+ devlink_port_attrs_pci_pf_set(&mport->dl_port, 0, mport->pf_idx,
+ external);
+ break;
+ default:
+ /* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */
+ return 0;
+ }
+
+ mport->dl_port.index = mport->mport_id;
+
+ return devl_port_register_with_ops(efx->devlink, &mport->dl_port,
+ mport->mport_id,
+ &sfc_devlink_port_ops);
+}
+
#endif
static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
@@ -609,10 +617,6 @@ static int efx_devlink_info_get(struct devlink *devlink,
static const struct devlink_ops sfc_devlink_ops = {
.info_get = efx_devlink_info_get,
-#ifdef CONFIG_SFC_SRIOV
- .port_function_hw_addr_get = efx_devlink_port_addr_get,
- .port_function_hw_addr_set = efx_devlink_port_addr_set,
-#endif
};
#ifdef CONFIG_SFC_SRIOV
@@ -622,6 +626,9 @@ static struct devlink_port *ef100_set_devlink_port(struct efx_nic *efx, u32 idx)
u32 id;
int rc;
+ if (!efx->mae)
+ return NULL;
+
if (efx_mae_lookup_mport(efx, idx, &id)) {
/* This should not happen. */
if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
diff --git a/drivers/net/ethernet/sfc/falcon/selftest.c b/drivers/net/ethernet/sfc/falcon/selftest.c
index 6a454ac6f876..c3dc88e6c26c 100644
--- a/drivers/net/ethernet/sfc/falcon/selftest.c
+++ b/drivers/net/ethernet/sfc/falcon/selftest.c
@@ -39,12 +39,17 @@
* Falcon only performs RSS on TCP/UDP packets.
*/
struct ef4_loopback_payload {
- struct ethhdr header;
- struct iphdr ip;
- struct udphdr udp;
- __be16 iteration;
- char msg[64];
-} __packed;
+ char pad[2]; /* Ensures ip is 4-byte aligned */
+ struct_group_attr(packet, __packed,
+ struct ethhdr header;
+ struct iphdr ip;
+ struct udphdr udp;
+ __be16 iteration;
+ char msg[64];
+ );
+} __packed __aligned(4);
+#define EF4_LOOPBACK_PAYLOAD_LEN \
+ sizeof_field(struct ef4_loopback_payload, packet)
/* Loopback test source MAC address */
static const u8 payload_source[ETH_ALEN] __aligned(2) = {
@@ -284,7 +289,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
const char *buf_ptr, int pkt_len)
{
struct ef4_loopback_state *state = efx->loopback_selftest;
- struct ef4_loopback_payload *received;
+ struct ef4_loopback_payload received;
struct ef4_loopback_payload *payload;
BUG_ON(!buf_ptr);
@@ -295,13 +300,14 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
payload = &state->payload;
- received = (struct ef4_loopback_payload *) buf_ptr;
- received->ip.saddr = payload->ip.saddr;
+ memcpy(&received.packet, buf_ptr,
+ min_t(int, pkt_len, EF4_LOOPBACK_PAYLOAD_LEN));
+ received.ip.saddr = payload->ip.saddr;
if (state->offload_csum)
- received->ip.check = payload->ip.check;
+ received.ip.check = payload->ip.check;
/* Check that header exists */
- if (pkt_len < sizeof(received->header)) {
+ if (pkt_len < sizeof(received.header)) {
netif_err(efx, drv, efx->net_dev,
"saw runt RX packet (length %d) in %s loopback "
"test\n", pkt_len, LOOPBACK_MODE(efx));
@@ -309,7 +315,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
}
/* Check that the ethernet header exists */
- if (memcmp(&received->header, &payload->header, ETH_HLEN) != 0) {
+ if (memcmp(&received.header, &payload->header, ETH_HLEN) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw non-loopback RX packet in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -317,16 +323,16 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
}
/* Check packet length */
- if (pkt_len != sizeof(*payload)) {
+ if (pkt_len != EF4_LOOPBACK_PAYLOAD_LEN) {
netif_err(efx, drv, efx->net_dev,
"saw incorrect RX packet length %d (wanted %d) in "
- "%s loopback test\n", pkt_len, (int)sizeof(*payload),
- LOOPBACK_MODE(efx));
+ "%s loopback test\n", pkt_len,
+ (int)EF4_LOOPBACK_PAYLOAD_LEN, LOOPBACK_MODE(efx));
goto err;
}
/* Check that IP header matches */
- if (memcmp(&received->ip, &payload->ip, sizeof(payload->ip)) != 0) {
+ if (memcmp(&received.ip, &payload->ip, sizeof(payload->ip)) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw corrupted IP header in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -334,7 +340,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
}
/* Check that msg and padding matches */
- if (memcmp(&received->msg, &payload->msg, sizeof(received->msg)) != 0) {
+ if (memcmp(&received.msg, &payload->msg, sizeof(received.msg)) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw corrupted RX packet in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -342,10 +348,10 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
}
/* Check that iteration matches */
- if (received->iteration != payload->iteration) {
+ if (received.iteration != payload->iteration) {
netif_err(efx, drv, efx->net_dev,
"saw RX packet from iteration %d (wanted %d) in "
- "%s loopback test\n", ntohs(received->iteration),
+ "%s loopback test\n", ntohs(received.iteration),
ntohs(payload->iteration), LOOPBACK_MODE(efx));
goto err;
}
@@ -365,7 +371,8 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
buf_ptr, pkt_len, 0);
netif_err(efx, drv, efx->net_dev, "expected packet:\n");
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
- &state->payload, sizeof(state->payload), 0);
+ &state->payload.packet, EF4_LOOPBACK_PAYLOAD_LEN,
+ 0);
}
#endif
atomic_inc(&state->rx_bad);
@@ -387,14 +394,15 @@ static void ef4_iterate_state(struct ef4_nic *efx)
payload->ip.daddr = htonl(INADDR_LOOPBACK);
payload->ip.ihl = 5;
payload->ip.check = (__force __sum16) htons(0xdead);
- payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr));
+ payload->ip.tot_len = htons(sizeof(*payload) -
+ offsetof(struct ef4_loopback_payload, ip));
payload->ip.version = IPVERSION;
payload->ip.protocol = IPPROTO_UDP;
/* Initialise udp header */
payload->udp.source = 0;
- payload->udp.len = htons(sizeof(*payload) - sizeof(struct ethhdr) -
- sizeof(struct iphdr));
+ payload->udp.len = htons(sizeof(*payload) -
+ offsetof(struct ef4_loopback_payload, udp));
payload->udp.check = 0; /* checksum ignored */
/* Fill out payload */
@@ -431,6 +439,10 @@ static int ef4_begin_loopback(struct ef4_tx_queue *tx_queue)
payload = skb_put(skb, sizeof(state->payload));
memcpy(payload, &state->payload, sizeof(state->payload));
payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2));
+ /* Strip off the leading padding */
+ skb_pull(skb, offsetof(struct ef4_loopback_payload, header));
+ /* Strip off the trailing padding */
+ skb_trim(skb, EF4_LOOPBACK_PAYLOAD_LEN);
/* Ensure everything we've written is visible to the
* interrupt handler. */
diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c
index 49706a7b94bf..0cab508f2f9d 100644
--- a/drivers/net/ethernet/sfc/mae.c
+++ b/drivers/net/ethernet/sfc/mae.c
@@ -15,6 +15,7 @@
#include "mcdi.h"
#include "mcdi_pcol.h"
#include "mcdi_pcol_mae.h"
+#include "tc_encap_actions.h"
int efx_mae_allocate_mport(struct efx_nic *efx, u32 *id, u32 *label)
{
@@ -482,12 +483,14 @@ int efx_mae_match_check_caps(struct efx_nic *efx,
rc; \
})
/* Checks that the fields needed for encap-rule matches are supported by the
- * MAE. All the fields are exact-match.
+ * MAE. All the fields are exact-match, except possibly ENC_IP_TOS.
*/
int efx_mae_check_encap_match_caps(struct efx_nic *efx, bool ipv6,
+ u8 ip_tos_mask, __be16 udp_sport_mask,
struct netlink_ext_ack *extack)
{
u8 *supported_fields = efx->tc->caps->outer_rule_fields;
+ enum mask_type typ;
int rc;
if (CHECK(ENC_ETHER_TYPE))
@@ -504,6 +507,22 @@ int efx_mae_check_encap_match_caps(struct efx_nic *efx, bool ipv6,
if (CHECK(ENC_L4_DPORT) ||
CHECK(ENC_IP_PROTO))
return rc;
+ typ = classify_mask((const u8 *)&udp_sport_mask, sizeof(udp_sport_mask));
+ rc = efx_mae_match_check_cap_typ(supported_fields[MAE_FIELD_ENC_L4_SPORT],
+ typ);
+ if (rc) {
+ NL_SET_ERR_MSG_FMT_MOD(extack, "No support for %s mask in field %s",
+ mask_type_name(typ), "enc_src_port");
+ return rc;
+ }
+ typ = classify_mask(&ip_tos_mask, sizeof(ip_tos_mask));
+ rc = efx_mae_match_check_cap_typ(supported_fields[MAE_FIELD_ENC_IP_TOS],
+ typ);
+ if (rc) {
+ NL_SET_ERR_MSG_FMT_MOD(extack, "No support for %s mask in field %s",
+ mask_type_name(typ), "enc_ip_tos");
+ return rc;
+ }
return 0;
}
#undef CHECK
@@ -592,6 +611,87 @@ static int efx_mae_encap_type_to_mae_type(enum efx_encap_type type)
}
}
+int efx_mae_allocate_encap_md(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap)
+{
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LEN(EFX_TC_MAX_ENCAP_HDR));
+ MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN);
+ size_t inlen, outlen;
+ int rc;
+
+ rc = efx_mae_encap_type_to_mae_type(encap->type);
+ if (rc < 0)
+ return rc;
+ MCDI_SET_DWORD(inbuf, MAE_ENCAP_HEADER_ALLOC_IN_ENCAP_TYPE, rc);
+ inlen = MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LEN(encap->encap_hdr_len);
+ if (WARN_ON(inlen > sizeof(inbuf))) /* can't happen */
+ return -EINVAL;
+ memcpy(MCDI_PTR(inbuf, MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA),
+ encap->encap_hdr,
+ encap->encap_hdr_len);
+ rc = efx_mcdi_rpc(efx, MC_CMD_MAE_ENCAP_HEADER_ALLOC, inbuf,
+ inlen, outbuf, sizeof(outbuf), &outlen);
+ if (rc)
+ return rc;
+ if (outlen < sizeof(outbuf))
+ return -EIO;
+ encap->fw_id = MCDI_DWORD(outbuf, MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID);
+ return 0;
+}
+
+int efx_mae_update_encap_md(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap)
+{
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LEN(EFX_TC_MAX_ENCAP_HDR));
+ size_t inlen;
+ int rc;
+
+ rc = efx_mae_encap_type_to_mae_type(encap->type);
+ if (rc < 0)
+ return rc;
+ MCDI_SET_DWORD(inbuf, MAE_ENCAP_HEADER_UPDATE_IN_ENCAP_TYPE, rc);
+ MCDI_SET_DWORD(inbuf, MAE_ENCAP_HEADER_UPDATE_IN_EH_ID,
+ encap->fw_id);
+ inlen = MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LEN(encap->encap_hdr_len);
+ if (WARN_ON(inlen > sizeof(inbuf))) /* can't happen */
+ return -EINVAL;
+ memcpy(MCDI_PTR(inbuf, MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA),
+ encap->encap_hdr,
+ encap->encap_hdr_len);
+
+ BUILD_BUG_ON(MC_CMD_MAE_ENCAP_HEADER_UPDATE_OUT_LEN != 0);
+ return efx_mcdi_rpc(efx, MC_CMD_MAE_ENCAP_HEADER_UPDATE, inbuf,
+ inlen, NULL, 0, NULL);
+}
+
+int efx_mae_free_encap_md(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap)
+{
+ MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1));
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1));
+ size_t outlen;
+ int rc;
+
+ MCDI_SET_DWORD(inbuf, MAE_ENCAP_HEADER_FREE_IN_EH_ID, encap->fw_id);
+ rc = efx_mcdi_rpc(efx, MC_CMD_MAE_ENCAP_HEADER_FREE, inbuf,
+ sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
+ if (rc)
+ return rc;
+ if (outlen < sizeof(outbuf))
+ return -EIO;
+ /* FW freed a different ID than we asked for, should also never happen.
+ * Warn because it means we've now got a different idea to the FW of
+ * what encap_mds exist, which could cause mayhem later.
+ */
+ if (WARN_ON(MCDI_DWORD(outbuf, MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID) != encap->fw_id))
+ return -EIO;
+ /* We're probably about to free @encap, but let's just make sure its
+ * fw_id is blatted so that it won't look valid if it leaks out.
+ */
+ encap->fw_id = MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL;
+ return 0;
+}
+
int efx_mae_lookup_mport(struct efx_nic *efx, u32 vf_idx, u32 *id)
{
struct ef100_nic_data *nic_data = efx->nic_data;
@@ -815,8 +915,12 @@ int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act)
MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE,
act->vlan_proto[1]);
}
- MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID,
- MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL);
+ if (act->encap_md)
+ MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID,
+ act->encap_md->fw_id);
+ else
+ MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID,
+ MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL);
if (act->deliver)
MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DELIVER,
act->dest_mport);
@@ -1001,8 +1105,16 @@ int efx_mae_register_encap_match(struct efx_nic *efx,
encap->udp_dport);
MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK,
~(__be16)0);
+ MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE,
+ encap->udp_sport);
+ MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK,
+ encap->udp_sport_mask);
MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO, IPPROTO_UDP);
MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_MASK, ~0);
+ MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_TOS,
+ encap->ip_tos);
+ MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_MASK,
+ encap->ip_tos_mask);
rc = efx_mcdi_rpc(efx, MC_CMD_MAE_OUTER_RULE_INSERT, inbuf,
sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
if (rc)
@@ -1203,6 +1315,29 @@ int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match,
return 0;
}
+int efx_mae_update_rule(struct efx_nic *efx, u32 acts_id, u32 id)
+{
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ACTION_RULE_UPDATE_IN_LEN);
+ MCDI_DECLARE_STRUCT_PTR(response);
+
+ BUILD_BUG_ON(MC_CMD_MAE_ACTION_RULE_UPDATE_OUT_LEN);
+ response = _MCDI_DWORD(inbuf, MAE_ACTION_RULE_UPDATE_IN_RESPONSE);
+
+ MCDI_SET_DWORD(inbuf, MAE_ACTION_RULE_UPDATE_IN_AR_ID, id);
+ if (efx_mae_asl_id(acts_id)) {
+ MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_ASL_ID, acts_id);
+ MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_AS_ID,
+ MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL);
+ } else {
+ /* We only had one AS, so we didn't wrap it in an ASL */
+ MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_ASL_ID,
+ MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL);
+ MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_AS_ID, acts_id);
+ }
+ return efx_mcdi_rpc(efx, MC_CMD_MAE_ACTION_RULE_UPDATE, inbuf, sizeof(inbuf),
+ NULL, 0, NULL);
+}
+
int efx_mae_delete_rule(struct efx_nic *efx, u32 id)
{
MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1));
diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h
index 9226219491a0..24abfe509690 100644
--- a/drivers/net/ethernet/sfc/mae.h
+++ b/drivers/net/ethernet/sfc/mae.h
@@ -82,6 +82,7 @@ int efx_mae_match_check_caps(struct efx_nic *efx,
const struct efx_tc_match_fields *mask,
struct netlink_ext_ack *extack);
int efx_mae_check_encap_match_caps(struct efx_nic *efx, bool ipv6,
+ u8 ip_tos_mask, __be16 udp_sport_mask,
struct netlink_ext_ack *extack);
int efx_mae_check_encap_type_supported(struct efx_nic *efx,
enum efx_encap_type typ);
@@ -89,6 +90,13 @@ int efx_mae_check_encap_type_supported(struct efx_nic *efx,
int efx_mae_allocate_counter(struct efx_nic *efx, struct efx_tc_counter *cnt);
int efx_mae_free_counter(struct efx_nic *efx, struct efx_tc_counter *cnt);
+int efx_mae_allocate_encap_md(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap);
+int efx_mae_update_encap_md(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap);
+int efx_mae_free_encap_md(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap);
+
int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act);
int efx_mae_free_action_set(struct efx_nic *efx, u32 fw_id);
@@ -104,6 +112,7 @@ int efx_mae_unregister_encap_match(struct efx_nic *efx,
int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match,
u32 prio, u32 acts_id, u32 *id);
+int efx_mae_update_rule(struct efx_nic *efx, u32 acts_id, u32 id);
int efx_mae_delete_rule(struct efx_nic *efx, u32 id);
int efx_init_mae(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index fcd51d3992fa..a7a22b019794 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -27,6 +27,7 @@
#include <linux/mtd/mtd.h>
#include <net/busy_poll.h>
#include <net/xdp.h>
+#include <net/netevent.h>
#include "enum.h"
#include "bitfield.h"
@@ -996,6 +997,7 @@ struct efx_mae;
* @xdp_rxq_info_failed: Have any of the rx queues failed to initialise their
* xdp_rxq_info structures?
* @netdev_notifier: Netdevice notifier.
+ * @netevent_notifier: Netevent notifier (for neighbour updates).
* @tc: state for TC offload (EF100).
* @devlink: reference to devlink structure owned by this device
* @dl_port: devlink port associated with the PF
@@ -1183,6 +1185,7 @@ struct efx_nic {
bool xdp_rxq_info_failed;
struct notifier_block netdev_notifier;
+ struct notifier_block netevent_notifier;
struct efx_tc_state *tc;
struct devlink *devlink;
diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c
index 3c5227afd497..563c1e317ce9 100644
--- a/drivers/net/ethernet/sfc/selftest.c
+++ b/drivers/net/ethernet/sfc/selftest.c
@@ -42,12 +42,17 @@
* Falcon only performs RSS on TCP/UDP packets.
*/
struct efx_loopback_payload {
- struct ethhdr header;
- struct iphdr ip;
- struct udphdr udp;
- __be16 iteration;
- char msg[64];
-} __packed;
+ char pad[2]; /* Ensures ip is 4-byte aligned */
+ struct_group_attr(packet, __packed,
+ struct ethhdr header;
+ struct iphdr ip;
+ struct udphdr udp;
+ __be16 iteration;
+ char msg[64];
+ );
+} __packed __aligned(4);
+#define EFX_LOOPBACK_PAYLOAD_LEN \
+ sizeof_field(struct efx_loopback_payload, packet)
/* Loopback test source MAC address */
static const u8 payload_source[ETH_ALEN] __aligned(2) = {
@@ -282,7 +287,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
const char *buf_ptr, int pkt_len)
{
struct efx_loopback_state *state = efx->loopback_selftest;
- struct efx_loopback_payload *received;
+ struct efx_loopback_payload received;
struct efx_loopback_payload *payload;
BUG_ON(!buf_ptr);
@@ -293,13 +298,14 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
payload = &state->payload;
- received = (struct efx_loopback_payload *) buf_ptr;
- received->ip.saddr = payload->ip.saddr;
+ memcpy(&received.packet, buf_ptr,
+ min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN));
+ received.ip.saddr = payload->ip.saddr;
if (state->offload_csum)
- received->ip.check = payload->ip.check;
+ received.ip.check = payload->ip.check;
/* Check that header exists */
- if (pkt_len < sizeof(received->header)) {
+ if (pkt_len < sizeof(received.header)) {
netif_err(efx, drv, efx->net_dev,
"saw runt RX packet (length %d) in %s loopback "
"test\n", pkt_len, LOOPBACK_MODE(efx));
@@ -307,7 +313,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
}
/* Check that the ethernet header exists */
- if (memcmp(&received->header, &payload->header, ETH_HLEN) != 0) {
+ if (memcmp(&received.header, &payload->header, ETH_HLEN) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw non-loopback RX packet in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -315,16 +321,16 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
}
/* Check packet length */
- if (pkt_len != sizeof(*payload)) {
+ if (pkt_len != EFX_LOOPBACK_PAYLOAD_LEN) {
netif_err(efx, drv, efx->net_dev,
"saw incorrect RX packet length %d (wanted %d) in "
- "%s loopback test\n", pkt_len, (int)sizeof(*payload),
- LOOPBACK_MODE(efx));
+ "%s loopback test\n", pkt_len,
+ (int)EFX_LOOPBACK_PAYLOAD_LEN, LOOPBACK_MODE(efx));
goto err;
}
/* Check that IP header matches */
- if (memcmp(&received->ip, &payload->ip, sizeof(payload->ip)) != 0) {
+ if (memcmp(&received.ip, &payload->ip, sizeof(payload->ip)) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw corrupted IP header in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -332,7 +338,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
}
/* Check that msg and padding matches */
- if (memcmp(&received->msg, &payload->msg, sizeof(received->msg)) != 0) {
+ if (memcmp(&received.msg, &payload->msg, sizeof(received.msg)) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw corrupted RX packet in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -340,10 +346,10 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
}
/* Check that iteration matches */
- if (received->iteration != payload->iteration) {
+ if (received.iteration != payload->iteration) {
netif_err(efx, drv, efx->net_dev,
"saw RX packet from iteration %d (wanted %d) in "
- "%s loopback test\n", ntohs(received->iteration),
+ "%s loopback test\n", ntohs(received.iteration),
ntohs(payload->iteration), LOOPBACK_MODE(efx));
goto err;
}
@@ -363,7 +369,8 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
buf_ptr, pkt_len, 0);
netif_err(efx, drv, efx->net_dev, "expected packet:\n");
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
- &state->payload, sizeof(state->payload), 0);
+ &state->payload.packet, EFX_LOOPBACK_PAYLOAD_LEN,
+ 0);
}
#endif
atomic_inc(&state->rx_bad);
@@ -385,14 +392,15 @@ static void efx_iterate_state(struct efx_nic *efx)
payload->ip.daddr = htonl(INADDR_LOOPBACK);
payload->ip.ihl = 5;
payload->ip.check = (__force __sum16) htons(0xdead);
- payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr));
+ payload->ip.tot_len = htons(sizeof(*payload) -
+ offsetof(struct efx_loopback_payload, ip));
payload->ip.version = IPVERSION;
payload->ip.protocol = IPPROTO_UDP;
/* Initialise udp header */
payload->udp.source = 0;
- payload->udp.len = htons(sizeof(*payload) - sizeof(struct ethhdr) -
- sizeof(struct iphdr));
+ payload->udp.len = htons(sizeof(*payload) -
+ offsetof(struct efx_loopback_payload, udp));
payload->udp.check = 0; /* checksum ignored */
/* Fill out payload */
@@ -429,6 +437,10 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue)
payload = skb_put(skb, sizeof(state->payload));
memcpy(payload, &state->payload, sizeof(state->payload));
payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2));
+ /* Strip off the leading padding */
+ skb_pull(skb, offsetof(struct efx_loopback_payload, header));
+ /* Strip off the trailing padding */
+ skb_trim(skb, EFX_LOOPBACK_PAYLOAD_LEN);
/* Ensure everything we've written is visible to the
* interrupt handler. */
diff --git a/drivers/net/ethernet/sfc/siena/selftest.c b/drivers/net/ethernet/sfc/siena/selftest.c
index 07715a3d6bea..526da43d4b61 100644
--- a/drivers/net/ethernet/sfc/siena/selftest.c
+++ b/drivers/net/ethernet/sfc/siena/selftest.c
@@ -42,12 +42,17 @@
* Falcon only performs RSS on TCP/UDP packets.
*/
struct efx_loopback_payload {
- struct ethhdr header;
- struct iphdr ip;
- struct udphdr udp;
- __be16 iteration;
- char msg[64];
-} __packed;
+ char pad[2]; /* Ensures ip is 4-byte aligned */
+ struct_group_attr(packet, __packed,
+ struct ethhdr header;
+ struct iphdr ip;
+ struct udphdr udp;
+ __be16 iteration;
+ char msg[64];
+ );
+} __packed __aligned(4);
+#define EFX_LOOPBACK_PAYLOAD_LEN \
+ sizeof_field(struct efx_loopback_payload, packet)
/* Loopback test source MAC address */
static const u8 payload_source[ETH_ALEN] __aligned(2) = {
@@ -282,7 +287,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
const char *buf_ptr, int pkt_len)
{
struct efx_loopback_state *state = efx->loopback_selftest;
- struct efx_loopback_payload *received;
+ struct efx_loopback_payload received;
struct efx_loopback_payload *payload;
BUG_ON(!buf_ptr);
@@ -293,13 +298,14 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
payload = &state->payload;
- received = (struct efx_loopback_payload *) buf_ptr;
- received->ip.saddr = payload->ip.saddr;
+ memcpy(&received.packet, buf_ptr,
+ min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN));
+ received.ip.saddr = payload->ip.saddr;
if (state->offload_csum)
- received->ip.check = payload->ip.check;
+ received.ip.check = payload->ip.check;
/* Check that header exists */
- if (pkt_len < sizeof(received->header)) {
+ if (pkt_len < sizeof(received.header)) {
netif_err(efx, drv, efx->net_dev,
"saw runt RX packet (length %d) in %s loopback "
"test\n", pkt_len, LOOPBACK_MODE(efx));
@@ -307,7 +313,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
}
/* Check that the ethernet header exists */
- if (memcmp(&received->header, &payload->header, ETH_HLEN) != 0) {
+ if (memcmp(&received.header, &payload->header, ETH_HLEN) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw non-loopback RX packet in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -315,16 +321,16 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
}
/* Check packet length */
- if (pkt_len != sizeof(*payload)) {
+ if (pkt_len != EFX_LOOPBACK_PAYLOAD_LEN) {
netif_err(efx, drv, efx->net_dev,
"saw incorrect RX packet length %d (wanted %d) in "
- "%s loopback test\n", pkt_len, (int)sizeof(*payload),
- LOOPBACK_MODE(efx));
+ "%s loopback test\n", pkt_len,
+ (int)EFX_LOOPBACK_PAYLOAD_LEN, LOOPBACK_MODE(efx));
goto err;
}
/* Check that IP header matches */
- if (memcmp(&received->ip, &payload->ip, sizeof(payload->ip)) != 0) {
+ if (memcmp(&received.ip, &payload->ip, sizeof(payload->ip)) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw corrupted IP header in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -332,7 +338,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
}
/* Check that msg and padding matches */
- if (memcmp(&received->msg, &payload->msg, sizeof(received->msg)) != 0) {
+ if (memcmp(&received.msg, &payload->msg, sizeof(received.msg)) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw corrupted RX packet in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -340,10 +346,10 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
}
/* Check that iteration matches */
- if (received->iteration != payload->iteration) {
+ if (received.iteration != payload->iteration) {
netif_err(efx, drv, efx->net_dev,
"saw RX packet from iteration %d (wanted %d) in "
- "%s loopback test\n", ntohs(received->iteration),
+ "%s loopback test\n", ntohs(received.iteration),
ntohs(payload->iteration), LOOPBACK_MODE(efx));
goto err;
}
@@ -363,7 +369,8 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
buf_ptr, pkt_len, 0);
netif_err(efx, drv, efx->net_dev, "expected packet:\n");
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
- &state->payload, sizeof(state->payload), 0);
+ &state->payload.packet, EFX_LOOPBACK_PAYLOAD_LEN,
+ 0);
}
#endif
atomic_inc(&state->rx_bad);
@@ -385,14 +392,15 @@ static void efx_iterate_state(struct efx_nic *efx)
payload->ip.daddr = htonl(INADDR_LOOPBACK);
payload->ip.ihl = 5;
payload->ip.check = (__force __sum16) htons(0xdead);
- payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr));
+ payload->ip.tot_len = htons(sizeof(*payload) -
+ offsetof(struct efx_loopback_payload, ip));
payload->ip.version = IPVERSION;
payload->ip.protocol = IPPROTO_UDP;
/* Initialise udp header */
payload->udp.source = 0;
- payload->udp.len = htons(sizeof(*payload) - sizeof(struct ethhdr) -
- sizeof(struct iphdr));
+ payload->udp.len = htons(sizeof(*payload) -
+ offsetof(struct efx_loopback_payload, udp));
payload->udp.check = 0; /* checksum ignored */
/* Fill out payload */
@@ -429,6 +437,10 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue)
payload = skb_put(skb, sizeof(state->payload));
memcpy(payload, &state->payload, sizeof(state->payload));
payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2));
+ /* Strip off the leading padding */
+ skb_pull(skb, offsetof(struct efx_loopback_payload, header));
+ /* Strip off the trailing padding */
+ skb_trim(skb, EFX_LOOPBACK_PAYLOAD_LEN);
/* Ensure everything we've written is visible to the
* interrupt handler. */
diff --git a/drivers/net/ethernet/sfc/siena/tx_common.c b/drivers/net/ethernet/sfc/siena/tx_common.c
index 93a32d61944f..a7a9ab304e13 100644
--- a/drivers/net/ethernet/sfc/siena/tx_common.c
+++ b/drivers/net/ethernet/sfc/siena/tx_common.c
@@ -12,6 +12,7 @@
#include "efx.h"
#include "nic_common.h"
#include "tx_common.h"
+#include <net/gso.h>
static unsigned int efx_tx_cb_page_count(struct efx_tx_queue *tx_queue)
{
diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c
index c004443c1d58..fe268b6c1cac 100644
--- a/drivers/net/ethernet/sfc/tc.c
+++ b/drivers/net/ethernet/sfc/tc.c
@@ -14,11 +14,12 @@
#include <net/geneve.h>
#include "tc.h"
#include "tc_bindings.h"
+#include "tc_encap_actions.h"
#include "mae.h"
#include "ef100_rep.h"
#include "efx.h"
-static enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev)
+enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev)
{
if (netif_is_vxlan(net_dev))
return EFX_ENCAP_TYPE_VXLAN;
@@ -33,8 +34,8 @@ static enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev)
* May return NULL for the PF (us), or an error pointer for a device that
* isn't supported as a TC offload endpoint
*/
-static struct efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx,
- struct net_device *dev)
+struct efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx,
+ struct net_device *dev)
{
struct efx_rep *efv;
@@ -70,7 +71,7 @@ static s64 efx_tc_flower_internal_mport(struct efx_nic *efx, struct efx_rep *efv
}
/* Convert a driver-internal vport ID into an external device (wire or VF) */
-static s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv)
+s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv)
{
u32 mport;
@@ -109,8 +110,17 @@ static void efx_tc_free_action_set(struct efx_nic *efx,
*/
list_del(&act->list);
}
- if (act->count)
+ if (act->count) {
+ spin_lock_bh(&act->count->cnt->lock);
+ if (!list_empty(&act->count_user))
+ list_del(&act->count_user);
+ spin_unlock_bh(&act->count->cnt->lock);
efx_tc_flower_put_counter_index(efx, act->count);
+ }
+ if (act->encap_md) {
+ list_del(&act->encap_user);
+ efx_tc_flower_release_encap_md(efx, act->encap_md);
+ }
kfree(act);
}
@@ -132,23 +142,6 @@ static void efx_tc_free_action_set_list(struct efx_nic *efx,
/* Don't kfree, as acts is embedded inside a struct efx_tc_flow_rule */
}
-static void efx_tc_flow_free(void *ptr, void *arg)
-{
- struct efx_tc_flow_rule *rule = ptr;
- struct efx_nic *efx = arg;
-
- netif_err(efx, drv, efx->net_dev,
- "tc rule %lx still present at teardown, removing\n",
- rule->cookie);
-
- efx_mae_delete_rule(efx, rule->fw_id);
-
- /* Release entries in subsidiary tables */
- efx_tc_free_action_set_list(efx, &rule->acts, true);
-
- kfree(rule);
-}
-
/* Boilerplate for the simple 'copy a field' cases */
#define _MAP_KEY_AND_MASK(_name, _type, _tcget, _tcfield, _field) \
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_##_name)) { \
@@ -219,6 +212,7 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx,
BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) |
BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) |
+ BIT(FLOW_DISSECTOR_KEY_ENC_IP) |
BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) |
BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) |
BIT(FLOW_DISSECTOR_KEY_TCP) |
@@ -363,20 +357,48 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx,
return 0;
}
+static void efx_tc_flower_release_encap_match(struct efx_nic *efx,
+ struct efx_tc_encap_match *encap)
+{
+ int rc;
+
+ if (!refcount_dec_and_test(&encap->ref))
+ return; /* still in use */
+
+ if (encap->type == EFX_TC_EM_DIRECT) {
+ rc = efx_mae_unregister_encap_match(efx, encap);
+ if (rc)
+ /* Display message but carry on and remove entry from our
+ * SW tables, because there's not much we can do about it.
+ */
+ netif_err(efx, drv, efx->net_dev,
+ "Failed to release encap match %#x, rc %d\n",
+ encap->fw_id, rc);
+ }
+ rhashtable_remove_fast(&efx->tc->encap_match_ht, &encap->linkage,
+ efx_tc_encap_match_ht_params);
+ if (encap->pseudo)
+ efx_tc_flower_release_encap_match(efx, encap->pseudo);
+ kfree(encap);
+}
+
static int efx_tc_flower_record_encap_match(struct efx_nic *efx,
struct efx_tc_match *match,
enum efx_encap_type type,
+ enum efx_tc_em_pseudo_type em_type,
+ u8 child_ip_tos_mask,
+ __be16 child_udp_sport_mask,
struct netlink_ext_ack *extack)
{
- struct efx_tc_encap_match *encap, *old;
+ struct efx_tc_encap_match *encap, *old, *pseudo = NULL;
bool ipv6 = false;
int rc;
/* We require that the socket-defining fields (IP addrs and UDP dest
- * port) are present and exact-match. Other fields are currently not
- * allowed. This meets what OVS will ask for, and means that we don't
- * need to handle difficult checks for overlapping matches as could
- * come up if we allowed masks or varying sets of match fields.
+ * port) are present and exact-match. Other fields may only be used
+ * if the field-set (and any masks) are the same for all encap
+ * matches on the same <sip,dip,dport> tuple; this is enforced by
+ * pseudo encap matches.
*/
if (match->mask.enc_dst_ip | match->mask.enc_src_ip) {
if (!IS_ALL_ONES(match->mask.enc_dst_ip)) {
@@ -414,29 +436,42 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx,
NL_SET_ERR_MSG_MOD(extack, "Egress encap match is not exact on dst UDP port");
return -EOPNOTSUPP;
}
- if (match->mask.enc_sport) {
- NL_SET_ERR_MSG_MOD(extack, "Egress encap match on src UDP port not supported");
- return -EOPNOTSUPP;
- }
- if (match->mask.enc_ip_tos) {
- NL_SET_ERR_MSG_MOD(extack, "Egress encap match on IP ToS not supported");
- return -EOPNOTSUPP;
+ if (match->mask.enc_sport || match->mask.enc_ip_tos) {
+ struct efx_tc_match pmatch = *match;
+
+ if (em_type == EFX_TC_EM_PSEUDO_MASK) { /* can't happen */
+ NL_SET_ERR_MSG_MOD(extack, "Bad recursion in egress encap match handler");
+ return -EOPNOTSUPP;
+ }
+ pmatch.value.enc_ip_tos = 0;
+ pmatch.mask.enc_ip_tos = 0;
+ pmatch.value.enc_sport = 0;
+ pmatch.mask.enc_sport = 0;
+ rc = efx_tc_flower_record_encap_match(efx, &pmatch, type,
+ EFX_TC_EM_PSEUDO_MASK,
+ match->mask.enc_ip_tos,
+ match->mask.enc_sport,
+ extack);
+ if (rc)
+ return rc;
+ pseudo = pmatch.encap;
}
if (match->mask.enc_ip_ttl) {
NL_SET_ERR_MSG_MOD(extack, "Egress encap match on IP TTL not supported");
- return -EOPNOTSUPP;
+ rc = -EOPNOTSUPP;
+ goto fail_pseudo;
}
- rc = efx_mae_check_encap_match_caps(efx, ipv6, extack);
- if (rc) {
- NL_SET_ERR_MSG_FMT_MOD(extack, "MAE hw reports no support for IPv%d encap matches",
- ipv6 ? 6 : 4);
- return -EOPNOTSUPP;
- }
+ rc = efx_mae_check_encap_match_caps(efx, ipv6, match->mask.enc_ip_tos,
+ match->mask.enc_sport, extack);
+ if (rc)
+ goto fail_pseudo;
encap = kzalloc(sizeof(*encap), GFP_USER);
- if (!encap)
- return -ENOMEM;
+ if (!encap) {
+ rc = -ENOMEM;
+ goto fail_pseudo;
+ }
encap->src_ip = match->value.enc_src_ip;
encap->dst_ip = match->value.enc_dst_ip;
#ifdef CONFIG_IPV6
@@ -445,12 +480,66 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx,
#endif
encap->udp_dport = match->value.enc_dport;
encap->tun_type = type;
+ encap->ip_tos = match->value.enc_ip_tos;
+ encap->ip_tos_mask = match->mask.enc_ip_tos;
+ encap->child_ip_tos_mask = child_ip_tos_mask;
+ encap->udp_sport = match->value.enc_sport;
+ encap->udp_sport_mask = match->mask.enc_sport;
+ encap->child_udp_sport_mask = child_udp_sport_mask;
+ encap->type = em_type;
+ encap->pseudo = pseudo;
old = rhashtable_lookup_get_insert_fast(&efx->tc->encap_match_ht,
&encap->linkage,
efx_tc_encap_match_ht_params);
if (old) {
/* don't need our new entry */
kfree(encap);
+ if (pseudo) /* don't need our new pseudo either */
+ efx_tc_flower_release_encap_match(efx, pseudo);
+ /* check old and new em_types are compatible */
+ switch (old->type) {
+ case EFX_TC_EM_DIRECT:
+ /* old EM is in hardware, so mustn't overlap with a
+ * pseudo, but may be shared with another direct EM
+ */
+ if (em_type == EFX_TC_EM_DIRECT)
+ break;
+ NL_SET_ERR_MSG_MOD(extack, "Pseudo encap match conflicts with existing direct entry");
+ return -EEXIST;
+ case EFX_TC_EM_PSEUDO_MASK:
+ /* old EM is protecting a ToS- or src port-qualified
+ * filter, so may only be shared with another pseudo
+ * for the same ToS and src port masks.
+ */
+ if (em_type != EFX_TC_EM_PSEUDO_MASK) {
+ NL_SET_ERR_MSG_FMT_MOD(extack,
+ "%s encap match conflicts with existing pseudo(MASK) entry",
+ em_type ? "Pseudo" : "Direct");
+ return -EEXIST;
+ }
+ if (child_ip_tos_mask != old->child_ip_tos_mask) {
+ NL_SET_ERR_MSG_FMT_MOD(extack,
+ "Pseudo encap match for TOS mask %#04x conflicts with existing pseudo(MASK) entry for TOS mask %#04x",
+ child_ip_tos_mask,
+ old->child_ip_tos_mask);
+ return -EEXIST;
+ }
+ if (child_udp_sport_mask != old->child_udp_sport_mask) {
+ NL_SET_ERR_MSG_FMT_MOD(extack,
+ "Pseudo encap match for UDP src port mask %#x conflicts with existing pseudo(MASK) entry for mask %#x",
+ child_udp_sport_mask,
+ old->child_udp_sport_mask);
+ return -EEXIST;
+ }
+ break;
+ default: /* Unrecognised pseudo-type. Just say no */
+ NL_SET_ERR_MSG_FMT_MOD(extack,
+ "%s encap match conflicts with existing pseudo(%d) entry",
+ em_type ? "Pseudo" : "Direct",
+ old->type);
+ return -EEXIST;
+ }
+ /* check old and new tun_types are compatible */
if (old->tun_type != type) {
NL_SET_ERR_MSG_FMT_MOD(extack,
"Egress encap match with conflicting tun_type %u != %u",
@@ -462,10 +551,12 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx,
/* existing entry found */
encap = old;
} else {
- rc = efx_mae_register_encap_match(efx, encap);
- if (rc) {
- NL_SET_ERR_MSG_MOD(extack, "Failed to record egress encap match in HW");
- goto fail;
+ if (em_type == EFX_TC_EM_DIRECT) {
+ rc = efx_mae_register_encap_match(efx, encap);
+ if (rc) {
+ NL_SET_ERR_MSG_MOD(extack, "Failed to record egress encap match in HW");
+ goto fail;
+ }
}
refcount_set(&encap->ref, 1);
}
@@ -475,30 +566,12 @@ fail:
rhashtable_remove_fast(&efx->tc->encap_match_ht, &encap->linkage,
efx_tc_encap_match_ht_params);
kfree(encap);
+fail_pseudo:
+ if (pseudo)
+ efx_tc_flower_release_encap_match(efx, pseudo);
return rc;
}
-static void efx_tc_flower_release_encap_match(struct efx_nic *efx,
- struct efx_tc_encap_match *encap)
-{
- int rc;
-
- if (!refcount_dec_and_test(&encap->ref))
- return; /* still in use */
-
- rc = efx_mae_unregister_encap_match(efx, encap);
- if (rc)
- /* Display message but carry on and remove entry from our
- * SW tables, because there's not much we can do about it.
- */
- netif_err(efx, drv, efx->net_dev,
- "Failed to release encap match %#x, rc %d\n",
- encap->fw_id, rc);
- rhashtable_remove_fast(&efx->tc->encap_match_ht, &encap->linkage,
- efx_tc_encap_match_ht_params);
- kfree(encap);
-}
-
static void efx_tc_delete_rule(struct efx_nic *efx, struct efx_tc_flow_rule *rule)
{
efx_mae_delete_rule(efx, rule->fw_id);
@@ -531,6 +604,7 @@ enum efx_tc_action_order {
EFX_TC_AO_VLAN_POP,
EFX_TC_AO_VLAN_PUSH,
EFX_TC_AO_COUNT,
+ EFX_TC_AO_ENCAP,
EFX_TC_AO_DELIVER
};
/* Determine whether we can add @new action without violating order */
@@ -560,6 +634,10 @@ static bool efx_tc_flower_action_order_ok(const struct efx_tc_action_set *act,
if (act->count)
return false;
fallthrough;
+ case EFX_TC_AO_ENCAP:
+ if (act->encap_md)
+ return false;
+ fallthrough;
case EFX_TC_AO_DELIVER:
return !act->deliver;
default:
@@ -650,6 +728,7 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx,
}
rc = efx_tc_flower_record_encap_match(efx, &match, type,
+ EFX_TC_EM_DIRECT, 0, 0,
extack);
if (rc)
return rc;
@@ -722,6 +801,7 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx,
goto release;
}
act->count = ctr;
+ INIT_LIST_HEAD(&act->count_user);
}
if (!efx_tc_flower_action_order_ok(act, EFX_TC_AO_DELIVER)) {
@@ -854,11 +934,13 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
{
struct flow_rule *fr = flow_cls_offload_flow_rule(tc);
struct netlink_ext_ack *extack = tc->common.extack;
+ const struct ip_tunnel_info *encap_info = NULL;
struct efx_tc_flow_rule *rule = NULL, *old;
struct efx_tc_action_set *act = NULL;
const struct flow_action_entry *fa;
struct efx_rep *from_efv, *to_efv;
struct efx_tc_match match;
+ u32 acts_id;
s64 rc;
int i;
@@ -1007,6 +1089,7 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
goto release;
}
act->count = ctr;
+ INIT_LIST_HEAD(&act->count_user);
}
switch (fa->id) {
@@ -1023,6 +1106,59 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
case FLOW_ACTION_MIRRED:
save = *act;
+ if (encap_info) {
+ struct efx_tc_encap_action *encap;
+
+ if (!efx_tc_flower_action_order_ok(act,
+ EFX_TC_AO_ENCAP)) {
+ rc = -EOPNOTSUPP;
+ NL_SET_ERR_MSG_MOD(extack, "Encap action violates action order");
+ goto release;
+ }
+ encap = efx_tc_flower_create_encap_md(
+ efx, encap_info, fa->dev, extack);
+ if (IS_ERR_OR_NULL(encap)) {
+ rc = PTR_ERR(encap);
+ if (!rc)
+ rc = -EIO; /* arbitrary */
+ goto release;
+ }
+ act->encap_md = encap;
+ list_add_tail(&act->encap_user, &encap->users);
+ act->dest_mport = encap->dest_mport;
+ act->deliver = 1;
+ if (act->count && !WARN_ON(!act->count->cnt)) {
+ /* This counter is used by an encap
+ * action, which needs a reference back
+ * so it can prod neighbouring whenever
+ * traffic is seen.
+ */
+ spin_lock_bh(&act->count->cnt->lock);
+ list_add_tail(&act->count_user,
+ &act->count->cnt->users);
+ spin_unlock_bh(&act->count->cnt->lock);
+ }
+ rc = efx_mae_alloc_action_set(efx, act);
+ if (rc) {
+ NL_SET_ERR_MSG_MOD(extack, "Failed to write action set to hw (encap)");
+ goto release;
+ }
+ list_add_tail(&act->list, &rule->acts.list);
+ act->user = &rule->acts;
+ act = NULL;
+ if (fa->id == FLOW_ACTION_REDIRECT)
+ break; /* end of the line */
+ /* Mirror, so continue on with saved act */
+ save.count = NULL;
+ act = kzalloc(sizeof(*act), GFP_USER);
+ if (!act) {
+ rc = -ENOMEM;
+ goto release;
+ }
+ *act = save;
+ break;
+ }
+
if (!efx_tc_flower_action_order_ok(act, EFX_TC_AO_DELIVER)) {
/* can't happen */
rc = -EOPNOTSUPP;
@@ -1086,6 +1222,37 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
act->vlan_proto[act->vlan_push] = fa->vlan.proto;
act->vlan_push++;
break;
+ case FLOW_ACTION_TUNNEL_ENCAP:
+ if (encap_info) {
+ /* Can't specify encap multiple times.
+ * If you want to overwrite an existing
+ * encap_info, use an intervening
+ * FLOW_ACTION_TUNNEL_DECAP to clear it.
+ */
+ NL_SET_ERR_MSG_MOD(extack, "Tunnel key set when already set");
+ rc = -EINVAL;
+ goto release;
+ }
+ if (!fa->tunnel) {
+ NL_SET_ERR_MSG_MOD(extack, "Tunnel key set is missing key");
+ rc = -EOPNOTSUPP;
+ goto release;
+ }
+ encap_info = fa->tunnel;
+ break;
+ case FLOW_ACTION_TUNNEL_DECAP:
+ if (encap_info) {
+ encap_info = NULL;
+ break;
+ }
+ /* Since we don't support enc_key matches on ingress
+ * (and if we did there'd be no tunnel-device to give
+ * us a type), we can't offload a decap that's not
+ * just undoing a previous encap action.
+ */
+ NL_SET_ERR_MSG_MOD(extack, "Cannot offload tunnel decap action without tunnel device");
+ rc = -EOPNOTSUPP;
+ goto release;
default:
NL_SET_ERR_MSG_FMT_MOD(extack, "Unhandled action %u",
fa->id);
@@ -1129,8 +1296,21 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
NL_SET_ERR_MSG_MOD(extack, "Failed to write action set list to hw");
goto release;
}
+ if (from_efv == EFX_EFV_PF)
+ /* PF netdev, so rule applies to traffic from wire */
+ rule->fallback = &efx->tc->facts.pf;
+ else
+ /* repdev, so rule applies to traffic from representee */
+ rule->fallback = &efx->tc->facts.reps;
+ if (!efx_tc_check_ready(efx, rule)) {
+ netif_dbg(efx, drv, efx->net_dev, "action not ready for hw\n");
+ acts_id = rule->fallback->fw_id;
+ } else {
+ netif_dbg(efx, drv, efx->net_dev, "ready for hw\n");
+ acts_id = rule->acts.fw_id;
+ }
rc = efx_mae_insert_rule(efx, &rule->match, EFX_TC_PRIO_TC,
- rule->acts.fw_id, &rule->fw_id);
+ acts_id, &rule->fw_id);
if (rc) {
NL_SET_ERR_MSG_MOD(extack, "Failed to insert rule in hw");
goto release_acts;
@@ -1327,6 +1507,58 @@ void efx_tc_deconfigure_default_rule(struct efx_nic *efx,
rule->fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL;
}
+static int efx_tc_configure_fallback_acts(struct efx_nic *efx, u32 eg_port,
+ struct efx_tc_action_set_list *acts)
+{
+ struct efx_tc_action_set *act;
+ int rc;
+
+ act = kzalloc(sizeof(*act), GFP_KERNEL);
+ if (!act)
+ return -ENOMEM;
+ act->deliver = 1;
+ act->dest_mport = eg_port;
+ rc = efx_mae_alloc_action_set(efx, act);
+ if (rc)
+ goto fail1;
+ EFX_WARN_ON_PARANOID(!list_empty(&acts->list));
+ list_add_tail(&act->list, &acts->list);
+ rc = efx_mae_alloc_action_set_list(efx, acts);
+ if (rc)
+ goto fail2;
+ return 0;
+fail2:
+ list_del(&act->list);
+ efx_mae_free_action_set(efx, act->fw_id);
+fail1:
+ kfree(act);
+ return rc;
+}
+
+static int efx_tc_configure_fallback_acts_pf(struct efx_nic *efx)
+{
+ struct efx_tc_action_set_list *acts = &efx->tc->facts.pf;
+ u32 eg_port;
+
+ efx_mae_mport_uplink(efx, &eg_port);
+ return efx_tc_configure_fallback_acts(efx, eg_port, acts);
+}
+
+static int efx_tc_configure_fallback_acts_reps(struct efx_nic *efx)
+{
+ struct efx_tc_action_set_list *acts = &efx->tc->facts.reps;
+ u32 eg_port;
+
+ efx_mae_mport_mport(efx, efx->tc->reps_mport_id, &eg_port);
+ return efx_tc_configure_fallback_acts(efx, eg_port, acts);
+}
+
+static void efx_tc_deconfigure_fallback_acts(struct efx_nic *efx,
+ struct efx_tc_action_set_list *acts)
+{
+ efx_tc_free_action_set_list(efx, acts, true);
+}
+
static int efx_tc_configure_rep_mport(struct efx_nic *efx)
{
u32 rep_mport_label;
@@ -1419,10 +1651,16 @@ int efx_init_tc(struct efx_nic *efx)
rc = efx_tc_configure_rep_mport(efx);
if (rc)
return rc;
- efx->tc->up = true;
+ rc = efx_tc_configure_fallback_acts_pf(efx);
+ if (rc)
+ return rc;
+ rc = efx_tc_configure_fallback_acts_reps(efx);
+ if (rc)
+ return rc;
rc = flow_indr_dev_register(efx_tc_indr_setup_cb, efx);
if (rc)
return rc;
+ efx->tc->up = true;
return 0;
}
@@ -1436,6 +1674,8 @@ void efx_fini_tc(struct efx_nic *efx)
efx_tc_deconfigure_rep_mport(efx);
efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.pf);
efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.wire);
+ efx_tc_deconfigure_fallback_acts(efx, &efx->tc->facts.pf);
+ efx_tc_deconfigure_fallback_acts(efx, &efx->tc->facts.reps);
efx->tc->up = false;
}
@@ -1451,6 +1691,21 @@ static void efx_tc_encap_match_free(void *ptr, void *__unused)
kfree(encap);
}
+static void efx_tc_flow_free(void *ptr, void *arg)
+{
+ struct efx_tc_flow_rule *rule = ptr;
+ struct efx_nic *efx = arg;
+
+ netif_err(efx, drv, efx->net_dev,
+ "tc rule %lx still present at teardown, removing\n",
+ rule->cookie);
+
+ /* Also releases entries in subsidiary tables */
+ efx_tc_delete_rule(efx, rule);
+
+ kfree(rule);
+}
+
int efx_init_struct_tc(struct efx_nic *efx)
{
int rc;
@@ -1470,6 +1725,9 @@ int efx_init_struct_tc(struct efx_nic *efx)
mutex_init(&efx->tc->mutex);
init_waitqueue_head(&efx->tc->flush_wq);
+ rc = efx_tc_init_encap_actions(efx);
+ if (rc < 0)
+ goto fail_encap_actions;
rc = efx_tc_init_counters(efx);
if (rc < 0)
goto fail_counters;
@@ -1485,6 +1743,10 @@ int efx_init_struct_tc(struct efx_nic *efx)
efx->tc->dflt.pf.fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL;
INIT_LIST_HEAD(&efx->tc->dflt.wire.acts.list);
efx->tc->dflt.wire.fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL;
+ INIT_LIST_HEAD(&efx->tc->facts.pf.list);
+ efx->tc->facts.pf.fw_id = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL;
+ INIT_LIST_HEAD(&efx->tc->facts.reps.list);
+ efx->tc->facts.reps.fw_id = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL;
efx->extra_channel_type[EFX_EXTRA_CHANNEL_TC] = &efx_tc_channel_type;
return 0;
fail_match_action_ht:
@@ -1492,6 +1754,8 @@ fail_match_action_ht:
fail_encap_match_ht:
efx_tc_destroy_counters(efx);
fail_counters:
+ efx_tc_destroy_encap_actions(efx);
+fail_encap_actions:
mutex_destroy(&efx->tc->mutex);
kfree(efx->tc->caps);
fail_alloc_caps:
@@ -1510,11 +1774,16 @@ void efx_fini_struct_tc(struct efx_nic *efx)
MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL);
EFX_WARN_ON_PARANOID(efx->tc->dflt.wire.fw_id !=
MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL);
+ EFX_WARN_ON_PARANOID(efx->tc->facts.pf.fw_id !=
+ MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL);
+ EFX_WARN_ON_PARANOID(efx->tc->facts.reps.fw_id !=
+ MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL);
rhashtable_free_and_destroy(&efx->tc->match_action_ht, efx_tc_flow_free,
efx);
rhashtable_free_and_destroy(&efx->tc->encap_match_ht,
efx_tc_encap_match_free, NULL);
efx_tc_fini_counters(efx);
+ efx_tc_fini_encap_actions(efx);
mutex_unlock(&efx->tc->mutex);
mutex_destroy(&efx->tc->mutex);
kfree(efx->tc->caps);
diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h
index 04cced6a2d39..1549c3df43bb 100644
--- a/drivers/net/ethernet/sfc/tc.h
+++ b/drivers/net/ethernet/sfc/tc.h
@@ -25,6 +25,8 @@ static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr)
}
#endif
+struct efx_tc_encap_action; /* see tc_encap_actions.h */
+
struct efx_tc_action_set {
u16 vlan_push:2;
u16 vlan_pop:2;
@@ -33,6 +35,10 @@ struct efx_tc_action_set {
__be16 vlan_tci[2]; /* TCIs for vlan_push */
__be16 vlan_proto[2]; /* Ethertypes for vlan_push */
struct efx_tc_counter_index *count;
+ struct efx_tc_encap_action *encap_md; /* entry in tc_encap_ht table */
+ struct list_head encap_user; /* entry on encap_md->users list */
+ struct efx_tc_action_set_list *user; /* Only populated if encap_md */
+ struct list_head count_user; /* entry on counter->users list, if encap */
u32 dest_mport;
u32 fw_id; /* index of this entry in firmware actions table */
struct list_head list;
@@ -74,14 +80,41 @@ static inline bool efx_tc_match_is_encap(const struct efx_tc_match_fields *mask)
mask->enc_ip_ttl || mask->enc_sport || mask->enc_dport;
}
+/**
+ * enum efx_tc_em_pseudo_type - &struct efx_tc_encap_match pseudo type
+ *
+ * These are used to classify "pseudo" encap matches, which don't refer
+ * to an entry in hardware but rather indicate that a section of the
+ * match space is in use by another Outer Rule.
+ *
+ * @EFX_TC_EM_DIRECT: real HW entry in Outer Rule table; not a pseudo.
+ * Hardware index in &struct efx_tc_encap_match.fw_id is valid.
+ * @EFX_TC_EM_PSEUDO_MASK: registered by an encap match which includes a
+ * match on an optional field (currently ip_tos and/or udp_sport),
+ * to prevent an overlapping encap match _without_ optional fields.
+ * The pseudo encap match may be referenced again by an encap match
+ * with different values for these fields, but all masks must match the
+ * first (stored in our child_* fields).
+ */
+enum efx_tc_em_pseudo_type {
+ EFX_TC_EM_DIRECT,
+ EFX_TC_EM_PSEUDO_MASK,
+};
+
struct efx_tc_encap_match {
__be32 src_ip, dst_ip;
struct in6_addr src_ip6, dst_ip6;
__be16 udp_dport;
+ __be16 udp_sport, udp_sport_mask;
+ u8 ip_tos, ip_tos_mask;
struct rhash_head linkage;
enum efx_encap_type tun_type;
+ u8 child_ip_tos_mask;
+ __be16 child_udp_sport_mask;
refcount_t ref;
+ enum efx_tc_em_pseudo_type type;
u32 fw_id; /* index of this entry in firmware encap match table */
+ struct efx_tc_encap_match *pseudo; /* Referenced pseudo EM if needed */
};
struct efx_tc_match {
@@ -100,6 +133,7 @@ struct efx_tc_flow_rule {
struct rhash_head linkage;
struct efx_tc_match match;
struct efx_tc_action_set_list acts;
+ struct efx_tc_action_set_list *fallback; /* what to use when unready? */
u32 fw_id;
};
@@ -117,8 +151,10 @@ enum efx_tc_rule_prios {
* @mutex: Used to serialise operations on TC hashtables
* @counter_ht: Hashtable of TC counters (FW IDs and counter values)
* @counter_id_ht: Hashtable mapping TC counter cookies to counters
+ * @encap_ht: Hashtable of TC encap actions
* @encap_match_ht: Hashtable of TC encap matches
* @match_action_ht: Hashtable of TC match-action rules
+ * @neigh_ht: Hashtable of neighbour watches (&struct efx_neigh_binder)
* @reps_mport_id: MAE port allocated for representor RX
* @reps_filter_uc: VNIC filter for representor unicast RX (promisc)
* @reps_filter_mc: VNIC filter for representor multicast RX (allmulti)
@@ -133,6 +169,11 @@ enum efx_tc_rule_prios {
* %EFX_TC_PRIO_DFLT. Named by *ingress* port
* @dflt.pf: rule for traffic ingressing from PF (egresses to wire)
* @dflt.wire: rule for traffic ingressing from wire (egresses to PF)
+ * @facts: Fallback action-set-lists for unready rules. Named by *egress* port
+ * @facts.pf: action-set-list for unready rules on PF netdev, hence applying to
+ * traffic from wire, and egressing to PF
+ * @facts.reps: action-set-list for unready rules on representors, hence
+ * applying to traffic from representees, and egressing to the reps mport
* @up: have TC datastructures been set up?
*/
struct efx_tc_state {
@@ -141,8 +182,10 @@ struct efx_tc_state {
struct mutex mutex;
struct rhashtable counter_ht;
struct rhashtable counter_id_ht;
+ struct rhashtable encap_ht;
struct rhashtable encap_match_ht;
struct rhashtable match_action_ht;
+ struct rhashtable neigh_ht;
u32 reps_mport_id, reps_mport_vport_id;
s32 reps_filter_uc, reps_filter_mc;
bool flush_counters;
@@ -153,11 +196,19 @@ struct efx_tc_state {
struct efx_tc_flow_rule pf;
struct efx_tc_flow_rule wire;
} dflt;
+ struct {
+ struct efx_tc_action_set_list pf;
+ struct efx_tc_action_set_list reps;
+ } facts;
bool up;
};
struct efx_rep;
+enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev);
+struct efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx,
+ struct net_device *dev);
+s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv);
int efx_tc_configure_default_rule_rep(struct efx_rep *efv);
void efx_tc_deconfigure_default_rule(struct efx_nic *efx,
struct efx_tc_flow_rule *rule);
diff --git a/drivers/net/ethernet/sfc/tc_bindings.c b/drivers/net/ethernet/sfc/tc_bindings.c
index c18d64519c2d..1b79c535c54e 100644
--- a/drivers/net/ethernet/sfc/tc_bindings.c
+++ b/drivers/net/ethernet/sfc/tc_bindings.c
@@ -10,6 +10,7 @@
#include "tc_bindings.h"
#include "tc.h"
+#include "tc_encap_actions.h"
struct efx_tc_block_binding {
struct list_head list;
@@ -226,3 +227,15 @@ int efx_tc_setup(struct net_device *net_dev, enum tc_setup_type type,
return -EOPNOTSUPP;
}
+
+int efx_tc_netdev_event(struct efx_nic *efx, unsigned long event,
+ struct net_device *net_dev)
+{
+ if (efx->type->is_vf)
+ return NOTIFY_DONE;
+
+ if (event == NETDEV_UNREGISTER)
+ efx_tc_unregister_egdev(efx, net_dev);
+
+ return NOTIFY_OK;
+}
diff --git a/drivers/net/ethernet/sfc/tc_bindings.h b/drivers/net/ethernet/sfc/tc_bindings.h
index c210bb09150e..a326d23d322b 100644
--- a/drivers/net/ethernet/sfc/tc_bindings.h
+++ b/drivers/net/ethernet/sfc/tc_bindings.h
@@ -12,6 +12,7 @@
#define EFX_TC_BINDINGS_H
#include "net_driver.h"
+#if IS_ENABLED(CONFIG_SFC_SRIOV)
#include <net/sch_generic.h>
struct efx_rep;
@@ -26,4 +27,17 @@ int efx_tc_indr_setup_cb(struct net_device *net_dev, struct Qdisc *sch,
void *cb_priv, enum tc_setup_type type,
void *type_data, void *data,
void (*cleanup)(struct flow_block_cb *block_cb));
+int efx_tc_netdev_event(struct efx_nic *efx, unsigned long event,
+ struct net_device *net_dev);
+
+#else /* CONFIG_SFC_SRIOV */
+
+static inline int efx_tc_netdev_event(struct efx_nic *efx, unsigned long event,
+ struct net_device *net_dev)
+{
+ return NOTIFY_DONE;
+}
+
+#endif /* CONFIG_SFC_SRIOV */
+
#endif /* EFX_TC_BINDINGS_H */
diff --git a/drivers/net/ethernet/sfc/tc_counters.c b/drivers/net/ethernet/sfc/tc_counters.c
index d1a91d54c6bb..979f49058a0c 100644
--- a/drivers/net/ethernet/sfc/tc_counters.c
+++ b/drivers/net/ethernet/sfc/tc_counters.c
@@ -9,6 +9,7 @@
*/
#include "tc_counters.h"
+#include "tc_encap_actions.h"
#include "mae_counter_format.h"
#include "mae.h"
#include "rx_common.h"
@@ -31,6 +32,15 @@ static void efx_tc_counter_free(void *ptr, void *__unused)
{
struct efx_tc_counter *cnt = ptr;
+ WARN_ON(!list_empty(&cnt->users));
+ /* We'd like to synchronize_rcu() here, but unfortunately we aren't
+ * removing the element from the hashtable (it's not clear that's a
+ * safe thing to do in an rhashtable_free_and_destroy free_fn), so
+ * threads could still be obtaining new pointers to *cnt if they can
+ * race against this function at all.
+ */
+ flush_work(&cnt->work);
+ EFX_WARN_ON_PARANOID(spin_is_locked(&cnt->lock));
kfree(cnt);
}
@@ -74,6 +84,49 @@ void efx_tc_fini_counters(struct efx_nic *efx)
rhashtable_free_and_destroy(&efx->tc->counter_ht, efx_tc_counter_free, NULL);
}
+static void efx_tc_counter_work(struct work_struct *work)
+{
+ struct efx_tc_counter *cnt = container_of(work, struct efx_tc_counter, work);
+ struct efx_tc_encap_action *encap;
+ struct efx_tc_action_set *act;
+ unsigned long touched;
+ struct neighbour *n;
+
+ spin_lock_bh(&cnt->lock);
+ touched = READ_ONCE(cnt->touched);
+
+ list_for_each_entry(act, &cnt->users, count_user) {
+ encap = act->encap_md;
+ if (!encap)
+ continue;
+ if (!encap->neigh) /* can't happen */
+ continue;
+ if (time_after_eq(encap->neigh->used, touched))
+ continue;
+ encap->neigh->used = touched;
+ /* We have passed traffic using this ARP entry, so
+ * indicate to the ARP cache that it's still active
+ */
+ if (encap->neigh->dst_ip)
+ n = neigh_lookup(&arp_tbl, &encap->neigh->dst_ip,
+ encap->neigh->egdev);
+ else
+#if IS_ENABLED(CONFIG_IPV6)
+ n = neigh_lookup(ipv6_stub->nd_tbl,
+ &encap->neigh->dst_ip6,
+ encap->neigh->egdev);
+#else
+ n = NULL;
+#endif
+ if (!n)
+ continue;
+
+ neigh_event_send(n, NULL);
+ neigh_release(n);
+ }
+ spin_unlock_bh(&cnt->lock);
+}
+
/* Counter allocation */
static struct efx_tc_counter *efx_tc_flower_allocate_counter(struct efx_nic *efx,
@@ -87,12 +140,14 @@ static struct efx_tc_counter *efx_tc_flower_allocate_counter(struct efx_nic *efx
return ERR_PTR(-ENOMEM);
spin_lock_init(&cnt->lock);
+ INIT_WORK(&cnt->work, efx_tc_counter_work);
cnt->touched = jiffies;
cnt->type = type;
rc = efx_mae_allocate_counter(efx, cnt);
if (rc)
goto fail1;
+ INIT_LIST_HEAD(&cnt->users);
rc = rhashtable_insert_fast(&efx->tc->counter_ht, &cnt->linkage,
efx_tc_counter_ht_params);
if (rc)
@@ -126,6 +181,7 @@ static void efx_tc_flower_release_counter(struct efx_nic *efx,
netif_warn(efx, hw, efx->net_dev,
"Failed to free MAE counter %u, rc %d\n",
cnt->fw_id, rc);
+ WARN_ON(!list_empty(&cnt->users));
/* This doesn't protect counter updates coming in arbitrarily long
* after we deleted the counter. The RCU just ensures that we won't
* free the counter while another thread has a pointer to it.
@@ -133,6 +189,7 @@ static void efx_tc_flower_release_counter(struct efx_nic *efx,
* is handled by the generation count.
*/
synchronize_rcu();
+ flush_work(&cnt->work);
EFX_WARN_ON_PARANOID(spin_is_locked(&cnt->lock));
kfree(cnt);
}
@@ -302,6 +359,7 @@ static void efx_tc_counter_update(struct efx_nic *efx,
cnt->touched = jiffies;
}
spin_unlock_bh(&cnt->lock);
+ schedule_work(&cnt->work);
out:
rcu_read_unlock();
}
diff --git a/drivers/net/ethernet/sfc/tc_counters.h b/drivers/net/ethernet/sfc/tc_counters.h
index 8fc7c4bbb29c..41e57f34b763 100644
--- a/drivers/net/ethernet/sfc/tc_counters.h
+++ b/drivers/net/ethernet/sfc/tc_counters.h
@@ -32,6 +32,9 @@ struct efx_tc_counter {
u64 old_packets, old_bytes; /* Values last time passed to userspace */
/* jiffies of the last time we saw packets increase */
unsigned long touched;
+ struct work_struct work; /* For notifying encap actions */
+ /* owners of corresponding count actions */
+ struct list_head users;
};
struct efx_tc_counter_index {
diff --git a/drivers/net/ethernet/sfc/tc_encap_actions.c b/drivers/net/ethernet/sfc/tc_encap_actions.c
new file mode 100644
index 000000000000..7e8bcdb222ad
--- /dev/null
+++ b/drivers/net/ethernet/sfc/tc_encap_actions.c
@@ -0,0 +1,747 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2023, Advanced Micro Devices, Inc.
+ *
+ * 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, incorporated herein by reference.
+ */
+
+#include "tc_encap_actions.h"
+#include "tc.h"
+#include "mae.h"
+#include <net/vxlan.h>
+#include <net/geneve.h>
+#include <net/netevent.h>
+#include <net/arp.h>
+
+static const struct rhashtable_params efx_neigh_ht_params = {
+ .key_len = offsetof(struct efx_neigh_binder, ha),
+ .key_offset = 0,
+ .head_offset = offsetof(struct efx_neigh_binder, linkage),
+};
+
+static const struct rhashtable_params efx_tc_encap_ht_params = {
+ .key_len = offsetofend(struct efx_tc_encap_action, key),
+ .key_offset = 0,
+ .head_offset = offsetof(struct efx_tc_encap_action, linkage),
+};
+
+static void efx_tc_encap_free(void *ptr, void *__unused)
+{
+ struct efx_tc_encap_action *enc = ptr;
+
+ WARN_ON(refcount_read(&enc->ref));
+ kfree(enc);
+}
+
+static void efx_neigh_free(void *ptr, void *__unused)
+{
+ struct efx_neigh_binder *neigh = ptr;
+
+ WARN_ON(refcount_read(&neigh->ref));
+ WARN_ON(!list_empty(&neigh->users));
+ put_net_track(neigh->net, &neigh->ns_tracker);
+ netdev_put(neigh->egdev, &neigh->dev_tracker);
+ kfree(neigh);
+}
+
+int efx_tc_init_encap_actions(struct efx_nic *efx)
+{
+ int rc;
+
+ rc = rhashtable_init(&efx->tc->neigh_ht, &efx_neigh_ht_params);
+ if (rc < 0)
+ goto fail_neigh_ht;
+ rc = rhashtable_init(&efx->tc->encap_ht, &efx_tc_encap_ht_params);
+ if (rc < 0)
+ goto fail_encap_ht;
+ return 0;
+fail_encap_ht:
+ rhashtable_destroy(&efx->tc->neigh_ht);
+fail_neigh_ht:
+ return rc;
+}
+
+/* Only call this in init failure teardown.
+ * Normal exit should fini instead as there may be entries in the table.
+ */
+void efx_tc_destroy_encap_actions(struct efx_nic *efx)
+{
+ rhashtable_destroy(&efx->tc->encap_ht);
+ rhashtable_destroy(&efx->tc->neigh_ht);
+}
+
+void efx_tc_fini_encap_actions(struct efx_nic *efx)
+{
+ rhashtable_free_and_destroy(&efx->tc->encap_ht, efx_tc_encap_free, NULL);
+ rhashtable_free_and_destroy(&efx->tc->neigh_ht, efx_neigh_free, NULL);
+}
+
+static void efx_neigh_update(struct work_struct *work);
+
+static int efx_bind_neigh(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap, struct net *net,
+ struct netlink_ext_ack *extack)
+{
+ struct efx_neigh_binder *neigh, *old;
+ struct flowi6 flow6 = {};
+ struct flowi4 flow4 = {};
+ int rc;
+
+ /* GCC stupidly thinks that only values explicitly listed in the enum
+ * definition can _possibly_ be sensible case values, so without this
+ * cast it complains about the IPv6 versions.
+ */
+ switch ((int)encap->type) {
+ case EFX_ENCAP_TYPE_VXLAN:
+ case EFX_ENCAP_TYPE_GENEVE:
+ flow4.flowi4_proto = IPPROTO_UDP;
+ flow4.fl4_dport = encap->key.tp_dst;
+ flow4.flowi4_tos = encap->key.tos;
+ flow4.daddr = encap->key.u.ipv4.dst;
+ flow4.saddr = encap->key.u.ipv4.src;
+ break;
+ case EFX_ENCAP_TYPE_VXLAN | EFX_ENCAP_FLAG_IPV6:
+ case EFX_ENCAP_TYPE_GENEVE | EFX_ENCAP_FLAG_IPV6:
+ flow6.flowi6_proto = IPPROTO_UDP;
+ flow6.fl6_dport = encap->key.tp_dst;
+ flow6.flowlabel = ip6_make_flowinfo(encap->key.tos,
+ encap->key.label);
+ flow6.daddr = encap->key.u.ipv6.dst;
+ flow6.saddr = encap->key.u.ipv6.src;
+ break;
+ default:
+ NL_SET_ERR_MSG_FMT_MOD(extack, "Unsupported encap type %d",
+ (int)encap->type);
+ return -EOPNOTSUPP;
+ }
+
+ neigh = kzalloc(sizeof(*neigh), GFP_KERNEL_ACCOUNT);
+ if (!neigh)
+ return -ENOMEM;
+ neigh->net = get_net_track(net, &neigh->ns_tracker, GFP_KERNEL_ACCOUNT);
+ neigh->dst_ip = flow4.daddr;
+ neigh->dst_ip6 = flow6.daddr;
+
+ old = rhashtable_lookup_get_insert_fast(&efx->tc->neigh_ht,
+ &neigh->linkage,
+ efx_neigh_ht_params);
+ if (old) {
+ /* don't need our new entry */
+ put_net_track(neigh->net, &neigh->ns_tracker);
+ kfree(neigh);
+ if (!refcount_inc_not_zero(&old->ref))
+ return -EAGAIN;
+ /* existing entry found, ref taken */
+ neigh = old;
+ } else {
+ /* New entry. We need to initiate a lookup */
+ struct neighbour *n;
+ struct rtable *rt;
+
+ if (encap->type & EFX_ENCAP_FLAG_IPV6) {
+#if IS_ENABLED(CONFIG_IPV6)
+ struct dst_entry *dst;
+
+ dst = ipv6_stub->ipv6_dst_lookup_flow(net, NULL, &flow6,
+ NULL);
+ rc = PTR_ERR_OR_ZERO(dst);
+ if (rc) {
+ NL_SET_ERR_MSG_MOD(extack, "Failed to lookup route for IPv6 encap");
+ goto out_free;
+ }
+ neigh->egdev = dst->dev;
+ netdev_hold(neigh->egdev, &neigh->dev_tracker,
+ GFP_KERNEL_ACCOUNT);
+ neigh->ttl = ip6_dst_hoplimit(dst);
+ n = dst_neigh_lookup(dst, &flow6.daddr);
+ dst_release(dst);
+#else
+ /* We shouldn't ever get here, because if IPv6 isn't
+ * enabled how did someone create an IPv6 tunnel_key?
+ */
+ rc = -EOPNOTSUPP;
+ NL_SET_ERR_MSG_MOD(extack, "No IPv6 support (neigh bind)");
+ goto out_free;
+#endif
+ } else {
+ rt = ip_route_output_key(net, &flow4);
+ if (IS_ERR_OR_NULL(rt)) {
+ rc = PTR_ERR_OR_ZERO(rt);
+ if (!rc)
+ rc = -EIO;
+ NL_SET_ERR_MSG_MOD(extack, "Failed to lookup route for encap");
+ goto out_free;
+ }
+ neigh->egdev = rt->dst.dev;
+ netdev_hold(neigh->egdev, &neigh->dev_tracker,
+ GFP_KERNEL_ACCOUNT);
+ neigh->ttl = ip4_dst_hoplimit(&rt->dst);
+ n = dst_neigh_lookup(&rt->dst, &flow4.daddr);
+ ip_rt_put(rt);
+ }
+ if (!n) {
+ rc = -ENETUNREACH;
+ NL_SET_ERR_MSG_MOD(extack, "Failed to lookup neighbour for encap");
+ netdev_put(neigh->egdev, &neigh->dev_tracker);
+ goto out_free;
+ }
+ refcount_set(&neigh->ref, 1);
+ INIT_LIST_HEAD(&neigh->users);
+ read_lock_bh(&n->lock);
+ ether_addr_copy(neigh->ha, n->ha);
+ neigh->n_valid = n->nud_state & NUD_VALID;
+ read_unlock_bh(&n->lock);
+ rwlock_init(&neigh->lock);
+ INIT_WORK(&neigh->work, efx_neigh_update);
+ neigh->efx = efx;
+ neigh->used = jiffies;
+ if (!neigh->n_valid)
+ /* Prod ARP to find us a neighbour */
+ neigh_event_send(n, NULL);
+ neigh_release(n);
+ }
+ /* Add us to this neigh */
+ encap->neigh = neigh;
+ list_add_tail(&encap->list, &neigh->users);
+ return 0;
+
+out_free:
+ /* cleanup common to several error paths */
+ rhashtable_remove_fast(&efx->tc->neigh_ht, &neigh->linkage,
+ efx_neigh_ht_params);
+ synchronize_rcu();
+ put_net_track(net, &neigh->ns_tracker);
+ kfree(neigh);
+ return rc;
+}
+
+static void efx_free_neigh(struct efx_neigh_binder *neigh)
+{
+ struct efx_nic *efx = neigh->efx;
+
+ rhashtable_remove_fast(&efx->tc->neigh_ht, &neigh->linkage,
+ efx_neigh_ht_params);
+ synchronize_rcu();
+ netdev_put(neigh->egdev, &neigh->dev_tracker);
+ put_net_track(neigh->net, &neigh->ns_tracker);
+ kfree(neigh);
+}
+
+static void efx_release_neigh(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap)
+{
+ struct efx_neigh_binder *neigh = encap->neigh;
+
+ if (!neigh)
+ return;
+ list_del(&encap->list);
+ encap->neigh = NULL;
+ if (!refcount_dec_and_test(&neigh->ref))
+ return; /* still in use */
+ efx_free_neigh(neigh);
+}
+
+static void efx_gen_tun_header_eth(struct efx_tc_encap_action *encap, u16 proto)
+{
+ struct efx_neigh_binder *neigh = encap->neigh;
+ struct ethhdr *eth;
+
+ encap->encap_hdr_len = sizeof(*eth);
+ eth = (struct ethhdr *)encap->encap_hdr;
+
+ if (encap->neigh->n_valid)
+ ether_addr_copy(eth->h_dest, neigh->ha);
+ else
+ eth_zero_addr(eth->h_dest);
+ ether_addr_copy(eth->h_source, neigh->egdev->dev_addr);
+ eth->h_proto = htons(proto);
+}
+
+static void efx_gen_tun_header_ipv4(struct efx_tc_encap_action *encap, u8 ipproto, u8 len)
+{
+ struct efx_neigh_binder *neigh = encap->neigh;
+ struct ip_tunnel_key *key = &encap->key;
+ struct iphdr *ip;
+
+ ip = (struct iphdr *)(encap->encap_hdr + encap->encap_hdr_len);
+ encap->encap_hdr_len += sizeof(*ip);
+
+ ip->daddr = key->u.ipv4.dst;
+ ip->saddr = key->u.ipv4.src;
+ ip->ttl = neigh->ttl;
+ ip->protocol = ipproto;
+ ip->version = 0x4;
+ ip->ihl = 0x5;
+ ip->tot_len = cpu_to_be16(ip->ihl * 4 + len);
+ ip_send_check(ip);
+}
+
+#ifdef CONFIG_IPV6
+static void efx_gen_tun_header_ipv6(struct efx_tc_encap_action *encap, u8 ipproto, u8 len)
+{
+ struct efx_neigh_binder *neigh = encap->neigh;
+ struct ip_tunnel_key *key = &encap->key;
+ struct ipv6hdr *ip;
+
+ ip = (struct ipv6hdr *)(encap->encap_hdr + encap->encap_hdr_len);
+ encap->encap_hdr_len += sizeof(*ip);
+
+ ip6_flow_hdr(ip, key->tos, key->label);
+ ip->daddr = key->u.ipv6.dst;
+ ip->saddr = key->u.ipv6.src;
+ ip->hop_limit = neigh->ttl;
+ ip->nexthdr = ipproto;
+ ip->version = 0x6;
+ ip->payload_len = cpu_to_be16(len);
+}
+#endif
+
+static void efx_gen_tun_header_udp(struct efx_tc_encap_action *encap, u8 len)
+{
+ struct ip_tunnel_key *key = &encap->key;
+ struct udphdr *udp;
+
+ udp = (struct udphdr *)(encap->encap_hdr + encap->encap_hdr_len);
+ encap->encap_hdr_len += sizeof(*udp);
+
+ udp->dest = key->tp_dst;
+ udp->len = cpu_to_be16(sizeof(*udp) + len);
+}
+
+static void efx_gen_tun_header_vxlan(struct efx_tc_encap_action *encap)
+{
+ struct ip_tunnel_key *key = &encap->key;
+ struct vxlanhdr *vxlan;
+
+ vxlan = (struct vxlanhdr *)(encap->encap_hdr + encap->encap_hdr_len);
+ encap->encap_hdr_len += sizeof(*vxlan);
+
+ vxlan->vx_flags = VXLAN_HF_VNI;
+ vxlan->vx_vni = vxlan_vni_field(tunnel_id_to_key32(key->tun_id));
+}
+
+static void efx_gen_tun_header_geneve(struct efx_tc_encap_action *encap)
+{
+ struct ip_tunnel_key *key = &encap->key;
+ struct genevehdr *geneve;
+ u32 vni;
+
+ geneve = (struct genevehdr *)(encap->encap_hdr + encap->encap_hdr_len);
+ encap->encap_hdr_len += sizeof(*geneve);
+
+ geneve->proto_type = htons(ETH_P_TEB);
+ /* convert tun_id to host-endian so we can use host arithmetic to
+ * extract individual bytes.
+ */
+ vni = ntohl(tunnel_id_to_key32(key->tun_id));
+ geneve->vni[0] = vni >> 16;
+ geneve->vni[1] = vni >> 8;
+ geneve->vni[2] = vni;
+}
+
+#define vxlan_header_l4_len (sizeof(struct udphdr) + sizeof(struct vxlanhdr))
+#define vxlan4_header_len (sizeof(struct ethhdr) + sizeof(struct iphdr) + vxlan_header_l4_len)
+static void efx_gen_vxlan_header_ipv4(struct efx_tc_encap_action *encap)
+{
+ BUILD_BUG_ON(sizeof(encap->encap_hdr) < vxlan4_header_len);
+ efx_gen_tun_header_eth(encap, ETH_P_IP);
+ efx_gen_tun_header_ipv4(encap, IPPROTO_UDP, vxlan_header_l4_len);
+ efx_gen_tun_header_udp(encap, sizeof(struct vxlanhdr));
+ efx_gen_tun_header_vxlan(encap);
+}
+
+#define geneve_header_l4_len (sizeof(struct udphdr) + sizeof(struct genevehdr))
+#define geneve4_header_len (sizeof(struct ethhdr) + sizeof(struct iphdr) + geneve_header_l4_len)
+static void efx_gen_geneve_header_ipv4(struct efx_tc_encap_action *encap)
+{
+ BUILD_BUG_ON(sizeof(encap->encap_hdr) < geneve4_header_len);
+ efx_gen_tun_header_eth(encap, ETH_P_IP);
+ efx_gen_tun_header_ipv4(encap, IPPROTO_UDP, geneve_header_l4_len);
+ efx_gen_tun_header_udp(encap, sizeof(struct genevehdr));
+ efx_gen_tun_header_geneve(encap);
+}
+
+#ifdef CONFIG_IPV6
+#define vxlan6_header_len (sizeof(struct ethhdr) + sizeof(struct ipv6hdr) + vxlan_header_l4_len)
+static void efx_gen_vxlan_header_ipv6(struct efx_tc_encap_action *encap)
+{
+ BUILD_BUG_ON(sizeof(encap->encap_hdr) < vxlan6_header_len);
+ efx_gen_tun_header_eth(encap, ETH_P_IPV6);
+ efx_gen_tun_header_ipv6(encap, IPPROTO_UDP, vxlan_header_l4_len);
+ efx_gen_tun_header_udp(encap, sizeof(struct vxlanhdr));
+ efx_gen_tun_header_vxlan(encap);
+}
+
+#define geneve6_header_len (sizeof(struct ethhdr) + sizeof(struct ipv6hdr) + geneve_header_l4_len)
+static void efx_gen_geneve_header_ipv6(struct efx_tc_encap_action *encap)
+{
+ BUILD_BUG_ON(sizeof(encap->encap_hdr) < geneve6_header_len);
+ efx_gen_tun_header_eth(encap, ETH_P_IPV6);
+ efx_gen_tun_header_ipv6(encap, IPPROTO_UDP, geneve_header_l4_len);
+ efx_gen_tun_header_udp(encap, sizeof(struct genevehdr));
+ efx_gen_tun_header_geneve(encap);
+}
+#endif
+
+static void efx_gen_encap_header(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap)
+{
+ encap->n_valid = encap->neigh->n_valid;
+
+ /* GCC stupidly thinks that only values explicitly listed in the enum
+ * definition can _possibly_ be sensible case values, so without this
+ * cast it complains about the IPv6 versions.
+ */
+ switch ((int)encap->type) {
+ case EFX_ENCAP_TYPE_VXLAN:
+ efx_gen_vxlan_header_ipv4(encap);
+ break;
+ case EFX_ENCAP_TYPE_GENEVE:
+ efx_gen_geneve_header_ipv4(encap);
+ break;
+#ifdef CONFIG_IPV6
+ case EFX_ENCAP_TYPE_VXLAN | EFX_ENCAP_FLAG_IPV6:
+ efx_gen_vxlan_header_ipv6(encap);
+ break;
+ case EFX_ENCAP_TYPE_GENEVE | EFX_ENCAP_FLAG_IPV6:
+ efx_gen_geneve_header_ipv6(encap);
+ break;
+#endif
+ default:
+ /* unhandled encap type, can't happen */
+ if (net_ratelimit())
+ netif_err(efx, drv, efx->net_dev,
+ "Bogus encap type %d, can't generate\n",
+ encap->type);
+
+ /* Use fallback action. */
+ encap->n_valid = false;
+ break;
+ }
+}
+
+static void efx_tc_update_encap(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap)
+{
+ struct efx_tc_action_set_list *acts, *fallback;
+ struct efx_tc_flow_rule *rule;
+ struct efx_tc_action_set *act;
+ int rc;
+
+ if (encap->n_valid) {
+ /* Make sure no rules are using this encap while we change it */
+ list_for_each_entry(act, &encap->users, encap_user) {
+ acts = act->user;
+ if (WARN_ON(!acts)) /* can't happen */
+ continue;
+ rule = container_of(acts, struct efx_tc_flow_rule, acts);
+ if (rule->fallback)
+ fallback = rule->fallback;
+ else /* fallback fallback: deliver to PF */
+ fallback = &efx->tc->facts.pf;
+ rc = efx_mae_update_rule(efx, fallback->fw_id,
+ rule->fw_id);
+ if (rc)
+ netif_err(efx, drv, efx->net_dev,
+ "Failed to update (f) rule %08x rc %d\n",
+ rule->fw_id, rc);
+ else
+ netif_dbg(efx, drv, efx->net_dev, "Updated (f) rule %08x\n",
+ rule->fw_id);
+ }
+ }
+
+ /* Make sure we don't leak arbitrary bytes on the wire;
+ * set an all-0s ethernet header. A successful call to
+ * efx_gen_encap_header() will overwrite this.
+ */
+ memset(encap->encap_hdr, 0, sizeof(encap->encap_hdr));
+ encap->encap_hdr_len = ETH_HLEN;
+
+ if (encap->neigh) {
+ read_lock_bh(&encap->neigh->lock);
+ efx_gen_encap_header(efx, encap);
+ read_unlock_bh(&encap->neigh->lock);
+ } else {
+ encap->n_valid = false;
+ }
+
+ rc = efx_mae_update_encap_md(efx, encap);
+ if (rc) {
+ netif_err(efx, drv, efx->net_dev,
+ "Failed to update encap hdr %08x rc %d\n",
+ encap->fw_id, rc);
+ return;
+ }
+ netif_dbg(efx, drv, efx->net_dev, "Updated encap hdr %08x\n",
+ encap->fw_id);
+ if (!encap->n_valid)
+ return;
+ /* Update rule users: use the action if they are now ready */
+ list_for_each_entry(act, &encap->users, encap_user) {
+ acts = act->user;
+ if (WARN_ON(!acts)) /* can't happen */
+ continue;
+ rule = container_of(acts, struct efx_tc_flow_rule, acts);
+ if (!efx_tc_check_ready(efx, rule))
+ continue;
+ rc = efx_mae_update_rule(efx, acts->fw_id, rule->fw_id);
+ if (rc)
+ netif_err(efx, drv, efx->net_dev,
+ "Failed to update rule %08x rc %d\n",
+ rule->fw_id, rc);
+ else
+ netif_dbg(efx, drv, efx->net_dev, "Updated rule %08x\n",
+ rule->fw_id);
+ }
+}
+
+static void efx_neigh_update(struct work_struct *work)
+{
+ struct efx_neigh_binder *neigh = container_of(work, struct efx_neigh_binder, work);
+ struct efx_tc_encap_action *encap;
+ struct efx_nic *efx = neigh->efx;
+
+ mutex_lock(&efx->tc->mutex);
+ list_for_each_entry(encap, &neigh->users, list)
+ efx_tc_update_encap(neigh->efx, encap);
+ /* release ref taken in efx_neigh_event() */
+ if (refcount_dec_and_test(&neigh->ref))
+ efx_free_neigh(neigh);
+ mutex_unlock(&efx->tc->mutex);
+}
+
+static int efx_neigh_event(struct efx_nic *efx, struct neighbour *n)
+{
+ struct efx_neigh_binder keys = {NULL}, *neigh;
+ bool n_valid, ipv6 = false;
+ char ha[ETH_ALEN];
+ size_t keysize;
+
+ if (WARN_ON(!efx->tc))
+ return NOTIFY_DONE;
+
+ if (n->tbl == &arp_tbl) {
+ keysize = sizeof(keys.dst_ip);
+#if IS_ENABLED(CONFIG_IPV6)
+ } else if (n->tbl == ipv6_stub->nd_tbl) {
+ ipv6 = true;
+ keysize = sizeof(keys.dst_ip6);
+#endif
+ } else {
+ return NOTIFY_DONE;
+ }
+ if (!n->parms) {
+ netif_warn(efx, drv, efx->net_dev, "neigh_event with no parms!\n");
+ return NOTIFY_DONE;
+ }
+ keys.net = read_pnet(&n->parms->net);
+ if (n->tbl->key_len != keysize) {
+ netif_warn(efx, drv, efx->net_dev, "neigh_event with bad key_len %u\n",
+ n->tbl->key_len);
+ return NOTIFY_DONE;
+ }
+ read_lock_bh(&n->lock); /* Get a consistent view */
+ memcpy(ha, n->ha, ETH_ALEN);
+ n_valid = (n->nud_state & NUD_VALID) && !n->dead;
+ read_unlock_bh(&n->lock);
+ if (ipv6)
+ memcpy(&keys.dst_ip6, n->primary_key, n->tbl->key_len);
+ else
+ memcpy(&keys.dst_ip, n->primary_key, n->tbl->key_len);
+ rcu_read_lock();
+ neigh = rhashtable_lookup_fast(&efx->tc->neigh_ht, &keys,
+ efx_neigh_ht_params);
+ if (!neigh || neigh->dying)
+ /* We're not interested in this neighbour */
+ goto done;
+ write_lock_bh(&neigh->lock);
+ if (n_valid == neigh->n_valid && !memcmp(ha, neigh->ha, ETH_ALEN)) {
+ write_unlock_bh(&neigh->lock);
+ /* Nothing has changed; no work to do */
+ goto done;
+ }
+ neigh->n_valid = n_valid;
+ memcpy(neigh->ha, ha, ETH_ALEN);
+ write_unlock_bh(&neigh->lock);
+ if (refcount_inc_not_zero(&neigh->ref)) {
+ rcu_read_unlock();
+ if (!schedule_work(&neigh->work))
+ /* failed to schedule, release the ref we just took */
+ if (refcount_dec_and_test(&neigh->ref))
+ efx_free_neigh(neigh);
+ } else {
+done:
+ rcu_read_unlock();
+ }
+ return NOTIFY_DONE;
+}
+
+bool efx_tc_check_ready(struct efx_nic *efx, struct efx_tc_flow_rule *rule)
+{
+ struct efx_tc_action_set *act;
+
+ /* Encap actions can only be offloaded if they have valid
+ * neighbour info for the outer Ethernet header.
+ */
+ list_for_each_entry(act, &rule->acts.list, list)
+ if (act->encap_md && !act->encap_md->n_valid)
+ return false;
+ return true;
+}
+
+struct efx_tc_encap_action *efx_tc_flower_create_encap_md(
+ struct efx_nic *efx, const struct ip_tunnel_info *info,
+ struct net_device *egdev, struct netlink_ext_ack *extack)
+{
+ enum efx_encap_type type = efx_tc_indr_netdev_type(egdev);
+ struct efx_tc_encap_action *encap, *old;
+ struct efx_rep *to_efv;
+ s64 rc;
+
+ if (type == EFX_ENCAP_TYPE_NONE) {
+ /* dest is not an encap device */
+ NL_SET_ERR_MSG_MOD(extack, "Not a (supported) tunnel device but tunnel_key is set");
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+ rc = efx_mae_check_encap_type_supported(efx, type);
+ if (rc < 0) {
+ NL_SET_ERR_MSG_MOD(extack, "Firmware reports no support for this tunnel type");
+ return ERR_PTR(rc);
+ }
+ /* No support yet for Geneve options */
+ if (info->options_len) {
+ NL_SET_ERR_MSG_MOD(extack, "Unsupported tunnel options");
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+ switch (info->mode) {
+ case IP_TUNNEL_INFO_TX:
+ break;
+ case IP_TUNNEL_INFO_TX | IP_TUNNEL_INFO_IPV6:
+ type |= EFX_ENCAP_FLAG_IPV6;
+ break;
+ default:
+ NL_SET_ERR_MSG_FMT_MOD(extack, "Unsupported tunnel mode %u",
+ info->mode);
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+ encap = kzalloc(sizeof(*encap), GFP_KERNEL_ACCOUNT);
+ if (!encap)
+ return ERR_PTR(-ENOMEM);
+ encap->type = type;
+ encap->key = info->key;
+ INIT_LIST_HEAD(&encap->users);
+ old = rhashtable_lookup_get_insert_fast(&efx->tc->encap_ht,
+ &encap->linkage,
+ efx_tc_encap_ht_params);
+ if (old) {
+ /* don't need our new entry */
+ kfree(encap);
+ if (!refcount_inc_not_zero(&old->ref))
+ return ERR_PTR(-EAGAIN);
+ /* existing entry found, ref taken */
+ return old;
+ }
+
+ rc = efx_bind_neigh(efx, encap, dev_net(egdev), extack);
+ if (rc < 0)
+ goto out_remove;
+ to_efv = efx_tc_flower_lookup_efv(efx, encap->neigh->egdev);
+ if (IS_ERR(to_efv)) {
+ /* neigh->egdev isn't ours */
+ NL_SET_ERR_MSG_MOD(extack, "Tunnel egress device not on switch");
+ rc = PTR_ERR(to_efv);
+ goto out_release;
+ }
+ rc = efx_tc_flower_external_mport(efx, to_efv);
+ if (rc < 0) {
+ NL_SET_ERR_MSG_MOD(extack, "Failed to identify tunnel egress m-port");
+ goto out_release;
+ }
+ encap->dest_mport = rc;
+ read_lock_bh(&encap->neigh->lock);
+ efx_gen_encap_header(efx, encap);
+ read_unlock_bh(&encap->neigh->lock);
+
+ rc = efx_mae_allocate_encap_md(efx, encap);
+ if (rc < 0) {
+ NL_SET_ERR_MSG_MOD(extack, "Failed to write tunnel header to hw");
+ goto out_release;
+ }
+
+ /* ref and return */
+ refcount_set(&encap->ref, 1);
+ return encap;
+out_release:
+ efx_release_neigh(efx, encap);
+out_remove:
+ rhashtable_remove_fast(&efx->tc->encap_ht, &encap->linkage,
+ efx_tc_encap_ht_params);
+ kfree(encap);
+ return ERR_PTR(rc);
+}
+
+void efx_tc_flower_release_encap_md(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap)
+{
+ if (!refcount_dec_and_test(&encap->ref))
+ return; /* still in use */
+ efx_release_neigh(efx, encap);
+ rhashtable_remove_fast(&efx->tc->encap_ht, &encap->linkage,
+ efx_tc_encap_ht_params);
+ efx_mae_free_encap_md(efx, encap);
+ kfree(encap);
+}
+
+static void efx_tc_remove_neigh_users(struct efx_nic *efx, struct efx_neigh_binder *neigh)
+{
+ struct efx_tc_encap_action *encap, *next;
+
+ list_for_each_entry_safe(encap, next, &neigh->users, list) {
+ /* Should cause neigh usage count to fall to zero, freeing it */
+ efx_release_neigh(efx, encap);
+ /* The encap has lost its neigh, so it's now unready */
+ efx_tc_update_encap(efx, encap);
+ }
+}
+
+void efx_tc_unregister_egdev(struct efx_nic *efx, struct net_device *net_dev)
+{
+ struct efx_neigh_binder *neigh;
+ struct rhashtable_iter walk;
+
+ mutex_lock(&efx->tc->mutex);
+ rhashtable_walk_enter(&efx->tc->neigh_ht, &walk);
+ rhashtable_walk_start(&walk);
+ while ((neigh = rhashtable_walk_next(&walk)) != NULL) {
+ if (IS_ERR(neigh))
+ continue;
+ if (neigh->egdev != net_dev)
+ continue;
+ neigh->dying = true;
+ rhashtable_walk_stop(&walk);
+ synchronize_rcu(); /* Make sure any updates see dying flag */
+ efx_tc_remove_neigh_users(efx, neigh); /* might sleep */
+ rhashtable_walk_start(&walk);
+ }
+ rhashtable_walk_stop(&walk);
+ rhashtable_walk_exit(&walk);
+ mutex_unlock(&efx->tc->mutex);
+}
+
+int efx_tc_netevent_event(struct efx_nic *efx, unsigned long event,
+ void *ptr)
+{
+ if (efx->type->is_vf)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETEVENT_NEIGH_UPDATE:
+ return efx_neigh_event(efx, ptr);
+ default:
+ return NOTIFY_DONE;
+ }
+}
diff --git a/drivers/net/ethernet/sfc/tc_encap_actions.h b/drivers/net/ethernet/sfc/tc_encap_actions.h
new file mode 100644
index 000000000000..c3c7904ad7ff
--- /dev/null
+++ b/drivers/net/ethernet/sfc/tc_encap_actions.h
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2023, Advanced Micro Devices, Inc.
+ *
+ * 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, incorporated herein by reference.
+ */
+
+#ifndef EFX_TC_ENCAP_ACTIONS_H
+#define EFX_TC_ENCAP_ACTIONS_H
+#include "net_driver.h"
+
+#if IS_ENABLED(CONFIG_SFC_SRIOV)
+#include <linux/refcount.h>
+#include <net/tc_act/tc_tunnel_key.h>
+
+/**
+ * struct efx_neigh_binder - driver state for a neighbour entry
+ * @net: the network namespace in which this neigh resides
+ * @dst_ip: the IPv4 destination address resolved by this neigh
+ * @dst_ip6: the IPv6 destination address resolved by this neigh
+ * @ha: the hardware (Ethernet) address of the neighbour
+ * @n_valid: true if the neighbour is in NUD_VALID state
+ * @lock: protects @ha and @n_valid
+ * @ttl: Time To Live associated with the route used
+ * @dying: set when egdev is going away, to skip further updates
+ * @egdev: egress device from the route lookup. Holds a reference
+ * @dev_tracker: reference tracker entry for @egdev
+ * @ns_tracker: reference tracker entry for @ns
+ * @ref: counts encap actions referencing this entry
+ * @used: jiffies of last time traffic hit any encap action using this.
+ * When counter reads update this, a new neighbour event is sent to
+ * indicate that the neighbour entry is still in use.
+ * @users: list of &struct efx_tc_encap_action
+ * @linkage: entry in efx->neigh_ht (keys are @net, @dst_ip, @dst_ip6).
+ * @work: processes neighbour state changes, updates the encap actions
+ * @efx: owning NIC instance.
+ *
+ * Associates a neighbour entry with the encap actions that are
+ * interested in it, allowing the latter to be updated when the
+ * neighbour details change.
+ * Whichever of @dst_ip and @dst_ip6 is not in use will be all-zeroes,
+ * this distinguishes IPv4 from IPv6 entries.
+ */
+struct efx_neigh_binder {
+ struct net *net;
+ __be32 dst_ip;
+ struct in6_addr dst_ip6;
+ char ha[ETH_ALEN];
+ bool n_valid;
+ rwlock_t lock;
+ u8 ttl;
+ bool dying;
+ struct net_device *egdev;
+ netdevice_tracker dev_tracker;
+ netns_tracker ns_tracker;
+ refcount_t ref;
+ unsigned long used;
+ struct list_head users;
+ struct rhash_head linkage;
+ struct work_struct work;
+ struct efx_nic *efx;
+};
+
+/* This limit is arbitrary; current hardware (SN1022) handles encap headers
+ * of up to 126 bytes, but that limit is not enshrined in the MCDI protocol.
+ */
+#define EFX_TC_MAX_ENCAP_HDR 126
+struct efx_tc_encap_action {
+ enum efx_encap_type type;
+ struct ip_tunnel_key key; /* 52 bytes */
+ u32 dest_mport; /* is copied into struct efx_tc_action_set */
+ u8 encap_hdr_len;
+ bool n_valid;
+ u8 encap_hdr[EFX_TC_MAX_ENCAP_HDR];
+ struct efx_neigh_binder *neigh;
+ struct list_head list; /* entry on neigh->users list */
+ struct list_head users; /* action sets using this encap_md */
+ struct rhash_head linkage; /* efx->tc_encap_ht */
+ refcount_t ref;
+ u32 fw_id; /* index of this entry in firmware encap table */
+};
+
+/* create/uncreate/teardown hashtables */
+int efx_tc_init_encap_actions(struct efx_nic *efx);
+void efx_tc_destroy_encap_actions(struct efx_nic *efx);
+void efx_tc_fini_encap_actions(struct efx_nic *efx);
+
+struct efx_tc_flow_rule;
+bool efx_tc_check_ready(struct efx_nic *efx, struct efx_tc_flow_rule *rule);
+
+struct efx_tc_encap_action *efx_tc_flower_create_encap_md(
+ struct efx_nic *efx, const struct ip_tunnel_info *info,
+ struct net_device *egdev, struct netlink_ext_ack *extack);
+void efx_tc_flower_release_encap_md(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap);
+
+void efx_tc_unregister_egdev(struct efx_nic *efx, struct net_device *net_dev);
+int efx_tc_netevent_event(struct efx_nic *efx, unsigned long event,
+ void *ptr);
+
+#else /* CONFIG_SFC_SRIOV */
+
+static inline int efx_tc_netevent_event(struct efx_nic *efx,
+ unsigned long event, void *ptr)
+{
+ return NOTIFY_DONE;
+}
+
+#endif /* CONFIG_SFC_SRIOV */
+
+#endif /* EFX_TC_ENCAP_ACTIONS_H */
diff --git a/drivers/net/ethernet/sfc/tx_common.c b/drivers/net/ethernet/sfc/tx_common.c
index 755aa92bf823..9f2393d34371 100644
--- a/drivers/net/ethernet/sfc/tx_common.c
+++ b/drivers/net/ethernet/sfc/tx_common.c
@@ -12,6 +12,7 @@
#include "efx.h"
#include "nic_common.h"
#include "tx_common.h"
+#include <net/gso.h>
static unsigned int efx_tx_cb_page_count(struct efx_tx_queue *tx_queue)
{
diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index 2d7347b71c41..0dcd6a568b06 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -1851,6 +1851,17 @@ static int netsec_of_probe(struct platform_device *pdev,
return err;
}
+ /*
+ * SynQuacer is physically configured with TX and RX delays
+ * but the standard firmware claimed otherwise for a long
+ * time, ignore it.
+ */
+ if (of_machine_is_compatible("socionext,developer-box") &&
+ priv->phy_interface != PHY_INTERFACE_MODE_RGMII_ID) {
+ dev_warn(&pdev->dev, "Outdated firmware reports incorrect PHY mode, overriding\n");
+ priv->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
+ }
+
priv->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
if (!priv->phy_np) {
dev_err(&pdev->dev, "missing required property 'phy-handle'\n");
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 5f5a997f21f3..5583f0b055ec 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -158,6 +158,9 @@ config DWMAC_SOCFPGA
default ARCH_INTEL_SOCFPGA
depends on OF && (ARCH_INTEL_SOCFPGA || COMPILE_TEST)
select MFD_SYSCON
+ select MDIO_REGMAP
+ select REGMAP_MMIO
+ select PCS_LYNX
help
Support for ethernet controller on Altera SOCFPGA
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 8738fdbb4b2d..7dd3d388068b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -35,7 +35,7 @@ obj-$(CONFIG_DWMAC_IMX8) += dwmac-imx.o
obj-$(CONFIG_DWMAC_TEGRA) += dwmac-tegra.o
obj-$(CONFIG_DWMAC_VISCONTI) += dwmac-visconti.o
stmmac-platform-objs:= stmmac_platform.o
-dwmac-altr-socfpga-objs := altr_tse_pcs.o dwmac-socfpga.o
+dwmac-altr-socfpga-objs := dwmac-socfpga.o
obj-$(CONFIG_STMMAC_PCI) += stmmac-pci.o
obj-$(CONFIG_DWMAC_INTEL) += dwmac-intel.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c
deleted file mode 100644
index 00f6d347eaf7..000000000000
--- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c
+++ /dev/null
@@ -1,257 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright Altera Corporation (C) 2016. All rights reserved.
- *
- * Author: Tien Hock Loh <thloh@altera.com>
- */
-
-#include <linux/mfd/syscon.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_net.h>
-#include <linux/phy.h>
-#include <linux/regmap.h>
-#include <linux/reset.h>
-#include <linux/stmmac.h>
-
-#include "stmmac.h"
-#include "stmmac_platform.h"
-#include "altr_tse_pcs.h"
-
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII BIT(1)
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII BIT(2)
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK GENMASK(1, 0)
-
-#define TSE_PCS_CONTROL_AN_EN_MASK BIT(12)
-#define TSE_PCS_CONTROL_REG 0x00
-#define TSE_PCS_CONTROL_RESTART_AN_MASK BIT(9)
-#define TSE_PCS_CTRL_AUTONEG_SGMII 0x1140
-#define TSE_PCS_IF_MODE_REG 0x28
-#define TSE_PCS_LINK_TIMER_0_REG 0x24
-#define TSE_PCS_LINK_TIMER_1_REG 0x26
-#define TSE_PCS_SIZE 0x40
-#define TSE_PCS_STATUS_AN_COMPLETED_MASK BIT(5)
-#define TSE_PCS_STATUS_LINK_MASK 0x0004
-#define TSE_PCS_STATUS_REG 0x02
-#define TSE_PCS_SGMII_SPEED_1000 BIT(3)
-#define TSE_PCS_SGMII_SPEED_100 BIT(2)
-#define TSE_PCS_SGMII_SPEED_10 0x0
-#define TSE_PCS_SW_RST_MASK 0x8000
-#define TSE_PCS_PARTNER_ABILITY_REG 0x0A
-#define TSE_PCS_PARTNER_DUPLEX_FULL 0x1000
-#define TSE_PCS_PARTNER_DUPLEX_HALF 0x0000
-#define TSE_PCS_PARTNER_DUPLEX_MASK 0x1000
-#define TSE_PCS_PARTNER_SPEED_MASK GENMASK(11, 10)
-#define TSE_PCS_PARTNER_SPEED_1000 BIT(11)
-#define TSE_PCS_PARTNER_SPEED_100 BIT(10)
-#define TSE_PCS_PARTNER_SPEED_10 0x0000
-#define TSE_PCS_PARTNER_SPEED_1000 BIT(11)
-#define TSE_PCS_PARTNER_SPEED_100 BIT(10)
-#define TSE_PCS_PARTNER_SPEED_10 0x0000
-#define TSE_PCS_SGMII_SPEED_MASK GENMASK(3, 2)
-#define TSE_PCS_SGMII_LINK_TIMER_0 0x0D40
-#define TSE_PCS_SGMII_LINK_TIMER_1 0x0003
-#define TSE_PCS_SW_RESET_TIMEOUT 100
-#define TSE_PCS_USE_SGMII_AN_MASK BIT(1)
-#define TSE_PCS_USE_SGMII_ENA BIT(0)
-#define TSE_PCS_IF_USE_SGMII 0x03
-
-#define AUTONEGO_LINK_TIMER 20
-
-static int tse_pcs_reset(void __iomem *base, struct tse_pcs *pcs)
-{
- int counter = 0;
- u16 val;
-
- val = readw(base + TSE_PCS_CONTROL_REG);
- val |= TSE_PCS_SW_RST_MASK;
- writew(val, base + TSE_PCS_CONTROL_REG);
-
- while (counter < TSE_PCS_SW_RESET_TIMEOUT) {
- val = readw(base + TSE_PCS_CONTROL_REG);
- val &= TSE_PCS_SW_RST_MASK;
- if (val == 0)
- break;
- counter++;
- udelay(1);
- }
- if (counter >= TSE_PCS_SW_RESET_TIMEOUT) {
- dev_err(pcs->dev, "PCS could not get out of sw reset\n");
- return -ETIMEDOUT;
- }
-
- return 0;
-}
-
-int tse_pcs_init(void __iomem *base, struct tse_pcs *pcs)
-{
- int ret = 0;
-
- writew(TSE_PCS_IF_USE_SGMII, base + TSE_PCS_IF_MODE_REG);
-
- writew(TSE_PCS_CTRL_AUTONEG_SGMII, base + TSE_PCS_CONTROL_REG);
-
- writew(TSE_PCS_SGMII_LINK_TIMER_0, base + TSE_PCS_LINK_TIMER_0_REG);
- writew(TSE_PCS_SGMII_LINK_TIMER_1, base + TSE_PCS_LINK_TIMER_1_REG);
-
- ret = tse_pcs_reset(base, pcs);
- if (ret == 0)
- writew(SGMII_ADAPTER_ENABLE,
- pcs->sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
-
- return ret;
-}
-
-static void pcs_link_timer_callback(struct tse_pcs *pcs)
-{
- u16 val = 0;
- void __iomem *tse_pcs_base = pcs->tse_pcs_base;
- void __iomem *sgmii_adapter_base = pcs->sgmii_adapter_base;
-
- val = readw(tse_pcs_base + TSE_PCS_STATUS_REG);
- val &= TSE_PCS_STATUS_LINK_MASK;
-
- if (val != 0) {
- dev_dbg(pcs->dev, "Adapter: Link is established\n");
- writew(SGMII_ADAPTER_ENABLE,
- sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
- } else {
- mod_timer(&pcs->aneg_link_timer, jiffies +
- msecs_to_jiffies(AUTONEGO_LINK_TIMER));
- }
-}
-
-static void auto_nego_timer_callback(struct tse_pcs *pcs)
-{
- u16 val = 0;
- u16 speed = 0;
- u16 duplex = 0;
- void __iomem *tse_pcs_base = pcs->tse_pcs_base;
- void __iomem *sgmii_adapter_base = pcs->sgmii_adapter_base;
-
- val = readw(tse_pcs_base + TSE_PCS_STATUS_REG);
- val &= TSE_PCS_STATUS_AN_COMPLETED_MASK;
-
- if (val != 0) {
- dev_dbg(pcs->dev, "Adapter: Auto Negotiation is completed\n");
- val = readw(tse_pcs_base + TSE_PCS_PARTNER_ABILITY_REG);
- speed = val & TSE_PCS_PARTNER_SPEED_MASK;
- duplex = val & TSE_PCS_PARTNER_DUPLEX_MASK;
-
- if (speed == TSE_PCS_PARTNER_SPEED_10 &&
- duplex == TSE_PCS_PARTNER_DUPLEX_FULL)
- dev_dbg(pcs->dev,
- "Adapter: Link Partner is Up - 10/Full\n");
- else if (speed == TSE_PCS_PARTNER_SPEED_100 &&
- duplex == TSE_PCS_PARTNER_DUPLEX_FULL)
- dev_dbg(pcs->dev,
- "Adapter: Link Partner is Up - 100/Full\n");
- else if (speed == TSE_PCS_PARTNER_SPEED_1000 &&
- duplex == TSE_PCS_PARTNER_DUPLEX_FULL)
- dev_dbg(pcs->dev,
- "Adapter: Link Partner is Up - 1000/Full\n");
- else if (speed == TSE_PCS_PARTNER_SPEED_10 &&
- duplex == TSE_PCS_PARTNER_DUPLEX_HALF)
- dev_err(pcs->dev,
- "Adapter does not support Half Duplex\n");
- else if (speed == TSE_PCS_PARTNER_SPEED_100 &&
- duplex == TSE_PCS_PARTNER_DUPLEX_HALF)
- dev_err(pcs->dev,
- "Adapter does not support Half Duplex\n");
- else if (speed == TSE_PCS_PARTNER_SPEED_1000 &&
- duplex == TSE_PCS_PARTNER_DUPLEX_HALF)
- dev_err(pcs->dev,
- "Adapter does not support Half Duplex\n");
- else
- dev_err(pcs->dev,
- "Adapter: Invalid Partner Speed and Duplex\n");
-
- if (duplex == TSE_PCS_PARTNER_DUPLEX_FULL &&
- (speed == TSE_PCS_PARTNER_SPEED_10 ||
- speed == TSE_PCS_PARTNER_SPEED_100 ||
- speed == TSE_PCS_PARTNER_SPEED_1000))
- writew(SGMII_ADAPTER_ENABLE,
- sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
- } else {
- val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG);
- val |= TSE_PCS_CONTROL_RESTART_AN_MASK;
- writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG);
-
- tse_pcs_reset(tse_pcs_base, pcs);
- mod_timer(&pcs->aneg_link_timer, jiffies +
- msecs_to_jiffies(AUTONEGO_LINK_TIMER));
- }
-}
-
-static void aneg_link_timer_callback(struct timer_list *t)
-{
- struct tse_pcs *pcs = from_timer(pcs, t, aneg_link_timer);
-
- if (pcs->autoneg == AUTONEG_ENABLE)
- auto_nego_timer_callback(pcs);
- else if (pcs->autoneg == AUTONEG_DISABLE)
- pcs_link_timer_callback(pcs);
-}
-
-void tse_pcs_fix_mac_speed(struct tse_pcs *pcs, struct phy_device *phy_dev,
- unsigned int speed)
-{
- void __iomem *tse_pcs_base = pcs->tse_pcs_base;
- u32 val;
-
- pcs->autoneg = phy_dev->autoneg;
-
- if (phy_dev->autoneg == AUTONEG_ENABLE) {
- val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG);
- val |= TSE_PCS_CONTROL_AN_EN_MASK;
- writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG);
-
- val = readw(tse_pcs_base + TSE_PCS_IF_MODE_REG);
- val |= TSE_PCS_USE_SGMII_AN_MASK;
- writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG);
-
- val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG);
- val |= TSE_PCS_CONTROL_RESTART_AN_MASK;
-
- tse_pcs_reset(tse_pcs_base, pcs);
-
- timer_setup(&pcs->aneg_link_timer, aneg_link_timer_callback,
- 0);
- mod_timer(&pcs->aneg_link_timer, jiffies +
- msecs_to_jiffies(AUTONEGO_LINK_TIMER));
- } else if (phy_dev->autoneg == AUTONEG_DISABLE) {
- val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG);
- val &= ~TSE_PCS_CONTROL_AN_EN_MASK;
- writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG);
-
- val = readw(tse_pcs_base + TSE_PCS_IF_MODE_REG);
- val &= ~TSE_PCS_USE_SGMII_AN_MASK;
- writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG);
-
- val = readw(tse_pcs_base + TSE_PCS_IF_MODE_REG);
- val &= ~TSE_PCS_SGMII_SPEED_MASK;
-
- switch (speed) {
- case 1000:
- val |= TSE_PCS_SGMII_SPEED_1000;
- break;
- case 100:
- val |= TSE_PCS_SGMII_SPEED_100;
- break;
- case 10:
- val |= TSE_PCS_SGMII_SPEED_10;
- break;
- default:
- return;
- }
- writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG);
-
- tse_pcs_reset(tse_pcs_base, pcs);
-
- timer_setup(&pcs->aneg_link_timer, aneg_link_timer_callback,
- 0);
- mod_timer(&pcs->aneg_link_timer, jiffies +
- msecs_to_jiffies(AUTONEGO_LINK_TIMER));
- }
-}
diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h
deleted file mode 100644
index 694ac25ef426..000000000000
--- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright Altera Corporation (C) 2016. All rights reserved.
- *
- * Author: Tien Hock Loh <thloh@altera.com>
- */
-
-#ifndef __TSE_PCS_H__
-#define __TSE_PCS_H__
-
-#include <linux/phy.h>
-#include <linux/timer.h>
-
-#define SGMII_ADAPTER_CTRL_REG 0x00
-#define SGMII_ADAPTER_ENABLE 0x0000
-#define SGMII_ADAPTER_DISABLE 0x0001
-
-struct tse_pcs {
- struct device *dev;
- void __iomem *tse_pcs_base;
- void __iomem *sgmii_adapter_base;
- struct timer_list aneg_link_timer;
- int autoneg;
-};
-
-int tse_pcs_init(void __iomem *base, struct tse_pcs *pcs);
-void tse_pcs_fix_mac_speed(struct tse_pcs *pcs, struct phy_device *phy_dev,
- unsigned int speed);
-
-#endif /* __TSE_PCS_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 4ad692c4116c..16e67c18b6f7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -519,6 +519,7 @@ struct mac_device_info {
const struct stmmac_tc_ops *tc;
const struct stmmac_mmc_ops *mmc;
struct dw_xpcs *xpcs;
+ struct phylink_pcs *lynx_pcs; /* Lynx external PCS */
struct mii_regs mii; /* MII register Addresses */
struct mac_link link;
void __iomem *pcsr; /* vpointer to device CSRs */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c
index 9354bf419112..58a7f08e8d78 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c
@@ -141,7 +141,7 @@ MODULE_DEVICE_TABLE(of, anarion_dwmac_match);
static struct platform_driver anarion_dwmac_driver = {
.probe = anarion_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "anarion-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
index 18acf7dd74e5..9f88530c5e8c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
@@ -464,7 +464,7 @@ remove_config:
return ret;
}
-static int dwc_eth_dwmac_remove(struct platform_device *pdev)
+static void dwc_eth_dwmac_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(ndev);
@@ -477,8 +477,6 @@ static int dwc_eth_dwmac_remove(struct platform_device *pdev)
data->remove(pdev);
stmmac_remove_config_dt(pdev, priv->plat);
-
- return 0;
}
static const struct of_device_id dwc_eth_dwmac_match[] = {
@@ -490,7 +488,7 @@ MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match);
static struct platform_driver dwc_eth_dwmac_driver = {
.probe = dwc_eth_dwmac_probe,
- .remove = dwc_eth_dwmac_remove,
+ .remove_new = dwc_eth_dwmac_remove,
.driver = {
.name = "dwc-eth-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
index ef8f3a940938..20fc455b3337 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
@@ -46,22 +46,12 @@ static int dwmac_generic_probe(struct platform_device *pdev)
plat_dat->unicast_filter_entries = 1;
}
- /* Custom initialisation (if needed) */
- if (plat_dat->init) {
- ret = plat_dat->init(pdev, plat_dat->bsp_priv);
- if (ret)
- goto err_remove_config_dt;
- }
-
- ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+ ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
if (ret)
- goto err_exit;
+ goto err_remove_config_dt;
return 0;
-err_exit:
- if (plat_dat->exit)
- plat_dat->exit(pdev, plat_dat->bsp_priv);
err_remove_config_dt:
if (pdev->dev.of_node)
stmmac_remove_config_dt(pdev, plat_dat);
@@ -87,7 +77,7 @@ MODULE_DEVICE_TABLE(of, dwmac_generic_match);
static struct platform_driver dwmac_generic_driver = {
.probe = dwmac_generic_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = STMMAC_RESOURCE_NAME,
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c
index 7c228bd0d099..b9378a63f0e8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c
@@ -376,7 +376,7 @@ MODULE_DEVICE_TABLE(of, imx_dwmac_match);
static struct platform_driver imx_dwmac_driver = {
.probe = imx_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "imx-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c
index 378b4dd826bb..8063ba1c3ce8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c
@@ -386,7 +386,7 @@ MODULE_DEVICE_TABLE(of, ingenic_mac_of_matches);
static struct platform_driver ingenic_mac_driver = {
.probe = ingenic_mac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "ingenic-mac",
.pm = pm_ptr(&ingenic_mac_pm_ops),
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c
index 06d287f104be..a5e639ab0b9e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c
@@ -169,20 +169,17 @@ err_remove_config_dt:
return ret;
}
-static int intel_eth_plat_remove(struct platform_device *pdev)
+static void intel_eth_plat_remove(struct platform_device *pdev)
{
struct intel_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev);
- int ret;
- ret = stmmac_pltfr_remove(pdev);
+ stmmac_pltfr_remove(pdev);
clk_disable_unprepare(dwmac->tx_clk);
-
- return ret;
}
static struct platform_driver intel_eth_plat_driver = {
.probe = intel_eth_plat_probe,
- .remove = intel_eth_plat_remove,
+ .remove_new = intel_eth_plat_remove,
.driver = {
.name = "intel-eth-plat",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
index e888c8a9c830..e39406df8516 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
@@ -498,7 +498,7 @@ MODULE_DEVICE_TABLE(of, ipq806x_gmac_dwmac_match);
static struct platform_driver ipq806x_gmac_dwmac_driver = {
.probe = ipq806x_gmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "ipq806x-gmac-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c
index 9d77c647badd..18e84ba693a6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c
@@ -83,7 +83,7 @@ MODULE_DEVICE_TABLE(of, lpc18xx_dwmac_match);
static struct platform_driver lpc18xx_dwmac_driver = {
.probe = lpc18xx_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "lpc18xx-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
index 9ae31e3dc821..73c1dfa7ecb1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
@@ -678,15 +678,12 @@ err_remove_config_dt:
return ret;
}
-static int mediatek_dwmac_remove(struct platform_device *pdev)
+static void mediatek_dwmac_remove(struct platform_device *pdev)
{
struct mediatek_dwmac_plat_data *priv_plat = get_stmmac_bsp_priv(&pdev->dev);
- int ret;
- ret = stmmac_pltfr_remove(pdev);
+ stmmac_pltfr_remove(pdev);
mediatek_dwmac_clks_config(priv_plat, false);
-
- return ret;
}
static const struct of_device_id mediatek_dwmac_match[] = {
@@ -701,7 +698,7 @@ MODULE_DEVICE_TABLE(of, mediatek_dwmac_match);
static struct platform_driver mediatek_dwmac_driver = {
.probe = mediatek_dwmac_probe,
- .remove = mediatek_dwmac_remove,
+ .remove_new = mediatek_dwmac_remove,
.driver = {
.name = "dwmac-mediatek",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
index 16fb66a0ca72..7aa5e6bc04eb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
@@ -91,7 +91,7 @@ MODULE_DEVICE_TABLE(of, meson6_dwmac_match);
static struct platform_driver meson6_dwmac_driver = {
.probe = meson6_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "meson6-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
index f6754e3643f3..92b16048f91c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
@@ -539,7 +539,7 @@ MODULE_DEVICE_TABLE(of, meson8b_dwmac_match);
static struct platform_driver meson8b_dwmac_driver = {
.probe = meson8b_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "meson8b-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c
index 62a69a91ab22..42954020de2c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c
@@ -231,7 +231,7 @@ MODULE_DEVICE_TABLE(of, oxnas_dwmac_match);
static struct platform_driver oxnas_dwmac_driver = {
.probe = oxnas_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "oxnas-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index f07905f00f98..e62940414e54 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -6,6 +6,9 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/phy.h>
+#include <linux/phy/phy.h>
+#include <linux/property.h>
+
#include "stmmac.h"
#include "stmmac_platform.h"
@@ -72,6 +75,10 @@
#define RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL BIT(6)
#define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN BIT(5)
+/* MAC_CTRL_REG bits */
+#define ETHQOS_MAC_CTRL_SPEED_MODE BIT(14)
+#define ETHQOS_MAC_CTRL_PORT_SEL BIT(15)
+
struct ethqos_emac_por {
unsigned int offset;
unsigned int value;
@@ -81,22 +88,28 @@ struct ethqos_emac_driver_data {
const struct ethqos_emac_por *por;
unsigned int num_por;
bool rgmii_config_loopback_en;
- bool has_emac3;
+ bool has_emac_ge_3;
+ const char *link_clk_name;
+ bool has_integrated_pcs;
struct dwmac4_addrs dwmac4_addrs;
};
struct qcom_ethqos {
struct platform_device *pdev;
void __iomem *rgmii_base;
+ void __iomem *mac_base;
+ int (*configure_func)(struct qcom_ethqos *ethqos);
- unsigned int rgmii_clk_rate;
- struct clk *rgmii_clk;
+ unsigned int link_clk_rate;
+ struct clk *link_clk;
+ struct phy *serdes_phy;
unsigned int speed;
+ int phy_mode;
const struct ethqos_emac_por *por;
unsigned int num_por;
bool rgmii_config_loopback_en;
- bool has_emac3;
+ bool has_emac_ge_3;
};
static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset)
@@ -115,7 +128,7 @@ static void rgmii_updatel(struct qcom_ethqos *ethqos,
{
unsigned int temp;
- temp = rgmii_readl(ethqos, offset);
+ temp = rgmii_readl(ethqos, offset);
temp = (temp & ~(mask)) | val;
rgmii_writel(ethqos, temp, offset);
}
@@ -123,25 +136,26 @@ static void rgmii_updatel(struct qcom_ethqos *ethqos,
static void rgmii_dump(void *priv)
{
struct qcom_ethqos *ethqos = priv;
+ struct device *dev = &ethqos->pdev->dev;
- dev_dbg(&ethqos->pdev->dev, "Rgmii register dump\n");
- dev_dbg(&ethqos->pdev->dev, "RGMII_IO_MACRO_CONFIG: %x\n",
+ dev_dbg(dev, "Rgmii register dump\n");
+ dev_dbg(dev, "RGMII_IO_MACRO_CONFIG: %x\n",
rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG));
- dev_dbg(&ethqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG: %x\n",
+ dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG: %x\n",
rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG));
- dev_dbg(&ethqos->pdev->dev, "SDCC_HC_REG_DDR_CONFIG: %x\n",
+ dev_dbg(dev, "SDCC_HC_REG_DDR_CONFIG: %x\n",
rgmii_readl(ethqos, SDCC_HC_REG_DDR_CONFIG));
- dev_dbg(&ethqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n",
+ dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n",
rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG2));
- dev_dbg(&ethqos->pdev->dev, "SDC4_STATUS: %x\n",
+ dev_dbg(dev, "SDC4_STATUS: %x\n",
rgmii_readl(ethqos, SDC4_STATUS));
- dev_dbg(&ethqos->pdev->dev, "SDCC_USR_CTL: %x\n",
+ dev_dbg(dev, "SDCC_USR_CTL: %x\n",
rgmii_readl(ethqos, SDCC_USR_CTL));
- dev_dbg(&ethqos->pdev->dev, "RGMII_IO_MACRO_CONFIG2: %x\n",
+ dev_dbg(dev, "RGMII_IO_MACRO_CONFIG2: %x\n",
rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG2));
- dev_dbg(&ethqos->pdev->dev, "RGMII_IO_MACRO_DEBUG1: %x\n",
+ dev_dbg(dev, "RGMII_IO_MACRO_DEBUG1: %x\n",
rgmii_readl(ethqos, RGMII_IO_MACRO_DEBUG1));
- dev_dbg(&ethqos->pdev->dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %x\n",
+ dev_dbg(dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %x\n",
rgmii_readl(ethqos, EMAC_SYSTEM_LOW_POWER_DEBUG));
}
@@ -151,23 +165,23 @@ static void rgmii_dump(void *priv)
#define RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ (5 * 1000 * 1000UL)
static void
-ethqos_update_rgmii_clk(struct qcom_ethqos *ethqos, unsigned int speed)
+ethqos_update_link_clk(struct qcom_ethqos *ethqos, unsigned int speed)
{
switch (speed) {
case SPEED_1000:
- ethqos->rgmii_clk_rate = RGMII_1000_NOM_CLK_FREQ;
+ ethqos->link_clk_rate = RGMII_1000_NOM_CLK_FREQ;
break;
case SPEED_100:
- ethqos->rgmii_clk_rate = RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ;
+ ethqos->link_clk_rate = RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ;
break;
case SPEED_10:
- ethqos->rgmii_clk_rate = RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ;
+ ethqos->link_clk_rate = RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ;
break;
}
- clk_set_rate(ethqos->rgmii_clk, ethqos->rgmii_clk_rate);
+ clk_set_rate(ethqos->link_clk, ethqos->link_clk_rate);
}
static void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos)
@@ -189,7 +203,7 @@ static const struct ethqos_emac_driver_data emac_v2_3_0_data = {
.por = emac_v2_3_0_por,
.num_por = ARRAY_SIZE(emac_v2_3_0_por),
.rgmii_config_loopback_en = true,
- .has_emac3 = false,
+ .has_emac_ge_3 = false,
};
static const struct ethqos_emac_por emac_v2_1_0_por[] = {
@@ -205,7 +219,7 @@ static const struct ethqos_emac_driver_data emac_v2_1_0_data = {
.por = emac_v2_1_0_por,
.num_por = ARRAY_SIZE(emac_v2_1_0_por),
.rgmii_config_loopback_en = false,
- .has_emac3 = false,
+ .has_emac_ge_3 = false,
};
static const struct ethqos_emac_por emac_v3_0_0_por[] = {
@@ -221,7 +235,41 @@ static const struct ethqos_emac_driver_data emac_v3_0_0_data = {
.por = emac_v3_0_0_por,
.num_por = ARRAY_SIZE(emac_v3_0_0_por),
.rgmii_config_loopback_en = false,
- .has_emac3 = true,
+ .has_emac_ge_3 = true,
+ .dwmac4_addrs = {
+ .dma_chan = 0x00008100,
+ .dma_chan_offset = 0x1000,
+ .mtl_chan = 0x00008000,
+ .mtl_chan_offset = 0x1000,
+ .mtl_ets_ctrl = 0x00008010,
+ .mtl_ets_ctrl_offset = 0x1000,
+ .mtl_txq_weight = 0x00008018,
+ .mtl_txq_weight_offset = 0x1000,
+ .mtl_send_slp_cred = 0x0000801c,
+ .mtl_send_slp_cred_offset = 0x1000,
+ .mtl_high_cred = 0x00008020,
+ .mtl_high_cred_offset = 0x1000,
+ .mtl_low_cred = 0x00008024,
+ .mtl_low_cred_offset = 0x1000,
+ },
+};
+
+static const struct ethqos_emac_por emac_v4_0_0_por[] = {
+ { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x40c01343 },
+ { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642c },
+ { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x80040800 },
+ { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 },
+ { .offset = SDCC_USR_CTL, .value = 0x00010800 },
+ { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 },
+};
+
+static const struct ethqos_emac_driver_data emac_v4_0_0_data = {
+ .por = emac_v4_0_0_por,
+ .num_por = ARRAY_SIZE(emac_v3_0_0_por),
+ .rgmii_config_loopback_en = false,
+ .has_emac_ge_3 = true,
+ .link_clk_name = "phyaux",
+ .has_integrated_pcs = true,
.dwmac4_addrs = {
.dma_chan = 0x00008100,
.dma_chan_offset = 0x1000,
@@ -242,6 +290,7 @@ static const struct ethqos_emac_driver_data emac_v3_0_0_data = {
static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
{
+ struct device *dev = &ethqos->pdev->dev;
unsigned int val;
int retry = 1000;
@@ -261,7 +310,7 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN,
SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG);
- if (!ethqos->has_emac3) {
+ if (!ethqos->has_emac_ge_3) {
rgmii_updatel(ethqos, SDCC_DLL_MCLK_GATING_EN,
0, SDCC_HC_REG_DLL_CONFIG);
@@ -279,7 +328,7 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
retry--;
} while (retry > 0);
if (!retry)
- dev_err(&ethqos->pdev->dev, "Clear CK_OUT_EN timedout\n");
+ dev_err(dev, "Clear CK_OUT_EN timedout\n");
/* Set CK_OUT_EN */
rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN,
@@ -296,13 +345,13 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
retry--;
} while (retry > 0);
if (!retry)
- dev_err(&ethqos->pdev->dev, "Set CK_OUT_EN timedout\n");
+ dev_err(dev, "Set CK_OUT_EN timedout\n");
/* Set DDR_CAL_EN */
rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_CAL_EN,
SDCC_DLL_CONFIG2_DDR_CAL_EN, SDCC_HC_REG_DLL_CONFIG2);
- if (!ethqos->has_emac3) {
+ if (!ethqos->has_emac_ge_3) {
rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DLL_CLOCK_DIS,
0, SDCC_HC_REG_DLL_CONFIG2);
@@ -322,14 +371,13 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
{
+ struct device *dev = &ethqos->pdev->dev;
int phase_shift;
- int phy_mode;
int loopback;
/* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */
- phy_mode = device_get_phy_mode(&ethqos->pdev->dev);
- if (phy_mode == PHY_INTERFACE_MODE_RGMII_ID ||
- phy_mode == PHY_INTERFACE_MODE_RGMII_TXID)
+ if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID ||
+ ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID)
phase_shift = 0;
else
phase_shift = RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN;
@@ -373,7 +421,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
/* PRG_RCLK_DLY = TCXO period * TCXO_CYCLES_CNT / 2 * RX delay ns,
* in practice this becomes PRG_RCLK_DLY = 52 * 4 / 2 * RX delay ns
*/
- if (ethqos->has_emac3) {
+ if (ethqos->has_emac_ge_3) {
/* 0.9 ns */
rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY,
115, SDCC_HC_REG_DDR_CONFIG);
@@ -408,7 +456,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
0, RGMII_IO_MACRO_CONFIG2);
- if (ethqos->has_emac3)
+ if (ethqos->has_emac_ge_3)
rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
RGMII_CONFIG2_RX_PROG_SWAP,
RGMII_IO_MACRO_CONFIG2);
@@ -448,7 +496,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
RGMII_IO_MACRO_CONFIG);
rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
0, RGMII_IO_MACRO_CONFIG2);
- if (ethqos->has_emac3)
+ if (ethqos->has_emac_ge_3)
rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
RGMII_CONFIG2_RX_PROG_SWAP,
RGMII_IO_MACRO_CONFIG2);
@@ -468,16 +516,16 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
loopback, RGMII_IO_MACRO_CONFIG);
break;
default:
- dev_err(&ethqos->pdev->dev,
- "Invalid speed %d\n", ethqos->speed);
+ dev_err(dev, "Invalid speed %d\n", ethqos->speed);
return -EINVAL;
}
return 0;
}
-static int ethqos_configure(struct qcom_ethqos *ethqos)
+static int ethqos_configure_rgmii(struct qcom_ethqos *ethqos)
{
+ struct device *dev = &ethqos->pdev->dev;
volatile unsigned int dll_lock;
unsigned int i, retry = 1000;
@@ -497,7 +545,7 @@ static int ethqos_configure(struct qcom_ethqos *ethqos)
rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN,
SDCC_DLL_CONFIG_PDN, SDCC_HC_REG_DLL_CONFIG);
- if (ethqos->has_emac3) {
+ if (ethqos->has_emac_ge_3) {
if (ethqos->speed == SPEED_1000) {
rgmii_writel(ethqos, 0x1800000, SDCC_TEST_CTL);
rgmii_writel(ethqos, 0x2C010800, SDCC_USR_CTL);
@@ -527,7 +575,7 @@ static int ethqos_configure(struct qcom_ethqos *ethqos)
SDCC_HC_REG_DLL_CONFIG);
/* Set USR_CTL bit 26 with mask of 3 bits */
- if (!ethqos->has_emac3)
+ if (!ethqos->has_emac_ge_3)
rgmii_updatel(ethqos, GENMASK(26, 24), BIT(26),
SDCC_USR_CTL);
@@ -540,8 +588,7 @@ static int ethqos_configure(struct qcom_ethqos *ethqos)
retry--;
} while (retry > 0);
if (!retry)
- dev_err(&ethqos->pdev->dev,
- "Timeout while waiting for DLL lock\n");
+ dev_err(dev, "Timeout while waiting for DLL lock\n");
}
if (ethqos->speed == SPEED_1000)
@@ -552,24 +599,80 @@ static int ethqos_configure(struct qcom_ethqos *ethqos)
return 0;
}
+static int ethqos_configure_sgmii(struct qcom_ethqos *ethqos)
+{
+ int val;
+
+ val = readl(ethqos->mac_base + MAC_CTRL_REG);
+
+ switch (ethqos->speed) {
+ case SPEED_1000:
+ val &= ~ETHQOS_MAC_CTRL_PORT_SEL;
+ rgmii_updatel(ethqos, RGMII_CONFIG2_RGMII_CLK_SEL_CFG,
+ RGMII_CONFIG2_RGMII_CLK_SEL_CFG,
+ RGMII_IO_MACRO_CONFIG2);
+ break;
+ case SPEED_100:
+ val |= ETHQOS_MAC_CTRL_PORT_SEL | ETHQOS_MAC_CTRL_SPEED_MODE;
+ break;
+ case SPEED_10:
+ val |= ETHQOS_MAC_CTRL_PORT_SEL;
+ val &= ~ETHQOS_MAC_CTRL_SPEED_MODE;
+ break;
+ }
+
+ writel(val, ethqos->mac_base + MAC_CTRL_REG);
+
+ return val;
+}
+
+static int ethqos_configure(struct qcom_ethqos *ethqos)
+{
+ return ethqos->configure_func(ethqos);
+}
+
static void ethqos_fix_mac_speed(void *priv, unsigned int speed)
{
struct qcom_ethqos *ethqos = priv;
ethqos->speed = speed;
- ethqos_update_rgmii_clk(ethqos, speed);
+ ethqos_update_link_clk(ethqos, speed);
ethqos_configure(ethqos);
}
+static int qcom_ethqos_serdes_powerup(struct net_device *ndev, void *priv)
+{
+ struct qcom_ethqos *ethqos = priv;
+ int ret;
+
+ ret = phy_init(ethqos->serdes_phy);
+ if (ret)
+ return ret;
+
+ ret = phy_power_on(ethqos->serdes_phy);
+ if (ret)
+ return ret;
+
+ return phy_set_speed(ethqos->serdes_phy, ethqos->speed);
+}
+
+static void qcom_ethqos_serdes_powerdown(struct net_device *ndev, void *priv)
+{
+ struct qcom_ethqos *ethqos = priv;
+
+ phy_power_off(ethqos->serdes_phy);
+ phy_exit(ethqos->serdes_phy);
+}
+
static int ethqos_clks_config(void *priv, bool enabled)
{
struct qcom_ethqos *ethqos = priv;
int ret = 0;
if (enabled) {
- ret = clk_prepare_enable(ethqos->rgmii_clk);
+ ret = clk_prepare_enable(ethqos->link_clk);
if (ret) {
- dev_err(&ethqos->pdev->dev, "rgmii_clk enable failed\n");
+ dev_err(&ethqos->pdev->dev, "link_clk enable failed\n");
return ret;
}
@@ -580,18 +683,24 @@ static int ethqos_clks_config(void *priv, bool enabled)
*/
ethqos_set_func_clk_en(ethqos);
} else {
- clk_disable_unprepare(ethqos->rgmii_clk);
+ clk_disable_unprepare(ethqos->link_clk);
}
return ret;
}
+static void ethqos_clks_disable(void *data)
+{
+ ethqos_clks_config(data, false);
+}
+
static int qcom_ethqos_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
+ const struct ethqos_emac_driver_data *data;
struct plat_stmmacenet_data *plat_dat;
struct stmmac_resources stmmac_res;
- const struct ethqos_emac_driver_data *data;
+ struct device *dev = &pdev->dev;
struct qcom_ethqos *ethqos;
int ret;
@@ -599,90 +708,91 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
if (ret)
return ret;
- plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
+ plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
if (IS_ERR(plat_dat)) {
- dev_err(&pdev->dev, "dt configuration failed\n");
+ dev_err(dev, "dt configuration failed\n");
return PTR_ERR(plat_dat);
}
plat_dat->clks_config = ethqos_clks_config;
- ethqos = devm_kzalloc(&pdev->dev, sizeof(*ethqos), GFP_KERNEL);
- if (!ethqos) {
- ret = -ENOMEM;
- goto err_mem;
+ ethqos = devm_kzalloc(dev, sizeof(*ethqos), GFP_KERNEL);
+ if (!ethqos)
+ return -ENOMEM;
+
+ ethqos->phy_mode = device_get_phy_mode(dev);
+ switch (ethqos->phy_mode) {
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ ethqos->configure_func = ethqos_configure_rgmii;
+ break;
+ case PHY_INTERFACE_MODE_SGMII:
+ ethqos->configure_func = ethqos_configure_sgmii;
+ break;
+ case -ENODEV:
+ return -ENODEV;
+ default:
+ return -EINVAL;
}
ethqos->pdev = pdev;
ethqos->rgmii_base = devm_platform_ioremap_resource_byname(pdev, "rgmii");
- if (IS_ERR(ethqos->rgmii_base)) {
- ret = PTR_ERR(ethqos->rgmii_base);
- goto err_mem;
- }
+ if (IS_ERR(ethqos->rgmii_base))
+ return PTR_ERR(ethqos->rgmii_base);
+
+ ethqos->mac_base = stmmac_res.addr;
- data = of_device_get_match_data(&pdev->dev);
+ data = of_device_get_match_data(dev);
ethqos->por = data->por;
ethqos->num_por = data->num_por;
ethqos->rgmii_config_loopback_en = data->rgmii_config_loopback_en;
- ethqos->has_emac3 = data->has_emac3;
+ ethqos->has_emac_ge_3 = data->has_emac_ge_3;
- ethqos->rgmii_clk = devm_clk_get(&pdev->dev, "rgmii");
- if (IS_ERR(ethqos->rgmii_clk)) {
- ret = PTR_ERR(ethqos->rgmii_clk);
- goto err_mem;
- }
+ ethqos->link_clk = devm_clk_get(dev, data->link_clk_name ?: "rgmii");
+ if (IS_ERR(ethqos->link_clk))
+ return PTR_ERR(ethqos->link_clk);
ret = ethqos_clks_config(ethqos, true);
if (ret)
- goto err_mem;
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, ethqos_clks_disable, ethqos);
+ if (ret)
+ return ret;
+
+ ethqos->serdes_phy = devm_phy_optional_get(dev, "serdes");
+ if (IS_ERR(ethqos->serdes_phy))
+ return PTR_ERR(ethqos->serdes_phy);
ethqos->speed = SPEED_1000;
- ethqos_update_rgmii_clk(ethqos, SPEED_1000);
+ ethqos_update_link_clk(ethqos, SPEED_1000);
ethqos_set_func_clk_en(ethqos);
plat_dat->bsp_priv = ethqos;
plat_dat->fix_mac_speed = ethqos_fix_mac_speed;
plat_dat->dump_debug_regs = rgmii_dump;
plat_dat->has_gmac4 = 1;
- if (ethqos->has_emac3)
+ if (ethqos->has_emac_ge_3)
plat_dat->dwmac4_addrs = &data->dwmac4_addrs;
plat_dat->pmt = 1;
plat_dat->tso_en = of_property_read_bool(np, "snps,tso");
if (of_device_is_compatible(np, "qcom,qcs404-ethqos"))
plat_dat->rx_clk_runs_in_lpi = 1;
+ plat_dat->has_integrated_pcs = data->has_integrated_pcs;
- ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
- if (ret)
- goto err_clk;
-
- return ret;
-
-err_clk:
- ethqos_clks_config(ethqos, false);
-
-err_mem:
- stmmac_remove_config_dt(pdev, plat_dat);
-
- return ret;
-}
-
-static int qcom_ethqos_remove(struct platform_device *pdev)
-{
- struct qcom_ethqos *ethqos;
- int ret;
-
- ethqos = get_stmmac_bsp_priv(&pdev->dev);
- if (!ethqos)
- return -ENODEV;
-
- ret = stmmac_pltfr_remove(pdev);
- ethqos_clks_config(ethqos, false);
+ if (ethqos->serdes_phy) {
+ plat_dat->serdes_powerup = qcom_ethqos_serdes_powerup;
+ plat_dat->serdes_powerdown = qcom_ethqos_serdes_powerdown;
+ }
- return ret;
+ return devm_stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
}
static const struct of_device_id qcom_ethqos_match[] = {
{ .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_data},
+ { .compatible = "qcom,sa8775p-ethqos", .data = &emac_v4_0_0_data},
{ .compatible = "qcom,sc8280xp-ethqos", .data = &emac_v3_0_0_data},
{ .compatible = "qcom,sm8150-ethqos", .data = &emac_v2_1_0_data},
{ }
@@ -691,7 +801,6 @@ MODULE_DEVICE_TABLE(of, qcom_ethqos_match);
static struct platform_driver qcom_ethqos_driver = {
.probe = qcom_ethqos_probe,
- .remove = qcom_ethqos_remove,
.driver = {
.name = "qcom-ethqos",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 4ea31ccf24d0..d81591b470a2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -1863,15 +1863,13 @@ err_remove_config_dt:
return ret;
}
-static int rk_gmac_remove(struct platform_device *pdev)
+static void rk_gmac_remove(struct platform_device *pdev)
{
struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(&pdev->dev);
stmmac_dvr_remove(&pdev->dev);
rk_gmac_powerdown(bsp_priv);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -1925,7 +1923,7 @@ MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match);
static struct platform_driver rk_gmac_dwmac_driver = {
.probe = rk_gmac_probe,
- .remove = rk_gmac_remove,
+ .remove_new = rk_gmac_remove,
.driver = {
.name = "rk_gmac-dwmac",
.pm = &rk_gmac_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
index 6b447d8f0bd8..6267bcb60206 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
@@ -10,14 +10,14 @@
#include <linux/of_net.h>
#include <linux/phy.h>
#include <linux/regmap.h>
+#include <linux/mdio/mdio-regmap.h>
+#include <linux/pcs-lynx.h>
#include <linux/reset.h>
#include <linux/stmmac.h>
#include "stmmac.h"
#include "stmmac_platform.h"
-#include "altr_tse_pcs.h"
-
#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2
@@ -37,6 +37,10 @@
#define EMAC_SPLITTER_CTRL_SPEED_100 0x3
#define EMAC_SPLITTER_CTRL_SPEED_1000 0x0
+#define SGMII_ADAPTER_CTRL_REG 0x00
+#define SGMII_ADAPTER_ENABLE 0x0000
+#define SGMII_ADAPTER_DISABLE 0x0001
+
struct socfpga_dwmac;
struct socfpga_dwmac_ops {
int (*set_phy_mode)(struct socfpga_dwmac *dwmac_priv);
@@ -50,16 +54,18 @@ struct socfpga_dwmac {
struct reset_control *stmmac_rst;
struct reset_control *stmmac_ocp_rst;
void __iomem *splitter_base;
+ void __iomem *tse_pcs_base;
+ void __iomem *sgmii_adapter_base;
bool f2h_ptp_ref_clk;
- struct tse_pcs pcs;
const struct socfpga_dwmac_ops *ops;
+ struct mdio_device *pcs_mdiodev;
};
static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed)
{
struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)priv;
void __iomem *splitter_base = dwmac->splitter_base;
- void __iomem *sgmii_adapter_base = dwmac->pcs.sgmii_adapter_base;
+ void __iomem *sgmii_adapter_base = dwmac->sgmii_adapter_base;
struct device *dev = dwmac->dev;
struct net_device *ndev = dev_get_drvdata(dev);
struct phy_device *phy_dev = ndev->phydev;
@@ -89,11 +95,9 @@ static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed)
writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG);
}
- if (phy_dev && sgmii_adapter_base) {
+ if (phy_dev && sgmii_adapter_base)
writew(SGMII_ADAPTER_ENABLE,
sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
- tse_pcs_fix_mac_speed(&dwmac->pcs, phy_dev, speed);
- }
}
static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev)
@@ -183,11 +187,11 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *
goto err_node_put;
}
- dwmac->pcs.sgmii_adapter_base =
+ dwmac->sgmii_adapter_base =
devm_ioremap_resource(dev, &res_sgmii_adapter);
- if (IS_ERR(dwmac->pcs.sgmii_adapter_base)) {
- ret = PTR_ERR(dwmac->pcs.sgmii_adapter_base);
+ if (IS_ERR(dwmac->sgmii_adapter_base)) {
+ ret = PTR_ERR(dwmac->sgmii_adapter_base);
goto err_node_put;
}
}
@@ -205,11 +209,11 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *
goto err_node_put;
}
- dwmac->pcs.tse_pcs_base =
+ dwmac->tse_pcs_base =
devm_ioremap_resource(dev, &res_tse_pcs);
- if (IS_ERR(dwmac->pcs.tse_pcs_base)) {
- ret = PTR_ERR(dwmac->pcs.tse_pcs_base);
+ if (IS_ERR(dwmac->tse_pcs_base)) {
+ ret = PTR_ERR(dwmac->tse_pcs_base);
goto err_node_put;
}
}
@@ -235,6 +239,13 @@ static int socfpga_get_plat_phymode(struct socfpga_dwmac *dwmac)
return priv->plat->interface;
}
+static void socfpga_sgmii_config(struct socfpga_dwmac *dwmac, bool enable)
+{
+ u16 val = enable ? SGMII_ADAPTER_ENABLE : SGMII_ADAPTER_DISABLE;
+
+ writew(val, dwmac->sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
+}
+
static int socfpga_set_phy_mode_common(int phymode, u32 *val)
{
switch (phymode) {
@@ -310,12 +321,8 @@ static int socfpga_gen5_set_phy_mode(struct socfpga_dwmac *dwmac)
*/
reset_control_deassert(dwmac->stmmac_ocp_rst);
reset_control_deassert(dwmac->stmmac_rst);
- if (phymode == PHY_INTERFACE_MODE_SGMII) {
- if (tse_pcs_init(dwmac->pcs.tse_pcs_base, &dwmac->pcs) != 0) {
- dev_err(dwmac->dev, "Unable to initialize TSE PCS");
- return -EINVAL;
- }
- }
+ if (phymode == PHY_INTERFACE_MODE_SGMII)
+ socfpga_sgmii_config(dwmac, true);
return 0;
}
@@ -367,12 +374,8 @@ static int socfpga_gen10_set_phy_mode(struct socfpga_dwmac *dwmac)
*/
reset_control_deassert(dwmac->stmmac_ocp_rst);
reset_control_deassert(dwmac->stmmac_rst);
- if (phymode == PHY_INTERFACE_MODE_SGMII) {
- if (tse_pcs_init(dwmac->pcs.tse_pcs_base, &dwmac->pcs) != 0) {
- dev_err(dwmac->dev, "Unable to initialize TSE PCS");
- return -EINVAL;
- }
- }
+ if (phymode == PHY_INTERFACE_MODE_SGMII)
+ socfpga_sgmii_config(dwmac, true);
return 0;
}
@@ -443,6 +446,48 @@ static int socfpga_dwmac_probe(struct platform_device *pdev)
if (ret)
goto err_dvr_remove;
+ /* Create a regmap for the PCS so that it can be used by the PCS driver,
+ * if we have such a PCS
+ */
+ if (dwmac->tse_pcs_base) {
+ struct regmap_config pcs_regmap_cfg;
+ struct mdio_regmap_config mrc;
+ struct regmap *pcs_regmap;
+ struct mii_bus *pcs_bus;
+
+ memset(&pcs_regmap_cfg, 0, sizeof(pcs_regmap_cfg));
+ memset(&mrc, 0, sizeof(mrc));
+
+ pcs_regmap_cfg.reg_bits = 16;
+ pcs_regmap_cfg.val_bits = 16;
+ pcs_regmap_cfg.reg_shift = REGMAP_UPSHIFT(1);
+
+ pcs_regmap = devm_regmap_init_mmio(&pdev->dev, dwmac->tse_pcs_base,
+ &pcs_regmap_cfg);
+ if (IS_ERR(pcs_regmap)) {
+ ret = PTR_ERR(pcs_regmap);
+ goto err_dvr_remove;
+ }
+
+ mrc.regmap = pcs_regmap;
+ mrc.parent = &pdev->dev;
+ mrc.valid_addr = 0x0;
+ mrc.autoscan = false;
+
+ snprintf(mrc.name, MII_BUS_ID_SIZE, "%s-pcs-mii", ndev->name);
+ pcs_bus = devm_mdio_regmap_register(&pdev->dev, &mrc);
+ if (IS_ERR(pcs_bus)) {
+ ret = PTR_ERR(pcs_bus);
+ goto err_dvr_remove;
+ }
+
+ stpriv->hw->lynx_pcs = lynx_pcs_create_mdiodev(pcs_bus, 0);
+ if (IS_ERR(stpriv->hw->lynx_pcs)) {
+ ret = PTR_ERR(stpriv->hw->lynx_pcs);
+ goto err_dvr_remove;
+ }
+ }
+
return 0;
err_dvr_remove:
@@ -453,6 +498,17 @@ err_remove_config_dt:
return ret;
}
+static void socfpga_dwmac_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ struct phylink_pcs *pcs = priv->hw->lynx_pcs;
+
+ stmmac_pltfr_remove(pdev);
+
+ lynx_pcs_destroy(pcs);
+}
+
#ifdef CONFIG_PM_SLEEP
static int socfpga_dwmac_resume(struct device *dev)
{
@@ -524,7 +580,7 @@ MODULE_DEVICE_TABLE(of, socfpga_dwmac_match);
static struct platform_driver socfpga_dwmac_driver = {
.probe = socfpga_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = socfpga_dwmac_remove,
.driver = {
.name = "socfpga-dwmac",
.pm = &socfpga_dwmac_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
index 4f51a7889642..d3a39d2fb3a9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
@@ -156,7 +156,7 @@ MODULE_DEVICE_TABLE(of, starfive_dwmac_match);
static struct platform_driver starfive_dwmac_driver = {
.probe = starfive_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "starfive-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
index 465ce66ef9c1..dcbb17c4f07a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
@@ -317,15 +317,13 @@ err_remove_config_dt:
return ret;
}
-static int sti_dwmac_remove(struct platform_device *pdev)
+static void sti_dwmac_remove(struct platform_device *pdev)
{
struct sti_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev);
stmmac_dvr_remove(&pdev->dev);
clk_disable_unprepare(dwmac->clk);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -365,7 +363,7 @@ MODULE_DEVICE_TABLE(of, sti_dwmac_match);
static struct platform_driver sti_dwmac_driver = {
.probe = sti_dwmac_probe,
- .remove = sti_dwmac_remove,
+ .remove_new = sti_dwmac_remove,
.driver = {
.name = "sti-dwmac",
.pm = &sti_dwmac_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
index 0616b3a04ff3..bdb4de59a672 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
@@ -417,7 +417,7 @@ err_remove_config_dt:
return ret;
}
-static int stm32_dwmac_remove(struct platform_device *pdev)
+static void stm32_dwmac_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(ndev);
@@ -431,8 +431,6 @@ static int stm32_dwmac_remove(struct platform_device *pdev)
dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
}
-
- return 0;
}
static int stm32mp1_suspend(struct stm32_dwmac *dwmac)
@@ -528,7 +526,7 @@ MODULE_DEVICE_TABLE(of, stm32_dwmac_match);
static struct platform_driver stm32_dwmac_driver = {
.probe = stm32_dwmac_probe,
- .remove = stm32_dwmac_remove,
+ .remove_new = stm32_dwmac_remove,
.driver = {
.name = "stm32-dwmac",
.pm = &stm32_dwmac_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index c2c592ba0eb8..1e714380d125 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -1294,7 +1294,7 @@ dwmac_deconfig:
return ret;
}
-static int sun8i_dwmac_remove(struct platform_device *pdev)
+static void sun8i_dwmac_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(ndev);
@@ -1309,8 +1309,6 @@ static int sun8i_dwmac_remove(struct platform_device *pdev)
stmmac_pltfr_remove(pdev);
sun8i_dwmac_unset_syscon(gmac);
-
- return 0;
}
static void sun8i_dwmac_shutdown(struct platform_device *pdev)
@@ -1341,7 +1339,7 @@ MODULE_DEVICE_TABLE(of, sun8i_dwmac_match);
static struct platform_driver sun8i_dwmac_driver = {
.probe = sun8i_dwmac_probe,
- .remove = sun8i_dwmac_remove,
+ .remove_new = sun8i_dwmac_remove,
.shutdown = sun8i_dwmac_shutdown,
.driver = {
.name = "dwmac-sun8i",
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
index fc3b0acc8f99..50963e91c347 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
@@ -179,7 +179,7 @@ MODULE_DEVICE_TABLE(of, sun7i_dwmac_match);
static struct platform_driver sun7i_dwmac_driver = {
.probe = sun7i_gmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "sun7i-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c
index bdf990cf2f31..fbb0ccf84afc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c
@@ -234,7 +234,8 @@ static int tegra_mgbe_probe(struct platform_device *pdev)
res.addr = mgbe->regs;
res.irq = irq;
- mgbe->clks = devm_kzalloc(&pdev->dev, sizeof(*mgbe->clks), GFP_KERNEL);
+ mgbe->clks = devm_kcalloc(&pdev->dev, ARRAY_SIZE(mgbe_clks),
+ sizeof(*mgbe->clks), GFP_KERNEL);
if (!mgbe->clks)
return -ENOMEM;
@@ -353,15 +354,13 @@ disable_clks:
return err;
}
-static int tegra_mgbe_remove(struct platform_device *pdev)
+static void tegra_mgbe_remove(struct platform_device *pdev)
{
struct tegra_mgbe *mgbe = get_stmmac_bsp_priv(&pdev->dev);
clk_bulk_disable_unprepare(ARRAY_SIZE(mgbe_clks), mgbe->clks);
stmmac_pltfr_remove(pdev);
-
- return 0;
}
static const struct of_device_id tegra_mgbe_match[] = {
@@ -374,7 +373,7 @@ static SIMPLE_DEV_PM_OPS(tegra_mgbe_pm_ops, tegra_mgbe_suspend, tegra_mgbe_resum
static struct platform_driver tegra_mgbe_driver = {
.probe = tegra_mgbe_probe,
- .remove = tegra_mgbe_remove,
+ .remove_new = tegra_mgbe_remove,
.driver = {
.name = "tegra-mgbe",
.pm = &tegra_mgbe_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
index c3f10a92b62b..acbb284be174 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
@@ -198,7 +198,7 @@ static int visconti_eth_clock_probe(struct platform_device *pdev,
return 0;
}
-static int visconti_eth_clock_remove(struct platform_device *pdev)
+static void visconti_eth_clock_remove(struct platform_device *pdev)
{
struct visconti_eth *dwmac = get_stmmac_bsp_priv(&pdev->dev);
struct net_device *ndev = platform_get_drvdata(pdev);
@@ -206,8 +206,6 @@ static int visconti_eth_clock_remove(struct platform_device *pdev)
clk_disable_unprepare(dwmac->phy_ref_clk);
clk_disable_unprepare(priv->plat->stmmac_clk);
-
- return 0;
}
static int visconti_eth_dwmac_probe(struct platform_device *pdev)
@@ -259,23 +257,16 @@ remove_config:
return ret;
}
-static int visconti_eth_dwmac_remove(struct platform_device *pdev)
+static void visconti_eth_dwmac_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(ndev);
- int err;
- err = stmmac_pltfr_remove(pdev);
- if (err < 0)
- dev_err(&pdev->dev, "failed to remove platform: %d\n", err);
+ stmmac_pltfr_remove(pdev);
- err = visconti_eth_clock_remove(pdev);
- if (err < 0)
- dev_err(&pdev->dev, "failed to remove clock: %d\n", err);
+ visconti_eth_clock_remove(pdev);
stmmac_remove_config_dt(pdev, priv->plat);
-
- return err;
}
static const struct of_device_id visconti_eth_dwmac_match[] = {
@@ -286,7 +277,7 @@ MODULE_DEVICE_TABLE(of, visconti_eth_dwmac_match);
static struct platform_driver visconti_eth_dwmac_driver = {
.probe = visconti_eth_dwmac_probe,
- .remove = visconti_eth_dwmac_remove,
+ .remove_new = visconti_eth_dwmac_remove,
.driver = {
.name = "visconti-eth-dwmac",
.of_match_table = visconti_eth_dwmac_match,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
index df41eac54058..03ceb6a94073 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
@@ -240,13 +240,15 @@ void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, const u8 addr[6],
void stmmac_dwmac4_set_mac(void __iomem *ioaddr, bool enable)
{
u32 value = readl(ioaddr + GMAC_CONFIG);
+ u32 old_val = value;
if (enable)
value |= GMAC_CONFIG_RE | GMAC_CONFIG_TE;
else
value &= ~(GMAC_CONFIG_TE | GMAC_CONFIG_RE);
- writel(value, ioaddr + GMAC_CONFIG);
+ if (value != old_val)
+ writel(value, ioaddr + GMAC_CONFIG);
}
void stmmac_dwmac4_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
index dfd53264e036..070bd912580b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
@@ -368,10 +368,12 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv,
if (likely(intr_status & XGMAC_RI)) {
x->rx_normal_irq_n++;
+ x->rxq_stats[chan].rx_normal_irq_n++;
ret |= handle_rx;
}
if (likely(intr_status & (XGMAC_TI | XGMAC_TBU))) {
x->tx_normal_irq_n++;
+ x->txq_stats[chan].tx_normal_irq_n++;
ret |= handle_tx;
}
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 87510951f4e8..4727f7be4f86 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -937,10 +937,13 @@ static struct phylink_pcs *stmmac_mac_select_pcs(struct phylink_config *config,
{
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
- if (!priv->hw->xpcs)
- return NULL;
+ if (priv->hw->xpcs)
+ return &priv->hw->xpcs->pcs;
- return &priv->hw->xpcs->pcs;
+ if (priv->hw->lynx_pcs)
+ return priv->hw->lynx_pcs;
+
+ return NULL;
}
static void stmmac_mac_config(struct phylink_config *config, unsigned int mode,
@@ -3813,7 +3816,8 @@ static int __stmmac_open(struct net_device *dev,
if (priv->hw->pcs != STMMAC_PCS_TBI &&
priv->hw->pcs != STMMAC_PCS_RTBI &&
(!priv->hw->xpcs ||
- xpcs_get_an_mode(priv->hw->xpcs, mode) != DW_AN_C73)) {
+ xpcs_get_an_mode(priv->hw->xpcs, mode) != DW_AN_C73) &&
+ !priv->hw->lynx_pcs) {
ret = stmmac_init_phy(dev);
if (ret) {
netdev_err(priv->dev,
@@ -5794,7 +5798,7 @@ static void stmmac_common_interrupt(struct stmmac_priv *priv)
}
/* PCS link status */
- if (priv->hw->pcs) {
+ if (priv->hw->pcs && !priv->plat->has_integrated_pcs) {
if (priv->xstats.pcs_link)
netif_carrier_on(priv->dev);
else
@@ -7457,12 +7461,6 @@ void stmmac_dvr_remove(struct device *dev)
netif_carrier_off(ndev);
unregister_netdev(ndev);
- /* Serdes power down needs to happen after VLAN filter
- * is deleted that is triggered by unregister_netdev().
- */
- if (priv->plat->serdes_powerdown)
- priv->plat->serdes_powerdown(ndev, priv->plat->bsp_priv);
-
#ifdef CONFIG_DEBUG_FS
stmmac_exit_fs(ndev);
#endif
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index 6807c4c1a0a2..3db1cb0fd160 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -491,7 +491,6 @@ int stmmac_mdio_reset(struct mii_bus *bus)
int stmmac_xpcs_setup(struct mii_bus *bus)
{
struct net_device *ndev = bus->priv;
- struct mdio_device *mdiodev;
struct stmmac_priv *priv;
struct dw_xpcs *xpcs;
int mode, addr;
@@ -501,16 +500,10 @@ int stmmac_xpcs_setup(struct mii_bus *bus)
/* Try to probe the XPCS by scanning all addresses. */
for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
- mdiodev = mdio_device_create(bus, addr);
- if (IS_ERR(mdiodev))
+ xpcs = xpcs_create_mdiodev(bus, addr, mode);
+ if (IS_ERR(xpcs))
continue;
- xpcs = xpcs_create(mdiodev, mode);
- if (IS_ERR_OR_NULL(xpcs)) {
- mdio_device_free(mdiodev);
- continue;
- }
-
priv->hw->xpcs = xpcs;
break;
}
@@ -669,10 +662,8 @@ int stmmac_mdio_unregister(struct net_device *ndev)
if (!priv->mii)
return 0;
- if (priv->hw->xpcs) {
- mdio_device_free(priv->hw->xpcs->mdiodev);
+ if (priv->hw->xpcs)
xpcs_destroy(priv->hw->xpcs);
- }
mdiobus_unregister(priv->mii);
priv->mii->priv = NULL;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index eb0b2898daa3..231152ee5a32 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -8,6 +8,7 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/module.h>
@@ -629,6 +630,39 @@ error_pclk_get:
return ret;
}
+static void devm_stmmac_remove_config_dt(void *data)
+{
+ struct plat_stmmacenet_data *plat = data;
+
+ /* Platform data argument is unused */
+ stmmac_remove_config_dt(NULL, plat);
+}
+
+/**
+ * devm_stmmac_probe_config_dt
+ * @pdev: platform_device structure
+ * @mac: MAC address to use
+ * Description: Devres variant of stmmac_probe_config_dt(). Does not require
+ * the user to call stmmac_remove_config_dt() at driver detach.
+ */
+struct plat_stmmacenet_data *
+devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
+{
+ struct plat_stmmacenet_data *plat;
+ int ret;
+
+ plat = stmmac_probe_config_dt(pdev, mac);
+ if (IS_ERR(plat))
+ return plat;
+
+ ret = devm_add_action_or_reset(&pdev->dev,
+ devm_stmmac_remove_config_dt, plat);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return plat;
+}
+
/**
* stmmac_remove_config_dt - undo the effects of stmmac_probe_config_dt()
* @pdev: platform_device structure
@@ -651,12 +685,19 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
return ERR_PTR(-EINVAL);
}
+struct plat_stmmacenet_data *
+devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
+{
+ return ERR_PTR(-EINVAL);
+}
+
void stmmac_remove_config_dt(struct platform_device *pdev,
struct plat_stmmacenet_data *plat)
{
}
#endif /* CONFIG_OF */
EXPORT_SYMBOL_GPL(stmmac_probe_config_dt);
+EXPORT_SYMBOL_GPL(devm_stmmac_probe_config_dt);
EXPORT_SYMBOL_GPL(stmmac_remove_config_dt);
int stmmac_get_platform_resources(struct platform_device *pdev,
@@ -702,25 +743,127 @@ int stmmac_get_platform_resources(struct platform_device *pdev,
EXPORT_SYMBOL_GPL(stmmac_get_platform_resources);
/**
- * stmmac_pltfr_remove
+ * stmmac_pltfr_init
+ * @pdev: pointer to the platform device
+ * @plat: driver data platform structure
+ * Description: Call the platform's init callback (if any) and propagate
+ * the return value.
+ */
+int stmmac_pltfr_init(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat)
+{
+ int ret = 0;
+
+ if (plat->init)
+ ret = plat->init(pdev, plat->bsp_priv);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(stmmac_pltfr_init);
+
+/**
+ * stmmac_pltfr_exit
+ * @pdev: pointer to the platform device
+ * @plat: driver data platform structure
+ * Description: Call the platform's exit callback (if any).
+ */
+void stmmac_pltfr_exit(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat)
+{
+ if (plat->exit)
+ plat->exit(pdev, plat->bsp_priv);
+}
+EXPORT_SYMBOL_GPL(stmmac_pltfr_exit);
+
+/**
+ * stmmac_pltfr_probe
* @pdev: platform device pointer
- * Description: this function calls the main to free the net resources
- * and calls the platforms hook and release the resources (e.g. mem).
+ * @plat: driver data platform structure
+ * @res: stmmac resources structure
+ * Description: This calls the platform's init() callback and probes the
+ * stmmac driver.
*/
-int stmmac_pltfr_remove(struct platform_device *pdev)
+int stmmac_pltfr_probe(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat,
+ struct stmmac_resources *res)
+{
+ int ret;
+
+ ret = stmmac_pltfr_init(pdev, plat);
+ if (ret)
+ return ret;
+
+ ret = stmmac_dvr_probe(&pdev->dev, plat, res);
+ if (ret) {
+ stmmac_pltfr_exit(pdev, plat);
+ return ret;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(stmmac_pltfr_probe);
+
+static void devm_stmmac_pltfr_remove(void *data)
+{
+ struct platform_device *pdev = data;
+
+ stmmac_pltfr_remove_no_dt(pdev);
+}
+
+/**
+ * devm_stmmac_pltfr_probe
+ * @pdev: pointer to the platform device
+ * @plat: driver data platform structure
+ * @res: stmmac resources
+ * Description: Devres variant of stmmac_pltfr_probe(). Allows users to skip
+ * calling stmmac_pltfr_remove() on driver detach.
+ */
+int devm_stmmac_pltfr_probe(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat,
+ struct stmmac_resources *res)
+{
+ int ret;
+
+ ret = stmmac_pltfr_probe(pdev, plat, res);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(&pdev->dev, devm_stmmac_pltfr_remove,
+ pdev);
+}
+EXPORT_SYMBOL_GPL(devm_stmmac_pltfr_probe);
+
+/**
+ * stmmac_pltfr_remove_no_dt
+ * @pdev: pointer to the platform device
+ * Description: This undoes the effects of stmmac_pltfr_probe() by removing the
+ * driver and calling the platform's exit() callback.
+ */
+void stmmac_pltfr_remove_no_dt(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(ndev);
struct plat_stmmacenet_data *plat = priv->plat;
stmmac_dvr_remove(&pdev->dev);
+ stmmac_pltfr_exit(pdev, plat);
+}
+EXPORT_SYMBOL_GPL(stmmac_pltfr_remove_no_dt);
- if (plat->exit)
- plat->exit(pdev, plat->bsp_priv);
+/**
+ * stmmac_pltfr_remove
+ * @pdev: platform device pointer
+ * Description: this function calls the main to free the net resources
+ * and calls the platforms hook and release the resources (e.g. mem).
+ */
+void stmmac_pltfr_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ struct plat_stmmacenet_data *plat = priv->plat;
+ stmmac_pltfr_remove_no_dt(pdev);
stmmac_remove_config_dt(pdev, plat);
-
- return 0;
}
EXPORT_SYMBOL_GPL(stmmac_pltfr_remove);
@@ -739,8 +882,7 @@ static int __maybe_unused stmmac_pltfr_suspend(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
ret = stmmac_suspend(dev);
- if (priv->plat->exit)
- priv->plat->exit(pdev, priv->plat->bsp_priv);
+ stmmac_pltfr_exit(pdev, priv->plat);
return ret;
}
@@ -757,9 +899,11 @@ static int __maybe_unused stmmac_pltfr_resume(struct device *dev)
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
struct platform_device *pdev = to_platform_device(dev);
+ int ret;
- if (priv->plat->init)
- priv->plat->init(pdev, priv->plat->bsp_priv);
+ ret = stmmac_pltfr_init(pdev, priv->plat->bsp_priv);
+ if (ret)
+ return ret;
return stmmac_resume(dev);
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
index 3fff3f59d73d..c5565b2a70ac 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
@@ -13,13 +13,27 @@
struct plat_stmmacenet_data *
stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac);
+struct plat_stmmacenet_data *
+devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac);
void stmmac_remove_config_dt(struct platform_device *pdev,
struct plat_stmmacenet_data *plat);
int stmmac_get_platform_resources(struct platform_device *pdev,
struct stmmac_resources *stmmac_res);
-int stmmac_pltfr_remove(struct platform_device *pdev);
+int stmmac_pltfr_init(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat);
+void stmmac_pltfr_exit(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat);
+
+int stmmac_pltfr_probe(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat,
+ struct stmmac_resources *res);
+int devm_stmmac_pltfr_probe(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat,
+ struct stmmac_resources *res);
+void stmmac_pltfr_remove_no_dt(struct platform_device *pdev);
+void stmmac_pltfr_remove(struct platform_device *pdev);
extern const struct dev_pm_ops stmmac_pltfr_pm_ops;
static inline void *get_stmmac_bsp_priv(struct device *dev)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index 9d55226479b4..ac41ef4cbd2f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -966,8 +966,11 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
return -EOPNOTSUPP;
}
- if (!qopt->enable)
+ if (qopt->cmd == TAPRIO_CMD_DESTROY)
goto disable;
+ else if (qopt->cmd != TAPRIO_CMD_REPLACE)
+ return -EOPNOTSUPP;
+
if (qopt->num_entries >= dep)
return -EINVAL;
if (!qopt->cycle_time)
@@ -988,7 +991,7 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
mutex_lock(&priv->plat->est->lock);
priv->plat->est->gcl_size = size;
- priv->plat->est->enable = qopt->enable;
+ priv->plat->est->enable = qopt->cmd == TAPRIO_CMD_REPLACE;
mutex_unlock(&priv->plat->est->lock);
for (i = 0; i < size; i++) {
diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c
index d61dfa250feb..b317b9486455 100644
--- a/drivers/net/ethernet/sun/cassini.c
+++ b/drivers/net/ethernet/sun/cassini.c
@@ -1998,10 +1998,8 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
skb->truesize += hlen - swivel;
skb->len += hlen - swivel;
- __skb_frag_set_page(frag, page->buffer);
+ skb_frag_fill_page_desc(frag, page->buffer, off, hlen - swivel);
__skb_frag_ref(frag);
- skb_frag_off_set(frag, off);
- skb_frag_size_set(frag, hlen - swivel);
/* any more data? */
if ((words[0] & RX_COMP1_SPLIT_PKT) && ((dlen -= hlen) > 0)) {
@@ -2024,10 +2022,8 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
skb->len += hlen;
frag++;
- __skb_frag_set_page(frag, page->buffer);
+ skb_frag_fill_page_desc(frag, page->buffer, 0, hlen);
__skb_frag_ref(frag);
- skb_frag_off_set(frag, 0);
- skb_frag_size_set(frag, hlen);
RX_USED_ADD(page, hlen + cp->crc_size);
}
diff --git a/drivers/net/ethernet/sun/sunvnet_common.c b/drivers/net/ethernet/sun/sunvnet_common.c
index a6211b95ed17..3525d5c0d694 100644
--- a/drivers/net/ethernet/sun/sunvnet_common.c
+++ b/drivers/net/ethernet/sun/sunvnet_common.c
@@ -25,6 +25,7 @@
#endif
#include <net/ip.h>
+#include <net/gso.h>
#include <net/icmp.h>
#include <net/route.h>
diff --git a/drivers/net/ethernet/ti/am65-cpsw-qos.c b/drivers/net/ethernet/ti/am65-cpsw-qos.c
index 3a908db6e5b2..eced87fa261c 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-qos.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-qos.c
@@ -450,7 +450,7 @@ static int am65_cpsw_configure_taprio(struct net_device *ndev,
am65_cpsw_est_update_state(ndev);
- if (!est_new->taprio.enable) {
+ if (est_new->taprio.cmd == TAPRIO_CMD_DESTROY) {
am65_cpsw_stop_est(ndev);
return ret;
}
@@ -476,7 +476,7 @@ static int am65_cpsw_configure_taprio(struct net_device *ndev,
am65_cpsw_est_set_sched_list(ndev, est_new);
am65_cpsw_port_est_assign_buf_num(ndev, est_new->buf);
- am65_cpsw_est_set(ndev, est_new->taprio.enable);
+ am65_cpsw_est_set(ndev, est_new->taprio.cmd == TAPRIO_CMD_REPLACE);
if (tact == TACT_PROG) {
ret = am65_cpsw_timer_set(ndev, est_new);
@@ -520,7 +520,7 @@ static int am65_cpsw_set_taprio(struct net_device *ndev, void *type_data)
am65_cpsw_cp_taprio(taprio, &est_new->taprio);
ret = am65_cpsw_configure_taprio(ndev, est_new);
if (!ret) {
- if (taprio->enable) {
+ if (taprio->cmd == TAPRIO_CMD_REPLACE) {
devm_kfree(&ndev->dev, port->qos.est_admin);
port->qos.est_admin = est_new;
@@ -564,8 +564,13 @@ purge_est:
static int am65_cpsw_setup_taprio(struct net_device *ndev, void *type_data)
{
struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
+ struct tc_taprio_qopt_offload *taprio = type_data;
struct am65_cpsw_common *common = port->common;
+ if (taprio->cmd != TAPRIO_CMD_REPLACE &&
+ taprio->cmd != TAPRIO_CMD_DESTROY)
+ return -EOPNOTSUPP;
+
if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_TAS))
return -ENODEV;
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 0c5e783e574c..64bf22cd860c 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -106,23 +106,37 @@ struct cpsw_ale_dev_id {
static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
{
- int idx;
+ int idx, idx2;
+ u32 hi_val = 0;
idx = start / 32;
+ idx2 = (start + bits - 1) / 32;
+ /* Check if bits to be fetched exceed a word */
+ if (idx != idx2) {
+ idx2 = 2 - idx2; /* flip */
+ hi_val = ale_entry[idx2] << ((idx2 * 32) - start);
+ }
start -= idx * 32;
idx = 2 - idx; /* flip */
- return (ale_entry[idx] >> start) & BITMASK(bits);
+ return (hi_val + (ale_entry[idx] >> start)) & BITMASK(bits);
}
static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
u32 value)
{
- int idx;
+ int idx, idx2;
value &= BITMASK(bits);
- idx = start / 32;
+ idx = start / 32;
+ idx2 = (start + bits - 1) / 32;
+ /* Check if bits to be set exceed a word */
+ if (idx != idx2) {
+ idx2 = 2 - idx2; /* flip */
+ ale_entry[idx2] &= ~(BITMASK(bits + start - (idx2 * 32)));
+ ale_entry[idx2] |= (value >> ((idx2 * 32) - start));
+ }
start -= idx * 32;
- idx = 2 - idx; /* flip */
+ idx = 2 - idx; /* flip */
ale_entry[idx] &= ~(BITMASK(bits) << start);
ale_entry[idx] |= (value << start);
}
diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig
index c9d88673d306..39596cd13539 100644
--- a/drivers/net/ethernet/wangxun/Kconfig
+++ b/drivers/net/ethernet/wangxun/Kconfig
@@ -40,6 +40,16 @@ config NGBE
config TXGBE
tristate "Wangxun(R) 10GbE PCI Express adapters support"
depends on PCI
+ depends on COMMON_CLK
+ select REGMAP
+ select I2C
+ select I2C_DESIGNWARE_PLATFORM
+ select PHYLINK
+ select HWMON if TXGBE=y
+ select SFP
+ select GPIOLIB
+ select GPIOLIB_IRQCHIP
+ select PCS_XPCS
select LIBWX
help
This driver supports Wangxun(R) 10GbE PCI Express family of
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index ca409b4054d0..6321178fc814 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -1182,12 +1182,28 @@ static void wx_enable_sec_rx_path(struct wx *wx)
WX_WRITE_FLUSH(wx);
}
+static void wx_vlan_strip_control(struct wx *wx, bool enable)
+{
+ int i, j;
+
+ for (i = 0; i < wx->num_rx_queues; i++) {
+ struct wx_ring *ring = wx->rx_ring[i];
+
+ j = ring->reg_idx;
+ wr32m(wx, WX_PX_RR_CFG(j), WX_PX_RR_CFG_VLAN,
+ enable ? WX_PX_RR_CFG_VLAN : 0);
+ }
+}
+
void wx_set_rx_mode(struct net_device *netdev)
{
struct wx *wx = netdev_priv(netdev);
+ netdev_features_t features;
u32 fctrl, vmolr, vlnctrl;
int count;
+ features = netdev->features;
+
/* Check for Promiscuous and All Multicast modes */
fctrl = rd32(wx, WX_PSR_CTL);
fctrl &= ~(WX_PSR_CTL_UPE | WX_PSR_CTL_MPE);
@@ -1254,6 +1270,13 @@ void wx_set_rx_mode(struct net_device *netdev)
wr32(wx, WX_PSR_VLAN_CTL, vlnctrl);
wr32(wx, WX_PSR_CTL, fctrl);
wr32(wx, WX_PSR_VM_L2CTL(0), vmolr);
+
+ if ((features & NETIF_F_HW_VLAN_CTAG_RX) &&
+ (features & NETIF_F_HW_VLAN_STAG_RX))
+ wx_vlan_strip_control(wx, true);
+ else
+ wx_vlan_strip_control(wx, false);
+
}
EXPORT_SYMBOL(wx_set_rx_mode);
@@ -1462,6 +1485,16 @@ static void wx_configure_tx(struct wx *wx)
WX_MAC_TX_CFG_TE, WX_MAC_TX_CFG_TE);
}
+static void wx_restore_vlan(struct wx *wx)
+{
+ u16 vid = 1;
+
+ wx_vlan_rx_add_vid(wx->netdev, htons(ETH_P_8021Q), 0);
+
+ for_each_set_bit_from(vid, wx->active_vlans, VLAN_N_VID)
+ wx_vlan_rx_add_vid(wx->netdev, htons(ETH_P_8021Q), vid);
+}
+
/**
* wx_configure_rx - Configure Receive Unit after Reset
* @wx: pointer to private structure
@@ -1478,7 +1511,6 @@ static void wx_configure_rx(struct wx *wx)
psrtype = WX_RDB_PL_CFG_L4HDR |
WX_RDB_PL_CFG_L3HDR |
WX_RDB_PL_CFG_L2HDR |
- WX_RDB_PL_CFG_TUN_TUNHDR |
WX_RDB_PL_CFG_TUN_TUNHDR;
wr32(wx, WX_RDB_PL_CFG(0), psrtype);
@@ -1527,7 +1559,7 @@ void wx_configure(struct wx *wx)
wx_configure_port(wx);
wx_set_rx_mode(wx->netdev);
-
+ wx_restore_vlan(wx);
wx_enable_sec_rx_path(wx);
wx_configure_tx(wx);
@@ -1727,4 +1759,241 @@ int wx_sw_init(struct wx *wx)
}
EXPORT_SYMBOL(wx_sw_init);
+/**
+ * wx_find_vlvf_slot - find the vlanid or the first empty slot
+ * @wx: pointer to hardware structure
+ * @vlan: VLAN id to write to VLAN filter
+ *
+ * return the VLVF index where this VLAN id should be placed
+ *
+ **/
+static int wx_find_vlvf_slot(struct wx *wx, u32 vlan)
+{
+ u32 bits = 0, first_empty_slot = 0;
+ int regindex;
+
+ /* short cut the special case */
+ if (vlan == 0)
+ return 0;
+
+ /* Search for the vlan id in the VLVF entries. Save off the first empty
+ * slot found along the way
+ */
+ for (regindex = 1; regindex < WX_PSR_VLAN_SWC_ENTRIES; regindex++) {
+ wr32(wx, WX_PSR_VLAN_SWC_IDX, regindex);
+ bits = rd32(wx, WX_PSR_VLAN_SWC);
+ if (!bits && !(first_empty_slot))
+ first_empty_slot = regindex;
+ else if ((bits & 0x0FFF) == vlan)
+ break;
+ }
+
+ if (regindex >= WX_PSR_VLAN_SWC_ENTRIES) {
+ if (first_empty_slot)
+ regindex = first_empty_slot;
+ else
+ regindex = -ENOMEM;
+ }
+
+ return regindex;
+}
+
+/**
+ * wx_set_vlvf - Set VLAN Pool Filter
+ * @wx: pointer to hardware structure
+ * @vlan: VLAN id to write to VLAN filter
+ * @vind: VMDq output index that maps queue to VLAN id in VFVFB
+ * @vlan_on: boolean flag to turn on/off VLAN in VFVF
+ * @vfta_changed: pointer to boolean flag which indicates whether VFTA
+ * should be changed
+ *
+ * Turn on/off specified bit in VLVF table.
+ **/
+static int wx_set_vlvf(struct wx *wx, u32 vlan, u32 vind, bool vlan_on,
+ bool *vfta_changed)
+{
+ int vlvf_index;
+ u32 vt, bits;
+
+ /* If VT Mode is set
+ * Either vlan_on
+ * make sure the vlan is in VLVF
+ * set the vind bit in the matching VLVFB
+ * Or !vlan_on
+ * clear the pool bit and possibly the vind
+ */
+ vt = rd32(wx, WX_CFG_PORT_CTL);
+ if (!(vt & WX_CFG_PORT_CTL_NUM_VT_MASK))
+ return 0;
+
+ vlvf_index = wx_find_vlvf_slot(wx, vlan);
+ if (vlvf_index < 0)
+ return vlvf_index;
+
+ wr32(wx, WX_PSR_VLAN_SWC_IDX, vlvf_index);
+ if (vlan_on) {
+ /* set the pool bit */
+ if (vind < 32) {
+ bits = rd32(wx, WX_PSR_VLAN_SWC_VM_L);
+ bits |= (1 << vind);
+ wr32(wx, WX_PSR_VLAN_SWC_VM_L, bits);
+ } else {
+ bits = rd32(wx, WX_PSR_VLAN_SWC_VM_H);
+ bits |= (1 << (vind - 32));
+ wr32(wx, WX_PSR_VLAN_SWC_VM_H, bits);
+ }
+ } else {
+ /* clear the pool bit */
+ if (vind < 32) {
+ bits = rd32(wx, WX_PSR_VLAN_SWC_VM_L);
+ bits &= ~(1 << vind);
+ wr32(wx, WX_PSR_VLAN_SWC_VM_L, bits);
+ bits |= rd32(wx, WX_PSR_VLAN_SWC_VM_H);
+ } else {
+ bits = rd32(wx, WX_PSR_VLAN_SWC_VM_H);
+ bits &= ~(1 << (vind - 32));
+ wr32(wx, WX_PSR_VLAN_SWC_VM_H, bits);
+ bits |= rd32(wx, WX_PSR_VLAN_SWC_VM_L);
+ }
+ }
+
+ if (bits) {
+ wr32(wx, WX_PSR_VLAN_SWC, (WX_PSR_VLAN_SWC_VIEN | vlan));
+ if (!vlan_on && vfta_changed)
+ *vfta_changed = false;
+ } else {
+ wr32(wx, WX_PSR_VLAN_SWC, 0);
+ }
+
+ return 0;
+}
+
+/**
+ * wx_set_vfta - Set VLAN filter table
+ * @wx: pointer to hardware structure
+ * @vlan: VLAN id to write to VLAN filter
+ * @vind: VMDq output index that maps queue to VLAN id in VFVFB
+ * @vlan_on: boolean flag to turn on/off VLAN in VFVF
+ *
+ * Turn on/off specified VLAN in the VLAN filter table.
+ **/
+static int wx_set_vfta(struct wx *wx, u32 vlan, u32 vind, bool vlan_on)
+{
+ u32 bitindex, vfta, targetbit;
+ bool vfta_changed = false;
+ int regindex, ret;
+
+ /* this is a 2 part operation - first the VFTA, then the
+ * VLVF and VLVFB if VT Mode is set
+ * We don't write the VFTA until we know the VLVF part succeeded.
+ */
+
+ /* Part 1
+ * The VFTA is a bitstring made up of 128 32-bit registers
+ * that enable the particular VLAN id, much like the MTA:
+ * bits[11-5]: which register
+ * bits[4-0]: which bit in the register
+ */
+ regindex = (vlan >> 5) & 0x7F;
+ bitindex = vlan & 0x1F;
+ targetbit = (1 << bitindex);
+ /* errata 5 */
+ vfta = wx->mac.vft_shadow[regindex];
+ if (vlan_on) {
+ if (!(vfta & targetbit)) {
+ vfta |= targetbit;
+ vfta_changed = true;
+ }
+ } else {
+ if ((vfta & targetbit)) {
+ vfta &= ~targetbit;
+ vfta_changed = true;
+ }
+ }
+ /* Part 2
+ * Call wx_set_vlvf to set VLVFB and VLVF
+ */
+ ret = wx_set_vlvf(wx, vlan, vind, vlan_on, &vfta_changed);
+ if (ret != 0)
+ return ret;
+
+ if (vfta_changed)
+ wr32(wx, WX_PSR_VLAN_TBL(regindex), vfta);
+ wx->mac.vft_shadow[regindex] = vfta;
+
+ return 0;
+}
+
+/**
+ * wx_clear_vfta - Clear VLAN filter table
+ * @wx: pointer to hardware structure
+ *
+ * Clears the VLAN filer table, and the VMDq index associated with the filter
+ **/
+static void wx_clear_vfta(struct wx *wx)
+{
+ u32 offset;
+
+ for (offset = 0; offset < wx->mac.vft_size; offset++) {
+ wr32(wx, WX_PSR_VLAN_TBL(offset), 0);
+ wx->mac.vft_shadow[offset] = 0;
+ }
+
+ for (offset = 0; offset < WX_PSR_VLAN_SWC_ENTRIES; offset++) {
+ wr32(wx, WX_PSR_VLAN_SWC_IDX, offset);
+ wr32(wx, WX_PSR_VLAN_SWC, 0);
+ wr32(wx, WX_PSR_VLAN_SWC_VM_L, 0);
+ wr32(wx, WX_PSR_VLAN_SWC_VM_H, 0);
+ }
+}
+
+int wx_vlan_rx_add_vid(struct net_device *netdev,
+ __be16 proto, u16 vid)
+{
+ struct wx *wx = netdev_priv(netdev);
+
+ /* add VID to filter table */
+ wx_set_vfta(wx, vid, VMDQ_P(0), true);
+ set_bit(vid, wx->active_vlans);
+
+ return 0;
+}
+EXPORT_SYMBOL(wx_vlan_rx_add_vid);
+
+int wx_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
+{
+ struct wx *wx = netdev_priv(netdev);
+
+ /* remove VID from filter table */
+ if (vid)
+ wx_set_vfta(wx, vid, VMDQ_P(0), false);
+ clear_bit(vid, wx->active_vlans);
+
+ return 0;
+}
+EXPORT_SYMBOL(wx_vlan_rx_kill_vid);
+
+/**
+ * wx_start_hw - Prepare hardware for Tx/Rx
+ * @wx: pointer to hardware structure
+ *
+ * Starts the hardware using the generic start_hw function
+ * and the generation start_hw function.
+ * Then performs revision-specific operations, if any.
+ **/
+void wx_start_hw(struct wx *wx)
+{
+ int i;
+
+ /* Clear the VLAN filter table */
+ wx_clear_vfta(wx);
+ WX_WRITE_FLUSH(wx);
+ /* Clear the rate limiters */
+ for (i = 0; i < wx->mac.max_tx_queues; i++) {
+ wr32(wx, WX_TDM_RP_IDX, i);
+ wr32(wx, WX_TDM_RP_RATE, 0);
+ }
+}
+EXPORT_SYMBOL(wx_start_hw);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.h b/drivers/net/ethernet/wangxun/libwx/wx_hw.h
index c173c56f0ab5..1f93ca32c921 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.h
@@ -26,10 +26,13 @@ void wx_set_rx_mode(struct net_device *netdev);
int wx_change_mtu(struct net_device *netdev, int new_mtu);
void wx_disable_rx_queue(struct wx *wx, struct wx_ring *ring);
void wx_configure(struct wx *wx);
+void wx_start_hw(struct wx *wx);
int wx_disable_pcie_master(struct wx *wx);
int wx_stop_adapter(struct wx *wx);
void wx_reset_misc(struct wx *wx);
int wx_get_pcie_msix_counts(struct wx *wx, u16 *msix_count, u16 max_msix_count);
int wx_sw_init(struct wx *wx);
+int wx_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid);
+int wx_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid);
#endif /* _WX_HW_H_ */
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
index 1e8d8b7b0c62..2c3f08be8c37 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
@@ -2,14 +2,157 @@
/* Copyright (c) 2019 - 2022 Beijing WangXun Technology Co., Ltd. */
#include <linux/etherdevice.h>
+#include <net/ip6_checksum.h>
#include <net/page_pool.h>
+#include <net/inet_ecn.h>
#include <linux/iopoll.h>
+#include <linux/sctp.h>
#include <linux/pci.h>
+#include <net/tcp.h>
+#include <net/ip.h>
#include "wx_type.h"
#include "wx_lib.h"
#include "wx_hw.h"
+/* Lookup table mapping the HW PTYPE to the bit field for decoding */
+static struct wx_dec_ptype wx_ptype_lookup[256] = {
+ /* L2: mac */
+ [0x11] = WX_PTT(L2, NONE, NONE, NONE, NONE, PAY2),
+ [0x12] = WX_PTT(L2, NONE, NONE, NONE, TS, PAY2),
+ [0x13] = WX_PTT(L2, NONE, NONE, NONE, NONE, PAY2),
+ [0x14] = WX_PTT(L2, NONE, NONE, NONE, NONE, PAY2),
+ [0x15] = WX_PTT(L2, NONE, NONE, NONE, NONE, NONE),
+ [0x16] = WX_PTT(L2, NONE, NONE, NONE, NONE, PAY2),
+ [0x17] = WX_PTT(L2, NONE, NONE, NONE, NONE, NONE),
+
+ /* L2: ethertype filter */
+ [0x18 ... 0x1F] = WX_PTT(L2, NONE, NONE, NONE, NONE, NONE),
+
+ /* L3: ip non-tunnel */
+ [0x21] = WX_PTT(IP, FGV4, NONE, NONE, NONE, PAY3),
+ [0x22] = WX_PTT(IP, IPV4, NONE, NONE, NONE, PAY3),
+ [0x23] = WX_PTT(IP, IPV4, NONE, NONE, UDP, PAY4),
+ [0x24] = WX_PTT(IP, IPV4, NONE, NONE, TCP, PAY4),
+ [0x25] = WX_PTT(IP, IPV4, NONE, NONE, SCTP, PAY4),
+ [0x29] = WX_PTT(IP, FGV6, NONE, NONE, NONE, PAY3),
+ [0x2A] = WX_PTT(IP, IPV6, NONE, NONE, NONE, PAY3),
+ [0x2B] = WX_PTT(IP, IPV6, NONE, NONE, UDP, PAY3),
+ [0x2C] = WX_PTT(IP, IPV6, NONE, NONE, TCP, PAY4),
+ [0x2D] = WX_PTT(IP, IPV6, NONE, NONE, SCTP, PAY4),
+
+ /* L2: fcoe */
+ [0x30 ... 0x34] = WX_PTT(FCOE, NONE, NONE, NONE, NONE, PAY3),
+ [0x38 ... 0x3C] = WX_PTT(FCOE, NONE, NONE, NONE, NONE, PAY3),
+
+ /* IPv4 --> IPv4/IPv6 */
+ [0x81] = WX_PTT(IP, IPV4, IPIP, FGV4, NONE, PAY3),
+ [0x82] = WX_PTT(IP, IPV4, IPIP, IPV4, NONE, PAY3),
+ [0x83] = WX_PTT(IP, IPV4, IPIP, IPV4, UDP, PAY4),
+ [0x84] = WX_PTT(IP, IPV4, IPIP, IPV4, TCP, PAY4),
+ [0x85] = WX_PTT(IP, IPV4, IPIP, IPV4, SCTP, PAY4),
+ [0x89] = WX_PTT(IP, IPV4, IPIP, FGV6, NONE, PAY3),
+ [0x8A] = WX_PTT(IP, IPV4, IPIP, IPV6, NONE, PAY3),
+ [0x8B] = WX_PTT(IP, IPV4, IPIP, IPV6, UDP, PAY4),
+ [0x8C] = WX_PTT(IP, IPV4, IPIP, IPV6, TCP, PAY4),
+ [0x8D] = WX_PTT(IP, IPV4, IPIP, IPV6, SCTP, PAY4),
+
+ /* IPv4 --> GRE/NAT --> NONE/IPv4/IPv6 */
+ [0x90] = WX_PTT(IP, IPV4, IG, NONE, NONE, PAY3),
+ [0x91] = WX_PTT(IP, IPV4, IG, FGV4, NONE, PAY3),
+ [0x92] = WX_PTT(IP, IPV4, IG, IPV4, NONE, PAY3),
+ [0x93] = WX_PTT(IP, IPV4, IG, IPV4, UDP, PAY4),
+ [0x94] = WX_PTT(IP, IPV4, IG, IPV4, TCP, PAY4),
+ [0x95] = WX_PTT(IP, IPV4, IG, IPV4, SCTP, PAY4),
+ [0x99] = WX_PTT(IP, IPV4, IG, FGV6, NONE, PAY3),
+ [0x9A] = WX_PTT(IP, IPV4, IG, IPV6, NONE, PAY3),
+ [0x9B] = WX_PTT(IP, IPV4, IG, IPV6, UDP, PAY4),
+ [0x9C] = WX_PTT(IP, IPV4, IG, IPV6, TCP, PAY4),
+ [0x9D] = WX_PTT(IP, IPV4, IG, IPV6, SCTP, PAY4),
+
+ /* IPv4 --> GRE/NAT --> MAC --> NONE/IPv4/IPv6 */
+ [0xA0] = WX_PTT(IP, IPV4, IGM, NONE, NONE, PAY3),
+ [0xA1] = WX_PTT(IP, IPV4, IGM, FGV4, NONE, PAY3),
+ [0xA2] = WX_PTT(IP, IPV4, IGM, IPV4, NONE, PAY3),
+ [0xA3] = WX_PTT(IP, IPV4, IGM, IPV4, UDP, PAY4),
+ [0xA4] = WX_PTT(IP, IPV4, IGM, IPV4, TCP, PAY4),
+ [0xA5] = WX_PTT(IP, IPV4, IGM, IPV4, SCTP, PAY4),
+ [0xA9] = WX_PTT(IP, IPV4, IGM, FGV6, NONE, PAY3),
+ [0xAA] = WX_PTT(IP, IPV4, IGM, IPV6, NONE, PAY3),
+ [0xAB] = WX_PTT(IP, IPV4, IGM, IPV6, UDP, PAY4),
+ [0xAC] = WX_PTT(IP, IPV4, IGM, IPV6, TCP, PAY4),
+ [0xAD] = WX_PTT(IP, IPV4, IGM, IPV6, SCTP, PAY4),
+
+ /* IPv4 --> GRE/NAT --> MAC+VLAN --> NONE/IPv4/IPv6 */
+ [0xB0] = WX_PTT(IP, IPV4, IGMV, NONE, NONE, PAY3),
+ [0xB1] = WX_PTT(IP, IPV4, IGMV, FGV4, NONE, PAY3),
+ [0xB2] = WX_PTT(IP, IPV4, IGMV, IPV4, NONE, PAY3),
+ [0xB3] = WX_PTT(IP, IPV4, IGMV, IPV4, UDP, PAY4),
+ [0xB4] = WX_PTT(IP, IPV4, IGMV, IPV4, TCP, PAY4),
+ [0xB5] = WX_PTT(IP, IPV4, IGMV, IPV4, SCTP, PAY4),
+ [0xB9] = WX_PTT(IP, IPV4, IGMV, FGV6, NONE, PAY3),
+ [0xBA] = WX_PTT(IP, IPV4, IGMV, IPV6, NONE, PAY3),
+ [0xBB] = WX_PTT(IP, IPV4, IGMV, IPV6, UDP, PAY4),
+ [0xBC] = WX_PTT(IP, IPV4, IGMV, IPV6, TCP, PAY4),
+ [0xBD] = WX_PTT(IP, IPV4, IGMV, IPV6, SCTP, PAY4),
+
+ /* IPv6 --> IPv4/IPv6 */
+ [0xC1] = WX_PTT(IP, IPV6, IPIP, FGV4, NONE, PAY3),
+ [0xC2] = WX_PTT(IP, IPV6, IPIP, IPV4, NONE, PAY3),
+ [0xC3] = WX_PTT(IP, IPV6, IPIP, IPV4, UDP, PAY4),
+ [0xC4] = WX_PTT(IP, IPV6, IPIP, IPV4, TCP, PAY4),
+ [0xC5] = WX_PTT(IP, IPV6, IPIP, IPV4, SCTP, PAY4),
+ [0xC9] = WX_PTT(IP, IPV6, IPIP, FGV6, NONE, PAY3),
+ [0xCA] = WX_PTT(IP, IPV6, IPIP, IPV6, NONE, PAY3),
+ [0xCB] = WX_PTT(IP, IPV6, IPIP, IPV6, UDP, PAY4),
+ [0xCC] = WX_PTT(IP, IPV6, IPIP, IPV6, TCP, PAY4),
+ [0xCD] = WX_PTT(IP, IPV6, IPIP, IPV6, SCTP, PAY4),
+
+ /* IPv6 --> GRE/NAT -> NONE/IPv4/IPv6 */
+ [0xD0] = WX_PTT(IP, IPV6, IG, NONE, NONE, PAY3),
+ [0xD1] = WX_PTT(IP, IPV6, IG, FGV4, NONE, PAY3),
+ [0xD2] = WX_PTT(IP, IPV6, IG, IPV4, NONE, PAY3),
+ [0xD3] = WX_PTT(IP, IPV6, IG, IPV4, UDP, PAY4),
+ [0xD4] = WX_PTT(IP, IPV6, IG, IPV4, TCP, PAY4),
+ [0xD5] = WX_PTT(IP, IPV6, IG, IPV4, SCTP, PAY4),
+ [0xD9] = WX_PTT(IP, IPV6, IG, FGV6, NONE, PAY3),
+ [0xDA] = WX_PTT(IP, IPV6, IG, IPV6, NONE, PAY3),
+ [0xDB] = WX_PTT(IP, IPV6, IG, IPV6, UDP, PAY4),
+ [0xDC] = WX_PTT(IP, IPV6, IG, IPV6, TCP, PAY4),
+ [0xDD] = WX_PTT(IP, IPV6, IG, IPV6, SCTP, PAY4),
+
+ /* IPv6 --> GRE/NAT -> MAC -> NONE/IPv4/IPv6 */
+ [0xE0] = WX_PTT(IP, IPV6, IGM, NONE, NONE, PAY3),
+ [0xE1] = WX_PTT(IP, IPV6, IGM, FGV4, NONE, PAY3),
+ [0xE2] = WX_PTT(IP, IPV6, IGM, IPV4, NONE, PAY3),
+ [0xE3] = WX_PTT(IP, IPV6, IGM, IPV4, UDP, PAY4),
+ [0xE4] = WX_PTT(IP, IPV6, IGM, IPV4, TCP, PAY4),
+ [0xE5] = WX_PTT(IP, IPV6, IGM, IPV4, SCTP, PAY4),
+ [0xE9] = WX_PTT(IP, IPV6, IGM, FGV6, NONE, PAY3),
+ [0xEA] = WX_PTT(IP, IPV6, IGM, IPV6, NONE, PAY3),
+ [0xEB] = WX_PTT(IP, IPV6, IGM, IPV6, UDP, PAY4),
+ [0xEC] = WX_PTT(IP, IPV6, IGM, IPV6, TCP, PAY4),
+ [0xED] = WX_PTT(IP, IPV6, IGM, IPV6, SCTP, PAY4),
+
+ /* IPv6 --> GRE/NAT -> MAC--> NONE/IPv */
+ [0xF0] = WX_PTT(IP, IPV6, IGMV, NONE, NONE, PAY3),
+ [0xF1] = WX_PTT(IP, IPV6, IGMV, FGV4, NONE, PAY3),
+ [0xF2] = WX_PTT(IP, IPV6, IGMV, IPV4, NONE, PAY3),
+ [0xF3] = WX_PTT(IP, IPV6, IGMV, IPV4, UDP, PAY4),
+ [0xF4] = WX_PTT(IP, IPV6, IGMV, IPV4, TCP, PAY4),
+ [0xF5] = WX_PTT(IP, IPV6, IGMV, IPV4, SCTP, PAY4),
+ [0xF9] = WX_PTT(IP, IPV6, IGMV, FGV6, NONE, PAY3),
+ [0xFA] = WX_PTT(IP, IPV6, IGMV, IPV6, NONE, PAY3),
+ [0xFB] = WX_PTT(IP, IPV6, IGMV, IPV6, UDP, PAY4),
+ [0xFC] = WX_PTT(IP, IPV6, IGMV, IPV6, TCP, PAY4),
+ [0xFD] = WX_PTT(IP, IPV6, IGMV, IPV6, SCTP, PAY4),
+};
+
+static struct wx_dec_ptype wx_decode_ptype(const u8 ptype)
+{
+ return wx_ptype_lookup[ptype];
+}
+
/* wx_test_staterr - tests bits in Rx descriptor status and error fields */
static __le32 wx_test_staterr(union wx_rx_desc *rx_desc,
const u32 stat_err_bits)
@@ -419,6 +562,116 @@ static bool wx_cleanup_headers(struct wx_ring *rx_ring,
return false;
}
+static void wx_rx_hash(struct wx_ring *ring,
+ union wx_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ u16 rss_type;
+
+ if (!(ring->netdev->features & NETIF_F_RXHASH))
+ return;
+
+ rss_type = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info) &
+ WX_RXD_RSSTYPE_MASK;
+
+ if (!rss_type)
+ return;
+
+ skb_set_hash(skb, le32_to_cpu(rx_desc->wb.lower.hi_dword.rss),
+ (WX_RSS_L4_TYPES_MASK & (1ul << rss_type)) ?
+ PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3);
+}
+
+/**
+ * wx_rx_checksum - indicate in skb if hw indicated a good cksum
+ * @ring: structure containing ring specific data
+ * @rx_desc: current Rx descriptor being processed
+ * @skb: skb currently being received and modified
+ **/
+static void wx_rx_checksum(struct wx_ring *ring,
+ union wx_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ struct wx_dec_ptype dptype = wx_decode_ptype(WX_RXD_PKTTYPE(rx_desc));
+
+ skb_checksum_none_assert(skb);
+ /* Rx csum disabled */
+ if (!(ring->netdev->features & NETIF_F_RXCSUM))
+ return;
+
+ /* if IPv4 header checksum error */
+ if ((wx_test_staterr(rx_desc, WX_RXD_STAT_IPCS) &&
+ wx_test_staterr(rx_desc, WX_RXD_ERR_IPE)) ||
+ (wx_test_staterr(rx_desc, WX_RXD_STAT_OUTERIPCS) &&
+ wx_test_staterr(rx_desc, WX_RXD_ERR_OUTERIPER))) {
+ ring->rx_stats.csum_err++;
+ return;
+ }
+
+ /* L4 checksum offload flag must set for the below code to work */
+ if (!wx_test_staterr(rx_desc, WX_RXD_STAT_L4CS))
+ return;
+
+ /* Hardware can't guarantee csum if IPv6 Dest Header found */
+ if (dptype.prot != WX_DEC_PTYPE_PROT_SCTP && WX_RXD_IPV6EX(rx_desc))
+ return;
+
+ /* if L4 checksum error */
+ if (wx_test_staterr(rx_desc, WX_RXD_ERR_TCPE)) {
+ ring->rx_stats.csum_err++;
+ return;
+ }
+
+ /* It must be a TCP or UDP or SCTP packet with a valid checksum */
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ /* If there is an outer header present that might contain a checksum
+ * we need to bump the checksum level by 1 to reflect the fact that
+ * we are indicating we validated the inner checksum.
+ */
+ if (dptype.etype >= WX_DEC_PTYPE_ETYPE_IG)
+ __skb_incr_checksum_unnecessary(skb);
+ ring->rx_stats.csum_good_cnt++;
+}
+
+static void wx_rx_vlan(struct wx_ring *ring, union wx_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ u16 ethertype;
+ u8 idx = 0;
+
+ if ((ring->netdev->features &
+ (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)) &&
+ wx_test_staterr(rx_desc, WX_RXD_STAT_VP)) {
+ idx = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info) &
+ 0x1c0) >> 6;
+ ethertype = ring->q_vector->wx->tpid[idx];
+ __vlan_hwaccel_put_tag(skb, htons(ethertype),
+ le16_to_cpu(rx_desc->wb.upper.vlan));
+ }
+}
+
+/**
+ * wx_process_skb_fields - Populate skb header fields from Rx descriptor
+ * @rx_ring: rx descriptor ring packet is being transacted on
+ * @rx_desc: pointer to the EOP Rx descriptor
+ * @skb: pointer to current skb being populated
+ *
+ * This function checks the ring, descriptor, and packet information in
+ * order to populate the hash, checksum, protocol, and
+ * other fields within the skb.
+ **/
+static void wx_process_skb_fields(struct wx_ring *rx_ring,
+ union wx_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ wx_rx_hash(rx_ring, rx_desc, skb);
+ wx_rx_checksum(rx_ring, rx_desc, skb);
+ wx_rx_vlan(rx_ring, rx_desc, skb);
+ skb_record_rx_queue(skb, rx_ring->queue_index);
+ skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+}
+
/**
* wx_clean_rx_irq - Clean completed descriptors from Rx ring - bounce buf
* @q_vector: structure containing interrupt and ring information
@@ -486,8 +739,8 @@ static int wx_clean_rx_irq(struct wx_q_vector *q_vector,
/* probably a little skewed due to removing CRC */
total_rx_bytes += skb->len;
- skb_record_rx_queue(skb, rx_ring->queue_index);
- skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+ /* populate checksum, timestamp, VLAN, and protocol */
+ wx_process_skb_fields(rx_ring, rx_desc, skb);
napi_gro_receive(&q_vector->napi, skb);
/* update budget accounting */
@@ -707,11 +960,50 @@ static int wx_maybe_stop_tx(struct wx_ring *tx_ring, u16 size)
return 0;
}
+static u32 wx_tx_cmd_type(u32 tx_flags)
+{
+ /* set type for advanced descriptor with frame checksum insertion */
+ u32 cmd_type = WX_TXD_DTYP_DATA | WX_TXD_IFCS;
+
+ /* set HW vlan bit if vlan is present */
+ cmd_type |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_HW_VLAN, WX_TXD_VLE);
+ /* set segmentation enable bits for TSO/FSO */
+ cmd_type |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_TSO, WX_TXD_TSE);
+ /* set timestamp bit if present */
+ cmd_type |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_TSTAMP, WX_TXD_MAC_TSTAMP);
+ cmd_type |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_LINKSEC, WX_TXD_LINKSEC);
+
+ return cmd_type;
+}
+
+static void wx_tx_olinfo_status(union wx_tx_desc *tx_desc,
+ u32 tx_flags, unsigned int paylen)
+{
+ u32 olinfo_status = paylen << WX_TXD_PAYLEN_SHIFT;
+
+ /* enable L4 checksum for TSO and TX checksum offload */
+ olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_CSUM, WX_TXD_L4CS);
+ /* enable IPv4 checksum for TSO */
+ olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_IPV4, WX_TXD_IIPCS);
+ /* enable outer IPv4 checksum for TSO */
+ olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_OUTER_IPV4,
+ WX_TXD_EIPCS);
+ /* Check Context must be set if Tx switch is enabled, which it
+ * always is for case where virtual functions are running
+ */
+ olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_CC, WX_TXD_CC);
+ olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_IPSEC,
+ WX_TXD_IPSEC);
+ tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
+}
+
static void wx_tx_map(struct wx_ring *tx_ring,
- struct wx_tx_buffer *first)
+ struct wx_tx_buffer *first,
+ const u8 hdr_len)
{
struct sk_buff *skb = first->skb;
struct wx_tx_buffer *tx_buffer;
+ u32 tx_flags = first->tx_flags;
u16 i = tx_ring->next_to_use;
unsigned int data_len, size;
union wx_tx_desc *tx_desc;
@@ -719,10 +1011,9 @@ static void wx_tx_map(struct wx_ring *tx_ring,
dma_addr_t dma;
u32 cmd_type;
- cmd_type = WX_TXD_DTYP_DATA | WX_TXD_IFCS;
+ cmd_type = wx_tx_cmd_type(tx_flags);
tx_desc = WX_TX_DESC(tx_ring, i);
-
- tx_desc->read.olinfo_status = cpu_to_le32(skb->len << WX_TXD_PAYLEN_SHIFT);
+ wx_tx_olinfo_status(tx_desc, tx_flags, skb->len - hdr_len);
size = skb_headlen(skb);
data_len = skb->data_len;
@@ -838,12 +1129,399 @@ dma_error:
tx_ring->next_to_use = i;
}
+static void wx_tx_ctxtdesc(struct wx_ring *tx_ring, u32 vlan_macip_lens,
+ u32 fcoe_sof_eof, u32 type_tucmd, u32 mss_l4len_idx)
+{
+ struct wx_tx_context_desc *context_desc;
+ u16 i = tx_ring->next_to_use;
+
+ context_desc = WX_TX_CTXTDESC(tx_ring, i);
+ i++;
+ tx_ring->next_to_use = (i < tx_ring->count) ? i : 0;
+
+ /* set bits to identify this as an advanced context descriptor */
+ type_tucmd |= WX_TXD_DTYP_CTXT;
+ context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
+ context_desc->seqnum_seed = cpu_to_le32(fcoe_sof_eof);
+ context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd);
+ context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
+}
+
+static void wx_get_ipv6_proto(struct sk_buff *skb, int offset, u8 *nexthdr)
+{
+ struct ipv6hdr *hdr = (struct ipv6hdr *)(skb->data + offset);
+
+ *nexthdr = hdr->nexthdr;
+ offset += sizeof(struct ipv6hdr);
+ while (ipv6_ext_hdr(*nexthdr)) {
+ struct ipv6_opt_hdr _hdr, *hp;
+
+ if (*nexthdr == NEXTHDR_NONE)
+ return;
+ hp = skb_header_pointer(skb, offset, sizeof(_hdr), &_hdr);
+ if (!hp)
+ return;
+ if (*nexthdr == NEXTHDR_FRAGMENT)
+ break;
+ *nexthdr = hp->nexthdr;
+ }
+}
+
+union network_header {
+ struct iphdr *ipv4;
+ struct ipv6hdr *ipv6;
+ void *raw;
+};
+
+static u8 wx_encode_tx_desc_ptype(const struct wx_tx_buffer *first)
+{
+ u8 tun_prot = 0, l4_prot = 0, ptype = 0;
+ struct sk_buff *skb = first->skb;
+
+ if (skb->encapsulation) {
+ union network_header hdr;
+
+ switch (first->protocol) {
+ case htons(ETH_P_IP):
+ tun_prot = ip_hdr(skb)->protocol;
+ ptype = WX_PTYPE_TUN_IPV4;
+ break;
+ case htons(ETH_P_IPV6):
+ wx_get_ipv6_proto(skb, skb_network_offset(skb), &tun_prot);
+ ptype = WX_PTYPE_TUN_IPV6;
+ break;
+ default:
+ return ptype;
+ }
+
+ if (tun_prot == IPPROTO_IPIP) {
+ hdr.raw = (void *)inner_ip_hdr(skb);
+ ptype |= WX_PTYPE_PKT_IPIP;
+ } else if (tun_prot == IPPROTO_UDP) {
+ hdr.raw = (void *)inner_ip_hdr(skb);
+ if (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
+ skb->inner_protocol != htons(ETH_P_TEB)) {
+ ptype |= WX_PTYPE_PKT_IG;
+ } else {
+ if (((struct ethhdr *)skb_inner_mac_header(skb))->h_proto
+ == htons(ETH_P_8021Q))
+ ptype |= WX_PTYPE_PKT_IGMV;
+ else
+ ptype |= WX_PTYPE_PKT_IGM;
+ }
+
+ } else if (tun_prot == IPPROTO_GRE) {
+ hdr.raw = (void *)inner_ip_hdr(skb);
+ if (skb->inner_protocol == htons(ETH_P_IP) ||
+ skb->inner_protocol == htons(ETH_P_IPV6)) {
+ ptype |= WX_PTYPE_PKT_IG;
+ } else {
+ if (((struct ethhdr *)skb_inner_mac_header(skb))->h_proto
+ == htons(ETH_P_8021Q))
+ ptype |= WX_PTYPE_PKT_IGMV;
+ else
+ ptype |= WX_PTYPE_PKT_IGM;
+ }
+ } else {
+ return ptype;
+ }
+
+ switch (hdr.ipv4->version) {
+ case IPVERSION:
+ l4_prot = hdr.ipv4->protocol;
+ break;
+ case 6:
+ wx_get_ipv6_proto(skb, skb_inner_network_offset(skb), &l4_prot);
+ ptype |= WX_PTYPE_PKT_IPV6;
+ break;
+ default:
+ return ptype;
+ }
+ } else {
+ switch (first->protocol) {
+ case htons(ETH_P_IP):
+ l4_prot = ip_hdr(skb)->protocol;
+ ptype = WX_PTYPE_PKT_IP;
+ break;
+ case htons(ETH_P_IPV6):
+ wx_get_ipv6_proto(skb, skb_network_offset(skb), &l4_prot);
+ ptype = WX_PTYPE_PKT_IP | WX_PTYPE_PKT_IPV6;
+ break;
+ default:
+ return WX_PTYPE_PKT_MAC | WX_PTYPE_TYP_MAC;
+ }
+ }
+ switch (l4_prot) {
+ case IPPROTO_TCP:
+ ptype |= WX_PTYPE_TYP_TCP;
+ break;
+ case IPPROTO_UDP:
+ ptype |= WX_PTYPE_TYP_UDP;
+ break;
+ case IPPROTO_SCTP:
+ ptype |= WX_PTYPE_TYP_SCTP;
+ break;
+ default:
+ ptype |= WX_PTYPE_TYP_IP;
+ break;
+ }
+
+ return ptype;
+}
+
+static int wx_tso(struct wx_ring *tx_ring, struct wx_tx_buffer *first,
+ u8 *hdr_len, u8 ptype)
+{
+ u32 vlan_macip_lens, type_tucmd, mss_l4len_idx;
+ struct net_device *netdev = tx_ring->netdev;
+ u32 l4len, tunhdr_eiplen_tunlen = 0;
+ struct sk_buff *skb = first->skb;
+ bool enc = skb->encapsulation;
+ struct ipv6hdr *ipv6h;
+ struct tcphdr *tcph;
+ struct iphdr *iph;
+ u8 tun_prot = 0;
+ int err;
+
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ return 0;
+
+ if (!skb_is_gso(skb))
+ return 0;
+
+ err = skb_cow_head(skb, 0);
+ if (err < 0)
+ return err;
+
+ /* indicates the inner headers in the skbuff are valid. */
+ iph = enc ? inner_ip_hdr(skb) : ip_hdr(skb);
+ if (iph->version == 4) {
+ tcph = enc ? inner_tcp_hdr(skb) : tcp_hdr(skb);
+ iph->tot_len = 0;
+ iph->check = 0;
+ tcph->check = ~csum_tcpudp_magic(iph->saddr,
+ iph->daddr, 0,
+ IPPROTO_TCP, 0);
+ first->tx_flags |= WX_TX_FLAGS_TSO |
+ WX_TX_FLAGS_CSUM |
+ WX_TX_FLAGS_IPV4 |
+ WX_TX_FLAGS_CC;
+ } else if (iph->version == 6 && skb_is_gso_v6(skb)) {
+ ipv6h = enc ? inner_ipv6_hdr(skb) : ipv6_hdr(skb);
+ tcph = enc ? inner_tcp_hdr(skb) : tcp_hdr(skb);
+ ipv6h->payload_len = 0;
+ tcph->check = ~csum_ipv6_magic(&ipv6h->saddr,
+ &ipv6h->daddr, 0,
+ IPPROTO_TCP, 0);
+ first->tx_flags |= WX_TX_FLAGS_TSO |
+ WX_TX_FLAGS_CSUM |
+ WX_TX_FLAGS_CC;
+ }
+
+ /* compute header lengths */
+ l4len = enc ? inner_tcp_hdrlen(skb) : tcp_hdrlen(skb);
+ *hdr_len = enc ? (skb_inner_transport_header(skb) - skb->data) :
+ skb_transport_offset(skb);
+ *hdr_len += l4len;
+
+ /* update gso size and bytecount with header size */
+ first->gso_segs = skb_shinfo(skb)->gso_segs;
+ first->bytecount += (first->gso_segs - 1) * *hdr_len;
+
+ /* mss_l4len_id: use 0 as index for TSO */
+ mss_l4len_idx = l4len << WX_TXD_L4LEN_SHIFT;
+ mss_l4len_idx |= skb_shinfo(skb)->gso_size << WX_TXD_MSS_SHIFT;
+
+ /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
+ if (enc) {
+ switch (first->protocol) {
+ case htons(ETH_P_IP):
+ tun_prot = ip_hdr(skb)->protocol;
+ first->tx_flags |= WX_TX_FLAGS_OUTER_IPV4;
+ break;
+ case htons(ETH_P_IPV6):
+ tun_prot = ipv6_hdr(skb)->nexthdr;
+ break;
+ default:
+ break;
+ }
+ switch (tun_prot) {
+ case IPPROTO_UDP:
+ tunhdr_eiplen_tunlen = WX_TXD_TUNNEL_UDP;
+ tunhdr_eiplen_tunlen |= ((skb_network_header_len(skb) >> 2) <<
+ WX_TXD_OUTER_IPLEN_SHIFT) |
+ (((skb_inner_mac_header(skb) -
+ skb_transport_header(skb)) >> 1) <<
+ WX_TXD_TUNNEL_LEN_SHIFT);
+ break;
+ case IPPROTO_GRE:
+ tunhdr_eiplen_tunlen = WX_TXD_TUNNEL_GRE;
+ tunhdr_eiplen_tunlen |= ((skb_network_header_len(skb) >> 2) <<
+ WX_TXD_OUTER_IPLEN_SHIFT) |
+ (((skb_inner_mac_header(skb) -
+ skb_transport_header(skb)) >> 1) <<
+ WX_TXD_TUNNEL_LEN_SHIFT);
+ break;
+ case IPPROTO_IPIP:
+ tunhdr_eiplen_tunlen = (((char *)inner_ip_hdr(skb) -
+ (char *)ip_hdr(skb)) >> 2) <<
+ WX_TXD_OUTER_IPLEN_SHIFT;
+ break;
+ default:
+ break;
+ }
+ vlan_macip_lens = skb_inner_network_header_len(skb) >> 1;
+ } else {
+ vlan_macip_lens = skb_network_header_len(skb) >> 1;
+ }
+
+ vlan_macip_lens |= skb_network_offset(skb) << WX_TXD_MACLEN_SHIFT;
+ vlan_macip_lens |= first->tx_flags & WX_TX_FLAGS_VLAN_MASK;
+
+ type_tucmd = ptype << 24;
+ if (skb->vlan_proto == htons(ETH_P_8021AD) &&
+ netdev->features & NETIF_F_HW_VLAN_STAG_TX)
+ type_tucmd |= WX_SET_FLAG(first->tx_flags,
+ WX_TX_FLAGS_HW_VLAN,
+ 0x1 << WX_TXD_TAG_TPID_SEL_SHIFT);
+ wx_tx_ctxtdesc(tx_ring, vlan_macip_lens, tunhdr_eiplen_tunlen,
+ type_tucmd, mss_l4len_idx);
+
+ return 1;
+}
+
+static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first,
+ u8 ptype)
+{
+ u32 tunhdr_eiplen_tunlen = 0, vlan_macip_lens = 0;
+ struct net_device *netdev = tx_ring->netdev;
+ u32 mss_l4len_idx = 0, type_tucmd;
+ struct sk_buff *skb = first->skb;
+ u8 tun_prot = 0;
+
+ if (skb->ip_summed != CHECKSUM_PARTIAL) {
+ if (!(first->tx_flags & WX_TX_FLAGS_HW_VLAN) &&
+ !(first->tx_flags & WX_TX_FLAGS_CC))
+ return;
+ vlan_macip_lens = skb_network_offset(skb) <<
+ WX_TXD_MACLEN_SHIFT;
+ } else {
+ u8 l4_prot = 0;
+ union {
+ struct iphdr *ipv4;
+ struct ipv6hdr *ipv6;
+ u8 *raw;
+ } network_hdr;
+ union {
+ struct tcphdr *tcphdr;
+ u8 *raw;
+ } transport_hdr;
+
+ if (skb->encapsulation) {
+ network_hdr.raw = skb_inner_network_header(skb);
+ transport_hdr.raw = skb_inner_transport_header(skb);
+ vlan_macip_lens = skb_network_offset(skb) <<
+ WX_TXD_MACLEN_SHIFT;
+ switch (first->protocol) {
+ case htons(ETH_P_IP):
+ tun_prot = ip_hdr(skb)->protocol;
+ break;
+ case htons(ETH_P_IPV6):
+ tun_prot = ipv6_hdr(skb)->nexthdr;
+ break;
+ default:
+ return;
+ }
+ switch (tun_prot) {
+ case IPPROTO_UDP:
+ tunhdr_eiplen_tunlen = WX_TXD_TUNNEL_UDP;
+ tunhdr_eiplen_tunlen |=
+ ((skb_network_header_len(skb) >> 2) <<
+ WX_TXD_OUTER_IPLEN_SHIFT) |
+ (((skb_inner_mac_header(skb) -
+ skb_transport_header(skb)) >> 1) <<
+ WX_TXD_TUNNEL_LEN_SHIFT);
+ break;
+ case IPPROTO_GRE:
+ tunhdr_eiplen_tunlen = WX_TXD_TUNNEL_GRE;
+ tunhdr_eiplen_tunlen |= ((skb_network_header_len(skb) >> 2) <<
+ WX_TXD_OUTER_IPLEN_SHIFT) |
+ (((skb_inner_mac_header(skb) -
+ skb_transport_header(skb)) >> 1) <<
+ WX_TXD_TUNNEL_LEN_SHIFT);
+ break;
+ case IPPROTO_IPIP:
+ tunhdr_eiplen_tunlen = (((char *)inner_ip_hdr(skb) -
+ (char *)ip_hdr(skb)) >> 2) <<
+ WX_TXD_OUTER_IPLEN_SHIFT;
+ break;
+ default:
+ break;
+ }
+
+ } else {
+ network_hdr.raw = skb_network_header(skb);
+ transport_hdr.raw = skb_transport_header(skb);
+ vlan_macip_lens = skb_network_offset(skb) <<
+ WX_TXD_MACLEN_SHIFT;
+ }
+
+ switch (network_hdr.ipv4->version) {
+ case IPVERSION:
+ vlan_macip_lens |= (transport_hdr.raw - network_hdr.raw) >> 1;
+ l4_prot = network_hdr.ipv4->protocol;
+ break;
+ case 6:
+ vlan_macip_lens |= (transport_hdr.raw - network_hdr.raw) >> 1;
+ l4_prot = network_hdr.ipv6->nexthdr;
+ break;
+ default:
+ break;
+ }
+
+ switch (l4_prot) {
+ case IPPROTO_TCP:
+ mss_l4len_idx = (transport_hdr.tcphdr->doff * 4) <<
+ WX_TXD_L4LEN_SHIFT;
+ break;
+ case IPPROTO_SCTP:
+ mss_l4len_idx = sizeof(struct sctphdr) <<
+ WX_TXD_L4LEN_SHIFT;
+ break;
+ case IPPROTO_UDP:
+ mss_l4len_idx = sizeof(struct udphdr) <<
+ WX_TXD_L4LEN_SHIFT;
+ break;
+ default:
+ break;
+ }
+
+ /* update TX checksum flag */
+ first->tx_flags |= WX_TX_FLAGS_CSUM;
+ }
+ first->tx_flags |= WX_TX_FLAGS_CC;
+ /* vlan_macip_lens: MACLEN, VLAN tag */
+ vlan_macip_lens |= first->tx_flags & WX_TX_FLAGS_VLAN_MASK;
+
+ type_tucmd = ptype << 24;
+ if (skb->vlan_proto == htons(ETH_P_8021AD) &&
+ netdev->features & NETIF_F_HW_VLAN_STAG_TX)
+ type_tucmd |= WX_SET_FLAG(first->tx_flags,
+ WX_TX_FLAGS_HW_VLAN,
+ 0x1 << WX_TXD_TAG_TPID_SEL_SHIFT);
+ wx_tx_ctxtdesc(tx_ring, vlan_macip_lens, tunhdr_eiplen_tunlen,
+ type_tucmd, mss_l4len_idx);
+}
+
static netdev_tx_t wx_xmit_frame_ring(struct sk_buff *skb,
struct wx_ring *tx_ring)
{
u16 count = TXD_USE_COUNT(skb_headlen(skb));
struct wx_tx_buffer *first;
+ u8 hdr_len = 0, ptype;
unsigned short f;
+ u32 tx_flags = 0;
+ int tso;
/* need: 1 descriptor per page * PAGE_SIZE/WX_MAX_DATA_PER_TXD,
* + 1 desc for skb_headlen/WX_MAX_DATA_PER_TXD,
@@ -864,7 +1542,29 @@ static netdev_tx_t wx_xmit_frame_ring(struct sk_buff *skb,
first->bytecount = skb->len;
first->gso_segs = 1;
- wx_tx_map(tx_ring, first);
+ /* if we have a HW VLAN tag being added default to the HW one */
+ if (skb_vlan_tag_present(skb)) {
+ tx_flags |= skb_vlan_tag_get(skb) << WX_TX_FLAGS_VLAN_SHIFT;
+ tx_flags |= WX_TX_FLAGS_HW_VLAN;
+ }
+
+ /* record initial flags and protocol */
+ first->tx_flags = tx_flags;
+ first->protocol = vlan_get_protocol(skb);
+
+ ptype = wx_encode_tx_desc_ptype(first);
+
+ tso = wx_tso(tx_ring, first, &hdr_len, ptype);
+ if (tso < 0)
+ goto out_drop;
+ else if (!tso)
+ wx_tx_csum(tx_ring, first, ptype);
+ wx_tx_map(tx_ring, first, hdr_len);
+
+ return NETDEV_TX_OK;
+out_drop:
+ dev_kfree_skb_any(first->skb);
+ first->skb = NULL;
return NETDEV_TX_OK;
}
@@ -1348,7 +2048,8 @@ void wx_free_irq(struct wx *wx)
free_irq(entry->vector, q_vector);
}
- free_irq(wx->msix_entries[vector].vector, wx);
+ if (wx->mac.type == wx_mac_em)
+ free_irq(wx->msix_entries[vector].vector, wx);
}
EXPORT_SYMBOL(wx_free_irq);
@@ -2004,4 +2705,24 @@ void wx_get_stats64(struct net_device *netdev,
}
EXPORT_SYMBOL(wx_get_stats64);
+int wx_set_features(struct net_device *netdev, netdev_features_t features)
+{
+ netdev_features_t changed = netdev->features ^ features;
+ struct wx *wx = netdev_priv(netdev);
+
+ if (changed & NETIF_F_RXHASH)
+ wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN,
+ WX_RDB_RA_CTL_RSS_EN);
+ else
+ wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN, 0);
+
+ if (changed &
+ (NETIF_F_HW_VLAN_CTAG_RX |
+ NETIF_F_HW_VLAN_STAG_RX))
+ wx_set_rx_mode(netdev);
+
+ return 1;
+}
+EXPORT_SYMBOL(wx_set_features);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.h b/drivers/net/ethernet/wangxun/libwx/wx_lib.h
index 50ee41f1fa10..df1f4a5951f0 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.h
@@ -28,5 +28,6 @@ void wx_free_resources(struct wx *wx);
int wx_setup_resources(struct wx *wx);
void wx_get_stats64(struct net_device *netdev,
struct rtnl_link_stats64 *stats);
+int wx_set_features(struct net_device *netdev, netdev_features_t features);
#endif /* _NGBE_LIB_H_ */
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index 32f952d93009..29dfb561887d 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -6,6 +6,8 @@
#include <linux/bitfield.h>
#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <net/ip.h>
#define WX_NCSI_SUP 0x8000
#define WX_NCSI_MASK 0x8000
@@ -64,6 +66,8 @@
#define WX_CFG_PORT_CTL_QINQ BIT(2)
#define WX_CFG_PORT_CTL_D_VLAN BIT(0) /* double vlan*/
#define WX_CFG_TAG_TPID(_i) (0x14430 + ((_i) * 4))
+#define WX_CFG_PORT_CTL_NUM_VT_MASK GENMASK(13, 12) /* number of TVs */
+
/* GPIO Registers */
#define WX_GPIO_DR 0x14800
@@ -79,7 +83,9 @@
#define WX_GPIO_INTMASK 0x14834
#define WX_GPIO_INTTYPE_LEVEL 0x14838
#define WX_GPIO_POLARITY 0x1483C
+#define WX_GPIO_INTSTATUS 0x14844
#define WX_GPIO_EOI 0x1484C
+#define WX_GPIO_EXT 0x14850
/*********************** Transmit DMA registers **************************/
/* transmit global control */
@@ -87,6 +93,8 @@
/* TDM CTL BIT */
#define WX_TDM_CTL_TE BIT(0) /* Transmit Enable */
#define WX_TDM_PB_THRE(_i) (0x18020 + ((_i) * 4))
+#define WX_TDM_RP_IDX 0x1820C
+#define WX_TDM_RP_RATE 0x18404
/***************************** RDB registers *********************************/
/* receive packet buffer */
@@ -105,6 +113,8 @@
#define WX_RDB_PL_CFG_L2HDR BIT(3)
#define WX_RDB_PL_CFG_TUN_TUNHDR BIT(4)
#define WX_RDB_PL_CFG_TUN_OUTL2HDR BIT(5)
+#define WX_RDB_RA_CTL 0x194F4
+#define WX_RDB_RA_CTL_RSS_EN BIT(2) /* RSS Enable */
/******************************* PSR Registers *******************************/
/* psr control */
@@ -150,6 +160,9 @@
#define WX_PSR_LAN_FLEX_DW_H(_i) (0x15C04 + ((_i) * 16))
#define WX_PSR_LAN_FLEX_MSK(_i) (0x15C08 + ((_i) * 16))
+/* vlan tbl */
+#define WX_PSR_VLAN_TBL(_i) (0x16000 + ((_i) * 4))
+
/* mac switcher */
#define WX_PSR_MAC_SWC_AD_L 0x16200
#define WX_PSR_MAC_SWC_AD_H 0x16204
@@ -161,6 +174,15 @@
#define WX_PSR_MAC_SWC_IDX 0x16210
#define WX_CLEAR_VMDQ_ALL 0xFFFFFFFFU
+/* vlan switch */
+#define WX_PSR_VLAN_SWC 0x16220
+#define WX_PSR_VLAN_SWC_VM_L 0x16224
+#define WX_PSR_VLAN_SWC_VM_H 0x16228
+#define WX_PSR_VLAN_SWC_IDX 0x16230 /* 64 vlan entries */
+/* VLAN pool filtering masks */
+#define WX_PSR_VLAN_SWC_VIEN BIT(31) /* filter is valid */
+#define WX_PSR_VLAN_SWC_ENTRIES 64
+
/********************************* RSEC **************************************/
/* general rsec */
#define WX_RSC_CTL 0x17000
@@ -255,6 +277,7 @@
#define WX_PX_RR_RP(_i) (0x0100C + ((_i) * 0x40))
#define WX_PX_RR_CFG(_i) (0x01010 + ((_i) * 0x40))
/* PX_RR_CFG bit definitions */
+#define WX_PX_RR_CFG_VLAN BIT(31)
#define WX_PX_RR_CFG_SPLIT_MODE BIT(26)
#define WX_PX_RR_CFG_RR_THER_SHIFT 16
#define WX_PX_RR_CFG_RR_HDR_SZ GENMASK(15, 12)
@@ -296,6 +319,7 @@
#define WX_MAX_TXD 8192
#define WX_MAX_JUMBO_FRAME_SIZE 9432 /* max payload 9414 */
+#define VMDQ_P(p) p
/* Supported Rx Buffer Sizes */
#define WX_RXBUFFER_256 256 /* Used for skb receive header */
@@ -315,17 +339,64 @@
#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), WX_MAX_DATA_PER_TXD)
#define DESC_NEEDED (MAX_SKB_FRAGS + 4)
-/* Ether Types */
-#define WX_ETH_P_CNM 0x22E7
-
#define WX_CFG_PORT_ST 0x14404
/******************* Receive Descriptor bit definitions **********************/
#define WX_RXD_STAT_DD BIT(0) /* Done */
#define WX_RXD_STAT_EOP BIT(1) /* End of Packet */
+#define WX_RXD_STAT_VP BIT(5) /* IEEE VLAN Pkt */
+#define WX_RXD_STAT_L4CS BIT(7) /* L4 xsum calculated */
+#define WX_RXD_STAT_IPCS BIT(8) /* IP xsum calculated */
+#define WX_RXD_STAT_OUTERIPCS BIT(10) /* Cloud IP xsum calculated*/
+#define WX_RXD_ERR_OUTERIPER BIT(26) /* CRC IP Header error */
#define WX_RXD_ERR_RXE BIT(29) /* Any MAC Error */
-
+#define WX_RXD_ERR_TCPE BIT(30) /* TCP/UDP Checksum Error */
+#define WX_RXD_ERR_IPE BIT(31) /* IP Checksum Error */
+
+/* RSS Hash results */
+#define WX_RXD_RSSTYPE_MASK GENMASK(3, 0)
+#define WX_RXD_RSSTYPE_IPV4_TCP 0x00000001U
+#define WX_RXD_RSSTYPE_IPV6_TCP 0x00000003U
+#define WX_RXD_RSSTYPE_IPV4_SCTP 0x00000004U
+#define WX_RXD_RSSTYPE_IPV6_SCTP 0x00000006U
+#define WX_RXD_RSSTYPE_IPV4_UDP 0x00000007U
+#define WX_RXD_RSSTYPE_IPV6_UDP 0x00000008U
+
+#define WX_RSS_L4_TYPES_MASK \
+ ((1ul << WX_RXD_RSSTYPE_IPV4_TCP) | \
+ (1ul << WX_RXD_RSSTYPE_IPV4_UDP) | \
+ (1ul << WX_RXD_RSSTYPE_IPV4_SCTP) | \
+ (1ul << WX_RXD_RSSTYPE_IPV6_TCP) | \
+ (1ul << WX_RXD_RSSTYPE_IPV6_UDP) | \
+ (1ul << WX_RXD_RSSTYPE_IPV6_SCTP))
+/* TUN */
+#define WX_PTYPE_TUN_IPV4 0x80
+#define WX_PTYPE_TUN_IPV6 0xC0
+
+/* PKT for TUN */
+#define WX_PTYPE_PKT_IPIP 0x00 /* IP+IP */
+#define WX_PTYPE_PKT_IG 0x10 /* IP+GRE */
+#define WX_PTYPE_PKT_IGM 0x20 /* IP+GRE+MAC */
+#define WX_PTYPE_PKT_IGMV 0x30 /* IP+GRE+MAC+VLAN */
+/* PKT for !TUN */
+#define WX_PTYPE_PKT_MAC 0x10
+#define WX_PTYPE_PKT_IP 0x20
+
+/* TYP for PKT=mac */
+#define WX_PTYPE_TYP_MAC 0x01
+/* TYP for PKT=ip */
+#define WX_PTYPE_PKT_IPV6 0x08
+#define WX_PTYPE_TYP_IPFRAG 0x01
+#define WX_PTYPE_TYP_IP 0x02
+#define WX_PTYPE_TYP_UDP 0x03
+#define WX_PTYPE_TYP_TCP 0x04
+#define WX_PTYPE_TYP_SCTP 0x05
+
+#define WX_RXD_PKTTYPE(_rxd) \
+ ((le32_to_cpu((_rxd)->wb.lower.lo_dword.data) >> 9) & 0xFF)
+#define WX_RXD_IPV6EX(_rxd) \
+ ((le32_to_cpu((_rxd)->wb.lower.lo_dword.data) >> 6) & 0x1)
/*********************** Transmit Descriptor Config Masks ****************/
#define WX_TXD_STAT_DD BIT(0) /* Descriptor Done */
#define WX_TXD_DTYP_DATA 0 /* Adv Data Descriptor */
@@ -334,6 +405,113 @@
#define WX_TXD_IFCS BIT(25) /* Insert FCS */
#define WX_TXD_RS BIT(27) /* Report Status */
+/*********************** Adv Transmit Descriptor Config Masks ****************/
+#define WX_TXD_MAC_TSTAMP BIT(19) /* IEEE1588 time stamp */
+#define WX_TXD_DTYP_CTXT BIT(20) /* Adv Context Desc */
+#define WX_TXD_LINKSEC BIT(26) /* enable linksec */
+#define WX_TXD_VLE BIT(30) /* VLAN pkt enable */
+#define WX_TXD_TSE BIT(31) /* TCP Seg enable */
+#define WX_TXD_CC BIT(7) /* Check Context */
+#define WX_TXD_IPSEC BIT(8) /* enable ipsec esp */
+#define WX_TXD_L4CS BIT(9)
+#define WX_TXD_IIPCS BIT(10)
+#define WX_TXD_EIPCS BIT(11)
+#define WX_TXD_PAYLEN_SHIFT 13 /* Adv desc PAYLEN shift */
+#define WX_TXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
+#define WX_TXD_TAG_TPID_SEL_SHIFT 11
+
+#define WX_TXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
+#define WX_TXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
+
+#define WX_TXD_OUTER_IPLEN_SHIFT 12 /* Adv ctxt OUTERIPLEN shift */
+#define WX_TXD_TUNNEL_LEN_SHIFT 21 /* Adv ctxt TUNNELLEN shift */
+#define WX_TXD_TUNNEL_TYPE_SHIFT 11 /* Adv Tx Desc Tunnel Type shift */
+#define WX_TXD_TUNNEL_UDP FIELD_PREP(BIT(WX_TXD_TUNNEL_TYPE_SHIFT), 0)
+#define WX_TXD_TUNNEL_GRE FIELD_PREP(BIT(WX_TXD_TUNNEL_TYPE_SHIFT), 1)
+
+enum wx_tx_flags {
+ /* cmd_type flags */
+ WX_TX_FLAGS_HW_VLAN = 0x01,
+ WX_TX_FLAGS_TSO = 0x02,
+ WX_TX_FLAGS_TSTAMP = 0x04,
+
+ /* olinfo flags */
+ WX_TX_FLAGS_CC = 0x08,
+ WX_TX_FLAGS_IPV4 = 0x10,
+ WX_TX_FLAGS_CSUM = 0x20,
+ WX_TX_FLAGS_OUTER_IPV4 = 0x100,
+ WX_TX_FLAGS_LINKSEC = 0x200,
+ WX_TX_FLAGS_IPSEC = 0x400,
+};
+
+/* VLAN info */
+#define WX_TX_FLAGS_VLAN_MASK GENMASK(31, 16)
+#define WX_TX_FLAGS_VLAN_SHIFT 16
+
+/* wx_dec_ptype.mac: outer mac */
+enum wx_dec_ptype_mac {
+ WX_DEC_PTYPE_MAC_IP = 0,
+ WX_DEC_PTYPE_MAC_L2 = 2,
+ WX_DEC_PTYPE_MAC_FCOE = 3,
+};
+
+/* wx_dec_ptype.[e]ip: outer&encaped ip */
+#define WX_DEC_PTYPE_IP_FRAG 0x4
+enum wx_dec_ptype_ip {
+ WX_DEC_PTYPE_IP_NONE = 0,
+ WX_DEC_PTYPE_IP_IPV4 = 1,
+ WX_DEC_PTYPE_IP_IPV6 = 2,
+ WX_DEC_PTYPE_IP_FGV4 = WX_DEC_PTYPE_IP_FRAG | WX_DEC_PTYPE_IP_IPV4,
+ WX_DEC_PTYPE_IP_FGV6 = WX_DEC_PTYPE_IP_FRAG | WX_DEC_PTYPE_IP_IPV6,
+};
+
+/* wx_dec_ptype.etype: encaped type */
+enum wx_dec_ptype_etype {
+ WX_DEC_PTYPE_ETYPE_NONE = 0,
+ WX_DEC_PTYPE_ETYPE_IPIP = 1, /* IP+IP */
+ WX_DEC_PTYPE_ETYPE_IG = 2, /* IP+GRE */
+ WX_DEC_PTYPE_ETYPE_IGM = 3, /* IP+GRE+MAC */
+ WX_DEC_PTYPE_ETYPE_IGMV = 4, /* IP+GRE+MAC+VLAN */
+};
+
+/* wx_dec_ptype.proto: payload proto */
+enum wx_dec_ptype_prot {
+ WX_DEC_PTYPE_PROT_NONE = 0,
+ WX_DEC_PTYPE_PROT_UDP = 1,
+ WX_DEC_PTYPE_PROT_TCP = 2,
+ WX_DEC_PTYPE_PROT_SCTP = 3,
+ WX_DEC_PTYPE_PROT_ICMP = 4,
+ WX_DEC_PTYPE_PROT_TS = 5, /* time sync */
+};
+
+/* wx_dec_ptype.layer: payload layer */
+enum wx_dec_ptype_layer {
+ WX_DEC_PTYPE_LAYER_NONE = 0,
+ WX_DEC_PTYPE_LAYER_PAY2 = 1,
+ WX_DEC_PTYPE_LAYER_PAY3 = 2,
+ WX_DEC_PTYPE_LAYER_PAY4 = 3,
+};
+
+struct wx_dec_ptype {
+ u32 known:1;
+ u32 mac:2; /* outer mac */
+ u32 ip:3; /* outer ip*/
+ u32 etype:3; /* encaped type */
+ u32 eip:3; /* encaped ip */
+ u32 prot:4; /* payload proto */
+ u32 layer:3; /* payload layer */
+};
+
+/* macro to make the table lines short */
+#define WX_PTT(mac, ip, etype, eip, proto, layer)\
+ {1, \
+ WX_DEC_PTYPE_MAC_##mac, /* mac */\
+ WX_DEC_PTYPE_IP_##ip, /* ip */ \
+ WX_DEC_PTYPE_ETYPE_##etype, /* etype */\
+ WX_DEC_PTYPE_IP_##eip, /* eip */\
+ WX_DEC_PTYPE_PROT_##proto, /* proto */\
+ WX_DEC_PTYPE_LAYER_##layer /* layer */}
+
/* Host Interface Command Structures */
struct wx_hic_hdr {
u8 cmd;
@@ -412,6 +590,8 @@ struct wx_mac_info {
u32 mta_shadow[128];
s32 mc_filter_type;
u32 mcft_size;
+ u32 vft_shadow[128];
+ u32 vft_size;
u32 num_rar_entries;
u32 rx_pb_size;
u32 tx_pb_size;
@@ -508,10 +688,25 @@ union wx_rx_desc {
} wb; /* writeback */
};
+struct wx_tx_context_desc {
+ __le32 vlan_macip_lens;
+ __le32 seqnum_seed;
+ __le32 type_tucmd_mlhl;
+ __le32 mss_l4len_idx;
+};
+
+/* if _flag is in _input, return _result */
+#define WX_SET_FLAG(_input, _flag, _result) \
+ (((_flag) <= (_result)) ? \
+ ((u32)((_input) & (_flag)) * ((_result) / (_flag))) : \
+ ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
+
#define WX_RX_DESC(R, i) \
(&(((union wx_rx_desc *)((R)->desc))[i]))
#define WX_TX_DESC(R, i) \
(&(((union wx_tx_desc *)((R)->desc))[i]))
+#define WX_TX_CTXTDESC(R, i) \
+ (&(((struct wx_tx_context_desc *)((R)->desc))[i]))
/* wrapper around a pointer to a socket buffer,
* so a DMA handle can be stored along with the buffer
@@ -523,6 +718,8 @@ struct wx_tx_buffer {
unsigned short gso_segs;
DEFINE_DMA_UNMAP_ADDR(dma);
DEFINE_DMA_UNMAP_LEN(len);
+ __be16 protocol;
+ u32 tx_flags;
};
struct wx_rx_buffer {
@@ -539,6 +736,11 @@ struct wx_queue_stats {
u64 bytes;
};
+struct wx_rx_queue_stats {
+ u64 csum_good_cnt;
+ u64 csum_err;
+};
+
/* iterator for handling rings in ring container */
#define wx_for_each_ring(posm, headm) \
for (posm = (headm).ring; posm; posm = posm->next)
@@ -550,7 +752,6 @@ struct wx_ring_container {
u8 count; /* total number of rings in vector */
u8 itr; /* current ITR setting for ring */
};
-
struct wx_ring {
struct wx_ring *next; /* pointer to next ring in q_vector */
struct wx_q_vector *q_vector; /* backpointer to host q_vector */
@@ -580,6 +781,9 @@ struct wx_ring {
struct wx_queue_stats stats;
struct u64_stats_sync syncp;
+ union {
+ struct wx_rx_queue_stats rx_stats;
+ };
} ____cacheline_internodealigned_in_smp;
struct wx_q_vector {
@@ -598,7 +802,7 @@ struct wx_q_vector {
char name[IFNAMSIZ + 17];
/* for dynamic allocation of rings associated with this q_vector */
- struct wx_ring ring[0] ____cacheline_internodealigned_in_smp;
+ struct wx_ring ring[] ____cacheline_internodealigned_in_smp;
};
enum wx_isb_idx {
@@ -610,6 +814,9 @@ enum wx_isb_idx {
};
struct wx {
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
+
+ void *priv;
u8 __iomem *hw_addr;
struct pci_dev *pdev;
struct net_device *netdev;
@@ -642,6 +849,7 @@ struct wx {
bool wol_enabled;
bool ncsi_enabled;
bool gpio_ctrl;
+ raw_spinlock_t gpio_lock;
/* Tx fast path data */
int num_tx_queues;
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index df6b870aa871..c99a5d3de72e 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -115,6 +115,7 @@ static int ngbe_sw_init(struct wx *wx)
wx->mac.max_rx_queues = NGBE_MAX_RX_QUEUES;
wx->mac.max_tx_queues = NGBE_MAX_TX_QUEUES;
wx->mac.mcft_size = NGBE_MC_TBL_SIZE;
+ wx->mac.vft_size = NGBE_SP_VFT_TBL_SIZE;
wx->mac.rx_pb_size = NGBE_RX_PB_SIZE;
wx->mac.tx_pb_size = NGBE_TDB_PB_SZ;
@@ -473,9 +474,12 @@ static const struct net_device_ops ngbe_netdev_ops = {
.ndo_change_mtu = wx_change_mtu,
.ndo_start_xmit = wx_xmit_frame,
.ndo_set_rx_mode = wx_set_rx_mode,
+ .ndo_set_features = wx_set_features,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = wx_set_mac,
.ndo_get_stats64 = wx_get_stats64,
+ .ndo_vlan_rx_add_vid = wx_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = wx_vlan_rx_kill_vid,
};
/**
@@ -551,12 +555,18 @@ static int ngbe_probe(struct pci_dev *pdev,
ngbe_set_ethtool_ops(netdev);
netdev->netdev_ops = &ngbe_netdev_ops;
- netdev->features |= NETIF_F_HIGHDMA;
- netdev->features = NETIF_F_SG;
-
+ netdev->features = NETIF_F_SG | NETIF_F_IP_CSUM |
+ NETIF_F_TSO | NETIF_F_TSO6 |
+ NETIF_F_RXHASH | NETIF_F_RXCSUM;
+ netdev->features |= NETIF_F_SCTP_CRC | NETIF_F_TSO_MANGLEID;
+ netdev->vlan_features |= netdev->features;
+ netdev->features |= NETIF_F_IPV6_CSUM | NETIF_F_VLAN_FEATURES;
/* copy netdev features into list of user selectable features */
- netdev->hw_features |= netdev->features |
- NETIF_F_RXALL;
+ netdev->hw_features |= netdev->features | NETIF_F_RXALL;
+ netdev->hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC;
+ netdev->features |= NETIF_F_HIGHDMA;
+ netdev->hw_features |= NETIF_F_GRO;
+ netdev->features |= NETIF_F_GRO;
netdev->priv_flags |= IFF_UNICAST_FLT;
netdev->priv_flags |= IFF_SUPP_NOFCS;
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
index 373d5af628cd..b70eca397b67 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
@@ -136,6 +136,7 @@ enum NGBE_MSCA_CMD_value {
#define NGBE_RAR_ENTRIES 32
#define NGBE_RX_PB_SIZE 42
#define NGBE_MC_TBL_SIZE 128
+#define NGBE_SP_VFT_TBL_SIZE 128
#define NGBE_TDB_PB_SZ (20 * 1024) /* 160KB Packet Buffer */
/* TX/RX descriptor defines */
diff --git a/drivers/net/ethernet/wangxun/txgbe/Makefile b/drivers/net/ethernet/wangxun/txgbe/Makefile
index 6db14a2cb2d0..7507f762edfe 100644
--- a/drivers/net/ethernet/wangxun/txgbe/Makefile
+++ b/drivers/net/ethernet/wangxun/txgbe/Makefile
@@ -8,4 +8,5 @@ obj-$(CONFIG_TXGBE) += txgbe.o
txgbe-objs := txgbe_main.o \
txgbe_hw.o \
+ txgbe_phy.o \
txgbe_ethtool.o
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
index d914e9a05404..859da112586a 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
@@ -6,11 +6,39 @@
#include <linux/netdevice.h>
#include "../libwx/wx_ethtool.h"
+#include "../libwx/wx_type.h"
+#include "txgbe_type.h"
#include "txgbe_ethtool.h"
+static int txgbe_nway_reset(struct net_device *netdev)
+{
+ struct txgbe *txgbe = netdev_to_txgbe(netdev);
+
+ return phylink_ethtool_nway_reset(txgbe->phylink);
+}
+
+static int txgbe_get_link_ksettings(struct net_device *netdev,
+ struct ethtool_link_ksettings *cmd)
+{
+ struct txgbe *txgbe = netdev_to_txgbe(netdev);
+
+ return phylink_ethtool_ksettings_get(txgbe->phylink, cmd);
+}
+
+static int txgbe_set_link_ksettings(struct net_device *netdev,
+ const struct ethtool_link_ksettings *cmd)
+{
+ struct txgbe *txgbe = netdev_to_txgbe(netdev);
+
+ return phylink_ethtool_ksettings_set(txgbe->phylink, cmd);
+}
+
static const struct ethtool_ops txgbe_ethtool_ops = {
.get_drvinfo = wx_get_drvinfo,
+ .nway_reset = txgbe_nway_reset,
.get_link = ethtool_op_get_link,
+ .get_link_ksettings = txgbe_get_link_ksettings,
+ .set_link_ksettings = txgbe_set_link_ksettings,
};
void txgbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c
index ebc46f3be056..0772eb14eabf 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c
@@ -160,34 +160,24 @@ int txgbe_read_pba_string(struct wx *wx, u8 *pba_num, u32 pba_num_size)
static int txgbe_calc_eeprom_checksum(struct wx *wx, u16 *checksum)
{
u16 *eeprom_ptrs = NULL;
- u32 buffer_size = 0;
- u16 *buffer = NULL;
u16 *local_buffer;
int status;
u16 i;
wx_init_eeprom_params(wx);
- if (!buffer) {
- eeprom_ptrs = kvmalloc_array(TXGBE_EEPROM_LAST_WORD, sizeof(u16),
- GFP_KERNEL);
- if (!eeprom_ptrs)
- return -ENOMEM;
- /* Read pointer area */
- status = wx_read_ee_hostif_buffer(wx, 0,
- TXGBE_EEPROM_LAST_WORD,
- eeprom_ptrs);
- if (status != 0) {
- wx_err(wx, "Failed to read EEPROM image\n");
- kvfree(eeprom_ptrs);
- return status;
- }
- local_buffer = eeprom_ptrs;
- } else {
- if (buffer_size < TXGBE_EEPROM_LAST_WORD)
- return -EFAULT;
- local_buffer = buffer;
+ eeprom_ptrs = kvmalloc_array(TXGBE_EEPROM_LAST_WORD, sizeof(u16),
+ GFP_KERNEL);
+ if (!eeprom_ptrs)
+ return -ENOMEM;
+ /* Read pointer area */
+ status = wx_read_ee_hostif_buffer(wx, 0, TXGBE_EEPROM_LAST_WORD, eeprom_ptrs);
+ if (status != 0) {
+ wx_err(wx, "Failed to read EEPROM image\n");
+ kvfree(eeprom_ptrs);
+ return status;
}
+ local_buffer = eeprom_ptrs;
for (i = 0; i < TXGBE_EEPROM_LAST_WORD; i++)
if (i != wx->eeprom.sw_region_offset + TXGBE_EEPROM_CHECKSUM)
@@ -196,9 +186,6 @@ static int txgbe_calc_eeprom_checksum(struct wx *wx, u16 *checksum)
if (eeprom_ptrs)
kvfree(eeprom_ptrs);
- if (*checksum > TXGBE_EEPROM_SUM)
- return -EINVAL;
-
*checksum = TXGBE_EEPROM_SUM - *checksum;
return 0;
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index 5b8a121fb496..46eba6d6188b 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -7,6 +7,7 @@
#include <linux/netdevice.h>
#include <linux/string.h>
#include <linux/etherdevice.h>
+#include <linux/phylink.h>
#include <net/ip.h>
#include <linux/if_vlan.h>
@@ -15,6 +16,7 @@
#include "../libwx/wx_hw.h"
#include "txgbe_type.h"
#include "txgbe_hw.h"
+#include "txgbe_phy.h"
#include "txgbe_ethtool.h"
char txgbe_driver_name[] = "txgbe";
@@ -81,6 +83,8 @@ static int txgbe_enumerate_functions(struct wx *wx)
**/
static void txgbe_irq_enable(struct wx *wx, bool queues)
{
+ wr32(wx, WX_PX_MISC_IEN, TXGBE_PX_MISC_IEN_MASK);
+
/* unmask interrupt */
wx_intr_enable(wx, TXGBE_INTR_MISC(wx));
if (queues)
@@ -128,17 +132,6 @@ static irqreturn_t txgbe_intr(int __always_unused irq, void *data)
return IRQ_HANDLED;
}
-static irqreturn_t txgbe_msix_other(int __always_unused irq, void *data)
-{
- struct wx *wx = data;
-
- /* re-enable the original interrupt state */
- if (netif_running(wx->netdev))
- txgbe_irq_enable(wx, false);
-
- return IRQ_HANDLED;
-}
-
/**
* txgbe_request_msix_irqs - Initialize MSI-X interrupts
* @wx: board private structure
@@ -170,13 +163,6 @@ static int txgbe_request_msix_irqs(struct wx *wx)
}
}
- err = request_irq(wx->msix_entries[vector].vector,
- txgbe_msix_other, 0, netdev->name, wx);
- if (err) {
- wx_err(wx, "request_irq for msix_other failed: %d\n", err);
- goto free_queue_irqs;
- }
-
return 0;
free_queue_irqs:
@@ -219,7 +205,8 @@ static int txgbe_request_irq(struct wx *wx)
static void txgbe_up_complete(struct wx *wx)
{
- u32 reg;
+ struct net_device *netdev = wx->netdev;
+ struct txgbe *txgbe;
wx_control_hw(wx, true);
wx_configure_vectors(wx);
@@ -228,24 +215,17 @@ static void txgbe_up_complete(struct wx *wx)
smp_mb__before_atomic();
wx_napi_enable_all(wx);
+ txgbe = netdev_to_txgbe(netdev);
+ phylink_start(txgbe->phylink);
+
/* clear any pending interrupts, may auto mask */
rd32(wx, WX_PX_IC(0));
rd32(wx, WX_PX_IC(1));
rd32(wx, WX_PX_MISC_IC);
txgbe_irq_enable(wx, true);
- /* Configure MAC Rx and Tx when link is up */
- reg = rd32(wx, WX_MAC_RX_CFG);
- wr32(wx, WX_MAC_RX_CFG, reg);
- wr32(wx, WX_MAC_PKT_FLT, WX_MAC_PKT_FLT_PR);
- reg = rd32(wx, WX_MAC_WDG_TIMEOUT);
- wr32(wx, WX_MAC_WDG_TIMEOUT, reg);
- reg = rd32(wx, WX_MAC_TX_CFG);
- wr32(wx, WX_MAC_TX_CFG, (reg & ~WX_MAC_TX_CFG_SPEED_MASK) | WX_MAC_TX_CFG_SPEED_10G);
-
/* enable transmits */
- netif_tx_start_all_queues(wx->netdev);
- netif_carrier_on(wx->netdev);
+ netif_tx_start_all_queues(netdev);
}
static void txgbe_reset(struct wx *wx)
@@ -258,6 +238,7 @@ static void txgbe_reset(struct wx *wx)
if (err != 0)
wx_err(wx, "Hardware Error: %d\n", err);
+ wx_start_hw(wx);
/* do not flush user set addresses */
memcpy(old_addr, &wx->mac_table[0].addr, netdev->addr_len);
wx_flush_sw_mac_table(wx);
@@ -279,7 +260,6 @@ static void txgbe_disable_device(struct wx *wx)
wx_disable_rx_queue(wx, wx->rx_ring[i]);
netif_tx_stop_all_queues(netdev);
- netif_carrier_off(netdev);
netif_tx_disable(netdev);
wx_irq_disable(wx);
@@ -310,8 +290,11 @@ static void txgbe_disable_device(struct wx *wx)
static void txgbe_down(struct wx *wx)
{
+ struct txgbe *txgbe = netdev_to_txgbe(wx->netdev);
+
txgbe_disable_device(wx);
txgbe_reset(wx);
+ phylink_stop(txgbe->phylink);
wx_clean_all_tx_rings(wx);
wx_clean_all_rx_rings(wx);
@@ -330,6 +313,7 @@ static int txgbe_sw_init(struct wx *wx)
wx->mac.max_tx_queues = TXGBE_SP_MAX_TX_QUEUES;
wx->mac.max_rx_queues = TXGBE_SP_MAX_RX_QUEUES;
wx->mac.mcft_size = TXGBE_SP_MC_TBL_SIZE;
+ wx->mac.vft_size = TXGBE_SP_VFT_TBL_SIZE;
wx->mac.rx_pb_size = TXGBE_SP_RX_PB_SIZE;
wx->mac.tx_pb_size = TXGBE_SP_TDB_PB_SZ;
@@ -455,7 +439,7 @@ static int txgbe_close(struct net_device *netdev)
return 0;
}
-static void txgbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake)
+static void txgbe_dev_shutdown(struct pci_dev *pdev)
{
struct wx *wx = pci_get_drvdata(pdev);
struct net_device *netdev;
@@ -475,12 +459,10 @@ static void txgbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake)
static void txgbe_shutdown(struct pci_dev *pdev)
{
- bool wake;
-
- txgbe_dev_shutdown(pdev, &wake);
+ txgbe_dev_shutdown(pdev);
if (system_state == SYSTEM_POWER_OFF) {
- pci_wake_from_d3(pdev, wake);
+ pci_wake_from_d3(pdev, false);
pci_set_power_state(pdev, PCI_D3hot);
}
}
@@ -491,9 +473,12 @@ static const struct net_device_ops txgbe_netdev_ops = {
.ndo_change_mtu = wx_change_mtu,
.ndo_start_xmit = wx_xmit_frame,
.ndo_set_rx_mode = wx_set_rx_mode,
+ .ndo_set_features = wx_set_features,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = wx_set_mac,
.ndo_get_stats64 = wx_get_stats64,
+ .ndo_vlan_rx_add_vid = wx_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = wx_vlan_rx_kill_vid,
};
/**
@@ -513,6 +498,7 @@ static int txgbe_probe(struct pci_dev *pdev,
struct net_device *netdev;
int err, expected_gts;
struct wx *wx = NULL;
+ struct txgbe *txgbe;
u16 eeprom_verh = 0, eeprom_verl = 0, offset = 0;
u16 eeprom_cfg_blkh = 0, eeprom_cfg_blkl = 0;
@@ -596,11 +582,25 @@ static int txgbe_probe(struct pci_dev *pdev,
goto err_free_mac_table;
}
- netdev->features |= NETIF_F_HIGHDMA;
- netdev->features = NETIF_F_SG;
-
+ netdev->features = NETIF_F_SG |
+ NETIF_F_TSO |
+ NETIF_F_TSO6 |
+ NETIF_F_RXHASH |
+ NETIF_F_RXCSUM |
+ NETIF_F_HW_CSUM;
+
+ netdev->gso_partial_features = NETIF_F_GSO_ENCAP_ALL;
+ netdev->features |= netdev->gso_partial_features;
+ netdev->features |= NETIF_F_SCTP_CRC;
+ netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID;
+ netdev->hw_enc_features |= netdev->vlan_features;
+ netdev->features |= NETIF_F_VLAN_FEATURES;
/* copy netdev features into list of user selectable features */
netdev->hw_features |= netdev->features | NETIF_F_RXALL;
+ netdev->hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC;
+ netdev->features |= NETIF_F_HIGHDMA;
+ netdev->hw_features |= NETIF_F_GRO;
+ netdev->features |= NETIF_F_GRO;
netdev->priv_flags |= IFF_UNICAST_FLT;
netdev->priv_flags |= IFF_SUPP_NOFCS;
@@ -663,10 +663,23 @@ static int txgbe_probe(struct pci_dev *pdev,
"0x%08x", etrack_id);
}
- err = register_netdev(netdev);
+ txgbe = devm_kzalloc(&pdev->dev, sizeof(*txgbe), GFP_KERNEL);
+ if (!txgbe) {
+ err = -ENOMEM;
+ goto err_release_hw;
+ }
+
+ txgbe->wx = wx;
+ wx->priv = txgbe;
+
+ err = txgbe_init_phy(txgbe);
if (err)
goto err_release_hw;
+ err = register_netdev(netdev);
+ if (err)
+ goto err_remove_phy;
+
pci_set_drvdata(pdev, wx);
netif_tx_stop_all_queues(netdev);
@@ -694,6 +707,8 @@ static int txgbe_probe(struct pci_dev *pdev,
return 0;
+err_remove_phy:
+ txgbe_remove_phy(txgbe);
err_release_hw:
wx_clear_interrupt_scheme(wx);
wx_control_hw(wx, false);
@@ -719,11 +734,14 @@ err_pci_disable_dev:
static void txgbe_remove(struct pci_dev *pdev)
{
struct wx *wx = pci_get_drvdata(pdev);
+ struct txgbe *txgbe = wx->priv;
struct net_device *netdev;
netdev = wx->netdev;
unregister_netdev(netdev);
+ txgbe_remove_phy(txgbe);
+
pci_release_selected_regions(pdev,
pci_select_bars(pdev, IORESOURCE_MEM));
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
new file mode 100644
index 000000000000..8779645a54be
--- /dev/null
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
@@ -0,0 +1,673 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */
+
+#include <linux/gpio/machine.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio/property.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/i2c.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/pcs/pcs-xpcs.h>
+#include <linux/phylink.h>
+
+#include "../libwx/wx_type.h"
+#include "../libwx/wx_lib.h"
+#include "../libwx/wx_hw.h"
+#include "txgbe_type.h"
+#include "txgbe_phy.h"
+
+static int txgbe_swnodes_register(struct txgbe *txgbe)
+{
+ struct txgbe_nodes *nodes = &txgbe->nodes;
+ struct pci_dev *pdev = txgbe->wx->pdev;
+ struct software_node *swnodes;
+ u32 id;
+
+ id = (pdev->bus->number << 8) | pdev->devfn;
+
+ snprintf(nodes->gpio_name, sizeof(nodes->gpio_name), "txgbe_gpio-%x", id);
+ snprintf(nodes->i2c_name, sizeof(nodes->i2c_name), "txgbe_i2c-%x", id);
+ snprintf(nodes->sfp_name, sizeof(nodes->sfp_name), "txgbe_sfp-%x", id);
+ snprintf(nodes->phylink_name, sizeof(nodes->phylink_name), "txgbe_phylink-%x", id);
+
+ swnodes = nodes->swnodes;
+
+ /* GPIO 0: tx fault
+ * GPIO 1: tx disable
+ * GPIO 2: sfp module absent
+ * GPIO 3: rx signal lost
+ * GPIO 4: rate select, 1G(0) 10G(1)
+ * GPIO 5: rate select, 1G(0) 10G(1)
+ */
+ nodes->gpio_props[0] = PROPERTY_ENTRY_STRING("pinctrl-names", "default");
+ swnodes[SWNODE_GPIO] = NODE_PROP(nodes->gpio_name, nodes->gpio_props);
+ nodes->gpio0_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 0, GPIO_ACTIVE_HIGH);
+ nodes->gpio1_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 1, GPIO_ACTIVE_HIGH);
+ nodes->gpio2_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 2, GPIO_ACTIVE_LOW);
+ nodes->gpio3_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 3, GPIO_ACTIVE_HIGH);
+ nodes->gpio4_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 4, GPIO_ACTIVE_HIGH);
+ nodes->gpio5_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 5, GPIO_ACTIVE_HIGH);
+
+ nodes->i2c_props[0] = PROPERTY_ENTRY_STRING("compatible", "snps,designware-i2c");
+ nodes->i2c_props[1] = PROPERTY_ENTRY_BOOL("wx,i2c-snps-model");
+ nodes->i2c_props[2] = PROPERTY_ENTRY_U32("clock-frequency", I2C_MAX_STANDARD_MODE_FREQ);
+ swnodes[SWNODE_I2C] = NODE_PROP(nodes->i2c_name, nodes->i2c_props);
+ nodes->i2c_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_I2C]);
+
+ nodes->sfp_props[0] = PROPERTY_ENTRY_STRING("compatible", "sff,sfp");
+ nodes->sfp_props[1] = PROPERTY_ENTRY_REF_ARRAY("i2c-bus", nodes->i2c_ref);
+ nodes->sfp_props[2] = PROPERTY_ENTRY_REF_ARRAY("tx-fault-gpios", nodes->gpio0_ref);
+ nodes->sfp_props[3] = PROPERTY_ENTRY_REF_ARRAY("tx-disable-gpios", nodes->gpio1_ref);
+ nodes->sfp_props[4] = PROPERTY_ENTRY_REF_ARRAY("mod-def0-gpios", nodes->gpio2_ref);
+ nodes->sfp_props[5] = PROPERTY_ENTRY_REF_ARRAY("los-gpios", nodes->gpio3_ref);
+ nodes->sfp_props[6] = PROPERTY_ENTRY_REF_ARRAY("rate-select1-gpios", nodes->gpio4_ref);
+ nodes->sfp_props[7] = PROPERTY_ENTRY_REF_ARRAY("rate-select0-gpios", nodes->gpio5_ref);
+ swnodes[SWNODE_SFP] = NODE_PROP(nodes->sfp_name, nodes->sfp_props);
+ nodes->sfp_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_SFP]);
+
+ nodes->phylink_props[0] = PROPERTY_ENTRY_STRING("managed", "in-band-status");
+ nodes->phylink_props[1] = PROPERTY_ENTRY_REF_ARRAY("sfp", nodes->sfp_ref);
+ swnodes[SWNODE_PHYLINK] = NODE_PROP(nodes->phylink_name, nodes->phylink_props);
+
+ nodes->group[SWNODE_GPIO] = &swnodes[SWNODE_GPIO];
+ nodes->group[SWNODE_I2C] = &swnodes[SWNODE_I2C];
+ nodes->group[SWNODE_SFP] = &swnodes[SWNODE_SFP];
+ nodes->group[SWNODE_PHYLINK] = &swnodes[SWNODE_PHYLINK];
+
+ return software_node_register_node_group(nodes->group);
+}
+
+static int txgbe_pcs_read(struct mii_bus *bus, int addr, int devnum, int regnum)
+{
+ struct wx *wx = bus->priv;
+ u32 offset, val;
+
+ if (addr)
+ return -EOPNOTSUPP;
+
+ offset = devnum << 16 | regnum;
+
+ /* Set the LAN port indicator to IDA_ADDR */
+ wr32(wx, TXGBE_XPCS_IDA_ADDR, offset);
+
+ /* Read the data from IDA_DATA register */
+ val = rd32(wx, TXGBE_XPCS_IDA_DATA);
+
+ return (u16)val;
+}
+
+static int txgbe_pcs_write(struct mii_bus *bus, int addr, int devnum, int regnum, u16 val)
+{
+ struct wx *wx = bus->priv;
+ u32 offset;
+
+ if (addr)
+ return -EOPNOTSUPP;
+
+ offset = devnum << 16 | regnum;
+
+ /* Set the LAN port indicator to IDA_ADDR */
+ wr32(wx, TXGBE_XPCS_IDA_ADDR, offset);
+
+ /* Write the data to IDA_DATA register */
+ wr32(wx, TXGBE_XPCS_IDA_DATA, val);
+
+ return 0;
+}
+
+static int txgbe_mdio_pcs_init(struct txgbe *txgbe)
+{
+ struct mii_bus *mii_bus;
+ struct dw_xpcs *xpcs;
+ struct pci_dev *pdev;
+ struct wx *wx;
+ int ret = 0;
+
+ wx = txgbe->wx;
+ pdev = wx->pdev;
+
+ mii_bus = devm_mdiobus_alloc(&pdev->dev);
+ if (!mii_bus)
+ return -ENOMEM;
+
+ mii_bus->name = "txgbe_pcs_mdio_bus";
+ mii_bus->read_c45 = &txgbe_pcs_read;
+ mii_bus->write_c45 = &txgbe_pcs_write;
+ mii_bus->parent = &pdev->dev;
+ mii_bus->phy_mask = ~0;
+ mii_bus->priv = wx;
+ snprintf(mii_bus->id, MII_BUS_ID_SIZE, "txgbe_pcs-%x",
+ (pdev->bus->number << 8) | pdev->devfn);
+
+ ret = devm_mdiobus_register(&pdev->dev, mii_bus);
+ if (ret)
+ return ret;
+
+ xpcs = xpcs_create_mdiodev(mii_bus, 0, PHY_INTERFACE_MODE_10GBASER);
+ if (IS_ERR(xpcs))
+ return PTR_ERR(xpcs);
+
+ txgbe->xpcs = xpcs;
+
+ return 0;
+}
+
+static struct phylink_pcs *txgbe_phylink_mac_select(struct phylink_config *config,
+ phy_interface_t interface)
+{
+ struct txgbe *txgbe = netdev_to_txgbe(to_net_dev(config->dev));
+
+ return &txgbe->xpcs->pcs;
+}
+
+static void txgbe_mac_config(struct phylink_config *config, unsigned int mode,
+ const struct phylink_link_state *state)
+{
+}
+
+static void txgbe_mac_link_down(struct phylink_config *config,
+ unsigned int mode, phy_interface_t interface)
+{
+ struct wx *wx = netdev_priv(to_net_dev(config->dev));
+
+ wr32m(wx, WX_MAC_TX_CFG, WX_MAC_TX_CFG_TE, 0);
+}
+
+static void txgbe_mac_link_up(struct phylink_config *config,
+ struct phy_device *phy,
+ unsigned int mode, phy_interface_t interface,
+ int speed, int duplex,
+ bool tx_pause, bool rx_pause)
+{
+ struct wx *wx = netdev_priv(to_net_dev(config->dev));
+ u32 txcfg, wdg;
+
+ txcfg = rd32(wx, WX_MAC_TX_CFG);
+ txcfg &= ~WX_MAC_TX_CFG_SPEED_MASK;
+
+ switch (speed) {
+ case SPEED_10000:
+ txcfg |= WX_MAC_TX_CFG_SPEED_10G;
+ break;
+ case SPEED_1000:
+ case SPEED_100:
+ case SPEED_10:
+ txcfg |= WX_MAC_TX_CFG_SPEED_1G;
+ break;
+ default:
+ break;
+ }
+
+ wr32(wx, WX_MAC_TX_CFG, txcfg | WX_MAC_TX_CFG_TE);
+
+ /* Re configure MAC Rx */
+ wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, WX_MAC_RX_CFG_RE);
+ wr32(wx, WX_MAC_PKT_FLT, WX_MAC_PKT_FLT_PR);
+ wdg = rd32(wx, WX_MAC_WDG_TIMEOUT);
+ wr32(wx, WX_MAC_WDG_TIMEOUT, wdg);
+}
+
+static const struct phylink_mac_ops txgbe_mac_ops = {
+ .mac_select_pcs = txgbe_phylink_mac_select,
+ .mac_config = txgbe_mac_config,
+ .mac_link_down = txgbe_mac_link_down,
+ .mac_link_up = txgbe_mac_link_up,
+};
+
+static int txgbe_phylink_init(struct txgbe *txgbe)
+{
+ struct phylink_config *config;
+ struct fwnode_handle *fwnode;
+ struct wx *wx = txgbe->wx;
+ phy_interface_t phy_mode;
+ struct phylink *phylink;
+
+ config = devm_kzalloc(&wx->pdev->dev, sizeof(*config), GFP_KERNEL);
+ if (!config)
+ return -ENOMEM;
+
+ config->dev = &wx->netdev->dev;
+ config->type = PHYLINK_NETDEV;
+ config->mac_capabilities = MAC_10000FD | MAC_1000FD | MAC_SYM_PAUSE | MAC_ASYM_PAUSE;
+ phy_mode = PHY_INTERFACE_MODE_10GBASER;
+ __set_bit(PHY_INTERFACE_MODE_10GBASER, config->supported_interfaces);
+ fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_PHYLINK]);
+ phylink = phylink_create(config, fwnode, phy_mode, &txgbe_mac_ops);
+ if (IS_ERR(phylink))
+ return PTR_ERR(phylink);
+
+ txgbe->phylink = phylink;
+
+ return 0;
+}
+
+static int txgbe_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct wx *wx = gpiochip_get_data(chip);
+ int val;
+
+ val = rd32m(wx, WX_GPIO_EXT, BIT(offset));
+
+ return !!(val & BIT(offset));
+}
+
+static int txgbe_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+ struct wx *wx = gpiochip_get_data(chip);
+ u32 val;
+
+ val = rd32(wx, WX_GPIO_DDR);
+ if (BIT(offset) & val)
+ return GPIO_LINE_DIRECTION_OUT;
+
+ return GPIO_LINE_DIRECTION_IN;
+}
+
+static int txgbe_gpio_direction_in(struct gpio_chip *chip, unsigned int offset)
+{
+ struct wx *wx = gpiochip_get_data(chip);
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&wx->gpio_lock, flags);
+ wr32m(wx, WX_GPIO_DDR, BIT(offset), 0);
+ raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
+
+ return 0;
+}
+
+static int txgbe_gpio_direction_out(struct gpio_chip *chip, unsigned int offset,
+ int val)
+{
+ struct wx *wx = gpiochip_get_data(chip);
+ unsigned long flags;
+ u32 set;
+
+ set = val ? BIT(offset) : 0;
+
+ raw_spin_lock_irqsave(&wx->gpio_lock, flags);
+ wr32m(wx, WX_GPIO_DR, BIT(offset), set);
+ wr32m(wx, WX_GPIO_DDR, BIT(offset), BIT(offset));
+ raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
+
+ return 0;
+}
+
+static void txgbe_gpio_irq_ack(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ struct wx *wx = gpiochip_get_data(gc);
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&wx->gpio_lock, flags);
+ wr32(wx, WX_GPIO_EOI, BIT(hwirq));
+ raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
+}
+
+static void txgbe_gpio_irq_mask(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ struct wx *wx = gpiochip_get_data(gc);
+ unsigned long flags;
+
+ gpiochip_disable_irq(gc, hwirq);
+
+ raw_spin_lock_irqsave(&wx->gpio_lock, flags);
+ wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), BIT(hwirq));
+ raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
+}
+
+static void txgbe_gpio_irq_unmask(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ struct wx *wx = gpiochip_get_data(gc);
+ unsigned long flags;
+
+ gpiochip_enable_irq(gc, hwirq);
+
+ raw_spin_lock_irqsave(&wx->gpio_lock, flags);
+ wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), 0);
+ raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
+}
+
+static void txgbe_toggle_trigger(struct gpio_chip *gc, unsigned int offset)
+{
+ struct wx *wx = gpiochip_get_data(gc);
+ u32 pol, val;
+
+ pol = rd32(wx, WX_GPIO_POLARITY);
+ val = rd32(wx, WX_GPIO_EXT);
+
+ if (val & BIT(offset))
+ pol &= ~BIT(offset);
+ else
+ pol |= BIT(offset);
+
+ wr32(wx, WX_GPIO_POLARITY, pol);
+}
+
+static int txgbe_gpio_set_type(struct irq_data *d, unsigned int type)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ struct wx *wx = gpiochip_get_data(gc);
+ u32 level, polarity, mask;
+ unsigned long flags;
+
+ mask = BIT(hwirq);
+
+ if (type & IRQ_TYPE_LEVEL_MASK) {
+ level = 0;
+ irq_set_handler_locked(d, handle_level_irq);
+ } else {
+ level = mask;
+ irq_set_handler_locked(d, handle_edge_irq);
+ }
+
+ if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH)
+ polarity = mask;
+ else
+ polarity = 0;
+
+ raw_spin_lock_irqsave(&wx->gpio_lock, flags);
+
+ wr32m(wx, WX_GPIO_INTEN, mask, mask);
+ wr32m(wx, WX_GPIO_INTTYPE_LEVEL, mask, level);
+ if (type == IRQ_TYPE_EDGE_BOTH)
+ txgbe_toggle_trigger(gc, hwirq);
+ else
+ wr32m(wx, WX_GPIO_POLARITY, mask, polarity);
+
+ raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
+
+ return 0;
+}
+
+static const struct irq_chip txgbe_gpio_irq_chip = {
+ .name = "txgbe_gpio_irq",
+ .irq_ack = txgbe_gpio_irq_ack,
+ .irq_mask = txgbe_gpio_irq_mask,
+ .irq_unmask = txgbe_gpio_irq_unmask,
+ .irq_set_type = txgbe_gpio_set_type,
+ .flags = IRQCHIP_IMMUTABLE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
+static void txgbe_irq_handler(struct irq_desc *desc)
+{
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct wx *wx = irq_desc_get_handler_data(desc);
+ struct txgbe *txgbe = wx->priv;
+ irq_hw_number_t hwirq;
+ unsigned long gpioirq;
+ struct gpio_chip *gc;
+ unsigned long flags;
+ u32 eicr;
+
+ eicr = wx_misc_isb(wx, WX_ISB_MISC);
+
+ chained_irq_enter(chip, desc);
+
+ gpioirq = rd32(wx, WX_GPIO_INTSTATUS);
+
+ gc = txgbe->gpio;
+ for_each_set_bit(hwirq, &gpioirq, gc->ngpio) {
+ int gpio = irq_find_mapping(gc->irq.domain, hwirq);
+ u32 irq_type = irq_get_trigger_type(gpio);
+
+ generic_handle_domain_irq(gc->irq.domain, hwirq);
+
+ if ((irq_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+ raw_spin_lock_irqsave(&wx->gpio_lock, flags);
+ txgbe_toggle_trigger(gc, hwirq);
+ raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+
+ if (eicr & (TXGBE_PX_MISC_ETH_LK | TXGBE_PX_MISC_ETH_LKDN)) {
+ u32 reg = rd32(wx, TXGBE_CFG_PORT_ST);
+
+ phylink_mac_change(txgbe->phylink, !!(reg & TXGBE_CFG_PORT_ST_LINK_UP));
+ }
+
+ /* unmask interrupt */
+ wx_intr_enable(wx, TXGBE_INTR_MISC(wx));
+}
+
+static int txgbe_gpio_init(struct txgbe *txgbe)
+{
+ struct gpio_irq_chip *girq;
+ struct gpio_chip *gc;
+ struct device *dev;
+ struct wx *wx;
+ int ret;
+
+ wx = txgbe->wx;
+ dev = &wx->pdev->dev;
+
+ raw_spin_lock_init(&wx->gpio_lock);
+
+ gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
+ if (!gc)
+ return -ENOMEM;
+
+ gc->label = devm_kasprintf(dev, GFP_KERNEL, "txgbe_gpio-%x",
+ (wx->pdev->bus->number << 8) | wx->pdev->devfn);
+ if (!gc->label)
+ return -ENOMEM;
+
+ gc->base = -1;
+ gc->ngpio = 6;
+ gc->owner = THIS_MODULE;
+ gc->parent = dev;
+ gc->fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_GPIO]);
+ gc->get = txgbe_gpio_get;
+ gc->get_direction = txgbe_gpio_get_direction;
+ gc->direction_input = txgbe_gpio_direction_in;
+ gc->direction_output = txgbe_gpio_direction_out;
+
+ girq = &gc->irq;
+ gpio_irq_chip_set_chip(girq, &txgbe_gpio_irq_chip);
+ girq->parent_handler = txgbe_irq_handler;
+ girq->parent_handler_data = wx;
+ girq->num_parents = 1;
+ girq->parents = devm_kcalloc(dev, girq->num_parents,
+ sizeof(*girq->parents), GFP_KERNEL);
+ if (!girq->parents)
+ return -ENOMEM;
+ girq->parents[0] = wx->msix_entries[wx->num_q_vectors].vector;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_bad_irq;
+
+ ret = devm_gpiochip_add_data(dev, gc, wx);
+ if (ret)
+ return ret;
+
+ txgbe->gpio = gc;
+
+ return 0;
+}
+
+static int txgbe_clock_register(struct txgbe *txgbe)
+{
+ struct pci_dev *pdev = txgbe->wx->pdev;
+ struct clk_lookup *clock;
+ char clk_name[32];
+ struct clk *clk;
+
+ snprintf(clk_name, sizeof(clk_name), "i2c_designware.%d",
+ (pdev->bus->number << 8) | pdev->devfn);
+
+ clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 156250000);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ clock = clkdev_create(clk, NULL, clk_name);
+ if (!clock) {
+ clk_unregister(clk);
+ return -ENOMEM;
+ }
+
+ txgbe->clk = clk;
+ txgbe->clock = clock;
+
+ return 0;
+}
+
+static int txgbe_i2c_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct wx *wx = context;
+
+ *val = rd32(wx, reg + TXGBE_I2C_BASE);
+
+ return 0;
+}
+
+static int txgbe_i2c_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct wx *wx = context;
+
+ wr32(wx, reg + TXGBE_I2C_BASE, val);
+
+ return 0;
+}
+
+static const struct regmap_config i2c_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_read = txgbe_i2c_read,
+ .reg_write = txgbe_i2c_write,
+ .fast_io = true,
+};
+
+static int txgbe_i2c_register(struct txgbe *txgbe)
+{
+ struct platform_device_info info = {};
+ struct platform_device *i2c_dev;
+ struct regmap *i2c_regmap;
+ struct pci_dev *pdev;
+ struct wx *wx;
+
+ wx = txgbe->wx;
+ pdev = wx->pdev;
+ i2c_regmap = devm_regmap_init(&pdev->dev, NULL, wx, &i2c_regmap_config);
+ if (IS_ERR(i2c_regmap)) {
+ wx_err(wx, "failed to init I2C regmap\n");
+ return PTR_ERR(i2c_regmap);
+ }
+
+ info.parent = &pdev->dev;
+ info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_I2C]);
+ info.name = "i2c_designware";
+ info.id = (pdev->bus->number << 8) | pdev->devfn;
+
+ info.res = &DEFINE_RES_IRQ(pdev->irq);
+ info.num_res = 1;
+ i2c_dev = platform_device_register_full(&info);
+ if (IS_ERR(i2c_dev))
+ return PTR_ERR(i2c_dev);
+
+ txgbe->i2c_dev = i2c_dev;
+
+ return 0;
+}
+
+static int txgbe_sfp_register(struct txgbe *txgbe)
+{
+ struct pci_dev *pdev = txgbe->wx->pdev;
+ struct platform_device_info info = {};
+ struct platform_device *sfp_dev;
+
+ info.parent = &pdev->dev;
+ info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_SFP]);
+ info.name = "sfp";
+ info.id = (pdev->bus->number << 8) | pdev->devfn;
+ sfp_dev = platform_device_register_full(&info);
+ if (IS_ERR(sfp_dev))
+ return PTR_ERR(sfp_dev);
+
+ txgbe->sfp_dev = sfp_dev;
+
+ return 0;
+}
+
+int txgbe_init_phy(struct txgbe *txgbe)
+{
+ int ret;
+
+ ret = txgbe_swnodes_register(txgbe);
+ if (ret) {
+ wx_err(txgbe->wx, "failed to register software nodes\n");
+ return ret;
+ }
+
+ ret = txgbe_mdio_pcs_init(txgbe);
+ if (ret) {
+ wx_err(txgbe->wx, "failed to init mdio pcs: %d\n", ret);
+ goto err_unregister_swnode;
+ }
+
+ ret = txgbe_phylink_init(txgbe);
+ if (ret) {
+ wx_err(txgbe->wx, "failed to init phylink\n");
+ goto err_destroy_xpcs;
+ }
+
+ ret = txgbe_gpio_init(txgbe);
+ if (ret) {
+ wx_err(txgbe->wx, "failed to init gpio\n");
+ goto err_destroy_phylink;
+ }
+
+ ret = txgbe_clock_register(txgbe);
+ if (ret) {
+ wx_err(txgbe->wx, "failed to register clock: %d\n", ret);
+ goto err_destroy_phylink;
+ }
+
+ ret = txgbe_i2c_register(txgbe);
+ if (ret) {
+ wx_err(txgbe->wx, "failed to init i2c interface: %d\n", ret);
+ goto err_unregister_clk;
+ }
+
+ ret = txgbe_sfp_register(txgbe);
+ if (ret) {
+ wx_err(txgbe->wx, "failed to register sfp\n");
+ goto err_unregister_i2c;
+ }
+
+ return 0;
+
+err_unregister_i2c:
+ platform_device_unregister(txgbe->i2c_dev);
+err_unregister_clk:
+ clkdev_drop(txgbe->clock);
+ clk_unregister(txgbe->clk);
+err_destroy_phylink:
+ phylink_destroy(txgbe->phylink);
+err_destroy_xpcs:
+ xpcs_destroy(txgbe->xpcs);
+err_unregister_swnode:
+ software_node_unregister_node_group(txgbe->nodes.group);
+
+ return ret;
+}
+
+void txgbe_remove_phy(struct txgbe *txgbe)
+{
+ platform_device_unregister(txgbe->sfp_dev);
+ platform_device_unregister(txgbe->i2c_dev);
+ clkdev_drop(txgbe->clock);
+ clk_unregister(txgbe->clk);
+ phylink_destroy(txgbe->phylink);
+ xpcs_destroy(txgbe->xpcs);
+ software_node_unregister_node_group(txgbe->nodes.group);
+}
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h
new file mode 100644
index 000000000000..1ab592124986
--- /dev/null
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */
+
+#ifndef _TXGBE_PHY_H_
+#define _TXGBE_PHY_H_
+
+int txgbe_init_phy(struct txgbe *txgbe);
+void txgbe_remove_phy(struct txgbe *txgbe);
+
+#endif /* _TXGBE_NODE_H_ */
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
index 63a1c733718d..51199c355f95 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
@@ -4,6 +4,8 @@
#ifndef _TXGBE_TYPE_H_
#define _TXGBE_TYPE_H_
+#include <linux/property.h>
+
/* Device IDs */
#define TXGBE_DEV_ID_SP1000 0x1001
#define TXGBE_DEV_ID_WX1820 0x2001
@@ -53,6 +55,39 @@
#define TXGBE_TS_CTL 0x10300
#define TXGBE_TS_CTL_EVAL_MD BIT(31)
+/* GPIO register bit */
+#define TXGBE_GPIOBIT_0 BIT(0) /* I:tx fault */
+#define TXGBE_GPIOBIT_1 BIT(1) /* O:tx disabled */
+#define TXGBE_GPIOBIT_2 BIT(2) /* I:sfp module absent */
+#define TXGBE_GPIOBIT_3 BIT(3) /* I:rx signal lost */
+#define TXGBE_GPIOBIT_4 BIT(4) /* O:rate select, 1G(0) 10G(1) */
+#define TXGBE_GPIOBIT_5 BIT(5) /* O:rate select, 1G(0) 10G(1) */
+
+/* Extended Interrupt Enable Set */
+#define TXGBE_PX_MISC_ETH_LKDN BIT(8)
+#define TXGBE_PX_MISC_DEV_RST BIT(10)
+#define TXGBE_PX_MISC_ETH_EVENT BIT(17)
+#define TXGBE_PX_MISC_ETH_LK BIT(18)
+#define TXGBE_PX_MISC_ETH_AN BIT(19)
+#define TXGBE_PX_MISC_INT_ERR BIT(20)
+#define TXGBE_PX_MISC_GPIO BIT(26)
+#define TXGBE_PX_MISC_IEN_MASK \
+ (TXGBE_PX_MISC_ETH_LKDN | TXGBE_PX_MISC_DEV_RST | \
+ TXGBE_PX_MISC_ETH_EVENT | TXGBE_PX_MISC_ETH_LK | \
+ TXGBE_PX_MISC_ETH_AN | TXGBE_PX_MISC_INT_ERR | \
+ TXGBE_PX_MISC_GPIO)
+
+/* Port cfg registers */
+#define TXGBE_CFG_PORT_ST 0x14404
+#define TXGBE_CFG_PORT_ST_LINK_UP BIT(0)
+
+/* I2C registers */
+#define TXGBE_I2C_BASE 0x14900
+
+/************************************** ETH PHY ******************************/
+#define TXGBE_XPCS_IDA_ADDR 0x13000
+#define TXGBE_XPCS_IDA_DATA 0x13004
+
/* Part Number String Length */
#define TXGBE_PBANUM_LENGTH 32
@@ -77,6 +112,7 @@
#define TXGBE_SP_MAX_RX_QUEUES 128
#define TXGBE_SP_RAR_ENTRIES 128
#define TXGBE_SP_MC_TBL_SIZE 128
+#define TXGBE_SP_VFT_TBL_SIZE 128
#define TXGBE_SP_RX_PB_SIZE 512
#define TXGBE_SP_TDB_PB_SZ (160 * 1024) /* 160KB Packet Buffer */
@@ -99,4 +135,58 @@
extern char txgbe_driver_name[];
+static inline struct txgbe *netdev_to_txgbe(struct net_device *netdev)
+{
+ struct wx *wx = netdev_priv(netdev);
+
+ return wx->priv;
+}
+
+#define NODE_PROP(_NAME, _PROP) \
+ (const struct software_node) { \
+ .name = _NAME, \
+ .properties = _PROP, \
+ }
+
+enum txgbe_swnodes {
+ SWNODE_GPIO = 0,
+ SWNODE_I2C,
+ SWNODE_SFP,
+ SWNODE_PHYLINK,
+ SWNODE_MAX
+};
+
+struct txgbe_nodes {
+ char gpio_name[32];
+ char i2c_name[32];
+ char sfp_name[32];
+ char phylink_name[32];
+ struct property_entry gpio_props[1];
+ struct property_entry i2c_props[3];
+ struct property_entry sfp_props[8];
+ struct property_entry phylink_props[2];
+ struct software_node_ref_args i2c_ref[1];
+ struct software_node_ref_args gpio0_ref[1];
+ struct software_node_ref_args gpio1_ref[1];
+ struct software_node_ref_args gpio2_ref[1];
+ struct software_node_ref_args gpio3_ref[1];
+ struct software_node_ref_args gpio4_ref[1];
+ struct software_node_ref_args gpio5_ref[1];
+ struct software_node_ref_args sfp_ref[1];
+ struct software_node swnodes[SWNODE_MAX];
+ const struct software_node *group[SWNODE_MAX + 1];
+};
+
+struct txgbe {
+ struct wx *wx;
+ struct txgbe_nodes nodes;
+ struct dw_xpcs *xpcs;
+ struct phylink *phylink;
+ struct platform_device *sfp_dev;
+ struct platform_device *i2c_dev;
+ struct clk_lookup *clock;
+ struct clk *clk;
+ struct gpio_chip *gpio;
+};
+
#endif /* _TXGBE_TYPE_H_ */
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index e0ac1bcd9925..49f303353ecb 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -1567,12 +1567,16 @@ static int temac_probe(struct platform_device *pdev)
}
/* Error handle returned DMA RX and TX interrupts */
- if (lp->rx_irq < 0)
- return dev_err_probe(&pdev->dev, lp->rx_irq,
+ if (lp->rx_irq <= 0) {
+ rc = lp->rx_irq ?: -EINVAL;
+ return dev_err_probe(&pdev->dev, rc,
"could not get DMA RX irq\n");
- if (lp->tx_irq < 0)
- return dev_err_probe(&pdev->dev, lp->tx_irq,
+ }
+ if (lp->tx_irq <= 0) {
+ rc = lp->tx_irq ?: -EINVAL;
+ return dev_err_probe(&pdev->dev, rc,
"could not get DMA TX irq\n");
+ }
if (temac_np) {
/* Retrieve the MAC address */
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 3e310b55bce2..8e32dc50a408 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -1631,7 +1631,7 @@ static void axienet_pcs_an_restart(struct phylink_pcs *pcs)
phylink_mii_c22_pcs_an_restart(pcs_phy);
}
-static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -1653,7 +1653,8 @@ static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
}
}
- ret = phylink_mii_c22_pcs_config(pcs_phy, mode, interface, advertising);
+ ret = phylink_mii_c22_pcs_config(pcs_phy, interface, advertising,
+ neg_mode);
if (ret < 0)
netdev_warn(ndev, "Failed to configure PCS: %d\n", ret);
@@ -2042,6 +2043,11 @@ static int axienet_probe(struct platform_device *pdev)
goto cleanup_clk;
}
+ /* Reset core now that clocks are enabled, prior to accessing MDIO */
+ ret = __axienet_device_reset(lp);
+ if (ret)
+ goto cleanup_clk;
+
/* Autodetect the need for 64-bit DMA pointers.
* When the IP is configured for a bus width bigger than 32 bits,
* writing the MSB registers is mandatory, even if they are all 0.
@@ -2096,11 +2102,6 @@ static int axienet_probe(struct platform_device *pdev)
lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD;
lp->coalesce_usec_tx = XAXIDMA_DFT_TX_USEC;
- /* Reset core now that clocks are enabled, prior to accessing MDIO */
- ret = __axienet_device_reset(lp);
- if (ret)
- goto cleanup_clk;
-
ret = axienet_mdio_setup(lp);
if (ret)
dev_warn(&pdev->dev,
@@ -2129,6 +2130,7 @@ static int axienet_probe(struct platform_device *pdev)
}
of_node_put(np);
lp->pcs.ops = &axienet_pcs_ops;
+ lp->pcs.neg_mode = true;
lp->pcs.poll = true;
}
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 15c7dc82107f..acb20ad4e37e 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -631,7 +631,9 @@ static void __gtp_encap_destroy(struct sock *sk)
gtp->sk1u = NULL;
udp_sk(sk)->encap_type = 0;
rcu_assign_sk_user_data(sk, NULL);
+ release_sock(sk);
sock_put(sk);
+ return;
}
release_sock(sk);
}
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 33d51e363913..c9dd69dbe1b8 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -74,6 +74,7 @@ struct ndis_recv_scale_cap { /* NDIS_RECEIVE_SCALE_CAPABILITIES */
#define NDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_2 40
#define ITAB_NUM 128
+#define ITAB_NUM_MAX 256
struct ndis_recv_scale_param { /* NDIS_RECEIVE_SCALE_PARAMETERS */
struct ndis_obj_header hdr;
@@ -1034,7 +1035,9 @@ struct net_device_context {
u32 tx_table[VRSS_SEND_TAB_SIZE];
- u16 rx_table[ITAB_NUM];
+ u16 *rx_table;
+
+ u32 rx_table_sz;
/* Ethtool settings */
u8 duplex;
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 0103ff914024..3ba3c8fb28a5 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1747,7 +1747,9 @@ static u32 netvsc_get_rxfh_key_size(struct net_device *dev)
static u32 netvsc_rss_indir_size(struct net_device *dev)
{
- return ITAB_NUM;
+ struct net_device_context *ndc = netdev_priv(dev);
+
+ return ndc->rx_table_sz;
}
static int netvsc_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
@@ -1766,7 +1768,7 @@ static int netvsc_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
rndis_dev = ndev->extension;
if (indir) {
- for (i = 0; i < ITAB_NUM; i++)
+ for (i = 0; i < ndc->rx_table_sz; i++)
indir[i] = ndc->rx_table[i];
}
@@ -1792,11 +1794,11 @@ static int netvsc_set_rxfh(struct net_device *dev, const u32 *indir,
rndis_dev = ndev->extension;
if (indir) {
- for (i = 0; i < ITAB_NUM; i++)
+ for (i = 0; i < ndc->rx_table_sz; i++)
if (indir[i] >= ndev->num_chn)
return -EINVAL;
- for (i = 0; i < ITAB_NUM; i++)
+ for (i = 0; i < ndc->rx_table_sz; i++)
ndc->rx_table[i] = indir[i];
}
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index eea777ec2541..af95947a87c5 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -21,6 +21,7 @@
#include <linux/rtnetlink.h>
#include <linux/ucs2_string.h>
#include <linux/string.h>
+#include <linux/slab.h>
#include "hyperv_net.h"
#include "netvsc_trace.h"
@@ -927,7 +928,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev,
struct rndis_set_request *set;
struct rndis_set_complete *set_complete;
u32 extlen = sizeof(struct ndis_recv_scale_param) +
- 4 * ITAB_NUM + NETVSC_HASH_KEYLEN;
+ 4 * ndc->rx_table_sz + NETVSC_HASH_KEYLEN;
struct ndis_recv_scale_param *rssp;
u32 *itab;
u8 *keyp;
@@ -953,7 +954,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev,
rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 |
NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 |
NDIS_HASH_TCP_IPV6;
- rssp->indirect_tabsize = 4*ITAB_NUM;
+ rssp->indirect_tabsize = 4 * ndc->rx_table_sz;
rssp->indirect_taboffset = sizeof(struct ndis_recv_scale_param);
rssp->hashkey_size = NETVSC_HASH_KEYLEN;
rssp->hashkey_offset = rssp->indirect_taboffset +
@@ -961,7 +962,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev,
/* Set indirection table entries */
itab = (u32 *)(rssp + 1);
- for (i = 0; i < ITAB_NUM; i++)
+ for (i = 0; i < ndc->rx_table_sz; i++)
itab[i] = ndc->rx_table[i];
/* Set hask key values */
@@ -1548,6 +1549,18 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
if (ret || rsscap.num_recv_que < 2)
goto out;
+ if (rsscap.num_indirect_tabent &&
+ rsscap.num_indirect_tabent <= ITAB_NUM_MAX)
+ ndc->rx_table_sz = rsscap.num_indirect_tabent;
+ else
+ ndc->rx_table_sz = ITAB_NUM;
+
+ ndc->rx_table = kcalloc(ndc->rx_table_sz, sizeof(u16), GFP_KERNEL);
+ if (!ndc->rx_table) {
+ ret = -ENOMEM;
+ goto err_dev_remv;
+ }
+
/* This guarantees that num_possible_rss_qs <= num_online_cpus */
num_possible_rss_qs = min_t(u32, num_online_cpus(),
rsscap.num_recv_que);
@@ -1558,7 +1571,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
net_device->num_chn = min(net_device->max_chn, device_info->num_chn);
if (!netif_is_rxfh_configured(net)) {
- for (i = 0; i < ITAB_NUM; i++)
+ for (i = 0; i < ndc->rx_table_sz; i++)
ndc->rx_table[i] = ethtool_rxfh_indir_default(
i, net_device->num_chn);
}
@@ -1596,11 +1609,19 @@ void rndis_filter_device_remove(struct hv_device *dev,
struct netvsc_device *net_dev)
{
struct rndis_device *rndis_dev = net_dev->extension;
+ struct net_device *net = hv_get_drvdata(dev);
+ struct net_device_context *ndc;
+
+ ndc = netdev_priv(net);
/* Halt and release the rndis device */
rndis_filter_halt_device(net_dev, rndis_dev);
netvsc_device_remove(dev);
+
+ ndc->rx_table_sz = 0;
+ kfree(ndc->rx_table);
+ ndc->rx_table = NULL;
}
int rndis_filter_open(struct netvsc_device *nvdev)
diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c
index 0134ebac227a..f9b10e84de06 100644
--- a/drivers/net/ieee802154/ca8210.c
+++ b/drivers/net/ieee802154/ca8210.c
@@ -2855,7 +2855,6 @@ static int ca8210_interrupt_init(struct spi_device *spi)
);
if (ret) {
dev_crit(&spi->dev, "request_irq %d failed\n", pdata->irq_id);
- gpiod_unexport(gpio_to_desc(pdata->gpio_irq));
gpio_free(pdata->gpio_irq);
}
@@ -2945,7 +2944,8 @@ static void ca8210_hw_setup(struct ieee802154_hw *ca8210_hw)
ca8210_hw->phy->flags =
WPAN_PHY_FLAG_TXPOWER |
WPAN_PHY_FLAG_CCA_ED_LEVEL |
- WPAN_PHY_FLAG_CCA_MODE;
+ WPAN_PHY_FLAG_CCA_MODE |
+ WPAN_PHY_FLAG_DATAGRAMS_ONLY;
}
/**
diff --git a/drivers/net/ipa/ipa_table.c b/drivers/net/ipa/ipa_table.c
index f0529c31d0b6..7b637bb8b41c 100644
--- a/drivers/net/ipa/ipa_table.c
+++ b/drivers/net/ipa/ipa_table.c
@@ -273,16 +273,15 @@ static int ipa_filter_reset(struct ipa *ipa, bool modem)
if (ret)
return ret;
- ret = ipa_filter_reset_table(ipa, true, false, modem);
- if (ret)
+ ret = ipa_filter_reset_table(ipa, false, true, modem);
+ if (ret || !ipa_table_hash_support(ipa))
return ret;
- ret = ipa_filter_reset_table(ipa, false, true, modem);
+ ret = ipa_filter_reset_table(ipa, true, false, modem);
if (ret)
return ret;
- ret = ipa_filter_reset_table(ipa, true, true, modem);
- return ret;
+ return ipa_filter_reset_table(ipa, true, true, modem);
}
/* The AP routes and modem routes are each contiguous within the
@@ -291,12 +290,13 @@ static int ipa_filter_reset(struct ipa *ipa, bool modem)
* */
static int ipa_route_reset(struct ipa *ipa, bool modem)
{
+ bool hash_support = ipa_table_hash_support(ipa);
u32 modem_route_count = ipa->modem_route_count;
struct gsi_trans *trans;
u16 first;
u16 count;
- trans = ipa_cmd_trans_alloc(ipa, 4);
+ trans = ipa_cmd_trans_alloc(ipa, hash_support ? 4 : 2);
if (!trans) {
dev_err(&ipa->pdev->dev,
"no transaction for %s route reset\n",
@@ -313,10 +313,12 @@ static int ipa_route_reset(struct ipa *ipa, bool modem)
}
ipa_table_reset_add(trans, false, false, false, first, count);
- ipa_table_reset_add(trans, false, true, false, first, count);
-
ipa_table_reset_add(trans, false, false, true, first, count);
- ipa_table_reset_add(trans, false, true, true, first, count);
+
+ if (hash_support) {
+ ipa_table_reset_add(trans, false, true, false, first, count);
+ ipa_table_reset_add(trans, false, true, true, first, count);
+ }
gsi_trans_commit_wait(trans);
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index ab5133eb1d51..c0c49f181367 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -555,8 +555,7 @@ static void ipvlan_multicast_enqueue(struct ipvl_port *port,
spin_lock(&port->backlog.lock);
if (skb_queue_len(&port->backlog) < IPVLAN_QBACKLOG_LIMIT) {
- if (skb->dev)
- dev_hold(skb->dev);
+ dev_hold(skb->dev);
__skb_queue_tail(&port->backlog, skb);
spin_unlock(&port->backlog.lock);
schedule_work(&port->wq);
@@ -585,7 +584,8 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
consume_skb(skb);
return NET_XMIT_DROP;
}
- return ipvlan_rcv_frame(addr, &skb, true);
+ ipvlan_rcv_frame(addr, &skb, true);
+ return NET_XMIT_SUCCESS;
}
}
out:
@@ -611,7 +611,8 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
consume_skb(skb);
return NET_XMIT_DROP;
}
- return ipvlan_rcv_frame(addr, &skb, true);
+ ipvlan_rcv_frame(addr, &skb, true);
+ return NET_XMIT_SUCCESS;
}
}
skb = skb_share_check(skb, GFP_ATOMIC);
@@ -623,7 +624,8 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
* the skb for the main-dev. At the RX side we just return
* RX_PASS for it to be processed further on the stack.
*/
- return dev_forward_skb(ipvlan->phy_dev, skb);
+ dev_forward_skb(ipvlan->phy_dev, skb);
+ return NET_XMIT_SUCCESS;
} else if (is_multicast_ether_addr(eth->h_dest)) {
skb_reset_mac_header(skb);
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index b15dd9a3ad54..1b55928e89b8 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -748,7 +748,8 @@ static int ipvlan_device_event(struct notifier_block *unused,
write_pnet(&port->pnet, newnet);
- ipvlan_migrate_l3s_hook(oldnet, newnet);
+ if (port->mode == IPVLAN_MODE_L3S)
+ ipvlan_migrate_l3s_hook(oldnet, newnet);
break;
}
case NETDEV_UNREGISTER:
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index 984dfa5d6c11..144ec756c796 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -743,7 +743,7 @@ static bool macsec_post_decrypt(struct sk_buff *skb, struct macsec_secy *secy, u
u64_stats_update_begin(&rxsc_stats->syncp);
rxsc_stats->stats.InPktsLate++;
u64_stats_update_end(&rxsc_stats->syncp);
- secy->netdev->stats.rx_dropped++;
+ DEV_STATS_INC(secy->netdev, rx_dropped);
return false;
}
@@ -767,7 +767,7 @@ static bool macsec_post_decrypt(struct sk_buff *skb, struct macsec_secy *secy, u
rxsc_stats->stats.InPktsNotValid++;
u64_stats_update_end(&rxsc_stats->syncp);
this_cpu_inc(rx_sa->stats->InPktsNotValid);
- secy->netdev->stats.rx_errors++;
+ DEV_STATS_INC(secy->netdev, rx_errors);
return false;
}
@@ -1069,7 +1069,7 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
u64_stats_update_begin(&secy_stats->syncp);
secy_stats->stats.InPktsNoTag++;
u64_stats_update_end(&secy_stats->syncp);
- macsec->secy.netdev->stats.rx_dropped++;
+ DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
continue;
}
@@ -1179,7 +1179,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
u64_stats_update_begin(&secy_stats->syncp);
secy_stats->stats.InPktsBadTag++;
u64_stats_update_end(&secy_stats->syncp);
- secy->netdev->stats.rx_errors++;
+ DEV_STATS_INC(secy->netdev, rx_errors);
goto drop_nosa;
}
@@ -1196,7 +1196,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
u64_stats_update_begin(&rxsc_stats->syncp);
rxsc_stats->stats.InPktsNotUsingSA++;
u64_stats_update_end(&rxsc_stats->syncp);
- secy->netdev->stats.rx_errors++;
+ DEV_STATS_INC(secy->netdev, rx_errors);
if (active_rx_sa)
this_cpu_inc(active_rx_sa->stats->InPktsNotUsingSA);
goto drop_nosa;
@@ -1230,7 +1230,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
u64_stats_update_begin(&rxsc_stats->syncp);
rxsc_stats->stats.InPktsLate++;
u64_stats_update_end(&rxsc_stats->syncp);
- macsec->secy.netdev->stats.rx_dropped++;
+ DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
goto drop;
}
}
@@ -1271,7 +1271,7 @@ deliver:
if (ret == NET_RX_SUCCESS)
count_rx(dev, len);
else
- macsec->secy.netdev->stats.rx_dropped++;
+ DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
rcu_read_unlock();
@@ -1308,7 +1308,7 @@ nosci:
u64_stats_update_begin(&secy_stats->syncp);
secy_stats->stats.InPktsNoSCI++;
u64_stats_update_end(&secy_stats->syncp);
- macsec->secy.netdev->stats.rx_errors++;
+ DEV_STATS_INC(macsec->secy.netdev, rx_errors);
continue;
}
@@ -1327,7 +1327,7 @@ nosci:
secy_stats->stats.InPktsUnknownSCI++;
u64_stats_update_end(&secy_stats->syncp);
} else {
- macsec->secy.netdev->stats.rx_dropped++;
+ DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
}
}
@@ -3422,7 +3422,7 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
if (!secy->operational) {
kfree_skb(skb);
- dev->stats.tx_dropped++;
+ DEV_STATS_INC(dev, tx_dropped);
return NETDEV_TX_OK;
}
@@ -3430,7 +3430,7 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
skb = macsec_encrypt(skb, dev);
if (IS_ERR(skb)) {
if (PTR_ERR(skb) != -EINPROGRESS)
- dev->stats.tx_dropped++;
+ DEV_STATS_INC(dev, tx_dropped);
return NETDEV_TX_OK;
}
@@ -3667,9 +3667,9 @@ static void macsec_get_stats64(struct net_device *dev,
dev_fetch_sw_netstats(s, dev->tstats);
- s->rx_dropped = dev->stats.rx_dropped;
- s->tx_dropped = dev->stats.tx_dropped;
- s->rx_errors = dev->stats.rx_errors;
+ s->rx_dropped = atomic_long_read(&dev->stats.__rx_dropped);
+ s->tx_dropped = atomic_long_read(&dev->stats.__tx_dropped);
+ s->rx_errors = atomic_long_read(&dev->stats.__rx_errors);
}
static int macsec_get_iflink(const struct net_device *dev)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 4a53debf9d7c..ed908165a8b4 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1746,6 +1746,7 @@ static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = {
[IFLA_MACVLAN_MACADDR_COUNT] = { .type = NLA_U32 },
[IFLA_MACVLAN_BC_QUEUE_LEN] = { .type = NLA_U32 },
[IFLA_MACVLAN_BC_QUEUE_LEN_USED] = { .type = NLA_REJECT },
+ [IFLA_MACVLAN_BC_CUTOFF] = { .type = NLA_S32 },
};
int macvlan_link_register(struct rtnl_link_ops *ops)
diff --git a/drivers/net/mctp/mctp-i2c.c b/drivers/net/mctp/mctp-i2c.c
index 1d67a3ca1fd1..b37a9e4bade4 100644
--- a/drivers/net/mctp/mctp-i2c.c
+++ b/drivers/net/mctp/mctp-i2c.c
@@ -1058,7 +1058,7 @@ static struct i2c_driver mctp_i2c_driver = {
.name = "mctp-i2c-interface",
.of_match_table = mctp_i2c_of_match,
},
- .probe_new = mctp_i2c_probe,
+ .probe = mctp_i2c_probe,
.remove = mctp_i2c_remove,
.id_table = mctp_i2c_id,
};
diff --git a/drivers/net/mdio/Kconfig b/drivers/net/mdio/Kconfig
index 9ff2e6f22f3f..4a7a303be2f7 100644
--- a/drivers/net/mdio/Kconfig
+++ b/drivers/net/mdio/Kconfig
@@ -185,6 +185,17 @@ config MDIO_IPQ8064
This driver supports the MDIO interface found in the network
interface units of the IPQ8064 SoC
+config MDIO_REGMAP
+ tristate
+ help
+ This driver allows using MDIO devices that are not sitting on a
+ regular MDIO bus, but still exposes the standard 802.3 register
+ layout. It's regmap-based so that it can be used on integrated,
+ memory-mapped PHYs, SPI PHYs and so on. A new virtual MDIO bus is
+ created, and its read/write operations are mapped to the underlying
+ regmap. Users willing to use this driver must explicitly select
+ REGMAP.
+
config MDIO_THUNDER
tristate "ThunderX SOCs MDIO buses"
depends on 64BIT
diff --git a/drivers/net/mdio/Makefile b/drivers/net/mdio/Makefile
index 7d4cb4c11e4e..1015f0db4531 100644
--- a/drivers/net/mdio/Makefile
+++ b/drivers/net/mdio/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o
obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-mscc-miim.o
obj-$(CONFIG_MDIO_MVUSB) += mdio-mvusb.o
obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
+obj-$(CONFIG_MDIO_REGMAP) += mdio-regmap.o
obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o
obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o
obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o
diff --git a/drivers/net/mdio/mdio-bitbang.c b/drivers/net/mdio/mdio-bitbang.c
index b83932562be2..81b7748c10ce 100644
--- a/drivers/net/mdio/mdio-bitbang.c
+++ b/drivers/net/mdio/mdio-bitbang.c
@@ -186,7 +186,7 @@ int mdiobb_read_c45(struct mii_bus *bus, int phy, int devad, int reg)
struct mdiobb_ctrl *ctrl = bus->priv;
mdiobb_cmd_addr(ctrl, phy, devad, reg);
- mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg);
+ mdiobb_cmd(ctrl, MDIO_C45_READ, phy, devad);
return mdiobb_read_common(bus, phy);
}
@@ -222,7 +222,7 @@ int mdiobb_write_c45(struct mii_bus *bus, int phy, int devad, int reg, u16 val)
struct mdiobb_ctrl *ctrl = bus->priv;
mdiobb_cmd_addr(ctrl, phy, devad, reg);
- mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg);
+ mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, devad);
return mdiobb_write_common(bus, val);
}
diff --git a/drivers/net/mdio/mdio-mux-mmioreg.c b/drivers/net/mdio/mdio-mux-mmioreg.c
index c02c9c660016..09af150ed774 100644
--- a/drivers/net/mdio/mdio-mux-mmioreg.c
+++ b/drivers/net/mdio/mdio-mux-mmioreg.c
@@ -140,14 +140,15 @@ static int mdio_mux_mmioreg_probe(struct platform_device *pdev)
* set any bits outside of the 'mask'.
*/
for_each_available_child_of_node(np, np2) {
- iprop = of_get_property(np2, "reg", &len);
- if (!iprop || len != sizeof(uint32_t)) {
+ u64 reg;
+
+ if (of_property_read_reg(np2, 0, &reg, NULL)) {
dev_err(&pdev->dev, "mdio-mux child node %pOF is "
"missing a 'reg' property\n", np2);
of_node_put(np2);
return -ENODEV;
}
- if (be32_to_cpup(iprop) & ~s->mask) {
+ if ((u32)reg & ~s->mask) {
dev_err(&pdev->dev, "mdio-mux child node %pOF has "
"a 'reg' value with unmasked bits\n",
np2);
diff --git a/drivers/net/mdio/mdio-regmap.c b/drivers/net/mdio/mdio-regmap.c
new file mode 100644
index 000000000000..8a742a8d6387
--- /dev/null
+++ b/drivers/net/mdio/mdio-regmap.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Driver for MMIO-Mapped MDIO devices. Some IPs expose internal PHYs or PCS
+ * within the MMIO-mapped area
+ *
+ * Copyright (C) 2023 Maxime Chevallier <maxime.chevallier@bootlin.com>
+ */
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/mdio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_mdio.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/mdio/mdio-regmap.h>
+
+#define DRV_NAME "mdio-regmap"
+
+struct mdio_regmap_priv {
+ struct regmap *regmap;
+ u8 valid_addr;
+};
+
+static int mdio_regmap_read_c22(struct mii_bus *bus, int addr, int regnum)
+{
+ struct mdio_regmap_priv *ctx = bus->priv;
+ unsigned int val;
+ int ret;
+
+ if (ctx->valid_addr != addr)
+ return -ENODEV;
+
+ ret = regmap_read(ctx->regmap, regnum, &val);
+ if (ret < 0)
+ return ret;
+
+ return val;
+}
+
+static int mdio_regmap_write_c22(struct mii_bus *bus, int addr, int regnum,
+ u16 val)
+{
+ struct mdio_regmap_priv *ctx = bus->priv;
+
+ if (ctx->valid_addr != addr)
+ return -ENODEV;
+
+ return regmap_write(ctx->regmap, regnum, val);
+}
+
+struct mii_bus *devm_mdio_regmap_register(struct device *dev,
+ const struct mdio_regmap_config *config)
+{
+ struct mdio_regmap_priv *mr;
+ struct mii_bus *mii;
+ int rc;
+
+ if (!config->parent)
+ return ERR_PTR(-EINVAL);
+
+ mii = devm_mdiobus_alloc_size(config->parent, sizeof(*mr));
+ if (!mii)
+ return ERR_PTR(-ENOMEM);
+
+ mr = mii->priv;
+ mr->regmap = config->regmap;
+ mr->valid_addr = config->valid_addr;
+
+ mii->name = DRV_NAME;
+ strscpy(mii->id, config->name, MII_BUS_ID_SIZE);
+ mii->parent = config->parent;
+ mii->read = mdio_regmap_read_c22;
+ mii->write = mdio_regmap_write_c22;
+
+ if (config->autoscan)
+ mii->phy_mask = ~BIT(config->valid_addr);
+ else
+ mii->phy_mask = ~0;
+
+ rc = devm_mdiobus_register(dev, mii);
+ if (rc) {
+ dev_err(config->parent, "Cannot register MDIO bus![%s] (%d)\n", mii->id, rc);
+ return ERR_PTR(rc);
+ }
+
+ return mii;
+}
+EXPORT_SYMBOL_GPL(devm_mdio_regmap_register);
+
+MODULE_DESCRIPTION("MDIO API over regmap");
+MODULE_AUTHOR("Maxime Chevallier <maxime.chevallier@bootlin.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c
index 6045bece2654..b4d3b9cde8bd 100644
--- a/drivers/net/netdevsim/dev.c
+++ b/drivers/net/netdevsim/dev.c
@@ -184,13 +184,10 @@ static ssize_t nsim_dev_trap_fa_cookie_write(struct file *file,
cookie_len = (count - 1) / 2;
if ((count - 1) % 2)
return -EINVAL;
- buf = kmalloc(count, GFP_KERNEL | __GFP_NOWARN);
- if (!buf)
- return -ENOMEM;
- ret = simple_write_to_buffer(buf, count, ppos, data, count);
- if (ret < 0)
- goto free_buf;
+ buf = memdup_user(data, count);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
fa_cookie = kmalloc(sizeof(*fa_cookie) + cookie_len,
GFP_KERNEL | __GFP_NOWARN);
diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c
index 85dbe7f73e31..536bd6564f8b 100644
--- a/drivers/net/ntb_netdev.c
+++ b/drivers/net/ntb_netdev.c
@@ -493,7 +493,7 @@ static int __init ntb_netdev_init_module(void)
return 0;
}
-module_init(ntb_netdev_init_module);
+late_initcall(ntb_netdev_init_module);
static void __exit ntb_netdev_exit_module(void)
{
diff --git a/drivers/net/pcs/Kconfig b/drivers/net/pcs/Kconfig
index 7c34fb7cbf7b..87cf308fc6d8 100644
--- a/drivers/net/pcs/Kconfig
+++ b/drivers/net/pcs/Kconfig
@@ -33,10 +33,4 @@ config PCS_RZN1_MIIC
on RZ/N1 SoCs. This PCS converts MII to RMII/RGMII or can be set in
pass-through mode for MII.
-config PCS_ALTERA_TSE
- tristate
- help
- This module provides helper functions for the Altera Triple Speed
- Ethernet SGMII PCS, that can be found on the Intel Socfpga family.
-
endmenu
diff --git a/drivers/net/pcs/Makefile b/drivers/net/pcs/Makefile
index 9b9afd6b1c22..ea662a7989b2 100644
--- a/drivers/net/pcs/Makefile
+++ b/drivers/net/pcs/Makefile
@@ -7,4 +7,3 @@ obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o
obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o
obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o
obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o
-obj-$(CONFIG_PCS_ALTERA_TSE) += pcs-altera-tse.o
diff --git a/drivers/net/pcs/pcs-altera-tse.c b/drivers/net/pcs/pcs-altera-tse.c
deleted file mode 100644
index d616749761f4..000000000000
--- a/drivers/net/pcs/pcs-altera-tse.c
+++ /dev/null
@@ -1,160 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2022 Bootlin
- *
- * Maxime Chevallier <maxime.chevallier@bootlin.com>
- */
-
-#include <linux/netdevice.h>
-#include <linux/phy.h>
-#include <linux/phylink.h>
-#include <linux/pcs-altera-tse.h>
-
-/* SGMII PCS register addresses
- */
-#define SGMII_PCS_LINK_TIMER_0 0x12
-#define SGMII_PCS_LINK_TIMER_1 0x13
-#define SGMII_PCS_IF_MODE 0x14
-#define PCS_IF_MODE_SGMII_ENA BIT(0)
-#define PCS_IF_MODE_USE_SGMII_AN BIT(1)
-#define PCS_IF_MODE_SGMI_HALF_DUPLEX BIT(4)
-#define PCS_IF_MODE_SGMI_PHY_AN BIT(5)
-#define SGMII_PCS_SW_RESET_TIMEOUT 100 /* usecs */
-
-struct altera_tse_pcs {
- struct phylink_pcs pcs;
- void __iomem *base;
- int reg_width;
-};
-
-static struct altera_tse_pcs *phylink_pcs_to_tse_pcs(struct phylink_pcs *pcs)
-{
- return container_of(pcs, struct altera_tse_pcs, pcs);
-}
-
-static u16 tse_pcs_read(struct altera_tse_pcs *tse_pcs, int regnum)
-{
- if (tse_pcs->reg_width == 4)
- return readl(tse_pcs->base + regnum * 4);
- else
- return readw(tse_pcs->base + regnum * 2);
-}
-
-static void tse_pcs_write(struct altera_tse_pcs *tse_pcs, int regnum,
- u16 value)
-{
- if (tse_pcs->reg_width == 4)
- writel(value, tse_pcs->base + regnum * 4);
- else
- writew(value, tse_pcs->base + regnum * 2);
-}
-
-static int tse_pcs_reset(struct altera_tse_pcs *tse_pcs)
-{
- u16 bmcr;
-
- /* Reset PCS block */
- bmcr = tse_pcs_read(tse_pcs, MII_BMCR);
- bmcr |= BMCR_RESET;
- tse_pcs_write(tse_pcs, MII_BMCR, bmcr);
-
- return read_poll_timeout(tse_pcs_read, bmcr, (bmcr & BMCR_RESET),
- 10, SGMII_PCS_SW_RESET_TIMEOUT, 1,
- tse_pcs, MII_BMCR);
-}
-
-static int alt_tse_pcs_validate(struct phylink_pcs *pcs,
- unsigned long *supported,
- const struct phylink_link_state *state)
-{
- if (state->interface == PHY_INTERFACE_MODE_SGMII ||
- state->interface == PHY_INTERFACE_MODE_1000BASEX)
- return 1;
-
- return -EINVAL;
-}
-
-static int alt_tse_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
- phy_interface_t interface,
- const unsigned long *advertising,
- bool permit_pause_to_mac)
-{
- struct altera_tse_pcs *tse_pcs = phylink_pcs_to_tse_pcs(pcs);
- u32 ctrl, if_mode;
-
- ctrl = tse_pcs_read(tse_pcs, MII_BMCR);
- if_mode = tse_pcs_read(tse_pcs, SGMII_PCS_IF_MODE);
-
- /* Set link timer to 1.6ms, as per the MegaCore Function User Guide */
- tse_pcs_write(tse_pcs, SGMII_PCS_LINK_TIMER_0, 0x0D40);
- tse_pcs_write(tse_pcs, SGMII_PCS_LINK_TIMER_1, 0x03);
-
- if (interface == PHY_INTERFACE_MODE_SGMII) {
- if_mode |= PCS_IF_MODE_USE_SGMII_AN | PCS_IF_MODE_SGMII_ENA;
- } else if (interface == PHY_INTERFACE_MODE_1000BASEX) {
- if_mode &= ~(PCS_IF_MODE_USE_SGMII_AN | PCS_IF_MODE_SGMII_ENA);
- }
-
- ctrl |= (BMCR_SPEED1000 | BMCR_FULLDPLX | BMCR_ANENABLE);
-
- tse_pcs_write(tse_pcs, MII_BMCR, ctrl);
- tse_pcs_write(tse_pcs, SGMII_PCS_IF_MODE, if_mode);
-
- return tse_pcs_reset(tse_pcs);
-}
-
-static void alt_tse_pcs_get_state(struct phylink_pcs *pcs,
- struct phylink_link_state *state)
-{
- struct altera_tse_pcs *tse_pcs = phylink_pcs_to_tse_pcs(pcs);
- u16 bmsr, lpa;
-
- bmsr = tse_pcs_read(tse_pcs, MII_BMSR);
- lpa = tse_pcs_read(tse_pcs, MII_LPA);
-
- phylink_mii_c22_pcs_decode_state(state, bmsr, lpa);
-}
-
-static void alt_tse_pcs_an_restart(struct phylink_pcs *pcs)
-{
- struct altera_tse_pcs *tse_pcs = phylink_pcs_to_tse_pcs(pcs);
- u16 bmcr;
-
- bmcr = tse_pcs_read(tse_pcs, MII_BMCR);
- bmcr |= BMCR_ANRESTART;
- tse_pcs_write(tse_pcs, MII_BMCR, bmcr);
-
- /* This PCS seems to require a soft reset to re-sync the AN logic */
- tse_pcs_reset(tse_pcs);
-}
-
-static const struct phylink_pcs_ops alt_tse_pcs_ops = {
- .pcs_validate = alt_tse_pcs_validate,
- .pcs_get_state = alt_tse_pcs_get_state,
- .pcs_config = alt_tse_pcs_config,
- .pcs_an_restart = alt_tse_pcs_an_restart,
-};
-
-struct phylink_pcs *alt_tse_pcs_create(struct net_device *ndev,
- void __iomem *pcs_base, int reg_width)
-{
- struct altera_tse_pcs *tse_pcs;
-
- if (reg_width != 4 && reg_width != 2)
- return ERR_PTR(-EINVAL);
-
- tse_pcs = devm_kzalloc(&ndev->dev, sizeof(*tse_pcs), GFP_KERNEL);
- if (!tse_pcs)
- return ERR_PTR(-ENOMEM);
-
- tse_pcs->pcs.ops = &alt_tse_pcs_ops;
- tse_pcs->base = pcs_base;
- tse_pcs->reg_width = reg_width;
-
- return &tse_pcs->pcs;
-}
-EXPORT_SYMBOL_GPL(alt_tse_pcs_create);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Altera TSE PCS driver");
-MODULE_AUTHOR("Maxime Chevallier <maxime.chevallier@bootlin.com>");
diff --git a/drivers/net/pcs/pcs-lynx.c b/drivers/net/pcs/pcs-lynx.c
index 622c3de3f3a8..9021b96d4f9d 100644
--- a/drivers/net/pcs/pcs-lynx.c
+++ b/drivers/net/pcs/pcs-lynx.c
@@ -6,6 +6,7 @@
#include <linux/mdio.h>
#include <linux/phylink.h>
#include <linux/pcs-lynx.h>
+#include <linux/property.h>
#define SGMII_CLOCK_PERIOD_NS 8 /* PCS is clocked at 125 MHz */
#define LINK_TIMER_VAL(ns) ((u32)((ns) / SGMII_CLOCK_PERIOD_NS))
@@ -34,14 +35,6 @@ enum sgmii_speed {
#define phylink_pcs_to_lynx(pl_pcs) container_of((pl_pcs), struct lynx_pcs, pcs)
#define lynx_to_phylink_pcs(lynx) (&(lynx)->pcs)
-struct mdio_device *lynx_get_mdio_device(struct phylink_pcs *pcs)
-{
- struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs);
-
- return lynx->mdio;
-}
-EXPORT_SYMBOL(lynx_get_mdio_device);
-
static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs,
struct phylink_link_state *state)
{
@@ -119,9 +112,10 @@ static void lynx_pcs_get_state(struct phylink_pcs *pcs,
state->link, state->an_complete);
}
-static int lynx_pcs_config_giga(struct mdio_device *pcs, unsigned int mode,
+static int lynx_pcs_config_giga(struct mdio_device *pcs,
phy_interface_t interface,
- const unsigned long *advertising)
+ const unsigned long *advertising,
+ unsigned int neg_mode)
{
int link_timer_ns;
u32 link_timer;
@@ -139,8 +133,9 @@ static int lynx_pcs_config_giga(struct mdio_device *pcs, unsigned int mode,
if (interface == PHY_INTERFACE_MODE_1000BASEX) {
if_mode = 0;
} else {
+ /* SGMII and QSGMII */
if_mode = IF_MODE_SGMII_EN;
- if (mode == MLO_AN_INBAND)
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
if_mode |= IF_MODE_USE_SGMII_AN;
}
@@ -150,16 +145,18 @@ static int lynx_pcs_config_giga(struct mdio_device *pcs, unsigned int mode,
if (err)
return err;
- return phylink_mii_c22_pcs_config(pcs, mode, interface, advertising);
+ return phylink_mii_c22_pcs_config(pcs, interface, advertising,
+ neg_mode);
}
-static int lynx_pcs_config_usxgmii(struct mdio_device *pcs, unsigned int mode,
- const unsigned long *advertising)
+static int lynx_pcs_config_usxgmii(struct mdio_device *pcs,
+ const unsigned long *advertising,
+ unsigned int neg_mode)
{
struct mii_bus *bus = pcs->bus;
int addr = pcs->addr;
- if (!phylink_autoneg_inband(mode)) {
+ if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) {
dev_err(&pcs->dev, "USXGMII only supports in-band AN for now\n");
return -EOPNOTSUPP;
}
@@ -171,10 +168,9 @@ static int lynx_pcs_config_usxgmii(struct mdio_device *pcs, unsigned int mode,
ADVERTISE_SGMII | ADVERTISE_LPACK);
}
-static int lynx_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+static int lynx_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t ifmode,
- const unsigned long *advertising,
- bool permit)
+ const unsigned long *advertising, bool permit)
{
struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs);
@@ -182,17 +178,18 @@ static int lynx_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
case PHY_INTERFACE_MODE_1000BASEX:
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_QSGMII:
- return lynx_pcs_config_giga(lynx->mdio, mode, ifmode,
- advertising);
+ return lynx_pcs_config_giga(lynx->mdio, ifmode, advertising,
+ neg_mode);
case PHY_INTERFACE_MODE_2500BASEX:
- if (phylink_autoneg_inband(mode)) {
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
dev_err(&lynx->mdio->dev,
"AN not supported on 3.125GHz SerDes lane\n");
return -EOPNOTSUPP;
}
break;
case PHY_INTERFACE_MODE_USXGMII:
- return lynx_pcs_config_usxgmii(lynx->mdio, mode, advertising);
+ return lynx_pcs_config_usxgmii(lynx->mdio, advertising,
+ neg_mode);
case PHY_INTERFACE_MODE_10GBASER:
/* Nothing to do here for 10GBASER */
break;
@@ -210,7 +207,8 @@ static void lynx_pcs_an_restart(struct phylink_pcs *pcs)
phylink_mii_c22_pcs_an_restart(lynx->mdio);
}
-static void lynx_pcs_link_up_sgmii(struct mdio_device *pcs, unsigned int mode,
+static void lynx_pcs_link_up_sgmii(struct mdio_device *pcs,
+ unsigned int neg_mode,
int speed, int duplex)
{
u16 if_mode = 0, sgmii_speed;
@@ -218,7 +216,7 @@ static void lynx_pcs_link_up_sgmii(struct mdio_device *pcs, unsigned int mode,
/* The PCS needs to be configured manually only
* when not operating on in-band mode
*/
- if (mode == MLO_AN_INBAND)
+ if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED)
return;
if (duplex == DUPLEX_HALF)
@@ -265,12 +263,12 @@ static void lynx_pcs_link_up_sgmii(struct mdio_device *pcs, unsigned int mode,
* 2500 Mbps and we do rate adaptation through pause frames.
*/
static void lynx_pcs_link_up_2500basex(struct mdio_device *pcs,
- unsigned int mode,
+ unsigned int neg_mode,
int speed, int duplex)
{
u16 if_mode = 0;
- if (mode == MLO_AN_INBAND) {
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
dev_err(&pcs->dev, "AN not supported for 2500BaseX\n");
return;
}
@@ -284,7 +282,7 @@ static void lynx_pcs_link_up_2500basex(struct mdio_device *pcs,
if_mode);
}
-static void lynx_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
+static void lynx_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
int speed, int duplex)
{
@@ -293,10 +291,10 @@ static void lynx_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
switch (interface) {
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_QSGMII:
- lynx_pcs_link_up_sgmii(lynx->mdio, mode, speed, duplex);
+ lynx_pcs_link_up_sgmii(lynx->mdio, neg_mode, speed, duplex);
break;
case PHY_INTERFACE_MODE_2500BASEX:
- lynx_pcs_link_up_2500basex(lynx->mdio, mode, speed, duplex);
+ lynx_pcs_link_up_2500basex(lynx->mdio, neg_mode, speed, duplex);
break;
case PHY_INTERFACE_MODE_USXGMII:
/* At the moment, only in-band AN is supported for USXGMII
@@ -315,26 +313,87 @@ static const struct phylink_pcs_ops lynx_pcs_phylink_ops = {
.pcs_link_up = lynx_pcs_link_up,
};
-struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio)
+static struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio)
{
struct lynx_pcs *lynx;
lynx = kzalloc(sizeof(*lynx), GFP_KERNEL);
if (!lynx)
- return NULL;
+ return ERR_PTR(-ENOMEM);
+ mdio_device_get(mdio);
lynx->mdio = mdio;
lynx->pcs.ops = &lynx_pcs_phylink_ops;
+ lynx->pcs.neg_mode = true;
lynx->pcs.poll = true;
return lynx_to_phylink_pcs(lynx);
}
-EXPORT_SYMBOL(lynx_pcs_create);
+
+struct phylink_pcs *lynx_pcs_create_mdiodev(struct mii_bus *bus, int addr)
+{
+ struct mdio_device *mdio;
+ struct phylink_pcs *pcs;
+
+ mdio = mdio_device_create(bus, addr);
+ if (IS_ERR(mdio))
+ return ERR_CAST(mdio);
+
+ pcs = lynx_pcs_create(mdio);
+
+ /* lynx_create() has taken a refcount on the mdiodev if it was
+ * successful. If lynx_create() fails, this will free the mdio
+ * device here. In any case, we don't need to hold our reference
+ * anymore, and putting it here will allow mdio_device_put() in
+ * lynx_destroy() to automatically free the mdio device.
+ */
+ mdio_device_put(mdio);
+
+ return pcs;
+}
+EXPORT_SYMBOL(lynx_pcs_create_mdiodev);
+
+/*
+ * lynx_pcs_create_fwnode() creates a lynx PCS instance from the fwnode
+ * device indicated by node.
+ *
+ * Returns:
+ * -ENODEV if the fwnode is marked unavailable
+ * -EPROBE_DEFER if we fail to find the device
+ * -ENOMEM if we fail to allocate memory
+ * pointer to a phylink_pcs on success
+ */
+struct phylink_pcs *lynx_pcs_create_fwnode(struct fwnode_handle *node)
+{
+ struct mdio_device *mdio;
+ struct phylink_pcs *pcs;
+
+ if (!fwnode_device_is_available(node))
+ return ERR_PTR(-ENODEV);
+
+ mdio = fwnode_mdio_find_device(node);
+ if (!mdio)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ pcs = lynx_pcs_create(mdio);
+
+ /* lynx_create() has taken a refcount on the mdiodev if it was
+ * successful. If lynx_create() fails, this will free the mdio
+ * device here. In any case, we don't need to hold our reference
+ * anymore, and putting it here will allow mdio_device_put() in
+ * lynx_destroy() to automatically free the mdio device.
+ */
+ mdio_device_put(mdio);
+
+ return pcs;
+}
+EXPORT_SYMBOL_GPL(lynx_pcs_create_fwnode);
void lynx_pcs_destroy(struct phylink_pcs *pcs)
{
struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs);
+ mdio_device_put(lynx->mdio);
kfree(lynx);
}
EXPORT_SYMBOL(lynx_pcs_destroy);
diff --git a/drivers/net/pcs/pcs-mtk-lynxi.c b/drivers/net/pcs/pcs-mtk-lynxi.c
index 888452325edc..b0f3ede945d9 100644
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
@@ -102,13 +102,13 @@ static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs,
FIELD_GET(SGMII_LPA, adv));
}
-static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int mode,
+static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
{
struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
- bool mode_changed = false, changed, use_an;
+ bool mode_changed = false, changed;
unsigned int rgc3, sgm_mode, bmcr;
int advertise, link_timer;
@@ -121,30 +121,21 @@ static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int mode,
* we assume that fixes it's speed at bitrate = line rate (in
* other words, 1000Mbps or 2500Mbps).
*/
- if (interface == PHY_INTERFACE_MODE_SGMII) {
+ if (interface == PHY_INTERFACE_MODE_SGMII)
sgm_mode = SGMII_IF_MODE_SGMII;
- if (phylink_autoneg_inband(mode)) {
- sgm_mode |= SGMII_REMOTE_FAULT_DIS |
- SGMII_SPEED_DUPLEX_AN;
- use_an = true;
- } else {
- use_an = false;
- }
- } else if (phylink_autoneg_inband(mode)) {
- /* 1000base-X or 2500base-X autoneg */
- sgm_mode = SGMII_REMOTE_FAULT_DIS;
- use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
- advertising);
- } else {
- /* 1000base-X or 2500base-X without autoneg */
+ else
sgm_mode = 0;
- use_an = false;
- }
- if (use_an)
+ if (neg_mode & PHYLINK_PCS_NEG_INBAND)
+ sgm_mode |= SGMII_REMOTE_FAULT_DIS;
+
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
+ if (interface == PHY_INTERFACE_MODE_SGMII)
+ sgm_mode |= SGMII_SPEED_DUPLEX_AN;
bmcr = BMCR_ANENABLE;
- else
+ } else {
bmcr = 0;
+ }
if (mpcs->interface != interface) {
link_timer = phylink_get_link_timer_ns(interface);
@@ -216,14 +207,15 @@ static void mtk_pcs_lynxi_restart_an(struct phylink_pcs *pcs)
regmap_set_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, BMCR_ANRESTART);
}
-static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, unsigned int mode,
+static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs,
+ unsigned int neg_mode,
phy_interface_t interface, int speed,
int duplex)
{
struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
unsigned int sgm_mode;
- if (!phylink_autoneg_inband(mode)) {
+ if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) {
/* Force the speed and duplex setting */
if (speed == SPEED_10)
sgm_mode = SGMII_SPEED_10;
@@ -286,6 +278,7 @@ struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev,
mpcs->regmap = regmap;
mpcs->flags = flags;
mpcs->pcs.ops = &mtk_pcs_lynxi_ops;
+ mpcs->pcs.neg_mode = true;
mpcs->pcs.poll = true;
mpcs->interface = PHY_INTERFACE_MODE_NA;
diff --git a/drivers/net/pcs/pcs-rzn1-miic.c b/drivers/net/pcs/pcs-rzn1-miic.c
index 323bec5e57f8..356099169003 100644
--- a/drivers/net/pcs/pcs-rzn1-miic.c
+++ b/drivers/net/pcs/pcs-rzn1-miic.c
@@ -313,15 +313,21 @@ struct phylink_pcs *miic_create(struct device *dev, struct device_node *np)
pdev = of_find_device_by_node(pcs_np);
of_node_put(pcs_np);
- if (!pdev || !platform_get_drvdata(pdev))
+ if (!pdev || !platform_get_drvdata(pdev)) {
+ if (pdev)
+ put_device(&pdev->dev);
return ERR_PTR(-EPROBE_DEFER);
+ }
miic_port = kzalloc(sizeof(*miic_port), GFP_KERNEL);
- if (!miic_port)
+ if (!miic_port) {
+ put_device(&pdev->dev);
return ERR_PTR(-ENOMEM);
+ }
miic = platform_get_drvdata(pdev);
device_link_add(dev, miic->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
+ put_device(&pdev->dev);
miic_port->miic = miic;
miic_port->port = port - 1;
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index 72f25e778840..44b037646865 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -64,6 +64,16 @@ static const int xpcs_xlgmii_features[] = {
__ETHTOOL_LINK_MODE_MASK_NBITS,
};
+static const int xpcs_10gbaser_features[] = {
+ ETHTOOL_LINK_MODE_Pause_BIT,
+ ETHTOOL_LINK_MODE_Asym_Pause_BIT,
+ ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
+ __ETHTOOL_LINK_MODE_MASK_NBITS,
+};
+
static const int xpcs_sgmii_features[] = {
ETHTOOL_LINK_MODE_Pause_BIT,
ETHTOOL_LINK_MODE_Asym_Pause_BIT,
@@ -106,6 +116,10 @@ static const phy_interface_t xpcs_xlgmii_interfaces[] = {
PHY_INTERFACE_MODE_XLGMII,
};
+static const phy_interface_t xpcs_10gbaser_interfaces[] = {
+ PHY_INTERFACE_MODE_10GBASER,
+};
+
static const phy_interface_t xpcs_sgmii_interfaces[] = {
PHY_INTERFACE_MODE_SGMII,
};
@@ -123,6 +137,7 @@ enum {
DW_XPCS_USXGMII,
DW_XPCS_10GKR,
DW_XPCS_XLGMII,
+ DW_XPCS_10GBASER,
DW_XPCS_SGMII,
DW_XPCS_1000BASEX,
DW_XPCS_2500BASEX,
@@ -246,6 +261,7 @@ static int xpcs_soft_reset(struct dw_xpcs *xpcs,
switch (compat->an_mode) {
case DW_AN_C73:
+ case DW_10GBASER:
dev = MDIO_MMD_PCS;
break;
case DW_AN_C37_SGMII:
@@ -271,15 +287,12 @@ static int xpcs_soft_reset(struct dw_xpcs *xpcs,
})
static int xpcs_read_fault_c73(struct dw_xpcs *xpcs,
- struct phylink_link_state *state)
+ struct phylink_link_state *state,
+ u16 pcs_stat1)
{
int ret;
- ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1);
- if (ret < 0)
- return ret;
-
- if (ret & MDIO_STAT1_FAULT) {
+ if (pcs_stat1 & MDIO_STAT1_FAULT) {
xpcs_warn(xpcs, state, "Link fault condition detected!\n");
return -EFAULT;
}
@@ -321,37 +334,6 @@ static int xpcs_read_fault_c73(struct dw_xpcs *xpcs,
return 0;
}
-static int xpcs_read_link_c73(struct dw_xpcs *xpcs)
-{
- bool link = true;
- int ret;
-
- ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1);
- if (ret < 0)
- return ret;
-
- if (!(ret & MDIO_STAT1_LSTATUS))
- link = false;
-
- return link;
-}
-
-static int xpcs_get_max_usxgmii_speed(const unsigned long *supported)
-{
- int max = SPEED_UNKNOWN;
-
- if (phylink_test(supported, 1000baseKX_Full))
- max = SPEED_1000;
- if (phylink_test(supported, 2500baseX_Full))
- max = SPEED_2500;
- if (phylink_test(supported, 10000baseKX4_Full))
- max = SPEED_10000;
- if (phylink_test(supported, 10000baseKR_Full))
- max = SPEED_10000;
-
- return max;
-}
-
static void xpcs_config_usxgmii(struct dw_xpcs *xpcs, int speed)
{
int ret, speed_sel;
@@ -478,16 +460,12 @@ static int xpcs_config_aneg_c73(struct dw_xpcs *xpcs,
static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs,
struct phylink_link_state *state,
- const struct xpcs_compat *compat)
+ const struct xpcs_compat *compat, u16 an_stat1)
{
int ret;
- ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
- if (ret < 0)
- return ret;
-
- if (ret & MDIO_AN_STAT1_COMPLETE) {
- ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1);
+ if (an_stat1 & MDIO_AN_STAT1_COMPLETE) {
+ ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_AN_LPA);
if (ret < 0)
return ret;
@@ -504,64 +482,32 @@ static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs,
}
static int xpcs_read_lpa_c73(struct dw_xpcs *xpcs,
- struct phylink_link_state *state)
+ struct phylink_link_state *state, u16 an_stat1)
{
- int ret;
-
- ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
- if (ret < 0)
- return ret;
+ u16 lpa[3];
+ int i, ret;
- if (!(ret & MDIO_AN_STAT1_LPABLE)) {
+ if (!(an_stat1 & MDIO_AN_STAT1_LPABLE)) {
phylink_clear(state->lp_advertising, Autoneg);
return 0;
}
phylink_set(state->lp_advertising, Autoneg);
- /* Clause 73 outcome */
- ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL3);
- if (ret < 0)
- return ret;
-
- if (ret & DW_C73_2500KX)
- phylink_set(state->lp_advertising, 2500baseX_Full);
-
- ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL2);
- if (ret < 0)
- return ret;
-
- if (ret & DW_C73_1000KX)
- phylink_set(state->lp_advertising, 1000baseKX_Full);
- if (ret & DW_C73_10000KX4)
- phylink_set(state->lp_advertising, 10000baseKX4_Full);
- if (ret & DW_C73_10000KR)
- phylink_set(state->lp_advertising, 10000baseKR_Full);
+ /* Read Clause 73 link partner advertisement */
+ for (i = ARRAY_SIZE(lpa); --i >= 0; ) {
+ ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_AN_LPA + i);
+ if (ret < 0)
+ return ret;
- ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1);
- if (ret < 0)
- return ret;
+ lpa[i] = ret;
+ }
- if (ret & DW_C73_PAUSE)
- phylink_set(state->lp_advertising, Pause);
- if (ret & DW_C73_ASYM_PAUSE)
- phylink_set(state->lp_advertising, Asym_Pause);
+ mii_c73_mod_linkmode(state->lp_advertising, lpa);
- linkmode_and(state->lp_advertising, state->lp_advertising,
- state->advertising);
return 0;
}
-static void xpcs_resolve_lpa_c73(struct dw_xpcs *xpcs,
- struct phylink_link_state *state)
-{
- int max_speed = xpcs_get_max_usxgmii_speed(state->lp_advertising);
-
- state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX;
- state->speed = max_speed;
- state->duplex = DUPLEX_FULL;
-}
-
static int xpcs_get_max_xlgmii_speed(struct dw_xpcs *xpcs,
struct phylink_link_state *state)
{
@@ -711,7 +657,8 @@ int xpcs_config_eee(struct dw_xpcs *xpcs, int mult_fact_100ns, int enable)
}
EXPORT_SYMBOL_GPL(xpcs_config_eee);
-static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, unsigned int mode)
+static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs,
+ unsigned int neg_mode)
{
int ret, mdio_ctrl;
@@ -761,7 +708,7 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, unsigned int mode)
if (ret < 0)
return ret;
- if (phylink_autoneg_inband(mode))
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
ret |= DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
else
ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
@@ -770,14 +717,15 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, unsigned int mode)
if (ret < 0)
return ret;
- if (phylink_autoneg_inband(mode))
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL,
mdio_ctrl | AN_CL37_EN);
return ret;
}
-static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs, unsigned int mode,
+static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs,
+ unsigned int neg_mode,
const unsigned long *advertising)
{
phy_interface_t interface = PHY_INTERFACE_MODE_1000BASEX;
@@ -828,8 +776,7 @@ static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs, unsigned int mod
if (ret < 0)
return ret;
- if (phylink_autoneg_inband(mode) &&
- linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising)) {
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL,
mdio_ctrl | AN_CL37_EN);
if (ret < 0)
@@ -862,7 +809,7 @@ static int xpcs_config_2500basex(struct dw_xpcs *xpcs)
}
int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
- unsigned int mode, const unsigned long *advertising)
+ const unsigned long *advertising, unsigned int neg_mode)
{
const struct xpcs_compat *compat;
int ret;
@@ -872,20 +819,22 @@ int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
return -ENODEV;
switch (compat->an_mode) {
+ case DW_10GBASER:
+ break;
case DW_AN_C73:
- if (test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising)) {
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
ret = xpcs_config_aneg_c73(xpcs, compat);
if (ret)
return ret;
}
break;
case DW_AN_C37_SGMII:
- ret = xpcs_config_aneg_c37_sgmii(xpcs, mode);
+ ret = xpcs_config_aneg_c37_sgmii(xpcs, neg_mode);
if (ret)
return ret;
break;
case DW_AN_C37_1000BASEX:
- ret = xpcs_config_aneg_c37_1000basex(xpcs, mode,
+ ret = xpcs_config_aneg_c37_1000basex(xpcs, neg_mode,
advertising);
if (ret)
return ret;
@@ -909,14 +858,14 @@ int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
}
EXPORT_SYMBOL_GPL(xpcs_do_config);
-static int xpcs_config(struct phylink_pcs *pcs, unsigned int mode,
+static int xpcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
{
struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
- return xpcs_do_config(xpcs, interface, mode, advertising);
+ return xpcs_do_config(xpcs, interface, advertising, neg_mode);
}
static int xpcs_get_state_c73(struct dw_xpcs *xpcs,
@@ -924,13 +873,25 @@ static int xpcs_get_state_c73(struct dw_xpcs *xpcs,
const struct xpcs_compat *compat)
{
bool an_enabled;
+ int pcs_stat1;
+ int an_stat1;
int ret;
+ /* The link status bit is latching-low, so it is important to
+ * avoid unnecessary re-reads of this register to avoid missing
+ * a link-down event.
+ */
+ pcs_stat1 = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1);
+ if (pcs_stat1 < 0) {
+ state->link = false;
+ return pcs_stat1;
+ }
+
/* Link needs to be read first ... */
- state->link = xpcs_read_link_c73(xpcs) > 0 ? 1 : 0;
+ state->link = !!(pcs_stat1 & MDIO_STAT1_LSTATUS);
/* ... and then we check the faults. */
- ret = xpcs_read_fault_c73(xpcs, state);
+ ret = xpcs_read_fault_c73(xpcs, state, pcs_stat1);
if (ret) {
ret = xpcs_soft_reset(xpcs, compat);
if (ret)
@@ -938,18 +899,42 @@ static int xpcs_get_state_c73(struct dw_xpcs *xpcs,
state->link = 0;
- return xpcs_do_config(xpcs, state->interface, MLO_AN_INBAND, NULL);
+ return xpcs_do_config(xpcs, state->interface, NULL,
+ PHYLINK_PCS_NEG_INBAND_ENABLED);
}
+ /* There is no point doing anything else if the link is down. */
+ if (!state->link)
+ return 0;
+
an_enabled = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
state->advertising);
- if (an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) {
- state->an_complete = true;
- xpcs_read_lpa_c73(xpcs, state);
- xpcs_resolve_lpa_c73(xpcs, state);
- } else if (an_enabled) {
- state->link = 0;
- } else if (state->link) {
+ if (an_enabled) {
+ /* The link status bit is latching-low, so it is important to
+ * avoid unnecessary re-reads of this register to avoid missing
+ * a link-down event.
+ */
+ an_stat1 = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
+ if (an_stat1 < 0) {
+ state->link = false;
+ return an_stat1;
+ }
+
+ state->an_complete = xpcs_aneg_done_c73(xpcs, state, compat,
+ an_stat1);
+ if (!state->an_complete) {
+ state->link = false;
+ return 0;
+ }
+
+ ret = xpcs_read_lpa_c73(xpcs, state, an_stat1);
+ if (ret < 0) {
+ state->link = false;
+ return ret;
+ }
+
+ phylink_resolve_c73(state);
+ } else {
xpcs_resolve_pma(xpcs, state);
}
@@ -1033,6 +1018,9 @@ static void xpcs_get_state(struct phylink_pcs *pcs,
return;
switch (compat->an_mode) {
+ case DW_10GBASER:
+ phylink_mii_c45_pcs_get_state(xpcs->mdiodev, state);
+ break;
case DW_AN_C73:
ret = xpcs_get_state_c73(xpcs, state, compat);
if (ret) {
@@ -1060,12 +1048,12 @@ static void xpcs_get_state(struct phylink_pcs *pcs,
}
}
-static void xpcs_link_up_sgmii(struct dw_xpcs *xpcs, unsigned int mode,
+static void xpcs_link_up_sgmii(struct dw_xpcs *xpcs, unsigned int neg_mode,
int speed, int duplex)
{
int val, ret;
- if (phylink_autoneg_inband(mode))
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
return;
val = mii_bmcr_encode_fixed(speed, duplex);
@@ -1074,12 +1062,12 @@ static void xpcs_link_up_sgmii(struct dw_xpcs *xpcs, unsigned int mode,
pr_err("%s: xpcs_write returned %pe\n", __func__, ERR_PTR(ret));
}
-static void xpcs_link_up_1000basex(struct dw_xpcs *xpcs, unsigned int mode,
+static void xpcs_link_up_1000basex(struct dw_xpcs *xpcs, unsigned int neg_mode,
int speed, int duplex)
{
int val, ret;
- if (phylink_autoneg_inband(mode))
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
return;
switch (speed) {
@@ -1103,7 +1091,7 @@ static void xpcs_link_up_1000basex(struct dw_xpcs *xpcs, unsigned int mode,
pr_err("%s: xpcs_write returned %pe\n", __func__, ERR_PTR(ret));
}
-void xpcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
+void xpcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface, int speed, int duplex)
{
struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
@@ -1111,9 +1099,9 @@ void xpcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
if (interface == PHY_INTERFACE_MODE_USXGMII)
return xpcs_config_usxgmii(xpcs, speed);
if (interface == PHY_INTERFACE_MODE_SGMII)
- return xpcs_link_up_sgmii(xpcs, mode, speed, duplex);
+ return xpcs_link_up_sgmii(xpcs, neg_mode, speed, duplex);
if (interface == PHY_INTERFACE_MODE_1000BASEX)
- return xpcs_link_up_1000basex(xpcs, mode, speed, duplex);
+ return xpcs_link_up_1000basex(xpcs, neg_mode, speed, duplex);
}
EXPORT_SYMBOL_GPL(xpcs_link_up);
@@ -1188,6 +1176,12 @@ static const struct xpcs_compat synopsys_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
.num_interfaces = ARRAY_SIZE(xpcs_xlgmii_interfaces),
.an_mode = DW_AN_C73,
},
+ [DW_XPCS_10GBASER] = {
+ .supported = xpcs_10gbaser_features,
+ .interface = xpcs_10gbaser_interfaces,
+ .num_interfaces = ARRAY_SIZE(xpcs_10gbaser_interfaces),
+ .an_mode = DW_10GBASER,
+ },
[DW_XPCS_SGMII] = {
.supported = xpcs_sgmii_features,
.interface = xpcs_sgmii_interfaces,
@@ -1259,8 +1253,8 @@ static const struct phylink_pcs_ops xpcs_phylink_ops = {
.pcs_link_up = xpcs_link_up,
};
-struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
- phy_interface_t interface)
+static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
+ phy_interface_t interface)
{
struct dw_xpcs *xpcs;
u32 xpcs_id;
@@ -1270,6 +1264,7 @@ struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
if (!xpcs)
return ERR_PTR(-ENOMEM);
+ mdio_device_get(mdiodev);
xpcs->mdiodev = mdiodev;
xpcs_id = xpcs_get_id(xpcs);
@@ -1290,6 +1285,10 @@ struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
}
xpcs->pcs.ops = &xpcs_phylink_ops;
+ xpcs->pcs.neg_mode = true;
+ if (compat->an_mode == DW_10GBASER)
+ return xpcs;
+
xpcs->pcs.poll = true;
ret = xpcs_soft_reset(xpcs, compat);
@@ -1302,16 +1301,42 @@ struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
ret = -ENODEV;
out:
+ mdio_device_put(mdiodev);
kfree(xpcs);
return ERR_PTR(ret);
}
-EXPORT_SYMBOL_GPL(xpcs_create);
void xpcs_destroy(struct dw_xpcs *xpcs)
{
+ if (xpcs)
+ mdio_device_put(xpcs->mdiodev);
kfree(xpcs);
}
EXPORT_SYMBOL_GPL(xpcs_destroy);
+struct dw_xpcs *xpcs_create_mdiodev(struct mii_bus *bus, int addr,
+ phy_interface_t interface)
+{
+ struct mdio_device *mdiodev;
+ struct dw_xpcs *xpcs;
+
+ mdiodev = mdio_device_create(bus, addr);
+ if (IS_ERR(mdiodev))
+ return ERR_CAST(mdiodev);
+
+ xpcs = xpcs_create(mdiodev, interface);
+
+ /* xpcs_create() has taken a refcount on the mdiodev if it was
+ * successful. If xpcs_create() fails, this will free the mdio
+ * device here. In any case, we don't need to hold our reference
+ * anymore, and putting it here will allow mdio_device_put() in
+ * xpcs_destroy() to automatically free the mdio device.
+ */
+ mdio_device_put(mdiodev);
+
+ return xpcs;
+}
+EXPORT_SYMBOL_GPL(xpcs_create_mdiodev);
+
MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/pcs/pcs-xpcs.h b/drivers/net/pcs/pcs-xpcs.h
index 770df50323a0..68c6b5a62088 100644
--- a/drivers/net/pcs/pcs-xpcs.h
+++ b/drivers/net/pcs/pcs-xpcs.h
@@ -32,9 +32,6 @@
#define DW_SR_AN_ADV1 0x10
#define DW_SR_AN_ADV2 0x11
#define DW_SR_AN_ADV3 0x12
-#define DW_SR_AN_LP_ABL1 0x13
-#define DW_SR_AN_LP_ABL2 0x14
-#define DW_SR_AN_LP_ABL3 0x15
/* Clause 73 Defines */
/* AN_LP_ABL1 */
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 93b8efc79227..78e6981650d9 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -236,6 +236,18 @@ config MEDIATEK_GE_PHY
help
Supports the MediaTek Gigabit Ethernet PHYs.
+config MEDIATEK_GE_SOC_PHY
+ tristate "MediaTek SoC Ethernet PHYs"
+ depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
+ depends on NVMEM_MTK_EFUSE
+ help
+ Supports MediaTek SoC built-in Gigabit Ethernet PHYs.
+
+ Include support for built-in Ethernet PHYs which are present in
+ the MT7981 and MT7988 SoCs. These PHYs need calibration data
+ present in the SoCs efuse and will dynamically calibrate VCM
+ (common-mode voltage) during startup.
+
config MICREL_PHY
tristate "Micrel PHYs"
depends on PTP_1588_CLOCK_OPTIONAL
@@ -243,9 +255,10 @@ config MICREL_PHY
Supports the KSZ9021, VSC8201, KS8001 PHYs.
config MICROCHIP_T1S_PHY
- tristate "Microchip 10BASE-T1S Ethernet PHY"
+ tristate "Microchip 10BASE-T1S Ethernet PHYs"
help
- Currently supports the LAN8670, LAN8671, LAN8672
+ Currently supports the LAN8670/1/2 Rev.B1 and LAN8650/1 Rev.B0 Internal
+ PHYs.
config MICROCHIP_PHY
tristate "Microchip PHYs"
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index f289ab16a1da..2fe51ea83bab 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o
obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o
obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o
obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o
+obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mediatek-ge-soc.o
obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o
obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
obj-$(CONFIG_MICREL_PHY) += micrel.o
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 656136628ffd..8a77ec33b417 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -304,7 +304,6 @@ struct at803x_priv {
bool is_1000basex;
struct regulator_dev *vddio_rdev;
struct regulator_dev *vddh_rdev;
- struct regulator *vddio;
u64 stats[ARRAY_SIZE(at803x_hw_stats)];
};
@@ -460,21 +459,27 @@ static int at803x_set_wol(struct phy_device *phydev,
phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i],
mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
- /* Enable WOL function */
- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL,
- 0, AT803X_WOL_EN);
- if (ret)
- return ret;
+ /* Enable WOL function for 1588 */
+ if (phydev->drv->phy_id == ATH8031_PHY_ID) {
+ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS,
+ AT803X_PHY_MMD3_WOL_CTRL,
+ 0, AT803X_WOL_EN);
+ if (ret)
+ return ret;
+ }
/* Enable WOL interrupt */
ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL);
if (ret)
return ret;
} else {
- /* Disable WoL function */
- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL,
- AT803X_WOL_EN, 0);
- if (ret)
- return ret;
+ /* Disable WoL function for 1588 */
+ if (phydev->drv->phy_id == ATH8031_PHY_ID) {
+ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS,
+ AT803X_PHY_MMD3_WOL_CTRL,
+ AT803X_WOL_EN, 0);
+ if (ret)
+ return ret;
+ }
/* Disable WOL interrupt */
ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0);
if (ret)
@@ -509,11 +514,11 @@ static void at803x_get_wol(struct phy_device *phydev,
wol->supported = WAKE_MAGIC;
wol->wolopts = 0;
- value = phy_read_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL);
+ value = phy_read(phydev, AT803X_INTR_ENABLE);
if (value < 0)
return;
- if (value & AT803X_WOL_EN)
+ if (value & AT803X_INTR_ENABLE_WOL)
wol->wolopts |= WAKE_MAGIC;
}
@@ -824,11 +829,11 @@ static int at803x_parse_dt(struct phy_device *phydev)
if (ret < 0)
return ret;
- priv->vddio = devm_regulator_get_optional(&phydev->mdio.dev,
- "vddio");
- if (IS_ERR(priv->vddio)) {
+ ret = devm_regulator_get_enable_optional(&phydev->mdio.dev,
+ "vddio");
+ if (ret) {
phydev_err(phydev, "failed to get VDDIO regulator\n");
- return PTR_ERR(priv->vddio);
+ return ret;
}
/* Only AR8031/8033 support 1000Base-X for SFP modules */
@@ -856,23 +861,12 @@ static int at803x_probe(struct phy_device *phydev)
if (ret)
return ret;
- if (priv->vddio) {
- ret = regulator_enable(priv->vddio);
- if (ret < 0)
- return ret;
- }
-
if (phydev->drv->phy_id == ATH8031_PHY_ID) {
int ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
int mode_cfg;
- struct ethtool_wolinfo wol = {
- .wolopts = 0,
- };
- if (ccr < 0) {
- ret = ccr;
- goto err;
- }
+ if (ccr < 0)
+ return ccr;
mode_cfg = ccr & AT803X_MODE_CFG_MASK;
switch (mode_cfg) {
@@ -886,29 +880,17 @@ static int at803x_probe(struct phy_device *phydev)
break;
}
- /* Disable WOL by default */
- ret = at803x_set_wol(phydev, &wol);
- if (ret < 0) {
- phydev_err(phydev, "failed to disable WOL on probe: %d\n", ret);
- goto err;
- }
+ /* Disable WoL in 1588 register which is enabled
+ * by default
+ */
+ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS,
+ AT803X_PHY_MMD3_WOL_CTRL,
+ AT803X_WOL_EN, 0);
+ if (ret)
+ return ret;
}
return 0;
-
-err:
- if (priv->vddio)
- regulator_disable(priv->vddio);
-
- return ret;
-}
-
-static void at803x_remove(struct phy_device *phydev)
-{
- struct at803x_priv *priv = phydev->priv;
-
- if (priv->vddio)
- regulator_disable(priv->vddio);
}
static int at803x_get_features(struct phy_device *phydev)
@@ -2021,7 +2003,6 @@ static struct phy_driver at803x_driver[] = {
.name = "Qualcomm Atheros AR8035",
.flags = PHY_POLL_CABLE_TEST,
.probe = at803x_probe,
- .remove = at803x_remove,
.config_aneg = at803x_config_aneg,
.config_init = at803x_config_init,
.soft_reset = genphy_soft_reset,
@@ -2043,7 +2024,6 @@ static struct phy_driver at803x_driver[] = {
.name = "Qualcomm Atheros AR8030",
.phy_id_mask = AT8030_PHY_ID_MASK,
.probe = at803x_probe,
- .remove = at803x_remove,
.config_init = at803x_config_init,
.link_change_notify = at803x_link_change_notify,
.set_wol = at803x_set_wol,
@@ -2059,7 +2039,6 @@ static struct phy_driver at803x_driver[] = {
.name = "Qualcomm Atheros AR8031/AR8033",
.flags = PHY_POLL_CABLE_TEST,
.probe = at803x_probe,
- .remove = at803x_remove,
.config_init = at803x_config_init,
.config_aneg = at803x_config_aneg,
.soft_reset = genphy_soft_reset,
@@ -2082,12 +2061,9 @@ static struct phy_driver at803x_driver[] = {
PHY_ID_MATCH_EXACT(ATH8032_PHY_ID),
.name = "Qualcomm Atheros AR8032",
.probe = at803x_probe,
- .remove = at803x_remove,
.flags = PHY_POLL_CABLE_TEST,
.config_init = at803x_config_init,
.link_change_notify = at803x_link_change_notify,
- .set_wol = at803x_set_wol,
- .get_wol = at803x_get_wol,
.suspend = at803x_suspend,
.resume = at803x_resume,
/* PHY_BASIC_FEATURES */
@@ -2100,7 +2076,6 @@ static struct phy_driver at803x_driver[] = {
PHY_ID_MATCH_EXACT(ATH9331_PHY_ID),
.name = "Qualcomm Atheros AR9331 built-in PHY",
.probe = at803x_probe,
- .remove = at803x_remove,
.suspend = at803x_suspend,
.resume = at803x_resume,
.flags = PHY_POLL_CABLE_TEST,
@@ -2117,7 +2092,6 @@ static struct phy_driver at803x_driver[] = {
PHY_ID_MATCH_EXACT(QCA9561_PHY_ID),
.name = "Qualcomm Atheros QCA9561 built-in PHY",
.probe = at803x_probe,
- .remove = at803x_remove,
.suspend = at803x_suspend,
.resume = at803x_resume,
.flags = PHY_POLL_CABLE_TEST,
@@ -2183,7 +2157,6 @@ static struct phy_driver at803x_driver[] = {
.name = "Qualcomm QCA8081",
.flags = PHY_POLL_CABLE_TEST,
.probe = at803x_probe,
- .remove = at803x_remove,
.config_intr = at803x_config_intr,
.handle_interrupt = at803x_handle_interrupt,
.get_tunable = at803x_get_tunable,
diff --git a/drivers/net/phy/bcm-phy-lib.c b/drivers/net/phy/bcm-phy-lib.c
index b2c0baa51f39..876f28fd8256 100644
--- a/drivers/net/phy/bcm-phy-lib.c
+++ b/drivers/net/phy/bcm-phy-lib.c
@@ -6,12 +6,14 @@
#include "bcm-phy-lib.h"
#include <linux/bitfield.h>
#include <linux/brcmphy.h>
+#include <linux/etherdevice.h>
#include <linux/export.h>
#include <linux/mdio.h>
#include <linux/module.h>
#include <linux/phy.h>
#include <linux/ethtool.h>
#include <linux/ethtool_netlink.h>
+#include <linux/netdevice.h>
#define MII_BCM_CHANNEL_WIDTH 0x2000
#define BCM_CL45VEN_EEE_ADV 0x3c
@@ -494,18 +496,20 @@ EXPORT_SYMBOL_GPL(bcm_phy_downshift_set);
struct bcm_phy_hw_stat {
const char *string;
- u8 reg;
+ int devad;
+ u16 reg;
u8 shift;
u8 bits;
};
/* Counters freeze at either 0xffff or 0xff, better than nothing */
static const struct bcm_phy_hw_stat bcm_phy_hw_stats[] = {
- { "phy_receive_errors", MII_BRCM_CORE_BASE12, 0, 16 },
- { "phy_serdes_ber_errors", MII_BRCM_CORE_BASE13, 8, 8 },
- { "phy_false_carrier_sense_errors", MII_BRCM_CORE_BASE13, 0, 8 },
- { "phy_local_rcvr_nok", MII_BRCM_CORE_BASE14, 8, 8 },
- { "phy_remote_rcv_nok", MII_BRCM_CORE_BASE14, 0, 8 },
+ { "phy_receive_errors", -1, MII_BRCM_CORE_BASE12, 0, 16 },
+ { "phy_serdes_ber_errors", -1, MII_BRCM_CORE_BASE13, 8, 8 },
+ { "phy_false_carrier_sense_errors", -1, MII_BRCM_CORE_BASE13, 0, 8 },
+ { "phy_local_rcvr_nok", -1, MII_BRCM_CORE_BASE14, 8, 8 },
+ { "phy_remote_rcv_nok", -1, MII_BRCM_CORE_BASE14, 0, 8 },
+ { "phy_lpi_count", MDIO_MMD_AN, BRCM_CL45VEN_EEE_LPI_CNT, 0, 16 },
};
int bcm_phy_get_sset_count(struct phy_device *phydev)
@@ -534,7 +538,10 @@ static u64 bcm_phy_get_stat(struct phy_device *phydev, u64 *shadow,
int val;
u64 ret;
- val = phy_read(phydev, stat.reg);
+ if (stat.devad < 0)
+ val = phy_read(phydev, stat.reg);
+ else
+ val = phy_read_mmd(phydev, stat.devad, stat.reg);
if (val < 0) {
ret = U64_MAX;
} else {
@@ -816,6 +823,249 @@ int bcm_phy_cable_test_get_status_rdb(struct phy_device *phydev,
}
EXPORT_SYMBOL_GPL(bcm_phy_cable_test_get_status_rdb);
+#define BCM54XX_WOL_SUPPORTED_MASK (WAKE_UCAST | \
+ WAKE_MCAST | \
+ WAKE_BCAST | \
+ WAKE_MAGIC | \
+ WAKE_MAGICSECURE)
+
+int bcm_phy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
+{
+ struct net_device *ndev = phydev->attached_dev;
+ u8 da[ETH_ALEN], mask[ETH_ALEN];
+ unsigned int i;
+ u16 ctl;
+ int ret;
+
+ /* Allow a MAC driver to play through its own Wake-on-LAN
+ * implementation
+ */
+ if (wol->wolopts & ~BCM54XX_WOL_SUPPORTED_MASK)
+ return -EOPNOTSUPP;
+
+ /* The PHY supports passwords of 4, 6 and 8 bytes in size, but Linux's
+ * ethtool only supports 6, for now.
+ */
+ BUILD_BUG_ON(sizeof(wol->sopass) != ETH_ALEN);
+
+ /* Clear previous interrupts */
+ ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS);
+ if (ret < 0)
+ return ret;
+
+ ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_MAIN_CTL);
+ if (ret < 0)
+ return ret;
+
+ ctl = ret;
+
+ if (!wol->wolopts) {
+ if (phy_interrupt_is_valid(phydev))
+ disable_irq_wake(phydev->irq);
+
+ /* Leave all interrupts disabled */
+ ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_INT_MASK,
+ BCM54XX_WOL_ALL_INTRS);
+ if (ret < 0)
+ return ret;
+
+ /* Disable the global Wake-on-LAN enable bit */
+ ctl &= ~BCM54XX_WOL_EN;
+
+ return bcm_phy_write_exp(phydev, BCM54XX_WOL_MAIN_CTL, ctl);
+ }
+
+ /* Clear the previously configured mode and mask mode for Wake-on-LAN */
+ ctl &= ~(BCM54XX_WOL_MODE_MASK << BCM54XX_WOL_MODE_SHIFT);
+ ctl &= ~(BCM54XX_WOL_MASK_MODE_MASK << BCM54XX_WOL_MASK_MODE_SHIFT);
+ ctl &= ~BCM54XX_WOL_DIR_PKT_EN;
+ ctl &= ~(BCM54XX_WOL_SECKEY_OPT_MASK << BCM54XX_WOL_SECKEY_OPT_SHIFT);
+
+ /* When using WAKE_MAGIC, we program the magic pattern filter to match
+ * the device's MAC address and we accept any MAC DA in the Ethernet
+ * frame.
+ *
+ * When using WAKE_UCAST, WAKE_BCAST or WAKE_MCAST, we program the
+ * following:
+ * - WAKE_UCAST -> MAC DA is the device's MAC with a perfect match
+ * - WAKE_MCAST -> MAC DA is X1:XX:XX:XX:XX:XX where XX is don't care
+ * - WAKE_BCAST -> MAC DA is FF:FF:FF:FF:FF:FF with a perfect match
+ *
+ * Note that the Broadcast MAC DA is inherently going to match the
+ * multicast pattern being matched.
+ */
+ memset(mask, 0, sizeof(mask));
+
+ if (wol->wolopts & WAKE_MCAST) {
+ memset(da, 0, sizeof(da));
+ memset(mask, 0xff, sizeof(mask));
+ da[0] = 0x01;
+ mask[0] = ~da[0];
+ } else {
+ if (wol->wolopts & WAKE_UCAST) {
+ ether_addr_copy(da, ndev->dev_addr);
+ } else if (wol->wolopts & WAKE_BCAST) {
+ eth_broadcast_addr(da);
+ } else if (wol->wolopts & WAKE_MAGICSECURE) {
+ ether_addr_copy(da, wol->sopass);
+ } else if (wol->wolopts & WAKE_MAGIC) {
+ memset(da, 0, sizeof(da));
+ memset(mask, 0xff, sizeof(mask));
+ }
+ }
+
+ for (i = 0; i < ETH_ALEN / 2; i++) {
+ if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
+ ret = bcm_phy_write_exp(phydev,
+ BCM54XX_WOL_MPD_DATA1(2 - i),
+ ndev->dev_addr[i * 2] << 8 |
+ ndev->dev_addr[i * 2 + 1]);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MPD_DATA2(2 - i),
+ da[i * 2] << 8 | da[i * 2 + 1]);
+ if (ret < 0)
+ return ret;
+
+ ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MASK(2 - i),
+ mask[i * 2] << 8 | mask[i * 2 + 1]);
+ if (ret)
+ return ret;
+ }
+
+ if (wol->wolopts & WAKE_MAGICSECURE) {
+ ctl |= BCM54XX_WOL_SECKEY_OPT_6B <<
+ BCM54XX_WOL_SECKEY_OPT_SHIFT;
+ ctl |= BCM54XX_WOL_MODE_SINGLE_MPDSEC << BCM54XX_WOL_MODE_SHIFT;
+ ctl |= BCM54XX_WOL_MASK_MODE_DA_FF <<
+ BCM54XX_WOL_MASK_MODE_SHIFT;
+ } else {
+ if (wol->wolopts & WAKE_MAGIC)
+ ctl |= BCM54XX_WOL_MODE_SINGLE_MPD;
+ else
+ ctl |= BCM54XX_WOL_DIR_PKT_EN;
+ ctl |= BCM54XX_WOL_MASK_MODE_DA_ONLY <<
+ BCM54XX_WOL_MASK_MODE_SHIFT;
+ }
+
+ /* Globally enable Wake-on-LAN */
+ ctl |= BCM54XX_WOL_EN | BCM54XX_WOL_CRC_CHK;
+
+ ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MAIN_CTL, ctl);
+ if (ret < 0)
+ return ret;
+
+ /* Enable WOL interrupt on LED4 */
+ ret = bcm_phy_read_exp(phydev, BCM54XX_TOP_MISC_LED_CTL);
+ if (ret < 0)
+ return ret;
+
+ ret |= BCM54XX_LED4_SEL_INTR;
+ ret = bcm_phy_write_exp(phydev, BCM54XX_TOP_MISC_LED_CTL, ret);
+ if (ret < 0)
+ return ret;
+
+ /* Enable all Wake-on-LAN interrupt sources */
+ ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_INT_MASK, 0);
+ if (ret < 0)
+ return ret;
+
+ if (phy_interrupt_is_valid(phydev))
+ enable_irq_wake(phydev->irq);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_set_wol);
+
+void bcm_phy_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
+{
+ struct net_device *ndev = phydev->attached_dev;
+ u8 da[ETH_ALEN];
+ unsigned int i;
+ int ret;
+ u16 ctl;
+
+ wol->supported = BCM54XX_WOL_SUPPORTED_MASK;
+ wol->wolopts = 0;
+
+ ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_MAIN_CTL);
+ if (ret < 0)
+ return;
+
+ ctl = ret;
+
+ if (!(ctl & BCM54XX_WOL_EN))
+ return;
+
+ for (i = 0; i < sizeof(da) / 2; i++) {
+ ret = bcm_phy_read_exp(phydev,
+ BCM54XX_WOL_MPD_DATA2(2 - i));
+ if (ret < 0)
+ return;
+
+ da[i * 2] = ret >> 8;
+ da[i * 2 + 1] = ret & 0xff;
+ }
+
+ if (ctl & BCM54XX_WOL_DIR_PKT_EN) {
+ if (is_broadcast_ether_addr(da))
+ wol->wolopts |= WAKE_BCAST;
+ else if (is_multicast_ether_addr(da))
+ wol->wolopts |= WAKE_MCAST;
+ else if (ether_addr_equal(da, ndev->dev_addr))
+ wol->wolopts |= WAKE_UCAST;
+ } else {
+ ctl = (ctl >> BCM54XX_WOL_MODE_SHIFT) & BCM54XX_WOL_MODE_MASK;
+ switch (ctl) {
+ case BCM54XX_WOL_MODE_SINGLE_MPD:
+ wol->wolopts |= WAKE_MAGIC;
+ break;
+ case BCM54XX_WOL_MODE_SINGLE_MPDSEC:
+ wol->wolopts |= WAKE_MAGICSECURE;
+ memcpy(wol->sopass, da, sizeof(da));
+ break;
+ default:
+ break;
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(bcm_phy_get_wol);
+
+irqreturn_t bcm_phy_wol_isr(int irq, void *dev_id)
+{
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_wol_isr);
+
+int bcm_phy_led_brightness_set(struct phy_device *phydev,
+ u8 index, enum led_brightness value)
+{
+ u8 led_num;
+ int ret;
+ u16 reg;
+
+ if (index >= 4)
+ return -EINVAL;
+
+ /* Two LEDS per register */
+ led_num = index % 2;
+ reg = index >= 2 ? BCM54XX_SHD_LEDS2 : BCM54XX_SHD_LEDS1;
+
+ ret = bcm_phy_read_shadow(phydev, reg);
+ if (ret < 0)
+ return ret;
+
+ ret &= ~(BCM_LED_SRC_MASK << BCM54XX_SHD_LEDS_SHIFT(led_num));
+ if (value == LED_OFF)
+ ret |= BCM_LED_SRC_OFF << BCM54XX_SHD_LEDS_SHIFT(led_num);
+ else
+ ret |= BCM_LED_SRC_ON << BCM54XX_SHD_LEDS_SHIFT(led_num);
+ return bcm_phy_write_shadow(phydev, reg, ret);
+}
+EXPORT_SYMBOL_GPL(bcm_phy_led_brightness_set);
+
MODULE_DESCRIPTION("Broadcom PHY Library");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Broadcom Corporation");
diff --git a/drivers/net/phy/bcm-phy-lib.h b/drivers/net/phy/bcm-phy-lib.h
index 729db441797a..b52189e45a84 100644
--- a/drivers/net/phy/bcm-phy-lib.h
+++ b/drivers/net/phy/bcm-phy-lib.h
@@ -8,6 +8,9 @@
#include <linux/brcmphy.h>
#include <linux/phy.h>
+#include <linux/interrupt.h>
+
+struct ethtool_wolinfo;
/* 28nm only register definitions */
#define MISC_ADDR(base, channel) base, channel
@@ -111,4 +114,11 @@ static inline void bcm_ptp_stop(struct bcm_ptp_private *priv)
}
#endif
+int bcm_phy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol);
+void bcm_phy_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol);
+irqreturn_t bcm_phy_wol_isr(int irq, void *dev_id);
+
+int bcm_phy_led_brightness_set(struct phy_device *phydev,
+ u8 index, enum led_brightness value);
+
#endif /* _LINUX_BCM_PHY_LIB_H */
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index ad71c88c87e7..04b2e6eeb195 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -14,8 +14,12 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/phy.h>
+#include <linux/pm_wakeup.h>
#include <linux/brcmphy.h>
#include <linux/of.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio/consumer.h>
#define BRCM_PHY_MODEL(phydev) \
((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
@@ -30,8 +34,17 @@ MODULE_LICENSE("GPL");
struct bcm54xx_phy_priv {
u64 *stats;
struct bcm_ptp_private *ptp;
+ int wake_irq;
+ bool wake_irq_enabled;
};
+static bool bcm54xx_phy_can_wakeup(struct phy_device *phydev)
+{
+ struct bcm54xx_phy_priv *priv = phydev->priv;
+
+ return phy_interrupt_is_valid(phydev) || priv->wake_irq >= 0;
+}
+
static int bcm54xx_config_clock_delay(struct phy_device *phydev)
{
int rc, val;
@@ -401,18 +414,28 @@ static int bcm54xx_config_init(struct phy_device *phydev)
* these settings will cause LOS to malfunction.
*/
if (!phy_on_sfp(phydev)) {
- val = BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) |
- BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1);
- bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val);
+ val = BCM54XX_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) |
+ BCM54XX_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1);
+ bcm_phy_write_shadow(phydev, BCM54XX_SHD_LEDS1, val);
val = BCM_LED_MULTICOLOR_IN_PHASE |
- BCM5482_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) |
- BCM5482_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT);
+ BCM54XX_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) |
+ BCM54XX_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT);
bcm_phy_write_exp(phydev, BCM_EXP_MULTICOLOR, val);
}
bcm54xx_ptp_config_init(phydev);
+ /* Acknowledge any left over interrupt and charge the device for
+ * wake-up.
+ */
+ err = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS);
+ if (err < 0)
+ return err;
+
+ if (err)
+ pm_wakeup_event(&phydev->mdio.dev, 0);
+
return 0;
}
@@ -437,12 +460,39 @@ out:
return ret;
}
+static int bcm54xx_set_wakeup_irq(struct phy_device *phydev, bool state)
+{
+ struct bcm54xx_phy_priv *priv = phydev->priv;
+ int ret = 0;
+
+ if (!bcm54xx_phy_can_wakeup(phydev))
+ return ret;
+
+ if (priv->wake_irq_enabled != state) {
+ if (state)
+ ret = enable_irq_wake(priv->wake_irq);
+ else
+ ret = disable_irq_wake(priv->wake_irq);
+ priv->wake_irq_enabled = state;
+ }
+
+ return ret;
+}
+
static int bcm54xx_suspend(struct phy_device *phydev)
{
- int ret;
+ int ret = 0;
bcm54xx_ptp_stop(phydev);
+ /* Acknowledge any Wake-on-LAN interrupt prior to suspend */
+ ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS);
+ if (ret < 0)
+ return ret;
+
+ if (phydev->wol_enabled)
+ return bcm54xx_set_wakeup_irq(phydev, true);
+
/* We cannot use a read/modify/write here otherwise the PHY gets into
* a bad state where its LEDs keep flashing, thus defeating the purpose
* of low power mode.
@@ -456,7 +506,13 @@ static int bcm54xx_suspend(struct phy_device *phydev)
static int bcm54xx_resume(struct phy_device *phydev)
{
- int ret;
+ int ret = 0;
+
+ if (phydev->wol_enabled) {
+ ret = bcm54xx_set_wakeup_irq(phydev, false);
+ if (ret)
+ return ret;
+ }
ret = bcm54xx_iddq_set(phydev, false);
if (ret < 0)
@@ -486,6 +542,17 @@ static int bcm54xx_resume(struct phy_device *phydev)
return bcm54xx_config_init(phydev);
}
+static int bcm54810_read_mmd(struct phy_device *phydev, int devnum, u16 regnum)
+{
+ return -EOPNOTSUPP;
+}
+
+static int bcm54810_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
+ u16 val)
+{
+ return -EOPNOTSUPP;
+}
+
static int bcm54811_config_init(struct phy_device *phydev)
{
int err, reg;
@@ -608,17 +675,6 @@ static int bcm54616s_read_status(struct phy_device *phydev)
return err;
}
-static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
-{
- int val;
-
- val = phy_read(phydev, reg);
- if (val < 0)
- return val;
-
- return phy_write(phydev, reg, val | set);
-}
-
static int brcm_fet_config_init(struct phy_device *phydev)
{
int reg, err, err2, brcmtest;
@@ -689,15 +745,15 @@ static int brcm_fet_config_init(struct phy_device *phydev)
goto done;
/* Enable auto MDIX */
- err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,
- MII_BRCM_FET_SHDW_MC_FAME);
+ err = phy_set_bits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,
+ MII_BRCM_FET_SHDW_MC_FAME);
if (err < 0)
goto done;
if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) {
/* Enable auto power down */
- err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
- MII_BRCM_FET_SHDW_AS2_APDE);
+ err = phy_set_bits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
+ MII_BRCM_FET_SHDW_AS2_APDE);
}
done:
@@ -801,14 +857,54 @@ static int brcm_fet_suspend(struct phy_device *phydev)
return err;
}
+static void bcm54xx_phy_get_wol(struct phy_device *phydev,
+ struct ethtool_wolinfo *wol)
+{
+ /* We cannot wake-up if we do not have a dedicated PHY interrupt line
+ * or an out of band GPIO descriptor for wake-up. Zeroing
+ * wol->supported allows the caller (MAC driver) to play through and
+ * offer its own Wake-on-LAN scheme if available.
+ */
+ if (!bcm54xx_phy_can_wakeup(phydev)) {
+ wol->supported = 0;
+ return;
+ }
+
+ bcm_phy_get_wol(phydev, wol);
+}
+
+static int bcm54xx_phy_set_wol(struct phy_device *phydev,
+ struct ethtool_wolinfo *wol)
+{
+ int ret;
+
+ /* We cannot wake-up if we do not have a dedicated PHY interrupt line
+ * or an out of band GPIO descriptor for wake-up. Returning -EOPNOTSUPP
+ * allows the caller (MAC driver) to play through and offer its own
+ * Wake-on-LAN scheme if available.
+ */
+ if (!bcm54xx_phy_can_wakeup(phydev))
+ return -EOPNOTSUPP;
+
+ ret = bcm_phy_set_wol(phydev, wol);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
static int bcm54xx_phy_probe(struct phy_device *phydev)
{
struct bcm54xx_phy_priv *priv;
+ struct gpio_desc *wakeup_gpio;
+ int ret = 0;
priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
+ priv->wake_irq = -ENXIO;
+
phydev->priv = priv;
priv->stats = devm_kcalloc(&phydev->mdio.dev,
@@ -821,7 +917,35 @@ static int bcm54xx_phy_probe(struct phy_device *phydev)
if (IS_ERR(priv->ptp))
return PTR_ERR(priv->ptp);
- return 0;
+ /* We cannot utilize the _optional variant here since we want to know
+ * whether the GPIO descriptor exists or not to advertise Wake-on-LAN
+ * support or not.
+ */
+ wakeup_gpio = devm_gpiod_get(&phydev->mdio.dev, "wakeup", GPIOD_IN);
+ if (PTR_ERR(wakeup_gpio) == -EPROBE_DEFER)
+ return PTR_ERR(wakeup_gpio);
+
+ if (!IS_ERR(wakeup_gpio)) {
+ priv->wake_irq = gpiod_to_irq(wakeup_gpio);
+
+ /* Dummy interrupt handler which is not enabled but is provided
+ * in order for the interrupt descriptor to be fully set-up.
+ */
+ ret = devm_request_irq(&phydev->mdio.dev, priv->wake_irq,
+ bcm_phy_wol_isr,
+ IRQF_TRIGGER_LOW | IRQF_NO_AUTOEN,
+ dev_name(&phydev->mdio.dev), phydev);
+ if (ret)
+ return ret;
+ }
+
+ /* If we do not have a main interrupt or a side-band wake-up interrupt,
+ * then the device cannot be marked as wake-up capable.
+ */
+ if (!bcm54xx_phy_can_wakeup(phydev))
+ return 0;
+
+ return device_init_wakeup(&phydev->mdio.dev, true);
}
static void bcm54xx_get_stats(struct phy_device *phydev,
@@ -894,6 +1018,7 @@ static struct phy_driver broadcom_drivers[] = {
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM54210E",
/* PHY_GBIT_FEATURES */
+ .flags = PHY_ALWAYS_CALL_SUSPEND,
.get_sset_count = bcm_phy_get_sset_count,
.get_strings = bcm_phy_get_strings,
.get_stats = bcm54xx_get_stats,
@@ -904,6 +1029,9 @@ static struct phy_driver broadcom_drivers[] = {
.link_change_notify = bcm54xx_link_change_notify,
.suspend = bcm54xx_suspend,
.resume = bcm54xx_resume,
+ .get_wol = bcm54xx_phy_get_wol,
+ .set_wol = bcm54xx_phy_set_wol,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM5461,
.phy_id_mask = 0xfffffff0,
@@ -917,6 +1045,7 @@ static struct phy_driver broadcom_drivers[] = {
.config_intr = bcm_phy_config_intr,
.handle_interrupt = bcm_phy_handle_interrupt,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM54612E,
.phy_id_mask = 0xfffffff0,
@@ -930,6 +1059,7 @@ static struct phy_driver broadcom_drivers[] = {
.config_intr = bcm_phy_config_intr,
.handle_interrupt = bcm_phy_handle_interrupt,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM54616S,
.phy_id_mask = 0xfffffff0,
@@ -943,6 +1073,7 @@ static struct phy_driver broadcom_drivers[] = {
.read_status = bcm54616s_read_status,
.probe = bcm54616s_probe,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM5464,
.phy_id_mask = 0xfffffff0,
@@ -958,6 +1089,7 @@ static struct phy_driver broadcom_drivers[] = {
.suspend = genphy_suspend,
.resume = genphy_resume,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM5481,
.phy_id_mask = 0xfffffff0,
@@ -972,6 +1104,7 @@ static struct phy_driver broadcom_drivers[] = {
.config_intr = bcm_phy_config_intr,
.handle_interrupt = bcm_phy_handle_interrupt,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM54810,
.phy_id_mask = 0xfffffff0,
@@ -981,6 +1114,8 @@ static struct phy_driver broadcom_drivers[] = {
.get_strings = bcm_phy_get_strings,
.get_stats = bcm54xx_get_stats,
.probe = bcm54xx_phy_probe,
+ .read_mmd = bcm54810_read_mmd,
+ .write_mmd = bcm54810_write_mmd,
.config_init = bcm54xx_config_init,
.config_aneg = bcm5481_config_aneg,
.config_intr = bcm_phy_config_intr,
@@ -988,6 +1123,7 @@ static struct phy_driver broadcom_drivers[] = {
.suspend = bcm54xx_suspend,
.resume = bcm54xx_resume,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM54811,
.phy_id_mask = 0xfffffff0,
@@ -1004,6 +1140,7 @@ static struct phy_driver broadcom_drivers[] = {
.suspend = bcm54xx_suspend,
.resume = bcm54xx_resume,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM5482,
.phy_id_mask = 0xfffffff0,
@@ -1017,6 +1154,7 @@ static struct phy_driver broadcom_drivers[] = {
.config_intr = bcm_phy_config_intr,
.handle_interrupt = bcm_phy_handle_interrupt,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM50610,
.phy_id_mask = 0xfffffff0,
@@ -1032,6 +1170,7 @@ static struct phy_driver broadcom_drivers[] = {
.link_change_notify = bcm54xx_link_change_notify,
.suspend = bcm54xx_suspend,
.resume = bcm54xx_resume,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM50610M,
.phy_id_mask = 0xfffffff0,
@@ -1047,6 +1186,7 @@ static struct phy_driver broadcom_drivers[] = {
.link_change_notify = bcm54xx_link_change_notify,
.suspend = bcm54xx_suspend,
.resume = bcm54xx_resume,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM57780,
.phy_id_mask = 0xfffffff0,
@@ -1060,6 +1200,7 @@ static struct phy_driver broadcom_drivers[] = {
.config_intr = bcm_phy_config_intr,
.handle_interrupt = bcm_phy_handle_interrupt,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCMAC131,
.phy_id_mask = 0xfffffff0,
@@ -1091,6 +1232,7 @@ static struct phy_driver broadcom_drivers[] = {
.get_stats = bcm54xx_get_stats,
.probe = bcm54xx_phy_probe,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM53125,
.phy_id_mask = 0xfffffff0,
@@ -1105,6 +1247,7 @@ static struct phy_driver broadcom_drivers[] = {
.config_intr = bcm_phy_config_intr,
.handle_interrupt = bcm_phy_handle_interrupt,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM53128,
.phy_id_mask = 0xfffffff0,
@@ -1119,6 +1262,7 @@ static struct phy_driver broadcom_drivers[] = {
.config_intr = bcm_phy_config_intr,
.handle_interrupt = bcm_phy_handle_interrupt,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM89610,
.phy_id_mask = 0xfffffff0,
diff --git a/drivers/net/phy/dp83869.c b/drivers/net/phy/dp83869.c
index 9ab5eff502b7..fa8c6fdcf301 100644
--- a/drivers/net/phy/dp83869.c
+++ b/drivers/net/phy/dp83869.c
@@ -692,8 +692,19 @@ static int dp83869_configure_mode(struct phy_device *phydev,
/* Below init sequence for each operational mode is defined in
* section 9.4.8 of the datasheet.
*/
+ phy_ctrl_val = dp83869->mode;
+ if (phydev->interface == PHY_INTERFACE_MODE_MII) {
+ if (dp83869->mode == DP83869_100M_MEDIA_CONVERT ||
+ dp83869->mode == DP83869_RGMII_100_BASE) {
+ phy_ctrl_val |= DP83869_OP_MODE_MII;
+ } else {
+ phydev_err(phydev, "selected op-mode is not valid with MII mode\n");
+ return -EINVAL;
+ }
+ }
+
ret = phy_write_mmd(phydev, DP83869_DEVADDR, DP83869_OP_MODE,
- dp83869->mode);
+ phy_ctrl_val);
if (ret)
return ret;
diff --git a/drivers/net/phy/dp83td510.c b/drivers/net/phy/dp83td510.c
index 3cd9a77f9532..d7616b13c594 100644
--- a/drivers/net/phy/dp83td510.c
+++ b/drivers/net/phy/dp83td510.c
@@ -12,6 +12,11 @@
/* MDIO_MMD_VEND2 registers */
#define DP83TD510E_PHY_STS 0x10
+/* Bit 7 - mii_interrupt, active high. Clears on read.
+ * Note: Clearing does not necessarily deactivate IRQ pin if interrupts pending.
+ * This differs from the DP83TD510E datasheet (2020) which states this bit
+ * clears on write 0.
+ */
#define DP83TD510E_STS_MII_INT BIT(7)
#define DP83TD510E_LINK_STATUS BIT(0)
@@ -53,12 +58,6 @@ static int dp83td510_config_intr(struct phy_device *phydev)
int ret;
if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
- /* Clear any pending interrupts */
- ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_PHY_STS,
- 0x0);
- if (ret)
- return ret;
-
ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
DP83TD510E_INTERRUPT_REG_1,
DP83TD510E_INT1_LINK_EN);
@@ -81,10 +80,6 @@ static int dp83td510_config_intr(struct phy_device *phydev)
DP83TD510E_GENCFG_INT_EN);
if (ret)
return ret;
-
- /* Clear any pending interrupts */
- ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_PHY_STS,
- 0x0);
}
return ret;
@@ -94,14 +89,6 @@ static irqreturn_t dp83td510_handle_interrupt(struct phy_device *phydev)
{
int ret;
- ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_PHY_STS);
- if (ret < 0) {
- phy_error(phydev);
- return IRQ_NONE;
- } else if (!(ret & DP83TD510E_STS_MII_INT)) {
- return IRQ_NONE;
- }
-
/* Read the current enabled interrupts */
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_INTERRUPT_REG_1);
if (ret < 0) {
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 55d9d7acc32e..d4bb90d76881 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -328,6 +328,13 @@ static int mv3310_power_up(struct phy_device *phydev)
ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
MV_V2_PORT_CTRL_PWRDOWN);
+ /* Sometimes, the power down bit doesn't clear immediately, and
+ * a read of this register causes the bit not to clear. Delay
+ * 100us to allow the PHY to come out of power down mode before
+ * the next access.
+ */
+ udelay(100);
+
if (phydev->drv->phy_id != MARVELL_PHY_ID_88X3310 ||
priv->firmware_ver < 0x00030000)
return ret;
diff --git a/drivers/net/phy/mediatek-ge-soc.c b/drivers/net/phy/mediatek-ge-soc.c
new file mode 100644
index 000000000000..95369171a7ba
--- /dev/null
+++ b/drivers/net/phy/mediatek-ge-soc.c
@@ -0,0 +1,1116 @@
+// SPDX-License-Identifier: GPL-2.0+
+#include <linux/bitfield.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/phy.h>
+
+#define MTK_GPHY_ID_MT7981 0x03a29461
+#define MTK_GPHY_ID_MT7988 0x03a29481
+
+#define MTK_EXT_PAGE_ACCESS 0x1f
+#define MTK_PHY_PAGE_STANDARD 0x0000
+#define MTK_PHY_PAGE_EXTENDED_3 0x0003
+
+#define MTK_PHY_LPI_REG_14 0x14
+#define MTK_PHY_LPI_WAKE_TIMER_1000_MASK GENMASK(8, 0)
+
+#define MTK_PHY_LPI_REG_1c 0x1c
+#define MTK_PHY_SMI_DET_ON_THRESH_MASK GENMASK(13, 8)
+
+#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30
+#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
+
+#define ANALOG_INTERNAL_OPERATION_MAX_US 20
+#define TXRESERVE_MIN 0
+#define TXRESERVE_MAX 7
+
+#define MTK_PHY_ANARG_RG 0x10
+#define MTK_PHY_TCLKOFFSET_MASK GENMASK(12, 8)
+
+/* Registers on MDIO_MMD_VEND1 */
+#define MTK_PHY_TXVLD_DA_RG 0x12
+#define MTK_PHY_DA_TX_I2MPB_A_GBE_MASK GENMASK(15, 10)
+#define MTK_PHY_DA_TX_I2MPB_A_TBT_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_A2 0x16
+#define MTK_PHY_DA_TX_I2MPB_A_HBT_MASK GENMASK(15, 10)
+#define MTK_PHY_DA_TX_I2MPB_A_TST_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_B1 0x17
+#define MTK_PHY_DA_TX_I2MPB_B_GBE_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_B_TBT_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_B2 0x18
+#define MTK_PHY_DA_TX_I2MPB_B_HBT_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_B_TST_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_C1 0x19
+#define MTK_PHY_DA_TX_I2MPB_C_GBE_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_C_TBT_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_C2 0x20
+#define MTK_PHY_DA_TX_I2MPB_C_HBT_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_C_TST_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_D1 0x21
+#define MTK_PHY_DA_TX_I2MPB_D_GBE_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_D_TBT_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_D2 0x22
+#define MTK_PHY_DA_TX_I2MPB_D_HBT_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_D_TST_MASK GENMASK(5, 0)
+
+#define MTK_PHY_RXADC_CTRL_RG7 0xc6
+#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK GENMASK(9, 8)
+
+#define MTK_PHY_RXADC_CTRL_RG9 0xc8
+#define MTK_PHY_DA_RX_PSBN_TBT_MASK GENMASK(14, 12)
+#define MTK_PHY_DA_RX_PSBN_HBT_MASK GENMASK(10, 8)
+#define MTK_PHY_DA_RX_PSBN_GBE_MASK GENMASK(6, 4)
+#define MTK_PHY_DA_RX_PSBN_LP_MASK GENMASK(2, 0)
+
+#define MTK_PHY_LDO_OUTPUT_V 0xd7
+
+#define MTK_PHY_RG_ANA_CAL_RG0 0xdb
+#define MTK_PHY_RG_CAL_CKINV BIT(12)
+#define MTK_PHY_RG_ANA_CALEN BIT(8)
+#define MTK_PHY_RG_ZCALEN_A BIT(0)
+
+#define MTK_PHY_RG_ANA_CAL_RG1 0xdc
+#define MTK_PHY_RG_ZCALEN_B BIT(12)
+#define MTK_PHY_RG_ZCALEN_C BIT(8)
+#define MTK_PHY_RG_ZCALEN_D BIT(4)
+#define MTK_PHY_RG_TXVOS_CALEN BIT(0)
+
+#define MTK_PHY_RG_ANA_CAL_RG5 0xe0
+#define MTK_PHY_RG_REXT_TRIM_MASK GENMASK(13, 8)
+
+#define MTK_PHY_RG_TX_FILTER 0xfe
+
+#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120 0x120
+#define MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK GENMASK(12, 8)
+#define MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK GENMASK(4, 0)
+
+#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122 0x122
+#define MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK GENMASK(7, 0)
+
+#define MTK_PHY_RG_TESTMUX_ADC_CTRL 0x144
+#define MTK_PHY_RG_TXEN_DIG_MASK GENMASK(5, 5)
+
+#define MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B 0x172
+#define MTK_PHY_CR_TX_AMP_OFFSET_A_MASK GENMASK(13, 8)
+#define MTK_PHY_CR_TX_AMP_OFFSET_B_MASK GENMASK(6, 0)
+
+#define MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D 0x173
+#define MTK_PHY_CR_TX_AMP_OFFSET_C_MASK GENMASK(13, 8)
+#define MTK_PHY_CR_TX_AMP_OFFSET_D_MASK GENMASK(6, 0)
+
+#define MTK_PHY_RG_AD_CAL_COMP 0x17a
+#define MTK_PHY_AD_CAL_COMP_OUT_SHIFT (8)
+
+#define MTK_PHY_RG_AD_CAL_CLK 0x17b
+#define MTK_PHY_DA_CAL_CLK BIT(0)
+
+#define MTK_PHY_RG_AD_CALIN 0x17c
+#define MTK_PHY_DA_CALIN_FLAG BIT(0)
+
+#define MTK_PHY_RG_DASN_DAC_IN0_A 0x17d
+#define MTK_PHY_DASN_DAC_IN0_A_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN0_B 0x17e
+#define MTK_PHY_DASN_DAC_IN0_B_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN0_C 0x17f
+#define MTK_PHY_DASN_DAC_IN0_C_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN0_D 0x180
+#define MTK_PHY_DASN_DAC_IN0_D_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN1_A 0x181
+#define MTK_PHY_DASN_DAC_IN1_A_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN1_B 0x182
+#define MTK_PHY_DASN_DAC_IN1_B_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN1_C 0x183
+#define MTK_PHY_DASN_DAC_IN1_C_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN1_D 0x184
+#define MTK_PHY_DASN_DAC_IN1_D_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DEV1E_REG19b 0x19b
+#define MTK_PHY_BYPASS_DSP_LPI_READY BIT(8)
+
+#define MTK_PHY_RG_LP_IIR2_K1_L 0x22a
+#define MTK_PHY_RG_LP_IIR2_K1_U 0x22b
+#define MTK_PHY_RG_LP_IIR2_K2_L 0x22c
+#define MTK_PHY_RG_LP_IIR2_K2_U 0x22d
+#define MTK_PHY_RG_LP_IIR2_K3_L 0x22e
+#define MTK_PHY_RG_LP_IIR2_K3_U 0x22f
+#define MTK_PHY_RG_LP_IIR2_K4_L 0x230
+#define MTK_PHY_RG_LP_IIR2_K4_U 0x231
+#define MTK_PHY_RG_LP_IIR2_K5_L 0x232
+#define MTK_PHY_RG_LP_IIR2_K5_U 0x233
+
+#define MTK_PHY_RG_DEV1E_REG234 0x234
+#define MTK_PHY_TR_OPEN_LOOP_EN_MASK GENMASK(0, 0)
+#define MTK_PHY_LPF_X_AVERAGE_MASK GENMASK(7, 4)
+#define MTK_PHY_TR_LP_IIR_EEE_EN BIT(12)
+
+#define MTK_PHY_RG_LPF_CNT_VAL 0x235
+
+#define MTK_PHY_RG_DEV1E_REG238 0x238
+#define MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK GENMASK(8, 0)
+#define MTK_PHY_LPI_SLV_SEND_TX_EN BIT(12)
+
+#define MTK_PHY_RG_DEV1E_REG239 0x239
+#define MTK_PHY_LPI_SEND_LOC_TIMER_MASK GENMASK(8, 0)
+#define MTK_PHY_LPI_TXPCS_LOC_RCV BIT(12)
+
+#define MTK_PHY_RG_DEV1E_REG27C 0x27c
+#define MTK_PHY_VGASTATE_FFE_THR_ST1_MASK GENMASK(12, 8)
+#define MTK_PHY_RG_DEV1E_REG27D 0x27d
+#define MTK_PHY_VGASTATE_FFE_THR_ST2_MASK GENMASK(4, 0)
+
+#define MTK_PHY_RG_DEV1E_REG2C7 0x2c7
+#define MTK_PHY_MAX_GAIN_MASK GENMASK(4, 0)
+#define MTK_PHY_MIN_GAIN_MASK GENMASK(12, 8)
+
+#define MTK_PHY_RG_DEV1E_REG2D1 0x2d1
+#define MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK GENMASK(7, 0)
+#define MTK_PHY_LPI_SKIP_SD_SLV_TR BIT(8)
+#define MTK_PHY_LPI_TR_READY BIT(9)
+#define MTK_PHY_LPI_VCO_EEE_STG0_EN BIT(10)
+
+#define MTK_PHY_RG_DEV1E_REG323 0x323
+#define MTK_PHY_EEE_WAKE_MAS_INT_DC BIT(0)
+#define MTK_PHY_EEE_WAKE_SLV_INT_DC BIT(4)
+
+#define MTK_PHY_RG_DEV1E_REG324 0x324
+#define MTK_PHY_SMI_DETCNT_MAX_MASK GENMASK(5, 0)
+#define MTK_PHY_SMI_DET_MAX_EN BIT(8)
+
+#define MTK_PHY_RG_DEV1E_REG326 0x326
+#define MTK_PHY_LPI_MODE_SD_ON BIT(0)
+#define MTK_PHY_RESET_RANDUPD_CNT BIT(1)
+#define MTK_PHY_TREC_UPDATE_ENAB_CLR BIT(2)
+#define MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF BIT(4)
+#define MTK_PHY_TR_READY_SKIP_AFE_WAKEUP BIT(5)
+
+#define MTK_PHY_LDO_PUMP_EN_PAIRAB 0x502
+#define MTK_PHY_LDO_PUMP_EN_PAIRCD 0x503
+
+#define MTK_PHY_DA_TX_R50_PAIR_A 0x53d
+#define MTK_PHY_DA_TX_R50_PAIR_B 0x53e
+#define MTK_PHY_DA_TX_R50_PAIR_C 0x53f
+#define MTK_PHY_DA_TX_R50_PAIR_D 0x540
+
+#define MTK_PHY_RG_BG_RASEL 0x115
+#define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0)
+
+/* These macro privides efuse parsing for internal phy. */
+#define EFS_DA_TX_I2MPB_A(x) (((x) >> 0) & GENMASK(5, 0))
+#define EFS_DA_TX_I2MPB_B(x) (((x) >> 6) & GENMASK(5, 0))
+#define EFS_DA_TX_I2MPB_C(x) (((x) >> 12) & GENMASK(5, 0))
+#define EFS_DA_TX_I2MPB_D(x) (((x) >> 18) & GENMASK(5, 0))
+#define EFS_DA_TX_AMP_OFFSET_A(x) (((x) >> 24) & GENMASK(5, 0))
+
+#define EFS_DA_TX_AMP_OFFSET_B(x) (((x) >> 0) & GENMASK(5, 0))
+#define EFS_DA_TX_AMP_OFFSET_C(x) (((x) >> 6) & GENMASK(5, 0))
+#define EFS_DA_TX_AMP_OFFSET_D(x) (((x) >> 12) & GENMASK(5, 0))
+#define EFS_DA_TX_R50_A(x) (((x) >> 18) & GENMASK(5, 0))
+#define EFS_DA_TX_R50_B(x) (((x) >> 24) & GENMASK(5, 0))
+
+#define EFS_DA_TX_R50_C(x) (((x) >> 0) & GENMASK(5, 0))
+#define EFS_DA_TX_R50_D(x) (((x) >> 6) & GENMASK(5, 0))
+
+#define EFS_RG_BG_RASEL(x) (((x) >> 4) & GENMASK(2, 0))
+#define EFS_RG_REXT_TRIM(x) (((x) >> 7) & GENMASK(5, 0))
+
+enum {
+ NO_PAIR,
+ PAIR_A,
+ PAIR_B,
+ PAIR_C,
+ PAIR_D,
+};
+
+enum {
+ GPHY_PORT0,
+ GPHY_PORT1,
+ GPHY_PORT2,
+ GPHY_PORT3,
+};
+
+enum calibration_mode {
+ EFUSE_K,
+ SW_K
+};
+
+enum CAL_ITEM {
+ REXT,
+ TX_OFFSET,
+ TX_AMP,
+ TX_R50,
+ TX_VCM
+};
+
+enum CAL_MODE {
+ EFUSE_M,
+ SW_M
+};
+
+static int mtk_socphy_read_page(struct phy_device *phydev)
+{
+ return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
+}
+
+static int mtk_socphy_write_page(struct phy_device *phydev, int page)
+{
+ return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
+}
+
+/* One calibration cycle consists of:
+ * 1.Set DA_CALIN_FLAG high to start calibration. Keep it high
+ * until AD_CAL_COMP is ready to output calibration result.
+ * 2.Wait until DA_CAL_CLK is available.
+ * 3.Fetch AD_CAL_COMP_OUT.
+ */
+static int cal_cycle(struct phy_device *phydev, int devad,
+ u32 regnum, u16 mask, u16 cal_val)
+{
+ int reg_val;
+ int ret;
+
+ phy_modify_mmd(phydev, devad, regnum,
+ mask, cal_val);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN,
+ MTK_PHY_DA_CALIN_FLAG);
+
+ ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_AD_CAL_CLK, reg_val,
+ reg_val & MTK_PHY_DA_CAL_CLK, 500,
+ ANALOG_INTERNAL_OPERATION_MAX_US, false);
+ if (ret) {
+ phydev_err(phydev, "Calibration cycle timeout\n");
+ return ret;
+ }
+
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN,
+ MTK_PHY_DA_CALIN_FLAG);
+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP) >>
+ MTK_PHY_AD_CAL_COMP_OUT_SHIFT;
+ phydev_dbg(phydev, "cal_val: 0x%x, ret: %d\n", cal_val, ret);
+
+ return ret;
+}
+
+static int rext_fill_result(struct phy_device *phydev, u16 *buf)
+{
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5,
+ MTK_PHY_RG_REXT_TRIM_MASK, buf[0] << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_BG_RASEL,
+ MTK_PHY_RG_BG_RASEL_MASK, buf[1]);
+
+ return 0;
+}
+
+static int rext_cal_efuse(struct phy_device *phydev, u32 *buf)
+{
+ u16 rext_cal_val[2];
+
+ rext_cal_val[0] = EFS_RG_REXT_TRIM(buf[3]);
+ rext_cal_val[1] = EFS_RG_BG_RASEL(buf[3]);
+ rext_fill_result(phydev, rext_cal_val);
+
+ return 0;
+}
+
+static int tx_offset_fill_result(struct phy_device *phydev, u16 *buf)
+{
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B,
+ MTK_PHY_CR_TX_AMP_OFFSET_A_MASK, buf[0] << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B,
+ MTK_PHY_CR_TX_AMP_OFFSET_B_MASK, buf[1]);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D,
+ MTK_PHY_CR_TX_AMP_OFFSET_C_MASK, buf[2] << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D,
+ MTK_PHY_CR_TX_AMP_OFFSET_D_MASK, buf[3]);
+
+ return 0;
+}
+
+static int tx_offset_cal_efuse(struct phy_device *phydev, u32 *buf)
+{
+ u16 tx_offset_cal_val[4];
+
+ tx_offset_cal_val[0] = EFS_DA_TX_AMP_OFFSET_A(buf[0]);
+ tx_offset_cal_val[1] = EFS_DA_TX_AMP_OFFSET_B(buf[1]);
+ tx_offset_cal_val[2] = EFS_DA_TX_AMP_OFFSET_C(buf[1]);
+ tx_offset_cal_val[3] = EFS_DA_TX_AMP_OFFSET_D(buf[1]);
+
+ tx_offset_fill_result(phydev, tx_offset_cal_val);
+
+ return 0;
+}
+
+static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf)
+{
+ int i;
+ int bias[16] = {};
+ const int vals_9461[16] = { 7, 1, 4, 7,
+ 7, 1, 4, 7,
+ 7, 1, 4, 7,
+ 7, 1, 4, 7 };
+ const int vals_9481[16] = { 10, 6, 6, 10,
+ 10, 6, 6, 10,
+ 10, 6, 6, 10,
+ 10, 6, 6, 10 };
+ switch (phydev->drv->phy_id) {
+ case MTK_GPHY_ID_MT7981:
+ /* We add some calibration to efuse values
+ * due to board level influence.
+ * GBE: +7, TBT: +1, HBT: +4, TST: +7
+ */
+ memcpy(bias, (const void *)vals_9461, sizeof(bias));
+ break;
+ case MTK_GPHY_ID_MT7988:
+ memcpy(bias, (const void *)vals_9481, sizeof(bias));
+ break;
+ }
+
+ /* Prevent overflow */
+ for (i = 0; i < 12; i++) {
+ if (buf[i >> 2] + bias[i] > 63) {
+ buf[i >> 2] = 63;
+ bias[i] = 0;
+ }
+ }
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
+ MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, (buf[0] + bias[0]) << 10);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
+ MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, buf[0] + bias[1]);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
+ MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, (buf[0] + bias[2]) << 10);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
+ MTK_PHY_DA_TX_I2MPB_A_TST_MASK, buf[0] + bias[3]);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
+ MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, (buf[1] + bias[4]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
+ MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, buf[1] + bias[5]);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
+ MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, (buf[1] + bias[6]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
+ MTK_PHY_DA_TX_I2MPB_B_TST_MASK, buf[1] + bias[7]);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
+ MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, (buf[2] + bias[8]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
+ MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, buf[2] + bias[9]);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
+ MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, (buf[2] + bias[10]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
+ MTK_PHY_DA_TX_I2MPB_C_TST_MASK, buf[2] + bias[11]);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
+ MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, (buf[3] + bias[12]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
+ MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, buf[3] + bias[13]);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
+ MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, (buf[3] + bias[14]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
+ MTK_PHY_DA_TX_I2MPB_D_TST_MASK, buf[3] + bias[15]);
+
+ return 0;
+}
+
+static int tx_amp_cal_efuse(struct phy_device *phydev, u32 *buf)
+{
+ u16 tx_amp_cal_val[4];
+
+ tx_amp_cal_val[0] = EFS_DA_TX_I2MPB_A(buf[0]);
+ tx_amp_cal_val[1] = EFS_DA_TX_I2MPB_B(buf[0]);
+ tx_amp_cal_val[2] = EFS_DA_TX_I2MPB_C(buf[0]);
+ tx_amp_cal_val[3] = EFS_DA_TX_I2MPB_D(buf[0]);
+ tx_amp_fill_result(phydev, tx_amp_cal_val);
+
+ return 0;
+}
+
+static int tx_r50_fill_result(struct phy_device *phydev, u16 tx_r50_cal_val,
+ u8 txg_calen_x)
+{
+ int bias = 0;
+ u16 reg, val;
+
+ if (phydev->drv->phy_id == MTK_GPHY_ID_MT7988)
+ bias = -2;
+
+ val = clamp_val(bias + tx_r50_cal_val, 0, 63);
+
+ switch (txg_calen_x) {
+ case PAIR_A:
+ reg = MTK_PHY_DA_TX_R50_PAIR_A;
+ break;
+ case PAIR_B:
+ reg = MTK_PHY_DA_TX_R50_PAIR_B;
+ break;
+ case PAIR_C:
+ reg = MTK_PHY_DA_TX_R50_PAIR_C;
+ break;
+ case PAIR_D:
+ reg = MTK_PHY_DA_TX_R50_PAIR_D;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, val | val << 8);
+
+ return 0;
+}
+
+static int tx_r50_cal_efuse(struct phy_device *phydev, u32 *buf,
+ u8 txg_calen_x)
+{
+ u16 tx_r50_cal_val;
+
+ switch (txg_calen_x) {
+ case PAIR_A:
+ tx_r50_cal_val = EFS_DA_TX_R50_A(buf[1]);
+ break;
+ case PAIR_B:
+ tx_r50_cal_val = EFS_DA_TX_R50_B(buf[1]);
+ break;
+ case PAIR_C:
+ tx_r50_cal_val = EFS_DA_TX_R50_C(buf[2]);
+ break;
+ case PAIR_D:
+ tx_r50_cal_val = EFS_DA_TX_R50_D(buf[2]);
+ break;
+ default:
+ return -EINVAL;
+ }
+ tx_r50_fill_result(phydev, tx_r50_cal_val, txg_calen_x);
+
+ return 0;
+}
+
+static int tx_vcm_cal_sw(struct phy_device *phydev, u8 rg_txreserve_x)
+{
+ u8 lower_idx, upper_idx, txreserve_val;
+ u8 lower_ret, upper_ret;
+ int ret;
+
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_ANA_CALEN);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_CAL_CKINV);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_TXVOS_CALEN);
+
+ switch (rg_txreserve_x) {
+ case PAIR_A:
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN0_A,
+ MTK_PHY_DASN_DAC_IN0_A_MASK);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN1_A,
+ MTK_PHY_DASN_DAC_IN1_A_MASK);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_ZCALEN_A);
+ break;
+ case PAIR_B:
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN0_B,
+ MTK_PHY_DASN_DAC_IN0_B_MASK);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN1_B,
+ MTK_PHY_DASN_DAC_IN1_B_MASK);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_ZCALEN_B);
+ break;
+ case PAIR_C:
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN0_C,
+ MTK_PHY_DASN_DAC_IN0_C_MASK);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN1_C,
+ MTK_PHY_DASN_DAC_IN1_C_MASK);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_ZCALEN_C);
+ break;
+ case PAIR_D:
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN0_D,
+ MTK_PHY_DASN_DAC_IN0_D_MASK);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN1_D,
+ MTK_PHY_DASN_DAC_IN1_D_MASK);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_ZCALEN_D);
+ break;
+ default:
+ ret = -EINVAL;
+ goto restore;
+ }
+
+ lower_idx = TXRESERVE_MIN;
+ upper_idx = TXRESERVE_MAX;
+
+ phydev_dbg(phydev, "Start TX-VCM SW cal.\n");
+ while ((upper_idx - lower_idx) > 1) {
+ txreserve_val = DIV_ROUND_CLOSEST(lower_idx + upper_idx, 2);
+ ret = cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
+ MTK_PHY_DA_RX_PSBN_TBT_MASK |
+ MTK_PHY_DA_RX_PSBN_HBT_MASK |
+ MTK_PHY_DA_RX_PSBN_GBE_MASK |
+ MTK_PHY_DA_RX_PSBN_LP_MASK,
+ txreserve_val << 12 | txreserve_val << 8 |
+ txreserve_val << 4 | txreserve_val);
+ if (ret == 1) {
+ upper_idx = txreserve_val;
+ upper_ret = ret;
+ } else if (ret == 0) {
+ lower_idx = txreserve_val;
+ lower_ret = ret;
+ } else {
+ goto restore;
+ }
+ }
+
+ if (lower_idx == TXRESERVE_MIN) {
+ lower_ret = cal_cycle(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RXADC_CTRL_RG9,
+ MTK_PHY_DA_RX_PSBN_TBT_MASK |
+ MTK_PHY_DA_RX_PSBN_HBT_MASK |
+ MTK_PHY_DA_RX_PSBN_GBE_MASK |
+ MTK_PHY_DA_RX_PSBN_LP_MASK,
+ lower_idx << 12 | lower_idx << 8 |
+ lower_idx << 4 | lower_idx);
+ ret = lower_ret;
+ } else if (upper_idx == TXRESERVE_MAX) {
+ upper_ret = cal_cycle(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RXADC_CTRL_RG9,
+ MTK_PHY_DA_RX_PSBN_TBT_MASK |
+ MTK_PHY_DA_RX_PSBN_HBT_MASK |
+ MTK_PHY_DA_RX_PSBN_GBE_MASK |
+ MTK_PHY_DA_RX_PSBN_LP_MASK,
+ upper_idx << 12 | upper_idx << 8 |
+ upper_idx << 4 | upper_idx);
+ ret = upper_ret;
+ }
+ if (ret < 0)
+ goto restore;
+
+ /* We calibrate TX-VCM in different logic. Check upper index and then
+ * lower index. If this calibration is valid, apply lower index's result.
+ */
+ ret = upper_ret - lower_ret;
+ if (ret == 1) {
+ ret = 0;
+ /* Make sure we use upper_idx in our calibration system */
+ cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
+ MTK_PHY_DA_RX_PSBN_TBT_MASK |
+ MTK_PHY_DA_RX_PSBN_HBT_MASK |
+ MTK_PHY_DA_RX_PSBN_GBE_MASK |
+ MTK_PHY_DA_RX_PSBN_LP_MASK,
+ upper_idx << 12 | upper_idx << 8 |
+ upper_idx << 4 | upper_idx);
+ phydev_dbg(phydev, "TX-VCM SW cal result: 0x%x\n", upper_idx);
+ } else if (lower_idx == TXRESERVE_MIN && upper_ret == 1 &&
+ lower_ret == 1) {
+ ret = 0;
+ cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
+ MTK_PHY_DA_RX_PSBN_TBT_MASK |
+ MTK_PHY_DA_RX_PSBN_HBT_MASK |
+ MTK_PHY_DA_RX_PSBN_GBE_MASK |
+ MTK_PHY_DA_RX_PSBN_LP_MASK,
+ lower_idx << 12 | lower_idx << 8 |
+ lower_idx << 4 | lower_idx);
+ phydev_warn(phydev, "TX-VCM SW cal result at low margin 0x%x\n",
+ lower_idx);
+ } else if (upper_idx == TXRESERVE_MAX && upper_ret == 0 &&
+ lower_ret == 0) {
+ ret = 0;
+ phydev_warn(phydev, "TX-VCM SW cal result at high margin 0x%x\n",
+ upper_idx);
+ } else {
+ ret = -EINVAL;
+ }
+
+restore:
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_ANA_CALEN);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_TXVOS_CALEN);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_ZCALEN_A);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_ZCALEN_B | MTK_PHY_RG_ZCALEN_C |
+ MTK_PHY_RG_ZCALEN_D);
+
+ return ret;
+}
+
+static void mt798x_phy_common_finetune(struct phy_device *phydev)
+{
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+ /* EnabRandUpdTrig = 1 */
+ __phy_write(phydev, 0x11, 0x2f00);
+ __phy_write(phydev, 0x12, 0xe);
+ __phy_write(phydev, 0x10, 0x8fb0);
+
+ /* NormMseLoThresh = 85 */
+ __phy_write(phydev, 0x11, 0x55a0);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x83aa);
+
+ /* TrFreeze = 0 */
+ __phy_write(phydev, 0x11, 0x0);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x9686);
+
+ /* SSTrKp1000Slv = 5 */
+ __phy_write(phydev, 0x11, 0xbaef);
+ __phy_write(phydev, 0x12, 0x2e);
+ __phy_write(phydev, 0x10, 0x968c);
+
+ /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2,
+ * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2
+ */
+ __phy_write(phydev, 0x11, 0xd10a);
+ __phy_write(phydev, 0x12, 0x34);
+ __phy_write(phydev, 0x10, 0x8f82);
+
+ /* VcoSlicerThreshBitsHigh */
+ __phy_write(phydev, 0x11, 0x5555);
+ __phy_write(phydev, 0x12, 0x55);
+ __phy_write(phydev, 0x10, 0x8ec0);
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9*/
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
+ MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
+ BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9));
+
+ /* rg_tr_lpf_cnt_val = 512 */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x200);
+
+ /* IIR2 related */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_L, 0x82);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_U, 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_L, 0x103);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_U, 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_L, 0x82);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_U, 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_L, 0xd177);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_U, 0x3);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_L, 0x2c82);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_U, 0xe);
+
+ /* FFE peaking */
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27C,
+ MTK_PHY_VGASTATE_FFE_THR_ST1_MASK, 0x1b << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27D,
+ MTK_PHY_VGASTATE_FFE_THR_ST2_MASK, 0x1e);
+
+ /* Disable LDO pump */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRAB, 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRCD, 0x0);
+ /* Adjust LDO output voltage */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_OUTPUT_V, 0x2222);
+}
+
+static void mt7981_phy_finetune(struct phy_device *phydev)
+{
+ u16 val[8] = { 0x01ce, 0x01c1,
+ 0x020f, 0x0202,
+ 0x03d0, 0x03c0,
+ 0x0013, 0x0005 };
+ int i, k;
+
+ /* 100M eye finetune:
+ * Keep middle level of TX MLT3 shapper as default.
+ * Only change TX MLT3 overshoot level here.
+ */
+ for (k = 0, i = 1; i < 12; i++) {
+ if (i % 3 == 0)
+ continue;
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[k++]);
+ }
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+ /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */
+ __phy_write(phydev, 0x11, 0xc71);
+ __phy_write(phydev, 0x12, 0xc);
+ __phy_write(phydev, 0x10, 0x8fae);
+
+ /* ResetSyncOffset = 6 */
+ __phy_write(phydev, 0x11, 0x600);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x8fc0);
+
+ /* VgaDecRate = 1 */
+ __phy_write(phydev, 0x11, 0x4c2a);
+ __phy_write(phydev, 0x12, 0x3e);
+ __phy_write(phydev, 0x10, 0x8fa4);
+
+ /* FfeUpdGainForce = 4 */
+ __phy_write(phydev, 0x11, 0x240);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x9680);
+
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+}
+
+static void mt7988_phy_finetune(struct phy_device *phydev)
+{
+ u16 val[12] = { 0x0187, 0x01cd, 0x01c8, 0x0182,
+ 0x020d, 0x0206, 0x0384, 0x03d0,
+ 0x03c6, 0x030a, 0x0011, 0x0005 };
+ int i;
+
+ /* Set default MLT3 shaper first */
+ for (i = 0; i < 12; i++)
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[i]);
+
+ /* TCT finetune */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5);
+
+ /* Disable TX power saving */
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7,
+ MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8);
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+
+ /* SlvDSPreadyTime = 24, MasDSPreadyTime = 12 */
+ __phy_write(phydev, 0x11, 0x671);
+ __phy_write(phydev, 0x12, 0xc);
+ __phy_write(phydev, 0x10, 0x8fae);
+
+ /* ResetSyncOffset = 5 */
+ __phy_write(phydev, 0x11, 0x500);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x8fc0);
+
+ /* VgaDecRate is 1 at default on mt7988 */
+
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_2A30);
+ /* TxClkOffset = 2 */
+ __phy_modify(phydev, MTK_PHY_ANARG_RG, MTK_PHY_TCLKOFFSET_MASK,
+ FIELD_PREP(MTK_PHY_TCLKOFFSET_MASK, 0x2));
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+}
+
+static void mt798x_phy_eee(struct phy_device *phydev)
+{
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120,
+ MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK |
+ MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK,
+ FIELD_PREP(MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK, 0x0) |
+ FIELD_PREP(MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK, 0x14));
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122,
+ MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
+ 0xff));
+
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_TESTMUX_ADC_CTRL,
+ MTK_PHY_RG_TXEN_DIG_MASK);
+
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DEV1E_REG19b, MTK_PHY_BYPASS_DSP_LPI_READY);
+
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DEV1E_REG234, MTK_PHY_TR_LP_IIR_EEE_EN);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG238,
+ MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK |
+ MTK_PHY_LPI_SLV_SEND_TX_EN,
+ FIELD_PREP(MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK, 0x120));
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239,
+ MTK_PHY_LPI_SEND_LOC_TIMER_MASK |
+ MTK_PHY_LPI_TXPCS_LOC_RCV,
+ FIELD_PREP(MTK_PHY_LPI_SEND_LOC_TIMER_MASK, 0x117));
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7,
+ MTK_PHY_MAX_GAIN_MASK | MTK_PHY_MIN_GAIN_MASK,
+ FIELD_PREP(MTK_PHY_MAX_GAIN_MASK, 0x8) |
+ FIELD_PREP(MTK_PHY_MIN_GAIN_MASK, 0x13));
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2D1,
+ MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK,
+ FIELD_PREP(MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK,
+ 0x33) |
+ MTK_PHY_LPI_SKIP_SD_SLV_TR | MTK_PHY_LPI_TR_READY |
+ MTK_PHY_LPI_VCO_EEE_STG0_EN);
+
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG323,
+ MTK_PHY_EEE_WAKE_MAS_INT_DC |
+ MTK_PHY_EEE_WAKE_SLV_INT_DC);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG324,
+ MTK_PHY_SMI_DETCNT_MAX_MASK,
+ FIELD_PREP(MTK_PHY_SMI_DETCNT_MAX_MASK, 0x3f) |
+ MTK_PHY_SMI_DET_MAX_EN);
+
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG326,
+ MTK_PHY_LPI_MODE_SD_ON | MTK_PHY_RESET_RANDUPD_CNT |
+ MTK_PHY_TREC_UPDATE_ENAB_CLR |
+ MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF |
+ MTK_PHY_TR_READY_SKIP_AFE_WAKEUP);
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+ /* Regsigdet_sel_1000 = 0 */
+ __phy_write(phydev, 0x11, 0xb);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x9690);
+
+ /* REG_EEE_st2TrKf1000 = 3 */
+ __phy_write(phydev, 0x11, 0x114f);
+ __phy_write(phydev, 0x12, 0x2);
+ __phy_write(phydev, 0x10, 0x969a);
+
+ /* RegEEE_slv_wake_tr_timer_tar = 6, RegEEE_slv_remtx_timer_tar = 20 */
+ __phy_write(phydev, 0x11, 0x3028);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x969e);
+
+ /* RegEEE_slv_wake_int_timer_tar = 8 */
+ __phy_write(phydev, 0x11, 0x5010);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x96a0);
+
+ /* RegEEE_trfreeze_timer2 = 586 */
+ __phy_write(phydev, 0x11, 0x24a);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x96a8);
+
+ /* RegEEE100Stg1_tar = 16 */
+ __phy_write(phydev, 0x11, 0x3210);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x96b8);
+
+ /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 1 */
+ __phy_write(phydev, 0x11, 0x1463);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x96ca);
+
+ /* DfeTailEnableVgaThresh1000 = 27 */
+ __phy_write(phydev, 0x11, 0x36);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x8f80);
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3);
+ __phy_modify(phydev, MTK_PHY_LPI_REG_14, MTK_PHY_LPI_WAKE_TIMER_1000_MASK,
+ FIELD_PREP(MTK_PHY_LPI_WAKE_TIMER_1000_MASK, 0x19c));
+
+ __phy_modify(phydev, MTK_PHY_LPI_REG_1c, MTK_PHY_SMI_DET_ON_THRESH_MASK,
+ FIELD_PREP(MTK_PHY_SMI_DET_ON_THRESH_MASK, 0xc));
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122,
+ MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, 0xff));
+}
+
+static int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item,
+ u8 start_pair, u8 end_pair)
+{
+ u8 pair_n;
+ int ret;
+
+ for (pair_n = start_pair; pair_n <= end_pair; pair_n++) {
+ /* TX_OFFSET & TX_AMP have no SW calibration. */
+ switch (cal_item) {
+ case TX_VCM:
+ ret = tx_vcm_cal_sw(phydev, pair_n);
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static int cal_efuse(struct phy_device *phydev, enum CAL_ITEM cal_item,
+ u8 start_pair, u8 end_pair, u32 *buf)
+{
+ u8 pair_n;
+ int ret;
+
+ for (pair_n = start_pair; pair_n <= end_pair; pair_n++) {
+ /* TX_VCM has no efuse calibration. */
+ switch (cal_item) {
+ case REXT:
+ ret = rext_cal_efuse(phydev, buf);
+ break;
+ case TX_OFFSET:
+ ret = tx_offset_cal_efuse(phydev, buf);
+ break;
+ case TX_AMP:
+ ret = tx_amp_cal_efuse(phydev, buf);
+ break;
+ case TX_R50:
+ ret = tx_r50_cal_efuse(phydev, buf, pair_n);
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int start_cal(struct phy_device *phydev, enum CAL_ITEM cal_item,
+ enum CAL_MODE cal_mode, u8 start_pair,
+ u8 end_pair, u32 *buf)
+{
+ int ret;
+
+ switch (cal_mode) {
+ case EFUSE_M:
+ ret = cal_efuse(phydev, cal_item, start_pair,
+ end_pair, buf);
+ break;
+ case SW_M:
+ ret = cal_sw(phydev, cal_item, start_pair, end_pair);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (ret) {
+ phydev_err(phydev, "cal %d failed\n", cal_item);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int mt798x_phy_calibration(struct phy_device *phydev)
+{
+ int ret = 0;
+ u32 *buf;
+ size_t len;
+ struct nvmem_cell *cell;
+
+ cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data");
+ if (IS_ERR(cell)) {
+ if (PTR_ERR(cell) == -EPROBE_DEFER)
+ return PTR_ERR(cell);
+ return 0;
+ }
+
+ buf = (u32 *)nvmem_cell_read(cell, &len);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+ nvmem_cell_put(cell);
+
+ if (!buf[0] || !buf[1] || !buf[2] || !buf[3] || len < 4 * sizeof(u32)) {
+ phydev_err(phydev, "invalid efuse data\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = start_cal(phydev, REXT, EFUSE_M, NO_PAIR, NO_PAIR, buf);
+ if (ret)
+ goto out;
+ ret = start_cal(phydev, TX_OFFSET, EFUSE_M, NO_PAIR, NO_PAIR, buf);
+ if (ret)
+ goto out;
+ ret = start_cal(phydev, TX_AMP, EFUSE_M, NO_PAIR, NO_PAIR, buf);
+ if (ret)
+ goto out;
+ ret = start_cal(phydev, TX_R50, EFUSE_M, PAIR_A, PAIR_D, buf);
+ if (ret)
+ goto out;
+ ret = start_cal(phydev, TX_VCM, SW_M, PAIR_A, PAIR_A, buf);
+ if (ret)
+ goto out;
+
+out:
+ kfree(buf);
+ return ret;
+}
+
+static int mt798x_phy_config_init(struct phy_device *phydev)
+{
+ switch (phydev->drv->phy_id) {
+ case MTK_GPHY_ID_MT7981:
+ mt7981_phy_finetune(phydev);
+ break;
+ case MTK_GPHY_ID_MT7988:
+ mt7988_phy_finetune(phydev);
+ break;
+ }
+
+ mt798x_phy_common_finetune(phydev);
+ mt798x_phy_eee(phydev);
+
+ return mt798x_phy_calibration(phydev);
+}
+
+static struct phy_driver mtk_socphy_driver[] = {
+ {
+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981),
+ .name = "MediaTek MT7981 PHY",
+ .config_init = mt798x_phy_config_init,
+ .config_intr = genphy_no_config_intr,
+ .handle_interrupt = genphy_handle_interrupt_no_ack,
+ .probe = mt798x_phy_calibration,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = mtk_socphy_read_page,
+ .write_page = mtk_socphy_write_page,
+ },
+ {
+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988),
+ .name = "MediaTek MT7988 PHY",
+ .config_init = mt798x_phy_config_init,
+ .config_intr = genphy_no_config_intr,
+ .handle_interrupt = genphy_handle_interrupt_no_ack,
+ .probe = mt798x_phy_calibration,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = mtk_socphy_read_page,
+ .write_page = mtk_socphy_write_page,
+ },
+};
+
+module_phy_driver(mtk_socphy_driver);
+
+static struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = {
+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981) },
+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988) },
+ { }
+};
+
+MODULE_DESCRIPTION("MediaTek SoC Gigabit Ethernet PHY driver");
+MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
+MODULE_AUTHOR("SkyLake Huang <SkyLake.Huang@mediatek.com>");
+MODULE_LICENSE("GPL");
+
+MODULE_DEVICE_TABLE(mdio, mtk_socphy_tbl);
diff --git a/drivers/net/phy/mediatek-ge.c b/drivers/net/phy/mediatek-ge.c
index 68ee434f9dea..a493ae01b267 100644
--- a/drivers/net/phy/mediatek-ge.c
+++ b/drivers/net/phy/mediatek-ge.c
@@ -102,7 +102,8 @@ static struct phy_driver mtk_gephy_driver[] = {
module_phy_driver(mtk_gephy_driver);
static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = {
- { PHY_ID_MATCH_VENDOR(0x03a29400) },
+ { PHY_ID_MATCH_EXACT(0x03a29441) },
+ { PHY_ID_MATCH_EXACT(0x03a29412) },
{ }
};
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 3f81bb8dac44..b6d7981b2d1e 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -252,6 +252,9 @@
#define PS_TO_REG 200
#define FIFO_SIZE 8
+/* Delay used to get the second part from the LTC */
+#define LAN8841_GET_SEC_LTC_DELAY (500 * NSEC_PER_MSEC)
+
struct kszphy_hw_stat {
const char *string;
u8 reg;
@@ -319,6 +322,10 @@ struct kszphy_ptp_priv {
/* Lock for ptp_clock */
struct mutex ptp_lock;
struct ptp_pin_desc *pin_config;
+
+ s64 seconds;
+ /* Lock for accessing seconds */
+ spinlock_t seconds_lock;
};
struct kszphy_priv {
@@ -637,7 +644,7 @@ static int ksz8051_ksz8795_match_phy_device(struct phy_device *phydev,
{
int ret;
- if ((phydev->phy_id & MICREL_PHY_ID_MASK) != PHY_ID_KSZ8051)
+ if (!phy_id_compare(phydev->phy_id, PHY_ID_KSZ8051, MICREL_PHY_ID_MASK))
return 0;
ret = phy_read(phydev, MII_BMSR);
@@ -1566,7 +1573,7 @@ static int ksz9x31_cable_test_fault_length(struct phy_device *phydev, u16 stat)
*
* distance to fault = (VCT_DATA - 22) * 4 / cable propagation velocity
*/
- if ((phydev->phy_id & MICREL_PHY_ID_MASK) == PHY_ID_KSZ9131)
+ if (phydev_id_compare(phydev, PHY_ID_KSZ9131))
dt = clamp(dt - 22, 0, 255);
return (dt * 400) / 10;
@@ -1774,6 +1781,79 @@ static int ksz886x_read_status(struct phy_device *phydev)
return genphy_read_status(phydev);
}
+struct ksz9477_errata_write {
+ u8 dev_addr;
+ u8 reg_addr;
+ u16 val;
+};
+
+static const struct ksz9477_errata_write ksz9477_errata_writes[] = {
+ /* Register settings are needed to improve PHY receive performance */
+ {0x01, 0x6f, 0xdd0b},
+ {0x01, 0x8f, 0x6032},
+ {0x01, 0x9d, 0x248c},
+ {0x01, 0x75, 0x0060},
+ {0x01, 0xd3, 0x7777},
+ {0x1c, 0x06, 0x3008},
+ {0x1c, 0x08, 0x2000},
+
+ /* Transmit waveform amplitude can be improved (1000BASE-T, 100BASE-TX, 10BASE-Te) */
+ {0x1c, 0x04, 0x00d0},
+
+ /* Energy Efficient Ethernet (EEE) feature select must be manually disabled */
+ {0x07, 0x3c, 0x0000},
+
+ /* Register settings are required to meet data sheet supply current specifications */
+ {0x1c, 0x13, 0x6eff},
+ {0x1c, 0x14, 0xe6ff},
+ {0x1c, 0x15, 0x6eff},
+ {0x1c, 0x16, 0xe6ff},
+ {0x1c, 0x17, 0x00ff},
+ {0x1c, 0x18, 0x43ff},
+ {0x1c, 0x19, 0xc3ff},
+ {0x1c, 0x1a, 0x6fff},
+ {0x1c, 0x1b, 0x07ff},
+ {0x1c, 0x1c, 0x0fff},
+ {0x1c, 0x1d, 0xe7ff},
+ {0x1c, 0x1e, 0xefff},
+ {0x1c, 0x20, 0xeeee},
+};
+
+static int ksz9477_config_init(struct phy_device *phydev)
+{
+ int err;
+ int i;
+
+ /* Apply PHY settings to address errata listed in
+ * KSZ9477, KSZ9897, KSZ9896, KSZ9567, KSZ8565
+ * Silicon Errata and Data Sheet Clarification documents.
+ *
+ * Document notes: Before configuring the PHY MMD registers, it is
+ * necessary to set the PHY to 100 Mbps speed with auto-negotiation
+ * disabled by writing to register 0xN100-0xN101. After writing the
+ * MMD registers, and after all errata workarounds that involve PHY
+ * register settings, write register 0xN100-0xN101 again to enable
+ * and restart auto-negotiation.
+ */
+ err = phy_write(phydev, MII_BMCR, BMCR_SPEED100 | BMCR_FULLDPLX);
+ if (err)
+ return err;
+
+ for (i = 0; i < ARRAY_SIZE(ksz9477_errata_writes); ++i) {
+ const struct ksz9477_errata_write *errata = &ksz9477_errata_writes[i];
+
+ err = phy_write_mmd(phydev, errata->dev_addr, errata->reg_addr, errata->val);
+ if (err)
+ return err;
+ }
+
+ err = genphy_restart_aneg(phydev);
+ if (err)
+ return err;
+
+ return kszphy_config_init(phydev);
+}
+
static int kszphy_get_sset_count(struct phy_device *phydev)
{
return ARRAY_SIZE(kszphy_hw_stats);
@@ -1998,7 +2078,7 @@ static __always_inline int ksz886x_cable_test_fault_length(struct phy_device *ph
*/
dt = FIELD_GET(data_mask, status);
- if ((phydev->phy_id & MICREL_PHY_ID_MASK) == PHY_ID_LAN8814)
+ if (phydev_id_compare(phydev, PHY_ID_LAN8814))
return ((dt - 22) * 800) / 10;
else
return (dt * 400) / 10;
@@ -3238,6 +3318,9 @@ static int lan8814_probe(struct phy_device *phydev)
#define LAN8841_PTP_CMD_CTL_PTP_RESET BIT(0)
#define LAN8841_PTP_RX_PARSE_CONFIG 368
#define LAN8841_PTP_TX_PARSE_CONFIG 432
+#define LAN8841_PTP_RX_MODE 381
+#define LAN8841_PTP_INSERT_TS_EN BIT(0)
+#define LAN8841_PTP_INSERT_TS_32BIT BIT(1)
static int lan8841_config_init(struct phy_device *phydev)
{
@@ -3386,68 +3469,18 @@ static void lan8841_ptp_process_tx_ts(struct kszphy_ptp_priv *ptp_priv)
lan8814_match_tx_skb(ptp_priv, sec, nsec, seq);
}
-#define LAN8841_PTP_RX_INGRESS_SEC_LO 389
-#define LAN8841_PTP_RX_INGRESS_SEC_HI 388
-#define LAN8841_PTP_RX_INGRESS_NS_LO 387
-#define LAN8841_PTP_RX_INGRESS_NS_HI 386
-#define LAN8841_PTP_RX_INGRESS_NSEC_HI_VALID BIT(15)
-#define LAN8841_PTP_RX_MSG_HEADER2 391
-
-static struct lan8814_ptp_rx_ts *lan8841_ptp_get_rx_ts(struct kszphy_ptp_priv *ptp_priv)
-{
- struct phy_device *phydev = ptp_priv->phydev;
- struct lan8814_ptp_rx_ts *rx_ts;
- u32 sec, nsec;
- u16 seq;
-
- nsec = phy_read_mmd(phydev, 2, LAN8841_PTP_RX_INGRESS_NS_HI);
- if (!(nsec & LAN8841_PTP_RX_INGRESS_NSEC_HI_VALID))
- return NULL;
-
- nsec = ((nsec & 0x3fff) << 16);
- nsec = nsec | phy_read_mmd(phydev, 2, LAN8841_PTP_RX_INGRESS_NS_LO);
-
- sec = phy_read_mmd(phydev, 2, LAN8841_PTP_RX_INGRESS_SEC_HI);
- sec = sec << 16;
- sec = sec | phy_read_mmd(phydev, 2, LAN8841_PTP_RX_INGRESS_SEC_LO);
-
- seq = phy_read_mmd(phydev, 2, LAN8841_PTP_RX_MSG_HEADER2);
-
- rx_ts = kzalloc(sizeof(*rx_ts), GFP_KERNEL);
- if (!rx_ts)
- return NULL;
-
- rx_ts->seconds = sec;
- rx_ts->nsec = nsec;
- rx_ts->seq_id = seq;
-
- return rx_ts;
-}
-
-static void lan8841_ptp_process_rx_ts(struct kszphy_ptp_priv *ptp_priv)
-{
- struct lan8814_ptp_rx_ts *rx_ts;
-
- while ((rx_ts = lan8841_ptp_get_rx_ts(ptp_priv)) != NULL)
- lan8814_match_rx_ts(ptp_priv, rx_ts);
-}
-
#define LAN8841_PTP_INT_STS 259
#define LAN8841_PTP_INT_STS_PTP_TX_TS_OVRFL_INT BIT(13)
#define LAN8841_PTP_INT_STS_PTP_TX_TS_INT BIT(12)
-#define LAN8841_PTP_INT_STS_PTP_RX_TS_OVRFL_INT BIT(9)
-#define LAN8841_PTP_INT_STS_PTP_RX_TS_INT BIT(8)
#define LAN8841_PTP_INT_STS_PTP_GPIO_CAP_INT BIT(2)
-static void lan8841_ptp_flush_fifo(struct kszphy_ptp_priv *ptp_priv, bool egress)
+static void lan8841_ptp_flush_fifo(struct kszphy_ptp_priv *ptp_priv)
{
struct phy_device *phydev = ptp_priv->phydev;
int i;
for (i = 0; i < FIFO_SIZE; ++i)
- phy_read_mmd(phydev, 2,
- egress ? LAN8841_PTP_TX_MSG_HEADER2 :
- LAN8841_PTP_RX_MSG_HEADER2);
+ phy_read_mmd(phydev, 2, LAN8841_PTP_TX_MSG_HEADER2);
phy_read_mmd(phydev, 2, LAN8841_PTP_INT_STS);
}
@@ -3525,23 +3558,17 @@ static void lan8841_handle_ptp_interrupt(struct phy_device *phydev)
if (status & LAN8841_PTP_INT_STS_PTP_TX_TS_INT)
lan8841_ptp_process_tx_ts(ptp_priv);
- if (status & LAN8841_PTP_INT_STS_PTP_RX_TS_INT)
- lan8841_ptp_process_rx_ts(ptp_priv);
-
if (status & LAN8841_PTP_INT_STS_PTP_GPIO_CAP_INT)
lan8841_gpio_process_cap(ptp_priv);
if (status & LAN8841_PTP_INT_STS_PTP_TX_TS_OVRFL_INT) {
- lan8841_ptp_flush_fifo(ptp_priv, true);
+ lan8841_ptp_flush_fifo(ptp_priv);
skb_queue_purge(&ptp_priv->tx_queue);
}
- if (status & LAN8841_PTP_INT_STS_PTP_RX_TS_OVRFL_INT) {
- lan8841_ptp_flush_fifo(ptp_priv, false);
- skb_queue_purge(&ptp_priv->rx_queue);
- }
-
- } while (status);
+ } while (status & (LAN8841_PTP_INT_STS_PTP_TX_TS_INT |
+ LAN8841_PTP_INT_STS_PTP_GPIO_CAP_INT |
+ LAN8841_PTP_INT_STS_PTP_TX_TS_OVRFL_INT));
}
#define LAN8841_INTS_PTP BIT(9)
@@ -3605,32 +3632,46 @@ static int lan8841_ts_info(struct mii_timestamper *mii_ts,
#define LAN8841_PTP_INT_EN 260
#define LAN8841_PTP_INT_EN_PTP_TX_TS_OVRFL_EN BIT(13)
#define LAN8841_PTP_INT_EN_PTP_TX_TS_EN BIT(12)
-#define LAN8841_PTP_INT_EN_PTP_RX_TS_OVRFL_EN BIT(9)
-#define LAN8841_PTP_INT_EN_PTP_RX_TS_EN BIT(8)
-static void lan8841_ptp_enable_int(struct kszphy_ptp_priv *ptp_priv,
- bool enable)
+static void lan8841_ptp_enable_processing(struct kszphy_ptp_priv *ptp_priv,
+ bool enable)
{
struct phy_device *phydev = ptp_priv->phydev;
- if (enable)
- /* Enable interrupts */
+ if (enable) {
+ /* Enable interrupts on the TX side */
phy_modify_mmd(phydev, 2, LAN8841_PTP_INT_EN,
LAN8841_PTP_INT_EN_PTP_TX_TS_OVRFL_EN |
- LAN8841_PTP_INT_EN_PTP_RX_TS_OVRFL_EN |
- LAN8841_PTP_INT_EN_PTP_TX_TS_EN |
- LAN8841_PTP_INT_EN_PTP_RX_TS_EN,
+ LAN8841_PTP_INT_EN_PTP_TX_TS_EN,
LAN8841_PTP_INT_EN_PTP_TX_TS_OVRFL_EN |
- LAN8841_PTP_INT_EN_PTP_RX_TS_OVRFL_EN |
- LAN8841_PTP_INT_EN_PTP_TX_TS_EN |
- LAN8841_PTP_INT_EN_PTP_RX_TS_EN);
- else
- /* Disable interrupts */
+ LAN8841_PTP_INT_EN_PTP_TX_TS_EN);
+
+ /* Enable the modification of the frame on RX side,
+ * this will add the ns and 2 bits of sec in the reserved field
+ * of the PTP header
+ */
+ phy_modify_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
+ LAN8841_PTP_RX_MODE,
+ LAN8841_PTP_INSERT_TS_EN |
+ LAN8841_PTP_INSERT_TS_32BIT,
+ LAN8841_PTP_INSERT_TS_EN |
+ LAN8841_PTP_INSERT_TS_32BIT);
+
+ ptp_schedule_worker(ptp_priv->ptp_clock, 0);
+ } else {
+ /* Disable interrupts on the TX side */
phy_modify_mmd(phydev, 2, LAN8841_PTP_INT_EN,
LAN8841_PTP_INT_EN_PTP_TX_TS_OVRFL_EN |
- LAN8841_PTP_INT_EN_PTP_RX_TS_OVRFL_EN |
- LAN8841_PTP_INT_EN_PTP_TX_TS_EN |
- LAN8841_PTP_INT_EN_PTP_RX_TS_EN, 0);
+ LAN8841_PTP_INT_EN_PTP_TX_TS_EN, 0);
+
+ /* Disable modification of the RX frames */
+ phy_modify_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
+ LAN8841_PTP_RX_MODE,
+ LAN8841_PTP_INSERT_TS_EN |
+ LAN8841_PTP_INSERT_TS_32BIT, 0);
+
+ ptp_cancel_worker_sync(ptp_priv->ptp_clock);
+ }
}
#define LAN8841_PTP_RX_TIMESTAMP_EN 379
@@ -3641,7 +3682,6 @@ static int lan8841_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr)
{
struct kszphy_ptp_priv *ptp_priv = container_of(mii_ts, struct kszphy_ptp_priv, mii_ts);
struct phy_device *phydev = ptp_priv->phydev;
- struct lan8814_ptp_rx_ts *rx_ts, *tmp;
struct hwtstamp_config config;
int txcfg = 0, rxcfg = 0;
int pkt_ts_enable;
@@ -3705,24 +3745,61 @@ static int lan8841_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr)
PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_ : 0);
/* Now enable/disable the timestamping */
- lan8841_ptp_enable_int(ptp_priv,
- config.rx_filter != HWTSTAMP_FILTER_NONE);
+ lan8841_ptp_enable_processing(ptp_priv,
+ config.rx_filter != HWTSTAMP_FILTER_NONE);
- /* In case of multiple starts and stops, these needs to be cleared */
- list_for_each_entry_safe(rx_ts, tmp, &ptp_priv->rx_ts_list, list) {
- list_del(&rx_ts->list);
- kfree(rx_ts);
- }
-
- skb_queue_purge(&ptp_priv->rx_queue);
skb_queue_purge(&ptp_priv->tx_queue);
- lan8841_ptp_flush_fifo(ptp_priv, false);
- lan8841_ptp_flush_fifo(ptp_priv, true);
+ lan8841_ptp_flush_fifo(ptp_priv);
return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0;
}
+static bool lan8841_rxtstamp(struct mii_timestamper *mii_ts,
+ struct sk_buff *skb, int type)
+{
+ struct kszphy_ptp_priv *ptp_priv =
+ container_of(mii_ts, struct kszphy_ptp_priv, mii_ts);
+ struct ptp_header *header = ptp_parse_header(skb, type);
+ struct skb_shared_hwtstamps *shhwtstamps;
+ struct timespec64 ts;
+ unsigned long flags;
+ u32 ts_header;
+
+ if (!header)
+ return false;
+
+ if (ptp_priv->rx_filter == HWTSTAMP_FILTER_NONE ||
+ type == PTP_CLASS_NONE)
+ return false;
+
+ if ((type & ptp_priv->version) == 0 || (type & ptp_priv->layer) == 0)
+ return false;
+
+ spin_lock_irqsave(&ptp_priv->seconds_lock, flags);
+ ts.tv_sec = ptp_priv->seconds;
+ spin_unlock_irqrestore(&ptp_priv->seconds_lock, flags);
+ ts_header = __be32_to_cpu(header->reserved2);
+
+ shhwtstamps = skb_hwtstamps(skb);
+ memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+
+ /* Check for any wrap arounds for the second part */
+ if ((ts.tv_sec & GENMASK(1, 0)) == 0 && (ts_header >> 30) == 3)
+ ts.tv_sec -= GENMASK(1, 0) + 1;
+ else if ((ts.tv_sec & GENMASK(1, 0)) == 3 && (ts_header >> 30) == 0)
+ ts.tv_sec += 1;
+
+ shhwtstamps->hwtstamp =
+ ktime_set((ts.tv_sec & ~(GENMASK(1, 0))) | ts_header >> 30,
+ ts_header & GENMASK(29, 0));
+ header->reserved2 = 0;
+
+ netif_rx(skb);
+
+ return true;
+}
+
#define LAN8841_EVENT_A 0
#define LAN8841_EVENT_B 1
#define LAN8841_PTP_LTC_TARGET_SEC_HI(event) ((event) == LAN8841_EVENT_A ? 278 : 288)
@@ -3807,6 +3884,7 @@ static int lan8841_ptp_settime64(struct ptp_clock_info *ptp,
struct kszphy_ptp_priv *ptp_priv = container_of(ptp, struct kszphy_ptp_priv,
ptp_clock_info);
struct phy_device *phydev = ptp_priv->phydev;
+ unsigned long flags;
int ret;
/* Set the value to be stored */
@@ -3823,6 +3901,10 @@ static int lan8841_ptp_settime64(struct ptp_clock_info *ptp,
ret = lan8841_ptp_update_target(ptp_priv, ts);
mutex_unlock(&ptp_priv->ptp_lock);
+ spin_lock_irqsave(&ptp_priv->seconds_lock, flags);
+ ptp_priv->seconds = ts->tv_sec;
+ spin_unlock_irqrestore(&ptp_priv->seconds_lock, flags);
+
return ret;
}
@@ -3863,6 +3945,30 @@ static int lan8841_ptp_gettime64(struct ptp_clock_info *ptp,
return 0;
}
+static void lan8841_ptp_getseconds(struct ptp_clock_info *ptp,
+ struct timespec64 *ts)
+{
+ struct kszphy_ptp_priv *ptp_priv = container_of(ptp, struct kszphy_ptp_priv,
+ ptp_clock_info);
+ struct phy_device *phydev = ptp_priv->phydev;
+ time64_t s;
+
+ mutex_lock(&ptp_priv->ptp_lock);
+ /* Issue the command to read the LTC */
+ phy_write_mmd(phydev, 2, LAN8841_PTP_CMD_CTL,
+ LAN8841_PTP_CMD_CTL_PTP_LTC_READ);
+
+ /* Read the LTC */
+ s = phy_read_mmd(phydev, 2, LAN8841_PTP_LTC_RD_SEC_HI);
+ s <<= 16;
+ s |= phy_read_mmd(phydev, 2, LAN8841_PTP_LTC_RD_SEC_MID);
+ s <<= 16;
+ s |= phy_read_mmd(phydev, 2, LAN8841_PTP_LTC_RD_SEC_LO);
+ mutex_unlock(&ptp_priv->ptp_lock);
+
+ set_normalized_timespec64(ts, s, 0);
+}
+
#define LAN8841_PTP_LTC_STEP_ADJ_LO 276
#define LAN8841_PTP_LTC_STEP_ADJ_HI 275
#define LAN8841_PTP_LTC_STEP_ADJ_DIR BIT(15)
@@ -4365,6 +4471,22 @@ static int lan8841_ptp_enable(struct ptp_clock_info *ptp,
return 0;
}
+static long lan8841_ptp_do_aux_work(struct ptp_clock_info *ptp)
+{
+ struct kszphy_ptp_priv *ptp_priv = container_of(ptp, struct kszphy_ptp_priv,
+ ptp_clock_info);
+ struct timespec64 ts;
+ unsigned long flags;
+
+ lan8841_ptp_getseconds(&ptp_priv->ptp_clock_info, &ts);
+
+ spin_lock_irqsave(&ptp_priv->seconds_lock, flags);
+ ptp_priv->seconds = ts.tv_sec;
+ spin_unlock_irqrestore(&ptp_priv->seconds_lock, flags);
+
+ return nsecs_to_jiffies(LAN8841_GET_SEC_LTC_DELAY);
+}
+
static struct ptp_clock_info lan8841_ptp_clock_info = {
.owner = THIS_MODULE,
.name = "lan8841 ptp",
@@ -4375,6 +4497,7 @@ static struct ptp_clock_info lan8841_ptp_clock_info = {
.adjfine = lan8841_ptp_adjfine,
.verify = lan8841_ptp_verify,
.enable = lan8841_ptp_enable,
+ .do_aux_work = lan8841_ptp_do_aux_work,
.n_per_out = LAN8841_PTP_GPIO_NUM,
.n_ext_ts = LAN8841_PTP_GPIO_NUM,
.n_pins = LAN8841_PTP_GPIO_NUM,
@@ -4435,13 +4558,11 @@ static int lan8841_probe(struct phy_device *phydev)
/* Initialize the SW */
skb_queue_head_init(&ptp_priv->tx_queue);
- skb_queue_head_init(&ptp_priv->rx_queue);
- INIT_LIST_HEAD(&ptp_priv->rx_ts_list);
- spin_lock_init(&ptp_priv->rx_ts_lock);
ptp_priv->phydev = phydev;
mutex_init(&ptp_priv->ptp_lock);
+ spin_lock_init(&ptp_priv->seconds_lock);
- ptp_priv->mii_ts.rxtstamp = lan8814_rxtstamp;
+ ptp_priv->mii_ts.rxtstamp = lan8841_rxtstamp;
ptp_priv->mii_ts.txtstamp = lan8814_txtstamp;
ptp_priv->mii_ts.hwtstamp = lan8841_hwtstamp;
ptp_priv->mii_ts.ts_info = lan8841_ts_info;
@@ -4451,6 +4572,16 @@ static int lan8841_probe(struct phy_device *phydev)
return 0;
}
+static int lan8841_suspend(struct phy_device *phydev)
+{
+ struct kszphy_priv *priv = phydev->priv;
+ struct kszphy_ptp_priv *ptp_priv = &priv->ptp_priv;
+
+ ptp_cancel_worker_sync(ptp_priv->ptp_clock);
+
+ return genphy_suspend(phydev);
+}
+
static struct phy_driver ksphy_driver[] = {
{
.phy_id = PHY_ID_KS8737,
@@ -4674,7 +4805,7 @@ static struct phy_driver ksphy_driver[] = {
.get_sset_count = kszphy_get_sset_count,
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
- .suspend = genphy_suspend,
+ .suspend = lan8841_suspend,
.resume = genphy_resume,
.cable_test_start = lan8814_cable_test_start,
.cable_test_get_status = ksz886x_cable_test_get_status,
@@ -4735,7 +4866,7 @@ static struct phy_driver ksphy_driver[] = {
.phy_id_mask = MICREL_PHY_ID_MASK,
.name = "Microchip KSZ9477",
/* PHY_GBIT_FEATURES */
- .config_init = kszphy_config_init,
+ .config_init = ksz9477_config_init,
.config_intr = kszphy_config_intr,
.handle_interrupt = kszphy_handle_interrupt,
.suspend = genphy_suspend,
diff --git a/drivers/net/phy/microchip_t1s.c b/drivers/net/phy/microchip_t1s.c
index 094967b3c111..534ca7d1b061 100644
--- a/drivers/net/phy/microchip_t1s.c
+++ b/drivers/net/phy/microchip_t1s.c
@@ -1,19 +1,29 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Driver for Microchip 10BASE-T1S LAN867X PHY
+ * Driver for Microchip 10BASE-T1S PHYs
*
* Support: Microchip Phys:
- * lan8670, lan8671, lan8672
+ * lan8670/1/2 Rev.B1
+ * lan8650/1 Rev.B0 Internal PHYs
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/phy.h>
-#define PHY_ID_LAN867X 0x0007C160
+#define PHY_ID_LAN867X_REVB1 0x0007C162
+#define PHY_ID_LAN865X_REVB0 0x0007C1B3
-#define LAN867X_REG_IRQ_1_CTL 0x001C
-#define LAN867X_REG_IRQ_2_CTL 0x001D
+#define LAN867X_REG_STS2 0x0019
+
+#define LAN867x_RESET_COMPLETE_STS BIT(11)
+
+#define LAN865X_REG_CFGPARAM_ADDR 0x00D8
+#define LAN865X_REG_CFGPARAM_DATA 0x00D9
+#define LAN865X_REG_CFGPARAM_CTRL 0x00DA
+#define LAN865X_REG_STS2 0x0019
+
+#define LAN865X_CFGPARAM_READ_ENABLE BIT(1)
/* The arrays below are pulled from the following table from AN1699
* Access MMD Address Value Mask
@@ -31,72 +41,219 @@
* W 0x1F 0x0099 0x7F80 ------
*/
-static const int lan867x_fixup_registers[12] = {
+static const u32 lan867x_revb1_fixup_registers[12] = {
0x00D0, 0x00D1, 0x0084, 0x0085,
0x008A, 0x0087, 0x0088, 0x008B,
0x0080, 0x00F1, 0x0096, 0x0099,
};
-static const int lan867x_fixup_values[12] = {
+static const u16 lan867x_revb1_fixup_values[12] = {
0x0002, 0x0000, 0x3380, 0x0006,
0xC000, 0x801C, 0x033F, 0x0404,
0x0600, 0x2400, 0x2000, 0x7F80,
};
-static const int lan867x_fixup_masks[12] = {
+static const u16 lan867x_revb1_fixup_masks[12] = {
0x0E03, 0x0300, 0xFFC0, 0x000F,
0xF800, 0x801C, 0x1FFF, 0xFFFF,
0x0600, 0x7F00, 0x2000, 0xFFFF,
};
-static int lan867x_config_init(struct phy_device *phydev)
+/* LAN865x Rev.B0 configuration parameters from AN1760 */
+static const u32 lan865x_revb0_fixup_registers[28] = {
+ 0x0091, 0x0081, 0x0043, 0x0044,
+ 0x0045, 0x0053, 0x0054, 0x0055,
+ 0x0040, 0x0050, 0x00D0, 0x00E9,
+ 0x00F5, 0x00F4, 0x00F8, 0x00F9,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3,
+ 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00BA, 0x00BB,
+};
+
+static const u16 lan865x_revb0_fixup_values[28] = {
+ 0x9660, 0x00C0, 0x00FF, 0xFFFF,
+ 0x0000, 0x00FF, 0xFFFF, 0x0000,
+ 0x0002, 0x0002, 0x5F21, 0x9E50,
+ 0x1CF8, 0xC020, 0x9B00, 0x4E53,
+ 0x0103, 0x0910, 0x1D26, 0x002A,
+ 0x0103, 0x070D, 0x1720, 0x0027,
+ 0x0509, 0x0E13, 0x1C25, 0x002B,
+};
+
+static const u16 lan865x_revb0_fixup_cfg_regs[5] = {
+ 0x0084, 0x008A, 0x00AD, 0x00AE, 0x00AF
+};
+
+/* Pulled from AN1760 describing 'indirect read'
+ *
+ * write_register(0x4, 0x00D8, addr)
+ * write_register(0x4, 0x00DA, 0x2)
+ * return (int8)(read_register(0x4, 0x00D9))
+ *
+ * 0x4 refers to memory map selector 4, which maps to MDIO_MMD_VEND2
+ */
+static int lan865x_revb0_indirect_read(struct phy_device *phydev, u16 addr)
+{
+ int ret;
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_ADDR,
+ addr);
+ if (ret)
+ return ret;
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_CTRL,
+ LAN865X_CFGPARAM_READ_ENABLE);
+ if (ret)
+ return ret;
+
+ return phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_DATA);
+}
+
+/* This is pulled straight from AN1760 from 'calculation of offset 1' &
+ * 'calculation of offset 2'
+ */
+static int lan865x_generate_cfg_offsets(struct phy_device *phydev, s8 offsets[2])
+{
+ const u16 fixup_regs[2] = {0x0004, 0x0008};
+ int ret;
+
+ for (int i = 0; i < ARRAY_SIZE(fixup_regs); i++) {
+ ret = lan865x_revb0_indirect_read(phydev, fixup_regs[i]);
+ if (ret < 0)
+ return ret;
+ if (ret & BIT(4))
+ offsets[i] = ret | 0xE0;
+ else
+ offsets[i] = ret;
+ }
+
+ return 0;
+}
+
+static int lan865x_read_cfg_params(struct phy_device *phydev, u16 cfg_params[])
+{
+ int ret;
+
+ for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs); i++) {
+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND2,
+ lan865x_revb0_fixup_cfg_regs[i]);
+ if (ret < 0)
+ return ret;
+ cfg_params[i] = (u16)ret;
+ }
+
+ return 0;
+}
+
+static int lan865x_write_cfg_params(struct phy_device *phydev, u16 cfg_params[])
{
- /* HW quirk: Microchip states in the application note (AN1699) for the phy
- * that a set of read-modify-write (rmw) operations has to be performed
- * on a set of seemingly magic registers.
- * The result of these operations is just described as 'optimal performance'
- * Microchip gives no explanation as to what these mmd regs do,
- * in fact they are marked as reserved in the datasheet.
- * It is unclear if phy_modify_mmd would be safe to use or if a write
- * really has to happen to each register.
- * In order to exactly conform to what is stated in the AN phy_write_mmd is
- * used, which might then write the same value back as read + modified.
+ int ret;
+
+ for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs); i++) {
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
+ lan865x_revb0_fixup_cfg_regs[i],
+ cfg_params[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int lan865x_setup_cfgparam(struct phy_device *phydev)
+{
+ u16 cfg_params[ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs)];
+ u16 cfg_results[5];
+ s8 offsets[2];
+ int ret;
+
+ ret = lan865x_generate_cfg_offsets(phydev, offsets);
+ if (ret)
+ return ret;
+
+ ret = lan865x_read_cfg_params(phydev, cfg_params);
+ if (ret)
+ return ret;
+
+ cfg_results[0] = (cfg_params[0] & 0x000F) |
+ FIELD_PREP(GENMASK(15, 10), 9 + offsets[0]) |
+ FIELD_PREP(GENMASK(15, 4), 14 + offsets[0]);
+ cfg_results[1] = (cfg_params[1] & 0x03FF) |
+ FIELD_PREP(GENMASK(15, 10), 40 + offsets[1]);
+ cfg_results[2] = (cfg_params[2] & 0xC0C0) |
+ FIELD_PREP(GENMASK(15, 8), 5 + offsets[0]) |
+ (9 + offsets[0]);
+ cfg_results[3] = (cfg_params[3] & 0xC0C0) |
+ FIELD_PREP(GENMASK(15, 8), 9 + offsets[0]) |
+ (14 + offsets[0]);
+ cfg_results[4] = (cfg_params[4] & 0xC0C0) |
+ FIELD_PREP(GENMASK(15, 8), 17 + offsets[0]) |
+ (22 + offsets[0]);
+
+ return lan865x_write_cfg_params(phydev, cfg_results);
+}
+
+static int lan865x_revb0_config_init(struct phy_device *phydev)
+{
+ int ret;
+
+ /* Reference to AN1760
+ * https://ww1.microchip.com/downloads/aemDocuments/documents/AIS/ProductDocuments/SupportingCollateral/AN-LAN8650-1-Configuration-60001760.pdf
+ */
+ for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_registers); i++) {
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
+ lan865x_revb0_fixup_registers[i],
+ lan865x_revb0_fixup_values[i]);
+ if (ret)
+ return ret;
+ }
+ /* Function to calculate and write the configuration parameters in the
+ * 0x0084, 0x008A, 0x00AD, 0x00AE and 0x00AF registers (from AN1760)
*/
+ return lan865x_setup_cfgparam(phydev);
+}
- int reg_value;
+static int lan867x_revb1_config_init(struct phy_device *phydev)
+{
int err;
- int reg;
- /* Read-Modified Write Pseudocode (from AN1699)
- * current_val = read_register(mmd, addr) // Read current register value
- * new_val = current_val AND (NOT mask) // Clear bit fields to be written
- * new_val = new_val OR value // Set bits
- * write_register(mmd, addr, new_val) // Write back updated register value
+ /* The chip completes a reset in 3us, we might get here earlier than
+ * that, as an added margin we'll conditionally sleep 5us.
*/
- for (int i = 0; i < ARRAY_SIZE(lan867x_fixup_registers); i++) {
- reg = lan867x_fixup_registers[i];
- reg_value = phy_read_mmd(phydev, MDIO_MMD_VEND2, reg);
- reg_value &= ~lan867x_fixup_masks[i];
- reg_value |= lan867x_fixup_values[i];
- err = phy_write_mmd(phydev, MDIO_MMD_VEND2, reg, reg_value);
- if (err != 0)
+ err = phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_STS2);
+ if (err < 0)
+ return err;
+
+ if (!(err & LAN867x_RESET_COMPLETE_STS)) {
+ udelay(5);
+ err = phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_STS2);
+ if (err < 0)
return err;
+ if (!(err & LAN867x_RESET_COMPLETE_STS)) {
+ phydev_err(phydev, "PHY reset failed\n");
+ return -ENODEV;
+ }
}
- /* None of the interrupts in the lan867x phy seem relevant.
- * Other phys inspect the link status and call phy_trigger_machine
- * in the interrupt handler.
- * This phy does not support link status, and thus has no interrupt
- * for it either.
- * So we'll just disable all interrupts on the chip.
+ /* Reference to AN1699
+ * https://ww1.microchip.com/downloads/aemDocuments/documents/AIS/ProductDocuments/SupportingCollateral/AN-LAN8670-1-2-config-60001699.pdf
+ * AN1699 says Read, Modify, Write, but the Write is not required if the
+ * register already has the required value. So it is safe to use
+ * phy_modify_mmd here.
*/
- err = phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_IRQ_1_CTL, 0xFFFF);
- if (err != 0)
- return err;
- return phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_IRQ_2_CTL, 0xFFFF);
+ for (int i = 0; i < ARRAY_SIZE(lan867x_revb1_fixup_registers); i++) {
+ err = phy_modify_mmd(phydev, MDIO_MMD_VEND2,
+ lan867x_revb1_fixup_registers[i],
+ lan867x_revb1_fixup_masks[i],
+ lan867x_revb1_fixup_values[i]);
+ if (err)
+ return err;
+ }
+
+ return 0;
}
-static int lan867x_read_status(struct phy_device *phydev)
+static int lan86xx_read_status(struct phy_device *phydev)
{
/* The phy has some limitations, namely:
* - always reports link up
@@ -111,28 +268,39 @@ static int lan867x_read_status(struct phy_device *phydev)
return 0;
}
-static struct phy_driver lan867x_driver[] = {
+static struct phy_driver microchip_t1s_driver[] = {
{
- PHY_ID_MATCH_MODEL(PHY_ID_LAN867X),
- .name = "LAN867X",
+ PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVB1),
+ .name = "LAN867X Rev.B1",
.features = PHY_BASIC_T1S_P2MP_FEATURES,
- .config_init = lan867x_config_init,
- .read_status = lan867x_read_status,
+ .config_init = lan867x_revb1_config_init,
+ .read_status = lan86xx_read_status,
.get_plca_cfg = genphy_c45_plca_get_cfg,
.set_plca_cfg = genphy_c45_plca_set_cfg,
.get_plca_status = genphy_c45_plca_get_status,
- }
+ },
+ {
+ PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB0),
+ .name = "LAN865X Rev.B0 Internal Phy",
+ .features = PHY_BASIC_T1S_P2MP_FEATURES,
+ .config_init = lan865x_revb0_config_init,
+ .read_status = lan86xx_read_status,
+ .get_plca_cfg = genphy_c45_plca_get_cfg,
+ .set_plca_cfg = genphy_c45_plca_set_cfg,
+ .get_plca_status = genphy_c45_plca_get_status,
+ },
};
-module_phy_driver(lan867x_driver);
+module_phy_driver(microchip_t1s_driver);
static struct mdio_device_id __maybe_unused tbl[] = {
- { PHY_ID_MATCH_MODEL(PHY_ID_LAN867X) },
+ { PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVB1) },
+ { PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB0) },
{ }
};
MODULE_DEVICE_TABLE(mdio, tbl);
-MODULE_DESCRIPTION("Microchip 10BASE-T1S lan867x Phy driver");
+MODULE_DESCRIPTION("Microchip 10BASE-T1S PHYs driver");
MODULE_AUTHOR("Ramón Nordin Rodriguez");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h
index defe5cc6d4fc..7a962050a4d4 100644
--- a/drivers/net/phy/mscc/mscc.h
+++ b/drivers/net/phy/mscc/mscc.h
@@ -292,6 +292,7 @@ enum rgmii_clock_delay {
#define PHY_ID_VSC8575 0x000707d0
#define PHY_ID_VSC8582 0x000707b0
#define PHY_ID_VSC8584 0x000707c0
+#define PHY_VENDOR_MSCC 0x00070400
#define MSCC_VDDMAC_1500 1500
#define MSCC_VDDMAC_1800 1800
diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c
index 28df8a2e4230..4171f01d34e5 100644
--- a/drivers/net/phy/mscc/mscc_main.c
+++ b/drivers/net/phy/mscc/mscc_main.c
@@ -107,6 +107,9 @@ static const struct vsc8531_edge_rate_table edge_table[] = {
};
#endif
+static const int vsc85xx_internal_delay[] = {200, 800, 1100, 1700, 2000, 2300,
+ 2600, 3400};
+
static int vsc85xx_phy_read_page(struct phy_device *phydev)
{
return __phy_read(phydev, MSCC_EXT_PAGE_ACCESS);
@@ -525,8 +528,12 @@ static int vsc85xx_update_rgmii_cntl(struct phy_device *phydev, u32 rgmii_cntl,
{
u16 rgmii_rx_delay_pos = ffs(rgmii_rx_delay_mask) - 1;
u16 rgmii_tx_delay_pos = ffs(rgmii_tx_delay_mask) - 1;
+ int delay_size = ARRAY_SIZE(vsc85xx_internal_delay);
+ struct device *dev = &phydev->mdio.dev;
u16 reg_val = 0;
u16 mask = 0;
+ s32 rx_delay;
+ s32 tx_delay;
int rc = 0;
/* For traffic to pass, the VSC8502 family needs the RX_CLK disable bit
@@ -541,12 +548,28 @@ static int vsc85xx_update_rgmii_cntl(struct phy_device *phydev, u32 rgmii_cntl,
if (phy_interface_is_rgmii(phydev))
mask |= rgmii_rx_delay_mask | rgmii_tx_delay_mask;
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
- phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
- reg_val |= RGMII_CLK_DELAY_2_0_NS << rgmii_rx_delay_pos;
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
- phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
- reg_val |= RGMII_CLK_DELAY_2_0_NS << rgmii_tx_delay_pos;
+ rx_delay = phy_get_internal_delay(phydev, dev, vsc85xx_internal_delay,
+ delay_size, true);
+ if (rx_delay < 0) {
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+ rx_delay = RGMII_CLK_DELAY_2_0_NS;
+ else
+ rx_delay = RGMII_CLK_DELAY_0_2_NS;
+ }
+
+ tx_delay = phy_get_internal_delay(phydev, dev, vsc85xx_internal_delay,
+ delay_size, false);
+ if (tx_delay < 0) {
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+ tx_delay = RGMII_CLK_DELAY_2_0_NS;
+ else
+ tx_delay = RGMII_CLK_DELAY_0_2_NS;
+ }
+
+ reg_val |= rx_delay << rgmii_rx_delay_pos;
+ reg_val |= tx_delay << rgmii_tx_delay_pos;
if (mask)
rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
@@ -2678,21 +2701,7 @@ static struct phy_driver vsc85xx_driver[] = {
module_phy_driver(vsc85xx_driver);
static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = {
- { PHY_ID_VSC8501, 0xfffffff0, },
- { PHY_ID_VSC8502, 0xfffffff0, },
- { PHY_ID_VSC8504, 0xfffffff0, },
- { PHY_ID_VSC8514, 0xfffffff0, },
- { PHY_ID_VSC8530, 0xfffffff0, },
- { PHY_ID_VSC8531, 0xfffffff0, },
- { PHY_ID_VSC8540, 0xfffffff0, },
- { PHY_ID_VSC8541, 0xfffffff0, },
- { PHY_ID_VSC8552, 0xfffffff0, },
- { PHY_ID_VSC856X, 0xfffffff0, },
- { PHY_ID_VSC8572, 0xfffffff0, },
- { PHY_ID_VSC8574, 0xfffffff0, },
- { PHY_ID_VSC8575, 0xfffffff0, },
- { PHY_ID_VSC8582, 0xfffffff0, },
- { PHY_ID_VSC8584, 0xfffffff0, },
+ { PHY_ID_MATCH_VENDOR(PHY_VENDOR_MSCC) },
{ }
};
diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index fee514b96ab1..93ed07223377 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -1425,12 +1425,15 @@ int genphy_c45_ethtool_get_eee(struct phy_device *phydev,
EXPORT_SYMBOL(genphy_c45_ethtool_get_eee);
/**
- * genphy_c45_ethtool_set_eee - get EEE supported and status
+ * genphy_c45_ethtool_set_eee - set EEE supported and status
* @phydev: target phy_device struct
* @data: ethtool_eee data
*
- * Description: it reportes the Supported/Advertisement/LP Advertisement
- * capabilities.
+ * Description: sets the Supported/Advertisement/LP Advertisement
+ * capabilities. If eee_enabled is false, no links modes are
+ * advertised, but the previously advertised link modes are
+ * retained. This allows EEE to be enabled/disabled in a
+ * non-destructive way.
*/
int genphy_c45_ethtool_set_eee(struct phy_device *phydev,
struct ethtool_eee *data)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 0c0df38cd1ab..a9ecfdd19624 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -52,6 +52,7 @@ static const char *phy_state_to_str(enum phy_state st)
PHY_STATE_STR(NOLINK)
PHY_STATE_STR(CABLETEST)
PHY_STATE_STR(HALTED)
+ PHY_STATE_STR(ERROR)
}
return NULL;
@@ -1183,9 +1184,11 @@ void phy_stop_machine(struct phy_device *phydev)
static void phy_process_error(struct phy_device *phydev)
{
- mutex_lock(&phydev->lock);
- phydev->state = PHY_HALTED;
- mutex_unlock(&phydev->lock);
+ /* phydev->lock must be held for the state change to be safe */
+ if (!mutex_is_locked(&phydev->lock))
+ phydev_err(phydev, "PHY-device data unsafe context\n");
+
+ phydev->state = PHY_ERROR;
phy_trigger_machine(phydev);
}
@@ -1194,17 +1197,18 @@ static void phy_error_precise(struct phy_device *phydev,
const void *func, int err)
{
WARN(1, "%pS: returned: %d\n", func, err);
+ mutex_lock(&phydev->lock);
phy_process_error(phydev);
+ mutex_unlock(&phydev->lock);
}
/**
- * phy_error - enter HALTED state for this PHY device
+ * phy_error - enter ERROR state for this PHY device
* @phydev: target phy_device struct
*
- * Moves the PHY to the HALTED state in response to a read
+ * Moves the PHY to the ERROR state in response to a read
* or write error, and tells the controller the link is down.
- * Must not be called from interrupt context, or while the
- * phydev->lock is held.
+ * Must be called with phydev->lock held.
*/
void phy_error(struct phy_device *phydev)
{
@@ -1326,7 +1330,8 @@ void phy_stop(struct phy_device *phydev)
struct net_device *dev = phydev->attached_dev;
enum phy_state old_state;
- if (!phy_is_started(phydev) && phydev->state != PHY_DOWN) {
+ if (!phy_is_started(phydev) && phydev->state != PHY_DOWN &&
+ phydev->state != PHY_ERROR) {
WARN(1, "called from state %s\n",
phy_state_to_str(phydev->state));
return;
@@ -1443,6 +1448,7 @@ void phy_state_machine(struct work_struct *work)
}
break;
case PHY_HALTED:
+ case PHY_ERROR:
if (phydev->link) {
phydev->link = 0;
phy_link_down(phydev);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 53598210be6c..c7cf61fe41cf 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -454,8 +454,7 @@ int phy_unregister_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask)
fixup = list_entry(pos, struct phy_fixup, list);
if ((!strcmp(fixup->bus_id, bus_id)) &&
- ((fixup->phy_uid & phy_uid_mask) ==
- (phy_uid & phy_uid_mask))) {
+ phy_id_compare(fixup->phy_uid, phy_uid, phy_uid_mask)) {
list_del(&fixup->list);
kfree(fixup);
ret = 0;
@@ -491,8 +490,8 @@ static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup)
if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0)
return 0;
- if ((fixup->phy_uid & fixup->phy_uid_mask) !=
- (phydev->phy_id & fixup->phy_uid_mask))
+ if (!phy_id_compare(phydev->phy_id, fixup->phy_uid,
+ fixup->phy_uid_mask))
if (fixup->phy_uid != PHY_ANY_UID)
return 0;
@@ -539,15 +538,14 @@ static int phy_bus_match(struct device *dev, struct device_driver *drv)
if (phydev->c45_ids.device_ids[i] == 0xffffffff)
continue;
- if ((phydrv->phy_id & phydrv->phy_id_mask) ==
- (phydev->c45_ids.device_ids[i] &
- phydrv->phy_id_mask))
+ if (phy_id_compare(phydev->c45_ids.device_ids[i],
+ phydrv->phy_id, phydrv->phy_id_mask))
return 1;
}
return 0;
} else {
- return (phydrv->phy_id & phydrv->phy_id_mask) ==
- (phydev->phy_id & phydrv->phy_id_mask);
+ return phy_id_compare(phydev->phy_id, phydrv->phy_id,
+ phydrv->phy_id_mask);
}
}
@@ -1860,9 +1858,10 @@ int phy_suspend(struct phy_device *phydev)
if (phydev->suspended)
return 0;
- /* If the device has WOL enabled, we cannot suspend the PHY */
phy_ethtool_get_wol(phydev, &wol);
- if (wol.wolopts || (netdev && netdev->wol_enabled))
+ phydev->wol_enabled = wol.wolopts || (netdev && netdev->wol_enabled);
+ /* If the device has WOL enabled, we cannot suspend the PHY */
+ if (phydev->wol_enabled && !(phydrv->flags & PHY_ALWAYS_CALL_SUSPEND))
return -EBUSY;
if (!phydrv || !phydrv->suspend)
@@ -3217,6 +3216,8 @@ static int phy_probe(struct device *dev)
goto out;
}
+ phy_disable_interrupts(phydev);
+
/* Start out supporting everything. Eventually,
* a controller will attach, and may modify one
* or both of these values
@@ -3334,16 +3335,6 @@ static int phy_remove(struct device *dev)
return 0;
}
-static void phy_shutdown(struct device *dev)
-{
- struct phy_device *phydev = to_phy_device(dev);
-
- if (phydev->state == PHY_READY || !phydev->attached_dev)
- return;
-
- phy_disable_interrupts(phydev);
-}
-
/**
* phy_driver_register - register a phy_driver with the PHY layer
* @new_driver: new phy_driver to register
@@ -3377,7 +3368,6 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner)
new_driver->mdiodrv.driver.bus = &mdio_bus_type;
new_driver->mdiodrv.driver.probe = phy_probe;
new_driver->mdiodrv.driver.remove = phy_remove;
- new_driver->mdiodrv.driver.shutdown = phy_shutdown;
new_driver->mdiodrv.driver.owner = owner;
new_driver->mdiodrv.driver.probe_type = PROBE_FORCE_SYNCHRONOUS;
@@ -3452,23 +3442,30 @@ static int __init phy_init(void)
{
int rc;
+ ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops);
+
rc = mdio_bus_init();
if (rc)
- return rc;
+ goto err_ethtool_phy_ops;
- ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops);
features_init();
rc = phy_driver_register(&genphy_c45_driver, THIS_MODULE);
if (rc)
- goto err_c45;
+ goto err_mdio_bus;
rc = phy_driver_register(&genphy_driver, THIS_MODULE);
- if (rc) {
- phy_driver_unregister(&genphy_c45_driver);
+ if (rc)
+ goto err_c45;
+
+ return 0;
+
err_c45:
- mdio_bus_exit();
- }
+ phy_driver_unregister(&genphy_c45_driver);
+err_mdio_bus:
+ mdio_bus_exit();
+err_ethtool_phy_ops:
+ ethtool_set_ethtool_phy_ops(NULL);
return rc;
}
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 5efdeb59f4b2..d0aaa5cad853 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -71,6 +71,7 @@ struct phylink {
struct mutex state_mutex;
struct phylink_link_state phy_state;
struct work_struct resolve;
+ unsigned int pcs_neg_mode;
bool mac_link_dropped;
bool using_mac_select_pcs;
@@ -156,6 +157,23 @@ static const char *phylink_an_mode_str(unsigned int mode)
return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown";
}
+static unsigned int phylink_interface_signal_rate(phy_interface_t interface)
+{
+ switch (interface) {
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_1000BASEX: /* 1.25Mbd */
+ return 1250;
+ case PHY_INTERFACE_MODE_2500BASEX: /* 3.125Mbd */
+ return 3125;
+ case PHY_INTERFACE_MODE_5GBASER: /* 5.15625Mbd */
+ return 5156;
+ case PHY_INTERFACE_MODE_10GBASER: /* 10.3125Mbd */
+ return 10313;
+ default:
+ return 0;
+ }
+}
+
/**
* phylink_interface_max_speed() - get the maximum speed of a phy interface
* @interface: phy interface mode defined by &typedef phy_interface_t
@@ -695,20 +713,17 @@ static int phylink_validate(struct phylink *pl, unsigned long *supported,
{
const unsigned long *interfaces = pl->config->supported_interfaces;
- if (!phy_interface_empty(interfaces)) {
- if (state->interface == PHY_INTERFACE_MODE_NA)
- return phylink_validate_mask(pl, supported, state,
- interfaces);
+ if (state->interface == PHY_INTERFACE_MODE_NA)
+ return phylink_validate_mask(pl, supported, state, interfaces);
- if (!test_bit(state->interface, interfaces))
- return -EINVAL;
- }
+ if (!test_bit(state->interface, interfaces))
+ return -EINVAL;
return phylink_validate_mac_and_pcs(pl, supported, state);
}
static int phylink_parse_fixedlink(struct phylink *pl,
- struct fwnode_handle *fwnode)
+ const struct fwnode_handle *fwnode)
{
struct fwnode_handle *fixed_node;
bool pause, asym_pause, autoneg;
@@ -819,7 +834,8 @@ static int phylink_parse_fixedlink(struct phylink *pl,
return 0;
}
-static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode)
+static int phylink_parse_mode(struct phylink *pl,
+ const struct fwnode_handle *fwnode)
{
struct fwnode_handle *dn;
const char *managed;
@@ -962,11 +978,10 @@ static void phylink_apply_manual_flow(struct phylink *pl,
state->pause = pl->link_config.pause;
}
-static void phylink_resolve_flow(struct phylink_link_state *state)
+static void phylink_resolve_an_pause(struct phylink_link_state *state)
{
bool tx_pause, rx_pause;
- state->pause = MLO_PAUSE_NONE;
if (state->duplex == DUPLEX_FULL) {
linkmode_resolve_pause(state->advertising,
state->lp_advertising,
@@ -978,6 +993,25 @@ static void phylink_resolve_flow(struct phylink_link_state *state)
}
}
+static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
+ const struct phylink_link_state *state,
+ bool permit_pause_to_mac)
+{
+ if (!pcs)
+ return 0;
+
+ return pcs->ops->pcs_config(pcs, neg_mode, state->interface,
+ state->advertising, permit_pause_to_mac);
+}
+
+static void phylink_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
+ phy_interface_t interface, int speed,
+ int duplex)
+{
+ if (pcs && pcs->ops->pcs_link_up)
+ pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex);
+}
+
static void phylink_pcs_poll_stop(struct phylink *pl)
{
if (pl->cfg_link_an_mode == MLO_AN_INBAND)
@@ -1024,10 +1058,16 @@ static void phylink_major_config(struct phylink *pl, bool restart,
{
struct phylink_pcs *pcs = NULL;
bool pcs_changed = false;
+ unsigned int rate_kbd;
+ unsigned int neg_mode;
int err;
phylink_dbg(pl, "major config %s\n", phy_modes(state->interface));
+ pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode,
+ state->interface,
+ state->advertising);
+
if (pl->using_mac_select_pcs) {
pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface);
if (IS_ERR(pcs)) {
@@ -1060,18 +1100,18 @@ static void phylink_major_config(struct phylink *pl, bool restart,
phylink_mac_config(pl, state);
- if (pl->pcs) {
- err = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode,
- state->interface,
- state->advertising,
- !!(pl->link_config.pause &
- MLO_PAUSE_AN));
- if (err < 0)
- phylink_err(pl, "pcs_config failed: %pe\n",
- ERR_PTR(err));
- if (err > 0)
- restart = true;
- }
+ neg_mode = pl->cur_link_an_mode;
+ if (pl->pcs && pl->pcs->neg_mode)
+ neg_mode = pl->pcs_neg_mode;
+
+ err = phylink_pcs_config(pl->pcs, neg_mode, state,
+ !!(pl->link_config.pause & MLO_PAUSE_AN));
+ if (err < 0)
+ phylink_err(pl, "pcs_config failed: %pe\n",
+ ERR_PTR(err));
+ else if (err > 0)
+ restart = true;
+
if (restart)
phylink_mac_pcs_an_restart(pl);
@@ -1083,6 +1123,12 @@ static void phylink_major_config(struct phylink *pl, bool restart,
ERR_PTR(err));
}
+ if (pl->sfp_bus) {
+ rate_kbd = phylink_interface_signal_rate(state->interface);
+ if (rate_kbd)
+ sfp_upstream_set_signal_rate(pl->sfp_bus, rate_kbd);
+ }
+
phylink_pcs_poll_start(pl);
}
@@ -1094,6 +1140,7 @@ static void phylink_major_config(struct phylink *pl, bool restart,
*/
static int phylink_change_inband_advert(struct phylink *pl)
{
+ unsigned int neg_mode;
int ret;
if (test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state))
@@ -1112,15 +1159,21 @@ static int phylink_change_inband_advert(struct phylink *pl)
__ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising,
pl->link_config.pause);
+ /* Recompute the PCS neg mode */
+ pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode,
+ pl->link_config.interface,
+ pl->link_config.advertising);
+
+ neg_mode = pl->cur_link_an_mode;
+ if (pl->pcs->neg_mode)
+ neg_mode = pl->pcs_neg_mode;
+
/* Modern PCS-based method; update the advert at the PCS, and
* restart negotiation if the pcs_config() helper indicates that
* the programmed advertisement has changed.
*/
- ret = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode,
- pl->link_config.interface,
- pl->link_config.advertising,
- !!(pl->link_config.pause &
- MLO_PAUSE_AN));
+ ret = phylink_pcs_config(pl->pcs, neg_mode, &pl->link_config,
+ !!(pl->link_config.pause & MLO_PAUSE_AN));
if (ret < 0)
return ret;
@@ -1171,7 +1224,8 @@ static void phylink_get_fixed_state(struct phylink *pl,
else if (pl->link_gpio)
state->link = !!gpiod_get_value_cansleep(pl->link_gpio);
- phylink_resolve_flow(state);
+ state->pause = MLO_PAUSE_NONE;
+ phylink_resolve_an_pause(state);
}
static void phylink_mac_initial_config(struct phylink *pl, bool force_restart)
@@ -1221,6 +1275,7 @@ static void phylink_link_up(struct phylink *pl,
struct phylink_link_state link_state)
{
struct net_device *ndev = pl->netdev;
+ unsigned int neg_mode;
int speed, duplex;
bool rx_pause;
@@ -1251,9 +1306,12 @@ static void phylink_link_up(struct phylink *pl,
pl->cur_interface = link_state.interface;
- if (pl->pcs && pl->pcs->ops->pcs_link_up)
- pl->pcs->ops->pcs_link_up(pl->pcs, pl->cur_link_an_mode,
- pl->cur_interface, speed, duplex);
+ neg_mode = pl->cur_link_an_mode;
+ if (pl->pcs && pl->pcs->neg_mode)
+ neg_mode = pl->pcs_neg_mode;
+
+ phylink_pcs_link_up(pl->pcs, neg_mode, pl->cur_interface, speed,
+ duplex);
pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode,
pl->cur_interface, speed, duplex,
@@ -1441,7 +1499,7 @@ static void phylink_fixed_poll(struct timer_list *t)
static const struct sfp_upstream_ops sfp_phylink_ops;
static int phylink_register_sfp(struct phylink *pl,
- struct fwnode_handle *fwnode)
+ const struct fwnode_handle *fwnode)
{
struct sfp_bus *bus;
int ret;
@@ -1480,7 +1538,7 @@ static int phylink_register_sfp(struct phylink *pl,
* must use IS_ERR() to check for errors from this function.
*/
struct phylink *phylink_create(struct phylink_config *config,
- struct fwnode_handle *fwnode,
+ const struct fwnode_handle *fwnode,
phy_interface_t iface,
const struct phylink_mac_ops *mac_ops)
{
@@ -1488,19 +1546,18 @@ struct phylink *phylink_create(struct phylink_config *config,
struct phylink *pl;
int ret;
- if (mac_ops->mac_select_pcs &&
- mac_ops->mac_select_pcs(config, PHY_INTERFACE_MODE_NA) !=
- ERR_PTR(-EOPNOTSUPP))
- using_mac_select_pcs = true;
-
/* Validate the supplied configuration */
- if (using_mac_select_pcs &&
- phy_interface_empty(config->supported_interfaces)) {
+ if (phy_interface_empty(config->supported_interfaces)) {
dev_err(config->dev,
- "phylink: error: empty supported_interfaces but mac_select_pcs() method present\n");
+ "phylink: error: empty supported_interfaces\n");
return ERR_PTR(-EINVAL);
}
+ if (mac_ops->mac_select_pcs &&
+ mac_ops->mac_select_pcs(config, PHY_INTERFACE_MODE_NA) !=
+ ERR_PTR(-EOPNOTSUPP))
+ using_mac_select_pcs = true;
+
pl = kzalloc(sizeof(*pl), GFP_KERNEL);
if (!pl)
return ERR_PTR(-ENOMEM);
@@ -1809,7 +1866,7 @@ EXPORT_SYMBOL_GPL(phylink_of_phy_connect);
* Returns 0 on success or a negative errno.
*/
int phylink_fwnode_phy_connect(struct phylink *pl,
- struct fwnode_handle *fwnode,
+ const struct fwnode_handle *fwnode,
u32 flags)
{
struct fwnode_handle *phy_fwnode;
@@ -3131,8 +3188,8 @@ static void phylink_sfp_link_up(void *upstream)
*/
static bool phylink_phy_no_inband(struct phy_device *phy)
{
- return phy->is_c45 &&
- (phy->c45_ids.device_ids[1] & 0xfffffff0) == 0xae025150;
+ return phy->is_c45 && phy_id_compare(phy->c45_ids.device_ids[1],
+ 0xae025150, 0xfffffff0);
}
static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
@@ -3196,10 +3253,48 @@ static const struct sfp_upstream_ops sfp_phylink_ops = {
/* Helpers for MAC drivers */
+static struct {
+ int bit;
+ int speed;
+} phylink_c73_priority_resolution[] = {
+ { ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, SPEED_100000 },
+ { ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, SPEED_100000 },
+ /* 100GBASE-KP4 and 100GBASE-CR10 not supported */
+ { ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, SPEED_40000 },
+ { ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, SPEED_40000 },
+ { ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, SPEED_10000 },
+ { ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, SPEED_10000 },
+ /* 5GBASE-KR not supported */
+ { ETHTOOL_LINK_MODE_2500baseX_Full_BIT, SPEED_2500 },
+ { ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, SPEED_1000 },
+};
+
+void phylink_resolve_c73(struct phylink_link_state *state)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(phylink_c73_priority_resolution); i++) {
+ int bit = phylink_c73_priority_resolution[i].bit;
+ if (linkmode_test_bit(bit, state->advertising) &&
+ linkmode_test_bit(bit, state->lp_advertising))
+ break;
+ }
+
+ if (i < ARRAY_SIZE(phylink_c73_priority_resolution)) {
+ state->speed = phylink_c73_priority_resolution[i].speed;
+ state->duplex = DUPLEX_FULL;
+ } else {
+ /* negotiation failure */
+ state->link = false;
+ }
+
+ phylink_resolve_an_pause(state);
+}
+EXPORT_SYMBOL_GPL(phylink_resolve_c73);
+
static void phylink_decode_c37_word(struct phylink_link_state *state,
uint16_t config_reg, int speed)
{
- bool tx_pause, rx_pause;
int fd_bit;
if (speed == SPEED_2500)
@@ -3218,13 +3313,7 @@ static void phylink_decode_c37_word(struct phylink_link_state *state,
state->link = false;
}
- linkmode_resolve_pause(state->advertising, state->lp_advertising,
- &tx_pause, &rx_pause);
-
- if (tx_pause)
- state->pause |= MLO_PAUSE_TX;
- if (rx_pause)
- state->pause |= MLO_PAUSE_RX;
+ phylink_resolve_an_pause(state);
}
static void phylink_decode_sgmii_word(struct phylink_link_state *state,
@@ -3456,18 +3545,19 @@ EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_encode_advertisement);
/**
* phylink_mii_c22_pcs_config() - configure clause 22 PCS
* @pcs: a pointer to a &struct mdio_device.
- * @mode: link autonegotiation mode
* @interface: the PHY interface mode being configured
* @advertising: the ethtool advertisement mask
+ * @neg_mode: PCS negotiation mode
*
* Configure a Clause 22 PCS PHY with the appropriate negotiation
* parameters for the @mode, @interface and @advertising parameters.
* Returns negative error number on failure, zero if the advertisement
* has not changed, or positive if there is a change.
*/
-int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode,
+int phylink_mii_c22_pcs_config(struct mdio_device *pcs,
phy_interface_t interface,
- const unsigned long *advertising)
+ const unsigned long *advertising,
+ unsigned int neg_mode)
{
bool changed = 0;
u16 bmcr;
@@ -3482,15 +3572,12 @@ int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode,
changed = ret;
}
- /* Ensure ISOLATE bit is disabled */
- if (mode == MLO_AN_INBAND &&
- (interface == PHY_INTERFACE_MODE_SGMII ||
- interface == PHY_INTERFACE_MODE_QSGMII ||
- linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising)))
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
bmcr = BMCR_ANENABLE;
else
bmcr = 0;
+ /* Configure the inband state. Ensure ISOLATE bit is disabled */
ret = mdiodev_modify(pcs, MII_BMCR, BMCR_ANENABLE | BMCR_ISOLATE, bmcr);
if (ret < 0)
return ret;
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 3d99fd6664d7..894172a3e15f 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -12,6 +12,7 @@
#include <linux/phy.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/clk.h>
#define RTL821x_PHYSR 0x11
#define RTL821x_PHYSR_DUPLEX BIT(13)
@@ -80,6 +81,7 @@ struct rtl821x_priv {
u16 phycr1;
u16 phycr2;
bool has_phycr2;
+ struct clk *clk;
};
static int rtl821x_read_page(struct phy_device *phydev)
@@ -103,6 +105,11 @@ static int rtl821x_probe(struct phy_device *phydev)
if (!priv)
return -ENOMEM;
+ priv->clk = devm_clk_get_optional_enabled(dev, NULL);
+ if (IS_ERR(priv->clk))
+ return dev_err_probe(dev, PTR_ERR(priv->clk),
+ "failed to get phy clock\n");
+
ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR1);
if (ret < 0)
return ret;
@@ -419,10 +426,31 @@ static int rtl8211f_config_init(struct phy_device *phydev)
return genphy_soft_reset(phydev);
}
+static int rtl821x_suspend(struct phy_device *phydev)
+{
+ struct rtl821x_priv *priv = phydev->priv;
+ int ret = 0;
+
+ if (!phydev->wol_enabled) {
+ ret = genphy_suspend(phydev);
+
+ if (ret)
+ return ret;
+
+ clk_disable_unprepare(priv->clk);
+ }
+
+ return ret;
+}
+
static int rtl821x_resume(struct phy_device *phydev)
{
+ struct rtl821x_priv *priv = phydev->priv;
int ret;
+ if (!phydev->wol_enabled)
+ clk_prepare_enable(priv->clk);
+
ret = genphy_resume(phydev);
if (ret < 0)
return ret;
@@ -927,10 +955,11 @@ static struct phy_driver realtek_drvs[] = {
.read_status = rtlgen_read_status,
.config_intr = &rtl8211f_config_intr,
.handle_interrupt = rtl8211f_handle_interrupt,
- .suspend = genphy_suspend,
+ .suspend = rtl821x_suspend,
.resume = rtl821x_resume,
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
+ .flags = PHY_ALWAYS_CALL_SUSPEND,
}, {
PHY_ID_MATCH_EXACT(RTL_8211FVD_PHYID),
.name = "RTL8211F-VD Gigabit Ethernet",
@@ -939,10 +968,11 @@ static struct phy_driver realtek_drvs[] = {
.read_status = rtlgen_read_status,
.config_intr = &rtl8211f_config_intr,
.handle_interrupt = rtl8211f_handle_interrupt,
- .suspend = genphy_suspend,
+ .suspend = rtl821x_suspend,
.resume = rtl821x_resume,
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
+ .flags = PHY_ALWAYS_CALL_SUSPEND,
}, {
.name = "Generic FE-GE Realtek PHY",
.match_phy_device = rtlgen_match_phy_device,
diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
index 9372e5a4cadc..208a9393c2df 100644
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
@@ -258,6 +258,16 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
switch (id->base.extended_cc) {
case SFF8024_ECC_UNSPEC:
break;
+ case SFF8024_ECC_100G_25GAUI_C2M_AOC:
+ if (br_min <= 28000 && br_max >= 25000) {
+ /* 25GBASE-R, possibly with FEC */
+ __set_bit(PHY_INTERFACE_MODE_25GBASER, interfaces);
+ /* There is currently no link mode for 25000base
+ * with unspecified range, reuse SR.
+ */
+ phylink_set(modes, 25000baseSR_Full);
+ }
+ break;
case SFF8024_ECC_100GBASE_SR4_25GBASE_SR:
phylink_set(modes, 100000baseSR4_Full);
phylink_set(modes, 25000baseSR_Full);
@@ -576,6 +586,26 @@ static void sfp_upstream_clear(struct sfp_bus *bus)
}
/**
+ * sfp_upstream_set_signal_rate() - set data signalling rate
+ * @bus: a pointer to the &struct sfp_bus structure for the sfp module
+ * @rate_kbd: signalling rate in units of 1000 baud
+ *
+ * Configure the rate select settings on the SFP module for the signalling
+ * rate (not the same as the data rate).
+ *
+ * Locks that may be held:
+ * Phylink's state_mutex
+ * rtnl lock
+ * SFP's sm_mutex
+ */
+void sfp_upstream_set_signal_rate(struct sfp_bus *bus, unsigned int rate_kbd)
+{
+ if (bus->registered)
+ bus->socket_ops->set_signal_rate(bus->sfp, rate_kbd);
+}
+EXPORT_SYMBOL_GPL(sfp_upstream_set_signal_rate);
+
+/**
* sfp_bus_find_fwnode() - parse and locate the SFP bus from fwnode
* @fwnode: firmware node for the parent device (MAC or PHY)
*
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 89636dc71e48..d855a18308d7 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -24,14 +24,18 @@ enum {
GPIO_LOS,
GPIO_TX_FAULT,
GPIO_TX_DISABLE,
- GPIO_RATE_SELECT,
+ GPIO_RS0,
+ GPIO_RS1,
GPIO_MAX,
SFP_F_PRESENT = BIT(GPIO_MODDEF0),
SFP_F_LOS = BIT(GPIO_LOS),
SFP_F_TX_FAULT = BIT(GPIO_TX_FAULT),
SFP_F_TX_DISABLE = BIT(GPIO_TX_DISABLE),
- SFP_F_RATE_SELECT = BIT(GPIO_RATE_SELECT),
+ SFP_F_RS0 = BIT(GPIO_RS0),
+ SFP_F_RS1 = BIT(GPIO_RS1),
+
+ SFP_F_OUTPUTS = SFP_F_TX_DISABLE | SFP_F_RS0 | SFP_F_RS1,
SFP_E_INSERT = 0,
SFP_E_REMOVE,
@@ -148,6 +152,7 @@ static const char *gpio_names[] = {
"tx-fault",
"tx-disable",
"rate-select0",
+ "rate-select1",
};
static const enum gpiod_flags gpio_flags[] = {
@@ -156,6 +161,7 @@ static const enum gpiod_flags gpio_flags[] = {
GPIOD_IN,
GPIOD_ASIS,
GPIOD_ASIS,
+ GPIOD_ASIS,
};
/* t_start_up (SFF-8431) or t_init (SFF-8472) is the time required for a
@@ -164,7 +170,6 @@ static const enum gpiod_flags gpio_flags[] = {
* on board (for a copper SFP) time to initialise.
*/
#define T_WAIT msecs_to_jiffies(50)
-#define T_WAIT_ROLLBALL msecs_to_jiffies(25000)
#define T_START_UP msecs_to_jiffies(300)
#define T_START_UP_BAD_GPON msecs_to_jiffies(60000)
@@ -242,10 +247,18 @@ struct sfp {
bool need_poll;
+ /* Access rules:
+ * state_hw_drive: st_mutex held
+ * state_hw_mask: st_mutex held
+ * state_soft_mask: st_mutex held
+ * state: st_mutex held unless reading input bits
+ */
struct mutex st_mutex; /* Protects state */
+ unsigned int state_hw_drive;
unsigned int state_hw_mask;
unsigned int state_soft_mask;
unsigned int state;
+
struct delayed_work poll;
struct delayed_work timeout;
struct mutex sm_mutex; /* Protects state machine */
@@ -262,6 +275,10 @@ struct sfp {
unsigned int module_t_start_up;
unsigned int module_t_wait;
+ unsigned int rate_kbd;
+ unsigned int rs_threshold_kbd;
+ unsigned int rs_state_mask;
+
bool have_a2;
bool tx_fault_ignore;
@@ -312,7 +329,7 @@ static bool sfp_module_supported(const struct sfp_eeprom_id *id)
static const struct sff_data sfp_data = {
.gpios = SFP_F_PRESENT | SFP_F_LOS | SFP_F_TX_FAULT |
- SFP_F_TX_DISABLE | SFP_F_RATE_SELECT,
+ SFP_F_TX_DISABLE | SFP_F_RS0 | SFP_F_RS1,
.module_supported = sfp_module_supported,
};
@@ -333,6 +350,27 @@ static void sfp_fixup_ignore_tx_fault(struct sfp *sfp)
sfp->tx_fault_ignore = true;
}
+// For 10GBASE-T short-reach modules
+static void sfp_fixup_10gbaset_30m(struct sfp *sfp)
+{
+ sfp->id.base.connector = SFF8024_CONNECTOR_RJ45;
+ sfp->id.base.extended_cc = SFF8024_ECC_10GBASE_T_SR;
+}
+
+static void sfp_fixup_rollball_proto(struct sfp *sfp, unsigned int secs)
+{
+ sfp->mdio_protocol = MDIO_I2C_ROLLBALL;
+ sfp->module_t_wait = msecs_to_jiffies(secs * 1000);
+}
+
+static void sfp_fixup_fs_10gt(struct sfp *sfp)
+{
+ sfp_fixup_10gbaset_30m(sfp);
+
+ // These SFPs need 4 seconds before the PHY can be accessed
+ sfp_fixup_rollball_proto(sfp, 4);
+}
+
static void sfp_fixup_halny_gsfp(struct sfp *sfp)
{
/* Ignore the TX_FAULT and LOS signals on this module.
@@ -344,8 +382,8 @@ static void sfp_fixup_halny_gsfp(struct sfp *sfp)
static void sfp_fixup_rollball(struct sfp *sfp)
{
- sfp->mdio_protocol = MDIO_I2C_ROLLBALL;
- sfp->module_t_wait = T_WAIT_ROLLBALL;
+ // Rollball SFPs need 25 seconds before the PHY can be accessed
+ sfp_fixup_rollball_proto(sfp, 25);
}
static void sfp_fixup_rollball_cc(struct sfp *sfp)
@@ -410,6 +448,10 @@ static const struct sfp_quirk sfp_quirks[] = {
SFP_QUIRK("ALCATELLUCENT", "3FE46541AA", sfp_quirk_2500basex,
sfp_fixup_long_startup),
+ // Fiberstore SFP-10G-T doesn't identify as copper, and uses the
+ // Rollball protocol to talk to the PHY.
+ SFP_QUIRK_F("FS", "SFP-10G-T", sfp_fixup_fs_10gt),
+
SFP_QUIRK_F("HALNy", "HL-GSFP", sfp_fixup_halny_gsfp),
// HG MXPD-483II-F 2.5G supports 2500Base-X, but incorrectly reports
@@ -427,6 +469,11 @@ static const struct sfp_quirk sfp_quirks[] = {
SFP_QUIRK_M("UBNT", "UF-INSTANT", sfp_quirk_ubnt_uf_instant),
+ // Walsun HXSX-ATR[CI]-1 don't identify as copper, and use the
+ // Rollball protocol to talk to the PHY.
+ SFP_QUIRK_F("Walsun", "HXSX-ATRC-1", sfp_fixup_fs_10gt),
+ SFP_QUIRK_F("Walsun", "HXSX-ATRI-1", sfp_fixup_fs_10gt),
+
SFP_QUIRK_F("OEM", "SFP-10G-T", sfp_fixup_rollball_cc),
SFP_QUIRK_M("OEM", "SFP-2.5G-T", sfp_quirk_oem_2_5g),
SFP_QUIRK_F("OEM", "RTSFP-10", sfp_fixup_rollball_cc),
@@ -500,20 +547,37 @@ static unsigned int sff_gpio_get_state(struct sfp *sfp)
static void sfp_gpio_set_state(struct sfp *sfp, unsigned int state)
{
- if (state & SFP_F_PRESENT) {
- /* If the module is present, drive the signals */
- if (sfp->gpio[GPIO_TX_DISABLE])
+ unsigned int drive;
+
+ if (state & SFP_F_PRESENT)
+ /* If the module is present, drive the requested signals */
+ drive = sfp->state_hw_drive;
+ else
+ /* Otherwise, let them float to the pull-ups */
+ drive = 0;
+
+ if (sfp->gpio[GPIO_TX_DISABLE]) {
+ if (drive & SFP_F_TX_DISABLE)
gpiod_direction_output(sfp->gpio[GPIO_TX_DISABLE],
state & SFP_F_TX_DISABLE);
- if (state & SFP_F_RATE_SELECT)
- gpiod_direction_output(sfp->gpio[GPIO_RATE_SELECT],
- state & SFP_F_RATE_SELECT);
- } else {
- /* Otherwise, let them float to the pull-ups */
- if (sfp->gpio[GPIO_TX_DISABLE])
+ else
gpiod_direction_input(sfp->gpio[GPIO_TX_DISABLE]);
- if (state & SFP_F_RATE_SELECT)
- gpiod_direction_input(sfp->gpio[GPIO_RATE_SELECT]);
+ }
+
+ if (sfp->gpio[GPIO_RS0]) {
+ if (drive & SFP_F_RS0)
+ gpiod_direction_output(sfp->gpio[GPIO_RS0],
+ state & SFP_F_RS0);
+ else
+ gpiod_direction_input(sfp->gpio[GPIO_RS0]);
+ }
+
+ if (sfp->gpio[GPIO_RS1]) {
+ if (drive & SFP_F_RS1)
+ gpiod_direction_output(sfp->gpio[GPIO_RS1],
+ state & SFP_F_RS1);
+ else
+ gpiod_direction_input(sfp->gpio[GPIO_RS1]);
}
}
@@ -675,16 +739,33 @@ static unsigned int sfp_soft_get_state(struct sfp *sfp)
return state & sfp->state_soft_mask;
}
-static void sfp_soft_set_state(struct sfp *sfp, unsigned int state)
+static void sfp_soft_set_state(struct sfp *sfp, unsigned int state,
+ unsigned int soft)
{
- u8 mask = SFP_STATUS_TX_DISABLE_FORCE;
+ u8 mask = 0;
u8 val = 0;
+ if (soft & SFP_F_TX_DISABLE)
+ mask |= SFP_STATUS_TX_DISABLE_FORCE;
if (state & SFP_F_TX_DISABLE)
val |= SFP_STATUS_TX_DISABLE_FORCE;
+ if (soft & SFP_F_RS0)
+ mask |= SFP_STATUS_RS0_SELECT;
+ if (state & SFP_F_RS0)
+ val |= SFP_STATUS_RS0_SELECT;
+
+ if (mask)
+ sfp_modify_u8(sfp, true, SFP_STATUS, mask, val);
- sfp_modify_u8(sfp, true, SFP_STATUS, mask, val);
+ val = mask = 0;
+ if (soft & SFP_F_RS1)
+ mask |= SFP_EXT_STATUS_RS1_SELECT;
+ if (state & SFP_F_RS1)
+ val |= SFP_EXT_STATUS_RS1_SELECT;
+
+ if (mask)
+ sfp_modify_u8(sfp, true, SFP_EXT_STATUS, mask, val);
}
static void sfp_soft_start_poll(struct sfp *sfp)
@@ -692,27 +773,35 @@ static void sfp_soft_start_poll(struct sfp *sfp)
const struct sfp_eeprom_id *id = &sfp->id;
unsigned int mask = 0;
- sfp->state_soft_mask = 0;
if (id->ext.enhopts & SFP_ENHOPTS_SOFT_TX_DISABLE)
mask |= SFP_F_TX_DISABLE;
if (id->ext.enhopts & SFP_ENHOPTS_SOFT_TX_FAULT)
mask |= SFP_F_TX_FAULT;
if (id->ext.enhopts & SFP_ENHOPTS_SOFT_RX_LOS)
mask |= SFP_F_LOS;
+ if (id->ext.enhopts & SFP_ENHOPTS_SOFT_RATE_SELECT)
+ mask |= sfp->rs_state_mask;
+ mutex_lock(&sfp->st_mutex);
// Poll the soft state for hardware pins we want to ignore
sfp->state_soft_mask = ~sfp->state_hw_mask & mask;
if (sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT) &&
!sfp->need_poll)
mod_delayed_work(system_wq, &sfp->poll, poll_jiffies);
+ mutex_unlock(&sfp->st_mutex);
}
static void sfp_soft_stop_poll(struct sfp *sfp)
{
+ mutex_lock(&sfp->st_mutex);
sfp->state_soft_mask = 0;
+ mutex_unlock(&sfp->st_mutex);
}
+/* sfp_get_state() - must be called with st_mutex held, or in the
+ * initialisation path.
+ */
static unsigned int sfp_get_state(struct sfp *sfp)
{
unsigned int soft = sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT);
@@ -725,13 +814,26 @@ static unsigned int sfp_get_state(struct sfp *sfp)
return state;
}
+/* sfp_set_state() - must be called with st_mutex held, or in the
+ * initialisation path.
+ */
static void sfp_set_state(struct sfp *sfp, unsigned int state)
{
+ unsigned int soft;
+
sfp->set_state(sfp, state);
- if (state & SFP_F_PRESENT &&
- sfp->state_soft_mask & SFP_F_TX_DISABLE)
- sfp_soft_set_state(sfp, state);
+ soft = sfp->state_soft_mask & SFP_F_OUTPUTS;
+ if (state & SFP_F_PRESENT && soft)
+ sfp_soft_set_state(sfp, state, soft);
+}
+
+static void sfp_mod_state(struct sfp *sfp, unsigned int mask, unsigned int set)
+{
+ mutex_lock(&sfp->st_mutex);
+ sfp->state = (sfp->state & ~mask) | set;
+ sfp_set_state(sfp, sfp->state);
+ mutex_unlock(&sfp->st_mutex);
}
static unsigned int sfp_check(void *buf, size_t len)
@@ -1537,16 +1639,14 @@ static void sfp_module_tx_disable(struct sfp *sfp)
{
dev_dbg(sfp->dev, "tx disable %u -> %u\n",
sfp->state & SFP_F_TX_DISABLE ? 1 : 0, 1);
- sfp->state |= SFP_F_TX_DISABLE;
- sfp_set_state(sfp, sfp->state);
+ sfp_mod_state(sfp, SFP_F_TX_DISABLE, SFP_F_TX_DISABLE);
}
static void sfp_module_tx_enable(struct sfp *sfp)
{
dev_dbg(sfp->dev, "tx disable %u -> %u\n",
sfp->state & SFP_F_TX_DISABLE ? 1 : 0, 0);
- sfp->state &= ~SFP_F_TX_DISABLE;
- sfp_set_state(sfp, sfp->state);
+ sfp_mod_state(sfp, SFP_F_TX_DISABLE, 0);
}
#if IS_ENABLED(CONFIG_DEBUG_FS)
@@ -1567,10 +1667,15 @@ static int sfp_debug_state_show(struct seq_file *s, void *data)
sfp->sm_fault_retries);
seq_printf(s, "PHY probe remaining retries: %d\n",
sfp->sm_phy_retries);
+ seq_printf(s, "Signalling rate: %u kBd\n", sfp->rate_kbd);
+ seq_printf(s, "Rate select threshold: %u kBd\n",
+ sfp->rs_threshold_kbd);
seq_printf(s, "moddef0: %d\n", !!(sfp->state & SFP_F_PRESENT));
seq_printf(s, "rx_los: %d\n", !!(sfp->state & SFP_F_LOS));
seq_printf(s, "tx_fault: %d\n", !!(sfp->state & SFP_F_TX_FAULT));
seq_printf(s, "tx_disable: %d\n", !!(sfp->state & SFP_F_TX_DISABLE));
+ seq_printf(s, "rs0: %d\n", !!(sfp->state & SFP_F_RS0));
+ seq_printf(s, "rs1: %d\n", !!(sfp->state & SFP_F_RS1));
return 0;
}
DEFINE_SHOW_ATTRIBUTE(sfp_debug_state);
@@ -1599,16 +1704,18 @@ static void sfp_debugfs_exit(struct sfp *sfp)
static void sfp_module_tx_fault_reset(struct sfp *sfp)
{
- unsigned int state = sfp->state;
-
- if (state & SFP_F_TX_DISABLE)
- return;
+ unsigned int state;
- sfp_set_state(sfp, state | SFP_F_TX_DISABLE);
+ mutex_lock(&sfp->st_mutex);
+ state = sfp->state;
+ if (!(state & SFP_F_TX_DISABLE)) {
+ sfp_set_state(sfp, state | SFP_F_TX_DISABLE);
- udelay(T_RESET_US);
+ udelay(T_RESET_US);
- sfp_set_state(sfp, state);
+ sfp_set_state(sfp, state);
+ }
+ mutex_unlock(&sfp->st_mutex);
}
/* SFP state machine */
@@ -1874,6 +1981,95 @@ static int sfp_sm_mod_hpower(struct sfp *sfp, bool enable)
return 0;
}
+static void sfp_module_parse_rate_select(struct sfp *sfp)
+{
+ u8 rate_id;
+
+ sfp->rs_threshold_kbd = 0;
+ sfp->rs_state_mask = 0;
+
+ if (!(sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_RATE_SELECT)))
+ /* No support for RateSelect */
+ return;
+
+ /* Default to INF-8074 RateSelect operation. The signalling threshold
+ * rate is not well specified, so always select "Full Bandwidth", but
+ * SFF-8079 reveals that it is understood that RS0 will be low for
+ * 1.0625Gb/s and high for 2.125Gb/s. Choose a value half-way between.
+ * This method exists prior to SFF-8472.
+ */
+ sfp->rs_state_mask = SFP_F_RS0;
+ sfp->rs_threshold_kbd = 1594;
+
+ /* Parse the rate identifier, which is complicated due to history:
+ * SFF-8472 rev 9.5 marks this field as reserved.
+ * SFF-8079 references SFF-8472 rev 9.5 and defines bit 0. SFF-8472
+ * compliance is not required.
+ * SFF-8472 rev 10.2 defines this field using values 0..4
+ * SFF-8472 rev 11.0 redefines this field with bit 0 for SFF-8079
+ * and even values.
+ */
+ rate_id = sfp->id.base.rate_id;
+ if (rate_id == 0)
+ /* Unspecified */
+ return;
+
+ /* SFF-8472 rev 10.0..10.4 did not account for SFF-8079 using bit 0,
+ * and allocated value 3 to SFF-8431 independent tx/rx rate select.
+ * Convert this to a SFF-8472 rev 11.0 rate identifier.
+ */
+ if (sfp->id.ext.sff8472_compliance >= SFP_SFF8472_COMPLIANCE_REV10_2 &&
+ sfp->id.ext.sff8472_compliance < SFP_SFF8472_COMPLIANCE_REV11_0 &&
+ rate_id == 3)
+ rate_id = SFF_RID_8431;
+
+ if (rate_id & SFF_RID_8079) {
+ /* SFF-8079 RateSelect / Application Select in conjunction with
+ * SFF-8472 rev 9.5. SFF-8079 defines rate_id as a bitfield
+ * with only bit 0 used, which takes precedence over SFF-8472.
+ */
+ if (!(sfp->id.ext.enhopts & SFP_ENHOPTS_APP_SELECT_SFF8079)) {
+ /* SFF-8079 Part 1 - rate selection between Fibre
+ * Channel 1.0625/2.125/4.25 Gbd modes. Note that RS0
+ * is high for 2125, so we have to subtract 1 to
+ * include it.
+ */
+ sfp->rs_threshold_kbd = 2125 - 1;
+ sfp->rs_state_mask = SFP_F_RS0;
+ }
+ return;
+ }
+
+ /* SFF-8472 rev 9.5 does not define the rate identifier */
+ if (sfp->id.ext.sff8472_compliance <= SFP_SFF8472_COMPLIANCE_REV9_5)
+ return;
+
+ /* SFF-8472 rev 11.0 defines rate_id as a numerical value which will
+ * always have bit 0 clear due to SFF-8079's bitfield usage of rate_id.
+ */
+ switch (rate_id) {
+ case SFF_RID_8431_RX_ONLY:
+ sfp->rs_threshold_kbd = 4250;
+ sfp->rs_state_mask = SFP_F_RS0;
+ break;
+
+ case SFF_RID_8431_TX_ONLY:
+ sfp->rs_threshold_kbd = 4250;
+ sfp->rs_state_mask = SFP_F_RS1;
+ break;
+
+ case SFF_RID_8431:
+ sfp->rs_threshold_kbd = 4250;
+ sfp->rs_state_mask = SFP_F_RS0 | SFP_F_RS1;
+ break;
+
+ case SFF_RID_10G8G:
+ sfp->rs_threshold_kbd = 9000;
+ sfp->rs_state_mask = SFP_F_RS0 | SFP_F_RS1;
+ break;
+ }
+}
+
/* GPON modules based on Realtek RTL8672 and RTL9601C chips (e.g. V-SOL
* V2801F, CarlitoxxPro CPGOS03-0490, Ubiquiti U-Fiber Instant, ...) do
* not support multibyte reads from the EEPROM. Each multi-byte read
@@ -1953,6 +2149,7 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
/* SFP module inserted - read I2C data */
struct sfp_eeprom_id id;
bool cotsworks_sfbg;
+ unsigned int mask;
bool cotsworks;
u8 check;
int ret;
@@ -2092,14 +2289,19 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
if (ret < 0)
return ret;
- /* Initialise state bits to use from hardware */
- sfp->state_hw_mask = SFP_F_PRESENT;
+ sfp_module_parse_rate_select(sfp);
+
+ mask = SFP_F_PRESENT;
if (sfp->gpio[GPIO_TX_DISABLE])
- sfp->state_hw_mask |= SFP_F_TX_DISABLE;
+ mask |= SFP_F_TX_DISABLE;
if (sfp->gpio[GPIO_TX_FAULT])
- sfp->state_hw_mask |= SFP_F_TX_FAULT;
+ mask |= SFP_F_TX_FAULT;
if (sfp->gpio[GPIO_LOS])
- sfp->state_hw_mask |= SFP_F_LOS;
+ mask |= SFP_F_LOS;
+ if (sfp->gpio[GPIO_RS0])
+ mask |= SFP_F_RS0;
+ if (sfp->gpio[GPIO_RS1])
+ mask |= SFP_F_RS1;
sfp->module_t_start_up = T_START_UP;
sfp->module_t_wait = T_WAIT;
@@ -2117,8 +2319,17 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
sfp->mdio_protocol = MDIO_I2C_NONE;
sfp->quirk = sfp_lookup_quirk(&id);
+
+ mutex_lock(&sfp->st_mutex);
+ /* Initialise state bits to use from hardware */
+ sfp->state_hw_mask = mask;
+
+ /* We want to drive the rate select pins that the module is using */
+ sfp->state_hw_drive |= sfp->rs_state_mask;
+
if (sfp->quirk && sfp->quirk->fixup)
sfp->quirk->fixup(sfp);
+ mutex_unlock(&sfp->st_mutex);
return 0;
}
@@ -2132,6 +2343,7 @@ static void sfp_sm_mod_remove(struct sfp *sfp)
memset(&sfp->id, 0, sizeof(sfp->id));
sfp->module_power_mW = 0;
+ sfp->state_hw_drive = SFP_F_TX_DISABLE;
sfp->have_a2 = false;
dev_info(sfp->dev, "module removed\n");
@@ -2452,10 +2664,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
}
}
-static void sfp_sm_event(struct sfp *sfp, unsigned int event)
+static void __sfp_sm_event(struct sfp *sfp, unsigned int event)
{
- mutex_lock(&sfp->sm_mutex);
-
dev_dbg(sfp->dev, "SM: enter %s:%s:%s event %s\n",
mod_state_to_str(sfp->sm_mod_state),
dev_state_to_str(sfp->sm_dev_state),
@@ -2470,7 +2680,12 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
mod_state_to_str(sfp->sm_mod_state),
dev_state_to_str(sfp->sm_dev_state),
sm_state_to_str(sfp->sm_state));
+}
+static void sfp_sm_event(struct sfp *sfp, unsigned int event)
+{
+ mutex_lock(&sfp->sm_mutex);
+ __sfp_sm_event(sfp, event);
mutex_unlock(&sfp->sm_mutex);
}
@@ -2494,6 +2709,20 @@ static void sfp_stop(struct sfp *sfp)
sfp_sm_event(sfp, SFP_E_DEV_DOWN);
}
+static void sfp_set_signal_rate(struct sfp *sfp, unsigned int rate_kbd)
+{
+ unsigned int set;
+
+ sfp->rate_kbd = rate_kbd;
+
+ if (rate_kbd > sfp->rs_threshold_kbd)
+ set = sfp->rs_state_mask;
+ else
+ set = 0;
+
+ sfp_mod_state(sfp, SFP_F_RS0 | SFP_F_RS1, set);
+}
+
static int sfp_module_info(struct sfp *sfp, struct ethtool_modinfo *modinfo)
{
/* locking... and check module is present */
@@ -2578,6 +2807,7 @@ static const struct sfp_socket_ops sfp_module_ops = {
.detach = sfp_detach,
.start = sfp_start,
.stop = sfp_stop,
+ .set_signal_rate = sfp_set_signal_rate,
.module_info = sfp_module_info,
.module_eeprom = sfp_module_eeprom,
.module_eeprom_by_page = sfp_module_eeprom_by_page,
@@ -2596,6 +2826,7 @@ static void sfp_check_state(struct sfp *sfp)
{
unsigned int state, i, changed;
+ rtnl_lock();
mutex_lock(&sfp->st_mutex);
state = sfp_get_state(sfp);
changed = state ^ sfp->state;
@@ -2609,23 +2840,24 @@ static void sfp_check_state(struct sfp *sfp)
dev_dbg(sfp->dev, "%s %u -> %u\n", gpio_names[i],
!!(sfp->state & BIT(i)), !!(state & BIT(i)));
- state |= sfp->state & (SFP_F_TX_DISABLE | SFP_F_RATE_SELECT);
+ state |= sfp->state & SFP_F_OUTPUTS;
sfp->state = state;
+ mutex_unlock(&sfp->st_mutex);
- rtnl_lock();
+ mutex_lock(&sfp->sm_mutex);
if (changed & SFP_F_PRESENT)
- sfp_sm_event(sfp, state & SFP_F_PRESENT ?
- SFP_E_INSERT : SFP_E_REMOVE);
+ __sfp_sm_event(sfp, state & SFP_F_PRESENT ?
+ SFP_E_INSERT : SFP_E_REMOVE);
if (changed & SFP_F_TX_FAULT)
- sfp_sm_event(sfp, state & SFP_F_TX_FAULT ?
- SFP_E_TX_FAULT : SFP_E_TX_CLEAR);
+ __sfp_sm_event(sfp, state & SFP_F_TX_FAULT ?
+ SFP_E_TX_FAULT : SFP_E_TX_CLEAR);
if (changed & SFP_F_LOS)
- sfp_sm_event(sfp, state & SFP_F_LOS ?
- SFP_E_LOS_HIGH : SFP_E_LOS_LOW);
+ __sfp_sm_event(sfp, state & SFP_F_LOS ?
+ SFP_E_LOS_HIGH : SFP_E_LOS_LOW);
+ mutex_unlock(&sfp->sm_mutex);
rtnl_unlock();
- mutex_unlock(&sfp->st_mutex);
}
static irqreturn_t sfp_irq(int irq, void *data)
@@ -2643,6 +2875,8 @@ static void sfp_poll(struct work_struct *work)
sfp_check_state(sfp);
+ // st_mutex doesn't need to be held here for state_soft_mask,
+ // it's unimportant if we race while reading this.
if (sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT) ||
sfp->need_poll)
mod_delayed_work(system_wq, &sfp->poll, poll_jiffies);
@@ -2748,6 +2982,7 @@ static int sfp_probe(struct platform_device *pdev)
}
sfp->state_hw_mask = SFP_F_PRESENT;
+ sfp->state_hw_drive = SFP_F_TX_DISABLE;
sfp->get_state = sfp_gpio_get_state;
sfp->set_state = sfp_gpio_set_state;
@@ -2773,9 +3008,9 @@ static int sfp_probe(struct platform_device *pdev)
*/
sfp->state = sfp_get_state(sfp) | SFP_F_TX_DISABLE;
- if (sfp->gpio[GPIO_RATE_SELECT] &&
- gpiod_get_value_cansleep(sfp->gpio[GPIO_RATE_SELECT]))
- sfp->state |= SFP_F_RATE_SELECT;
+ if (sfp->gpio[GPIO_RS0] &&
+ gpiod_get_value_cansleep(sfp->gpio[GPIO_RS0]))
+ sfp->state |= SFP_F_RS0;
sfp_set_state(sfp, sfp->state);
sfp_module_tx_disable(sfp);
if (sfp->state & SFP_F_PRESENT) {
diff --git a/drivers/net/phy/sfp.h b/drivers/net/phy/sfp.h
index 6cf1643214d3..c7cb50d10099 100644
--- a/drivers/net/phy/sfp.h
+++ b/drivers/net/phy/sfp.h
@@ -19,6 +19,7 @@ struct sfp_socket_ops {
void (*detach)(struct sfp *sfp);
void (*start)(struct sfp *sfp);
void (*stop)(struct sfp *sfp);
+ void (*set_signal_rate)(struct sfp *sfp, unsigned int rate_kbd);
int (*module_info)(struct sfp *sfp, struct ethtool_modinfo *modinfo);
int (*module_eeprom)(struct sfp *sfp, struct ethtool_eeprom *ee,
u8 *data);
diff --git a/drivers/net/ppp/Kconfig b/drivers/net/ppp/Kconfig
index ac4d162d9455..8c9ed1889d1a 100644
--- a/drivers/net/ppp/Kconfig
+++ b/drivers/net/ppp/Kconfig
@@ -129,6 +129,40 @@ config PPPOE
which contains instruction on how to use this driver (under
the heading "Kernel mode PPPoE").
+choice
+ prompt "Number of PPPoE hash bits"
+ default PPPOE_HASH_BITS_4
+ depends on PPPOE
+ help
+ Select the number of bits used for hashing PPPoE interfaces.
+
+ Larger sizes reduces the risk of hash collisions at the cost
+ of slightly increased memory usage.
+
+ This hash table is on a per outer ethernet interface.
+
+config PPPOE_HASH_BITS_1
+ bool "1 bit (2 buckets)"
+
+config PPPOE_HASH_BITS_2
+ bool "2 bits (4 buckets)"
+
+config PPPOE_HASH_BITS_4
+ bool "4 bits (16 buckets)"
+
+config PPPOE_HASH_BITS_8
+ bool "8 bits (256 buckets)"
+
+endchoice
+
+config PPPOE_HASH_BITS
+ int
+ default 1 if PPPOE_HASH_BITS_1
+ default 2 if PPPOE_HASH_BITS_2
+ default 4 if PPPOE_HASH_BITS_4
+ default 8 if PPPOE_HASH_BITS_8
+ default 4
+
config PPTP
tristate "PPP over IPv4 (PPTP)"
depends on PPP && NET_IPGRE_DEMUX
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index ce2cbb5903d7..3b79c603b936 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -80,7 +80,7 @@
#include <linux/uaccess.h>
-#define PPPOE_HASH_BITS 4
+#define PPPOE_HASH_BITS CONFIG_PPPOE_HASH_BITS
#define PPPOE_HASH_SIZE (1 << PPPOE_HASH_BITS)
#define PPPOE_HASH_MASK (PPPOE_HASH_SIZE - 1)
diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c
index 0fe78826c8fa..32183f24e63f 100644
--- a/drivers/net/ppp/pptp.c
+++ b/drivers/net/ppp/pptp.c
@@ -24,6 +24,7 @@
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/rcupdate.h>
+#include <linux/security.h>
#include <linux/spinlock.h>
#include <net/sock.h>
@@ -128,6 +129,23 @@ static void del_chan(struct pppox_sock *sock)
spin_unlock(&chan_lock);
}
+static struct rtable *pptp_route_output(struct pppox_sock *po,
+ struct flowi4 *fl4)
+{
+ struct sock *sk = &po->sk;
+ struct net *net;
+
+ net = sock_net(sk);
+ flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, 0,
+ RT_SCOPE_UNIVERSE, IPPROTO_GRE, 0,
+ po->proto.pptp.dst_addr.sin_addr.s_addr,
+ po->proto.pptp.src_addr.sin_addr.s_addr,
+ 0, 0, sock_net_uid(net, sk));
+ security_sk_classify_flow(sk, flowi4_to_flowi_common(fl4));
+
+ return ip_route_output_flow(net, fl4, sk);
+}
+
static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
{
struct sock *sk = (struct sock *) chan->private;
@@ -151,11 +169,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
if (sk_pppox(po)->sk_state & PPPOX_DEAD)
goto tx_error;
- rt = ip_route_output_ports(net, &fl4, NULL,
- opt->dst_addr.sin_addr.s_addr,
- opt->src_addr.sin_addr.s_addr,
- 0, 0, IPPROTO_GRE,
- RT_TOS(0), sk->sk_bound_dev_if);
+ rt = pptp_route_output(po, &fl4);
if (IS_ERR(rt))
goto tx_error;
@@ -438,12 +452,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr,
po->chan.private = sk;
po->chan.ops = &pptp_chan_ops;
- rt = ip_route_output_ports(sock_net(sk), &fl4, sk,
- opt->dst_addr.sin_addr.s_addr,
- opt->src_addr.sin_addr.s_addr,
- 0, 0,
- IPPROTO_GRE, RT_CONN_FLAGS(sk),
- sk->sk_bound_dev_if);
+ rt = pptp_route_output(po, &fl4);
if (IS_ERR(rt)) {
error = -EHOSTUNREACH;
goto end;
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index d30d730ed5a7..49d1d6acf95e 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -18,6 +18,7 @@
#include <linux/fs.h>
#include <linux/uio.h>
+#include <net/gso.h>
#include <net/net_namespace.h>
#include <net/rtnetlink.h>
#include <net/sock.h>
@@ -533,7 +534,7 @@ static int tap_open(struct inode *inode, struct file *file)
q->sock.state = SS_CONNECTED;
q->sock.file = file;
q->sock.ops = &tap_socket_ops;
- sock_init_data_uid(&q->sock, &q->sk, inode->i_uid);
+ sock_init_data_uid(&q->sock, &q->sk, current_fsuid());
q->sk.sk_write_space = tap_sock_write_space;
q->sk.sk_destruct = tap_sock_destruct;
q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP;
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 555b0b1e9a78..382756c3fb83 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2135,6 +2135,15 @@ static void team_setup_by_port(struct net_device *dev,
dev->mtu = port_dev->mtu;
memcpy(dev->broadcast, port_dev->broadcast, port_dev->addr_len);
eth_hw_addr_inherit(dev, port_dev);
+
+ if (port_dev->flags & IFF_POINTOPOINT) {
+ dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
+ dev->flags |= (IFF_POINTOPOINT | IFF_NOARP);
+ } else if ((port_dev->flags & (IFF_BROADCAST | IFF_MULTICAST)) ==
+ (IFF_BROADCAST | IFF_MULTICAST)) {
+ dev->flags |= (IFF_BROADCAST | IFF_MULTICAST);
+ dev->flags &= ~(IFF_POINTOPOINT | IFF_NOARP);
+ }
}
static int team_dev_type_check_change(struct net_device *dev,
@@ -2191,7 +2200,9 @@ static void team_setup(struct net_device *dev)
dev->hw_features = TEAM_VLAN_FEATURES |
NETIF_F_HW_VLAN_CTAG_RX |
- NETIF_F_HW_VLAN_CTAG_FILTER;
+ NETIF_F_HW_VLAN_CTAG_FILTER |
+ NETIF_F_HW_VLAN_STAG_RX |
+ NETIF_F_HW_VLAN_STAG_FILTER;
dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
dev->features |= dev->hw_features;
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index d75456adc62a..100339bc8b04 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1594,7 +1594,7 @@ static bool tun_can_build_skb(struct tun_struct *tun, struct tun_file *tfile,
if (zerocopy)
return false;
- if (SKB_DATA_ALIGN(len + TUN_RX_PAD) +
+ if (SKB_DATA_ALIGN(len + TUN_RX_PAD + XDP_PACKET_HEADROOM) +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) > PAGE_SIZE)
return false;
@@ -3469,7 +3469,7 @@ static int tun_chr_open(struct inode *inode, struct file * file)
tfile->socket.file = file;
tfile->socket.ops = &tun_socket_ops;
- sock_init_data_uid(&tfile->socket, &tfile->sk, inode->i_uid);
+ sock_init_data_uid(&tfile->socket, &tfile->sk, current_fsuid());
tfile->sk.sk_write_space = tun_sock_write_space;
tfile->sk.sk_sndbuf = INT_MAX;
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index 4402eedb3d1a..3fd7dccf0f9c 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -583,12 +583,10 @@ config USB_IPHETH
default n
help
Module used to share Internet connection (tethering) from your
- iPhone (Original, 3G and 3GS) to your system.
- Note that you need userspace libraries and programs that are needed
- to pair your device with your system and that understand the iPhone
- protocol.
-
- For more information: http://giagio.com/wiki/moin.cgi/iPhoneEthernetDriver
+ iPhone to your system.
+ Note that you need a corresponding userspace library/program
+ to pair your device with your system, for example usbmuxd
+ <https://github.com/libimobiledevice/usbmuxd>.
config USB_SIERRA_NET
tristate "USB-to-WWAN Driver for Sierra Wireless modems"
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 80849d115e5d..6d61052353f0 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -618,6 +618,13 @@ static const struct usb_device_id products[] = {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
+ .idProduct = 0x8005, /* A-300 */
+ ZAURUS_FAKE_INTERFACE,
+ .driver_info = 0,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
.idProduct = 0x8006, /* B-500/SL-5600 */
ZAURUS_MASTER_INTERFACE,
.driver_info = 0,
@@ -625,11 +632,25 @@ static const struct usb_device_id products[] = {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
+ .idProduct = 0x8006, /* B-500/SL-5600 */
+ ZAURUS_FAKE_INTERFACE,
+ .driver_info = 0,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
.idProduct = 0x8007, /* C-700 */
ZAURUS_MASTER_INTERFACE,
.driver_info = 0,
}, {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8007, /* C-700 */
+ ZAURUS_FAKE_INTERFACE,
+ .driver_info = 0,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
.idProduct = 0x9031, /* C-750 C-760 */
@@ -876,6 +897,12 @@ static const struct usb_device_id products[] = {
USB_CDC_PROTO_NONE),
.driver_info = (unsigned long)&wwan_info,
}, {
+ /* U-blox LARA-R6 01B */
+ USB_DEVICE_AND_INTERFACE_INFO(UBLOX_VENDOR_ID, 0x1313, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_ETHERNET,
+ USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long)&wwan_info,
+}, {
/* U-blox LARA-L6 */
USB_DEVICE_AND_INTERFACE_INFO(UBLOX_VENDOR_ID, 0x1343, USB_CLASS_COMM,
USB_CDC_SUBCLASS_ETHERNET,
diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c
index 6a769df0b421..687d70cfc556 100644
--- a/drivers/net/usb/ipheth.c
+++ b/drivers/net/usb/ipheth.c
@@ -52,6 +52,7 @@
#include <linux/ethtool.h>
#include <linux/usb.h>
#include <linux/workqueue.h>
+#include <linux/usb/cdc.h>
#define USB_VENDOR_APPLE 0x05ac
@@ -59,8 +60,12 @@
#define IPHETH_USBINTF_SUBCLASS 253
#define IPHETH_USBINTF_PROTO 1
-#define IPHETH_BUF_SIZE 1514
#define IPHETH_IP_ALIGN 2 /* padding at front of URB */
+#define IPHETH_NCM_HEADER_SIZE (12 + 96) /* NCMH + NCM0 */
+#define IPHETH_TX_BUF_SIZE ETH_FRAME_LEN
+#define IPHETH_RX_BUF_SIZE_LEGACY (IPHETH_IP_ALIGN + ETH_FRAME_LEN)
+#define IPHETH_RX_BUF_SIZE_NCM 65536
+
#define IPHETH_TX_TIMEOUT (5 * HZ)
#define IPHETH_INTFNUM 2
@@ -71,6 +76,7 @@
#define IPHETH_CTRL_TIMEOUT (5 * HZ)
#define IPHETH_CMD_GET_MACADDR 0x00
+#define IPHETH_CMD_ENABLE_NCM 0x04
#define IPHETH_CMD_CARRIER_CHECK 0x45
#define IPHETH_CARRIER_CHECK_TIMEOUT round_jiffies_relative(1 * HZ)
@@ -97,6 +103,8 @@ struct ipheth_device {
u8 bulk_out;
struct delayed_work carrier_work;
bool confirmed_pairing;
+ int (*rcvbulk_callback)(struct urb *urb);
+ size_t rx_buf_len;
};
static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags);
@@ -116,12 +124,12 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone)
if (rx_urb == NULL)
goto free_tx_urb;
- tx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE,
+ tx_buf = usb_alloc_coherent(iphone->udev, IPHETH_TX_BUF_SIZE,
GFP_KERNEL, &tx_urb->transfer_dma);
if (tx_buf == NULL)
goto free_rx_urb;
- rx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN,
+ rx_buf = usb_alloc_coherent(iphone->udev, iphone->rx_buf_len,
GFP_KERNEL, &rx_urb->transfer_dma);
if (rx_buf == NULL)
goto free_tx_buf;
@@ -134,7 +142,7 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone)
return 0;
free_tx_buf:
- usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, tx_buf,
+ usb_free_coherent(iphone->udev, IPHETH_TX_BUF_SIZE, tx_buf,
tx_urb->transfer_dma);
free_rx_urb:
usb_free_urb(rx_urb);
@@ -146,9 +154,9 @@ error_nomem:
static void ipheth_free_urbs(struct ipheth_device *iphone)
{
- usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, iphone->rx_buf,
+ usb_free_coherent(iphone->udev, iphone->rx_buf_len, iphone->rx_buf,
iphone->rx_urb->transfer_dma);
- usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->tx_buf,
+ usb_free_coherent(iphone->udev, IPHETH_TX_BUF_SIZE, iphone->tx_buf,
iphone->tx_urb->transfer_dma);
usb_free_urb(iphone->rx_urb);
usb_free_urb(iphone->tx_urb);
@@ -160,15 +168,106 @@ static void ipheth_kill_urbs(struct ipheth_device *dev)
usb_kill_urb(dev->rx_urb);
}
-static void ipheth_rcvbulk_callback(struct urb *urb)
+static int ipheth_consume_skb(char *buf, int len, struct ipheth_device *dev)
{
- struct ipheth_device *dev;
struct sk_buff *skb;
- int status;
+
+ skb = dev_alloc_skb(len);
+ if (!skb) {
+ dev->net->stats.rx_dropped++;
+ return -ENOMEM;
+ }
+
+ skb_put_data(skb, buf, len);
+ skb->dev = dev->net;
+ skb->protocol = eth_type_trans(skb, dev->net);
+
+ dev->net->stats.rx_packets++;
+ dev->net->stats.rx_bytes += len;
+ netif_rx(skb);
+
+ return 0;
+}
+
+static int ipheth_rcvbulk_callback_legacy(struct urb *urb)
+{
+ struct ipheth_device *dev;
char *buf;
int len;
dev = urb->context;
+
+ if (urb->actual_length <= IPHETH_IP_ALIGN) {
+ dev->net->stats.rx_length_errors++;
+ return -EINVAL;
+ }
+ len = urb->actual_length - IPHETH_IP_ALIGN;
+ buf = urb->transfer_buffer + IPHETH_IP_ALIGN;
+
+ return ipheth_consume_skb(buf, len, dev);
+}
+
+static int ipheth_rcvbulk_callback_ncm(struct urb *urb)
+{
+ struct usb_cdc_ncm_nth16 *ncmh;
+ struct usb_cdc_ncm_ndp16 *ncm0;
+ struct usb_cdc_ncm_dpe16 *dpe;
+ struct ipheth_device *dev;
+ int retval = -EINVAL;
+ char *buf;
+ int len;
+
+ dev = urb->context;
+
+ if (urb->actual_length < IPHETH_NCM_HEADER_SIZE) {
+ dev->net->stats.rx_length_errors++;
+ return retval;
+ }
+
+ ncmh = urb->transfer_buffer;
+ if (ncmh->dwSignature != cpu_to_le32(USB_CDC_NCM_NTH16_SIGN) ||
+ le16_to_cpu(ncmh->wNdpIndex) >= urb->actual_length) {
+ dev->net->stats.rx_errors++;
+ return retval;
+ }
+
+ ncm0 = urb->transfer_buffer + le16_to_cpu(ncmh->wNdpIndex);
+ if (ncm0->dwSignature != cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN) ||
+ le16_to_cpu(ncmh->wHeaderLength) + le16_to_cpu(ncm0->wLength) >=
+ urb->actual_length) {
+ dev->net->stats.rx_errors++;
+ return retval;
+ }
+
+ dpe = ncm0->dpe16;
+ while (le16_to_cpu(dpe->wDatagramIndex) != 0 &&
+ le16_to_cpu(dpe->wDatagramLength) != 0) {
+ if (le16_to_cpu(dpe->wDatagramIndex) >= urb->actual_length ||
+ le16_to_cpu(dpe->wDatagramIndex) +
+ le16_to_cpu(dpe->wDatagramLength) > urb->actual_length) {
+ dev->net->stats.rx_length_errors++;
+ return retval;
+ }
+
+ buf = urb->transfer_buffer + le16_to_cpu(dpe->wDatagramIndex);
+ len = le16_to_cpu(dpe->wDatagramLength);
+
+ retval = ipheth_consume_skb(buf, len, dev);
+ if (retval != 0)
+ return retval;
+
+ dpe++;
+ }
+
+ return 0;
+}
+
+static void ipheth_rcvbulk_callback(struct urb *urb)
+{
+ struct ipheth_device *dev;
+ int retval, status;
+
+ dev = urb->context;
if (dev == NULL)
return;
@@ -191,25 +290,27 @@ static void ipheth_rcvbulk_callback(struct urb *urb)
dev->net->stats.rx_length_errors++;
return;
}
- len = urb->actual_length - IPHETH_IP_ALIGN;
- buf = urb->transfer_buffer + IPHETH_IP_ALIGN;
- skb = dev_alloc_skb(len);
- if (!skb) {
- dev_err(&dev->intf->dev, "%s: dev_alloc_skb: -ENOMEM\n",
- __func__);
- dev->net->stats.rx_dropped++;
+ /* RX URBs starting with 0x00 0x01 do not encapsulate Ethernet frames,
+ * but rather are control frames. Their purpose is not documented, and
+ * they don't affect driver functionality, okay to drop them.
+ * There is usually just one 4-byte control frame as the very first
+ * URB received from the bulk IN endpoint.
+ */
+ if (unlikely
+ (((char *)urb->transfer_buffer)[0] == 0 &&
+ ((char *)urb->transfer_buffer)[1] == 1))
+ goto rx_submit;
+
+ retval = dev->rcvbulk_callback(urb);
+ if (retval != 0) {
+ dev_err(&dev->intf->dev, "%s: callback retval: %d\n",
+ __func__, retval);
return;
}
- skb_put_data(skb, buf, len);
- skb->dev = dev->net;
- skb->protocol = eth_type_trans(skb, dev->net);
-
- dev->net->stats.rx_packets++;
- dev->net->stats.rx_bytes += len;
+rx_submit:
dev->confirmed_pairing = true;
- netif_rx(skb);
ipheth_rx_submit(dev, GFP_ATOMIC);
}
@@ -310,6 +411,27 @@ static int ipheth_get_macaddr(struct ipheth_device *dev)
return retval;
}
+static int ipheth_enable_ncm(struct ipheth_device *dev)
+{
+ struct usb_device *udev = dev->udev;
+ int retval;
+
+ retval = usb_control_msg(udev,
+ usb_sndctrlpipe(udev, IPHETH_CTRL_ENDP),
+ IPHETH_CMD_ENABLE_NCM, /* request */
+ 0x41, /* request type */
+ 0x00, /* value */
+ 0x02, /* index */
+ NULL,
+ 0,
+ IPHETH_CTRL_TIMEOUT);
+
+ dev_info(&dev->intf->dev, "%s: usb_control_msg: %d\n",
+ __func__, retval);
+
+ return retval;
+}
+
static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags)
{
struct usb_device *udev = dev->udev;
@@ -317,7 +439,7 @@ static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags)
usb_fill_bulk_urb(dev->rx_urb, udev,
usb_rcvbulkpipe(udev, dev->bulk_in),
- dev->rx_buf, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN,
+ dev->rx_buf, dev->rx_buf_len,
ipheth_rcvbulk_callback,
dev);
dev->rx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -365,7 +487,7 @@ static netdev_tx_t ipheth_tx(struct sk_buff *skb, struct net_device *net)
int retval;
/* Paranoid */
- if (skb->len > IPHETH_BUF_SIZE) {
+ if (skb->len > IPHETH_TX_BUF_SIZE) {
WARN(1, "%s: skb too large: %d bytes\n", __func__, skb->len);
dev->net->stats.tx_dropped++;
dev_kfree_skb_any(skb);
@@ -373,12 +495,10 @@ static netdev_tx_t ipheth_tx(struct sk_buff *skb, struct net_device *net)
}
memcpy(dev->tx_buf, skb->data, skb->len);
- if (skb->len < IPHETH_BUF_SIZE)
- memset(dev->tx_buf + skb->len, 0, IPHETH_BUF_SIZE - skb->len);
usb_fill_bulk_urb(dev->tx_urb, udev,
usb_sndbulkpipe(udev, dev->bulk_out),
- dev->tx_buf, IPHETH_BUF_SIZE,
+ dev->tx_buf, skb->len,
ipheth_sndbulk_callback,
dev);
dev->tx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -450,6 +570,8 @@ static int ipheth_probe(struct usb_interface *intf,
dev->net = netdev;
dev->intf = intf;
dev->confirmed_pairing = false;
+ dev->rx_buf_len = IPHETH_RX_BUF_SIZE_LEGACY;
+ dev->rcvbulk_callback = ipheth_rcvbulk_callback_legacy;
/* Set up endpoints */
hintf = usb_altnum_to_altsetting(intf, IPHETH_ALT_INTFNUM);
if (hintf == NULL) {
@@ -481,6 +603,12 @@ static int ipheth_probe(struct usb_interface *intf,
if (retval)
goto err_get_macaddr;
+ retval = ipheth_enable_ncm(dev);
+ if (!retval) {
+ dev->rx_buf_len = IPHETH_RX_BUF_SIZE_NCM;
+ dev->rcvbulk_callback = ipheth_rcvbulk_callback_ncm;
+ }
+
INIT_DELAYED_WORK(&dev->carrier_work, ipheth_carrier_check_work);
retval = ipheth_alloc_urbs(dev);
@@ -510,8 +638,8 @@ err_register_netdev:
ipheth_free_urbs(dev);
err_alloc_urbs:
err_get_macaddr:
-err_alloc_ctrl_buf:
kfree(dev->ctrl_buf);
+err_alloc_ctrl_buf:
err_endpoints:
free_netdev(netdev);
return retval;
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index c458c030fadf..59cde06aa7f6 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -4224,8 +4224,6 @@ static void lan78xx_disconnect(struct usb_interface *intf)
if (!dev)
return;
- set_bit(EVENT_DEV_DISCONNECT, &dev->flags);
-
netif_napi_del(&dev->napi);
udev = interface_to_usbdev(intf);
@@ -4233,6 +4231,8 @@ static void lan78xx_disconnect(struct usb_interface *intf)
unregister_netdev(net);
+ timer_shutdown_sync(&dev->stat_monitor);
+ set_bit(EVENT_DEV_DISCONNECT, &dev->flags);
cancel_delayed_work_sync(&dev->wq);
phydev = net->phydev;
@@ -4247,9 +4247,6 @@ static void lan78xx_disconnect(struct usb_interface *intf)
usb_scuttle_anchored_urbs(&dev->deferred);
- if (timer_pending(&dev->stat_monitor))
- del_timer_sync(&dev->stat_monitor);
-
lan78xx_unbind(dev, intf);
lan78xx_free_tx_resources(dev);
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 2e7c7b0cdc54..344af3c5c836 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -1423,10 +1423,12 @@ static const struct usb_device_id products[] = {
{QMI_QUIRK_SET_DTR(0x2c7c, 0x0191, 4)}, /* Quectel EG91 */
{QMI_QUIRK_SET_DTR(0x2c7c, 0x0195, 4)}, /* Quectel EG95 */
{QMI_FIXED_INTF(0x2c7c, 0x0296, 4)}, /* Quectel BG96 */
+ {QMI_QUIRK_SET_DTR(0x2c7c, 0x030e, 4)}, /* Quectel EM05GV2 */
{QMI_QUIRK_SET_DTR(0x2cb7, 0x0104, 4)}, /* Fibocom NL678 series */
{QMI_FIXED_INTF(0x0489, 0xe0b4, 0)}, /* Foxconn T77W968 LTE */
{QMI_FIXED_INTF(0x0489, 0xe0b5, 0)}, /* Foxconn T77W968 LTE with eSIM support*/
{QMI_FIXED_INTF(0x2692, 0x9025, 4)}, /* Cellient MPL200 (rebranded Qualcomm 05c6:9025) */
+ {QMI_QUIRK_SET_DTR(0x1546, 0x1312, 4)}, /* u-blox LARA-R6 01B */
{QMI_QUIRK_SET_DTR(0x1546, 0x1342, 4)}, /* u-blox LARA-L6 */
/* 4. Gobi 1000 devices */
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 0999a58ca9d2..0738baa5b82e 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -27,6 +27,7 @@
#include <linux/firmware.h>
#include <crypto/hash.h>
#include <linux/usb/r8152.h>
+#include <net/gso.h>
/* Information for net-next */
#define NETNEXT_VERSION "12"
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 283ffddda821..2d14b0d78541 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1775,6 +1775,10 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
} else if (!info->in || !info->out)
status = usbnet_get_endpoints (dev, udev);
else {
+ u8 ep_addrs[3] = {
+ info->in + USB_DIR_IN, info->out + USB_DIR_OUT, 0
+ };
+
dev->in = usb_rcvbulkpipe (xdev, info->in);
dev->out = usb_sndbulkpipe (xdev, info->out);
if (!(info->flags & FLAG_NO_SETINT))
@@ -1784,6 +1788,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
else
status = 0;
+ if (status == 0 && !usb_check_bulk_endpoints(udev, ep_addrs))
+ status = -EINVAL;
}
if (status >= 0 && dev->status)
status = init_status (dev, udev);
diff --git a/drivers/net/usb/zaurus.c b/drivers/net/usb/zaurus.c
index 7984f2157d22..df3617c4c44e 100644
--- a/drivers/net/usb/zaurus.c
+++ b/drivers/net/usb/zaurus.c
@@ -289,11 +289,25 @@ static const struct usb_device_id products [] = {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
+ .idProduct = 0x8005, /* A-300 */
+ ZAURUS_FAKE_INTERFACE,
+ .driver_info = (unsigned long)&bogus_mdlm_info,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
.idProduct = 0x8006, /* B-500/SL-5600 */
ZAURUS_MASTER_INTERFACE,
.driver_info = ZAURUS_PXA_INFO,
}, {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8006, /* B-500/SL-5600 */
+ ZAURUS_FAKE_INTERFACE,
+ .driver_info = (unsigned long)&bogus_mdlm_info,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
.idProduct = 0x8007, /* C-700 */
@@ -301,6 +315,13 @@ static const struct usb_device_id products [] = {
.driver_info = ZAURUS_PXA_INFO,
}, {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8007, /* C-700 */
+ ZAURUS_FAKE_INTERFACE,
+ .driver_info = (unsigned long)&bogus_mdlm_info,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
.idProduct = 0x9031, /* C-750 C-760 */
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index dce9f9d63e04..ef8eacb596f7 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -176,12 +176,27 @@ static int veth_get_sset_count(struct net_device *dev, int sset)
}
}
+static void veth_get_page_pool_stats(struct net_device *dev, u64 *data)
+{
+#ifdef CONFIG_PAGE_POOL_STATS
+ struct veth_priv *priv = netdev_priv(dev);
+ struct page_pool_stats pp_stats = {};
+ int i;
+
+ for (i = 0; i < dev->real_num_rx_queues; i++) {
+ if (!priv->rq[i].page_pool)
+ continue;
+ page_pool_get_stats(priv->rq[i].page_pool, &pp_stats);
+ }
+ page_pool_ethtool_stats_get(data, &pp_stats);
+#endif /* CONFIG_PAGE_POOL_STATS */
+}
+
static void veth_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats, u64 *data)
{
struct veth_priv *rcv_priv, *priv = netdev_priv(dev);
struct net_device *peer = rtnl_dereference(priv->peer);
- struct page_pool_stats pp_stats = {};
int i, j, idx, pp_idx;
data[0] = peer ? peer->ifindex : 0;
@@ -225,12 +240,7 @@ static void veth_get_ethtool_stats(struct net_device *dev,
}
page_pool_stats:
- for (i = 0; i < dev->real_num_rx_queues; i++) {
- if (!priv->rq[i].page_pool)
- continue;
- page_pool_get_stats(priv->rq[i].page_pool, &pp_stats);
- }
- page_pool_ethtool_stats_get(&data[pp_idx], &pp_stats);
+ veth_get_page_pool_stats(dev, &data[pp_idx]);
}
static void veth_get_channels(struct net_device *dev,
@@ -747,7 +757,7 @@ static int veth_convert_skb_to_xdp_buff(struct veth_rq *rq,
if (!page)
goto drop;
- nskb = build_skb(page_address(page), PAGE_SIZE);
+ nskb = napi_build_skb(page_address(page), PAGE_SIZE);
if (!nskb) {
page_pool_put_full_page(rq->page_pool, page, true);
goto drop;
@@ -1071,8 +1081,9 @@ static int __veth_napi_enable_range(struct net_device *dev, int start, int end)
err_xdp_ring:
for (i--; i >= start; i--)
ptr_ring_cleanup(&priv->rq[i].xdp_ring, veth_ptr_free);
+ i = end;
err_page_pool:
- for (i = start; i < end; i++) {
+ for (i--; i >= start; i--) {
page_pool_destroy(priv->rq[i].page_pool);
priv->rq[i].page_pool = NULL;
}
@@ -1850,10 +1861,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
nla_peer = data[VETH_INFO_PEER];
ifmp = nla_data(nla_peer);
- err = rtnl_nla_parse_ifla(peer_tb,
- nla_data(nla_peer) + sizeof(struct ifinfomsg),
- nla_len(nla_peer) - sizeof(struct ifinfomsg),
- NULL);
+ err = rtnl_nla_parse_ifinfomsg(peer_tb, nla_peer, extack);
if (err < 0)
return err;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 486b5849033d..8e9f4cfe941f 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -445,6 +445,22 @@ static unsigned int mergeable_ctx_to_truesize(void *mrg_ctx)
return (unsigned long)mrg_ctx & ((1 << MRG_CTX_HEADER_SHIFT) - 1);
}
+static struct sk_buff *virtnet_build_skb(void *buf, unsigned int buflen,
+ unsigned int headroom,
+ unsigned int len)
+{
+ struct sk_buff *skb;
+
+ skb = build_skb(buf, buflen);
+ if (unlikely(!skb))
+ return NULL;
+
+ skb_reserve(skb, headroom);
+ skb_put(skb, len);
+
+ return skb;
+}
+
/* Called from bottom half context */
static struct sk_buff *page_to_skb(struct virtnet_info *vi,
struct receive_queue *rq,
@@ -478,13 +494,10 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
/* copy small packet so we can reuse these pages */
if (!NET_IP_ALIGN && len > GOOD_COPY_LEN && tailroom >= shinfo_size) {
- skb = build_skb(buf, truesize);
+ skb = virtnet_build_skb(buf, truesize, p - buf, len);
if (unlikely(!skb))
return NULL;
- skb_reserve(skb, p - buf);
- skb_put(skb, len);
-
page = (struct page *)page->private;
if (page)
give_pages(rq, page);
@@ -791,6 +804,75 @@ out:
return ret;
}
+static void put_xdp_frags(struct xdp_buff *xdp)
+{
+ struct skb_shared_info *shinfo;
+ struct page *xdp_page;
+ int i;
+
+ if (xdp_buff_has_frags(xdp)) {
+ shinfo = xdp_get_shared_info_from_buff(xdp);
+ for (i = 0; i < shinfo->nr_frags; i++) {
+ xdp_page = skb_frag_page(&shinfo->frags[i]);
+ put_page(xdp_page);
+ }
+ }
+}
+
+static int virtnet_xdp_handler(struct bpf_prog *xdp_prog, struct xdp_buff *xdp,
+ struct net_device *dev,
+ unsigned int *xdp_xmit,
+ struct virtnet_rq_stats *stats)
+{
+ struct xdp_frame *xdpf;
+ int err;
+ u32 act;
+
+ act = bpf_prog_run_xdp(xdp_prog, xdp);
+ stats->xdp_packets++;
+
+ switch (act) {
+ case XDP_PASS:
+ return act;
+
+ case XDP_TX:
+ stats->xdp_tx++;
+ xdpf = xdp_convert_buff_to_frame(xdp);
+ if (unlikely(!xdpf)) {
+ netdev_dbg(dev, "convert buff to frame failed for xdp\n");
+ return XDP_DROP;
+ }
+
+ err = virtnet_xdp_xmit(dev, 1, &xdpf, 0);
+ if (unlikely(!err)) {
+ xdp_return_frame_rx_napi(xdpf);
+ } else if (unlikely(err < 0)) {
+ trace_xdp_exception(dev, xdp_prog, act);
+ return XDP_DROP;
+ }
+ *xdp_xmit |= VIRTIO_XDP_TX;
+ return act;
+
+ case XDP_REDIRECT:
+ stats->xdp_redirects++;
+ err = xdp_do_redirect(dev, xdp, xdp_prog);
+ if (err)
+ return XDP_DROP;
+
+ *xdp_xmit |= VIRTIO_XDP_REDIR;
+ return act;
+
+ default:
+ bpf_warn_invalid_xdp_action(dev, xdp_prog, act);
+ fallthrough;
+ case XDP_ABORTED:
+ trace_xdp_exception(dev, xdp_prog, act);
+ fallthrough;
+ case XDP_DROP:
+ return XDP_DROP;
+ }
+}
+
static unsigned int virtnet_get_headroom(struct virtnet_info *vi)
{
return vi->xdp_enabled ? VIRTIO_XDP_HEADROOM : 0;
@@ -864,134 +946,103 @@ err_buf:
return NULL;
}
-static struct sk_buff *receive_small(struct net_device *dev,
- struct virtnet_info *vi,
- struct receive_queue *rq,
- void *buf, void *ctx,
- unsigned int len,
- unsigned int *xdp_xmit,
- struct virtnet_rq_stats *stats)
+static struct sk_buff *receive_small_build_skb(struct virtnet_info *vi,
+ unsigned int xdp_headroom,
+ void *buf,
+ unsigned int len)
{
+ unsigned int header_offset;
+ unsigned int headroom;
+ unsigned int buflen;
struct sk_buff *skb;
- struct bpf_prog *xdp_prog;
- unsigned int xdp_headroom = (unsigned long)ctx;
+
+ header_offset = VIRTNET_RX_PAD + xdp_headroom;
+ headroom = vi->hdr_len + header_offset;
+ buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) +
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
+ skb = virtnet_build_skb(buf, buflen, headroom, len);
+ if (unlikely(!skb))
+ return NULL;
+
+ buf += header_offset;
+ memcpy(skb_vnet_hdr(skb), buf, vi->hdr_len);
+
+ return skb;
+}
+
+static struct sk_buff *receive_small_xdp(struct net_device *dev,
+ struct virtnet_info *vi,
+ struct receive_queue *rq,
+ struct bpf_prog *xdp_prog,
+ void *buf,
+ unsigned int xdp_headroom,
+ unsigned int len,
+ unsigned int *xdp_xmit,
+ struct virtnet_rq_stats *stats)
+{
unsigned int header_offset = VIRTNET_RX_PAD + xdp_headroom;
unsigned int headroom = vi->hdr_len + header_offset;
- unsigned int buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) +
- SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+ struct virtio_net_hdr_mrg_rxbuf *hdr = buf + header_offset;
struct page *page = virt_to_head_page(buf);
- unsigned int delta = 0;
struct page *xdp_page;
- int err;
+ unsigned int buflen;
+ struct xdp_buff xdp;
+ struct sk_buff *skb;
unsigned int metasize = 0;
+ u32 act;
- len -= vi->hdr_len;
- stats->bytes += len;
+ if (unlikely(hdr->hdr.gso_type))
+ goto err_xdp;
- if (unlikely(len > GOOD_PACKET_LEN)) {
- pr_debug("%s: rx error: len %u exceeds max size %d\n",
- dev->name, len, GOOD_PACKET_LEN);
- dev->stats.rx_length_errors++;
- goto err;
- }
+ buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) +
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
+ if (unlikely(xdp_headroom < virtnet_get_headroom(vi))) {
+ int offset = buf - page_address(page) + header_offset;
+ unsigned int tlen = len + vi->hdr_len;
+ int num_buf = 1;
+
+ xdp_headroom = virtnet_get_headroom(vi);
+ header_offset = VIRTNET_RX_PAD + xdp_headroom;
+ headroom = vi->hdr_len + header_offset;
+ buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) +
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+ xdp_page = xdp_linearize_page(rq, &num_buf, page,
+ offset, header_offset,
+ &tlen);
+ if (!xdp_page)
+ goto err_xdp;
- if (likely(!vi->xdp_enabled)) {
- xdp_prog = NULL;
- goto skip_xdp;
+ buf = page_address(xdp_page);
+ put_page(page);
+ page = xdp_page;
}
- rcu_read_lock();
- xdp_prog = rcu_dereference(rq->xdp_prog);
- if (xdp_prog) {
- struct virtio_net_hdr_mrg_rxbuf *hdr = buf + header_offset;
- struct xdp_frame *xdpf;
- struct xdp_buff xdp;
- void *orig_data;
- u32 act;
+ xdp_init_buff(&xdp, buflen, &rq->xdp_rxq);
+ xdp_prepare_buff(&xdp, buf + VIRTNET_RX_PAD + vi->hdr_len,
+ xdp_headroom, len, true);
- if (unlikely(hdr->hdr.gso_type))
- goto err_xdp;
+ act = virtnet_xdp_handler(xdp_prog, &xdp, dev, xdp_xmit, stats);
- if (unlikely(xdp_headroom < virtnet_get_headroom(vi))) {
- int offset = buf - page_address(page) + header_offset;
- unsigned int tlen = len + vi->hdr_len;
- int num_buf = 1;
-
- xdp_headroom = virtnet_get_headroom(vi);
- header_offset = VIRTNET_RX_PAD + xdp_headroom;
- headroom = vi->hdr_len + header_offset;
- buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) +
- SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
- xdp_page = xdp_linearize_page(rq, &num_buf, page,
- offset, header_offset,
- &tlen);
- if (!xdp_page)
- goto err_xdp;
-
- buf = page_address(xdp_page);
- put_page(page);
- page = xdp_page;
- }
+ switch (act) {
+ case XDP_PASS:
+ /* Recalculate length in case bpf program changed it */
+ len = xdp.data_end - xdp.data;
+ metasize = xdp.data - xdp.data_meta;
+ break;
- xdp_init_buff(&xdp, buflen, &rq->xdp_rxq);
- xdp_prepare_buff(&xdp, buf + VIRTNET_RX_PAD + vi->hdr_len,
- xdp_headroom, len, true);
- orig_data = xdp.data;
- act = bpf_prog_run_xdp(xdp_prog, &xdp);
- stats->xdp_packets++;
-
- switch (act) {
- case XDP_PASS:
- /* Recalculate length in case bpf program changed it */
- delta = orig_data - xdp.data;
- len = xdp.data_end - xdp.data;
- metasize = xdp.data - xdp.data_meta;
- break;
- case XDP_TX:
- stats->xdp_tx++;
- xdpf = xdp_convert_buff_to_frame(&xdp);
- if (unlikely(!xdpf))
- goto err_xdp;
- err = virtnet_xdp_xmit(dev, 1, &xdpf, 0);
- if (unlikely(!err)) {
- xdp_return_frame_rx_napi(xdpf);
- } else if (unlikely(err < 0)) {
- trace_xdp_exception(vi->dev, xdp_prog, act);
- goto err_xdp;
- }
- *xdp_xmit |= VIRTIO_XDP_TX;
- rcu_read_unlock();
- goto xdp_xmit;
- case XDP_REDIRECT:
- stats->xdp_redirects++;
- err = xdp_do_redirect(dev, &xdp, xdp_prog);
- if (err)
- goto err_xdp;
- *xdp_xmit |= VIRTIO_XDP_REDIR;
- rcu_read_unlock();
- goto xdp_xmit;
- default:
- bpf_warn_invalid_xdp_action(vi->dev, xdp_prog, act);
- fallthrough;
- case XDP_ABORTED:
- trace_xdp_exception(vi->dev, xdp_prog, act);
- goto err_xdp;
- case XDP_DROP:
- goto err_xdp;
- }
+ case XDP_TX:
+ case XDP_REDIRECT:
+ goto xdp_xmit;
+
+ default:
+ goto err_xdp;
}
- rcu_read_unlock();
-skip_xdp:
- skb = build_skb(buf, buflen);
- if (!skb)
+ skb = virtnet_build_skb(buf, buflen, xdp.data - buf, len);
+ if (unlikely(!skb))
goto err;
- skb_reserve(skb, headroom - delta);
- skb_put(skb, len);
- if (!xdp_prog) {
- buf += header_offset;
- memcpy(skb_vnet_hdr(skb), buf, vi->hdr_len);
- } /* keep zeroed vnet hdr since XDP is loaded */
if (metasize)
skb_metadata_set(skb, metasize);
@@ -999,7 +1050,6 @@ skip_xdp:
return skb;
err_xdp:
- rcu_read_unlock();
stats->xdp_drops++;
err:
stats->drops++;
@@ -1008,6 +1058,53 @@ xdp_xmit:
return NULL;
}
+static struct sk_buff *receive_small(struct net_device *dev,
+ struct virtnet_info *vi,
+ struct receive_queue *rq,
+ void *buf, void *ctx,
+ unsigned int len,
+ unsigned int *xdp_xmit,
+ struct virtnet_rq_stats *stats)
+{
+ unsigned int xdp_headroom = (unsigned long)ctx;
+ struct page *page = virt_to_head_page(buf);
+ struct sk_buff *skb;
+
+ len -= vi->hdr_len;
+ stats->bytes += len;
+
+ if (unlikely(len > GOOD_PACKET_LEN)) {
+ pr_debug("%s: rx error: len %u exceeds max size %d\n",
+ dev->name, len, GOOD_PACKET_LEN);
+ dev->stats.rx_length_errors++;
+ goto err;
+ }
+
+ if (unlikely(vi->xdp_enabled)) {
+ struct bpf_prog *xdp_prog;
+
+ rcu_read_lock();
+ xdp_prog = rcu_dereference(rq->xdp_prog);
+ if (xdp_prog) {
+ skb = receive_small_xdp(dev, vi, rq, xdp_prog, buf,
+ xdp_headroom, len, xdp_xmit,
+ stats);
+ rcu_read_unlock();
+ return skb;
+ }
+ rcu_read_unlock();
+ }
+
+ skb = receive_small_build_skb(vi, xdp_headroom, buf, len);
+ if (likely(skb))
+ return skb;
+
+err:
+ stats->drops++;
+ put_page(page);
+ return NULL;
+}
+
static struct sk_buff *receive_big(struct net_device *dev,
struct virtnet_info *vi,
struct receive_queue *rq,
@@ -1031,6 +1128,28 @@ err:
return NULL;
}
+static void mergeable_buf_free(struct receive_queue *rq, int num_buf,
+ struct net_device *dev,
+ struct virtnet_rq_stats *stats)
+{
+ struct page *page;
+ void *buf;
+ int len;
+
+ while (num_buf-- > 1) {
+ buf = virtqueue_get_buf(rq->vq, &len);
+ if (unlikely(!buf)) {
+ pr_debug("%s: rx error: %d buffers missing\n",
+ dev->name, num_buf);
+ dev->stats.rx_length_errors++;
+ break;
+ }
+ stats->bytes += len;
+ page = virt_to_head_page(buf);
+ put_page(page);
+ }
+}
+
/* Why not use xdp_build_skb_from_frame() ?
* XDP core assumes that xdp frags are PAGE_SIZE in length, while in
* virtio-net there are 2 points that do not match its requirements:
@@ -1132,7 +1251,7 @@ static int virtnet_build_xdp_buff_mrg(struct net_device *dev,
dev->name, *num_buf,
virtio16_to_cpu(vi->vdev, hdr->num_buffers));
dev->stats.rx_length_errors++;
- return -EINVAL;
+ goto err;
}
stats->bytes += len;
@@ -1151,13 +1270,11 @@ static int virtnet_build_xdp_buff_mrg(struct net_device *dev,
pr_debug("%s: rx error: len %u exceeds truesize %lu\n",
dev->name, len, (unsigned long)(truesize - room));
dev->stats.rx_length_errors++;
- return -EINVAL;
+ goto err;
}
frag = &shinfo->frags[shinfo->nr_frags++];
- __skb_frag_set_page(frag, page);
- skb_frag_off_set(frag, offset);
- skb_frag_size_set(frag, len);
+ skb_frag_fill_page_desc(frag, page, offset, len);
if (page_is_pfmemalloc(page))
xdp_buff_set_frag_pfmemalloc(xdp);
@@ -1166,6 +1283,144 @@ static int virtnet_build_xdp_buff_mrg(struct net_device *dev,
*xdp_frags_truesize = xdp_frags_truesz;
return 0;
+
+err:
+ put_xdp_frags(xdp);
+ return -EINVAL;
+}
+
+static void *mergeable_xdp_get_buf(struct virtnet_info *vi,
+ struct receive_queue *rq,
+ struct bpf_prog *xdp_prog,
+ void *ctx,
+ unsigned int *frame_sz,
+ int *num_buf,
+ struct page **page,
+ int offset,
+ unsigned int *len,
+ struct virtio_net_hdr_mrg_rxbuf *hdr)
+{
+ unsigned int truesize = mergeable_ctx_to_truesize(ctx);
+ unsigned int headroom = mergeable_ctx_to_headroom(ctx);
+ struct page *xdp_page;
+ unsigned int xdp_room;
+
+ /* Transient failure which in theory could occur if
+ * in-flight packets from before XDP was enabled reach
+ * the receive path after XDP is loaded.
+ */
+ if (unlikely(hdr->hdr.gso_type))
+ return NULL;
+
+ /* Now XDP core assumes frag size is PAGE_SIZE, but buffers
+ * with headroom may add hole in truesize, which
+ * make their length exceed PAGE_SIZE. So we disabled the
+ * hole mechanism for xdp. See add_recvbuf_mergeable().
+ */
+ *frame_sz = truesize;
+
+ if (likely(headroom >= virtnet_get_headroom(vi) &&
+ (*num_buf == 1 || xdp_prog->aux->xdp_has_frags))) {
+ return page_address(*page) + offset;
+ }
+
+ /* This happens when headroom is not enough because
+ * of the buffer was prefilled before XDP is set.
+ * This should only happen for the first several packets.
+ * In fact, vq reset can be used here to help us clean up
+ * the prefilled buffers, but many existing devices do not
+ * support it, and we don't want to bother users who are
+ * using xdp normally.
+ */
+ if (!xdp_prog->aux->xdp_has_frags) {
+ /* linearize data for XDP */
+ xdp_page = xdp_linearize_page(rq, num_buf,
+ *page, offset,
+ VIRTIO_XDP_HEADROOM,
+ len);
+ if (!xdp_page)
+ return NULL;
+ } else {
+ xdp_room = SKB_DATA_ALIGN(VIRTIO_XDP_HEADROOM +
+ sizeof(struct skb_shared_info));
+ if (*len + xdp_room > PAGE_SIZE)
+ return NULL;
+
+ xdp_page = alloc_page(GFP_ATOMIC);
+ if (!xdp_page)
+ return NULL;
+
+ memcpy(page_address(xdp_page) + VIRTIO_XDP_HEADROOM,
+ page_address(*page) + offset, *len);
+ }
+
+ *frame_sz = PAGE_SIZE;
+
+ put_page(*page);
+
+ *page = xdp_page;
+
+ return page_address(*page) + VIRTIO_XDP_HEADROOM;
+}
+
+static struct sk_buff *receive_mergeable_xdp(struct net_device *dev,
+ struct virtnet_info *vi,
+ struct receive_queue *rq,
+ struct bpf_prog *xdp_prog,
+ void *buf,
+ void *ctx,
+ unsigned int len,
+ unsigned int *xdp_xmit,
+ struct virtnet_rq_stats *stats)
+{
+ struct virtio_net_hdr_mrg_rxbuf *hdr = buf;
+ int num_buf = virtio16_to_cpu(vi->vdev, hdr->num_buffers);
+ struct page *page = virt_to_head_page(buf);
+ int offset = buf - page_address(page);
+ unsigned int xdp_frags_truesz = 0;
+ struct sk_buff *head_skb;
+ unsigned int frame_sz;
+ struct xdp_buff xdp;
+ void *data;
+ u32 act;
+ int err;
+
+ data = mergeable_xdp_get_buf(vi, rq, xdp_prog, ctx, &frame_sz, &num_buf, &page,
+ offset, &len, hdr);
+ if (unlikely(!data))
+ goto err_xdp;
+
+ err = virtnet_build_xdp_buff_mrg(dev, vi, rq, &xdp, data, len, frame_sz,
+ &num_buf, &xdp_frags_truesz, stats);
+ if (unlikely(err))
+ goto err_xdp;
+
+ act = virtnet_xdp_handler(xdp_prog, &xdp, dev, xdp_xmit, stats);
+
+ switch (act) {
+ case XDP_PASS:
+ head_skb = build_skb_from_xdp_buff(dev, vi, &xdp, xdp_frags_truesz);
+ if (unlikely(!head_skb))
+ break;
+ return head_skb;
+
+ case XDP_TX:
+ case XDP_REDIRECT:
+ return NULL;
+
+ default:
+ break;
+ }
+
+ put_xdp_frags(&xdp);
+
+err_xdp:
+ put_page(page);
+ mergeable_buf_free(rq, num_buf, dev, stats);
+
+ stats->xdp_drops++;
+ stats->drops++;
+ return NULL;
}
static struct sk_buff *receive_mergeable(struct net_device *dev,
@@ -1182,13 +1437,10 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
struct page *page = virt_to_head_page(buf);
int offset = buf - page_address(page);
struct sk_buff *head_skb, *curr_skb;
- struct bpf_prog *xdp_prog;
unsigned int truesize = mergeable_ctx_to_truesize(ctx);
unsigned int headroom = mergeable_ctx_to_headroom(ctx);
unsigned int tailroom = headroom ? sizeof(struct skb_shared_info) : 0;
unsigned int room = SKB_DATA_ALIGN(headroom + tailroom);
- unsigned int frame_sz, xdp_room;
- int err;
head_skb = NULL;
stats->bytes += len - vi->hdr_len;
@@ -1200,149 +1452,20 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
goto err_skb;
}
- if (likely(!vi->xdp_enabled)) {
- xdp_prog = NULL;
- goto skip_xdp;
- }
-
- rcu_read_lock();
- xdp_prog = rcu_dereference(rq->xdp_prog);
- if (xdp_prog) {
- unsigned int xdp_frags_truesz = 0;
- struct skb_shared_info *shinfo;
- struct xdp_frame *xdpf;
- struct page *xdp_page;
- struct xdp_buff xdp;
- void *data;
- u32 act;
- int i;
-
- /* Transient failure which in theory could occur if
- * in-flight packets from before XDP was enabled reach
- * the receive path after XDP is loaded.
- */
- if (unlikely(hdr->hdr.gso_type))
- goto err_xdp;
-
- /* Now XDP core assumes frag size is PAGE_SIZE, but buffers
- * with headroom may add hole in truesize, which
- * make their length exceed PAGE_SIZE. So we disabled the
- * hole mechanism for xdp. See add_recvbuf_mergeable().
- */
- frame_sz = truesize;
-
- /* This happens when headroom is not enough because
- * of the buffer was prefilled before XDP is set.
- * This should only happen for the first several packets.
- * In fact, vq reset can be used here to help us clean up
- * the prefilled buffers, but many existing devices do not
- * support it, and we don't want to bother users who are
- * using xdp normally.
- */
- if (!xdp_prog->aux->xdp_has_frags &&
- (num_buf > 1 || headroom < virtnet_get_headroom(vi))) {
- /* linearize data for XDP */
- xdp_page = xdp_linearize_page(rq, &num_buf,
- page, offset,
- VIRTIO_XDP_HEADROOM,
- &len);
- frame_sz = PAGE_SIZE;
-
- if (!xdp_page)
- goto err_xdp;
- offset = VIRTIO_XDP_HEADROOM;
- } else if (unlikely(headroom < virtnet_get_headroom(vi))) {
- xdp_room = SKB_DATA_ALIGN(VIRTIO_XDP_HEADROOM +
- sizeof(struct skb_shared_info));
- if (len + xdp_room > PAGE_SIZE)
- goto err_xdp;
-
- xdp_page = alloc_page(GFP_ATOMIC);
- if (!xdp_page)
- goto err_xdp;
-
- memcpy(page_address(xdp_page) + VIRTIO_XDP_HEADROOM,
- page_address(page) + offset, len);
- frame_sz = PAGE_SIZE;
- offset = VIRTIO_XDP_HEADROOM;
- } else {
- xdp_page = page;
- }
+ if (unlikely(vi->xdp_enabled)) {
+ struct bpf_prog *xdp_prog;
- data = page_address(xdp_page) + offset;
- err = virtnet_build_xdp_buff_mrg(dev, vi, rq, &xdp, data, len, frame_sz,
- &num_buf, &xdp_frags_truesz, stats);
- if (unlikely(err))
- goto err_xdp_frags;
-
- act = bpf_prog_run_xdp(xdp_prog, &xdp);
- stats->xdp_packets++;
-
- switch (act) {
- case XDP_PASS:
- head_skb = build_skb_from_xdp_buff(dev, vi, &xdp, xdp_frags_truesz);
- if (unlikely(!head_skb))
- goto err_xdp_frags;
-
- if (unlikely(xdp_page != page))
- put_page(page);
+ rcu_read_lock();
+ xdp_prog = rcu_dereference(rq->xdp_prog);
+ if (xdp_prog) {
+ head_skb = receive_mergeable_xdp(dev, vi, rq, xdp_prog, buf, ctx,
+ len, xdp_xmit, stats);
rcu_read_unlock();
return head_skb;
- case XDP_TX:
- stats->xdp_tx++;
- xdpf = xdp_convert_buff_to_frame(&xdp);
- if (unlikely(!xdpf)) {
- netdev_dbg(dev, "convert buff to frame failed for xdp\n");
- goto err_xdp_frags;
- }
- err = virtnet_xdp_xmit(dev, 1, &xdpf, 0);
- if (unlikely(!err)) {
- xdp_return_frame_rx_napi(xdpf);
- } else if (unlikely(err < 0)) {
- trace_xdp_exception(vi->dev, xdp_prog, act);
- goto err_xdp_frags;
- }
- *xdp_xmit |= VIRTIO_XDP_TX;
- if (unlikely(xdp_page != page))
- put_page(page);
- rcu_read_unlock();
- goto xdp_xmit;
- case XDP_REDIRECT:
- stats->xdp_redirects++;
- err = xdp_do_redirect(dev, &xdp, xdp_prog);
- if (err)
- goto err_xdp_frags;
- *xdp_xmit |= VIRTIO_XDP_REDIR;
- if (unlikely(xdp_page != page))
- put_page(page);
- rcu_read_unlock();
- goto xdp_xmit;
- default:
- bpf_warn_invalid_xdp_action(vi->dev, xdp_prog, act);
- fallthrough;
- case XDP_ABORTED:
- trace_xdp_exception(vi->dev, xdp_prog, act);
- fallthrough;
- case XDP_DROP:
- goto err_xdp_frags;
}
-err_xdp_frags:
- if (unlikely(xdp_page != page))
- __free_pages(xdp_page, 0);
-
- if (xdp_buff_has_frags(&xdp)) {
- shinfo = xdp_get_shared_info_from_buff(&xdp);
- for (i = 0; i < shinfo->nr_frags; i++) {
- xdp_page = skb_frag_page(&shinfo->frags[i]);
- put_page(xdp_page);
- }
- }
-
- goto err_xdp;
+ rcu_read_unlock();
}
- rcu_read_unlock();
-skip_xdp:
head_skb = page_to_skb(vi, rq, page, offset, len, truesize, headroom);
curr_skb = head_skb;
@@ -1408,27 +1531,13 @@ skip_xdp:
ewma_pkt_len_add(&rq->mrg_avg_pkt_len, head_skb->len);
return head_skb;
-err_xdp:
- rcu_read_unlock();
- stats->xdp_drops++;
err_skb:
put_page(page);
- while (num_buf-- > 1) {
- buf = virtqueue_get_buf(rq->vq, &len);
- if (unlikely(!buf)) {
- pr_debug("%s: rx error: %d buffers missing\n",
- dev->name, num_buf);
- dev->stats.rx_length_errors++;
- break;
- }
- stats->bytes += len;
- page = virt_to_head_page(buf);
- put_page(page);
- }
+ mergeable_buf_free(rq, num_buf, dev, stats);
+
err_buf:
stats->drops++;
dev_kfree_skb(head_skb);
-xdp_xmit:
return NULL;
}
@@ -2652,7 +2761,7 @@ static void virtnet_init_default_rss(struct virtnet_info *vi)
vi->ctrl->rss.indirection_table[i] = indir_val;
}
- vi->ctrl->rss.max_tx_vq = vi->curr_queue_pairs;
+ vi->ctrl->rss.max_tx_vq = vi->has_rss ? vi->curr_queue_pairs : 0;
vi->ctrl->rss.hash_key_length = vi->rss_key_size;
netdev_rss_key_fill(vi->ctrl->rss.key, vi->rss_key_size);
@@ -4122,6 +4231,8 @@ static int virtnet_probe(struct virtio_device *vdev)
virtio_device_ready(vdev);
+ _virtnet_set_queues(vi, vi->curr_queue_pairs);
+
/* a random MAC address has been assigned, notify the device.
* We don't fail probe if VIRTIO_NET_F_CTRL_MAC_ADDR is not there
* because many devices work fine without getting MAC explicitly
@@ -4148,8 +4259,6 @@ static int virtnet_probe(struct virtio_device *vdev)
goto free_unregister_netdev;
}
- virtnet_set_queues(vi, vi->curr_queue_pairs);
-
/* Assume link up if device can't report link status,
otherwise get link status from config. */
netif_carrier_off(dev);
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index f2b76ee866a4..7fa74b8b2100 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -686,9 +686,7 @@ vmxnet3_append_frag(struct sk_buff *skb, struct Vmxnet3_RxCompDesc *rcd,
BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS);
- __skb_frag_set_page(frag, rbi->page);
- skb_frag_off_set(frag, 0);
- skb_frag_size_set(frag, rcd->len);
+ skb_frag_fill_page_desc(frag, rbi->page, 0, rcd->len);
skb->data_len += rcd->len;
skb->truesize += PAGE_SIZE;
skb_shinfo(skb)->nr_frags++;
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index bdb3a76a352e..6043e63b42f9 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -664,7 +664,7 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
skb->protocol = htons(ETH_P_IPV6);
skb->dev = dev;
- rcu_read_lock_bh();
+ rcu_read_lock();
nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr);
neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop);
if (unlikely(!neigh))
@@ -672,10 +672,10 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
if (!IS_ERR(neigh)) {
sock_confirm_neigh(skb, neigh);
ret = neigh_output(neigh, skb, false);
- rcu_read_unlock_bh();
+ rcu_read_unlock();
return ret;
}
- rcu_read_unlock_bh();
+ rcu_read_unlock();
IP6_INC_STATS(dev_net(dst->dev),
ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
@@ -889,7 +889,7 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s
}
}
- rcu_read_lock_bh();
+ rcu_read_lock();
neigh = ip_neigh_for_gw(rt, skb, &is_v6gw);
if (!IS_ERR(neigh)) {
@@ -898,11 +898,11 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s
sock_confirm_neigh(skb, neigh);
/* if crossing protocols, can not use the cached header */
ret = neigh_output(neigh, skb, is_v6gw);
- rcu_read_unlock_bh();
+ rcu_read_unlock();
return ret;
}
- rcu_read_unlock_bh();
+ rcu_read_unlock();
vrf_tx_error(skb->dev, skb);
return -EINVAL;
}
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 561fe1b314f5..c9a9373733c0 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -623,6 +623,32 @@ static int vxlan_fdb_append(struct vxlan_fdb *f,
return 1;
}
+static bool vxlan_parse_gpe_proto(struct vxlanhdr *hdr, __be16 *protocol)
+{
+ struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)hdr;
+
+ /* Need to have Next Protocol set for interfaces in GPE mode. */
+ if (!gpe->np_applied)
+ return false;
+ /* "The initial version is 0. If a receiver does not support the
+ * version indicated it MUST drop the packet.
+ */
+ if (gpe->version != 0)
+ return false;
+ /* "When the O bit is set to 1, the packet is an OAM packet and OAM
+ * processing MUST occur." However, we don't implement OAM
+ * processing, thus drop the packet.
+ */
+ if (gpe->oam_flag)
+ return false;
+
+ *protocol = tun_p_to_eth_p(gpe->next_protocol);
+ if (!*protocol)
+ return false;
+
+ return true;
+}
+
static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb,
unsigned int off,
struct vxlanhdr *vh, size_t hdrlen,
@@ -649,26 +675,24 @@ static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb,
return vh;
}
-static struct sk_buff *vxlan_gro_receive(struct sock *sk,
- struct list_head *head,
- struct sk_buff *skb)
+static struct vxlanhdr *vxlan_gro_prepare_receive(struct sock *sk,
+ struct list_head *head,
+ struct sk_buff *skb,
+ struct gro_remcsum *grc)
{
- struct sk_buff *pp = NULL;
struct sk_buff *p;
struct vxlanhdr *vh, *vh2;
unsigned int hlen, off_vx;
- int flush = 1;
struct vxlan_sock *vs = rcu_dereference_sk_user_data(sk);
__be32 flags;
- struct gro_remcsum grc;
- skb_gro_remcsum_init(&grc);
+ skb_gro_remcsum_init(grc);
off_vx = skb_gro_offset(skb);
hlen = off_vx + sizeof(*vh);
vh = skb_gro_header(skb, hlen, off_vx);
if (unlikely(!vh))
- goto out;
+ return NULL;
skb_gro_postpull_rcsum(skb, vh, sizeof(struct vxlanhdr));
@@ -676,12 +700,12 @@ static struct sk_buff *vxlan_gro_receive(struct sock *sk,
if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) {
vh = vxlan_gro_remcsum(skb, off_vx, vh, sizeof(struct vxlanhdr),
- vh->vx_vni, &grc,
+ vh->vx_vni, grc,
!!(vs->flags &
VXLAN_F_REMCSUM_NOPARTIAL));
if (!vh)
- goto out;
+ return NULL;
}
skb_gro_pull(skb, sizeof(struct vxlanhdr)); /* pull vxlan header */
@@ -698,12 +722,48 @@ static struct sk_buff *vxlan_gro_receive(struct sock *sk,
}
}
- pp = call_gro_receive(eth_gro_receive, head, skb);
- flush = 0;
+ return vh;
+}
-out:
+static struct sk_buff *vxlan_gro_receive(struct sock *sk,
+ struct list_head *head,
+ struct sk_buff *skb)
+{
+ struct sk_buff *pp = NULL;
+ struct gro_remcsum grc;
+ int flush = 1;
+
+ if (vxlan_gro_prepare_receive(sk, head, skb, &grc)) {
+ pp = call_gro_receive(eth_gro_receive, head, skb);
+ flush = 0;
+ }
skb_gro_flush_final_remcsum(skb, pp, flush, &grc);
+ return pp;
+}
+
+static struct sk_buff *vxlan_gpe_gro_receive(struct sock *sk,
+ struct list_head *head,
+ struct sk_buff *skb)
+{
+ const struct packet_offload *ptype;
+ struct sk_buff *pp = NULL;
+ struct gro_remcsum grc;
+ struct vxlanhdr *vh;
+ __be16 protocol;
+ int flush = 1;
+ vh = vxlan_gro_prepare_receive(sk, head, skb, &grc);
+ if (vh) {
+ if (!vxlan_parse_gpe_proto(vh, &protocol))
+ goto out;
+ ptype = gro_find_receive_by_type(protocol);
+ if (!ptype)
+ goto out;
+ pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
+ flush = 0;
+ }
+out:
+ skb_gro_flush_final_remcsum(skb, pp, flush, &grc);
return pp;
}
@@ -715,6 +775,21 @@ static int vxlan_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
return eth_gro_complete(skb, nhoff + sizeof(struct vxlanhdr));
}
+static int vxlan_gpe_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
+{
+ struct vxlanhdr *vh = (struct vxlanhdr *)(skb->data + nhoff);
+ const struct packet_offload *ptype;
+ int err = -ENOSYS;
+ __be16 protocol;
+
+ if (!vxlan_parse_gpe_proto(vh, &protocol))
+ return err;
+ ptype = gro_find_complete_by_type(protocol);
+ if (ptype)
+ err = ptype->callbacks.gro_complete(skb, nhoff + sizeof(struct vxlanhdr));
+ return err;
+}
+
static struct vxlan_fdb *vxlan_fdb_alloc(struct vxlan_dev *vxlan, const u8 *mac,
__u16 state, __be32 src_vni,
__u16 ndm_flags)
@@ -1525,35 +1600,6 @@ out:
unparsed->vx_flags &= ~VXLAN_GBP_USED_BITS;
}
-static bool vxlan_parse_gpe_hdr(struct vxlanhdr *unparsed,
- __be16 *protocol,
- struct sk_buff *skb, u32 vxflags)
-{
- struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)unparsed;
-
- /* Need to have Next Protocol set for interfaces in GPE mode. */
- if (!gpe->np_applied)
- return false;
- /* "The initial version is 0. If a receiver does not support the
- * version indicated it MUST drop the packet.
- */
- if (gpe->version != 0)
- return false;
- /* "When the O bit is set to 1, the packet is an OAM packet and OAM
- * processing MUST occur." However, we don't implement OAM
- * processing, thus drop the packet.
- */
- if (gpe->oam_flag)
- return false;
-
- *protocol = tun_p_to_eth_p(gpe->next_protocol);
- if (!*protocol)
- return false;
-
- unparsed->vx_flags &= ~VXLAN_GPE_USED_BITS;
- return true;
-}
-
static bool vxlan_set_mac(struct vxlan_dev *vxlan,
struct vxlan_sock *vs,
struct sk_buff *skb, __be32 vni)
@@ -1655,8 +1701,9 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
* used by VXLAN extensions if explicitly requested.
*/
if (vs->flags & VXLAN_F_GPE) {
- if (!vxlan_parse_gpe_hdr(&unparsed, &protocol, skb, vs->flags))
+ if (!vxlan_parse_gpe_proto(&unparsed, &protocol))
goto drop;
+ unparsed.vx_flags &= ~VXLAN_GPE_USED_BITS;
raw_proto = true;
}
@@ -2352,7 +2399,8 @@ static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev,
#endif
/* Bypass encapsulation if the destination is local */
if (rt_flags & RTCF_LOCAL &&
- !(rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) {
+ !(rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) &&
+ vxlan->cfg.flags & VXLAN_F_LOCALBYPASS) {
struct vxlan_dev *dst_vxlan;
dst_release(dst);
@@ -2515,7 +2563,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
}
ndst = &rt->dst;
- err = skb_tunnel_check_pmtu(skb, ndst, VXLAN_HEADROOM,
+ err = skb_tunnel_check_pmtu(skb, ndst, vxlan_headroom(flags & VXLAN_F_GPE),
netif_is_any_bridge_port(dev));
if (err < 0) {
goto tx_error;
@@ -2576,7 +2624,8 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
goto out_unlock;
}
- err = skb_tunnel_check_pmtu(skb, ndst, VXLAN6_HEADROOM,
+ err = skb_tunnel_check_pmtu(skb, ndst,
+ vxlan_headroom((flags & VXLAN_F_GPE) | VXLAN_F_IPV6),
netif_is_any_bridge_port(dev));
if (err < 0) {
goto tx_error;
@@ -2988,14 +3037,12 @@ static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
struct vxlan_rdst *dst = &vxlan->default_dst;
struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
dst->remote_ifindex);
- bool use_ipv6 = !!(vxlan->cfg.flags & VXLAN_F_IPV6);
/* This check is different than dev->max_mtu, because it looks at
* the lowerdev->mtu, rather than the static dev->max_mtu
*/
if (lowerdev) {
- int max_mtu = lowerdev->mtu -
- (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
+ int max_mtu = lowerdev->mtu - vxlan_headroom(vxlan->cfg.flags);
if (new_mtu > max_mtu)
return -EINVAL;
}
@@ -3172,6 +3219,7 @@ static void vxlan_raw_setup(struct net_device *dev)
}
static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
+ [IFLA_VXLAN_UNSPEC] = { .strict_start_type = IFLA_VXLAN_LOCALBYPASS },
[IFLA_VXLAN_ID] = { .type = NLA_U32 },
[IFLA_VXLAN_GROUP] = { .len = sizeof_field(struct iphdr, daddr) },
[IFLA_VXLAN_GROUP6] = { .len = sizeof(struct in6_addr) },
@@ -3202,6 +3250,7 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
[IFLA_VXLAN_TTL_INHERIT] = { .type = NLA_FLAG },
[IFLA_VXLAN_DF] = { .type = NLA_U8 },
[IFLA_VXLAN_VNIFILTER] = { .type = NLA_U8 },
+ [IFLA_VXLAN_LOCALBYPASS] = NLA_POLICY_MAX(NLA_U8, 1),
};
static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[],
@@ -3376,8 +3425,13 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
tunnel_cfg.encap_rcv = vxlan_rcv;
tunnel_cfg.encap_err_lookup = vxlan_err_lookup;
tunnel_cfg.encap_destroy = NULL;
- tunnel_cfg.gro_receive = vxlan_gro_receive;
- tunnel_cfg.gro_complete = vxlan_gro_complete;
+ if (vs->flags & VXLAN_F_GPE) {
+ tunnel_cfg.gro_receive = vxlan_gpe_gro_receive;
+ tunnel_cfg.gro_complete = vxlan_gpe_gro_complete;
+ } else {
+ tunnel_cfg.gro_receive = vxlan_gro_receive;
+ tunnel_cfg.gro_complete = vxlan_gro_complete;
+ }
setup_udp_tunnel_sock(net, sock, &tunnel_cfg);
@@ -3641,11 +3695,11 @@ static void vxlan_config_apply(struct net_device *dev,
struct vxlan_dev *vxlan = netdev_priv(dev);
struct vxlan_rdst *dst = &vxlan->default_dst;
unsigned short needed_headroom = ETH_HLEN;
- bool use_ipv6 = !!(conf->flags & VXLAN_F_IPV6);
int max_mtu = ETH_MAX_MTU;
+ u32 flags = conf->flags;
if (!changelink) {
- if (conf->flags & VXLAN_F_GPE)
+ if (flags & VXLAN_F_GPE)
vxlan_raw_setup(dev);
else
vxlan_ether_setup(dev);
@@ -3670,8 +3724,7 @@ static void vxlan_config_apply(struct net_device *dev,
dev->needed_tailroom = lowerdev->needed_tailroom;
- max_mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM :
- VXLAN_HEADROOM);
+ max_mtu = lowerdev->mtu - vxlan_headroom(flags);
if (max_mtu < ETH_MIN_MTU)
max_mtu = ETH_MIN_MTU;
@@ -3682,10 +3735,9 @@ static void vxlan_config_apply(struct net_device *dev,
if (dev->mtu > max_mtu)
dev->mtu = max_mtu;
- if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA)
- needed_headroom += VXLAN6_HEADROOM;
- else
- needed_headroom += VXLAN_HEADROOM;
+ if (flags & VXLAN_F_COLLECT_METADATA)
+ flags |= VXLAN_F_IPV6;
+ needed_headroom += vxlan_headroom(flags);
dev->needed_headroom = needed_headroom;
memcpy(&vxlan->cfg, conf, sizeof(*conf));
@@ -4011,6 +4063,17 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
conf->flags |= VXLAN_F_UDP_ZERO_CSUM_TX;
}
+ if (data[IFLA_VXLAN_LOCALBYPASS]) {
+ err = vxlan_nl2flag(conf, data, IFLA_VXLAN_LOCALBYPASS,
+ VXLAN_F_LOCALBYPASS, changelink,
+ true, extack);
+ if (err)
+ return err;
+ } else if (!changelink) {
+ /* default to local bypass on a new device */
+ conf->flags |= VXLAN_F_LOCALBYPASS;
+ }
+
if (data[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]) {
err = vxlan_nl2flag(conf, data, IFLA_VXLAN_UDP_ZERO_CSUM6_TX,
VXLAN_F_UDP_ZERO_CSUM6_TX, changelink,
@@ -4232,6 +4295,7 @@ static size_t vxlan_get_size(const struct net_device *dev)
nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_ZERO_CSUM6_RX */
nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_TX */
nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_RX */
+ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_LOCALBYPASS */
0;
}
@@ -4308,7 +4372,9 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
nla_put_u8(skb, IFLA_VXLAN_REMCSUM_TX,
!!(vxlan->cfg.flags & VXLAN_F_REMCSUM_TX)) ||
nla_put_u8(skb, IFLA_VXLAN_REMCSUM_RX,
- !!(vxlan->cfg.flags & VXLAN_F_REMCSUM_RX)))
+ !!(vxlan->cfg.flags & VXLAN_F_REMCSUM_RX)) ||
+ nla_put_u8(skb, IFLA_VXLAN_LOCALBYPASS,
+ !!(vxlan->cfg.flags & VXLAN_F_LOCALBYPASS)))
goto nla_put_failure;
if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports))
diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
index a3de081cda5e..c3ff30ab782e 100644
--- a/drivers/net/vxlan/vxlan_vnifilter.c
+++ b/drivers/net/vxlan/vxlan_vnifilter.c
@@ -713,6 +713,12 @@ static struct vxlan_vni_node *vxlan_vni_alloc(struct vxlan_dev *vxlan,
return vninode;
}
+static void vxlan_vni_free(struct vxlan_vni_node *vninode)
+{
+ free_percpu(vninode->stats);
+ kfree(vninode);
+}
+
static int vxlan_vni_add(struct vxlan_dev *vxlan,
struct vxlan_vni_group *vg,
u32 vni, union vxlan_addr *group,
@@ -740,7 +746,7 @@ static int vxlan_vni_add(struct vxlan_dev *vxlan,
&vninode->vnode,
vxlan_vni_rht_params);
if (err) {
- kfree(vninode);
+ vxlan_vni_free(vninode);
return err;
}
@@ -763,8 +769,7 @@ static void vxlan_vni_node_rcu_free(struct rcu_head *rcu)
struct vxlan_vni_node *v;
v = container_of(rcu, struct vxlan_vni_node, rcu);
- free_percpu(v->stats);
- kfree(v);
+ vxlan_vni_free(v);
}
static int vxlan_vni_del(struct vxlan_dev *vxlan,
diff --git a/drivers/net/wireguard/allowedips.c b/drivers/net/wireguard/allowedips.c
index 5bf7822c53f1..0ba714ca5185 100644
--- a/drivers/net/wireguard/allowedips.c
+++ b/drivers/net/wireguard/allowedips.c
@@ -6,7 +6,7 @@
#include "allowedips.h"
#include "peer.h"
-enum { MAX_ALLOWEDIPS_BITS = 128 };
+enum { MAX_ALLOWEDIPS_DEPTH = 129 };
static struct kmem_cache *node_cache;
@@ -42,7 +42,7 @@ static void push_rcu(struct allowedips_node **stack,
struct allowedips_node __rcu *p, unsigned int *len)
{
if (rcu_access_pointer(p)) {
- if (WARN_ON(IS_ENABLED(DEBUG) && *len >= MAX_ALLOWEDIPS_BITS))
+ if (WARN_ON(IS_ENABLED(DEBUG) && *len >= MAX_ALLOWEDIPS_DEPTH))
return;
stack[(*len)++] = rcu_dereference_raw(p);
}
@@ -55,7 +55,7 @@ static void node_free_rcu(struct rcu_head *rcu)
static void root_free_rcu(struct rcu_head *rcu)
{
- struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_BITS] = {
+ struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_DEPTH] = {
container_of(rcu, struct allowedips_node, rcu) };
unsigned int len = 1;
@@ -68,7 +68,7 @@ static void root_free_rcu(struct rcu_head *rcu)
static void root_remove_peer_lists(struct allowedips_node *root)
{
- struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_BITS] = { root };
+ struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_DEPTH] = { root };
unsigned int len = 1;
while (len > 0 && (node = stack[--len])) {
diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c
index d58e9f818d3b..258dcc103921 100644
--- a/drivers/net/wireguard/device.c
+++ b/drivers/net/wireguard/device.c
@@ -20,6 +20,7 @@
#include <linux/icmp.h>
#include <linux/suspend.h>
#include <net/dst_metadata.h>
+#include <net/gso.h>
#include <net/icmp.h>
#include <net/rtnetlink.h>
#include <net/ip_tunnels.h>
diff --git a/drivers/net/wireguard/netlink.c b/drivers/net/wireguard/netlink.c
index 43c8c84e7ea8..6d1bd9f52d02 100644
--- a/drivers/net/wireguard/netlink.c
+++ b/drivers/net/wireguard/netlink.c
@@ -546,6 +546,7 @@ static int wg_set_device(struct sk_buff *skb, struct genl_info *info)
u8 *private_key = nla_data(info->attrs[WGDEVICE_A_PRIVATE_KEY]);
u8 public_key[NOISE_PUBLIC_KEY_LEN];
struct wg_peer *peer, *temp;
+ bool send_staged_packets;
if (!crypto_memneq(wg->static_identity.static_private,
private_key, NOISE_PUBLIC_KEY_LEN))
@@ -564,14 +565,17 @@ static int wg_set_device(struct sk_buff *skb, struct genl_info *info)
}
down_write(&wg->static_identity.lock);
- wg_noise_set_static_identity_private_key(&wg->static_identity,
- private_key);
- list_for_each_entry_safe(peer, temp, &wg->peer_list,
- peer_list) {
+ send_staged_packets = !wg->static_identity.has_identity && netif_running(wg->dev);
+ wg_noise_set_static_identity_private_key(&wg->static_identity, private_key);
+ send_staged_packets = send_staged_packets && wg->static_identity.has_identity;
+
+ wg_cookie_checker_precompute_device_keys(&wg->cookie_checker);
+ list_for_each_entry_safe(peer, temp, &wg->peer_list, peer_list) {
wg_noise_precompute_static_static(peer);
wg_noise_expire_current_peer_keypairs(peer);
+ if (send_staged_packets)
+ wg_packet_send_staged_packets(peer);
}
- wg_cookie_checker_precompute_device_keys(&wg->cookie_checker);
up_write(&wg->static_identity.lock);
}
skip_set_private_key:
diff --git a/drivers/net/wireguard/queueing.c b/drivers/net/wireguard/queueing.c
index 8084e7408c0a..26d235d15235 100644
--- a/drivers/net/wireguard/queueing.c
+++ b/drivers/net/wireguard/queueing.c
@@ -28,6 +28,7 @@ int wg_packet_queue_init(struct crypt_queue *queue, work_func_t function,
int ret;
memset(queue, 0, sizeof(*queue));
+ queue->last_cpu = -1;
ret = ptr_ring_init(&queue->ring, len, GFP_KERNEL);
if (ret)
return ret;
diff --git a/drivers/net/wireguard/queueing.h b/drivers/net/wireguard/queueing.h
index 125284b346a7..1ea4f874e367 100644
--- a/drivers/net/wireguard/queueing.h
+++ b/drivers/net/wireguard/queueing.h
@@ -117,20 +117,17 @@ static inline int wg_cpumask_choose_online(int *stored_cpu, unsigned int id)
return cpu;
}
-/* This function is racy, in the sense that next is unlocked, so it could return
- * the same CPU twice. A race-free version of this would be to instead store an
- * atomic sequence number, do an increment-and-return, and then iterate through
- * every possible CPU until we get to that index -- choose_cpu. However that's
- * a bit slower, and it doesn't seem like this potential race actually
- * introduces any performance loss, so we live with it.
+/* This function is racy, in the sense that it's called while last_cpu is
+ * unlocked, so it could return the same CPU twice. Adding locking or using
+ * atomic sequence numbers is slower though, and the consequences of racing are
+ * harmless, so live with it.
*/
-static inline int wg_cpumask_next_online(int *next)
+static inline int wg_cpumask_next_online(int *last_cpu)
{
- int cpu = *next;
-
- while (unlikely(!cpumask_test_cpu(cpu, cpu_online_mask)))
- cpu = cpumask_next(cpu, cpu_online_mask) % nr_cpumask_bits;
- *next = cpumask_next(cpu, cpu_online_mask) % nr_cpumask_bits;
+ int cpu = cpumask_next(*last_cpu, cpu_online_mask);
+ if (cpu >= nr_cpu_ids)
+ cpu = cpumask_first(cpu_online_mask);
+ *last_cpu = cpu;
return cpu;
}
@@ -159,7 +156,7 @@ static inline void wg_prev_queue_drop_peeked(struct prev_queue *queue)
static inline int wg_queue_enqueue_per_device_and_peer(
struct crypt_queue *device_queue, struct prev_queue *peer_queue,
- struct sk_buff *skb, struct workqueue_struct *wq, int *next_cpu)
+ struct sk_buff *skb, struct workqueue_struct *wq)
{
int cpu;
@@ -173,7 +170,7 @@ static inline int wg_queue_enqueue_per_device_and_peer(
/* Then we queue it up in the device queue, which consumes the
* packet as soon as it can.
*/
- cpu = wg_cpumask_next_online(next_cpu);
+ cpu = wg_cpumask_next_online(&device_queue->last_cpu);
if (unlikely(ptr_ring_produce_bh(&device_queue->ring, skb)))
return -EPIPE;
queue_work_on(cpu, wq, &per_cpu_ptr(device_queue->worker, cpu)->work);
diff --git a/drivers/net/wireguard/receive.c b/drivers/net/wireguard/receive.c
index 7135d51d2d87..0b3f0c843550 100644
--- a/drivers/net/wireguard/receive.c
+++ b/drivers/net/wireguard/receive.c
@@ -524,7 +524,7 @@ static void wg_packet_consume_data(struct wg_device *wg, struct sk_buff *skb)
goto err;
ret = wg_queue_enqueue_per_device_and_peer(&wg->decrypt_queue, &peer->rx_queue, skb,
- wg->packet_crypt_wq, &wg->decrypt_queue.last_cpu);
+ wg->packet_crypt_wq);
if (unlikely(ret == -EPIPE))
wg_queue_enqueue_per_peer_rx(skb, PACKET_STATE_DEAD);
if (likely(!ret || ret == -EPIPE)) {
diff --git a/drivers/net/wireguard/selftest/allowedips.c b/drivers/net/wireguard/selftest/allowedips.c
index 78ebe2892a78..3d1f64ff2e12 100644
--- a/drivers/net/wireguard/selftest/allowedips.c
+++ b/drivers/net/wireguard/selftest/allowedips.c
@@ -593,16 +593,20 @@ bool __init wg_allowedips_selftest(void)
wg_allowedips_remove_by_peer(&t, a, &mutex);
test_negative(4, a, 192, 168, 0, 1);
- /* These will hit the WARN_ON(len >= MAX_ALLOWEDIPS_BITS) in free_node
+ /* These will hit the WARN_ON(len >= MAX_ALLOWEDIPS_DEPTH) in free_node
* if something goes wrong.
*/
- for (i = 0; i < MAX_ALLOWEDIPS_BITS; ++i) {
- part = cpu_to_be64(~(1LLU << (i % 64)));
- memset(&ip, 0xff, 16);
- memcpy((u8 *)&ip + (i < 64) * 8, &part, 8);
+ for (i = 0; i < 64; ++i) {
+ part = cpu_to_be64(~0LLU << i);
+ memset(&ip, 0xff, 8);
+ memcpy((u8 *)&ip + 8, &part, 8);
+ wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex);
+ memcpy(&ip, &part, 8);
+ memset((u8 *)&ip + 8, 0, 8);
wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex);
}
-
+ memset(&ip, 0, 16);
+ wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex);
wg_allowedips_free(&t, &mutex);
wg_allowedips_init(&t);
diff --git a/drivers/net/wireguard/send.c b/drivers/net/wireguard/send.c
index 5368f7c35b4b..95c853b59e1d 100644
--- a/drivers/net/wireguard/send.c
+++ b/drivers/net/wireguard/send.c
@@ -318,7 +318,7 @@ static void wg_packet_create_data(struct wg_peer *peer, struct sk_buff *first)
goto err;
ret = wg_queue_enqueue_per_device_and_peer(&wg->encrypt_queue, &peer->tx_queue, first,
- wg->packet_crypt_wq, &wg->encrypt_queue.last_cpu);
+ wg->packet_crypt_wq);
if (unlikely(ret == -EPIPE))
wg_queue_enqueue_per_peer_tx(first, PACKET_STATE_DEAD);
err:
diff --git a/drivers/net/wireguard/timers.c b/drivers/net/wireguard/timers.c
index 53d8a57a0dfa..968bdb4df0b3 100644
--- a/drivers/net/wireguard/timers.c
+++ b/drivers/net/wireguard/timers.c
@@ -234,10 +234,10 @@ void wg_timers_init(struct wg_peer *peer)
void wg_timers_stop(struct wg_peer *peer)
{
- del_timer_sync(&peer->timer_retransmit_handshake);
- del_timer_sync(&peer->timer_send_keepalive);
- del_timer_sync(&peer->timer_new_handshake);
- del_timer_sync(&peer->timer_zero_key_material);
- del_timer_sync(&peer->timer_persistent_keepalive);
+ timer_delete_sync(&peer->timer_retransmit_handshake);
+ timer_delete_sync(&peer->timer_send_keepalive);
+ timer_delete_sync(&peer->timer_new_handshake);
+ timer_delete_sync(&peer->timer_zero_key_material);
+ timer_delete_sync(&peer->timer_persistent_keepalive);
flush_work(&peer->clear_peer_work);
}
diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c
index f0c615fa5614..4a006fb4d424 100644
--- a/drivers/net/wireless/ath/ath10k/ahb.c
+++ b/drivers/net/wireless/ath/ath10k/ahb.c
@@ -27,7 +27,7 @@ MODULE_DEVICE_TABLE(of, ath10k_ahb_of_match);
static inline struct ath10k_ahb *ath10k_ahb_priv(struct ath10k *ar)
{
- return &((struct ath10k_pci *)ar->drv_priv)->ahb[0];
+ return &ath10k_pci_priv(ar)->ahb[0];
}
static void ath10k_ahb_write32(struct ath10k *ar, u32 offset, u32 value)
@@ -816,23 +816,13 @@ err_resource_deinit:
err_core_destroy:
ath10k_core_destroy(ar);
- platform_set_drvdata(pdev, NULL);
return ret;
}
-static int ath10k_ahb_remove(struct platform_device *pdev)
+static void ath10k_ahb_remove(struct platform_device *pdev)
{
struct ath10k *ar = platform_get_drvdata(pdev);
- struct ath10k_ahb *ar_ahb;
-
- if (!ar)
- return -EINVAL;
-
- ar_ahb = ath10k_ahb_priv(ar);
-
- if (!ar_ahb)
- return -EINVAL;
ath10k_dbg(ar, ATH10K_DBG_AHB, "ahb remove\n");
@@ -844,10 +834,6 @@ static int ath10k_ahb_remove(struct platform_device *pdev)
ath10k_ahb_clock_disable(ar);
ath10k_ahb_resource_deinit(ar);
ath10k_core_destroy(ar);
-
- platform_set_drvdata(pdev, NULL);
-
- return 0;
}
static struct platform_driver ath10k_ahb_driver = {
@@ -856,7 +842,7 @@ static struct platform_driver ath10k_ahb_driver = {
.of_match_table = ath10k_ahb_of_match,
},
.probe = ath10k_ahb_probe,
- .remove = ath10k_ahb_remove,
+ .remove_new = ath10k_ahb_remove,
};
int ath10k_ahb_init(void)
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 5eb131ab916f..6cdb225b7eac 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2504,7 +2504,6 @@ EXPORT_SYMBOL(ath10k_core_napi_sync_disable);
static void ath10k_core_restart(struct work_struct *work)
{
struct ath10k *ar = container_of(work, struct ath10k, restart_work);
- struct ath10k_vif *arvif;
int ret;
set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
@@ -2543,14 +2542,6 @@ static void ath10k_core_restart(struct work_struct *work)
ar->state = ATH10K_STATE_RESTARTING;
ath10k_halt(ar);
ath10k_scan_finish(ar);
- if (ar->hw_params.hw_restart_disconnect) {
- list_for_each_entry(arvif, &ar->arvifs, list) {
- if (arvif->is_up &&
- arvif->vdev_type == WMI_VDEV_TYPE_STA)
- ieee80211_hw_restart_disconnect(arvif->vif);
- }
- }
-
ieee80211_restart_hw(ar->hw);
break;
case ATH10K_STATE_OFF:
@@ -3643,6 +3634,9 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
mutex_init(&ar->dump_mutex);
spin_lock_init(&ar->data_lock);
+ for (int ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+ spin_lock_init(&ar->queue_lock[ac]);
+
INIT_LIST_HEAD(&ar->peers);
init_waitqueue_head(&ar->peer_mapping_wq);
init_waitqueue_head(&ar->htt.empty_tx_wq);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index f5de8ce8fb45..4b5239de4018 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -1170,6 +1170,9 @@ struct ath10k {
/* protects shared structure data */
spinlock_t data_lock;
+ /* serialize wake_tx_queue calls per ac */
+ spinlock_t queue_lock[IEEE80211_NUM_ACS];
+
struct list_head arvifs;
struct list_head peers;
struct ath10k_peer *peer_map[ATH10K_MAX_NUM_PEER_IDS];
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index b9aea1510f7b..f9518e1c9903 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -293,8 +293,8 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
goto free;
}
- num_peers = ath10k_wmi_fw_stats_num_peers(&ar->debug.fw_stats.peers);
- num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
+ num_peers = list_count_nodes(&ar->debug.fw_stats.peers);
+ num_vdevs = list_count_nodes(&ar->debug.fw_stats.vdevs);
is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
!list_empty(&stats.pdevs));
is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index c051a22fce14..e0c9f45e7476 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -707,7 +707,7 @@ struct htt_rx_indication_prefix {
__le16 fw_rx_desc_bytes;
u8 pad0;
u8 pad1;
-};
+} __packed;
struct htt_rx_indication {
struct htt_rx_indication_hdr hdr;
@@ -1565,7 +1565,7 @@ struct htt_tx_fetch_ind {
/* ath10k_htt_get_tx_fetch_ind_resp_ids() */
DECLARE_FLEX_ARRAY(__le32, resp_ids);
DECLARE_FLEX_ARRAY(struct htt_tx_fetch_record, records);
- };
+ } __packed;
} __packed;
static inline void *
@@ -1723,7 +1723,7 @@ struct htt_resp {
struct htt_tx_mode_switch_ind tx_mode_switch_ind;
struct htt_channel_change chan_change;
struct htt_peer_tx_stats peer_tx_stats;
- };
+ } __packed;
} __packed;
/*** host side structures follow ***/
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 7675858f069b..03e7bc5b6c0b 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4732,13 +4732,14 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
{
struct ath10k *ar = hw->priv;
int ret;
- u8 ac;
+ u8 ac = txq->ac;
ath10k_htt_tx_txq_update(hw, txq);
if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH)
return;
- ac = txq->ac;
+ spin_lock_bh(&ar->queue_lock[ac]);
+
ieee80211_txq_schedule_start(hw, ac);
txq = ieee80211_next_txq(hw, ac);
if (!txq)
@@ -4753,6 +4754,7 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
ath10k_htt_tx_txq_update(hw, txq);
out:
ieee80211_txq_schedule_end(hw, ac);
+ spin_unlock_bh(&ar->queue_lock[ac]);
}
/* Must not be called with conf_mutex held as workers can use that also. */
@@ -8107,6 +8109,7 @@ static void ath10k_reconfig_complete(struct ieee80211_hw *hw,
enum ieee80211_reconfig_type reconfig_type)
{
struct ath10k *ar = hw->priv;
+ struct ath10k_vif *arvif;
if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
return;
@@ -8121,6 +8124,12 @@ static void ath10k_reconfig_complete(struct ieee80211_hw *hw,
ar->state = ATH10K_STATE_ON;
ieee80211_wake_queues(ar->hw);
clear_bit(ATH10K_FLAG_RESTARTING, &ar->dev_flags);
+ if (ar->hw_params.hw_restart_disconnect) {
+ list_for_each_entry(arvif, &ar->arvifs, list) {
+ if (arvif->is_up && arvif->vdev_type == WMI_VDEV_TYPE_STA)
+ ieee80211_hw_restart_disconnect(arvif->vif);
+ }
+ }
}
mutex_unlock(&ar->conf_mutex);
diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c
index 038c5903c0dc..52c1a3de8da6 100644
--- a/drivers/net/wireless/ath/ath10k/qmi.c
+++ b/drivers/net/wireless/ath/ath10k/qmi.c
@@ -1082,8 +1082,7 @@ int ath10k_qmi_init(struct ath10k *ar, u32 msa_size)
if (ret)
goto err;
- qmi->event_wq = alloc_workqueue("ath10k_qmi_driver_event",
- WQ_UNBOUND, 1);
+ qmi->event_wq = alloc_ordered_workqueue("ath10k_qmi_driver_event", 0);
if (!qmi->event_wq) {
ath10k_err(ar, "failed to allocate workqueue\n");
ret = -EFAULT;
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index 5128a452c65f..26214c00cd0d 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -1848,7 +1848,7 @@ static int ath10k_snoc_free_resources(struct ath10k *ar)
return 0;
}
-static int ath10k_snoc_remove(struct platform_device *pdev)
+static void ath10k_snoc_remove(struct platform_device *pdev)
{
struct ath10k *ar = platform_get_drvdata(pdev);
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
@@ -1861,8 +1861,6 @@ static int ath10k_snoc_remove(struct platform_device *pdev)
wait_for_completion_timeout(&ar->driver_recovery, 3 * HZ);
ath10k_snoc_free_resources(ar);
-
- return 0;
}
static void ath10k_snoc_shutdown(struct platform_device *pdev)
@@ -1875,8 +1873,8 @@ static void ath10k_snoc_shutdown(struct platform_device *pdev)
static struct platform_driver ath10k_snoc_driver = {
.probe = ath10k_snoc_probe,
- .remove = ath10k_snoc_remove,
- .shutdown = ath10k_snoc_shutdown,
+ .remove_new = ath10k_snoc_remove,
+ .shutdown = ath10k_snoc_shutdown,
.driver = {
.name = "ath10k_snoc",
.of_match_table = ath10k_snoc_dt_match,
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 980d4124fa28..05fa7d4c0e1a 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -8164,28 +8164,6 @@ ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config(struct ath10k *ar, u32 param)
return skb;
}
-size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head)
-{
- struct ath10k_fw_stats_peer *i;
- size_t num = 0;
-
- list_for_each_entry(i, head, list)
- ++num;
-
- return num;
-}
-
-size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head)
-{
- struct ath10k_fw_stats_vdev *i;
- size_t num = 0;
-
- list_for_each_entry(i, head, list)
- ++num;
-
- return num;
-}
-
static void
ath10k_wmi_fw_pdev_base_stats_fill(const struct ath10k_fw_stats_pdev *pdev,
char *buf, u32 *length)
@@ -8462,8 +8440,8 @@ void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar,
goto unlock;
}
- num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
- num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
+ num_peers = list_count_nodes(&fw_stats->peers);
+ num_vdevs = list_count_nodes(&fw_stats->vdevs);
ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len);
@@ -8520,8 +8498,8 @@ void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar,
goto unlock;
}
- num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
- num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
+ num_peers = list_count_nodes(&fw_stats->peers);
+ num_vdevs = list_count_nodes(&fw_stats->vdevs);
ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len);
@@ -8668,8 +8646,8 @@ void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
goto unlock;
}
- num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
- num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
+ num_peers = list_count_nodes(&fw_stats->peers);
+ num_vdevs = list_count_nodes(&fw_stats->vdevs);
ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 6de3cc4640a0..6d04a66fe5e0 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -7502,8 +7502,6 @@ void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar,
void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar,
struct ath10k_fw_stats *fw_stats,
char *buf);
-size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head);
-size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head);
void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
struct ath10k_fw_stats *fw_stats,
char *buf);
diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
index 5cbba9a8b6ba..139da578831a 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 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.
*/
#include <linux/module.h>
@@ -376,7 +376,6 @@ static void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab)
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
if (!irq_grp->napi_enabled) {
- dev_set_threaded(&irq_grp->napi_ndev, true);
napi_enable(&irq_grp->napi);
irq_grp->napi_enabled = true;
}
@@ -734,7 +733,7 @@ static int ath11k_ahb_hif_suspend(struct ath11k_base *ab)
return ret;
}
- ath11k_dbg(ab, ATH11K_DBG_AHB, "ahb device suspended\n");
+ ath11k_dbg(ab, ATH11K_DBG_AHB, "device suspended\n");
return ret;
}
@@ -777,7 +776,7 @@ static int ath11k_ahb_hif_resume(struct ath11k_base *ab)
return -ETIMEDOUT;
}
- ath11k_dbg(ab, ATH11K_DBG_AHB, "ahb device resumed\n");
+ ath11k_dbg(ab, ATH11K_DBG_AHB, "device resumed\n");
return 0;
}
@@ -1127,6 +1126,7 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
switch (hw_rev) {
case ATH11K_HW_IPQ8074:
case ATH11K_HW_IPQ6018_HW10:
+ case ATH11K_HW_IPQ5018_HW10:
hif_ops = &ath11k_ahb_hif_ops_ipq8074;
pci_ops = NULL;
break;
@@ -1155,6 +1155,7 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
ab->hif.ops = hif_ops;
ab->pdev = pdev;
ab->hw_rev = hw_rev;
+ ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL;
platform_set_drvdata(pdev, ab);
ret = ath11k_pcic_register_pci_ops(ab, pci_ops);
diff --git a/drivers/net/wireless/ath/ath11k/ce.c b/drivers/net/wireless/ath/ath11k/ce.c
index f2da95fd4253..289d47ae92af 100644
--- a/drivers/net/wireless/ath/ath11k/ce.c
+++ b/drivers/net/wireless/ath/ath11k/ce.c
@@ -442,7 +442,7 @@ static void ath11k_ce_recv_process_cb(struct ath11k_ce_pipe *pipe)
}
while ((skb = __skb_dequeue(&list))) {
- ath11k_dbg(ab, ATH11K_DBG_AHB, "rx ce pipe %d len %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_CE, "rx ce pipe %d len %d\n",
pipe->pipe_num, skb->len);
pipe->recv_cb(ab, skb);
}
@@ -520,7 +520,7 @@ static void ath11k_ce_tx_process_cb(struct ath11k_ce_pipe *pipe)
}
while ((skb = __skb_dequeue(&list))) {
- ath11k_dbg(ab, ATH11K_DBG_AHB, "tx ce pipe %d len %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_CE, "tx ce pipe %d len %d\n",
pipe->pipe_num, skb->len);
pipe->send_cb(ab, skb);
}
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index b1b90bd34d67..bebfd342e28b 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/module.h>
@@ -32,6 +32,10 @@ module_param_named(frame_mode, ath11k_frame_mode, uint, 0644);
MODULE_PARM_DESC(frame_mode,
"Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");
+bool ath11k_ftm_mode;
+module_param_named(ftm_mode, ath11k_ftm_mode, bool, 0444);
+MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode");
+
static const struct ath11k_hw_params ath11k_hw_params[] = {
{
.hw_rev = ATH11K_HW_IPQ8074,
@@ -664,6 +668,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.hal_params = &ath11k_hw_hal_params_ipq8074,
.single_pdev_only = false,
.cold_boot_calib = true,
+ .cbcal_restart_fw = true,
.fix_l1ss = true,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = true,
@@ -874,16 +879,16 @@ static void ath11k_core_check_cc_code_bdfext(const struct dmi_header *hdr, void
case ATH11K_SMBIOS_CC_ISO:
ab->new_alpha2[0] = (smbios->cc_code >> 8) & 0xff;
ab->new_alpha2[1] = smbios->cc_code & 0xff;
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot smbios cc_code %c%c\n",
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "smbios cc_code %c%c\n",
ab->new_alpha2[0], ab->new_alpha2[1]);
break;
case ATH11K_SMBIOS_CC_WW:
ab->new_alpha2[0] = '0';
ab->new_alpha2[1] = '0';
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot smbios worldwide regdomain\n");
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "smbios worldwide regdomain\n");
break;
default:
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot ignore smbios country code setting %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "ignore smbios country code setting %d\n",
smbios->country_code_flag);
break;
}
@@ -961,7 +966,8 @@ int ath11k_core_check_dt(struct ath11k_base *ab)
}
static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
- size_t name_len, bool with_variant)
+ size_t name_len, bool with_variant,
+ bool bus_type_mode)
{
/* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */
char variant[9 + ATH11K_QMI_BDF_EXT_STR_LENGTH] = { 0 };
@@ -972,15 +978,20 @@ static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
switch (ab->id.bdf_search) {
case ATH11K_BDF_SEARCH_BUS_AND_BOARD:
- scnprintf(name, name_len,
- "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s",
- ath11k_bus_str(ab->hif.bus),
- ab->id.vendor, ab->id.device,
- ab->id.subsystem_vendor,
- ab->id.subsystem_device,
- ab->qmi.target.chip_id,
- ab->qmi.target.board_id,
- variant);
+ if (bus_type_mode)
+ scnprintf(name, name_len,
+ "bus=%s",
+ ath11k_bus_str(ab->hif.bus));
+ else
+ scnprintf(name, name_len,
+ "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s",
+ ath11k_bus_str(ab->hif.bus),
+ ab->id.vendor, ab->id.device,
+ ab->id.subsystem_vendor,
+ ab->id.subsystem_device,
+ ab->qmi.target.chip_id,
+ ab->qmi.target.board_id,
+ variant);
break;
default:
scnprintf(name, name_len,
@@ -991,7 +1002,7 @@ static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
break;
}
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot using board name '%s'\n", name);
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board name '%s'\n", name);
return 0;
}
@@ -999,13 +1010,19 @@ static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
size_t name_len)
{
- return __ath11k_core_create_board_name(ab, name, name_len, true);
+ return __ath11k_core_create_board_name(ab, name, name_len, true, false);
}
static int ath11k_core_create_fallback_board_name(struct ath11k_base *ab, char *name,
size_t name_len)
{
- return __ath11k_core_create_board_name(ab, name, name_len, false);
+ return __ath11k_core_create_board_name(ab, name, name_len, false, false);
+}
+
+static int ath11k_core_create_bus_type_board_name(struct ath11k_base *ab, char *name,
+ size_t name_len)
+{
+ return __ath11k_core_create_board_name(ab, name, name_len, false, true);
}
const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
@@ -1024,7 +1041,7 @@ const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
if (ret)
return ERR_PTR(ret);
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot firmware request %s size %zu\n",
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "firmware request %s size %zu\n",
path, fw->size);
return fw;
@@ -1085,7 +1102,7 @@ static int ath11k_core_parse_bd_ie_board(struct ath11k_base *ab,
name_match_found = true;
ath11k_dbg(ab, ATH11K_DBG_BOOT,
- "boot found match %s for name '%s'",
+ "found match %s for name '%s'",
ath11k_bd_ie_type_str(ie_id),
boardname);
} else if (board_ie_id == data_id) {
@@ -1094,7 +1111,7 @@ static int ath11k_core_parse_bd_ie_board(struct ath11k_base *ab,
goto next;
ath11k_dbg(ab, ATH11K_DBG_BOOT,
- "boot found %s for '%s'",
+ "found %s for '%s'",
ath11k_bd_ie_type_str(ie_id),
boardname);
@@ -1309,7 +1326,7 @@ success:
int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd)
{
- char boardname[BOARD_NAME_SIZE];
+ char boardname[BOARD_NAME_SIZE], default_boardname[BOARD_NAME_SIZE];
int ret;
ret = ath11k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE);
@@ -1326,6 +1343,21 @@ int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd
if (!ret)
goto exit;
+ ret = ath11k_core_create_bus_type_board_name(ab, default_boardname,
+ BOARD_NAME_SIZE);
+ if (ret) {
+ ath11k_dbg(ab, ATH11K_DBG_BOOT,
+ "failed to create default board name for regdb: %d", ret);
+ goto exit;
+ }
+
+ ret = ath11k_core_fetch_board_data_api_n(ab, bd, default_boardname,
+ ATH11K_BD_IE_REGDB,
+ ATH11K_BD_IE_REGDB_NAME,
+ ATH11K_BD_IE_REGDB_DATA);
+ if (!ret)
+ goto exit;
+
ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_REGDB_FILE_NAME);
if (ret)
ath11k_dbg(ab, ATH11K_DBG_BOOT, "failed to fetch %s from %s\n",
@@ -1354,6 +1386,11 @@ static int ath11k_core_soc_create(struct ath11k_base *ab)
{
int ret;
+ if (ath11k_ftm_mode) {
+ ab->fw_mode = ATH11K_FIRMWARE_MODE_FTM;
+ ath11k_info(ab, "Booting in factory test mode\n");
+ }
+
ret = ath11k_qmi_init_service(ab);
if (ret) {
ath11k_err(ab, "failed to initialize qmi :%d\n", ret);
@@ -1580,7 +1617,7 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab)
{
int ret;
- ret = ath11k_core_start_firmware(ab, ATH11K_FIRMWARE_MODE_NORMAL);
+ ret = ath11k_core_start_firmware(ab, ab->fw_mode);
if (ret) {
ath11k_err(ab, "failed to start firmware: %d\n", ret);
return ret;
@@ -1745,7 +1782,8 @@ void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)
for (i = 0; i < ab->num_radios; i++) {
pdev = &ab->pdevs[i];
ar = pdev->ar;
- if (!ar || ar->state == ATH11K_STATE_OFF)
+ if (!ar || ar->state == ATH11K_STATE_OFF ||
+ ar->state == ATH11K_STATE_FTM)
continue;
ieee80211_stop_queues(ar->hw);
@@ -1814,7 +1852,12 @@ static void ath11k_core_post_reconfigure_recovery(struct ath11k_base *ab)
ath11k_warn(ab,
"device is wedged, will not restart radio %d\n", i);
break;
+ case ATH11K_STATE_FTM:
+ ath11k_dbg(ab, ATH11K_DBG_TESTMODE,
+ "fw mode reset done radio %d\n", i);
+ break;
}
+
mutex_unlock(&ar->conf_mutex);
}
complete(&ab->driver_recovery);
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 0830276e5028..9d15b4390b9c 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH11K_CORE_H
@@ -52,6 +52,7 @@
#define ATH11K_SMBIOS_BDF_EXT_MAGIC "BDF_"
extern unsigned int ath11k_frame_mode;
+extern bool ath11k_ftm_mode;
#define ATH11K_SCAN_TIMEOUT_HZ (20 * HZ)
@@ -277,6 +278,7 @@ enum ath11k_dev_flags {
ATH11K_FLAG_FIXED_MEM_RGN,
ATH11K_FLAG_DEVICE_INIT_DONE,
ATH11K_FLAG_MULTI_MSI_VECTORS,
+ ATH11K_FLAG_FTM_SEGMENTED,
};
enum ath11k_monitor_flags {
@@ -530,6 +532,7 @@ enum ath11k_state {
ATH11K_STATE_RESTARTING,
ATH11K_STATE_RESTARTED,
ATH11K_STATE_WEDGED,
+ ATH11K_STATE_FTM,
/* Add other states as required */
};
@@ -709,6 +712,8 @@ struct ath11k {
u32 last_ppdu_id;
u32 cached_ppdu_id;
int monitor_vdev_id;
+ struct completion fw_mode_reset;
+ u8 ftm_msgref;
#ifdef CONFIG_ATH11K_DEBUGFS
struct ath11k_debug debug;
#endif
@@ -838,6 +843,7 @@ struct ath11k_msi_config {
/* Master structure to hold the hw data which may be used in core module */
struct ath11k_base {
enum ath11k_hw_rev hw_rev;
+ enum ath11k_firmware_mode fw_mode;
struct platform_device *pdev;
struct device *dev;
struct ath11k_qmi qmi;
@@ -978,6 +984,14 @@ struct ath11k_base {
const struct ath11k_pci_ops *ops;
} pci;
+#ifdef CONFIG_NL80211_TESTMODE
+ struct {
+ u32 data_pos;
+ u32 expected_seq;
+ u8 *eventdata;
+ } testmode;
+#endif
+
/* must be last */
u8 drv_priv[] __aligned(sizeof(void *));
};
diff --git a/drivers/net/wireless/ath/ath11k/debug.c b/drivers/net/wireless/ath/ath11k/debug.c
index 958d87429062..f5c8a34c8802 100644
--- a/drivers/net/wireless/ath/ath11k/debug.c
+++ b/drivers/net/wireless/ath/ath11k/debug.c
@@ -66,7 +66,7 @@ void __ath11k_dbg(struct ath11k_base *ab, enum ath11k_debug_mask mask,
vaf.va = &args;
if (ath11k_debug_mask & mask)
- dev_printk(KERN_DEBUG, ab->dev, "%pV", &vaf);
+ dev_printk(KERN_DEBUG, ab->dev, "%s %pV", ath11k_dbg_str(mask), &vaf);
trace_ath11k_log_dbg(ab, mask, &vaf);
diff --git a/drivers/net/wireless/ath/ath11k/debug.h b/drivers/net/wireless/ath/ath11k/debug.h
index 91545640c47b..9c52804ef8ac 100644
--- a/drivers/net/wireless/ath/ath11k/debug.h
+++ b/drivers/net/wireless/ath/ath11k/debug.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _ATH11K_DEBUG_H_
@@ -21,13 +22,57 @@ enum ath11k_debug_mask {
ATH11K_DBG_MGMT = 0x00000100,
ATH11K_DBG_REG = 0x00000200,
ATH11K_DBG_TESTMODE = 0x00000400,
- ATH11k_DBG_HAL = 0x00000800,
+ ATH11K_DBG_HAL = 0x00000800,
ATH11K_DBG_PCI = 0x00001000,
ATH11K_DBG_DP_TX = 0x00002000,
ATH11K_DBG_DP_RX = 0x00004000,
- ATH11K_DBG_ANY = 0xffffffff,
+ ATH11K_DBG_CE = 0x00008000,
};
+static inline const char *ath11k_dbg_str(enum ath11k_debug_mask mask)
+{
+ switch (mask) {
+ case ATH11K_DBG_AHB:
+ return "ahb";
+ case ATH11K_DBG_WMI:
+ return "wmi";
+ case ATH11K_DBG_HTC:
+ return "htc";
+ case ATH11K_DBG_DP_HTT:
+ return "dp_htt";
+ case ATH11K_DBG_MAC:
+ return "mac";
+ case ATH11K_DBG_BOOT:
+ return "boot";
+ case ATH11K_DBG_QMI:
+ return "qmi";
+ case ATH11K_DBG_DATA:
+ return "data";
+ case ATH11K_DBG_MGMT:
+ return "mgmt";
+ case ATH11K_DBG_REG:
+ return "reg";
+ case ATH11K_DBG_TESTMODE:
+ return "testmode";
+ case ATH11K_DBG_HAL:
+ return "hal";
+ case ATH11K_DBG_PCI:
+ return "pci";
+ case ATH11K_DBG_DP_TX:
+ return "dp_tx";
+ case ATH11K_DBG_DP_RX:
+ return "dp_rx";
+ case ATH11K_DBG_CE:
+ return "ce";
+
+ /* no default handler to allow compiler to check that the
+ * enum is fully handled
+ */
+ }
+
+ return "<?>";
+}
+
__printf(2, 3) void ath11k_info(struct ath11k_base *ab, const char *fmt, ...);
__printf(2, 3) void ath11k_err(struct ath11k_base *ab, const char *fmt, ...);
__printf(2, 3) void ath11k_warn(struct ath11k_base *ab, const char *fmt, ...);
diff --git a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c
index b3efca6bd7dd..0207fc4910f3 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c
@@ -4011,6 +4011,114 @@ void htt_print_phy_stats_tlv(const void *tag_buf,
stats_req->buf_len = len;
}
+static inline void
+htt_print_phy_reset_counters_tlv(const void *tag_buf,
+ u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct htt_phy_reset_counters_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_PHY_RESET_COUNTERS_TLV:\n");
+
+ len += scnprintf(buf + len, buf_len - len, "pdev_id = %u\n",
+ htt_stats_buf->pdev_id);
+ len += scnprintf(buf + len, buf_len - len, "cf_active_low_fail_cnt = %u\n",
+ htt_stats_buf->cf_active_low_fail_cnt);
+ len += scnprintf(buf + len, buf_len - len, "cf_active_low_pass_cnt = %u\n",
+ htt_stats_buf->cf_active_low_pass_cnt);
+ len += scnprintf(buf + len, buf_len - len, "phy_off_through_vreg_cnt = %u\n",
+ htt_stats_buf->phy_off_through_vreg_cnt);
+ len += scnprintf(buf + len, buf_len - len, "force_calibration_cnt = %u\n",
+ htt_stats_buf->force_calibration_cnt);
+ len += scnprintf(buf + len, buf_len - len, "rf_mode_switch_phy_off_cnt = %u\n",
+ htt_stats_buf->rf_mode_switch_phy_off_cnt);
+
+ stats_req->buf_len = len;
+}
+
+static inline void
+htt_print_phy_reset_stats_tlv(const void *tag_buf,
+ u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct htt_phy_reset_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_PHY_RESET_STATS_TLV:\n");
+
+ len += scnprintf(buf + len, buf_len - len, "pdev_id = %u\n",
+ htt_stats_buf->pdev_id);
+ len += scnprintf(buf + len, buf_len - len, "chan_mhz = %u\n",
+ htt_stats_buf->chan_mhz);
+ len += scnprintf(buf + len, buf_len - len, "chan_band_center_freq1 = %u\n",
+ htt_stats_buf->chan_band_center_freq1);
+ len += scnprintf(buf + len, buf_len - len, "chan_band_center_freq2 = %u\n",
+ htt_stats_buf->chan_band_center_freq2);
+ len += scnprintf(buf + len, buf_len - len, "chan_phy_mode = %u\n",
+ htt_stats_buf->chan_phy_mode);
+ len += scnprintf(buf + len, buf_len - len, "chan_flags = 0x%0x\n",
+ htt_stats_buf->chan_flags);
+ len += scnprintf(buf + len, buf_len - len, "chan_num = %u\n",
+ htt_stats_buf->chan_num);
+ len += scnprintf(buf + len, buf_len - len, "reset_cause = 0x%0x\n",
+ htt_stats_buf->reset_cause);
+ len += scnprintf(buf + len, buf_len - len, "prev_reset_cause = 0x%0x\n",
+ htt_stats_buf->prev_reset_cause);
+ len += scnprintf(buf + len, buf_len - len, "phy_warm_reset_src = 0x%0x\n",
+ htt_stats_buf->phy_warm_reset_src);
+ len += scnprintf(buf + len, buf_len - len, "rx_gain_tbl_mode = %d\n",
+ htt_stats_buf->rx_gain_tbl_mode);
+ len += scnprintf(buf + len, buf_len - len, "xbar_val = 0x%0x\n",
+ htt_stats_buf->xbar_val);
+ len += scnprintf(buf + len, buf_len - len, "force_calibration = %u\n",
+ htt_stats_buf->force_calibration);
+ len += scnprintf(buf + len, buf_len - len, "phyrf_mode = %u\n",
+ htt_stats_buf->phyrf_mode);
+ len += scnprintf(buf + len, buf_len - len, "phy_homechan = %u\n",
+ htt_stats_buf->phy_homechan);
+ len += scnprintf(buf + len, buf_len - len, "phy_tx_ch_mask = 0x%0x\n",
+ htt_stats_buf->phy_tx_ch_mask);
+ len += scnprintf(buf + len, buf_len - len, "phy_rx_ch_mask = 0x%0x\n",
+ htt_stats_buf->phy_rx_ch_mask);
+ len += scnprintf(buf + len, buf_len - len, "phybb_ini_mask = 0x%0x\n",
+ htt_stats_buf->phybb_ini_mask);
+ len += scnprintf(buf + len, buf_len - len, "phyrf_ini_mask = 0x%0x\n",
+ htt_stats_buf->phyrf_ini_mask);
+ len += scnprintf(buf + len, buf_len - len, "phy_dfs_en_mask = 0x%0x\n",
+ htt_stats_buf->phy_dfs_en_mask);
+ len += scnprintf(buf + len, buf_len - len, "phy_sscan_en_mask = 0x%0x\n",
+ htt_stats_buf->phy_sscan_en_mask);
+ len += scnprintf(buf + len, buf_len - len, "phy_synth_sel_mask = 0x%0x\n",
+ htt_stats_buf->phy_synth_sel_mask);
+ len += scnprintf(buf + len, buf_len - len, "phy_adfs_freq = %u\n",
+ htt_stats_buf->phy_adfs_freq);
+ len += scnprintf(buf + len, buf_len - len, "cck_fir_settings = 0x%0x\n",
+ htt_stats_buf->cck_fir_settings);
+ len += scnprintf(buf + len, buf_len - len, "phy_dyn_pri_chan = %u\n",
+ htt_stats_buf->phy_dyn_pri_chan);
+ len += scnprintf(buf + len, buf_len - len, "cca_thresh = 0x%0x\n",
+ htt_stats_buf->cca_thresh);
+ len += scnprintf(buf + len, buf_len - len, "dyn_cca_status = %u\n",
+ htt_stats_buf->dyn_cca_status);
+ len += scnprintf(buf + len, buf_len - len, "rxdesense_thresh_hw = 0x%x\n",
+ htt_stats_buf->rxdesense_thresh_hw);
+ len += scnprintf(buf + len, buf_len - len, "rxdesense_thresh_sw = 0x%x\n",
+ htt_stats_buf->rxdesense_thresh_sw);
+
+ stats_req->buf_len = len;
+}
+
static inline
void htt_print_peer_ctrl_path_txrx_stats_tlv(const void *tag_buf,
struct debug_htt_stats_req *stats_req)
@@ -4425,6 +4533,12 @@ static int ath11k_dbg_htt_ext_stats_parse(struct ath11k_base *ab,
case HTT_STATS_PHY_STATS_TAG:
htt_print_phy_stats_tlv(tag_buf, stats_req);
break;
+ case HTT_STATS_PHY_RESET_COUNTERS_TAG:
+ htt_print_phy_reset_counters_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_PHY_RESET_STATS_TAG:
+ htt_print_phy_reset_stats_tlv(tag_buf, len, stats_req);
+ break;
case HTT_STATS_PEER_CTRL_PATH_TXRX_STATS_TAG:
htt_print_peer_ctrl_path_txrx_stats_tlv(tag_buf, stats_req);
break;
diff --git a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h
index 0bbd58a380de..96219301f05b 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h
+++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h
@@ -111,6 +111,8 @@ enum htt_tlv_tag_t {
HTT_STATS_TXBF_OFDMA_STEER_STATS_TAG = 116,
HTT_STATS_PHY_COUNTERS_TAG = 121,
HTT_STATS_PHY_STATS_TAG = 122,
+ HTT_STATS_PHY_RESET_COUNTERS_TAG = 123,
+ HTT_STATS_PHY_RESET_STATS_TAG = 124,
HTT_STATS_MAX_TAG,
};
@@ -1964,6 +1966,47 @@ struct htt_phy_stats_tlv {
u32 fw_run_time;
};
+struct htt_phy_reset_counters_tlv {
+ u32 pdev_id;
+ u32 cf_active_low_fail_cnt;
+ u32 cf_active_low_pass_cnt;
+ u32 phy_off_through_vreg_cnt;
+ u32 force_calibration_cnt;
+ u32 rf_mode_switch_phy_off_cnt;
+};
+
+struct htt_phy_reset_stats_tlv {
+ u32 pdev_id;
+ u32 chan_mhz;
+ u32 chan_band_center_freq1;
+ u32 chan_band_center_freq2;
+ u32 chan_phy_mode;
+ u32 chan_flags;
+ u32 chan_num;
+ u32 reset_cause;
+ u32 prev_reset_cause;
+ u32 phy_warm_reset_src;
+ u32 rx_gain_tbl_mode;
+ u32 xbar_val;
+ u32 force_calibration;
+ u32 phyrf_mode;
+ u32 phy_homechan;
+ u32 phy_tx_ch_mask;
+ u32 phy_rx_ch_mask;
+ u32 phybb_ini_mask;
+ u32 phyrf_ini_mask;
+ u32 phy_dfs_en_mask;
+ u32 phy_sscan_en_mask;
+ u32 phy_synth_sel_mask;
+ u32 phy_adfs_freq;
+ u32 cck_fir_settings;
+ u32 phy_dyn_pri_chan;
+ u32 cca_thresh;
+ u32 dyn_cca_status;
+ u32 rxdesense_thresh_hw;
+ u32 rxdesense_thresh_sw;
+};
+
struct htt_peer_ctrl_path_txrx_stats_tlv {
/* peer mac address */
u8 peer_mac_addr[ETH_ALEN];
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index f67ce62b2b48..5c76664ba0dd 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -1651,7 +1651,7 @@ static void ath11k_htt_backpressure_event_handler(struct ath11k_base *ab,
backpressure_time = *data;
- ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt backpressure event, pdev %d, ring type %d,ring id %d, hp %d tp %d, backpressure time %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "backpressure event, pdev %d, ring type %d,ring id %d, hp %d tp %d, backpressure time %d\n",
pdev_id, ring_type, ring_id, hp, tp, backpressure_time);
if (ring_type == HTT_BACKPRESSURE_UMAC_RING_TYPE) {
@@ -2466,7 +2466,7 @@ static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *nap
spin_unlock_bh(&ar->ab->base_lock);
ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
- "rx skb %pK len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
+ "rx skb %p len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
msdu,
msdu->len,
peer ? peer->addr : NULL,
@@ -4908,7 +4908,7 @@ ath11k_dp_rx_mon_merg_msdus(struct ath11k *ar,
goto err_merge_fail;
ath11k_dbg(ab, ATH11K_DBG_DATA,
- "mpdu_buf %pK mpdu_buf->len %u",
+ "mpdu_buf %p mpdu_buf->len %u",
prev_buf, prev_buf->len);
} else {
ath11k_dbg(ab, ATH11K_DBG_DATA,
@@ -5099,7 +5099,7 @@ static void ath11k_dp_rx_mon_dest_process(struct ath11k *ar, int mac_id,
if (!mon_dst_srng) {
ath11k_warn(ar->ab,
- "HAL Monitor Destination Ring Init Failed -- %pK",
+ "HAL Monitor Destination Ring Init Failed -- %p",
mon_dst_srng);
return;
}
diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c
index 08a28464eb7a..a34833de7c67 100644
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
@@ -964,14 +964,10 @@ int ath11k_dp_tx_htt_srng_setup(struct ath11k_base *ab, u32 ring_id,
params.low_threshold);
}
- ath11k_dbg(ab, ATH11k_DBG_HAL,
- "%s msi_addr_lo:0x%x, msi_addr_hi:0x%x, msi_data:0x%x\n",
- __func__, cmd->ring_msi_addr_lo, cmd->ring_msi_addr_hi,
- cmd->msi_data);
-
- ath11k_dbg(ab, ATH11k_DBG_HAL,
- "ring_id:%d, ring_type:%d, intr_info:0x%x, flags:0x%x\n",
- ring_id, ring_type, cmd->intr_info, cmd->info2);
+ ath11k_dbg(ab, ATH11K_DBG_DP_TX,
+ "htt srng setup msi_addr_lo 0x%x msi_addr_hi 0x%x msi_data 0x%x ring_id %d ring_type %d intr_info 0x%x flags 0x%x\n",
+ cmd->ring_msi_addr_lo, cmd->ring_msi_addr_hi,
+ cmd->msi_data, ring_id, ring_type, cmd->intr_info, cmd->info2);
ret = ath11k_htc_send(&ab->htc, ab->dp.eid, skb);
if (ret)
diff --git a/drivers/net/wireless/ath/ath11k/hal.c b/drivers/net/wireless/ath/ath11k/hal.c
index 22422237500c..0a99aa7ddbf4 100644
--- a/drivers/net/wireless/ath/ath11k/hal.c
+++ b/drivers/net/wireless/ath/ath11k/hal.c
@@ -1009,8 +1009,8 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type,
srng->u.src_ring.hp_addr =
(u32 *)((unsigned long)ab->mem + reg_base);
else
- ath11k_dbg(ab, ATH11k_DBG_HAL,
- "hal type %d ring_num %d reg_base 0x%x shadow 0x%lx\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL,
+ "type %d ring_num %d reg_base 0x%x shadow 0x%lx\n",
type, ring_num,
reg_base,
(unsigned long)srng->u.src_ring.hp_addr -
@@ -1043,7 +1043,7 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type,
(u32 *)((unsigned long)ab->mem + reg_base +
(HAL_REO1_RING_TP(ab) - HAL_REO1_RING_HP(ab)));
else
- ath11k_dbg(ab, ATH11k_DBG_HAL,
+ ath11k_dbg(ab, ATH11K_DBG_HAL,
"type %d ring_num %d target_reg 0x%x shadow 0x%lx\n",
type, ring_num,
reg_base + (HAL_REO1_RING_TP(ab) -
@@ -1118,8 +1118,8 @@ int ath11k_hal_srng_update_shadow_config(struct ath11k_base *ab,
ath11k_hal_srng_update_hp_tp_addr(ab, shadow_cfg_idx, ring_type,
ring_num);
- ath11k_dbg(ab, ATH11k_DBG_HAL,
- "target_reg %x, shadow reg 0x%x shadow_idx 0x%x, ring_type %d, ring num %d",
+ ath11k_dbg(ab, ATH11K_DBG_HAL,
+ "update shadow config target_reg %x shadow reg 0x%x shadow_idx 0x%x ring_type %d ring num %d",
target_reg,
HAL_SHADOW_REG(ab, shadow_cfg_idx),
shadow_cfg_idx,
diff --git a/drivers/net/wireless/ath/ath11k/hal_rx.c b/drivers/net/wireless/ath/ath11k/hal_rx.c
index bb1d40034aa8..e5ed5efb139e 100644
--- a/drivers/net/wireless/ath/ath11k/hal_rx.c
+++ b/drivers/net/wireless/ath/ath11k/hal_rx.c
@@ -442,54 +442,54 @@ void ath11k_hal_reo_status_queue_stats(struct ath11k_base *ab, u32 *reo_desc,
FIELD_GET(HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS,
desc->hdr.info0);
- ath11k_dbg(ab, ATH11k_DBG_HAL, "Queue stats status:\n");
- ath11k_dbg(ab, ATH11k_DBG_HAL, "header: cmd_num %d status %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "Queue stats status:\n");
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "header: cmd_num %d status %d\n",
status->uniform_hdr.cmd_num,
status->uniform_hdr.cmd_status);
- ath11k_dbg(ab, ATH11k_DBG_HAL, "ssn %ld cur_idx %ld\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "ssn %ld cur_idx %ld\n",
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO0_SSN,
desc->info0),
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO0_CUR_IDX,
desc->info0));
- ath11k_dbg(ab, ATH11k_DBG_HAL, "pn = [%08x, %08x, %08x, %08x]\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "pn = [%08x, %08x, %08x, %08x]\n",
desc->pn[0], desc->pn[1], desc->pn[2], desc->pn[3]);
- ath11k_dbg(ab, ATH11k_DBG_HAL,
+ ath11k_dbg(ab, ATH11K_DBG_HAL,
"last_rx: enqueue_tstamp %08x dequeue_tstamp %08x\n",
desc->last_rx_enqueue_timestamp,
desc->last_rx_dequeue_timestamp);
- ath11k_dbg(ab, ATH11k_DBG_HAL,
+ ath11k_dbg(ab, ATH11K_DBG_HAL,
"rx_bitmap [%08x %08x %08x %08x %08x %08x %08x %08x]\n",
desc->rx_bitmap[0], desc->rx_bitmap[1], desc->rx_bitmap[2],
desc->rx_bitmap[3], desc->rx_bitmap[4], desc->rx_bitmap[5],
desc->rx_bitmap[6], desc->rx_bitmap[7]);
- ath11k_dbg(ab, ATH11k_DBG_HAL, "count: cur_mpdu %ld cur_msdu %ld\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "count: cur_mpdu %ld cur_msdu %ld\n",
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO1_MPDU_COUNT,
desc->info1),
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO1_MSDU_COUNT,
desc->info1));
- ath11k_dbg(ab, ATH11k_DBG_HAL, "fwd_timeout %ld fwd_bar %ld dup_count %ld\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "fwd_timeout %ld fwd_bar %ld dup_count %ld\n",
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO2_TIMEOUT_COUNT,
desc->info2),
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO2_FDTB_COUNT,
desc->info2),
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO2_DUPLICATE_COUNT,
desc->info2));
- ath11k_dbg(ab, ATH11k_DBG_HAL, "frames_in_order %ld bar_rcvd %ld\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "frames_in_order %ld bar_rcvd %ld\n",
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO3_FIO_COUNT,
desc->info3),
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO3_BAR_RCVD_CNT,
desc->info3));
- ath11k_dbg(ab, ATH11k_DBG_HAL, "num_mpdus %d num_msdus %d total_bytes %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "num_mpdus %d num_msdus %d total_bytes %d\n",
desc->num_mpdu_frames, desc->num_msdu_frames,
desc->total_bytes);
- ath11k_dbg(ab, ATH11k_DBG_HAL, "late_rcvd %ld win_jump_2k %ld hole_cnt %ld\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "late_rcvd %ld win_jump_2k %ld hole_cnt %ld\n",
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO4_LATE_RX_MPDU,
desc->info4),
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO4_WINDOW_JMP2K,
desc->info4),
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO4_HOLE_COUNT,
desc->info4));
- ath11k_dbg(ab, ATH11k_DBG_HAL, "looping count %ld\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "looping count %ld\n",
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO5_LOOPING_CNT,
desc->info5));
}
diff --git a/drivers/net/wireless/ath/ath11k/htc.c b/drivers/net/wireless/ath/ath11k/htc.c
index ca3aedc0252d..2c2e425c8665 100644
--- a/drivers/net/wireless/ath/ath11k/htc.c
+++ b/drivers/net/wireless/ath/ath11k/htc.c
@@ -46,7 +46,6 @@ static struct sk_buff *ath11k_htc_build_tx_ctrl_skb(void *ab)
skb_cb = ATH11K_SKB_CB(skb);
memset(skb_cb, 0, sizeof(*skb_cb));
- ath11k_dbg(ab, ATH11K_DBG_HTC, "%s: skb %pK\n", __func__, skb);
return skb;
}
@@ -96,7 +95,7 @@ int ath11k_htc_send(struct ath11k_htc *htc,
spin_lock_bh(&htc->tx_lock);
if (ep->tx_credits < credits) {
ath11k_dbg(ab, ATH11K_DBG_HTC,
- "htc insufficient credits ep %d required %d available %d\n",
+ "ep %d insufficient credits required %d total %d\n",
eid, credits, ep->tx_credits);
spin_unlock_bh(&htc->tx_lock);
ret = -EAGAIN;
@@ -104,7 +103,7 @@ int ath11k_htc_send(struct ath11k_htc *htc,
}
ep->tx_credits -= credits;
ath11k_dbg(ab, ATH11K_DBG_HTC,
- "htc ep %d consumed %d credits (total %d)\n",
+ "ep %d credits consumed %d total %d\n",
eid, credits, ep->tx_credits);
spin_unlock_bh(&htc->tx_lock);
}
@@ -119,6 +118,9 @@ int ath11k_htc_send(struct ath11k_htc *htc,
goto err_credits;
}
+ ath11k_dbg(ab, ATH11K_DBG_HTC, "tx skb %p eid %d paddr %pad\n",
+ skb, skb_cb->eid, &skb_cb->paddr);
+
ret = ath11k_ce_send(htc->ab, skb, ep->ul_pipe_id, ep->eid);
if (ret)
goto err_unmap;
@@ -132,7 +134,7 @@ err_credits:
spin_lock_bh(&htc->tx_lock);
ep->tx_credits += credits;
ath11k_dbg(ab, ATH11K_DBG_HTC,
- "htc ep %d reverted %d credits back (total %d)\n",
+ "ep %d credits reverted %d total %d\n",
eid, credits, ep->tx_credits);
spin_unlock_bh(&htc->tx_lock);
@@ -167,7 +169,7 @@ ath11k_htc_process_credit_report(struct ath11k_htc *htc,
ep = &htc->endpoint[report->eid];
ep->tx_credits += report->credits;
- ath11k_dbg(ab, ATH11K_DBG_HTC, "htc ep %d got %d credits (total %d)\n",
+ ath11k_dbg(ab, ATH11K_DBG_HTC, "ep %d credits got %d total %d\n",
report->eid, report->credits, ep->tx_credits);
if (ep->ep_ops.ep_tx_credits) {
@@ -239,7 +241,7 @@ static int ath11k_htc_process_trailer(struct ath11k_htc *htc,
static void ath11k_htc_suspend_complete(struct ath11k_base *ab, bool ack)
{
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot suspend complete %d\n", ack);
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "suspend complete %d\n", ack);
if (ack)
set_bit(ATH11K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags);
@@ -276,7 +278,7 @@ void ath11k_htc_tx_completion_handler(struct ath11k_base *ab,
static void ath11k_htc_wakeup_from_suspend(struct ath11k_base *ab)
{
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot wakeup from suspend is received\n");
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "wakeup from suspend is received\n");
}
void ath11k_htc_rx_completion_handler(struct ath11k_base *ab,
@@ -287,7 +289,7 @@ void ath11k_htc_rx_completion_handler(struct ath11k_base *ab,
struct ath11k_htc_hdr *hdr;
struct ath11k_htc_ep *ep;
u16 payload_len;
- u32 trailer_len = 0;
+ u32 message_id, trailer_len = 0;
size_t min_len;
u8 eid;
bool trailer_present;
@@ -322,6 +324,9 @@ void ath11k_htc_rx_completion_handler(struct ath11k_base *ab,
trailer_present = (FIELD_GET(HTC_HDR_FLAGS, hdr->htc_info)) &
ATH11K_HTC_FLAG_TRAILER_PRESENT;
+ ath11k_dbg(ab, ATH11K_DBG_HTC, "rx ep %d skb %p trailer_present %d\n",
+ eid, skb, trailer_present);
+
if (trailer_present) {
u8 *trailer;
@@ -354,7 +359,12 @@ void ath11k_htc_rx_completion_handler(struct ath11k_base *ab,
if (eid == ATH11K_HTC_EP_0) {
struct ath11k_htc_msg *msg = (struct ath11k_htc_msg *)skb->data;
- switch (FIELD_GET(HTC_MSG_MESSAGEID, msg->msg_svc_id)) {
+ message_id = FIELD_GET(HTC_MSG_MESSAGEID, msg->msg_svc_id);
+
+ ath11k_dbg(ab, ATH11K_DBG_HTC, "rx ep %d skb %p message_id %d\n",
+ eid, skb, message_id);
+
+ switch (message_id) {
case ATH11K_HTC_MSG_READY_ID:
case ATH11K_HTC_MSG_CONNECT_SERVICE_RESP_ID:
/* handle HTC control message */
@@ -393,8 +403,6 @@ void ath11k_htc_rx_completion_handler(struct ath11k_base *ab,
goto out;
}
- ath11k_dbg(ab, ATH11K_DBG_HTC, "htc rx completion ep %d skb %pK\n",
- eid, skb);
ep->ep_ops.ep_rx_complete(ab, skb);
/* poll tx completion for interrupt disabled CE's */
@@ -564,7 +572,7 @@ int ath11k_htc_wait_target(struct ath11k_htc *htc)
htc->target_credit_size = credit_size;
ath11k_dbg(ab, ATH11K_DBG_HTC,
- "Target ready! transmit resources: %d size:%d\n",
+ "target ready total_transmit_credits %d target_credit_size %d\n",
htc->total_transmit_credits, htc->target_credit_size);
if ((htc->total_transmit_credits == 0) ||
@@ -615,7 +623,7 @@ int ath11k_htc_connect_service(struct ath11k_htc *htc,
conn_req->service_id);
if (!tx_alloc)
ath11k_dbg(ab, ATH11K_DBG_BOOT,
- "boot htc service %s does not allocate target credits\n",
+ "htc service %s does not allocate target credits\n",
htc_service_name(conn_req->service_id));
skb = ath11k_htc_build_tx_ctrl_skb(htc->ab);
@@ -680,7 +688,7 @@ int ath11k_htc_connect_service(struct ath11k_htc *htc,
}
ath11k_dbg(ab, ATH11K_DBG_HTC,
- "HTC Service %s connect response: status: 0x%lx, assigned ep: 0x%lx\n",
+ "service %s connect response status 0x%lx assigned ep 0x%lx\n",
htc_service_name(service_id),
FIELD_GET(HTC_SVC_RESP_MSG_STATUS, resp_msg->flags_len),
FIELD_GET(HTC_SVC_RESP_MSG_ENDPOINTID, resp_msg->flags_len));
@@ -740,14 +748,14 @@ setup:
return status;
ath11k_dbg(ab, ATH11K_DBG_BOOT,
- "boot htc service '%s' ul pipe %d dl pipe %d eid %d ready\n",
+ "htc service '%s' ul pipe %d dl pipe %d eid %d ready\n",
htc_service_name(ep->service_id), ep->ul_pipe_id,
ep->dl_pipe_id, ep->eid);
if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) {
ep->tx_credit_flow_enabled = false;
ath11k_dbg(ab, ATH11K_DBG_BOOT,
- "boot htc service '%s' eid %d TX flow control disabled\n",
+ "htc service '%s' eid %d tx flow control disabled\n",
htc_service_name(ep->service_id), assigned_eid);
}
@@ -773,7 +781,7 @@ int ath11k_htc_start(struct ath11k_htc *htc)
ATH11K_HTC_MSG_SETUP_COMPLETE_EX_ID);
if (ab->hw_params.credit_flow)
- ath11k_dbg(ab, ATH11K_DBG_HTC, "HTC is using TX credit flow control\n");
+ ath11k_dbg(ab, ATH11K_DBG_HTC, "using tx credit flow control\n");
else
msg->flags |= ATH11K_GLOBAL_DISABLE_CREDIT_FLOW;
diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c
index eb995f9cf0fa..d7b5ec6e6904 100644
--- a/drivers/net/wireless/ath/ath11k/hw.c
+++ b/drivers/net/wireless/ath/ath11k/hw.c
@@ -202,6 +202,9 @@ static void ath11k_init_wmi_config_ipq8074(struct ath11k_base *ab,
config->twt_ap_sta_count = 1000;
config->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64;
config->flag1 |= WMI_RSRC_CFG_FLAG1_ACK_RSSI;
+ config->ema_max_vap_cnt = ab->num_radios;
+ config->ema_max_profile_period = TARGET_EMA_MAX_PROFILE_PERIOD;
+ config->beacon_tx_offload_max_vdev += config->ema_max_vap_cnt;
}
static int ath11k_hw_mac_id_to_pdev_id_ipq8074(struct ath11k_hw_params *hw,
@@ -1175,7 +1178,7 @@ const struct ath11k_hw_ops ipq5018_ops = {
.mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid,
.rx_desc_mac_addr2_valid = ath11k_hw_ipq9074_rx_desc_mac_addr2_valid,
.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2,
-
+ .get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector,
};
#define ATH11K_TX_RING_MASK_0 BIT(0)
diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h
index 6a5dd2dbdb3a..f5533630a7f9 100644
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -64,6 +64,7 @@
#define TARGET_NUM_WDS_ENTRIES 32
#define TARGET_DMA_BURST_SIZE 1
#define TARGET_RX_BATCHMODE 1
+#define TARGET_EMA_MAX_PROFILE_PERIOD 8
#define ATH11K_HW_MAX_QUEUES 4
#define ATH11K_QUEUE_LEN 4096
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 1c93f1afccc5..8c77ade49437 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <net/mac80211.h>
@@ -433,7 +433,7 @@ u8 ath11k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
}
static u32
-ath11k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
+ath11k_mac_max_ht_nss(const u8 *ht_mcs_mask)
{
int nss;
@@ -445,7 +445,7 @@ ath11k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
}
static u32
-ath11k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
+ath11k_mac_max_vht_nss(const u16 *vht_mcs_mask)
{
int nss;
@@ -457,7 +457,7 @@ ath11k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
}
static u32
-ath11k_mac_max_he_nss(const u16 he_mcs_mask[NL80211_HE_NSS_MAX])
+ath11k_mac_max_he_nss(const u16 *he_mcs_mask)
{
int nss;
@@ -643,7 +643,10 @@ struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id)
return NULL;
for (i = 0; i < ab->num_radios; i++) {
- pdev = rcu_dereference(ab->pdevs_active[i]);
+ if (ab->fw_mode == ATH11K_FIRMWARE_MODE_FTM)
+ pdev = &ab->pdevs[i];
+ else
+ pdev = rcu_dereference(ab->pdevs_active[i]);
if (pdev && pdev->pdev_id == pdev_id)
return (pdev->ar ? pdev->ar : NULL);
@@ -815,7 +818,7 @@ static int ath11k_recalc_rtscts_prot(struct ath11k_vif *arvif)
arvif->rtscts_prot_mode = rts_cts;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %d recalc rts/cts prot %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %d recalc rts/cts prot %d\n",
arvif->vdev_id, rts_cts);
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
@@ -964,14 +967,14 @@ static int ath11k_mac_monitor_vdev_start(struct ath11k *ar, int vdev_id,
return ret;
}
- ret = ath11k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr);
+ ret = ath11k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr, NULL, 0, 0);
if (ret) {
ath11k_warn(ar->ab, "failed to put up monitor vdev %i: %d\n",
vdev_id, ret);
goto vdev_stop;
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor vdev %i started\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %i started\n",
vdev_id);
return 0;
@@ -1025,7 +1028,7 @@ static int ath11k_mac_monitor_vdev_stop(struct ath11k *ar)
return ret;
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor vdev %i stopped\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %i stopped\n",
ar->monitor_vdev_id);
return 0;
@@ -1096,7 +1099,7 @@ static int ath11k_mac_monitor_vdev_create(struct ath11k *ar)
ar->num_created_vdevs++;
set_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor vdev %d created\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %d created\n",
ar->monitor_vdev_id);
return 0;
@@ -1131,7 +1134,7 @@ static int ath11k_mac_monitor_vdev_delete(struct ath11k *ar)
if (time_left == 0) {
ath11k_warn(ar->ab, "Timeout in receiving vdev delete response\n");
} else {
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor vdev %d deleted\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %d deleted\n",
ar->monitor_vdev_id);
ar->allocated_vdev_map &= ~(1LL << ar->monitor_vdev_id);
@@ -1177,7 +1180,7 @@ static int ath11k_mac_monitor_start(struct ath11k *ar)
return ret;
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor started\n");
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor started\n");
return 0;
}
@@ -1207,7 +1210,7 @@ static int ath11k_mac_monitor_stop(struct ath11k *ar)
return ret;
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor stopped ret %d\n", ret);
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor stopped ret %d\n", ret);
return 0;
}
@@ -1258,7 +1261,7 @@ static int ath11k_mac_vif_setup_ps(struct ath11k_vif *arvif)
psmode = WMI_STA_PS_MODE_DISABLED;
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %d psmode %s\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %d psmode %s\n",
arvif->vdev_id, psmode ? "enable" : "disable");
ret = ath11k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, psmode);
@@ -1351,28 +1354,92 @@ err_mon_del:
return ret;
}
-static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
+static void ath11k_mac_setup_nontx_vif_rsnie(struct ath11k_vif *arvif,
+ bool tx_arvif_rsnie_present,
+ const u8 *profile, u8 profile_len)
{
- struct ath11k *ar = arvif->ar;
- struct ath11k_base *ab = ar->ab;
- struct ieee80211_hw *hw = ar->hw;
- struct ieee80211_vif *vif = arvif->vif;
- struct ieee80211_mutable_offsets offs = {};
- struct sk_buff *bcn;
- struct ieee80211_mgmt *mgmt;
- u8 *ies;
- int ret;
+ if (cfg80211_find_ie(WLAN_EID_RSN, profile, profile_len)) {
+ arvif->rsnie_present = true;
+ } else if (tx_arvif_rsnie_present) {
+ int i;
+ u8 nie_len;
+ const u8 *nie = cfg80211_find_ext_ie(WLAN_EID_EXT_NON_INHERITANCE,
+ profile, profile_len);
+ if (!nie)
+ return;
- if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
- return 0;
+ nie_len = nie[1];
+ nie += 2;
+ for (i = 0; i < nie_len; i++) {
+ if (nie[i] == WLAN_EID_RSN) {
+ arvif->rsnie_present = false;
+ break;
+ }
+ }
+ }
+}
- bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0);
- if (!bcn) {
- ath11k_warn(ab, "failed to get beacon template from mac80211\n");
- return -EPERM;
+static bool ath11k_mac_set_nontx_vif_params(struct ath11k_vif *tx_arvif,
+ struct ath11k_vif *arvif,
+ struct sk_buff *bcn)
+{
+ struct ieee80211_mgmt *mgmt;
+ const u8 *ies, *profile, *next_profile;
+ int ies_len;
+
+ ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
+ mgmt = (struct ieee80211_mgmt *)bcn->data;
+ ies += sizeof(mgmt->u.beacon);
+ ies_len = skb_tail_pointer(bcn) - ies;
+
+ ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ies, ies_len);
+ arvif->rsnie_present = tx_arvif->rsnie_present;
+
+ while (ies) {
+ u8 mbssid_len;
+
+ ies_len -= (2 + ies[1]);
+ mbssid_len = ies[1] - 1;
+ profile = &ies[3];
+
+ while (mbssid_len) {
+ u8 profile_len;
+
+ profile_len = profile[1];
+ next_profile = profile + (2 + profile_len);
+ mbssid_len -= (2 + profile_len);
+
+ profile += 2;
+ profile_len -= (2 + profile[1]);
+ profile += (2 + profile[1]); /* nontx capabilities */
+ profile_len -= (2 + profile[1]);
+ profile += (2 + profile[1]); /* SSID */
+ if (profile[2] == arvif->vif->bss_conf.bssid_index) {
+ profile_len -= 5;
+ profile = profile + 5;
+ ath11k_mac_setup_nontx_vif_rsnie(arvif,
+ tx_arvif->rsnie_present,
+ profile,
+ profile_len);
+ return true;
+ }
+ profile = next_profile;
+ }
+ ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, profile,
+ ies_len);
}
+ return false;
+}
+
+static void ath11k_mac_set_vif_params(struct ath11k_vif *arvif,
+ struct sk_buff *bcn)
+{
+ struct ieee80211_mgmt *mgmt;
+ u8 *ies;
+
ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
+ mgmt = (struct ieee80211_mgmt *)bcn->data;
ies += sizeof(mgmt->u.beacon);
if (cfg80211_find_ie(WLAN_EID_RSN, ies, (skb_tail_pointer(bcn) - ies)))
@@ -1386,9 +1453,95 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
arvif->wpaie_present = true;
else
arvif->wpaie_present = false;
+}
+
+static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif)
+{
+ struct ath11k_vif *tx_arvif;
+ struct ieee80211_ema_beacons *beacons;
+ int ret = 0;
+ bool nontx_vif_params_set = false;
+ u32 params = 0;
+ u8 i = 0;
+
+ tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv;
- ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn);
+ beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->hw,
+ tx_arvif->vif, 0);
+ if (!beacons || !beacons->cnt) {
+ ath11k_warn(arvif->ar->ab,
+ "failed to get ema beacon templates from mac80211\n");
+ return -EPERM;
+ }
+ if (tx_arvif == arvif)
+ ath11k_mac_set_vif_params(tx_arvif, beacons->bcn[0].skb);
+ else
+ arvif->wpaie_present = tx_arvif->wpaie_present;
+
+ for (i = 0; i < beacons->cnt; i++) {
+ if (tx_arvif != arvif && !nontx_vif_params_set)
+ nontx_vif_params_set =
+ ath11k_mac_set_nontx_vif_params(tx_arvif, arvif,
+ beacons->bcn[i].skb);
+
+ params = beacons->cnt;
+ params |= (i << WMI_EMA_TMPL_IDX_SHIFT);
+ params |= ((!i ? 1 : 0) << WMI_EMA_FIRST_TMPL_SHIFT);
+ params |= ((i + 1 == beacons->cnt ? 1 : 0) << WMI_EMA_LAST_TMPL_SHIFT);
+
+ ret = ath11k_wmi_bcn_tmpl(tx_arvif->ar, tx_arvif->vdev_id,
+ &beacons->bcn[i].offs,
+ beacons->bcn[i].skb, params);
+ if (ret) {
+ ath11k_warn(tx_arvif->ar->ab,
+ "failed to set ema beacon template id %i error %d\n",
+ i, ret);
+ break;
+ }
+ }
+
+ ieee80211_beacon_free_ema_list(beacons);
+
+ if (tx_arvif != arvif && !nontx_vif_params_set)
+ return -EINVAL; /* Profile not found in the beacons */
+
+ return ret;
+}
+
+static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif)
+{
+ struct ath11k *ar = arvif->ar;
+ struct ath11k_base *ab = ar->ab;
+ struct ath11k_vif *tx_arvif = arvif;
+ struct ieee80211_hw *hw = ar->hw;
+ struct ieee80211_vif *vif = arvif->vif;
+ struct ieee80211_mutable_offsets offs = {};
+ struct sk_buff *bcn;
+ int ret;
+
+ if (arvif->vif->mbssid_tx_vif) {
+ tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv;
+ if (tx_arvif != arvif) {
+ ar = tx_arvif->ar;
+ ab = ar->ab;
+ hw = ar->hw;
+ vif = tx_arvif->vif;
+ }
+ }
+
+ bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0);
+ if (!bcn) {
+ ath11k_warn(ab, "failed to get beacon template from mac80211\n");
+ return -EPERM;
+ }
+
+ if (tx_arvif == arvif)
+ ath11k_mac_set_vif_params(tx_arvif, bcn);
+ else if (!ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, bcn))
+ return -EINVAL;
+
+ ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn, 0);
kfree_skb(bcn);
if (ret)
@@ -1398,6 +1551,26 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
return ret;
}
+static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
+{
+ struct ieee80211_vif *vif = arvif->vif;
+
+ if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
+ return 0;
+
+ /* Target does not expect beacon templates for the already up
+ * non-transmitting interfaces, and results in a crash if sent.
+ */
+ if (vif->mbssid_tx_vif &&
+ arvif != (void *)vif->mbssid_tx_vif->drv_priv && arvif->is_up)
+ return 0;
+
+ if (vif->bss_conf.ema_ap && vif->mbssid_tx_vif)
+ return ath11k_mac_setup_bcn_tmpl_ema(arvif);
+
+ return ath11k_mac_setup_bcn_tmpl_mbssid(arvif);
+}
+
void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif)
{
struct ieee80211_vif *vif = arvif->vif;
@@ -1423,6 +1596,7 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif,
struct ieee80211_bss_conf *info)
{
struct ath11k *ar = arvif->ar;
+ struct ath11k_vif *tx_arvif = NULL;
int ret = 0;
lockdep_assert_held(&arvif->ar->conf_mutex);
@@ -1451,8 +1625,14 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif,
ether_addr_copy(arvif->bssid, info->bssid);
+ if (arvif->vif->mbssid_tx_vif)
+ tx_arvif = (struct ath11k_vif *)arvif->vif->mbssid_tx_vif->drv_priv;
+
ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
- arvif->bssid);
+ arvif->bssid,
+ tx_arvif ? tx_arvif->bssid : NULL,
+ info->bssid_index,
+ 1 << info->bssid_indicator);
if (ret) {
ath11k_warn(ar->ab, "failed to bring up vdev %d: %i\n",
arvif->vdev_id, ret);
@@ -1461,7 +1641,7 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif,
arvif->is_up = true;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %d up\n", arvif->vdev_id);
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %d up\n", arvif->vdev_id);
}
static void ath11k_mac_handle_beacon_iter(void *data, u8 *mac,
@@ -1658,7 +1838,7 @@ static void ath11k_peer_assoc_h_rates(struct ath11k *ar,
}
static bool
-ath11k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
+ath11k_peer_assoc_h_ht_masked(const u8 *ht_mcs_mask)
{
int nss;
@@ -1670,7 +1850,7 @@ ath11k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
}
static bool
-ath11k_peer_assoc_h_vht_masked(const u16 vht_mcs_mask[])
+ath11k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask)
{
int nss;
@@ -1784,7 +1964,7 @@ static void ath11k_peer_assoc_h_ht(struct ath11k *ar,
arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "ht peer %pM mcs cnt %d nss %d\n",
arg->peer_mac,
arg->peer_ht_rates.num_rates,
arg->peer_nss);
@@ -1948,7 +2128,7 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar,
}
if (!user_rate_valid) {
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac setting vht range mcs value to peer supported nss %d for peer %pM\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "setting vht range mcs value to peer supported nss %d for peer %pM\n",
sta->deflink.rx_nss, sta->addr);
vht_mcs_mask[sta->deflink.rx_nss - 1] = vht_mcs_mask[vht_nss - 1];
}
@@ -2005,7 +2185,7 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac vht peer %pM max_mpdu %d flags 0x%x nss_override 0x%x\n",
+ "vht peer %pM max_mpdu %d flags 0x%x nss_override 0x%x\n",
sta->addr, arg->peer_max_mpdu, arg->peer_flags,
arg->peer_bw_rxnss_override);
}
@@ -2065,7 +2245,7 @@ static u16 ath11k_peer_assoc_h_he_limit(u16 tx_mcs_set,
}
static bool
-ath11k_peer_assoc_h_he_masked(const u16 he_mcs_mask[NL80211_HE_NSS_MAX])
+ath11k_peer_assoc_h_he_masked(const u16 *he_mcs_mask)
{
int nss;
@@ -2230,7 +2410,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
}
if (!user_rate_valid) {
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac setting he range mcs value to peer supported nss %d for peer %pM\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "setting he range mcs value to peer supported nss %d for peer %pM\n",
sta->deflink.rx_nss, sta->addr);
he_mcs_mask[sta->deflink.rx_nss - 1] = he_mcs_mask[he_nss - 1];
}
@@ -2311,7 +2491,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac he peer %pM nss %d mcs cnt %d nss_override 0x%x\n",
+ "he peer %pM nss %d mcs cnt %d nss_override 0x%x\n",
sta->addr, arg->peer_nss,
arg->peer_he_mcs_count,
arg->peer_bw_rxnss_override);
@@ -2431,7 +2611,7 @@ static void ath11k_peer_assoc_h_qos(struct ath11k *ar,
break;
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac peer %pM qos %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "peer %pM qos %d\n",
sta->addr, arg->qos_flag);
}
@@ -2448,7 +2628,7 @@ static int ath11k_peer_assoc_qos_ap(struct ath11k *ar,
params.vdev_id = arvif->vdev_id;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac uapsd_queues 0x%x max_sp %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "uapsd_queues 0x%x max_sp %d\n",
sta->uapsd_queues, sta->max_sp);
uapsd = 0;
@@ -2634,7 +2814,7 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar,
break;
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac peer %pM phymode %s\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "peer %pM phymode %s\n",
sta->addr, ath11k_wmi_phymode_str(phymode));
arg->peer_phymode = phymode;
@@ -2825,7 +3005,7 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
lockdep_assert_held(&ar->conf_mutex);
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %i assoc bssid %pM aid %d\n",
arvif->vdev_id, arvif->bssid, arvif->aid);
rcu_read_lock();
@@ -2879,7 +3059,8 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
arvif->aid = vif->cfg.aid;
ether_addr_copy(arvif->bssid, bss_conf->bssid);
- ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid);
+ ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid,
+ NULL, 0, 0);
if (ret) {
ath11k_warn(ar->ab, "failed to set vdev %d up: %d\n",
arvif->vdev_id, ret);
@@ -2890,7 +3071,7 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
arvif->rekey_data.enable_offload = false;
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac vdev %d up (associated) bssid %pM aid %d\n",
+ "vdev %d up (associated) bssid %pM aid %d\n",
arvif->vdev_id, bss_conf->bssid, vif->cfg.aid);
spin_lock_bh(&ar->ab->base_lock);
@@ -2935,7 +3116,7 @@ static void ath11k_bss_disassoc(struct ieee80211_hw *hw,
lockdep_assert_held(&ar->conf_mutex);
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %i disassoc bssid %pM\n",
arvif->vdev_id, arvif->bssid);
ret = ath11k_wmi_vdev_down(ar, arvif->vdev_id);
@@ -3084,7 +3265,7 @@ static int ath11k_mac_config_obss_pd(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac obss pd sr_ctrl %x non_srg_thres %u srg_max %u\n",
+ "obss pd sr_ctrl %x non_srg_thres %u srg_max %u\n",
he_obss_pd->sr_ctrl, he_obss_pd->non_srg_max_offset,
he_obss_pd->max_offset);
@@ -3412,7 +3593,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
}
if (changed & BSS_CHANGED_TXPOWER) {
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev_id %i txpower %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev_id %i txpower %d\n",
arvif->vdev_id, info->txpower);
arvif->txpower = info->txpower;
@@ -3453,7 +3634,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
rate = ATH11K_HW_RATE_CODE(hw_value, 0, preamble);
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac vdev %d mcast_rate %x\n",
+ "vdev %d mcast_rate %x\n",
arvif->vdev_id, rate);
vdev_param = WMI_VDEV_PARAM_MCAST_DATA_RATE;
@@ -3562,7 +3743,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
memcpy(arvif->arp_ns_offload.mac_addr, vif->addr, ETH_ALEN);
arvif->arp_ns_offload.ipv4_count = ipv4_cnt;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac arp_addr_cnt %d vif->addr %pM, offload_addr %pI4\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "arp_addr_cnt %d vif->addr %pM, offload_addr %pI4\n",
vif->cfg.arp_addr_cnt,
vif->addr, arvif->arp_ns_offload.ipv4_addr);
}
@@ -4160,6 +4341,20 @@ exit:
}
static int
+ath11k_mac_bitrate_mask_num_ht_rates(struct ath11k *ar,
+ enum nl80211_band band,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ int num_rates = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
+ num_rates += hweight8(mask->control[band].ht_mcs[i]);
+
+ return num_rates;
+}
+
+static int
ath11k_mac_bitrate_mask_num_vht_rates(struct ath11k *ar,
enum nl80211_band band,
const struct cfg80211_bitrate_mask *mask)
@@ -4270,7 +4465,7 @@ ath11k_mac_set_peer_he_fixed_rate(struct ath11k_vif *arvif,
return -EINVAL;
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac setting fixed he rate for peer %pM, device will not switch to any other selected rates",
+ "setting fixed he rate for peer %pM, device will not switch to any other selected rates",
sta->addr);
rate_code = ATH11K_HW_RATE_CODE(he_rate, nss - 1,
@@ -4288,6 +4483,54 @@ ath11k_mac_set_peer_he_fixed_rate(struct ath11k_vif *arvif,
return ret;
}
+static int
+ath11k_mac_set_peer_ht_fixed_rate(struct ath11k_vif *arvif,
+ struct ieee80211_sta *sta,
+ const struct cfg80211_bitrate_mask *mask,
+ enum nl80211_band band)
+{
+ struct ath11k *ar = arvif->ar;
+ u8 ht_rate, nss = 0;
+ u32 rate_code;
+ int ret, i;
+
+ lockdep_assert_held(&ar->conf_mutex);
+
+ for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
+ if (hweight8(mask->control[band].ht_mcs[i]) == 1) {
+ nss = i + 1;
+ ht_rate = ffs(mask->control[band].ht_mcs[i]) - 1;
+ }
+ }
+
+ if (!nss) {
+ ath11k_warn(ar->ab, "No single HT Fixed rate found to set for %pM",
+ sta->addr);
+ return -EINVAL;
+ }
+
+ /* Avoid updating invalid nss as fixed rate*/
+ if (nss > sta->deflink.rx_nss)
+ return -EINVAL;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
+ "Setting Fixed HT Rate for peer %pM. Device will not switch to any other selected rates",
+ sta->addr);
+
+ rate_code = ATH11K_HW_RATE_CODE(ht_rate, nss - 1,
+ WMI_RATE_PREAMBLE_HT);
+ ret = ath11k_wmi_set_peer_param(ar, sta->addr,
+ arvif->vdev_id,
+ WMI_PEER_PARAM_FIXED_RATE,
+ rate_code);
+ if (ret)
+ ath11k_warn(ar->ab,
+ "failed to update STA %pM HT Fixed Rate %d: %d\n",
+ sta->addr, rate_code, ret);
+
+ return ret;
+}
+
static int ath11k_station_assoc(struct ath11k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -4299,7 +4542,7 @@ static int ath11k_station_assoc(struct ath11k *ar,
struct cfg80211_chan_def def;
enum nl80211_band band;
struct cfg80211_bitrate_mask *mask;
- u8 num_vht_rates, num_he_rates;
+ u8 num_ht_rates, num_vht_rates, num_he_rates;
lockdep_assert_held(&ar->conf_mutex);
@@ -4327,6 +4570,7 @@ static int ath11k_station_assoc(struct ath11k *ar,
num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask);
num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask);
+ num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band, mask);
/* If single VHT/HE rate is configured (by set_bitrate_mask()),
* peer_assoc will disable VHT/HE. This is now enabled by a peer specific
@@ -4343,6 +4587,11 @@ static int ath11k_station_assoc(struct ath11k *ar,
band);
if (ret)
return ret;
+ } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) {
+ ret = ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask,
+ band);
+ if (ret)
+ return ret;
}
/* Re-assoc is run only to update supported rates for given station. It
@@ -4416,7 +4665,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
const u16 *vht_mcs_mask;
const u16 *he_mcs_mask;
u32 changed, bw, nss, smps, bw_prev;
- int err, num_vht_rates, num_he_rates;
+ int err, num_ht_rates, num_vht_rates, num_he_rates;
const struct cfg80211_bitrate_mask *mask;
struct peer_assoc_params peer_arg;
enum wmi_phy_mode peer_phymode;
@@ -4458,14 +4707,14 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
ath11k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg);
peer_phymode = peer_arg.peer_phymode;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac update sta %pM peer bw %d phymode %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "update sta %pM peer bw %d phymode %d\n",
sta->addr, bw, peer_phymode);
if (bw > bw_prev) {
/* BW is upgraded. In this case we send WMI_PEER_PHYMODE
* followed by WMI_PEER_CHWIDTH
*/
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW upgrade for sta %pM new BW %d, old BW %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "BW upgrade for sta %pM new BW %d, old BW %d\n",
sta->addr, bw, bw_prev);
err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
@@ -4487,7 +4736,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
/* BW is downgraded. In this case we send WMI_PEER_CHWIDTH
* followed by WMI_PEER_PHYMODE
*/
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW downgrade for sta %pM new BW %d,old BW %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "BW downgrade for sta %pM new BW %d,old BW %d\n",
sta->addr, bw, bw_prev);
err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
@@ -4509,7 +4758,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
}
if (changed & IEEE80211_RC_NSS_CHANGED) {
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac update sta %pM nss %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "update sta %pM nss %d\n",
sta->addr, nss);
err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
@@ -4520,7 +4769,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
}
if (changed & IEEE80211_RC_SMPS_CHANGED) {
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac update sta %pM smps %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "update sta %pM smps %d\n",
sta->addr, smps);
err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
@@ -4532,6 +4781,8 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
mask = &arvif->bitrate_mask;
+ num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band,
+ mask);
num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band,
mask);
num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band,
@@ -4554,6 +4805,9 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
} else if (sta->deflink.he_cap.has_he && num_he_rates == 1) {
ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask,
band);
+ } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) {
+ ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask,
+ band);
} else {
/* If the peer is non-VHT/HE or no fixed VHT/HE rate
* is provided in the new bitrate mask we set the
@@ -4973,7 +5227,7 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
spin_unlock_bh(&ar->ab->base_lock);
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n",
+ "sta rc update for %pM changed %08x bw %d nss %d smps %d\n",
sta->addr, changed, sta->deflink.bandwidth,
sta->deflink.rx_nss,
sta->deflink.smps_mode);
@@ -5784,7 +6038,7 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
spin_unlock_bh(&ar->txmgmt_idr_lock);
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac tx mgmt frame, buf id %d\n", buf_id);
+ "tx mgmt frame, buf id %d\n", buf_id);
if (buf_id < 0)
return -ENOSPC;
@@ -5861,7 +6115,7 @@ static void ath11k_mgmt_over_wmi_tx_work(struct work_struct *work)
ath11k_mgmt_over_wmi_tx_drop(ar, skb);
} else {
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac tx mgmt frame, vdev_id %d\n",
+ "tx mgmt frame, vdev_id %d\n",
arvif->vdev_id);
}
} else {
@@ -6020,6 +6274,11 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw)
struct ath11k_pdev *pdev = ar->pdev;
int ret;
+ if (ath11k_ftm_mode) {
+ ath11k_warn(ab, "mac operations not supported in factory test mode\n");
+ return -EOPNOTSUPP;
+ }
+
ath11k_mac_drain_tx(ar);
mutex_lock(&ar->conf_mutex);
@@ -6034,6 +6293,7 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw)
case ATH11K_STATE_RESTARTED:
case ATH11K_STATE_WEDGED:
case ATH11K_STATE_ON:
+ case ATH11K_STATE_FTM:
WARN_ON(1);
ret = -EINVAL;
goto err;
@@ -6181,17 +6441,62 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw)
atomic_set(&ar->num_pending_mgmt_tx, 0);
}
-static void
-ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
- struct vdev_create_params *params)
+static int ath11k_mac_setup_vdev_params_mbssid(struct ath11k_vif *arvif,
+ u32 *flags, u32 *tx_vdev_id)
+{
+ struct ath11k *ar = arvif->ar;
+ struct ath11k_vif *tx_arvif;
+ struct ieee80211_vif *tx_vif;
+
+ *tx_vdev_id = 0;
+ tx_vif = arvif->vif->mbssid_tx_vif;
+ if (!tx_vif) {
+ *flags = WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP;
+ return 0;
+ }
+
+ tx_arvif = (void *)tx_vif->drv_priv;
+
+ if (arvif->vif->bss_conf.nontransmitted) {
+ if (ar->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy)
+ return -EINVAL;
+
+ *flags = WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP;
+ *tx_vdev_id = ath11k_vif_to_arvif(tx_vif)->vdev_id;
+ } else if (tx_arvif == arvif) {
+ *flags = WMI_HOST_VDEV_FLAGS_TRANSMIT_AP;
+ } else {
+ return -EINVAL;
+ }
+
+ if (arvif->vif->bss_conf.ema_ap)
+ *flags |= WMI_HOST_VDEV_FLAGS_EMA_MODE;
+
+ return 0;
+}
+
+static int ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
+ struct vdev_create_params *params)
{
struct ath11k *ar = arvif->ar;
struct ath11k_pdev *pdev = ar->pdev;
+ int ret;
params->if_id = arvif->vdev_id;
params->type = arvif->vdev_type;
params->subtype = arvif->vdev_subtype;
params->pdev_id = pdev->pdev_id;
+ params->mbssid_flags = 0;
+ params->mbssid_tx_vdev_id = 0;
+
+ if (!test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT,
+ ar->ab->wmi_ab.svc_map)) {
+ ret = ath11k_mac_setup_vdev_params_mbssid(arvif,
+ &params->mbssid_flags,
+ &params->mbssid_tx_vdev_id);
+ if (ret)
+ return ret;
+ }
if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) {
params->chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains;
@@ -6206,6 +6511,7 @@ ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
params->chains[NL80211_BAND_6GHZ].tx = ar->num_tx_chains;
params->chains[NL80211_BAND_6GHZ].rx = ar->num_rx_chains;
}
+ return 0;
}
static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
@@ -6281,7 +6587,7 @@ void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id)
mutex_lock(&ar->ab->vdev_id_11d_lock);
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev id for 11d scan %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev id for 11d scan %d\n",
ar->vdev_id_11d_scan);
if (ar->regdom_set_by_user)
@@ -6300,7 +6606,7 @@ void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id)
param.start_interval_msec = 0;
param.scan_period_msec = ATH11K_SCAN_11D_INTERVAL;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac start 11d scan\n");
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "start 11d scan\n");
ret = ath11k_wmi_send_11d_scan_start_cmd(ar, &param);
if (ret) {
@@ -6329,11 +6635,11 @@ void ath11k_mac_11d_scan_stop(struct ath11k *ar)
if (!test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map))
return;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac stop 11d scan\n");
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "stop 11d scan\n");
mutex_lock(&ar->ab->vdev_id_11d_lock);
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac stop 11d vdev id %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "stop 11d vdev id %d\n",
ar->vdev_id_11d_scan);
if (ar->state_11d == ATH11K_11D_PREPARING) {
@@ -6364,7 +6670,7 @@ void ath11k_mac_11d_scan_stop_all(struct ath11k_base *ab)
struct ath11k_pdev *pdev;
int i;
- ath11k_dbg(ab, ATH11K_DBG_MAC, "mac stop soc 11d scan\n");
+ ath11k_dbg(ab, ATH11K_DBG_MAC, "stop soc 11d scan\n");
for (i = 0; i < ab->num_radios; i++) {
pdev = &ab->pdevs[i];
@@ -6492,7 +6798,7 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
break;
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac add interface id %d type %d subtype %d map %llx\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "add interface id %d type %d subtype %d map %llx\n",
arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype,
ab->free_vdev_map);
@@ -6500,7 +6806,12 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++)
vif->hw_queue[i] = i % (ATH11K_HW_MAX_QUEUES - 1);
- ath11k_mac_setup_vdev_create_params(arvif, &vdev_param);
+ ret = ath11k_mac_setup_vdev_create_params(arvif, &vdev_param);
+ if (ret) {
+ ath11k_warn(ab, "failed to create vdev parameters %d: %d\n",
+ arvif->vdev_id, ret);
+ goto err;
+ }
ret = ath11k_wmi_vdev_create(ar, vif->addr, &vdev_param);
if (ret) {
@@ -6678,7 +6989,7 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&ar->conf_mutex);
- ath11k_dbg(ab, ATH11K_DBG_MAC, "mac remove interface (vdev %d)\n",
+ ath11k_dbg(ab, ATH11K_DBG_MAC, "remove interface (vdev %d)\n",
arvif->vdev_id);
ret = ath11k_spectral_vif_stop(arvif);
@@ -6833,7 +7144,7 @@ static int ath11k_mac_op_add_chanctx(struct ieee80211_hw *hw,
struct ath11k_base *ab = ar->ab;
ath11k_dbg(ab, ATH11K_DBG_MAC,
- "mac chanctx add freq %u width %d ptr %pK\n",
+ "chanctx add freq %u width %d ptr %p\n",
ctx->def.chan->center_freq, ctx->def.width, ctx);
mutex_lock(&ar->conf_mutex);
@@ -6857,7 +7168,7 @@ static void ath11k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
struct ath11k_base *ab = ar->ab;
ath11k_dbg(ab, ATH11K_DBG_MAC,
- "mac chanctx remove freq %u width %d ptr %pK\n",
+ "chanctx remove freq %u width %d ptr %p\n",
ctx->def.chan->center_freq, ctx->def.width, ctx);
mutex_lock(&ar->conf_mutex);
@@ -6905,6 +7216,17 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
arg.pref_tx_streams = ar->num_tx_chains;
arg.pref_rx_streams = ar->num_rx_chains;
+ arg.mbssid_flags = 0;
+ arg.mbssid_tx_vdev_id = 0;
+ if (test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT,
+ ar->ab->wmi_ab.svc_map)) {
+ ret = ath11k_mac_setup_vdev_params_mbssid(arvif,
+ &arg.mbssid_flags,
+ &arg.mbssid_tx_vdev_id);
+ if (ret)
+ return ret;
+ }
+
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
arg.ssid = arvif->u.ap.ssid;
arg.ssid_len = arvif->u.ap.ssid_len;
@@ -6926,7 +7248,7 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
arg.channel.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
ath11k_dbg(ab, ATH11K_DBG_MAC,
- "mac vdev %d start center_freq %d phymode %s\n",
+ "vdev %d start center_freq %d phymode %s\n",
arg.vdev_id, arg.channel.freq,
ath11k_wmi_phymode_str(arg.channel.mode));
@@ -7071,7 +7393,8 @@ ath11k_mac_update_vif_chan(struct ath11k *ar,
int n_vifs)
{
struct ath11k_base *ab = ar->ab;
- struct ath11k_vif *arvif;
+ struct ath11k_vif *arvif, *tx_arvif = NULL;
+ struct ieee80211_vif *mbssid_tx_vif;
int ret;
int i;
bool monitor_vif = false;
@@ -7125,8 +7448,15 @@ ath11k_mac_update_vif_chan(struct ath11k *ar,
ath11k_warn(ab, "failed to update bcn tmpl during csa: %d\n",
ret);
+ mbssid_tx_vif = arvif->vif->mbssid_tx_vif;
+ if (mbssid_tx_vif)
+ tx_arvif = (struct ath11k_vif *)mbssid_tx_vif->drv_priv;
+
ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
- arvif->bssid);
+ arvif->bssid,
+ tx_arvif ? tx_arvif->bssid : NULL,
+ arvif->vif->bss_conf.bssid_index,
+ 1 << arvif->vif->bss_conf.bssid_indicator);
if (ret) {
ath11k_warn(ab, "failed to bring vdev up %d: %d\n",
arvif->vdev_id, ret);
@@ -7192,7 +7522,7 @@ static void ath11k_mac_op_change_chanctx(struct ieee80211_hw *hw,
mutex_lock(&ar->conf_mutex);
ath11k_dbg(ab, ATH11K_DBG_MAC,
- "mac chanctx change freq %u width %d ptr %pK changed %x\n",
+ "chanctx change freq %u width %d ptr %p changed %x\n",
ctx->def.chan->center_freq, ctx->def.width, ctx, changed);
/* This shouldn't really happen because channel switching should use
@@ -7244,7 +7574,8 @@ static int ath11k_start_vdev_delay(struct ieee80211_hw *hw,
}
if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
- ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr);
+ ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr,
+ NULL, 0, 0);
if (ret) {
ath11k_warn(ab, "failed put monitor up: %d\n", ret);
return ret;
@@ -7272,7 +7603,7 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
mutex_lock(&ar->conf_mutex);
ath11k_dbg(ab, ATH11K_DBG_MAC,
- "mac chanctx assign ptr %pK vdev_id %i\n",
+ "chanctx assign ptr %p vdev_id %i\n",
ctx, arvif->vdev_id);
/* for QCA6390 bss peer must be created before vdev_start */
@@ -7362,7 +7693,7 @@ ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
mutex_lock(&ar->conf_mutex);
ath11k_dbg(ab, ATH11K_DBG_MAC,
- "mac chanctx unassign ptr %pK vdev_id %i\n",
+ "chanctx unassign ptr %p vdev_id %i\n",
ctx, arvif->vdev_id);
WARN_ON(!arvif->is_started);
@@ -7406,7 +7737,7 @@ ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
arvif->bssid, arvif->vdev_id, ret);
else
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac removed peer %pM vdev %d after vdev stop\n",
+ "removed peer %pM vdev %d after vdev stop\n",
arvif->bssid, arvif->vdev_id);
}
@@ -7441,7 +7772,7 @@ ath11k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
mutex_lock(&ar->conf_mutex);
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac chanctx switch n_vifs %d mode %d\n",
+ "chanctx switch n_vifs %d mode %d\n",
n_vifs, mode);
ath11k_mac_update_vif_chan(ar, vifs, n_vifs);
@@ -7542,20 +7873,6 @@ static void ath11k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v
ath11k_mac_flush_tx_complete(ar);
}
-static int
-ath11k_mac_bitrate_mask_num_ht_rates(struct ath11k *ar,
- enum nl80211_band band,
- const struct cfg80211_bitrate_mask *mask)
-{
- int num_rates = 0;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
- num_rates += hweight16(mask->control[band].ht_mcs[i]);
-
- return num_rates;
-}
-
static bool
ath11k_mac_has_single_legacy_rate(struct ath11k *ar,
enum nl80211_band band,
@@ -7787,7 +8104,7 @@ static int ath11k_mac_set_rate_params(struct ath11k_vif *arvif,
lockdep_assert_held(&ar->conf_mutex);
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac set rate params vdev %i rate 0x%02x nss 0x%02x sgi 0x%02x ldpc 0x%02x he_gi 0x%02x he_ltf 0x%02x he_fixed_rate %d\n",
+ "set rate params vdev %i rate 0x%02x nss 0x%02x sgi 0x%02x ldpc 0x%02x he_gi 0x%02x he_ltf 0x%02x he_fixed_rate %d\n",
arvif->vdev_id, rate, nss, sgi, ldpc, he_gi,
he_ltf, he_fixed_rate);
@@ -8292,7 +8609,7 @@ static void ath11k_mac_put_chain_rssi(struct station_info *sinfo,
arsta->chain_signal[i] = ATH11K_INVALID_RSSI_FULL;
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac sta statistics %s rssi[%d] %d\n", pre, i, rssi);
+ "sta statistics %s rssi[%d] %d\n", pre, i, rssi);
if (rssi != ATH11K_DEFAULT_NOISE_FLOOR &&
rssi != ATH11K_INVALID_RSSI_FULL &&
@@ -8356,7 +8673,7 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,
signal = arsta->rssi_beacon;
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac sta statistics db2dbm %u rssi comb %d rssi beacon %d\n",
+ "sta statistics db2dbm %u rssi comb %d rssi beacon %d\n",
db2dbm, arsta->rssi_comb, arsta->rssi_beacon);
if (signal) {
@@ -8403,7 +8720,7 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw,
struct list_head *p;
u32 count, scope;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac op ipv6 changed\n");
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "op ipv6 changed\n");
offload = &arvif->arp_ns_offload;
count = 0;
@@ -8428,7 +8745,7 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw,
memcpy(offload->ipv6_addr[count], &ifa6->addr.s6_addr,
sizeof(ifa6->addr.s6_addr));
offload->ipv6_type[count] = ATH11K_IPV6_UC_TYPE;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac count %d ipv6 uc %pI6 scope %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "count %d ipv6 uc %pI6 scope %d\n",
count, offload->ipv6_addr[count],
scope);
count++;
@@ -8448,7 +8765,7 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw,
memcpy(offload->ipv6_addr[count], &ifaca6->aca_addr,
sizeof(ifaca6->aca_addr));
offload->ipv6_type[count] = ATH11K_IPV6_AC_TYPE;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac count %d ipv6 ac %pI6 scope %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "count %d ipv6 ac %pI6 scope %d\n",
count, offload->ipv6_addr[count],
scope);
count++;
@@ -8474,7 +8791,7 @@ static void ath11k_mac_op_set_rekey_data(struct ieee80211_hw *hw,
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
struct ath11k_rekey_data *rekey_data = &arvif->rekey_data;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac set rekey data vdev %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "set rekey data vdev %d\n",
arvif->vdev_id);
mutex_lock(&ar->conf_mutex);
@@ -8892,7 +9209,7 @@ static int ath11k_mac_setup_channels_rates(struct ath11k *ar,
}
if (supported_bands & WMI_HOST_WLAN_5G_CAP) {
- if (reg_cap->high_5ghz_chan >= ATH11K_MAX_6G_FREQ) {
+ if (reg_cap->high_5ghz_chan >= ATH11K_MIN_6G_FREQ) {
channels = kmemdup(ath11k_6ghz_channels,
sizeof(ath11k_6ghz_channels), GFP_KERNEL);
if (!channels) {
@@ -9001,19 +9318,23 @@ static int ath11k_mac_setup_iface_combinations(struct ath11k *ar)
static const u8 ath11k_if_types_ext_capa[] = {
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
+ [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
};
static const u8 ath11k_if_types_ext_capa_sta[] = {
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
+ [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
[9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
};
static const u8 ath11k_if_types_ext_capa_ap[] = {
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
+ [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
[9] = WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT,
+ [10] = WLAN_EXT_CAPA11_EMA_SUPPORT,
};
static const struct wiphy_iftype_ext_capab ath11k_iftypes_ext_capa[] = {
@@ -9251,6 +9572,9 @@ static int __ath11k_mac_register(struct ath11k *ar)
wiphy_ext_feature_set(ar->hw->wiphy,
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
+ ar->hw->wiphy->mbssid_max_interfaces = TARGET_NUM_VDEVS(ab);
+ ar->hw->wiphy->ema_max_profile_periodicity = TARGET_EMA_MAX_PROFILE_PERIOD;
+
ath11k_reg_init(ar);
if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) {
@@ -9468,6 +9792,7 @@ void ath11k_mac_destroy(struct ath11k_base *ab)
if (!ar)
continue;
+ ath11k_fw_stats_free(&ar->fw_stats);
ieee80211_free_hw(ar->hw);
pdev->ar = NULL;
}
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
index a62ee05c5409..3ac689f1def4 100644
--- a/drivers/net/wireless/ath/ath11k/mhi.c
+++ b/drivers/net/wireless/ath/ath11k/mhi.c
@@ -211,7 +211,7 @@ void ath11k_mhi_set_mhictrl_reset(struct ath11k_base *ab)
val = ath11k_pcic_read32(ab, MHISTATUS);
- ath11k_dbg(ab, ATH11K_DBG_PCI, "MHISTATUS 0x%x\n", val);
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "mhistatus 0x%x\n", val);
/* Observed on QCA6390 that after SOC_GLOBAL_RESET, MHISTATUS
* has SYSERR bit set and thus need to set MHICTRL_RESET
@@ -263,7 +263,7 @@ static int ath11k_mhi_get_msi(struct ath11k_pci *ab_pci)
if (ret)
return ret;
- ath11k_dbg(ab, ATH11K_DBG_PCI, "Number of assigned MSI for MHI is %d, base vector is %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "num_vectors %d base_vector %d\n",
num_vectors, base_vector);
irq = kcalloc(num_vectors, sizeof(int), GFP_KERNEL);
@@ -325,7 +325,7 @@ static void ath11k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl,
{
struct ath11k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev);
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "mhi notify status reason %s\n",
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "notify status reason %s\n",
ath11k_mhi_op_callback_to_str(cb));
switch (cb) {
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index 7b33731a50ee..79e2cbe82638 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/module.h>
@@ -203,10 +203,10 @@ static void ath11k_pci_clear_dbg_registers(struct ath11k_base *ab)
/* read cookie */
val = ath11k_pcic_read32(ab, PCIE_Q6_COOKIE_ADDR);
- ath11k_dbg(ab, ATH11K_DBG_PCI, "cookie:0x%x\n", val);
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "pcie_q6_cookie_addr 0x%x\n", val);
val = ath11k_pcic_read32(ab, WLAON_WARM_SW_ENTRY);
- ath11k_dbg(ab, ATH11K_DBG_PCI, "WLAON_WARM_SW_ENTRY 0x%x\n", val);
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "wlaon_warm_sw_entry 0x%x\n", val);
/* TODO: exact time to sleep is uncertain */
mdelay(10);
@@ -218,13 +218,13 @@ static void ath11k_pci_clear_dbg_registers(struct ath11k_base *ab)
mdelay(10);
val = ath11k_pcic_read32(ab, WLAON_WARM_SW_ENTRY);
- ath11k_dbg(ab, ATH11K_DBG_PCI, "WLAON_WARM_SW_ENTRY 0x%x\n", val);
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "wlaon_warm_sw_entry 0x%x\n", val);
/* A read clear register. clear the register to prevent
* Q6 from entering wrong code path.
*/
val = ath11k_pcic_read32(ab, WLAON_SOC_RESET_CAUSE_REG);
- ath11k_dbg(ab, ATH11K_DBG_PCI, "soc reset cause:%d\n", val);
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "soc reset cause %d\n", val);
}
static int ath11k_pci_set_link_reg(struct ath11k_base *ab,
@@ -312,14 +312,14 @@ static void ath11k_pci_enable_ltssm(struct ath11k_base *ab)
val = ath11k_pcic_read32(ab, PCIE_PCIE_PARF_LTSSM);
}
- ath11k_dbg(ab, ATH11K_DBG_PCI, "pci ltssm 0x%x\n", val);
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "ltssm 0x%x\n", val);
val = ath11k_pcic_read32(ab, GCC_GCC_PCIE_HOT_RST);
val |= GCC_GCC_PCIE_HOT_RST_VAL;
ath11k_pcic_write32(ab, GCC_GCC_PCIE_HOT_RST, val);
val = ath11k_pcic_read32(ab, GCC_GCC_PCIE_HOT_RST);
- ath11k_dbg(ab, ATH11K_DBG_PCI, "pci pcie_hot_rst 0x%x\n", val);
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "pcie_hot_rst 0x%x\n", val);
mdelay(5);
}
@@ -433,7 +433,7 @@ static int ath11k_pci_alloc_msi(struct ath11k_pci *ab_pci)
}
clear_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags);
ab->pci.msi.config = &msi_config_one_msi;
- ath11k_dbg(ab, ATH11K_DBG_PCI, "request MSI one vector\n");
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "request one msi vector\n");
}
ath11k_info(ab, "MSI vectors: %d\n", num_vectors);
@@ -487,7 +487,7 @@ static int ath11k_pci_config_msi_data(struct ath11k_pci *ab_pci)
ab_pci->ab->pci.msi.ep_base_data = msi_desc->msg.data;
- ath11k_dbg(ab_pci->ab, ATH11K_DBG_PCI, "pci after request_irq msi_ep_base_data %d\n",
+ ath11k_dbg(ab_pci->ab, ATH11K_DBG_PCI, "after request_irq msi_ep_base_data %d\n",
ab_pci->ab->pci.msi.ep_base_data);
return 0;
@@ -545,7 +545,7 @@ static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
ab->mem_ce = ab->mem;
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem);
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "pci_mem 0x%p\n", ab->mem);
return 0;
release_region:
@@ -575,7 +575,7 @@ static void ath11k_pci_aspm_disable(struct ath11k_pci *ab_pci)
pcie_capability_read_word(ab_pci->pdev, PCI_EXP_LNKCTL,
&ab_pci->link_ctl);
- ath11k_dbg(ab, ATH11K_DBG_PCI, "pci link_ctl 0x%04x L0s %d L1 %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "link_ctl 0x%04x L0s %d L1 %d\n",
ab_pci->link_ctl,
u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L0S),
u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L1));
@@ -709,7 +709,7 @@ static void ath11k_pci_read_hw_version(struct ath11k_base *ab, u32 *major, u32 *
*minor = FIELD_GET(TCSR_SOC_HW_VERSION_MINOR_MASK,
soc_hw_version);
- ath11k_dbg(ab, ATH11K_DBG_PCI, "pci tcsr_soc_hw_version major %d minor %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "tcsr_soc_hw_version major %d minor %d\n",
*major, *minor);
}
@@ -745,6 +745,7 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
ab_pci->ab = ab;
ab_pci->pdev = pdev;
ab->hif.ops = &ath11k_pci_hif_ops;
+ ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL;
pci_set_drvdata(pdev, ab);
spin_lock_init(&ab_pci->window_lock);
diff --git a/drivers/net/wireless/ath/ath11k/pcic.c b/drivers/net/wireless/ath/ath11k/pcic.c
index 30d66147223f..c63083633b37 100644
--- a/drivers/net/wireless/ath/ath11k/pcic.c
+++ b/drivers/net/wireless/ath/ath11k/pcic.c
@@ -263,7 +263,7 @@ int ath11k_pcic_get_user_msi_assignment(struct ath11k_base *ab, char *user_name,
*user_base_data = *base_vector + ab->pci.msi.ep_base_data;
ath11k_dbg(ab, ATH11K_DBG_PCI,
- "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n",
+ "msi assignment %s num_vectors %d user_base_data %u base_vector %u\n",
user_name, *num_vectors, *user_base_data,
*base_vector);
@@ -466,7 +466,6 @@ void ath11k_pcic_ext_irq_enable(struct ath11k_base *ab)
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
if (!irq_grp->napi_enabled) {
- dev_set_threaded(&irq_grp->napi_ndev, true);
napi_enable(&irq_grp->napi);
irq_grp->napi_enabled = true;
}
@@ -527,7 +526,7 @@ static irqreturn_t ath11k_pcic_ext_interrupt_handler(int irq, void *arg)
if (!test_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags))
return IRQ_HANDLED;
- ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq:%d\n", irq);
+ ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq %d\n", irq);
/* last interrupt received for this group */
irq_grp->timestamp = jiffies;
@@ -597,7 +596,7 @@ static int ath11k_pcic_ext_irq_config(struct ath11k_base *ab)
ab->irq_num[irq_idx] = irq;
ath11k_dbg(ab, ATH11K_DBG_PCI,
- "irq:%d group:%d\n", irq, i);
+ "irq %d group %d\n", irq, i);
irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY);
ret = request_irq(irq, ath11k_pcic_ext_interrupt_handler,
diff --git a/drivers/net/wireless/ath/ath11k/peer.c b/drivers/net/wireless/ath/ath11k/peer.c
index 1380811827a8..114aa3a9a339 100644
--- a/drivers/net/wireless/ath/ath11k/peer.c
+++ b/drivers/net/wireless/ath/ath11k/peer.c
@@ -106,7 +106,7 @@ void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id)
goto exit;
}
- ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt peer unmap vdev %d peer %pM id %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "peer unmap vdev %d peer %pM id %d\n",
peer->vdev_id, peer->addr, peer_id);
list_del(&peer->list);
@@ -138,7 +138,7 @@ void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id,
wake_up(&ab->peer_mapping_wq);
}
- ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt peer map vdev %d peer %pM id %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "peer map vdev %d peer %pM id %d\n",
vdev_id, mac_addr, peer_id);
exit:
diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c
index ab923e24b0a9..d4eaf7d2ba84 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 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.
*/
#include <linux/elf.h>
@@ -1755,7 +1755,7 @@ static int ath11k_qmi_host_cap_send(struct ath11k_base *ab)
req.nm_modem |= PLATFORM_CAP_PCIE_PME_D3COLD;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi host cap request\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "host cap request\n");
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_host_cap_resp_msg_v01_ei, &resp);
@@ -1833,7 +1833,7 @@ static int ath11k_qmi_fw_ind_register_send(struct ath11k_base *ab)
if (ret < 0)
goto out;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi indication register request\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "indication register request\n");
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_IND_REGISTER_REQ_V01,
@@ -1889,7 +1889,7 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
test_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags)) &&
ab->qmi.target_mem_delayed) {
delayed = true;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi delays mem_request %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "delays mem_request %d\n",
ab->qmi.mem_seg_count);
memset(req, 0, sizeof(*req));
} else {
@@ -1901,7 +1901,7 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
req->mem_seg[i].size = ab->qmi.target_mem[i].size;
req->mem_seg[i].type = ab->qmi.target_mem[i].type;
ath11k_dbg(ab, ATH11K_DBG_QMI,
- "qmi req mem_seg[%d] %pad %u %u\n", i,
+ "req mem_seg[%d] %pad %u %u\n", i,
&ab->qmi.target_mem[i].paddr,
ab->qmi.target_mem[i].size,
ab->qmi.target_mem[i].type);
@@ -1913,7 +1913,7 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
if (ret < 0)
goto out;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi respond memory request delayed %i\n",
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "respond memory request delayed %i\n",
delayed);
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
@@ -2002,7 +2002,7 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
if (!chunk->vaddr) {
if (ab->qmi.mem_seg_count <= ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT) {
ath11k_dbg(ab, ATH11K_DBG_QMI,
- "qmi dma allocation failed (%d B type %u), will try later with small size\n",
+ "dma allocation failed (%d B type %u), will try later with small size\n",
chunk->size,
chunk->type);
ath11k_qmi_free_target_mem_chunk(ab);
@@ -2036,7 +2036,7 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
hremote_node = of_parse_phandle(dev->of_node, "memory-region", 0);
if (!hremote_node) {
ath11k_dbg(ab, ATH11K_DBG_QMI,
- "qmi fail to get hremote_node\n");
+ "fail to get hremote_node\n");
return -ENODEV;
}
@@ -2044,13 +2044,13 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
of_node_put(hremote_node);
if (ret) {
ath11k_dbg(ab, ATH11K_DBG_QMI,
- "qmi fail to get reg from hremote\n");
+ "fail to get reg from hremote\n");
return ret;
}
if (res.end - res.start + 1 < ab->qmi.target_mem[i].size) {
ath11k_dbg(ab, ATH11K_DBG_QMI,
- "qmi fail to assign memory of sz\n");
+ "fail to assign memory of sz\n");
return -EINVAL;
}
@@ -2058,6 +2058,9 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
ab->qmi.target_mem[idx].iaddr =
ioremap(ab->qmi.target_mem[idx].paddr,
ab->qmi.target_mem[i].size);
+ if (!ab->qmi.target_mem[idx].iaddr)
+ return -EIO;
+
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
host_ddr_sz = ab->qmi.target_mem[i].size;
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
@@ -2083,6 +2086,8 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
ab->qmi.target_mem[idx].iaddr =
ioremap(ab->qmi.target_mem[idx].paddr,
ab->qmi.target_mem[i].size);
+ if (!ab->qmi.target_mem[idx].iaddr)
+ return -EIO;
} else {
ab->qmi.target_mem[idx].paddr =
ATH11K_QMI_CALDB_ADDRESS;
@@ -2198,7 +2203,7 @@ static int ath11k_qmi_request_target_cap(struct ath11k_base *ab)
if (ret < 0)
goto out;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi target cap request\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "target cap request\n");
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_CAP_REQ_V01,
@@ -2251,7 +2256,7 @@ static int ath11k_qmi_request_target_cap(struct ath11k_base *ab)
if (resp.eeprom_read_timeout_valid) {
ab->qmi.target.eeprom_caldata =
resp.eeprom_read_timeout;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi cal data supported from eeprom\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "cal data supported from eeprom\n");
}
fw_build_id = ab->qmi.target.fw_build_id;
@@ -2348,7 +2353,7 @@ static int ath11k_qmi_load_file_target_mem(struct ath11k_base *ab,
if (ret < 0)
goto err_iounmap;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf download req fixed addr type %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "bdf download req fixed addr type %d\n",
type);
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
@@ -2381,7 +2386,7 @@ static int ath11k_qmi_load_file_target_mem(struct ath11k_base *ab,
remaining -= req->data_len;
temp += req->data_len;
req->seg_id++;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf download request remaining %i\n",
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "bdf download request remaining %i\n",
remaining);
}
}
@@ -2427,7 +2432,7 @@ static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab,
else
bdf_type = ATH11K_QMI_BDF_TYPE_BIN;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf_type %d\n", bdf_type);
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "bdf_type %d\n", bdf_type);
fw_size = min_t(u32, ab->hw_params.fw.board_size, bd.len);
@@ -2457,6 +2462,14 @@ static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab,
fw_entry = ath11k_core_firmware_request(ab, ATH11K_DEFAULT_CAL_FILE);
if (IS_ERR(fw_entry)) {
+ /* Caldata may not be present during first time calibration in
+ * factory hence allow to boot without loading caldata in ftm mode
+ */
+ if (ath11k_ftm_mode) {
+ ath11k_info(ab,
+ "Booting without cal data file in factory test mode\n");
+ return 0;
+ }
ret = PTR_ERR(fw_entry);
ath11k_warn(ab,
"qmi failed to load CAL data file:%s\n",
@@ -2474,14 +2487,14 @@ success:
goto out_qmi_cal;
}
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi caldata type: %u\n", file_type);
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "caldata type: %u\n", file_type);
out_qmi_cal:
if (!ab->qmi.target.eeprom_caldata)
release_firmware(fw_entry);
out:
ath11k_core_free_bdf(ab, &bd);
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi BDF download sequence completed\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "BDF download sequence completed\n");
return ret;
}
@@ -2566,7 +2579,7 @@ static int ath11k_qmi_wlanfw_m3_info_send(struct ath11k_base *ab)
if (ret < 0)
goto out;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi m3 info req\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "m3 info req\n");
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_M3_INFO_REQ_V01,
@@ -2615,7 +2628,7 @@ static int ath11k_qmi_wlanfw_mode_send(struct ath11k_base *ab,
if (ret < 0)
goto out;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi wlan mode req mode %d\n", mode);
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "wlan mode req mode %d\n", mode);
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_WLAN_MODE_REQ_V01,
@@ -2710,7 +2723,7 @@ static int ath11k_qmi_wlanfw_wlan_cfg_send(struct ath11k_base *ab)
if (ret < 0)
goto out;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi wlan cfg req\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "wlan cfg req\n");
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_WLAN_CFG_REQ_V01,
@@ -2787,7 +2800,7 @@ void ath11k_qmi_firmware_stop(struct ath11k_base *ab)
{
int ret;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware stop\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware stop\n");
ret = ath11k_qmi_wlanfw_mode_send(ab, ATH11K_FIRMWARE_MODE_OFF);
if (ret < 0) {
@@ -2801,7 +2814,7 @@ int ath11k_qmi_firmware_start(struct ath11k_base *ab,
{
int ret;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware start\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware start\n");
if (ab->hw_params.fw_wmi_diag_event) {
ret = ath11k_qmi_wlanfw_wlan_ini_send(ab, true);
@@ -2959,7 +2972,7 @@ static void ath11k_qmi_msg_mem_request_cb(struct qmi_handle *qmi_hdl,
const struct qmi_wlanfw_request_mem_ind_msg_v01 *msg = data;
int i, ret;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware request memory request\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware request memory request\n");
if (msg->mem_seg_len == 0 ||
msg->mem_seg_len > ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01)
@@ -2971,7 +2984,7 @@ static void ath11k_qmi_msg_mem_request_cb(struct qmi_handle *qmi_hdl,
for (i = 0; i < qmi->mem_seg_count ; i++) {
ab->qmi.target_mem[i].type = msg->mem_seg[i].type;
ab->qmi.target_mem[i].size = msg->mem_seg[i].size;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi mem seg type %d size %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "mem seg type %d size %d\n",
msg->mem_seg[i].type, msg->mem_seg[i].size);
}
@@ -3003,7 +3016,7 @@ static void ath11k_qmi_msg_mem_ready_cb(struct qmi_handle *qmi_hdl,
struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle);
struct ath11k_base *ab = qmi->ab;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware memory ready indication\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware memory ready indication\n");
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_FW_MEM_READY, NULL);
}
@@ -3015,7 +3028,7 @@ static void ath11k_qmi_msg_fw_ready_cb(struct qmi_handle *qmi_hdl,
struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle);
struct ath11k_base *ab = qmi->ab;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware ready\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware ready\n");
if (!ab->qmi.cal_done) {
ab->qmi.cal_done = 1;
@@ -3036,7 +3049,7 @@ static void ath11k_qmi_msg_cold_boot_cal_done_cb(struct qmi_handle *qmi_hdl,
ab->qmi.cal_done = 1;
wake_up(&ab->qmi.cold_boot_waitq);
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi cold boot calibration done\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "cold boot calibration done\n");
}
static void ath11k_qmi_msg_fw_init_done_cb(struct qmi_handle *qmi_hdl,
@@ -3049,7 +3062,7 @@ static void ath11k_qmi_msg_fw_init_done_cb(struct qmi_handle *qmi_hdl,
struct ath11k_base *ab = qmi->ab;
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_FW_INIT_DONE, NULL);
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware init done\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware init done\n");
}
static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = {
@@ -3114,7 +3127,7 @@ static int ath11k_qmi_ops_new_server(struct qmi_handle *qmi_hdl,
return ret;
}
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi wifi fw qmi service connected\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "wifi fw qmi service connected\n");
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_SERVER_ARRIVE, NULL);
return ret;
@@ -3126,7 +3139,7 @@ static void ath11k_qmi_ops_del_server(struct qmi_handle *qmi_hdl,
struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle);
struct ath11k_base *ab = qmi->ab;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi wifi fw del server\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "wifi fw del server\n");
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_SERVER_EXIT, NULL);
}
@@ -3256,8 +3269,7 @@ int ath11k_qmi_init_service(struct ath11k_base *ab)
return ret;
}
- ab->qmi.event_wq = alloc_workqueue("ath11k_qmi_driver_event",
- WQ_UNBOUND, 1);
+ ab->qmi.event_wq = alloc_ordered_workqueue("ath11k_qmi_driver_event", 0);
if (!ab->qmi.event_wq) {
ath11k_err(ab, "failed to allocate workqueue\n");
return -EFAULT;
diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c
index 67443457f4da..7f9fb968dac6 100644
--- a/drivers/net/wireless/ath/ath11k/reg.c
+++ b/drivers/net/wireless/ath/ath11k/reg.c
@@ -123,7 +123,7 @@ int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait)
ar->state_11d = ATH11K_11D_IDLE;
}
ath11k_dbg(ar->ab, ATH11K_DBG_REG,
- "reg 11d scan wait left time %d\n", left);
+ "11d scan wait left time %d\n", left);
}
if (wait &&
@@ -136,7 +136,7 @@ int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait)
"failed to receive hw scan complete: timed out\n");
ath11k_dbg(ar->ab, ATH11K_DBG_REG,
- "reg hw scan wait left time %d\n", left);
+ "hw scan wait left time %d\n", left);
}
if (ar->state == ATH11K_STATE_RESTARTING)
diff --git a/drivers/net/wireless/ath/ath11k/testmode.c b/drivers/net/wireless/ath/ath11k/testmode.c
index 4bf1931adbaa..8fc5cddb28bd 100644
--- a/drivers/net/wireless/ath/ath11k/testmode.c
+++ b/drivers/net/wireless/ath/ath11k/testmode.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "testmode.h"
@@ -11,6 +12,9 @@
#include "core.h"
#include "testmode_i.h"
+#define ATH11K_FTM_SEGHDR_CURRENT_SEQ GENMASK(3, 0)
+#define ATH11K_FTM_SEGHDR_TOTAL_SEGMENTS GENMASK(7, 4)
+
static const struct nla_policy ath11k_tm_policy[ATH11K_TM_ATTR_MAX + 1] = {
[ATH11K_TM_ATTR_CMD] = { .type = NLA_U32 },
[ATH11K_TM_ATTR_DATA] = { .type = NLA_BINARY,
@@ -20,58 +24,162 @@ static const struct nla_policy ath11k_tm_policy[ATH11K_TM_ATTR_MAX + 1] = {
[ATH11K_TM_ATTR_VERSION_MINOR] = { .type = NLA_U32 },
};
-/* Returns true if callee consumes the skb and the skb should be discarded.
- * Returns false if skb is not used. Does not sleep.
+static struct ath11k *ath11k_tm_get_ar(struct ath11k_base *ab)
+{
+ struct ath11k_pdev *pdev;
+ struct ath11k *ar = NULL;
+ int i;
+
+ for (i = 0; i < ab->num_radios; i++) {
+ pdev = &ab->pdevs[i];
+ ar = pdev->ar;
+
+ if (ar && ar->state == ATH11K_STATE_FTM)
+ break;
+ }
+
+ return ar;
+}
+
+/* This function handles unsegmented events. Data in various events are aggregated
+ * in application layer, this event is unsegmented from host perspective.
*/
-bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, struct sk_buff *skb)
+static void ath11k_tm_wmi_event_unsegmented(struct ath11k_base *ab, u32 cmd_id,
+ struct sk_buff *skb)
{
struct sk_buff *nl_skb;
- bool consumed;
- int ret;
+ struct ath11k *ar;
- ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE,
- "testmode event wmi cmd_id %d skb %pK skb->len %d\n",
- cmd_id, skb, skb->len);
+ ath11k_dbg(ab, ATH11K_DBG_TESTMODE,
+ "event wmi cmd_id %d skb length %d\n",
+ cmd_id, skb->len);
+ ath11k_dbg_dump(ab, ATH11K_DBG_TESTMODE, NULL, "", skb->data, skb->len);
- ath11k_dbg_dump(ar->ab, ATH11K_DBG_TESTMODE, NULL, "", skb->data, skb->len);
+ ar = ath11k_tm_get_ar(ab);
+ if (!ar) {
+ ath11k_warn(ab, "testmode event not handled due to invalid pdev\n");
+ return;
+ }
spin_lock_bh(&ar->data_lock);
- consumed = true;
-
nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy,
- 2 * sizeof(u32) + skb->len,
+ 2 * nla_total_size(sizeof(u32)) +
+ nla_total_size(skb->len),
GFP_ATOMIC);
if (!nl_skb) {
- ath11k_warn(ar->ab,
- "failed to allocate skb for testmode wmi event\n");
+ ath11k_warn(ab,
+ "failed to allocate skb for unsegmented testmode wmi event\n");
goto out;
}
- ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, ATH11K_TM_CMD_WMI);
- if (ret) {
- ath11k_warn(ar->ab,
- "failed to put testmode wmi event cmd attribute: %d\n",
- ret);
+ if (nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, ATH11K_TM_CMD_WMI) ||
+ nla_put_u32(nl_skb, ATH11K_TM_ATTR_WMI_CMDID, cmd_id) ||
+ nla_put(nl_skb, ATH11K_TM_ATTR_DATA, skb->len, skb->data)) {
+ ath11k_warn(ab, "failed to populate testmode unsegmented event\n");
kfree_skb(nl_skb);
goto out;
}
- ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_WMI_CMDID, cmd_id);
- if (ret) {
- ath11k_warn(ar->ab,
- "failed to put testmode wmi even cmd_id: %d\n",
- ret);
- kfree_skb(nl_skb);
+ cfg80211_testmode_event(nl_skb, GFP_ATOMIC);
+ spin_unlock_bh(&ar->data_lock);
+ return;
+
+out:
+ spin_unlock_bh(&ar->data_lock);
+ ath11k_warn(ab, "Failed to send testmode event to higher layers\n");
+}
+
+/* This function handles segmented events. Data of various events received
+ * from firmware is aggregated and sent to application layer
+ */
+static int ath11k_tm_process_event(struct ath11k_base *ab, u32 cmd_id,
+ const struct wmi_ftm_event_msg *ftm_msg,
+ u16 length)
+{
+ struct sk_buff *nl_skb;
+ int ret = 0;
+ struct ath11k *ar;
+ u8 const *buf_pos;
+ u16 datalen;
+ u8 total_segments, current_seq;
+ u32 data_pos;
+ u32 pdev_id;
+
+ ath11k_dbg(ab, ATH11K_DBG_TESTMODE,
+ "event wmi cmd_id %d ftm event msg %pK datalen %d\n",
+ cmd_id, ftm_msg, length);
+ ath11k_dbg_dump(ab, ATH11K_DBG_TESTMODE, NULL, "", ftm_msg, length);
+ pdev_id = DP_HW2SW_MACID(ftm_msg->seg_hdr.pdev_id);
+
+ if (pdev_id >= ab->num_radios) {
+ ath11k_warn(ab, "testmode event not handled due to invalid pdev id: %d\n",
+ pdev_id);
+ return -EINVAL;
+ }
+
+ ar = ab->pdevs[pdev_id].ar;
+ if (!ar) {
+ ath11k_warn(ab, "testmode event not handled due to absence of pdev\n");
+ return -ENODEV;
+ }
+
+ current_seq = FIELD_GET(ATH11K_FTM_SEGHDR_CURRENT_SEQ,
+ ftm_msg->seg_hdr.segmentinfo);
+ total_segments = FIELD_GET(ATH11K_FTM_SEGHDR_TOTAL_SEGMENTS,
+ ftm_msg->seg_hdr.segmentinfo);
+ datalen = length - (sizeof(struct wmi_ftm_seg_hdr));
+ buf_pos = ftm_msg->data;
+
+ spin_lock_bh(&ar->data_lock);
+
+ if (current_seq == 0) {
+ ab->testmode.expected_seq = 0;
+ ab->testmode.data_pos = 0;
+ }
+
+ data_pos = ab->testmode.data_pos;
+
+ if ((data_pos + datalen) > ATH11K_FTM_EVENT_MAX_BUF_LENGTH) {
+ ath11k_warn(ab, "Invalid ftm event length at %d: %d\n",
+ data_pos, datalen);
+ ret = -EINVAL;
goto out;
}
- ret = nla_put(nl_skb, ATH11K_TM_ATTR_DATA, skb->len, skb->data);
- if (ret) {
- ath11k_warn(ar->ab,
- "failed to copy skb to testmode wmi event: %d\n",
- ret);
+ memcpy(&ab->testmode.eventdata[data_pos], buf_pos, datalen);
+ data_pos += datalen;
+
+ if (++ab->testmode.expected_seq != total_segments) {
+ ab->testmode.data_pos = data_pos;
+ ath11k_dbg(ab, ATH11K_DBG_TESTMODE,
+ "partial data received current_seq %d total_seg %d\n",
+ current_seq, total_segments);
+ goto out;
+ }
+
+ ath11k_dbg(ab, ATH11K_DBG_TESTMODE,
+ "total data length pos %d len %d\n",
+ data_pos, ftm_msg->seg_hdr.len);
+ nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy,
+ 2 * nla_total_size(sizeof(u32)) +
+ nla_total_size(data_pos),
+ GFP_ATOMIC);
+ if (!nl_skb) {
+ ath11k_warn(ab,
+ "failed to allocate skb for segmented testmode wmi event\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD,
+ ATH11K_TM_CMD_WMI_FTM) ||
+ nla_put_u32(nl_skb, ATH11K_TM_ATTR_WMI_CMDID, cmd_id) ||
+ nla_put(nl_skb, ATH11K_TM_ATTR_DATA, data_pos,
+ &ab->testmode.eventdata[0])) {
+ ath11k_warn(ab, "failed to populate segmented testmode event");
kfree_skb(nl_skb);
+ ret = -ENOBUFS;
goto out;
}
@@ -79,8 +187,45 @@ bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, struct sk_buff *skb)
out:
spin_unlock_bh(&ar->data_lock);
+ return ret;
+}
+
+static void ath11k_tm_wmi_event_segmented(struct ath11k_base *ab, u32 cmd_id,
+ struct sk_buff *skb)
+{
+ const void **tb;
+ const struct wmi_ftm_event_msg *ev;
+ u16 length;
+ int ret;
+
+ tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
+ if (IS_ERR(tb)) {
+ ret = PTR_ERR(tb);
+ ath11k_warn(ab, "failed to parse ftm event tlv: %d\n", ret);
+ return;
+ }
+
+ ev = tb[WMI_TAG_ARRAY_BYTE];
+ if (!ev) {
+ ath11k_warn(ab, "failed to fetch ftm msg\n");
+ kfree(tb);
+ return;
+ }
- return consumed;
+ length = skb->len - TLV_HDR_SIZE;
+ ret = ath11k_tm_process_event(ab, cmd_id, ev, length);
+ if (ret)
+ ath11k_warn(ab, "Failed to process ftm event\n");
+
+ kfree(tb);
+}
+
+void ath11k_tm_wmi_event(struct ath11k_base *ab, u32 cmd_id, struct sk_buff *skb)
+{
+ if (test_bit(ATH11K_FLAG_FTM_SEGMENTED, &ab->dev_flags))
+ ath11k_tm_wmi_event_segmented(ab, cmd_id, skb);
+ else
+ ath11k_tm_wmi_event_unsegmented(ab, cmd_id, skb);
}
static int ath11k_tm_cmd_get_version(struct ath11k *ar, struct nlattr *tb[])
@@ -89,7 +234,7 @@ static int ath11k_tm_cmd_get_version(struct ath11k *ar, struct nlattr *tb[])
int ret;
ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE,
- "testmode cmd get version_major %d version_minor %d\n",
+ "cmd get version_major %d version_minor %d\n",
ATH11K_TESTMODE_VERSION_MAJOR,
ATH11K_TESTMODE_VERSION_MINOR);
@@ -115,21 +260,56 @@ static int ath11k_tm_cmd_get_version(struct ath11k *ar, struct nlattr *tb[])
return cfg80211_testmode_reply(skb);
}
-static int ath11k_tm_cmd_wmi(struct ath11k *ar, struct nlattr *tb[])
+static int ath11k_tm_cmd_testmode_start(struct ath11k *ar, struct nlattr *tb[])
+{
+ int ret;
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->state == ATH11K_STATE_FTM) {
+ ret = -EALREADY;
+ goto err;
+ }
+
+ /* start utf only when the driver is not in use */
+ if (ar->state != ATH11K_STATE_OFF) {
+ ret = -EBUSY;
+ goto err;
+ }
+
+ ar->ab->testmode.eventdata = kzalloc(ATH11K_FTM_EVENT_MAX_BUF_LENGTH,
+ GFP_KERNEL);
+ if (!ar->ab->testmode.eventdata) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ ar->state = ATH11K_STATE_FTM;
+ ar->ftm_msgref = 0;
+
+ mutex_unlock(&ar->conf_mutex);
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, "cmd start\n");
+ return 0;
+
+err:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
+static int ath11k_tm_cmd_wmi(struct ath11k *ar, struct nlattr *tb[],
+ struct ieee80211_vif *vif)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
struct sk_buff *skb;
+ struct ath11k_vif *arvif;
u32 cmd_id, buf_len;
- int ret;
+ int ret, tag;
void *buf;
+ u32 *ptr;
mutex_lock(&ar->conf_mutex);
- if (ar->state != ATH11K_STATE_ON) {
- ret = -ENETDOWN;
- goto out;
- }
-
if (!tb[ATH11K_TM_ATTR_DATA]) {
ret = -EINVAL;
goto out;
@@ -142,11 +322,45 @@ static int ath11k_tm_cmd_wmi(struct ath11k *ar, struct nlattr *tb[])
buf = nla_data(tb[ATH11K_TM_ATTR_DATA]);
buf_len = nla_len(tb[ATH11K_TM_ATTR_DATA]);
+ if (!buf_len) {
+ ath11k_warn(ar->ab, "No data present in testmode wmi command\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
cmd_id = nla_get_u32(tb[ATH11K_TM_ATTR_WMI_CMDID]);
+ /* Make sure that the buffer length is long enough to
+ * hold TLV and pdev/vdev id.
+ */
+ if (buf_len < sizeof(struct wmi_tlv) + sizeof(u32)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ptr = buf;
+ tag = FIELD_GET(WMI_TLV_TAG, *ptr);
+
+ /* pdev/vdev id start after TLV header */
+ ptr++;
+
+ if (tag == WMI_TAG_PDEV_SET_PARAM_CMD)
+ *ptr = ar->pdev->pdev_id;
+
+ if (ar->ab->fw_mode != ATH11K_FIRMWARE_MODE_FTM &&
+ (tag == WMI_TAG_VDEV_SET_PARAM_CMD || tag == WMI_TAG_UNIT_TEST_CMD)) {
+ if (vif) {
+ arvif = (struct ath11k_vif *)vif->drv_priv;
+ *ptr = arvif->vdev_id;
+ } else {
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE,
- "testmode cmd wmi cmd_id %d buf %pK buf_len %d\n",
- cmd_id, buf, buf_len);
+ "cmd wmi cmd_id %d buf length %d\n",
+ cmd_id, buf_len);
ath11k_dbg_dump(ar->ab, ATH11K_DBG_TESTMODE, NULL, "", buf, buf_len);
@@ -173,6 +387,91 @@ out:
return ret;
}
+static int ath11k_tm_cmd_wmi_ftm(struct ath11k *ar, struct nlattr *tb[])
+{
+ struct ath11k_pdev_wmi *wmi = ar->wmi;
+ struct ath11k_base *ab = ar->ab;
+ struct sk_buff *skb;
+ u32 cmd_id, buf_len, hdr_info;
+ int ret;
+ void *buf;
+ u8 segnumber = 0, seginfo;
+ u16 chunk_len, total_bytes, num_segments;
+ u8 *bufpos;
+ struct wmi_ftm_cmd *ftm_cmd;
+
+ set_bit(ATH11K_FLAG_FTM_SEGMENTED, &ab->dev_flags);
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->state != ATH11K_STATE_FTM) {
+ ret = -ENETDOWN;
+ goto out;
+ }
+
+ if (!tb[ATH11K_TM_ATTR_DATA]) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ buf = nla_data(tb[ATH11K_TM_ATTR_DATA]);
+ buf_len = nla_len(tb[ATH11K_TM_ATTR_DATA]);
+ cmd_id = WMI_PDEV_UTF_CMDID;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE,
+ "cmd wmi ftm cmd_id %d buffer length %d\n",
+ cmd_id, buf_len);
+ ath11k_dbg_dump(ar->ab, ATH11K_DBG_TESTMODE, NULL, "", buf, buf_len);
+
+ bufpos = buf;
+ total_bytes = buf_len;
+ num_segments = total_bytes / MAX_WMI_UTF_LEN;
+
+ if (buf_len - (num_segments * MAX_WMI_UTF_LEN))
+ num_segments++;
+
+ while (buf_len) {
+ chunk_len = min_t(u16, buf_len, MAX_WMI_UTF_LEN);
+
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, (chunk_len +
+ sizeof(struct wmi_ftm_cmd)));
+ if (!skb) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ftm_cmd = (struct wmi_ftm_cmd *)skb->data;
+ hdr_info = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) |
+ FIELD_PREP(WMI_TLV_LEN, (chunk_len +
+ sizeof(struct wmi_ftm_seg_hdr)));
+ ftm_cmd->tlv_header = hdr_info;
+ ftm_cmd->seg_hdr.len = total_bytes;
+ ftm_cmd->seg_hdr.msgref = ar->ftm_msgref;
+ seginfo = FIELD_PREP(ATH11K_FTM_SEGHDR_TOTAL_SEGMENTS, num_segments) |
+ FIELD_PREP(ATH11K_FTM_SEGHDR_CURRENT_SEQ, segnumber);
+ ftm_cmd->seg_hdr.segmentinfo = seginfo;
+ segnumber++;
+
+ memcpy(&ftm_cmd->data, bufpos, chunk_len);
+
+ ret = ath11k_wmi_cmd_send(wmi, skb, cmd_id);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to send wmi ftm command: %d\n", ret);
+ goto out;
+ }
+
+ buf_len -= chunk_len;
+ bufpos += chunk_len;
+ }
+
+ ar->ftm_msgref++;
+ ret = 0;
+
+out:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
int ath11k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
void *data, int len)
{
@@ -192,7 +491,11 @@ int ath11k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
case ATH11K_TM_CMD_GET_VERSION:
return ath11k_tm_cmd_get_version(ar, tb);
case ATH11K_TM_CMD_WMI:
- return ath11k_tm_cmd_wmi(ar, tb);
+ return ath11k_tm_cmd_wmi(ar, tb, vif);
+ case ATH11K_TM_CMD_TESTMODE_START:
+ return ath11k_tm_cmd_testmode_start(ar, tb);
+ case ATH11K_TM_CMD_WMI_FTM:
+ return ath11k_tm_cmd_wmi_ftm(ar, tb);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/wireless/ath/ath11k/testmode.h b/drivers/net/wireless/ath/ath11k/testmode.h
index aaa122ed9069..2f62f2c4422f 100644
--- a/drivers/net/wireless/ath/ath11k/testmode.h
+++ b/drivers/net/wireless/ath/ath11k/testmode.h
@@ -1,22 +1,22 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "core.h"
#ifdef CONFIG_NL80211_TESTMODE
-bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, struct sk_buff *skb);
+void ath11k_tm_wmi_event(struct ath11k_base *ab, u32 cmd_id, struct sk_buff *skb);
int ath11k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
void *data, int len);
#else
-static inline bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id,
+static inline void ath11k_tm_wmi_event(struct ath11k_base *ab, u32 cmd_id,
struct sk_buff *skb)
{
- return false;
}
static inline int ath11k_tm_cmd(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/ath/ath11k/testmode_i.h b/drivers/net/wireless/ath/ath11k/testmode_i.h
index 4bae2a9eeea4..91b83873d660 100644
--- a/drivers/net/wireless/ath/ath11k/testmode_i.h
+++ b/drivers/net/wireless/ath/ath11k/testmode_i.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
/* "API" level of the ath11k testmode interface. Bump it after every
@@ -11,9 +12,10 @@
/* Bump this after every _compatible_ interface change, for example
* addition of a new command or an attribute.
*/
-#define ATH11K_TESTMODE_VERSION_MINOR 0
+#define ATH11K_TESTMODE_VERSION_MINOR 1
#define ATH11K_TM_DATA_MAX_LEN 5000
+#define ATH11K_FTM_EVENT_MAX_BUF_LENGTH 2048
enum ath11k_tm_attr {
__ATH11K_TM_ATTR_INVALID = 0,
@@ -47,4 +49,18 @@ enum ath11k_tm_cmd {
* ATH11K_TM_ATTR_DATA.
*/
ATH11K_TM_CMD_WMI = 1,
+
+ /* Boots the UTF firmware, the netdev interface must be down at the
+ * time.
+ */
+ ATH11K_TM_CMD_TESTMODE_START = 2,
+
+ /* The command used to transmit a FTM WMI command to the firmware
+ * and the event to receive WMI events from the firmware. The data
+ * received only contain the payload, need to add the tlv header
+ * and send the cmd to firmware with command id WMI_PDEV_UTF_CMDID.
+ * The data payload size could be large and the driver needs to
+ * send segmented data to firmware.
+ */
+ ATH11K_TM_CMD_WMI_FTM = 3,
};
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index d0b59bc2905a..23ad6825e5be 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021, 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/skbuff.h>
#include <linux/ctype.h>
@@ -19,6 +19,7 @@
#include "mac.h"
#include "hw.h"
#include "peer.h"
+#include "testmode.h"
struct wmi_tlv_policy {
size_t min_len;
@@ -237,9 +238,8 @@ static int ath11k_wmi_tlv_parse(struct ath11k_base *ar, const void **tb,
(void *)tb);
}
-static const void **
-ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab, const void *ptr,
- size_t len, gfp_t gfp)
+const void **ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab, const void *ptr,
+ size_t len, gfp_t gfp)
{
const void **tb;
int ret;
@@ -606,6 +606,8 @@ static int ath11k_service_ready_event(struct ath11k_base *ab, struct sk_buff *sk
return ret;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event service ready");
+
return 0;
}
@@ -690,6 +692,8 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd mgmt tx send");
+
return ret;
}
@@ -724,6 +728,9 @@ int ath11k_wmi_vdev_create(struct ath11k *ar, u8 *macaddr,
cmd->vdev_subtype = param->subtype;
cmd->num_cfg_txrx_streams = WMI_NUM_SUPPORTED_BAND_MAX;
cmd->pdev_id = param->pdev_id;
+ cmd->mbssid_flags = param->mbssid_flags;
+ cmd->mbssid_tx_vdev_id = param->mbssid_tx_vdev_id;
+
ether_addr_copy(cmd->vdev_macaddr.addr, macaddr);
ptr = skb->data + sizeof(*cmd);
@@ -763,7 +770,7 @@ int ath11k_wmi_vdev_create(struct ath11k *ar, u8 *macaddr,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev create: id %d type %d subtype %d macaddr %pM pdevid %d\n",
+ "cmd vdev create id %d type %d subtype %d macaddr %pM pdevid %d\n",
param->if_id, param->type, param->subtype,
macaddr, param->pdev_id);
@@ -792,7 +799,7 @@ int ath11k_wmi_vdev_delete(struct ath11k *ar, u8 vdev_id)
dev_kfree_skb(skb);
}
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "WMI vdev delete id %d\n", vdev_id);
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd vdev delete id %d\n", vdev_id);
return ret;
}
@@ -820,7 +827,7 @@ int ath11k_wmi_vdev_stop(struct ath11k *ar, u8 vdev_id)
dev_kfree_skb(skb);
}
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "WMI vdev stop id 0x%x\n", vdev_id);
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd vdev stop id 0x%x\n", vdev_id);
return ret;
}
@@ -848,7 +855,7 @@ int ath11k_wmi_vdev_down(struct ath11k *ar, u8 vdev_id)
dev_kfree_skb(skb);
}
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "WMI vdev down id 0x%x\n", vdev_id);
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd vdev down id 0x%x\n", vdev_id);
return ret;
}
@@ -941,6 +948,8 @@ int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,
cmd->cac_duration_ms = arg->cac_duration_ms;
cmd->regdomain = arg->regdomain;
cmd->he_ops = arg->he_ops;
+ cmd->mbssid_flags = arg->mbssid_flags;
+ cmd->mbssid_tx_vdev_id = arg->mbssid_tx_vdev_id;
if (!restart) {
if (arg->ssid) {
@@ -989,14 +998,15 @@ int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,
dev_kfree_skb(skb);
}
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "vdev %s id 0x%x freq 0x%x mode 0x%x\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd vdev %s id 0x%x freq 0x%x mode 0x%x\n",
restart ? "restart" : "start", arg->vdev_id,
arg->channel.freq, arg->channel.mode);
return ret;
}
-int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
+int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid,
+ u8 *tx_bssid, u32 nontx_profile_idx, u32 nontx_profile_cnt)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
struct wmi_vdev_up_cmd *cmd;
@@ -1020,14 +1030,19 @@ int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
ether_addr_copy(cmd->vdev_bssid.addr, bssid);
+ cmd->nontx_profile_idx = nontx_profile_idx;
+ cmd->nontx_profile_cnt = nontx_profile_cnt;
+ if (tx_bssid)
+ ether_addr_copy(cmd->tx_vdev_bssid.addr, tx_bssid);
+
if (arvif && arvif->vif->type == NL80211_IFTYPE_STATION) {
bss_conf = &arvif->vif->bss_conf;
if (bss_conf->nontransmitted) {
- ether_addr_copy(cmd->trans_bssid.addr,
+ ether_addr_copy(cmd->tx_vdev_bssid.addr,
bss_conf->transmitter_bssid);
- cmd->profile_idx = bss_conf->bssid_index;
- cmd->profile_num = bss_conf->bssid_indicator;
+ cmd->nontx_profile_idx = bss_conf->bssid_index;
+ cmd->nontx_profile_cnt = bss_conf->bssid_indicator;
}
}
@@ -1038,7 +1053,7 @@ int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI mgmt vdev up id 0x%x assoc id %d bssid %pM\n",
+ "cmd vdev up id 0x%x assoc id %d bssid %pM\n",
vdev_id, aid, bssid);
return ret;
@@ -1071,7 +1086,7 @@ int ath11k_wmi_send_peer_create_cmd(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI peer create vdev_id %d peer_addr %pM\n",
+ "cmd peer create vdev_id %d peer_addr %pM\n",
param->vdev_id, param->peer_addr);
return ret;
@@ -1096,16 +1111,16 @@ int ath11k_wmi_send_peer_delete_cmd(struct ath11k *ar,
ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
cmd->vdev_id = vdev_id;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI peer delete vdev_id %d peer_addr %pM\n",
- vdev_id, peer_addr);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PEER_DELETE_CMDID);
if (ret) {
ath11k_warn(ar->ab, "failed to send WMI_PEER_DELETE cmd\n");
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd peer delete vdev_id %d peer_addr %pM\n",
+ vdev_id, peer_addr);
+
return ret;
}
@@ -1134,11 +1149,6 @@ int ath11k_wmi_send_pdev_set_regdomain(struct ath11k *ar,
cmd->dfs_domain = param->dfs_domain;
cmd->pdev_id = param->pdev_id;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI pdev regd rd %d rd2g %d rd5g %d domain %d pdev id %d\n",
- param->current_rd_in_use, param->current_rd_2g,
- param->current_rd_5g, param->dfs_domain, param->pdev_id);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_REGDOMAIN_CMDID);
if (ret) {
ath11k_warn(ar->ab,
@@ -1146,6 +1156,11 @@ int ath11k_wmi_send_pdev_set_regdomain(struct ath11k *ar,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev regd rd %d rd2g %d rd5g %d domain %d pdev id %d\n",
+ param->current_rd_in_use, param->current_rd_2g,
+ param->current_rd_5g, param->dfs_domain, param->pdev_id);
+
return ret;
}
@@ -1176,7 +1191,7 @@ int ath11k_wmi_set_peer_param(struct ath11k *ar, const u8 *peer_addr,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev %d peer 0x%pM set param %d value %d\n",
+ "cmd peer set param vdev %d peer 0x%pM set param %d value %d\n",
vdev_id, peer_addr, param_id, param_val);
return ret;
@@ -1211,7 +1226,7 @@ int ath11k_wmi_send_peer_flush_tids_cmd(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI peer flush vdev_id %d peer_addr %pM tids %08x\n",
+ "cmd peer flush tids vdev_id %d peer_addr %pM tids %08x\n",
param->vdev_id, peer_addr, param->peer_tid_bitmap);
return ret;
@@ -1254,7 +1269,7 @@ int ath11k_wmi_peer_rx_reorder_queue_setup(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi rx reorder queue setup addr %pM vdev_id %d tid %d\n",
+ "cmd peer reorder queue setup addr %pM vdev_id %d tid %d\n",
addr, vdev_id, tid);
return ret;
@@ -1282,10 +1297,6 @@ ath11k_wmi_rx_reord_queue_remove(struct ath11k *ar,
cmd->vdev_id = param->vdev_id;
cmd->tid_mask = param->peer_tid_bitmap;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "%s: peer_macaddr %pM vdev_id %d, tid_map %d", __func__,
- param->peer_macaddr, param->vdev_id, param->peer_tid_bitmap);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PEER_REORDER_QUEUE_REMOVE_CMDID);
if (ret) {
@@ -1294,6 +1305,10 @@ ath11k_wmi_rx_reord_queue_remove(struct ath11k *ar,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd peer reorder queue remove peer_macaddr %pM vdev_id %d tid_map %d",
+ param->peer_macaddr, param->vdev_id, param->peer_tid_bitmap);
+
return ret;
}
@@ -1323,7 +1338,7 @@ int ath11k_wmi_pdev_set_param(struct ath11k *ar, u32 param_id,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI pdev set param %d pdev id %d value %d\n",
+ "cmd pdev set param %d pdev id %d value %d\n",
param_id, pdev_id, param_value);
return ret;
@@ -1354,7 +1369,7 @@ int ath11k_wmi_pdev_set_ps_mode(struct ath11k *ar, int vdev_id,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev set psmode %d vdev id %d\n",
+ "cmd sta powersave mode psmode %d vdev id %d\n",
psmode, vdev_id);
return ret;
@@ -1387,7 +1402,7 @@ int ath11k_wmi_pdev_suspend(struct ath11k *ar, u32 suspend_opt,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI pdev suspend pdev_id %d\n", pdev_id);
+ "cmd pdev suspend pdev_id %d\n", pdev_id);
return ret;
}
@@ -1409,15 +1424,15 @@ int ath11k_wmi_pdev_resume(struct ath11k *ar, u32 pdev_id)
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
cmd->pdev_id = pdev_id;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI pdev resume pdev id %d\n", pdev_id);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_RESUME_CMDID);
if (ret) {
ath11k_warn(ar->ab, "failed to send WMI_PDEV_RESUME cmd\n");
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev resume pdev id %d\n", pdev_id);
+
return ret;
}
@@ -1445,9 +1460,6 @@ int ath11k_wmi_pdev_bss_chan_info_request(struct ath11k *ar,
cmd->req_type = type;
cmd->pdev_id = ar->pdev->pdev_id;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI bss chan info req type %d\n", type);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PDEV_BSS_CHAN_INFO_REQUEST_CMDID);
if (ret) {
@@ -1456,6 +1468,9 @@ int ath11k_wmi_pdev_bss_chan_info_request(struct ath11k *ar,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev bss chan info request type %d\n", type);
+
return ret;
}
@@ -1488,7 +1503,7 @@ int ath11k_wmi_send_set_ap_ps_param_cmd(struct ath11k *ar, u8 *peer_addr,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI set ap ps vdev id %d peer %pM param %d value %d\n",
+ "cmd ap ps peer param vdev id %d peer %pM param %d value %d\n",
param->vdev_id, peer_addr, param->param, param->value);
return ret;
@@ -1515,16 +1530,16 @@ int ath11k_wmi_set_sta_ps_param(struct ath11k *ar, u32 vdev_id,
cmd->param = param;
cmd->value = param_value;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI set sta ps vdev_id %d param %d value %d\n",
- vdev_id, param, param_value);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_STA_POWERSAVE_PARAM_CMDID);
if (ret) {
ath11k_warn(ar->ab, "failed to send WMI_STA_POWERSAVE_PARAM_CMDID");
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd set powersave param vdev_id %d param %d value %d\n",
+ vdev_id, param, param_value);
+
return ret;
}
@@ -1554,6 +1569,9 @@ int ath11k_wmi_force_fw_hang_cmd(struct ath11k *ar, u32 type, u32 delay_time_ms)
ath11k_warn(ar->ab, "Failed to send WMI_FORCE_FW_HANG_CMDID");
dev_kfree_skb(skb);
}
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd force fw hang");
+
return ret;
}
@@ -1585,7 +1603,7 @@ int ath11k_wmi_vdev_set_param_cmd(struct ath11k *ar, u32 vdev_id,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev id 0x%x set param %d value %d\n",
+ "cmd vdev set param vdev 0x%x param %d value %d\n",
vdev_id, param_id, param_value);
return ret;
@@ -1618,7 +1636,7 @@ int ath11k_wmi_send_stats_request_cmd(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI request stats 0x%x vdev id %d pdev id %d\n",
+ "cmd request stats 0x%x vdev id %d pdev id %d\n",
param->stats_id, param->vdev_id, param->pdev_id);
return ret;
@@ -1647,7 +1665,7 @@ int ath11k_wmi_send_pdev_temperature_cmd(struct ath11k *ar)
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI pdev get temperature for pdev_id %d\n", ar->pdev->pdev_id);
+ "cmd pdev get temperature for pdev_id %d\n", ar->pdev->pdev_id);
return ret;
}
@@ -1672,10 +1690,6 @@ int ath11k_wmi_send_bcn_offload_control_cmd(struct ath11k *ar,
cmd->vdev_id = vdev_id;
cmd->bcn_ctrl_op = bcn_ctrl_op;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI bcn ctrl offload vdev id %d ctrl_op %d\n",
- vdev_id, bcn_ctrl_op);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_BCN_OFFLOAD_CTRL_CMDID);
if (ret) {
ath11k_warn(ar->ab,
@@ -1683,12 +1697,16 @@ int ath11k_wmi_send_bcn_offload_control_cmd(struct ath11k *ar,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd bcn offload ctrl vdev id %d ctrl_op %d\n",
+ vdev_id, bcn_ctrl_op);
+
return ret;
}
int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
struct ieee80211_mutable_offsets *offs,
- struct sk_buff *bcn)
+ struct sk_buff *bcn, u32 ema_params)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
struct wmi_bcn_tmpl_cmd *cmd;
@@ -1726,6 +1744,8 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
}
cmd->buf_len = bcn->len;
+ cmd->mbssid_ie_offset = offs->mbssid_off;
+ cmd->ema_params = ema_params;
ptr = skb->data + sizeof(*cmd);
@@ -1750,6 +1770,8 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd bcn tmpl");
+
return ret;
}
@@ -1799,7 +1821,7 @@ int ath11k_wmi_vdev_install_key(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev install key idx %d cipher %d len %d\n",
+ "cmd vdev install key idx %d cipher %d len %d\n",
arg->key_idx, arg->key_cipher, arg->key_len);
return ret;
@@ -2035,7 +2057,7 @@ int ath11k_wmi_send_peer_assoc_cmd(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x\n",
+ "cmd peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x\n",
cmd->vdev_id, cmd->peer_associd, param->peer_mac,
cmd->peer_flags, cmd->peer_rate_caps, cmd->peer_caps,
cmd->peer_listen_intval, cmd->peer_ht_caps,
@@ -2352,6 +2374,8 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd start scan");
+
return ret;
}
@@ -2400,6 +2424,8 @@ int ath11k_wmi_send_scan_stop_cmd(struct ath11k *ar,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd stop scan");
+
return ret;
}
@@ -2444,7 +2470,7 @@ int ath11k_wmi_send_scan_chan_list_cmd(struct ath11k *ar,
cmd->flags |= WMI_APPEND_TO_EXISTING_CHAN_LIST_FLAG;
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI no.of chan = %d len = %d pdev_id = %d num_sends = %d\n",
+ "no.of chan = %d len = %d pdev_id = %d num_sends = %d\n",
num_send_chans, len, cmd->pdev_id, num_sends);
ptr = skb->data + sizeof(*cmd);
@@ -2503,7 +2529,7 @@ int ath11k_wmi_send_scan_chan_list_cmd(struct ath11k *ar,
tchan_info->maxregpower);
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI chan scan list chan[%d] = %u, chan_info->info %8x\n",
+ "chan scan list chan[%d] = %u, chan_info->info %8x\n",
i, chan_info->mhz, chan_info->info);
ptr += sizeof(*chan_info);
@@ -2518,6 +2544,9 @@ int ath11k_wmi_send_scan_chan_list_cmd(struct ath11k *ar,
return ret;
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd scan chan list channels %d",
+ num_send_chans);
+
num_sends++;
}
@@ -2577,7 +2606,7 @@ int ath11k_wmi_send_wmm_update_cmd_tlv(struct ath11k *ar, u32 vdev_id,
wmm_param->no_ack = wmi_wmm_arg->no_ack;
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi wmm set ac %d aifs %d cwmin %d cwmax %d txop %d acm %d no_ack %d\n",
+ "wmm set ac %d aifs %d cwmin %d cwmax %d txop %d acm %d no_ack %d\n",
ac, wmm_param->aifs, wmm_param->cwmin,
wmm_param->cwmax, wmm_param->txoplimit,
wmm_param->acm, wmm_param->no_ack);
@@ -2590,6 +2619,8 @@ int ath11k_wmi_send_wmm_update_cmd_tlv(struct ath11k *ar, u32 vdev_id,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd vdev set wmm params");
+
return ret;
}
@@ -2613,9 +2644,6 @@ int ath11k_wmi_send_dfs_phyerr_offload_enable_cmd(struct ath11k *ar,
cmd->pdev_id = pdev_id;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI dfs phy err offload enable pdev id %d\n", pdev_id);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PDEV_DFS_PHYERR_OFFLOAD_ENABLE_CMDID);
if (ret) {
@@ -2624,6 +2652,9 @@ int ath11k_wmi_send_dfs_phyerr_offload_enable_cmd(struct ath11k *ar,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev dfs phyerr offload enable pdev id %d\n", pdev_id);
+
return ret;
}
@@ -2648,10 +2679,6 @@ int ath11k_wmi_delba_send(struct ath11k *ar, u32 vdev_id, const u8 *mac,
cmd->initiator = initiator;
cmd->reasoncode = reason;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi delba send vdev_id 0x%X mac_addr %pM tid %u initiator %u reason %u\n",
- vdev_id, mac, tid, initiator, reason);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_DELBA_SEND_CMDID);
if (ret) {
@@ -2660,6 +2687,10 @@ int ath11k_wmi_delba_send(struct ath11k *ar, u32 vdev_id, const u8 *mac,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd delba send vdev_id 0x%X mac_addr %pM tid %u initiator %u reason %u\n",
+ vdev_id, mac, tid, initiator, reason);
+
return ret;
}
@@ -2684,10 +2715,6 @@ int ath11k_wmi_addba_set_resp(struct ath11k *ar, u32 vdev_id, const u8 *mac,
cmd->tid = tid;
cmd->statuscode = status;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi addba set resp vdev_id 0x%X mac_addr %pM tid %u status %u\n",
- vdev_id, mac, tid, status);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_ADDBA_SET_RESP_CMDID);
if (ret) {
@@ -2696,6 +2723,10 @@ int ath11k_wmi_addba_set_resp(struct ath11k *ar, u32 vdev_id, const u8 *mac,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd addba set resp vdev_id 0x%X mac_addr %pM tid %u status %u\n",
+ vdev_id, mac, tid, status);
+
return ret;
}
@@ -2719,10 +2750,6 @@ int ath11k_wmi_addba_send(struct ath11k *ar, u32 vdev_id, const u8 *mac,
cmd->tid = tid;
cmd->buffersize = buf_size;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi addba send vdev_id 0x%X mac_addr %pM tid %u bufsize %u\n",
- vdev_id, mac, tid, buf_size);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_ADDBA_SEND_CMDID);
if (ret) {
@@ -2731,6 +2758,10 @@ int ath11k_wmi_addba_send(struct ath11k *ar, u32 vdev_id, const u8 *mac,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd addba send vdev_id 0x%X mac_addr %pM tid %u bufsize %u\n",
+ vdev_id, mac, tid, buf_size);
+
return ret;
}
@@ -2752,10 +2783,6 @@ int ath11k_wmi_addba_clear_resp(struct ath11k *ar, u32 vdev_id, const u8 *mac)
cmd->vdev_id = vdev_id;
ether_addr_copy(cmd->peer_macaddr.addr, mac);
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi addba clear resp vdev_id 0x%X mac_addr %pM\n",
- vdev_id, mac);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_ADDBA_CLEAR_RESP_CMDID);
if (ret) {
@@ -2764,6 +2791,10 @@ int ath11k_wmi_addba_clear_resp(struct ath11k *ar, u32 vdev_id, const u8 *mac)
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd addba clear resp vdev_id 0x%X mac_addr %pM\n",
+ vdev_id, mac);
+
return ret;
}
@@ -2812,6 +2843,8 @@ int ath11k_wmi_pdev_peer_pktlog_filter(struct ath11k *ar, u8 *addr, u8 enable)
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd pdev pktlog filter");
+
return ret;
}
@@ -2851,21 +2884,27 @@ ath11k_wmi_send_init_country_cmd(struct ath11k *ar,
cmd->cc_info.regdom_id = init_cc_params.cc_info.regdom_id;
break;
default:
+ ath11k_warn(ar->ab, "unknown cc params flags: 0x%x",
+ init_cc_params.flags);
ret = -EINVAL;
- goto out;
+ goto err;
}
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_SET_INIT_COUNTRY_CMDID);
-
-out:
if (ret) {
ath11k_warn(ar->ab,
"failed to send WMI_SET_INIT_COUNTRY CMD :%d\n",
ret);
- dev_kfree_skb(skb);
+ goto err;
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd set init country");
+
+ return 0;
+
+err:
+ dev_kfree_skb(skb);
return ret;
}
@@ -2888,20 +2927,20 @@ int ath11k_wmi_send_set_current_country_cmd(struct ath11k *ar,
cmd->pdev_id = ar->pdev->pdev_id;
memcpy(&cmd->new_alpha2, &param->alpha2, 3);
- ret = ath11k_wmi_cmd_send(wmi, skb, WMI_SET_CURRENT_COUNTRY_CMDID);
-
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "set current country pdev id %d alpha2 %c%c\n",
- ar->pdev->pdev_id,
- param->alpha2[0],
- param->alpha2[1]);
+ ret = ath11k_wmi_cmd_send(wmi, skb, WMI_SET_CURRENT_COUNTRY_CMDID);
if (ret) {
ath11k_warn(ar->ab,
"failed to send WMI_SET_CURRENT_COUNTRY_CMDID: %d\n", ret);
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd set current country pdev id %d alpha2 %c%c\n",
+ ar->pdev->pdev_id,
+ param->alpha2[0],
+ param->alpha2[1]);
+
return ret;
}
@@ -2962,7 +3001,7 @@ ath11k_wmi_send_thermal_mitigation_param_cmd(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev set thermal throt pdev_id %d enable %d dc %d dc_per_event %x levels %d\n",
+ "cmd therm throt set conf pdev_id %d enable %d dc %d dc_per_event %x levels %d\n",
ar->pdev->pdev_id, param->enable, param->dc,
param->dc_per_event, THERMAL_LEVELS);
@@ -2989,20 +3028,20 @@ int ath11k_wmi_send_11d_scan_start_cmd(struct ath11k *ar,
cmd->vdev_id = param->vdev_id;
cmd->scan_period_msec = param->scan_period_msec;
cmd->start_interval_msec = param->start_interval_msec;
- ret = ath11k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_START_CMDID);
-
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "send 11d scan start vdev id %d period %d ms internal %d ms\n",
- cmd->vdev_id,
- cmd->scan_period_msec,
- cmd->start_interval_msec);
+ ret = ath11k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_START_CMDID);
if (ret) {
ath11k_warn(ar->ab,
"failed to send WMI_11D_SCAN_START_CMDID: %d\n", ret);
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd 11d scan start vdev id %d period %d ms internal %d ms\n",
+ cmd->vdev_id,
+ cmd->scan_period_msec,
+ cmd->start_interval_msec);
+
return ret;
}
@@ -3023,18 +3062,18 @@ int ath11k_wmi_send_11d_scan_stop_cmd(struct ath11k *ar, u32 vdev_id)
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
cmd->vdev_id = vdev_id;
- ret = ath11k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_STOP_CMDID);
-
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "send 11d scan stop vdev id %d\n",
- cmd->vdev_id);
+ ret = ath11k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_STOP_CMDID);
if (ret) {
ath11k_warn(ar->ab,
"failed to send WMI_11D_SCAN_STOP_CMDID: %d\n", ret);
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd 11d scan stop vdev id %d\n",
+ cmd->vdev_id);
+
return ret;
}
@@ -3065,6 +3104,8 @@ int ath11k_wmi_pdev_pktlog_enable(struct ath11k *ar, u32 pktlog_filter)
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd pdev pktlog enable");
+
return ret;
}
@@ -3093,6 +3134,8 @@ int ath11k_wmi_pdev_pktlog_disable(struct ath11k *ar)
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd pdev pktlog disable");
+
return ret;
}
@@ -3162,10 +3205,14 @@ int ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id,
if (ret) {
ath11k_warn(ab, "Failed to send WMI_TWT_ENABLE_CMDID");
dev_kfree_skb(skb);
- } else {
- ar->twt_enabled = 1;
+ return ret;
}
- return ret;
+
+ ar->twt_enabled = 1;
+
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "cmd twt enable");
+
+ return 0;
}
int
@@ -3192,10 +3239,14 @@ ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id)
if (ret) {
ath11k_warn(ab, "Failed to send WMI_TWT_DISABLE_CMDID");
dev_kfree_skb(skb);
- } else {
- ar->twt_enabled = 0;
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "cmd twt disable");
+
+ ar->twt_enabled = 0;
+
+ return 0;
}
int ath11k_wmi_send_twt_add_dialog_cmd(struct ath11k *ar,
@@ -3234,21 +3285,22 @@ int ath11k_wmi_send_twt_add_dialog_cmd(struct ath11k *ar,
if (params->flag_protection)
cmd->flags |= WMI_TWT_ADD_DIALOG_FLAG_PROTECTION;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi add twt dialog vdev %u dialog id %u wake interval %u mantissa %u wake duration %u service period offset %u flags 0x%x\n",
- cmd->vdev_id, cmd->dialog_id, cmd->wake_intvl_us,
- cmd->wake_intvl_mantis, cmd->wake_dura_us, cmd->sp_offset_us,
- cmd->flags);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_TWT_ADD_DIALOG_CMDID);
-
if (ret) {
ath11k_warn(ab,
"failed to send wmi command to add twt dialog: %d",
ret);
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd twt add dialog vdev %u dialog id %u wake interval %u mantissa %u wake duration %u service period offset %u flags 0x%x\n",
+ cmd->vdev_id, cmd->dialog_id, cmd->wake_intvl_us,
+ cmd->wake_intvl_mantis, cmd->wake_dura_us, cmd->sp_offset_us,
+ cmd->flags);
+
+ return 0;
}
int ath11k_wmi_send_twt_del_dialog_cmd(struct ath11k *ar,
@@ -3274,18 +3326,20 @@ int ath11k_wmi_send_twt_del_dialog_cmd(struct ath11k *ar,
ether_addr_copy(cmd->peer_macaddr.addr, params->peer_macaddr);
cmd->dialog_id = params->dialog_id;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi delete twt dialog vdev %u dialog id %u\n",
- cmd->vdev_id, cmd->dialog_id);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_TWT_DEL_DIALOG_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send wmi command to delete twt dialog: %d",
ret);
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd twt del dialog vdev %u dialog id %u\n",
+ cmd->vdev_id, cmd->dialog_id);
+
+ return 0;
}
int ath11k_wmi_send_twt_pause_dialog_cmd(struct ath11k *ar,
@@ -3312,18 +3366,20 @@ int ath11k_wmi_send_twt_pause_dialog_cmd(struct ath11k *ar,
ether_addr_copy(cmd->peer_macaddr.addr, params->peer_macaddr);
cmd->dialog_id = params->dialog_id;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi pause twt dialog vdev %u dialog id %u\n",
- cmd->vdev_id, cmd->dialog_id);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_TWT_PAUSE_DIALOG_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send wmi command to pause twt dialog: %d",
ret);
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd twt pause dialog vdev %u dialog id %u\n",
+ cmd->vdev_id, cmd->dialog_id);
+
+ return 0;
}
int ath11k_wmi_send_twt_resume_dialog_cmd(struct ath11k *ar,
@@ -3352,19 +3408,21 @@ int ath11k_wmi_send_twt_resume_dialog_cmd(struct ath11k *ar,
cmd->sp_offset_us = params->sp_offset_us;
cmd->next_twt_size = params->next_twt_size;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi resume twt dialog vdev %u dialog id %u service period offset %u next twt subfield size %u\n",
- cmd->vdev_id, cmd->dialog_id, cmd->sp_offset_us,
- cmd->next_twt_size);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_TWT_RESUME_DIALOG_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send wmi command to resume twt dialog: %d",
ret);
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd twt resume dialog vdev %u dialog id %u service period offset %u next twt subfield size %u\n",
+ cmd->vdev_id, cmd->dialog_id, cmd->sp_offset_us,
+ cmd->next_twt_size);
+
+ return 0;
}
int
@@ -3398,8 +3456,12 @@ ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id,
ath11k_warn(ab,
"Failed to send WMI_PDEV_OBSS_PD_SPATIAL_REUSE_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "cmd pdev obss pd spatial reuse");
+
+ return 0;
}
int
@@ -3424,19 +3486,20 @@ ath11k_wmi_pdev_set_srg_bss_color_bitmap(struct ath11k *ar, u32 *bitmap)
cmd->pdev_id = ar->pdev->pdev_id;
memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "obss pd pdev_id %d bss color bitmap %08x %08x\n",
- cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev set srg bss color bitmap pdev_id %d bss color bitmap %08x %08x\n",
+ cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
+
+ return 0;
}
int
@@ -3462,19 +3525,20 @@ ath11k_wmi_pdev_set_srg_patial_bssid_bitmap(struct ath11k *ar, u32 *bitmap)
cmd->pdev_id = ar->pdev->pdev_id;
memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "obss pd pdev_id %d partial bssid bitmap %08x %08x\n",
- cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev set srg partial bssid bitmap pdev_id %d partial bssid bitmap %08x %08x\n",
+ cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
+
+ return 0;
}
int
@@ -3500,19 +3564,20 @@ ath11k_wmi_pdev_srg_obss_color_enable_bitmap(struct ath11k *ar, u32 *bitmap)
cmd->pdev_id = ar->pdev->pdev_id;
memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "obss pd srg pdev_id %d bss color enable bitmap %08x %08x\n",
- cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev set srg obsscolor enable pdev_id %d bss color enable bitmap %08x %08x\n",
+ cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
+
+ return 0;
}
int
@@ -3538,19 +3603,20 @@ ath11k_wmi_pdev_srg_obss_bssid_enable_bitmap(struct ath11k *ar, u32 *bitmap)
cmd->pdev_id = ar->pdev->pdev_id;
memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "obss pd srg pdev_id %d bssid enable bitmap %08x %08x\n",
- cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev set srg obss bssid enable bitmap pdev_id %d bssid enable bitmap %08x %08x\n",
+ cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
+
+ return 0;
}
int
@@ -3576,19 +3642,20 @@ ath11k_wmi_pdev_non_srg_obss_color_enable_bitmap(struct ath11k *ar, u32 *bitmap)
cmd->pdev_id = ar->pdev->pdev_id;
memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "obss pd non_srg pdev_id %d bss color enable bitmap %08x %08x\n",
- cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev set non srg obss color enable bitmap pdev_id %d bss color enable bitmap %08x %08x\n",
+ cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
+
+ return 0;
}
int
@@ -3614,19 +3681,20 @@ ath11k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(struct ath11k *ar, u32 *bitmap)
cmd->pdev_id = ar->pdev->pdev_id;
memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "obss pd non_srg pdev_id %d bssid enable bitmap %08x %08x\n",
- cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev set non srg obss bssid enable bitmap pdev_id %d bssid enable bitmap %08x %08x\n",
+ cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
+
+ return 0;
}
int
@@ -3659,18 +3727,20 @@ ath11k_wmi_send_obss_color_collision_cfg_cmd(struct ath11k *ar, u32 vdev_id,
cmd->free_slot_expiry_time_ms = 0;
cmd->flags = 0;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi_send_obss_color_collision_cfg id %d type %d bss_color %d detect_period %d scan_period %d\n",
- cmd->vdev_id, cmd->evt_type, cmd->current_bss_color,
- cmd->detection_period_ms, cmd->scan_period_ms);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_OBSS_COLOR_COLLISION_DET_CONFIG_CMDID);
if (ret) {
ath11k_warn(ab, "Failed to send WMI_OBSS_COLOR_COLLISION_DET_CONFIG_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd obss color collision det config id %d type %d bss_color %d detect_period %d scan_period %d\n",
+ cmd->vdev_id, cmd->evt_type, cmd->current_bss_color,
+ cmd->detection_period_ms, cmd->scan_period_ms);
+
+ return 0;
}
int ath11k_wmi_send_bss_color_change_enable_cmd(struct ath11k *ar, u32 vdev_id,
@@ -3694,17 +3764,19 @@ int ath11k_wmi_send_bss_color_change_enable_cmd(struct ath11k *ar, u32 vdev_id,
cmd->vdev_id = vdev_id;
cmd->enable = enable ? 1 : 0;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi_send_bss_color_change_enable id %d enable %d\n",
- cmd->vdev_id, cmd->enable);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_BSS_COLOR_CHANGE_ENABLE_CMDID);
if (ret) {
ath11k_warn(ab, "Failed to send WMI_BSS_COLOR_CHANGE_ENABLE_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd bss color change enable id %d enable %d\n",
+ cmd->vdev_id, cmd->enable);
+
+ return 0;
}
int ath11k_wmi_fils_discovery_tmpl(struct ath11k *ar, u32 vdev_id,
@@ -3721,7 +3793,7 @@ int ath11k_wmi_fils_discovery_tmpl(struct ath11k *ar, u32 vdev_id,
len = sizeof(*cmd) + TLV_HDR_SIZE + aligned_len;
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev %i set FILS discovery template\n", vdev_id);
+ "vdev %i set FILS discovery template\n", vdev_id);
skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
if (!skb)
@@ -3746,8 +3818,12 @@ int ath11k_wmi_fils_discovery_tmpl(struct ath11k *ar, u32 vdev_id,
"WMI vdev %i failed to send FILS discovery template command\n",
vdev_id);
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd fils discovery tmpl");
+
+ return 0;
}
int ath11k_wmi_probe_resp_tmpl(struct ath11k *ar, u32 vdev_id,
@@ -3762,7 +3838,7 @@ int ath11k_wmi_probe_resp_tmpl(struct ath11k *ar, u32 vdev_id,
size_t aligned_len = roundup(tmpl->len, 4);
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev %i set probe response template\n", vdev_id);
+ "vdev %i set probe response template\n", vdev_id);
len = sizeof(*cmd) + sizeof(*probe_info) + TLV_HDR_SIZE + aligned_len;
@@ -3799,8 +3875,12 @@ int ath11k_wmi_probe_resp_tmpl(struct ath11k *ar, u32 vdev_id,
"WMI vdev %i failed to send probe response template command\n",
vdev_id);
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd ");
+
+ return 0;
}
int ath11k_wmi_fils_discovery(struct ath11k *ar, u32 vdev_id, u32 interval,
@@ -3811,7 +3891,7 @@ int ath11k_wmi_fils_discovery(struct ath11k *ar, u32 vdev_id, u32 interval,
struct wmi_fils_discovery_cmd *cmd;
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev %i set %s interval to %u TU\n",
+ "vdev %i set %s interval to %u TU\n",
vdev_id, unsol_bcast_probe_resp_enabled ?
"unsolicited broadcast probe response" : "FILS discovery",
interval);
@@ -3834,8 +3914,12 @@ int ath11k_wmi_fils_discovery(struct ath11k *ar, u32 vdev_id, u32 interval,
"WMI vdev %i failed to send FILS discovery enable/disable command\n",
vdev_id);
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd enable fils");
+
+ return 0;
}
static void
@@ -3853,6 +3937,8 @@ ath11k_wmi_obss_color_collision_event(struct ath11k_base *ab, struct sk_buff *sk
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event obss color collision");
+
rcu_read_lock();
ev = tb[WMI_TAG_OBSS_COLOR_COLLISION_EVT];
@@ -3987,6 +4073,9 @@ ath11k_wmi_copy_resource_config(struct wmi_resource_config *wmi_cfg,
~(1 << WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT);
wmi_cfg->host_service_flags |= (tg_cfg->is_reg_cc_ext_event_supported <<
WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT);
+ wmi_cfg->flags2 = WMI_RSRC_CFG_FLAG2_CALC_NEXT_DTIM_COUNT_SET;
+ wmi_cfg->ema_max_vap_cnt = tg_cfg->ema_max_vap_cnt;
+ wmi_cfg->ema_max_profile_period = tg_cfg->ema_max_profile_period;
}
static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi,
@@ -4044,7 +4133,7 @@ static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi,
host_mem_chunks[idx].req_id = param->mem_chunks[idx].req_id;
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "WMI host mem chunk req_id %d paddr 0x%llx len %d\n",
+ "host mem chunk req_id %d paddr 0x%llx len %d\n",
param->mem_chunks[idx].req_id,
(u64)param->mem_chunks[idx].paddr,
param->mem_chunks[idx].len);
@@ -4098,9 +4187,12 @@ static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi,
if (ret) {
ath11k_warn(ab, "failed to send WMI_INIT_CMDID\n");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "cmd wmi init");
+
+ return 0;
}
int ath11k_wmi_pdev_lro_cfg(struct ath11k *ar,
@@ -4131,7 +4223,7 @@ int ath11k_wmi_pdev_lro_cfg(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI lro cfg cmd pdev_id 0x%x\n", pdev_id);
+ "cmd lro config pdev_id 0x%x\n", pdev_id);
return 0;
err:
dev_kfree_skb(skb);
@@ -4189,9 +4281,12 @@ int ath11k_wmi_set_hw_mode(struct ath11k_base *ab,
if (ret) {
ath11k_warn(ab, "failed to send WMI_PDEV_SET_HW_MODE_CMDID\n");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "cmd pdev set hw mode %d", cmd->hw_mode_index);
+
+ return 0;
}
int ath11k_wmi_cmd_init(struct ath11k_base *ab)
@@ -4252,7 +4347,7 @@ int ath11k_wmi_vdev_spectral_conf(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI spectral scan config cmd vdev_id 0x%x\n",
+ "cmd vdev spectral scan configure vdev_id 0x%x\n",
param->vdev_id);
return 0;
@@ -4290,7 +4385,7 @@ int ath11k_wmi_vdev_spectral_enable(struct ath11k *ar, u32 vdev_id,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI spectral enable cmd vdev id 0x%x\n",
+ "cmd vdev spectral scan enable vdev id 0x%x\n",
vdev_id);
return 0;
@@ -4336,7 +4431,7 @@ int ath11k_wmi_pdev_dma_ring_cfg(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI DMA ring cfg req cmd pdev_id 0x%x\n",
+ "cmd pdev dma ring cfg req pdev_id 0x%x\n",
param->pdev_id);
return 0;
@@ -4442,6 +4537,8 @@ static void ath11k_wmi_pdev_dma_ring_buf_release_event(struct ath11k_base *ab,
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event pdev dma ring buf release");
+
param.fixed = parse.fixed;
param.buf_entry = parse.buf_entry;
param.num_buf_entry = parse.num_buf_entry;
@@ -4836,6 +4933,8 @@ static int ath11k_service_ready_ext_event(struct ath11k_base *ab,
goto err;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event service ready ext");
+
if (!test_bit(WMI_TLV_SERVICE_EXT2_MSG, ab->wmi_ab.svc_map))
complete(&ab->wmi_ab.service_ready);
@@ -4886,6 +4985,8 @@ static int ath11k_service_ready_ext2_event(struct ath11k_base *ab,
goto err;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event service ready ext2");
+
complete(&ab->wmi_ab.service_ready);
return 0;
@@ -5757,7 +5858,7 @@ static int wmi_process_mgmt_tx_comp(struct ath11k *ar,
WARN_ON_ONCE(1);
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi mgmt tx comp pending %d desc id %d\n",
+ "mgmt tx comp pending %d desc id %d\n",
num_mgmt, tx_compl_param->desc_id);
if (!num_mgmt)
@@ -6326,7 +6427,7 @@ static int ath11k_wmi_tlv_rssi_chain_parse(struct ath11k_base *ab,
stats->stats_id = WMI_REQUEST_RSSI_PER_CHAIN_STAT;
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "wmi stats vdev id %d mac %pM\n",
+ "stats vdev id %d mac %pM\n",
stats_rssi->vdev_id, stats_rssi->peer_macaddr.addr);
arvif = ath11k_mac_get_arvif(ar, stats_rssi->vdev_id);
@@ -6338,7 +6439,7 @@ static int ath11k_wmi_tlv_rssi_chain_parse(struct ath11k_base *ab,
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "wmi stats bssid %pM vif %pK\n",
+ "stats bssid %pM vif %p\n",
arvif->bssid, arvif->vif);
sta = ieee80211_find_sta_by_ifaddr(ar->hw,
@@ -6359,7 +6460,7 @@ static int ath11k_wmi_tlv_rssi_chain_parse(struct ath11k_base *ab,
for (j = 0; j < ARRAY_SIZE(arsta->chain_signal); j++) {
arsta->chain_signal[j] = stats_rssi->rssi_avg_beacon[j];
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "wmi stats beacon rssi[%d] %d data rssi[%d] %d\n",
+ "stats beacon rssi[%d] %d data rssi[%d] %d\n",
j,
stats_rssi->rssi_avg_beacon[j],
j,
@@ -6442,7 +6543,7 @@ static int ath11k_wmi_tlv_fw_stats_data_parse(struct ath11k_base *ab,
arsta = (struct ath11k_sta *)sta->drv_priv;
arsta->rssi_beacon = src->beacon_snr;
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "wmi stats vdev id %d snr %d\n",
+ "stats vdev id %d snr %d\n",
src->vdev_id, src->beacon_snr);
} else {
ath11k_dbg(ab, ATH11K_DBG_WMI,
@@ -6512,7 +6613,7 @@ static int ath11k_wmi_tlv_fw_stats_parse(struct ath11k_base *ab,
parse->rssi_num = parse->rssi->num_per_chain_rssi_stats;
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "wmi stats id 0x%x num chain %d\n",
+ "stats id 0x%x num chain %d\n",
parse->ev->stats_id,
parse->rssi_num);
break;
@@ -6548,28 +6649,6 @@ int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb,
&parse);
}
-size_t ath11k_wmi_fw_stats_num_vdevs(struct list_head *head)
-{
- struct ath11k_fw_stats_vdev *i;
- size_t num = 0;
-
- list_for_each_entry(i, head, list)
- ++num;
-
- return num;
-}
-
-static size_t ath11k_wmi_fw_stats_num_bcn(struct list_head *head)
-{
- struct ath11k_fw_stats_bcn *i;
- size_t num = 0;
-
- list_for_each_entry(i, head, list)
- ++num;
-
- return num;
-}
-
static void
ath11k_wmi_fw_pdev_base_stats_fill(const struct ath11k_fw_stats_pdev *pdev,
char *buf, u32 *length)
@@ -6880,7 +6959,7 @@ void ath11k_wmi_fw_stats_fill(struct ath11k *ar,
}
if (stats_id == WMI_REQUEST_BCN_STAT) {
- num_bcn = ath11k_wmi_fw_stats_num_bcn(&fw_stats->bcn);
+ num_bcn = list_count_nodes(&fw_stats->bcn);
len += scnprintf(buf + len, buf_len - len, "\n");
len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
@@ -6933,7 +7012,7 @@ static int ath11k_reg_11d_new_cc_event(struct ath11k_base *ab, struct sk_buff *s
memcpy(&ab->new_alpha2, &ev->new_alpha2, 2);
spin_unlock_bh(&ab->base_lock);
- ath11k_dbg(ab, ATH11K_DBG_WMI, "wmi 11d new cc %c%c\n",
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event 11d new cc %c%c\n",
ab->new_alpha2[0],
ab->new_alpha2[1]);
@@ -7017,6 +7096,8 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab,
goto fallback;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event reg chan list id %d", id);
+
if (reg_info->status_code != REG_SET_CC_STATUS_PASS) {
/* In case of failure to set the requested ctry,
* fw retains the current regd. We print a failure info
@@ -7182,6 +7263,8 @@ static int ath11k_ready_event(struct ath11k_base *ab, struct sk_buff *skb)
return ret;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event ready");
+
complete(&ab->wmi_ab.unified_ready);
return 0;
}
@@ -7196,6 +7279,8 @@ static void ath11k_peer_delete_resp_event(struct ath11k_base *ab, struct sk_buff
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event peer delete resp");
+
rcu_read_lock();
ar = ath11k_mac_get_ar_by_vdev_id(ab, peer_del_resp.vdev_id);
if (!ar) {
@@ -7235,7 +7320,7 @@ static void ath11k_vdev_delete_resp_event(struct ath11k_base *ab,
rcu_read_unlock();
- ath11k_dbg(ab, ATH11K_DBG_WMI, "vdev delete resp for vdev id %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event vdev delete resp for vdev id %d\n",
vdev_id);
}
@@ -7266,6 +7351,8 @@ static void ath11k_vdev_start_resp_event(struct ath11k_base *ab, struct sk_buff
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event start resp event");
+
rcu_read_lock();
ar = ath11k_mac_get_ar_by_vdev_id(ab, vdev_start_resp.vdev_id);
if (!ar) {
@@ -7304,6 +7391,8 @@ static void ath11k_bcn_tx_status_event(struct ath11k_base *ab, struct sk_buff *s
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event offload bcn tx status");
+
rcu_read_lock();
arvif = ath11k_mac_get_arvif_by_vdev_id(ab, vdev_id);
if (!arvif) {
@@ -7343,7 +7432,7 @@ static void ath11k_wmi_event_peer_sta_ps_state_chg(struct ath11k_base *ab,
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "peer sta ps change ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n",
+ "event peer sta ps change ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n",
ev->peer_macaddr.addr, ev->peer_ps_state,
ev->ps_supported_bitmap, ev->peer_ps_valid,
ev->peer_ps_timestamp);
@@ -7427,6 +7516,8 @@ static void ath11k_vdev_stopped_event(struct ath11k_base *ab, struct sk_buff *sk
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event vdev stopped");
+
rcu_read_lock();
ar = ath11k_mac_get_ar_by_vdev_id(ab, vdev_id);
if (!ar) {
@@ -7460,7 +7551,7 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb)
memset(status, 0, sizeof(*status));
- ath11k_dbg(ab, ATH11K_DBG_MGMT, "mgmt rx event status %08x\n",
+ ath11k_dbg(ab, ATH11K_DBG_MGMT, "event mgmt rx status %08x\n",
rx_ev.status);
rcu_read_lock();
@@ -7503,7 +7594,7 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb)
if (rx_ev.phy_mode == MODE_11B &&
(status->band == NL80211_BAND_5GHZ || status->band == NL80211_BAND_6GHZ))
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "wmi mgmt rx 11b (CCK) on 5/6GHz, band = %d\n", status->band);
+ "mgmt rx 11b (CCK) on 5/6GHz, band = %d\n", status->band);
sband = &ar->mac.sbands[status->band];
@@ -7543,7 +7634,7 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb)
ath11k_mac_handle_beacon(ar, skb);
ath11k_dbg(ab, ATH11K_DBG_MGMT,
- "event mgmt rx skb %pK len %d ftype %02x stype %02x\n",
+ "event mgmt rx skb %p len %d ftype %02x stype %02x\n",
skb, skb->len,
fc & IEEE80211_FCTL_FTYPE, fc & IEEE80211_FCTL_STYPE);
@@ -7579,7 +7670,7 @@ static void ath11k_mgmt_tx_compl_event(struct ath11k_base *ab, struct sk_buff *s
wmi_process_mgmt_tx_comp(ar, &tx_compl_param);
ath11k_dbg(ab, ATH11K_DBG_MGMT,
- "mgmt tx compl ev pdev_id %d, desc_id %d, status %d ack_rssi %d",
+ "event mgmt tx compl ev pdev_id %d, desc_id %d, status %d ack_rssi %d",
tx_compl_param.pdev_id, tx_compl_param.desc_id,
tx_compl_param.status, tx_compl_param.ack_rssi);
@@ -7650,7 +7741,7 @@ static void ath11k_scan_event(struct ath11k_base *ab, struct sk_buff *skb)
spin_lock_bh(&ar->data_lock);
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "scan event %s type %d reason %d freq %d req_id %d scan_id %d vdev_id %d state %s (%d)\n",
+ "event scan %s type %d reason %d freq %d req_id %d scan_id %d vdev_id %d state %s (%d)\n",
ath11k_wmi_event_scan_type_str(scan_ev.event_type, scan_ev.reason),
scan_ev.event_type, scan_ev.reason, scan_ev.channel_freq,
scan_ev.scan_req_id, scan_ev.scan_id, scan_ev.vdev_id,
@@ -7733,7 +7824,7 @@ static void ath11k_peer_sta_kickout_event(struct ath11k_base *ab, struct sk_buff
goto exit;
}
- ath11k_dbg(ab, ATH11K_DBG_WMI, "peer sta kickout event %pM",
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event peer sta kickout %pM",
arg.mac_addr);
ieee80211_report_low_ack(sta, 10);
@@ -7753,7 +7844,7 @@ static void ath11k_roam_event(struct ath11k_base *ab, struct sk_buff *skb)
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "wmi roam event vdev %u reason 0x%08x rssi %d\n",
+ "event roam vdev %u reason 0x%08x rssi %d\n",
roam_ev.vdev_id, roam_ev.reason, roam_ev.rssi);
rcu_read_lock();
@@ -7800,7 +7891,7 @@ static void ath11k_chan_info_event(struct ath11k_base *ab, struct sk_buff *skb)
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "chan info vdev_id %d err_code %d freq %d cmd_flags %d noise_floor %d rx_clear_count %d cycle_count %d mac_clk_mhz %d\n",
+ "event chan info vdev_id %d err_code %d freq %d cmd_flags %d noise_floor %d rx_clear_count %d cycle_count %d mac_clk_mhz %d\n",
ch_info_ev.vdev_id, ch_info_ev.err_code, ch_info_ev.freq,
ch_info_ev.cmd_flags, ch_info_ev.noise_floor,
ch_info_ev.rx_clear_count, ch_info_ev.cycle_count,
@@ -7889,7 +7980,7 @@ ath11k_pdev_bss_chan_info_event(struct ath11k_base *ab, struct sk_buff *skb)
bss_ch_info_ev.rx_bss_cycle_count_low;
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "pdev bss chan info:\n pdev_id: %d freq: %d noise: %d cycle: busy %llu total %llu tx %llu rx %llu rx_bss %llu\n",
+ "event pdev bss chan info:\n pdev_id: %d freq: %d noise: %d cycle: busy %llu total %llu tx %llu rx %llu rx_bss %llu\n",
bss_ch_info_ev.pdev_id, bss_ch_info_ev.freq,
bss_ch_info_ev.noise_floor, busy, total,
tx, rx, rx_bss);
@@ -7943,7 +8034,7 @@ static void ath11k_vdev_install_key_compl_event(struct ath11k_base *ab,
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "vdev install key ev idx %d flags %08x macaddr %pM status %d\n",
+ "event vdev install key ev idx %d flags %08x macaddr %pM status %d\n",
install_key_compl.key_idx, install_key_compl.key_flags,
install_key_compl.macaddr, install_key_compl.status);
@@ -8026,6 +8117,8 @@ static void ath11k_service_available_event(struct ath11k_base *ab, struct sk_buf
NULL);
if (ret)
ath11k_warn(ab, "failed to parse services available tlv %d\n", ret);
+
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event service available");
}
static void ath11k_peer_assoc_conf_event(struct ath11k_base *ab, struct sk_buff *skb)
@@ -8039,7 +8132,7 @@ static void ath11k_peer_assoc_conf_event(struct ath11k_base *ab, struct sk_buff
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "peer assoc conf ev vdev id %d macaddr %pM\n",
+ "event peer assoc conf ev vdev id %d macaddr %pM\n",
peer_assoc_conf.vdev_id, peer_assoc_conf.macaddr);
rcu_read_lock();
@@ -8072,6 +8165,8 @@ static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *sk
goto free;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event update stats");
+
rcu_read_lock();
ar = ath11k_mac_get_ar_by_pdev_id(ab, stats.pdev_id);
if (!ar) {
@@ -8103,6 +8198,11 @@ complete:
rcu_read_unlock();
spin_unlock_bh(&ar->data_lock);
+ /* Since the stats's pdev, vdev and beacon list are spliced and reinitialised
+ * at this point, no need to free the individual list.
+ */
+ return;
+
free:
ath11k_fw_stats_free(&stats);
}
@@ -8132,7 +8232,7 @@ static void ath11k_pdev_ctl_failsafe_check_event(struct ath11k_base *ab,
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "pdev ctl failsafe check ev status %d\n",
+ "event pdev ctl failsafe check status %d\n",
ev->ctl_failsafe_status);
/* If ctl_failsafe_status is set to 1 FW will max out the Transmit power
@@ -8199,7 +8299,7 @@ ath11k_wmi_pdev_csa_switch_count_status_event(struct ath11k_base *ab,
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "pdev csa switch count %d for pdev %d, num_vdevs %d",
+ "event pdev csa switch count %d for pdev %d, num_vdevs %d",
ev->current_switch_count, ev->pdev_id,
ev->num_vdevs);
@@ -8232,7 +8332,7 @@ ath11k_wmi_pdev_dfs_radar_detected_event(struct ath11k_base *ab, struct sk_buff
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "pdev dfs radar detected on pdev %d, detection mode %d, chan freq %d, chan_width %d, detector id %d, seg id %d, timestamp %d, chirp %d, freq offset %d, sidx %d",
+ "event pdev dfs radar detected on pdev %d, detection mode %d, chan freq %d, chan_width %d, detector id %d, seg id %d, timestamp %d, chirp %d, freq offset %d, sidx %d",
ev->pdev_id, ev->detection_mode, ev->chan_freq, ev->chan_width,
ev->detector_id, ev->segment_id, ev->timestamp, ev->is_chirp,
ev->freq_offset, ev->sidx);
@@ -8280,8 +8380,8 @@ ath11k_wmi_pdev_temperature_event(struct ath11k_base *ab,
return;
}
- ath11k_dbg(ab, ATH11K_DBG_WMI,
- "pdev temperature ev temp %d pdev_id %d\n", ev->temp, ev->pdev_id);
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event pdev temperature ev temp %d pdev_id %d\n",
+ ev->temp, ev->pdev_id);
ar = ath11k_mac_get_ar_by_pdev_id(ab, ev->pdev_id);
if (!ar) {
@@ -8311,6 +8411,8 @@ static void ath11k_fils_discovery_event(struct ath11k_base *ab,
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event fils discovery");
+
ev = tb[WMI_TAG_HOST_SWFDA_EVENT];
if (!ev) {
ath11k_warn(ab, "failed to fetch FILS discovery event\n");
@@ -8341,6 +8443,8 @@ static void ath11k_probe_resp_tx_status_event(struct ath11k_base *ab,
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event probe resp tx status");
+
ev = tb[WMI_TAG_OFFLOAD_PRB_RSP_TX_STATUS_EVENT];
if (!ev) {
ath11k_warn(ab,
@@ -8407,6 +8511,8 @@ static void ath11k_wmi_event_wow_wakeup_host(struct ath11k_base *ab, struct sk_b
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event wow wakeup host");
+
complete(&ab->wow.wakeup_completed);
}
@@ -8414,6 +8520,8 @@ static void
ath11k_wmi_diag_event(struct ath11k_base *ab,
struct sk_buff *skb)
{
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event diag");
+
trace_ath11k_wmi_diag(ab, skb->data, skb->len);
}
@@ -8461,6 +8569,8 @@ static void ath11k_wmi_twt_add_dialog_event(struct ath11k_base *ab,
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event twt add dialog");
+
ev = tb[WMI_TAG_TWT_ADD_DIALOG_COMPLETE_EVENT];
if (!ev) {
ath11k_warn(ab, "failed to fetch twt add dialog wmi event\n");
@@ -8509,7 +8619,7 @@ static void ath11k_wmi_gtk_offload_status_event(struct ath11k_base *ab,
return;
}
- ath11k_dbg(ab, ATH11K_DBG_WMI, "wmi gtk offload event refresh_cnt %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event gtk offload refresh_cnt %d\n",
ev->refresh_cnt);
ath11k_dbg_dump(ab, ATH11K_DBG_WMI, "replay_cnt",
NULL, ev->replay_ctr.counter, GTK_REPLAY_COUNTER_BYTES);
@@ -8612,6 +8722,9 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
case WMI_PDEV_CSA_SWITCH_COUNT_STATUS_EVENTID:
ath11k_wmi_pdev_csa_switch_count_status_event(ab, skb);
break;
+ case WMI_PDEV_UTF_EVENTID:
+ ath11k_tm_wmi_event(ab, id, skb);
+ break;
case WMI_PDEV_TEMPERATURE_EVENTID:
ath11k_wmi_pdev_temperature_event(ab, skb);
break;
@@ -8630,19 +8743,6 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
case WMI_TWT_ADD_DIALOG_EVENTID:
ath11k_wmi_twt_add_dialog_event(ab, skb);
break;
- /* add Unsupported events here */
- case WMI_TBTTOFFSET_EXT_UPDATE_EVENTID:
- case WMI_PEER_OPER_MODE_CHANGE_EVENTID:
- case WMI_TWT_ENABLE_EVENTID:
- case WMI_TWT_DISABLE_EVENTID:
- case WMI_TWT_DEL_DIALOG_EVENTID:
- case WMI_TWT_PAUSE_DIALOG_EVENTID:
- case WMI_TWT_RESUME_DIALOG_EVENTID:
- case WMI_PDEV_DMA_RING_CFG_RSP_EVENTID:
- case WMI_PEER_CREATE_CONF_EVENTID:
- ath11k_dbg(ab, ATH11K_DBG_WMI,
- "ignoring unsupported event 0x%x\n", id);
- break;
case WMI_PDEV_DFS_RADAR_DETECTION_EVENTID:
ath11k_wmi_pdev_dfs_radar_detected_event(ab, skb);
break;
@@ -8664,9 +8764,8 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
case WMI_GTK_OFFLOAD_STATUS_EVENTID:
ath11k_wmi_gtk_offload_status_event(ab, skb);
break;
- /* TODO: Add remaining events */
default:
- ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id);
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "unsupported event id 0x%x\n", id);
break;
}
@@ -8763,7 +8862,7 @@ ath11k_wmi_send_unit_test_cmd(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI unit test : module %d vdev %d n_args %d token %d\n",
+ "cmd unit test module %d vdev %d n_args %d token %d\n",
cmd->module_id, cmd->vdev_id, cmd->num_args,
cmd->diag_token);
@@ -8855,6 +8954,9 @@ int ath11k_wmi_fw_dbglog_cfg(struct ath11k *ar, u32 *module_id_bitmap,
"failed to send WMI_DBGLOG_CFG_CMDID\n");
dev_kfree_skb(skb);
}
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd dbglog cfg");
+
return ret;
}
@@ -8960,7 +9062,7 @@ int ath11k_wmi_hw_data_filter_cmd(struct ath11k *ar, u32 vdev_id,
cmd->hw_filter_bitmap = ((u32)~0U);
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi hw data filter enable %d filter_bitmap 0x%x\n",
+ "hw data filter enable %d filter_bitmap 0x%x\n",
enable, filter_bitmap);
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_HW_DATA_FILTER_CMDID);
@@ -8982,7 +9084,7 @@ int ath11k_wmi_wow_host_wakeup_ind(struct ath11k *ar)
WMI_TAG_WOW_HOSTWAKEUP_FROM_SLEEP_CMD) |
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow host wakeup ind\n");
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow host wakeup ind\n");
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
}
@@ -9004,7 +9106,7 @@ int ath11k_wmi_wow_enable(struct ath11k *ar)
cmd->enable = 1;
cmd->pause_iface_config = WOW_IFACE_PAUSE_ENABLED;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow enable\n");
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow enable\n");
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID);
}
@@ -9031,7 +9133,7 @@ int ath11k_wmi_scan_prob_req_oui(struct ath11k *ar,
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
cmd->prob_req_oui = prob_req_oui;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi scan prob req oui %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "scan prob req oui %d\n",
prob_req_oui);
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_SCAN_PROB_REQ_OUI_CMDID);
@@ -9058,7 +9160,7 @@ int ath11k_wmi_wow_add_wakeup_event(struct ath11k *ar, u32 vdev_id,
cmd->is_add = enable;
cmd->event_bitmap = (1 << event);
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow add wakeup event %s enable %d vdev_id %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow add wakeup event %s enable %d vdev_id %d\n",
wow_wakeup_event(event), enable, vdev_id);
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
@@ -9163,7 +9265,7 @@ int ath11k_wmi_wow_add_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id,
WMI_TAG_ARRAY_UINT32) |
FIELD_PREP(WMI_TLV_LEN, sizeof(u32));
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow add pattern vdev_id %d pattern_id %d pattern_offset %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow add pattern vdev_id %d pattern_id %d pattern_offset %d\n",
vdev_id, pattern_id, pattern_offset);
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ADD_WAKE_PATTERN_CMDID);
@@ -9189,7 +9291,7 @@ int ath11k_wmi_wow_del_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id)
cmd->pattern_id = pattern_id;
cmd->pattern_type = WOW_BITMAP_PATTERN;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow del pattern vdev_id %d pattern_id %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow del pattern vdev_id %d pattern_id %d\n",
vdev_id, pattern_id);
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_DEL_WAKE_PATTERN_CMDID);
@@ -9302,7 +9404,7 @@ ath11k_wmi_op_gen_config_pno_start(struct ath11k *ar,
for (i = 0; i < cmd->num_of_channels; i++)
channel_list[i] = pno->a_networks[0].channels[i];
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv start pno config vdev_id %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv start pno config vdev_id %d\n",
vdev_id);
return skb;
@@ -9328,7 +9430,7 @@ static struct sk_buff *ath11k_wmi_op_gen_config_pno_stop(struct ath11k *ar,
cmd->flags = WMI_NLO_CONFIG_STOP;
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi tlv stop pno config vdev_id %d\n", vdev_id);
+ "tlv stop pno config vdev_id %d\n", vdev_id);
return skb;
}
@@ -9405,7 +9507,7 @@ static void ath11k_wmi_fill_ns_offload(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi index %d ns_solicited %pI6 target %pI6",
+ "index %d ns_solicited %pI6 target %pI6",
i, ns->solicitation_ipaddr,
ns->target_ipaddr[0]);
}
@@ -9443,7 +9545,7 @@ static void ath11k_wmi_fill_arp_offload(struct ath11k *ar,
memcpy(arp->target_ipaddr, offload->ipv4_addr[i], 4);
ath11k_ce_byte_swap(arp->target_ipaddr, 4);
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi arp offload address %pI4",
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "arp offload address %pI4",
arp->target_ipaddr);
}
@@ -9676,7 +9778,7 @@ int ath11k_wmi_sta_keepalive(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi sta keepalive vdev %d enabled %d method %d interval %d\n",
+ "sta keepalive vdev %d enabled %d method %d interval %d\n",
arg->vdev_id, arg->enabled, arg->method, arg->interval);
return ath11k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID);
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index 92fddb77669c..100bb816b592 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH11K_WMI_H
@@ -68,6 +69,7 @@ struct wmi_tlv {
#define WMI_APPEND_TO_EXISTING_CHAN_LIST_FLAG 1
+#define MAX_WMI_UTF_LEN 252
#define WMI_BA_MODE_BUFFER_SIZE_256 3
/*
* HW mode config type replicated from FW header
@@ -137,6 +139,14 @@ enum {
WMI_AUTORATE_3200NS_GI = BIT(11),
};
+enum {
+ WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP = 0x00000001,
+ WMI_HOST_VDEV_FLAGS_TRANSMIT_AP = 0x00000002,
+ WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP = 0x00000004,
+ WMI_HOST_VDEV_FLAGS_EMA_MODE = 0x00000008,
+ WMI_HOST_VDEV_FLAGS_SCAN_MODE_VAP = 0x00000010,
+};
+
/*
* wmi command groups.
*/
@@ -2096,6 +2106,7 @@ enum wmi_tlv_service {
WMI_TLV_SERVICE_EXT2_MSG = 220,
WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT = 246,
WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249,
+ WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253,
WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE = 263,
/* The second 128 bits */
@@ -2317,6 +2328,7 @@ struct wmi_init_cmd {
} __packed;
#define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5)
+#define WMI_RSRC_CFG_FLAG2_CALC_NEXT_DTIM_COUNT_SET BIT(9)
#define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18)
#define WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT 4
@@ -2389,6 +2401,9 @@ struct wmi_resource_config {
u32 msdu_flow_override_config1;
u32 flags2;
u32 host_service_flags;
+ u32 max_rnr_neighbours;
+ u32 ema_max_vap_cnt;
+ u32 ema_max_profile_period;
} __packed;
struct wmi_service_ready_event {
@@ -2579,6 +2594,8 @@ struct vdev_create_params {
u8 rx;
} chains[NUM_NL80211_BANDS];
u32 pdev_id;
+ u32 mbssid_flags;
+ u32 mbssid_tx_vdev_id;
};
struct wmi_vdev_create_cmd {
@@ -2589,6 +2606,8 @@ struct wmi_vdev_create_cmd {
struct wmi_mac_addr vdev_macaddr;
u32 num_cfg_txrx_streams;
u32 pdev_id;
+ u32 mbssid_flags;
+ u32 mbssid_tx_vdev_id;
} __packed;
struct wmi_vdev_txrx_streams {
@@ -2608,9 +2627,9 @@ struct wmi_vdev_up_cmd {
u32 vdev_id;
u32 vdev_assoc_id;
struct wmi_mac_addr vdev_bssid;
- struct wmi_mac_addr trans_bssid;
- u32 profile_idx;
- u32 profile_num;
+ struct wmi_mac_addr tx_vdev_bssid;
+ u32 nontx_profile_idx;
+ u32 nontx_profile_cnt;
} __packed;
struct wmi_vdev_stop_cmd {
@@ -2652,6 +2671,9 @@ struct wmi_vdev_start_request_cmd {
u32 he_ops;
u32 cac_duration_ms;
u32 regdomain;
+ u32 min_data_rate;
+ u32 mbssid_flags;
+ u32 mbssid_tx_vdev_id;
} __packed;
#define MGMT_TX_DL_FRM_LEN 64
@@ -2821,6 +2843,9 @@ struct wmi_vdev_start_req_arg {
u32 pref_rx_streams;
u32 pref_tx_streams;
u32 num_noa_descriptors;
+ u32 min_data_rate;
+ u32 mbssid_flags;
+ u32 mbssid_tx_vdev_id;
};
struct peer_create_params {
@@ -3541,8 +3566,30 @@ struct wmi_get_pdev_temperature_cmd {
u32 pdev_id;
} __packed;
+struct wmi_ftm_seg_hdr {
+ u32 len;
+ u32 msgref;
+ u32 segmentinfo;
+ u32 pdev_id;
+} __packed;
+
+struct wmi_ftm_cmd {
+ u32 tlv_header;
+ struct wmi_ftm_seg_hdr seg_hdr;
+ u8 data[];
+} __packed;
+
+struct wmi_ftm_event_msg {
+ struct wmi_ftm_seg_hdr seg_hdr;
+ u8 data[];
+} __packed;
+
#define WMI_BEACON_TX_BUFFER_SIZE 512
+#define WMI_EMA_TMPL_IDX_SHIFT 8
+#define WMI_EMA_FIRST_TMPL_SHIFT 16
+#define WMI_EMA_LAST_TMPL_SHIFT 24
+
struct wmi_bcn_tmpl_cmd {
u32 tlv_header;
u32 vdev_id;
@@ -3553,6 +3600,11 @@ struct wmi_bcn_tmpl_cmd {
u32 csa_event_bitmap;
u32 mbssid_ie_offset;
u32 esp_ie_offset;
+ u32 csc_switch_count_offset;
+ u32 csc_event_bitmap;
+ u32 mu_edca_ie_offset;
+ u32 feature_enable_bitmap;
+ u32 ema_params;
} __packed;
struct wmi_key_seq_counter {
@@ -5646,6 +5698,8 @@ struct target_resource_config {
u32 twt_ap_pdev_count;
u32 twt_ap_sta_count;
u8 is_reg_cc_ext_event_supported;
+ u32 ema_max_vap_cnt;
+ u32 ema_max_profile_period;
};
enum wmi_debug_log_param {
@@ -6266,6 +6320,8 @@ enum wmi_sta_keepalive_method {
#define WMI_STA_KEEPALIVE_INTERVAL_DEFAULT 30
#define WMI_STA_KEEPALIVE_INTERVAL_DISABLE 0
+const void **ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab, const void *ptr,
+ size_t len, gfp_t gfp);
int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb,
u32 cmd_id);
struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len);
@@ -6273,10 +6329,11 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
struct sk_buff *frame);
int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
struct ieee80211_mutable_offsets *offs,
- struct sk_buff *bcn);
+ struct sk_buff *bcn, u32 ema_param);
int ath11k_wmi_vdev_down(struct ath11k *ar, u8 vdev_id);
int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid,
- const u8 *bssid);
+ const u8 *bssid, u8 *tx_bssid, u32 nontx_profile_idx,
+ u32 nontx_profile_cnt);
int ath11k_wmi_vdev_stop(struct ath11k *ar, u8 vdev_id);
int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,
bool restart);
@@ -6372,9 +6429,6 @@ int ath11k_wmi_send_pdev_set_regdomain(struct ath11k *ar,
struct pdev_set_regdomain_params *param);
int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb,
struct ath11k_fw_stats *stats);
-size_t ath11k_wmi_fw_stats_num_peers(struct list_head *head);
-size_t ath11k_wmi_fw_stats_num_peers_extd(struct list_head *head);
-size_t ath11k_wmi_fw_stats_num_vdevs(struct list_head *head);
void ath11k_wmi_fw_stats_fill(struct ath11k *ar,
struct ath11k_fw_stats *fw_stats, u32 stats_id,
char *buf);
diff --git a/drivers/net/wireless/ath/ath11k/wow.c b/drivers/net/wireless/ath/ath11k/wow.c
index 1dec23b0699c..99d8ba45a75b 100644
--- a/drivers/net/wireless/ath/ath11k/wow.c
+++ b/drivers/net/wireless/ath/ath11k/wow.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2020 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.
*/
#include <linux/delay.h>
@@ -838,6 +838,7 @@ exit:
case ATH11K_STATE_RESTARTING:
case ATH11K_STATE_RESTARTED:
case ATH11K_STATE_WEDGED:
+ case ATH11K_STATE_FTM:
ath11k_warn(ar->ab, "encountered unexpected device state %d on resume, cannot recover\n",
ar->state);
ret = -EIO;
diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index a89e66653f04..3df8059d5512 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -706,6 +706,7 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
idr_for_each(&ar->txmgmt_idr,
ath12k_mac_tx_mgmt_pending_free, ar);
idr_destroy(&ar->txmgmt_idr);
+ wake_up(&ar->txmgmt_empty_waitq);
}
wake_up(&ab->wmi_ab.tx_credits_wq);
@@ -885,6 +886,7 @@ void ath12k_core_deinit(struct ath12k_base *ab)
void ath12k_core_free(struct ath12k_base *ab)
{
+ timer_delete_sync(&ab->rx_replenish_retry);
destroy_workqueue(ab->workqueue_aux);
destroy_workqueue(ab->workqueue);
kfree(ab);
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 9439052a652e..2f93296db792 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -533,6 +533,7 @@ struct ath12k {
/* protects txmgmt_idr data */
spinlock_t txmgmt_idr_lock;
atomic_t num_pending_mgmt_tx;
+ wait_queue_head_t txmgmt_empty_waitq;
/* cycle count is reported twice for each visited channel during scan.
* access protected by data_lock
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
index e78478a5b978..ffd9a2018610 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -193,11 +193,11 @@ static void ath12k_dp_rxdesc_set_msdu_len(struct ath12k_base *ab,
ab->hw_params->hal_ops->rx_desc_set_msdu_len(desc, len);
}
-static bool ath12k_dp_rx_h_is_mcbc(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
+static bool ath12k_dp_rx_h_is_da_mcbc(struct ath12k_base *ab,
+ struct hal_rx_desc *desc)
{
return (ath12k_dp_rx_h_first_msdu(ab, desc) &&
- ab->hw_params->hal_ops->rx_desc_is_mcbc(desc));
+ ab->hw_params->hal_ops->rx_desc_is_da_mcbc(desc));
}
static bool ath12k_dp_rxdesc_mac_addr2_valid(struct ath12k_base *ab,
@@ -978,7 +978,19 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
return ret;
}
- return ret;
+ if (!ab->hw_params->reoq_lut_support) {
+ ret = ath12k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id,
+ peer_mac,
+ paddr, tid, 1,
+ ba_win_sz);
+ if (ret) {
+ ath12k_warn(ab, "failed to setup peer rx reorder queuefor tid %d: %d\n",
+ tid, ret);
+ return ret;
+ }
+ }
+
+ return 0;
}
rx_tid->tid = tid;
@@ -1362,11 +1374,6 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar,
* Firmware rate's control to be skipped for this?
*/
- if (flags == WMI_RATE_PREAMBLE_HE && mcs > 11) {
- ath12k_warn(ab, "Invalid HE mcs %d peer stats", mcs);
- return;
- }
-
if (flags == WMI_RATE_PREAMBLE_HE && mcs > ATH12K_HE_MCS_MAX) {
ath12k_warn(ab, "Invalid HE mcs %d peer stats", mcs);
return;
@@ -2201,7 +2208,7 @@ static void ath12k_dp_rx_h_mpdu(struct ath12k *ar,
/* PN for multicast packets will be checked in mac80211 */
rxcb = ATH12K_SKB_RXCB(msdu);
- fill_crypto_hdr = ath12k_dp_rx_h_is_mcbc(ar->ab, rx_desc);
+ fill_crypto_hdr = ath12k_dp_rx_h_is_da_mcbc(ar->ab, rx_desc);
rxcb->is_mcbc = fill_crypto_hdr;
if (rxcb->is_mcbc)
diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c
index 0ec53afe9915..e7a150e7158e 100644
--- a/drivers/net/wireless/ath/ath12k/hal.c
+++ b/drivers/net/wireless/ath/ath12k/hal.c
@@ -447,10 +447,10 @@ static u8 *ath12k_hw_qcn9274_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc)
return desc->u.qcn9274.mpdu_start.addr2;
}
-static bool ath12k_hw_qcn9274_rx_desc_is_mcbc(struct hal_rx_desc *desc)
+static bool ath12k_hw_qcn9274_rx_desc_is_da_mcbc(struct hal_rx_desc *desc)
{
- return __le32_to_cpu(desc->u.qcn9274.mpdu_start.info6) &
- RX_MPDU_START_INFO6_MCAST_BCAST;
+ return __le16_to_cpu(desc->u.qcn9274.msdu_end.info5) &
+ RX_MSDU_END_INFO5_DA_IS_MCBC;
}
static void ath12k_hw_qcn9274_rx_desc_get_dot11_hdr(struct hal_rx_desc *desc,
@@ -708,7 +708,7 @@ const struct hal_ops hal_qcn9274_ops = {
.rx_desc_get_msdu_end_offset = ath12k_hw_qcn9274_rx_desc_get_msdu_end_offset,
.rx_desc_mac_addr2_valid = ath12k_hw_qcn9274_rx_desc_mac_addr2_valid,
.rx_desc_mpdu_start_addr2 = ath12k_hw_qcn9274_rx_desc_mpdu_start_addr2,
- .rx_desc_is_mcbc = ath12k_hw_qcn9274_rx_desc_is_mcbc,
+ .rx_desc_is_da_mcbc = ath12k_hw_qcn9274_rx_desc_is_da_mcbc,
.rx_desc_get_dot11_hdr = ath12k_hw_qcn9274_rx_desc_get_dot11_hdr,
.rx_desc_get_crypto_header = ath12k_hw_qcn9274_rx_desc_get_crypto_hdr,
.rx_desc_get_mpdu_frame_ctl = ath12k_hw_qcn9274_rx_desc_get_mpdu_frame_ctl,
@@ -887,10 +887,10 @@ static u8 *ath12k_hw_wcn7850_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc)
return desc->u.wcn7850.mpdu_start.addr2;
}
-static bool ath12k_hw_wcn7850_rx_desc_is_mcbc(struct hal_rx_desc *desc)
+static bool ath12k_hw_wcn7850_rx_desc_is_da_mcbc(struct hal_rx_desc *desc)
{
- return __le32_to_cpu(desc->u.wcn7850.mpdu_start.info6) &
- RX_MPDU_START_INFO6_MCAST_BCAST;
+ return __le16_to_cpu(desc->u.wcn7850.msdu_end.info5) &
+ RX_MSDU_END_INFO5_DA_IS_MCBC;
}
static void ath12k_hw_wcn7850_rx_desc_get_dot11_hdr(struct hal_rx_desc *desc,
@@ -1163,7 +1163,7 @@ const struct hal_ops hal_wcn7850_ops = {
.rx_desc_get_msdu_end_offset = ath12k_hw_wcn7850_rx_desc_get_msdu_end_offset,
.rx_desc_mac_addr2_valid = ath12k_hw_wcn7850_rx_desc_mac_addr2_valid,
.rx_desc_mpdu_start_addr2 = ath12k_hw_wcn7850_rx_desc_mpdu_start_addr2,
- .rx_desc_is_mcbc = ath12k_hw_wcn7850_rx_desc_is_mcbc,
+ .rx_desc_is_da_mcbc = ath12k_hw_wcn7850_rx_desc_is_da_mcbc,
.rx_desc_get_dot11_hdr = ath12k_hw_wcn7850_rx_desc_get_dot11_hdr,
.rx_desc_get_crypto_header = ath12k_hw_wcn7850_rx_desc_get_crypto_hdr,
.rx_desc_get_mpdu_frame_ctl = ath12k_hw_wcn7850_rx_desc_get_mpdu_frame_ctl,
diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h
index 0d4fa12ea622..66035a787c72 100644
--- a/drivers/net/wireless/ath/ath12k/hal.h
+++ b/drivers/net/wireless/ath/ath12k/hal.h
@@ -1063,7 +1063,7 @@ struct hal_ops {
u32 (*rx_desc_get_msdu_end_offset)(void);
bool (*rx_desc_mac_addr2_valid)(struct hal_rx_desc *desc);
u8* (*rx_desc_mpdu_start_addr2)(struct hal_rx_desc *desc);
- bool (*rx_desc_is_mcbc)(struct hal_rx_desc *desc);
+ bool (*rx_desc_is_da_mcbc)(struct hal_rx_desc *desc);
void (*rx_desc_get_dot11_hdr)(struct hal_rx_desc *desc,
struct ieee80211_hdr *hdr);
u16 (*rx_desc_get_mpdu_frame_ctl)(struct hal_rx_desc *desc);
diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c
index 1ffac7e3deaa..5991cc91cd00 100644
--- a/drivers/net/wireless/ath/ath12k/hw.c
+++ b/drivers/net/wireless/ath/ath12k/hw.c
@@ -906,6 +906,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
.hal_ops = &hal_qcn9274_ops,
+ .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01),
},
{
.name = "wcn7850 hw2.0",
@@ -960,6 +961,9 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
.wmi_init = ath12k_wmi_init_wcn7850,
.hal_ops = &hal_wcn7850_ops,
+
+ .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01) |
+ BIT(CNSS_PCIE_PERST_NO_PULL_V01),
},
{
.name = "qcn9274 hw2.0",
@@ -1013,6 +1017,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
.wmi_init = ath12k_wmi_init_qcn9274,
.hal_ops = &hal_qcn9274_ops,
+
+ .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01),
},
};
diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h
index e3461004188b..e6c4223c283c 100644
--- a/drivers/net/wireless/ath/ath12k/hw.h
+++ b/drivers/net/wireless/ath/ath12k/hw.h
@@ -184,6 +184,8 @@ struct ath12k_hw_params {
struct ath12k_wmi_resource_config_arg *config);
const struct hal_ops *hal_ops;
+
+ u64 qmi_cnss_feature_bitmap;
};
struct ath12k_hw_ops {
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index ee792822b411..1bb9802ef569 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -381,7 +381,7 @@ u8 ath12k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
}
static u32
-ath12k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
+ath12k_mac_max_ht_nss(const u8 *ht_mcs_mask)
{
int nss;
@@ -393,7 +393,7 @@ ath12k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
}
static u32
-ath12k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
+ath12k_mac_max_vht_nss(const u16 *vht_mcs_mask)
{
int nss;
@@ -771,6 +771,9 @@ static int ath12k_mac_vdev_setup_sync(struct ath12k *ar)
if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
return -ESHUTDOWN;
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "vdev setup timeout %d\n",
+ ATH12K_VDEV_SETUP_TIMEOUT_HZ);
+
if (!wait_for_completion_timeout(&ar->vdev_setup_done,
ATH12K_VDEV_SETUP_TIMEOUT_HZ))
return -ETIMEDOUT;
@@ -1303,7 +1306,7 @@ static void ath12k_peer_assoc_h_rates(struct ath12k *ar,
}
static bool
-ath12k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
+ath12k_peer_assoc_h_ht_masked(const u8 *ht_mcs_mask)
{
int nss;
@@ -1315,7 +1318,7 @@ ath12k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
}
static bool
-ath12k_peer_assoc_h_vht_masked(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
+ath12k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask)
{
int nss;
@@ -4375,6 +4378,21 @@ static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant)
return 0;
}
+static void ath12k_mgmt_over_wmi_tx_drop(struct ath12k *ar, struct sk_buff *skb)
+{
+ int num_mgmt;
+
+ ieee80211_free_txskb(ar->hw, skb);
+
+ num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);
+
+ if (num_mgmt < 0)
+ WARN_ON_ONCE(1);
+
+ if (!num_mgmt)
+ wake_up(&ar->txmgmt_empty_waitq);
+}
+
int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
{
struct sk_buff *msdu = skb;
@@ -4391,7 +4409,7 @@ int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
info = IEEE80211_SKB_CB(msdu);
memset(&info->status, 0, sizeof(info->status));
- ieee80211_free_txskb(ar->hw, msdu);
+ ath12k_mgmt_over_wmi_tx_drop(ar, skb);
return 0;
}
@@ -4425,6 +4443,7 @@ static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_vif *arvif,
int buf_id;
int ret;
+ ATH12K_SKB_CB(skb)->ar = ar;
spin_lock_bh(&ar->txmgmt_idr_lock);
buf_id = idr_alloc(&ar->txmgmt_idr, skb, 0,
ATH12K_TX_MGMT_NUM_PENDING_MAX, GFP_ATOMIC);
@@ -4475,7 +4494,7 @@ static void ath12k_mgmt_over_wmi_tx_purge(struct ath12k *ar)
struct sk_buff *skb;
while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL)
- ieee80211_free_txskb(ar->hw, skb);
+ ath12k_mgmt_over_wmi_tx_drop(ar, skb);
}
static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
@@ -4490,7 +4509,7 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
skb_cb = ATH12K_SKB_CB(skb);
if (!skb_cb->vif) {
ath12k_warn(ar->ab, "no vif found for mgmt frame\n");
- ieee80211_free_txskb(ar->hw, skb);
+ ath12k_mgmt_over_wmi_tx_drop(ar, skb);
continue;
}
@@ -4501,16 +4520,14 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
if (ret) {
ath12k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n",
arvif->vdev_id, ret);
- ieee80211_free_txskb(ar->hw, skb);
- } else {
- atomic_inc(&ar->num_pending_mgmt_tx);
+ ath12k_mgmt_over_wmi_tx_drop(ar, skb);
}
} else {
ath12k_warn(ar->ab,
"dropping mgmt frame for vdev %d, is_started %d\n",
arvif->vdev_id,
arvif->is_started);
- ieee80211_free_txskb(ar->hw, skb);
+ ath12k_mgmt_over_wmi_tx_drop(ar, skb);
}
}
}
@@ -4535,12 +4552,13 @@ static int ath12k_mac_mgmt_tx(struct ath12k *ar, struct sk_buff *skb,
return -ENOSPC;
}
- if (skb_queue_len(q) == ATH12K_TX_MGMT_NUM_PENDING_MAX) {
+ if (skb_queue_len_lockless(q) >= ATH12K_TX_MGMT_NUM_PENDING_MAX) {
ath12k_warn(ar->ab, "mgmt tx queue is full\n");
return -ENOSPC;
}
skb_queue_tail(q, skb);
+ atomic_inc(&ar->num_pending_mgmt_tx);
ieee80211_queue_work(ar->hw, &ar->wmi_mgmt_tx_work);
return 0;
@@ -5910,7 +5928,6 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
}
arvif->is_started = false;
- mutex_unlock(&ar->conf_mutex);
}
ret = ath12k_mac_vdev_stop(arvif);
@@ -6014,6 +6031,13 @@ static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v
ATH12K_FLUSH_TIMEOUT);
if (time_left == 0)
ath12k_warn(ar->ab, "failed to flush transmit queue %ld\n", time_left);
+
+ time_left = wait_event_timeout(ar->txmgmt_empty_waitq,
+ (atomic_read(&ar->num_pending_mgmt_tx) == 0),
+ ATH12K_FLUSH_TIMEOUT);
+ if (time_left == 0)
+ ath12k_warn(ar->ab, "failed to flush mgmt transmit queue %ld\n",
+ time_left);
}
static int
@@ -6991,6 +7015,7 @@ int ath12k_mac_register(struct ath12k_base *ab)
if (ret)
goto err_cleanup;
+ init_waitqueue_head(&ar->txmgmt_empty_waitq);
idr_init(&ar->txmgmt_idr);
spin_lock_init(&ar->txmgmt_idr_lock);
}
diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
index 9f174daf324c..5990a55801f0 100644
--- a/drivers/net/wireless/ath/ath12k/pci.c
+++ b/drivers/net/wireless/ath/ath12k/pci.c
@@ -1227,8 +1227,20 @@ static int ath12k_pci_probe(struct pci_dev *pdev,
case WCN7850_DEVICE_ID:
ab_pci->msi_config = &ath12k_msi_config[0];
ab->static_window_map = false;
- ab->hw_rev = ATH12K_HW_WCN7850_HW20;
ab_pci->pci_ops = &ath12k_pci_ops_wcn7850;
+ ath12k_pci_read_hw_version(ab, &soc_hw_version_major,
+ &soc_hw_version_minor);
+ switch (soc_hw_version_major) {
+ case ATH12K_PCI_SOC_HW_VERSION_2:
+ ab->hw_rev = ATH12K_HW_WCN7850_HW20;
+ break;
+ default:
+ dev_err(&pdev->dev,
+ "Unknown hardware version found for WCN7850: 0x%x\n",
+ soc_hw_version_major);
+ ret = -EOPNOTSUPP;
+ goto err_pci_free_region;
+ }
break;
default:
diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c
index 03ba245fbee9..b510c2de1bd4 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.c
+++ b/drivers/net/wireless/ath/ath12k/qmi.c
@@ -1942,8 +1942,10 @@ static int ath12k_qmi_host_cap_send(struct ath12k_base *ab)
req.cal_done_valid = 1;
req.cal_done = ab->qmi.cal_done;
- req.feature_list_valid = 1;
- req.feature_list = BIT(CNSS_QDSS_CFG_MISS_V01);
+ if (ab->hw_params->qmi_cnss_feature_bitmap) {
+ req.feature_list_valid = 1;
+ req.feature_list = ab->hw_params->qmi_cnss_feature_bitmap;
+ }
/* BRINGUP: here we are piggybacking a lot of stuff using
* internal_sleep_clock, should it be split?
@@ -3056,8 +3058,7 @@ int ath12k_qmi_init_service(struct ath12k_base *ab)
return ret;
}
- ab->qmi.event_wq = alloc_workqueue("ath12k_qmi_driver_event",
- WQ_UNBOUND, 1);
+ ab->qmi.event_wq = alloc_ordered_workqueue("ath12k_qmi_driver_event", 0);
if (!ab->qmi.event_wq) {
ath12k_err(ab, "failed to allocate workqueue\n");
return -EFAULT;
diff --git a/drivers/net/wireless/ath/ath12k/qmi.h b/drivers/net/wireless/ath/ath12k/qmi.h
index ad87f19903db..df76149c49f5 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.h
+++ b/drivers/net/wireless/ath/ath12k/qmi.h
@@ -189,6 +189,7 @@ struct wlfw_host_mlo_chip_info_s_v01 {
enum ath12k_qmi_cnss_feature {
CNSS_FEATURE_MIN_ENUM_VAL_V01 = INT_MIN,
CNSS_QDSS_CFG_MISS_V01 = 3,
+ CNSS_PCIE_PERST_NO_PULL_V01 = 4,
CNSS_MAX_FEATURE_V01 = 64,
CNSS_FEATURE_MAX_ENUM_VAL_V01 = INT_MAX,
};
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index 7ae0bb78b2b5..4928e4e91660 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -2144,8 +2144,7 @@ int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar,
struct wmi_tlv *tlv;
void *ptr;
int i, ret, len;
- u32 *tmp_ptr;
- u8 extraie_len_with_pad = 0;
+ u32 *tmp_ptr, extraie_len_with_pad = 0;
struct ath12k_wmi_hint_short_ssid_arg *s_ssid = NULL;
struct ath12k_wmi_hint_bssid_arg *hint_bssid = NULL;
@@ -3181,8 +3180,8 @@ ath12k_wmi_copy_resource_config(struct ath12k_wmi_resource_config_params *wmi_cf
wmi_cfg->sched_params = cpu_to_le32(tg_cfg->sched_params);
wmi_cfg->twt_ap_pdev_count = cpu_to_le32(tg_cfg->twt_ap_pdev_count);
wmi_cfg->twt_ap_sta_count = cpu_to_le32(tg_cfg->twt_ap_sta_count);
- wmi_cfg->host_service_flags =
- cpu_to_le32(1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT);
+ wmi_cfg->host_service_flags = cpu_to_le32(tg_cfg->is_reg_cc_ext_event_supported <<
+ WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT);
}
static int ath12k_init_cmd_send(struct ath12k_wmi_pdev *wmi,
@@ -3390,6 +3389,10 @@ int ath12k_wmi_cmd_init(struct ath12k_base *ab)
struct ath12k_wmi_base *wmi_sc = &ab->wmi_ab;
struct ath12k_wmi_init_cmd_arg arg = {};
+ if (test_bit(WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT,
+ ab->wmi_ab.svc_map))
+ arg.res_cfg.is_reg_cc_ext_event_supported = true;
+
ab->hw_params->wmi_init(ab, &arg.res_cfg);
arg.num_mem_chunks = wmi_sc->num_mem_chunks;
@@ -4640,6 +4643,7 @@ static int wmi_process_mgmt_tx_comp(struct ath12k *ar, u32 desc_id,
struct sk_buff *msdu;
struct ieee80211_tx_info *info;
struct ath12k_skb_cb *skb_cb;
+ int num_mgmt;
spin_lock_bh(&ar->txmgmt_idr_lock);
msdu = idr_find(&ar->txmgmt_idr, desc_id);
@@ -4663,10 +4667,15 @@ static int wmi_process_mgmt_tx_comp(struct ath12k *ar, u32 desc_id,
ieee80211_tx_status_irqsafe(ar->hw, msdu);
+ num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);
+
/* WARN when we received this event without doing any mgmt tx */
- if (atomic_dec_if_positive(&ar->num_pending_mgmt_tx) < 0)
+ if (num_mgmt < 0)
WARN_ON_ONCE(1);
+ if (!num_mgmt)
+ wake_up(&ar->txmgmt_empty_waitq);
+
return 0;
}
@@ -5979,47 +5988,72 @@ static void ath12k_vdev_install_key_compl_event(struct ath12k_base *ab,
rcu_read_unlock();
}
-static void ath12k_service_available_event(struct ath12k_base *ab, struct sk_buff *skb)
+static int ath12k_wmi_tlv_services_parser(struct ath12k_base *ab,
+ u16 tag, u16 len,
+ const void *ptr,
+ void *data)
{
- const void **tb;
const struct wmi_service_available_event *ev;
- int ret;
+ u32 *wmi_ext2_service_bitmap;
int i, j;
+ u16 expected_len;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
- if (IS_ERR(tb)) {
- ret = PTR_ERR(tb);
- ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
- return;
+ expected_len = WMI_SERVICE_SEGMENT_BM_SIZE32 * sizeof(u32);
+ if (len < expected_len) {
+ ath12k_warn(ab, "invalid length %d for the WMI services available tag 0x%x\n",
+ len, tag);
+ return -EINVAL;
}
- ev = tb[WMI_TAG_SERVICE_AVAILABLE_EVENT];
- if (!ev) {
- ath12k_warn(ab, "failed to fetch svc available ev");
- kfree(tb);
- return;
- }
+ switch (tag) {
+ case WMI_TAG_SERVICE_AVAILABLE_EVENT:
+ ev = (struct wmi_service_available_event *)ptr;
+ for (i = 0, j = WMI_MAX_SERVICE;
+ i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT_SERVICE;
+ i++) {
+ do {
+ if (le32_to_cpu(ev->wmi_service_segment_bitmap[i]) &
+ BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32))
+ set_bit(j, ab->wmi_ab.svc_map);
+ } while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32);
+ }
- /* TODO: Use wmi_service_segment_offset information to get the service
- * especially when more services are advertised in multiple service
- * available events.
- */
- for (i = 0, j = WMI_MAX_SERVICE;
- i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT_SERVICE;
- i++) {
- do {
- if (le32_to_cpu(ev->wmi_service_segment_bitmap[i]) &
- BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32))
- set_bit(j, ab->wmi_ab.svc_map);
- } while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32);
+ ath12k_dbg(ab, ATH12K_DBG_WMI,
+ "wmi_ext_service_bitmap 0x%x 0x%x 0x%x 0x%x",
+ ev->wmi_service_segment_bitmap[0],
+ ev->wmi_service_segment_bitmap[1],
+ ev->wmi_service_segment_bitmap[2],
+ ev->wmi_service_segment_bitmap[3]);
+ break;
+ case WMI_TAG_ARRAY_UINT32:
+ wmi_ext2_service_bitmap = (u32 *)ptr;
+ for (i = 0, j = WMI_MAX_EXT_SERVICE;
+ i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT2_SERVICE;
+ i++) {
+ do {
+ if (wmi_ext2_service_bitmap[i] &
+ BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32))
+ set_bit(j, ab->wmi_ab.svc_map);
+ } while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32);
+ }
+
+ ath12k_dbg(ab, ATH12K_DBG_WMI,
+ "wmi_ext2_service_bitmap 0x%04x 0x%04x 0x%04x 0x%04x",
+ wmi_ext2_service_bitmap[0], wmi_ext2_service_bitmap[1],
+ wmi_ext2_service_bitmap[2], wmi_ext2_service_bitmap[3]);
+ break;
}
+ return 0;
+}
- ath12k_dbg(ab, ATH12K_DBG_WMI,
- "wmi_ext_service_bitmap 0:0x%x, 1:0x%x, 2:0x%x, 3:0x%x",
- ev->wmi_service_segment_bitmap[0], ev->wmi_service_segment_bitmap[1],
- ev->wmi_service_segment_bitmap[2], ev->wmi_service_segment_bitmap[3]);
+static int ath12k_service_available_event(struct ath12k_base *ab, struct sk_buff *skb)
+{
+ int ret;
- kfree(tb);
+ ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,
+ ath12k_wmi_tlv_services_parser,
+ NULL);
+ return ret;
}
static void ath12k_peer_assoc_conf_event(struct ath12k_base *ab, struct sk_buff *skb)
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index 08a8c9e0f59f..d89c12bfb009 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -2148,7 +2148,10 @@ enum wmi_tlv_service {
WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219,
WMI_TLV_SERVICE_EXT2_MSG = 220,
- WMI_MAX_EXT_SERVICE
+ WMI_MAX_EXT_SERVICE = 256,
+
+ WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281,
+ WMI_MAX_EXT2_SERVICE,
};
enum {
@@ -2333,6 +2336,7 @@ struct ath12k_wmi_resource_config_arg {
u32 sched_params;
u32 twt_ap_pdev_count;
u32 twt_ap_sta_count;
+ bool is_reg_cc_ext_event_supported;
};
struct ath12k_wmi_init_cmd_arg {
@@ -2682,7 +2686,7 @@ struct ath12k_wmi_ssid_params {
u8 ssid[ATH12K_WMI_SSID_LEN];
} __packed;
-#define ATH12K_VDEV_SETUP_TIMEOUT_HZ (1 * HZ)
+#define ATH12K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ)
struct wmi_vdev_start_request_cmd {
__le32 tlv_header;
@@ -4664,7 +4668,7 @@ struct ath12k_wmi_base {
struct completion service_ready;
struct completion unified_ready;
- DECLARE_BITMAP(svc_map, WMI_MAX_EXT_SERVICE);
+ DECLARE_BITMAP(svc_map, WMI_MAX_EXT2_SERVICE);
wait_queue_head_t tx_credits_wq;
const struct wmi_peer_flags_map *peer_flags;
u32 num_mem_chunks;
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile
index a75bfa9fd1cf..dc2b3b46781e 100644
--- a/drivers/net/wireless/ath/ath6kl/Makefile
+++ b/drivers/net/wireless/ath/ath6kl/Makefile
@@ -36,11 +36,6 @@ ath6kl_core-y += wmi.o
ath6kl_core-y += core.o
ath6kl_core-y += recovery.o
-# FIXME: temporarily silence -Wdangling-pointer on non W=1+ builds
-ifndef KBUILD_EXTRA_WARN
-CFLAGS_htc_mbox.o += $(call cc-disable-warning, dangling-pointer)
-endif
-
ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
ath6kl_core-$(CONFIG_ATH6KL_TRACING) += trace.o
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 4f27a9fb1482..e9bd13eeee92 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -1099,17 +1099,22 @@ static bool ath9k_hw_verify_hang(struct ath_hw *ah, unsigned int queue)
{
u32 dma_dbg_chain, dma_dbg_complete;
u8 dcu_chain_state, dcu_complete_state;
+ unsigned int dbg_reg, reg_offset;
int i;
- for (i = 0; i < NUM_STATUS_READS; i++) {
- if (queue < 6)
- dma_dbg_chain = REG_READ(ah, AR_DMADBG_4);
- else
- dma_dbg_chain = REG_READ(ah, AR_DMADBG_5);
+ if (queue < 6) {
+ dbg_reg = AR_DMADBG_4;
+ reg_offset = queue * 5;
+ } else {
+ dbg_reg = AR_DMADBG_5;
+ reg_offset = (queue - 6) * 5;
+ }
+ for (i = 0; i < NUM_STATUS_READS; i++) {
+ dma_dbg_chain = REG_READ(ah, dbg_reg);
dma_dbg_complete = REG_READ(ah, AR_DMADBG_6);
- dcu_chain_state = (dma_dbg_chain >> (5 * queue)) & 0x1f;
+ dcu_chain_state = (dma_dbg_chain >> reg_offset) & 0x1f;
dcu_complete_state = dma_dbg_complete & 0x3;
if ((dcu_chain_state != 0x6) || (dcu_complete_state != 0x1))
@@ -1128,6 +1133,7 @@ static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah)
u8 dcu_chain_state, dcu_complete_state;
bool dcu_wait_frdone = false;
unsigned long chk_dcu = 0;
+ unsigned int reg_offset;
unsigned int i = 0;
dma_dbg_4 = REG_READ(ah, AR_DMADBG_4);
@@ -1139,12 +1145,15 @@ static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah)
goto exit;
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
- if (i < 6)
+ if (i < 6) {
chk_dbg = dma_dbg_4;
- else
+ reg_offset = i * 5;
+ } else {
chk_dbg = dma_dbg_5;
+ reg_offset = (i - 6) * 5;
+ }
- dcu_chain_state = (chk_dbg >> (5 * i)) & 0x1f;
+ dcu_chain_state = (chk_dbg >> reg_offset) & 0x1f;
if (dcu_chain_state == 0x6) {
dcu_wait_frdone = true;
chk_dcu |= BIT(i);
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
index fe62ff668f75..99667aba289d 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
@@ -114,7 +114,13 @@ static void htc_process_conn_rsp(struct htc_target *target,
if (svc_rspmsg->status == HTC_SERVICE_SUCCESS) {
epid = svc_rspmsg->endpoint_id;
- if (epid < 0 || epid >= ENDPOINT_MAX)
+
+ /* Check that the received epid for the endpoint to attach
+ * a new service is valid. ENDPOINT0 can't be used here as it
+ * is already reserved for HTC_CTRL_RSVD_SVC service and thus
+ * should not be modified.
+ */
+ if (epid <= ENDPOINT0 || epid >= ENDPOINT_MAX)
return;
service_id = be16_to_cpu(svc_rspmsg->service_id);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index a4197c14f0a9..6360d3356e25 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -203,7 +203,7 @@ void ath_cancel_work(struct ath_softc *sc)
void ath_restart_work(struct ath_softc *sc)
{
ieee80211_queue_delayed_work(sc->hw, &sc->hw_check_work,
- ATH_HW_CHECK_POLL_INT);
+ msecs_to_jiffies(ATH_HW_CHECK_POLL_INT));
if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9330(sc->sc_ah))
ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
@@ -850,7 +850,7 @@ static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
{
struct ath_hw *ah = sc->sc_ah;
- int i;
+ int i, j;
struct ath_txq *txq;
bool key_in_use = false;
@@ -868,8 +868,9 @@ static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
int idx = txq->txq_tailidx;
- while (!key_in_use &&
- !list_empty(&txq->txq_fifo[idx])) {
+ for (j = 0; !key_in_use &&
+ !list_empty(&txq->txq_fifo[idx]) &&
+ j < ATH_TXFIFO_DEPTH; j++) {
key_in_use = ath9k_txq_list_has_key(
&txq->txq_fifo[idx], keyix);
INCR(idx, ATH_TXFIFO_DEPTH);
@@ -2239,7 +2240,7 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
}
ieee80211_queue_delayed_work(hw, &sc->hw_check_work,
- ATH_HW_CHECK_POLL_INT);
+ msecs_to_jiffies(ATH_HW_CHECK_POLL_INT));
}
static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index 19345b8f7bfd..d652c647d56b 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -221,6 +221,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
if (unlikely(wmi->stopped))
goto free_skb;
+ /* Validate the obtained SKB. */
+ if (unlikely(skb->len < sizeof(struct wmi_cmd_hdr)))
+ goto free_skb;
+
hdr = (struct wmi_cmd_hdr *) skb->data;
cmd_id = be16_to_cpu(hdr->command_id);
diff --git a/drivers/net/wireless/ath/wil6210/fw.h b/drivers/net/wireless/ath/wil6210/fw.h
index 440614d61156..aa1620e0d24f 100644
--- a/drivers/net/wireless/ath/wil6210/fw.h
+++ b/drivers/net/wireless/ath/wil6210/fw.h
@@ -47,7 +47,7 @@ struct wil_fw_record_fill { /* type == wil_fw_type_fill */
* for informational purpose, data_size is @head.size from record header
*/
struct wil_fw_record_comment { /* type == wil_fw_type_comment */
- u8 data[0]; /* free-form data [data_size], see above */
+ DECLARE_FLEX_ARRAY(u8, data); /* free-form data [data_size], see above */
} __packed;
/* Comment header - common for all comment record types */
@@ -131,7 +131,7 @@ struct wil_fw_data_dwrite {
* data_size is @head.size where @head is record header
*/
struct wil_fw_record_direct_write { /* type == wil_fw_type_direct_write */
- struct wil_fw_data_dwrite data[0];
+ DECLARE_FLEX_ARRAY(struct wil_fw_data_dwrite, data);
} __packed;
/* verify condition: [@addr] & @mask == @value
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h
index 9affa4525609..71bf2ae27a98 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.h
+++ b/drivers/net/wireless/ath/wil6210/wmi.h
@@ -2763,7 +2763,7 @@ struct wmi_rf_xpm_write_result_event {
/* WMI_TX_MGMT_PACKET_EVENTID */
struct wmi_tx_mgmt_packet_event {
- u8 payload[0];
+ DECLARE_FLEX_ARRAY(u8, payload);
} __packed;
/* WMI_RX_MGMT_PACKET_EVENTID */
diff --git a/drivers/net/wireless/atmel/Kconfig b/drivers/net/wireless/atmel/Kconfig
index ca45a1021cf4..bafdd57b049a 100644
--- a/drivers/net/wireless/atmel/Kconfig
+++ b/drivers/net/wireless/atmel/Kconfig
@@ -14,7 +14,7 @@ if WLAN_VENDOR_ATMEL
config ATMEL
tristate "Atmel at76c50x chipset 802.11b support"
- depends on CFG80211 && (PCI || PCMCIA)
+ depends on CFG80211 && (PCI || PCMCIA) && HAS_IOPORT
select WIRELESS_EXT
select WEXT_PRIV
select FW_LOADER
diff --git a/drivers/net/wireless/atmel/atmel_cs.c b/drivers/net/wireless/atmel/atmel_cs.c
index 453bb84cb338..58bba9875d36 100644
--- a/drivers/net/wireless/atmel/atmel_cs.c
+++ b/drivers/net/wireless/atmel/atmel_cs.c
@@ -72,6 +72,7 @@ struct local_info {
static int atmel_probe(struct pcmcia_device *p_dev)
{
struct local_info *local;
+ int ret;
dev_dbg(&p_dev->dev, "atmel_attach()\n");
@@ -82,8 +83,16 @@ static int atmel_probe(struct pcmcia_device *p_dev)
p_dev->priv = local;
- return atmel_config(p_dev);
-} /* atmel_attach */
+ ret = atmel_config(p_dev);
+ if (ret)
+ goto err_free_priv;
+
+ return 0;
+
+err_free_priv:
+ kfree(p_dev->priv);
+ return ret;
+}
static void atmel_detach(struct pcmcia_device *link)
{
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index de8a2e27f49c..2a90bb24ba77 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -1456,6 +1456,10 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
params_size -= BRCMF_SCAN_PARAMS_V2_FIXED_SIZE;
params_size += BRCMF_SCAN_PARAMS_FIXED_SIZE;
params_v1 = kzalloc(params_size, GFP_KERNEL);
+ if (!params_v1) {
+ err = -ENOMEM;
+ goto exit_params;
+ }
params_v1->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
brcmf_scan_params_v2_to_v1(&params->params_v2_le, &params_v1->params_le);
kfree(params);
@@ -1473,6 +1477,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
bphy_err(drvr, "error (%d)\n", err);
}
+exit_params:
kfree(params);
exit:
return err;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
index 9f9bf08a70bb..2ef92ef25517 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
@@ -972,6 +972,7 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
u32 regdata;
u32 socitype;
int ret;
+ const u32 READ_FAILED = 0xFFFFFFFF;
/* Get CC core rev
* Chipid is assume to be at offset 0 from SI_ENUM_BASE
@@ -980,6 +981,11 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
*/
regdata = ci->ops->read32(ci->ctx,
CORE_CC_REG(ci->pub.enum_base, chipid));
+ if (regdata == READ_FAILED) {
+ brcmf_err("MMIO read failed: 0x%08x\n", regdata);
+ return -ENODEV;
+ }
+
ci->pub.chip = regdata & CID_ID_MASK;
ci->pub.chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
index 792adaf880b4..bece26741d3a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
@@ -398,7 +398,12 @@ struct brcmf_scan_params_le {
* fixed parameter portion is assumed, otherwise
* ssid in the fixed portion is ignored
*/
- __le16 channel_list[1]; /* list of chanspecs */
+ union {
+ __le16 padding; /* Reserve space for at least 1 entry for abort
+ * which uses an on stack brcmf_scan_params_le
+ */
+ DECLARE_FLEX_ARRAY(__le16, channel_list); /* chanspecs */
+ };
};
struct brcmf_scan_params_v2_le {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h
index 5a139d7ed47a..5d66e94c806d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h
@@ -28,6 +28,11 @@ static inline void trace_ ## name(proto) {}
#define MAX_MSG_LEN 100
+#pragma GCC diagnostic push
+#ifndef __clang__
+#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
+#endif
+
TRACE_EVENT(brcmf_err,
TP_PROTO(const char *func, struct va_format *vaf),
TP_ARGS(func, vaf),
@@ -123,6 +128,8 @@ TRACE_EVENT(brcmf_sdpcm_hdr,
__entry->len, ((u8 *)__get_dynamic_array(hdr))[4])
);
+#pragma GCC diagnostic pop
+
#ifdef CONFIG_BRCM_TRACING
#undef TRACE_INCLUDE_PATH
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c
index 02de99818efa..5573a47766ad 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c
@@ -12,13 +12,13 @@
static int brcmf_wcc_attach(struct brcmf_pub *drvr)
{
- pr_err("%s: executing\n", __func__);
+ pr_debug("%s: executing\n", __func__);
return 0;
}
static void brcmf_wcc_detach(struct brcmf_pub *drvr)
{
- pr_err("%s: executing\n", __func__);
+ pr_debug("%s: executing\n", __func__);
}
const struct brcmf_fwvid_ops brcmf_wcc_ops = {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h
index 488456420353..42b0a91656c4 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h
@@ -24,6 +24,11 @@
#define MAX_MSG_LEN 100
+#pragma GCC diagnostic push
+#ifndef __clang__
+#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
+#endif
+
DECLARE_EVENT_CLASS(brcms_msg_event,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf),
@@ -71,6 +76,9 @@ TRACE_EVENT(brcms_dbg,
),
TP_printk("%s: %s", __get_str(func), __get_str(msg))
);
+
+#pragma GCC diagnostic pop
+
#endif /* __TRACE_BRCMSMAC_MSG_H */
#ifdef CONFIG_BRCM_TRACING
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c b/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c
index e87e68cc46e2..fe94db0ba3f3 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c
@@ -186,7 +186,7 @@ struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out)
{
int prec;
- if (pq->len == 0)
+ if (pktq_empty(pq))
return NULL;
for (prec = 0; prec < pq->hi_prec; prec++)
@@ -223,7 +223,7 @@ struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp,
struct sk_buff *p;
int prec;
- if (pq->len == 0)
+ if (pktq_empty(pq))
return NULL;
while ((prec = pq->hi_prec) > 0 &&
diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c
index 7c4cc5f5e1eb..dbd13f7aa3e6 100644
--- a/drivers/net/wireless/cisco/airo.c
+++ b/drivers/net/wireless/cisco/airo.c
@@ -6157,8 +6157,11 @@ static int airo_get_rate(struct net_device *dev,
struct iw_param *vwrq = &wrqu->bitrate;
struct airo_info *local = dev->ml_priv;
StatusRid status_rid; /* Card status info */
+ int ret;
- readStatusRid(local, &status_rid, 1);
+ ret = readStatusRid(local, &status_rid, 1);
+ if (ret)
+ return -EBUSY;
vwrq->value = le16_to_cpu(status_rid.currentXmitRate) * 500000;
/* If more than one rate, set auto */
diff --git a/drivers/net/wireless/intel/iwlwifi/Kconfig b/drivers/net/wireless/intel/iwlwifi/Kconfig
index b20409f8c13a..20971304fdef 100644
--- a/drivers/net/wireless/intel/iwlwifi/Kconfig
+++ b/drivers/net/wireless/intel/iwlwifi/Kconfig
@@ -66,6 +66,7 @@ config IWLMVM
tristate "Intel Wireless WiFi MVM Firmware support"
select WANT_DEV_COREDUMP
depends on MAC80211
+ depends on PTP_1588_CLOCK_OPTIONAL
help
This is the driver that supports the MVM firmware. The list
of the devices that use this firmware is available here:
diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile
index 75a703eb1bdf..b983982aee45 100644
--- a/drivers/net/wireless/intel/iwlwifi/Makefile
+++ b/drivers/net/wireless/intel/iwlwifi/Makefile
@@ -11,6 +11,7 @@ iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-gen3.o
iwlwifi-objs += pcie/trans-gen2.o pcie/tx-gen2.o
iwlwifi-$(CONFIG_IWLDVM) += cfg/1000.o cfg/2000.o cfg/5000.o cfg/6000.o
iwlwifi-$(CONFIG_IWLMVM) += cfg/7000.o cfg/8000.o cfg/9000.o cfg/22000.o
+iwlwifi-$(CONFIG_IWLMVM) += cfg/ax210.o cfg/bz.o cfg/sc.o
iwlwifi-objs += iwl-dbg-tlv.o
iwlwifi-objs += iwl-trans.o
iwlwifi-objs += queue/tx.o
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c
index 116defb15afb..f172ffd2a841 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2018 - 2020 Intel Corporation
+ * Copyright(c) 2018 - 2020, 2023 Intel Corporation
*****************************************************************************/
#include <linux/module.h>
@@ -22,11 +22,11 @@
#define EEPROM_1000_TX_POWER_VERSION (4)
#define EEPROM_1000_EEPROM_VERSION (0x15C)
-#define IWL1000_FW_PRE "iwlwifi-1000-"
-#define IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE __stringify(api) ".ucode"
+#define IWL1000_FW_PRE "iwlwifi-1000"
+#define IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL100_FW_PRE "iwlwifi-100-"
-#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE __stringify(api) ".ucode"
+#define IWL100_FW_PRE "iwlwifi-100"
+#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl1000_base_params = {
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c
index ab2038a3fbe2..6f3f26da0ad5 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2018 - 2020 Intel Corporation
+ * Copyright(c) 2018 - 2020, 2023 Intel Corporation
*****************************************************************************/
#include <linux/module.h>
@@ -28,17 +28,17 @@
#define EEPROM_2000_EEPROM_VERSION (0x805)
-#define IWL2030_FW_PRE "iwlwifi-2030-"
-#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE __stringify(api) ".ucode"
+#define IWL2030_FW_PRE "iwlwifi-2030"
+#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL2000_FW_PRE "iwlwifi-2000-"
-#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE __stringify(api) ".ucode"
+#define IWL2000_FW_PRE "iwlwifi-2000"
+#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL105_FW_PRE "iwlwifi-105-"
-#define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE __stringify(api) ".ucode"
+#define IWL105_FW_PRE "iwlwifi-105"
+#define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL135_FW_PRE "iwlwifi-135-"
-#define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE __stringify(api) ".ucode"
+#define IWL135_FW_PRE "iwlwifi-135"
+#define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl2000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_2K,
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
index b6f82510e980..d594694206b3 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#include <linux/module.h>
#include <linux/stringify.h>
@@ -10,10 +10,10 @@
#include "fw/api/txq.h"
/* Highest firmware API version supported */
-#define IWL_22000_UCODE_API_MAX 78
+#define IWL_22000_UCODE_API_MAX 77
/* Lowest firmware API version supported */
-#define IWL_22000_UCODE_API_MIN 39
+#define IWL_22000_UCODE_API_MIN 50
/* NVM versions */
#define IWL_22000_NVM_VERSION 0x0a1d
@@ -26,162 +26,26 @@
#define IWL_22000_SMEM_OFFSET 0x400000
#define IWL_22000_SMEM_LEN 0xD0000
-#define IWL_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0-"
-#define IWL_QNJ_B_HR_B_FW_PRE "iwlwifi-QuQnj-b0-hr-b0-"
-#define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0-"
-#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0-"
-#define IWL_QU_C_JF_B_FW_PRE "iwlwifi-Qu-c0-jf-b0-"
-#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0-"
-#define IWL_QUZ_A_JF_B_FW_PRE "iwlwifi-QuZ-a0-jf-b0-"
-#define IWL_QNJ_B_JF_B_FW_PRE "iwlwifi-QuQnj-b0-jf-b0-"
-#define IWL_CC_A_FW_PRE "iwlwifi-cc-a0-"
-#define IWL_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0-"
-#define IWL_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0-"
-#define IWL_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0-"
-#define IWL_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0-"
-#define IWL_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0-"
-#define IWL_SO_A_MR_A_FW_PRE "iwlwifi-so-a0-mr-a0-"
-#define IWL_SNJ_A_GF4_A_FW_PRE "iwlwifi-SoSnj-a0-gf4-a0-"
-#define IWL_SNJ_A_GF_A_FW_PRE "iwlwifi-SoSnj-a0-gf-a0-"
-#define IWL_SNJ_A_HR_B_FW_PRE "iwlwifi-SoSnj-a0-hr-b0-"
-#define IWL_SNJ_A_JF_B_FW_PRE "iwlwifi-SoSnj-a0-jf-b0-"
-#define IWL_MA_A_HR_B_FW_PRE "iwlwifi-ma-a0-hr-b0-"
-#define IWL_MA_A_GF_A_FW_PRE "iwlwifi-ma-a0-gf-a0-"
-#define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0-"
-#define IWL_MA_A_MR_A_FW_PRE "iwlwifi-ma-a0-mr-a0-"
-#define IWL_MA_A_FM_A_FW_PRE "iwlwifi-ma-a0-fm-a0-"
-#define IWL_MA_B_HR_B_FW_PRE "iwlwifi-ma-b0-hr-b0-"
-#define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0-"
-#define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0-"
-#define IWL_MA_B_MR_A_FW_PRE "iwlwifi-ma-b0-mr-a0-"
-#define IWL_MA_B_FM_A_FW_PRE "iwlwifi-ma-b0-fm-a0-"
-#define IWL_SNJ_A_MR_A_FW_PRE "iwlwifi-SoSnj-a0-mr-a0-"
-#define IWL_BZ_A_HR_A_FW_PRE "iwlwifi-bz-a0-hr-b0-"
-#define IWL_BZ_A_HR_B_FW_PRE "iwlwifi-bz-a0-hr-b0-"
-#define IWL_BZ_A_GF_A_FW_PRE "iwlwifi-bz-a0-gf-a0-"
-#define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0-"
-#define IWL_BZ_A_MR_A_FW_PRE "iwlwifi-bz-a0-mr-a0-"
-#define IWL_BZ_A_FM_A_FW_PRE "iwlwifi-bz-a0-fm-a0-"
-#define IWL_BZ_A_FM4_A_FW_PRE "iwlwifi-bz-a0-fm4-a0-"
-#define IWL_BZ_A_FM_B_FW_PRE "iwlwifi-bz-a0-fm-b0-"
-#define IWL_BZ_A_FM4_B_FW_PRE "iwlwifi-bz-a0-fm4-b0-"
-#define IWL_GL_A_FM_A_FW_PRE "iwlwifi-gl-a0-fm-a0-"
-#define IWL_GL_B_FM_B_FW_PRE "iwlwifi-gl-b0-fm-b0-"
-#define IWL_BZ_Z_GF_A_FW_PRE "iwlwifi-bz-z0-gf-a0-"
-#define IWL_BNJ_A_FM_A_FW_PRE "iwlwifi-BzBnj-a0-fm-a0-"
-#define IWL_BNJ_A_FM4_A_FW_PRE "iwlwifi-BzBnj-a0-fm4-a0-"
-#define IWL_BNJ_B_FM4_B_FW_PRE "iwlwifi-BzBnj-b0-fm4-b0-"
-#define IWL_BNJ_A_GF_A_FW_PRE "iwlwifi-BzBnj-a0-gf-a0-"
-#define IWL_BNJ_B_GF_A_FW_PRE "iwlwifi-BzBnj-b0-gf-a0-"
-#define IWL_BNJ_A_GF4_A_FW_PRE "iwlwifi-BzBnj-a0-gf4-a0-"
-#define IWL_BNJ_B_GF4_A_FW_PRE "iwlwifi-BzBnj-b0-gf4-a0-"
-#define IWL_BNJ_A_HR_A_FW_PRE "iwlwifi-BzBnj-a0-hr-b0-"
-#define IWL_BNJ_A_HR_B_FW_PRE "iwlwifi-BzBnj-a0-hr-b0-"
-#define IWL_BNJ_B_HR_A_FW_PRE "iwlwifi-BzBnj-b0-hr-b0-"
-#define IWL_BNJ_B_HR_B_FW_PRE "iwlwifi-BzBnj-b0-hr-b0-"
-#define IWL_BNJ_B_FM_B_FW_PRE "iwlwifi-BzBnj-b0-fm-b0-"
-
+#define IWL_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0"
+#define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0"
+#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0"
+#define IWL_QU_C_JF_B_FW_PRE "iwlwifi-Qu-c0-jf-b0"
+#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0"
+#define IWL_QUZ_A_JF_B_FW_PRE "iwlwifi-QuZ-a0-jf-b0"
+#define IWL_CC_A_FW_PRE "iwlwifi-cc-a0"
#define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \
- IWL_QU_B_HR_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_QNJ_B_HR_B_MODULE_FIRMWARE(api) \
- IWL_QNJ_B_HR_B_FW_PRE __stringify(api) ".ucode"
+ IWL_QU_B_HR_B_FW_PRE "-" __stringify(api) ".ucode"
#define IWL_QUZ_A_HR_B_MODULE_FIRMWARE(api) \
- IWL_QUZ_A_HR_B_FW_PRE __stringify(api) ".ucode"
+ IWL_QUZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
#define IWL_QUZ_A_JF_B_MODULE_FIRMWARE(api) \
- IWL_QUZ_A_JF_B_FW_PRE __stringify(api) ".ucode"
+ IWL_QUZ_A_JF_B_FW_PRE "-" __stringify(api) ".ucode"
#define IWL_QU_C_HR_B_MODULE_FIRMWARE(api) \
- IWL_QU_C_HR_B_FW_PRE __stringify(api) ".ucode"
+ IWL_QU_C_HR_B_FW_PRE "-" __stringify(api) ".ucode"
#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \
- IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_QNJ_B_JF_B_MODULE_FIRMWARE(api) \
- IWL_QNJ_B_JF_B_FW_PRE __stringify(api) ".ucode"
+ IWL_QU_B_JF_B_FW_PRE "-" __stringify(api) ".ucode"
#define IWL_CC_A_MODULE_FIRMWARE(api) \
- IWL_CC_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_SO_A_JF_B_MODULE_FIRMWARE(api) \
- IWL_SO_A_JF_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_SO_A_HR_B_MODULE_FIRMWARE(api) \
- IWL_SO_A_HR_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_SO_A_GF_A_MODULE_FIRMWARE(api) \
- IWL_SO_A_GF_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_TY_A_GF_A_MODULE_FIRMWARE(api) \
- IWL_TY_A_GF_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_SNJ_A_GF4_A_MODULE_FIRMWARE(api) \
- IWL_SNJ_A_GF4_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_SNJ_A_GF_A_MODULE_FIRMWARE(api) \
- IWL_SNJ_A_GF_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_SNJ_A_HR_B_MODULE_FIRMWARE(api) \
- IWL_SNJ_A_HR_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_SNJ_A_JF_B_MODULE_FIRMWARE(api) \
- IWL_SNJ_A_JF_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(api) \
- IWL_MA_A_HR_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(api) \
- IWL_MA_A_GF_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(api) \
- IWL_MA_A_GF4_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(api) \
- IWL_MA_A_MR_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_A_FM_A_FW_MODULE_FIRMWARE(api) \
- IWL_MA_A_FM_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(api) \
- IWL_MA_B_HR_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(api) \
- IWL_MA_B_GF_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(api) \
- IWL_MA_B_GF4_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(api) \
- IWL_MA_B_MR_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_B_FM_A_FW_MODULE_FIRMWARE(api) \
- IWL_MA_B_FM_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_SNJ_A_MR_A_MODULE_FIRMWARE(api) \
- IWL_SNJ_A_MR_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_HR_A_MODULE_FIRMWARE(api) \
- IWL_BZ_A_HR_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \
- IWL_BZ_A_HR_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_GF_A_MODULE_FIRMWARE(api) \
- IWL_BZ_A_GF_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_GF4_A_MODULE_FIRMWARE(api) \
- IWL_BZ_A_GF4_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_MR_A_MODULE_FIRMWARE(api) \
- IWL_BZ_A_MR_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_FM_A_MODULE_FIRMWARE(api) \
- IWL_BZ_A_FM_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_FM4_A_MODULE_FIRMWARE(api) \
- IWL_BZ_A_FM4_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_FM_B_MODULE_FIRMWARE(api) \
- IWL_BZ_A_FM_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_FM4_B_MODULE_FIRMWARE(api) \
- IWL_BZ_A_FM4_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_GL_A_FM_A_MODULE_FIRMWARE(api) \
- IWL_GL_A_FM_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_GL_B_FM_B_MODULE_FIRMWARE(api) \
- IWL_GL_B_FM_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_A_FM_A_MODULE_FIRMWARE(api) \
- IWL_BNJ_A_FM_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_A_FM4_A_MODULE_FIRMWARE(api) \
- IWL_BNJ_A_FM4_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_B_FM4_B_MODULE_FIRMWARE(api) \
- IWL_BNJ_B_FM4_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_A_GF_A_MODULE_FIRMWARE(api) \
- IWL_BNJ_A_GF_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_B_GF_A_MODULE_FIRMWARE(api) \
- IWL_BNJ_B_GF_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_A_GF4_A_MODULE_FIRMWARE(api) \
- IWL_BNJ_A_GF4_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_B_GF4_A_MODULE_FIRMWARE(api) \
- IWL_BNJ_B_GF4_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_A_HR_A_MODULE_FIRMWARE(api) \
- IWL_BNJ_A_HR_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_A_HR_B_MODULE_FIRMWARE(api) \
- IWL_BNJ_A_HR_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_B_HR_A_MODULE_FIRMWARE(api) \
- IWL_BNJ_B_HR_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_B_HR_B_MODULE_FIRMWARE(api) \
- IWL_BNJ_B_HR_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_B_FM_B_MODULE_FIRMWARE(api) \
- IWL_BNJ_B_FM_B_FW_PRE __stringify(api) ".ucode"
+ IWL_CC_A_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl_22000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
@@ -195,34 +59,14 @@ static const struct iwl_base_params iwl_22000_base_params = {
.pcie_l1_allowed = true,
};
-static const struct iwl_base_params iwl_ax210_base_params = {
- .eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
- .num_of_queues = 512,
- .max_tfd_queue_size = 65536,
- .shadow_ram_support = true,
- .led_compensation = 57,
- .wd_timeout = IWL_LONG_WD_TIMEOUT,
- .max_event_log_size = 512,
- .shadow_reg_enable = true,
- .pcie_l1_allowed = true,
-};
-
-static const struct iwl_ht_params iwl_22000_ht_params = {
+const struct iwl_ht_params iwl_22000_ht_params = {
.stbc = true,
.ldpc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ) |
BIT(NL80211_BAND_6GHZ),
};
-static const struct iwl_ht_params iwl_gl_a_ht_params = {
- .stbc = false, /* we explicitly disable STBC for GL step A */
- .ldpc = true,
- .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ) |
- BIT(NL80211_BAND_6GHZ),
-};
-
#define IWL_DEVICE_22000_COMMON \
- .ucode_api_max = IWL_22000_UCODE_API_MAX, \
.ucode_api_min = IWL_22000_UCODE_API_MIN, \
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = 10, \
@@ -240,7 +84,6 @@ static const struct iwl_ht_params iwl_gl_a_ht_params = {
.mac_addr_from_csr = 0x380, \
.ht_params = &iwl_22000_ht_params, \
.nvm_ver = IWL_22000_NVM_VERSION, \
- .trans.use_tfh = true, \
.trans.rf_id = true, \
.trans.gen2 = true, \
.nvm_type = IWL_NVM_EXT, \
@@ -261,6 +104,7 @@ static const struct iwl_ht_params iwl_gl_a_ht_params = {
#define IWL_DEVICE_22500 \
IWL_DEVICE_22000_COMMON, \
+ .ucode_api_max = IWL_22000_UCODE_API_MAX, \
.trans.device_family = IWL_DEVICE_FAMILY_22000, \
.trans.base_params = &iwl_22000_base_params, \
.gp2_reg_addr = 0xa02c68, \
@@ -275,111 +119,8 @@ static const struct iwl_ht_params iwl_gl_a_ht_params = {
}, \
}
-#define IWL_DEVICE_AX210 \
- IWL_DEVICE_22000_COMMON, \
- .trans.umac_prph_offset = 0x300000, \
- .trans.device_family = IWL_DEVICE_FAMILY_AX210, \
- .trans.base_params = &iwl_ax210_base_params, \
- .min_txq_size = 128, \
- .gp2_reg_addr = 0xd02c68, \
- .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_HE, \
- .mon_dram_regs = { \
- .write_ptr = { \
- .addr = DBGC_CUR_DBGBUF_STATUS, \
- .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
- }, \
- .cycle_cnt = { \
- .addr = DBGC_DBGBUF_WRAP_AROUND, \
- .mask = 0xffffffff, \
- }, \
- .cur_frag = { \
- .addr = DBGC_CUR_DBGBUF_STATUS, \
- .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
- }, \
- }
-
-#define IWL_DEVICE_BZ_COMMON \
- .ucode_api_max = IWL_22000_UCODE_API_MAX, \
- .ucode_api_min = IWL_22000_UCODE_API_MIN, \
- .led_mode = IWL_LED_RF_STATE, \
- .nvm_hw_section_num = 10, \
- .non_shared_ant = ANT_B, \
- .dccm_offset = IWL_22000_DCCM_OFFSET, \
- .dccm_len = IWL_22000_DCCM_LEN, \
- .dccm2_offset = IWL_22000_DCCM2_OFFSET, \
- .dccm2_len = IWL_22000_DCCM2_LEN, \
- .smem_offset = IWL_22000_SMEM_OFFSET, \
- .smem_len = IWL_22000_SMEM_LEN, \
- .apmg_not_supported = true, \
- .trans.mq_rx_supported = true, \
- .vht_mu_mimo_supported = true, \
- .mac_addr_from_csr = 0x30, \
- .nvm_ver = IWL_22000_NVM_VERSION, \
- .trans.use_tfh = true, \
- .trans.rf_id = true, \
- .trans.gen2 = true, \
- .nvm_type = IWL_NVM_EXT, \
- .dbgc_supported = true, \
- .min_umac_error_event_table = 0xD0000, \
- .d3_debug_data_base_addr = 0x401000, \
- .d3_debug_data_length = 60 * 1024, \
- .mon_smem_regs = { \
- .write_ptr = { \
- .addr = LDBG_M2S_BUF_WPTR, \
- .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
- }, \
- .cycle_cnt = { \
- .addr = LDBG_M2S_BUF_WRAP_CNT, \
- .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
- }, \
- }, \
- .trans.umac_prph_offset = 0x300000, \
- .trans.device_family = IWL_DEVICE_FAMILY_BZ, \
- .trans.base_params = &iwl_ax210_base_params, \
- .min_txq_size = 128, \
- .gp2_reg_addr = 0xd02c68, \
- .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT, \
- .mon_dram_regs = { \
- .write_ptr = { \
- .addr = DBGC_CUR_DBGBUF_STATUS, \
- .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
- }, \
- .cycle_cnt = { \
- .addr = DBGC_DBGBUF_WRAP_AROUND, \
- .mask = 0xffffffff, \
- }, \
- .cur_frag = { \
- .addr = DBGC_CUR_DBGBUF_STATUS, \
- .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
- }, \
- }, \
- .mon_dbgi_regs = { \
- .write_ptr = { \
- .addr = DBGI_SRAM_FIFO_POINTERS, \
- .mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK, \
- }, \
- }
-
-#define IWL_DEVICE_BZ \
- IWL_DEVICE_BZ_COMMON, \
- .ht_params = &iwl_22000_ht_params
-
-#define IWL_DEVICE_GL_A \
- IWL_DEVICE_BZ_COMMON, \
- .ht_params = &iwl_gl_a_ht_params
-
-const struct iwl_cfg_trans_params iwl_qnj_trans_cfg = {
- .mq_rx_supported = true,
- .use_tfh = true,
- .rf_id = true,
- .gen2 = true,
- .device_family = IWL_DEVICE_FAMILY_22000,
- .base_params = &iwl_22000_base_params,
-};
-
const struct iwl_cfg_trans_params iwl_qu_trans_cfg = {
.mq_rx_supported = true,
- .use_tfh = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_22000,
@@ -391,7 +132,6 @@ const struct iwl_cfg_trans_params iwl_qu_trans_cfg = {
const struct iwl_cfg_trans_params iwl_qu_medium_latency_trans_cfg = {
.mq_rx_supported = true,
- .use_tfh = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_22000,
@@ -403,7 +143,6 @@ const struct iwl_cfg_trans_params iwl_qu_medium_latency_trans_cfg = {
const struct iwl_cfg_trans_params iwl_qu_long_latency_trans_cfg = {
.mq_rx_supported = true,
- .use_tfh = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_22000,
@@ -414,59 +153,6 @@ const struct iwl_cfg_trans_params iwl_qu_long_latency_trans_cfg = {
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
};
-const struct iwl_cfg_trans_params iwl_snj_trans_cfg = {
- .mq_rx_supported = true,
- .use_tfh = true,
- .rf_id = true,
- .gen2 = true,
- .device_family = IWL_DEVICE_FAMILY_AX210,
- .base_params = &iwl_ax210_base_params,
- .umac_prph_offset = 0x300000,
-};
-
-const struct iwl_cfg_trans_params iwl_so_trans_cfg = {
- .mq_rx_supported = true,
- .use_tfh = true,
- .rf_id = true,
- .gen2 = true,
- .device_family = IWL_DEVICE_FAMILY_AX210,
- .base_params = &iwl_ax210_base_params,
- .umac_prph_offset = 0x300000,
- .integrated = true,
- /* TODO: the following values need to be checked */
- .xtal_latency = 500,
- .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_200US,
-};
-
-const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg = {
- .mq_rx_supported = true,
- .use_tfh = true,
- .rf_id = true,
- .gen2 = true,
- .device_family = IWL_DEVICE_FAMILY_AX210,
- .base_params = &iwl_ax210_base_params,
- .umac_prph_offset = 0x300000,
- .integrated = true,
- .low_latency_xtal = true,
- .xtal_latency = 12000,
- .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
-};
-
-const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg = {
- .mq_rx_supported = true,
- .use_tfh = true,
- .rf_id = true,
- .gen2 = true,
- .device_family = IWL_DEVICE_FAMILY_AX210,
- .base_params = &iwl_ax210_base_params,
- .umac_prph_offset = 0x300000,
- .integrated = true,
- .low_latency_xtal = true,
- .xtal_latency = 12000,
- .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
- .imr_enabled = true,
-};
-
/*
* If the device doesn't support HE, no need to have that many buffers.
* 22000 devices can split multiple frames into a single RB, so fewer are
@@ -476,7 +162,6 @@ const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg = {
*/
#define IWL_NUM_RBDS_NON_HE 512
#define IWL_NUM_RBDS_22000_HE 2048
-#define IWL_NUM_RBDS_AX210_HE 4096
/*
* All JF radio modules are part of the 9000 series, but the MAC part
@@ -507,63 +192,20 @@ const struct iwl_cfg iwl9560_quz_a0_jf_b0_cfg = {
.num_rbds = IWL_NUM_RBDS_NON_HE,
};
-const struct iwl_cfg iwl9560_qnj_b0_jf_b0_cfg = {
- .fw_name_pre = IWL_QNJ_B_JF_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_NON_HE,
-};
-
const struct iwl_cfg_trans_params iwl_ax200_trans_cfg = {
.device_family = IWL_DEVICE_FAMILY_22000,
.base_params = &iwl_22000_base_params,
.mq_rx_supported = true,
- .use_tfh = true,
.rf_id = true,
.gen2 = true,
.bisr_workaround = 1,
};
-const struct iwl_cfg_trans_params iwl_ma_trans_cfg = {
- .device_family = IWL_DEVICE_FAMILY_AX210,
- .base_params = &iwl_ax210_base_params,
- .mq_rx_supported = true,
- .use_tfh = true,
- .rf_id = true,
- .gen2 = true,
- .integrated = true,
- .umac_prph_offset = 0x300000
-};
-
-const struct iwl_cfg_trans_params iwl_bz_trans_cfg = {
- .device_family = IWL_DEVICE_FAMILY_BZ,
- .base_params = &iwl_ax210_base_params,
- .mq_rx_supported = true,
- .use_tfh = true,
- .rf_id = true,
- .gen2 = true,
- .integrated = true,
- .umac_prph_offset = 0x300000,
- .xtal_latency = 12000,
- .low_latency_xtal = true,
- .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
-};
-
const char iwl_ax101_name[] = "Intel(R) Wi-Fi 6 AX101";
const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz";
const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz";
const char iwl_ax203_name[] = "Intel(R) Wi-Fi 6 AX203";
const char iwl_ax204_name[] = "Intel(R) Wi-Fi 6 AX204 160MHz";
-const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz";
-const char iwl_ax221_name[] = "Intel(R) Wi-Fi 6E AX221 160MHz";
-const char iwl_ax231_name[] = "Intel(R) Wi-Fi 6E AX231 160MHz";
-const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6E AX411 160MHz";
-const char iwl_bz_name[] = "Intel(R) TBD Bz device";
const char iwl_ax200_killer_1650w_name[] =
"Killer(R) Wi-Fi 6 AX1650w 160MHz Wireless Network Adapter (200D2W)";
@@ -573,18 +215,6 @@ const char iwl_ax201_killer_1650s_name[] =
"Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)";
const char iwl_ax201_killer_1650i_name[] =
"Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)";
-const char iwl_ax210_killer_1675w_name[] =
- "Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)";
-const char iwl_ax210_killer_1675x_name[] =
- "Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)";
-const char iwl_ax211_killer_1675s_name[] =
- "Killer(R) Wi-Fi 6E AX1675s 160MHz Wireless Network Adapter (211NGW)";
-const char iwl_ax211_killer_1675i_name[] =
- "Killer(R) Wi-Fi 6E AX1675i 160MHz Wireless Network Adapter (211NGW)";
-const char iwl_ax411_killer_1690s_name[] =
- "Killer(R) Wi-Fi 6E AX1690s 160MHz Wireless Network Adapter (411D2W)";
-const char iwl_ax411_killer_1690i_name[] =
- "Killer(R) Wi-Fi 6E AX1690i 160MHz Wireless Network Adapter (411NGW)";
const struct iwl_cfg iwl_qu_b0_hr1_b0 = {
.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
@@ -778,203 +408,6 @@ const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0 = {
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
-const struct iwl_cfg iwl_qnj_b0_hr_b0_cfg = {
- .fw_name_pre = IWL_QNJ_B_HR_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0 = {
- .name = "Intel(R) Wireless-AC 9560 160MHz",
- .fw_name_pre = IWL_SO_A_JF_B_FW_PRE,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_NON_HE,
-};
-
-const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0 = {
- .name = iwl_ax211_name,
- .fw_name_pre = IWL_SO_A_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long = {
- .name = iwl_ax211_name,
- .fw_name_pre = IWL_SO_A_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
- .trans.xtal_latency = 12000,
- .trans.low_latency_xtal = true,
-};
-
-const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = {
- .name = "Intel(R) Wi-Fi 6 AX210 160MHz",
- .fw_name_pre = IWL_TY_A_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0 = {
- .name = iwl_ax411_name,
- .fw_name_pre = IWL_SO_A_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0_long = {
- .name = iwl_ax411_name,
- .fw_name_pre = IWL_SO_A_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
- .trans.xtal_latency = 12000,
- .trans.low_latency_xtal = true,
-};
-
-const struct iwl_cfg iwlax411_2ax_cfg_sosnj_gf4_a0 = {
- .name = iwl_ax411_name,
- .fw_name_pre = IWL_SNJ_A_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwlax211_cfg_snj_gf_a0 = {
- .name = iwl_ax211_name,
- .fw_name_pre = IWL_SNJ_A_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_snj_hr_b0 = {
- .fw_name_pre = IWL_SNJ_A_HR_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_snj_a0_jf_b0 = {
- .fw_name_pre = IWL_SNJ_A_JF_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_a0_hr_b0 = {
- .fw_name_pre = IWL_MA_A_HR_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_a0_gf_a0 = {
- .fw_name_pre = IWL_MA_A_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_a0_gf4_a0 = {
- .fw_name_pre = IWL_MA_A_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_a0_mr_a0 = {
- .fw_name_pre = IWL_MA_A_MR_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_a0_ms_a0 = {
- .fw_name_pre = IWL_MA_A_MR_A_FW_PRE,
- .uhb_supported = false,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_b0_fm_a0 = {
- .fw_name_pre = IWL_MA_B_FM_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_b0_hr_b0 = {
- .fw_name_pre = IWL_MA_B_HR_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_b0_gf_a0 = {
- .fw_name_pre = IWL_MA_B_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_b0_gf4_a0 = {
- .fw_name_pre = IWL_MA_B_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_b0_mr_a0 = {
- .fw_name_pre = IWL_MA_B_MR_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_so_a0_ms_a0 = {
- .fw_name_pre = IWL_SO_A_MR_A_FW_PRE,
- .uhb_supported = false,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_a0_fm_a0 = {
- .fw_name_pre = IWL_MA_A_FM_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_snj_a0_mr_a0 = {
- .fw_name_pre = IWL_SNJ_A_MR_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_snj_a0_ms_a0 = {
- .fw_name_pre = IWL_SNJ_A_MR_A_FW_PRE,
- .uhb_supported = false,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_so_a0_hr_a0 = {
- .fw_name_pre = IWL_SO_A_HR_B_FW_PRE,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
const struct iwl_cfg iwl_cfg_quz_a0_hr_b0 = {
.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
IWL_DEVICE_22500,
@@ -987,243 +420,9 @@ const struct iwl_cfg iwl_cfg_quz_a0_hr_b0 = {
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
-const struct iwl_cfg iwl_cfg_bz_a0_hr_a0 = {
- .fw_name_pre = IWL_BZ_A_HR_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_a0_hr_b0 = {
- .fw_name_pre = IWL_BZ_A_HR_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_a0_gf_a0 = {
- .fw_name_pre = IWL_BZ_A_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0 = {
- .fw_name_pre = IWL_BZ_A_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_a0_mr_a0 = {
- .fw_name_pre = IWL_BZ_A_MR_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_a0_fm_a0 = {
- .fw_name_pre = IWL_BZ_A_FM_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_a0_fm4_a0 = {
- .fw_name_pre = IWL_BZ_A_FM4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_a0_fm_b0 = {
- .fw_name_pre = IWL_BZ_A_FM_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_a0_fm4_b0 = {
- .fw_name_pre = IWL_BZ_A_FM4_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_gl_a0_fm_a0 = {
- .fw_name_pre = IWL_GL_A_FM_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_GL_A,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_gl_b0_fm_b0 = {
- .fw_name_pre = IWL_GL_B_FM_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_z0_gf_a0 = {
- .fw_name_pre = IWL_BZ_Z_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_a0_fm_a0 = {
- .fw_name_pre = IWL_BNJ_A_FM_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_a0_fm4_a0 = {
- .fw_name_pre = IWL_BNJ_A_FM4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_b0_fm4_b0 = {
- .fw_name_pre = IWL_BNJ_B_FM4_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_a0_gf_a0 = {
- .fw_name_pre = IWL_BNJ_A_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_b0_gf_a0 = {
- .fw_name_pre = IWL_BNJ_B_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_a0_gf4_a0 = {
- .fw_name_pre = IWL_BNJ_A_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_b0_gf4_a0 = {
- .fw_name_pre = IWL_BNJ_B_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_a0_hr_a0 = {
- .fw_name_pre = IWL_BNJ_A_HR_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_a0_hr_b0 = {
- .fw_name_pre = IWL_BNJ_A_HR_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_b0_hr_a0 = {
- .fw_name_pre = IWL_BNJ_B_HR_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_b0_hr_b0 = {
- .fw_name_pre = IWL_BNJ_B_HR_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_b0_fm_b0 = {
- .fw_name_pre = IWL_BNJ_B_FM_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_QNJ_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QUZ_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_QNJ_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SO_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_TY_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SNJ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SNJ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SNJ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SNJ_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_A_FM_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_B_FM_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SNJ_A_MR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_HR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_MR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_FM_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_GL_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_A_FM4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_B_FM4_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_B_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_B_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_B_HR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_FM4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_FM4_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_GL_B_FM_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_B_FM_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c
index e2e23d2bc1fe..de7ede59a994 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2018 - 2020 Intel Corporation
+ * Copyright(c) 2018 - 2020, 2023 Intel Corporation
*****************************************************************************/
#include <linux/module.h>
@@ -24,11 +24,11 @@
#define EEPROM_5050_TX_POWER_VERSION (4)
#define EEPROM_5050_EEPROM_VERSION (0x21E)
-#define IWL5000_FW_PRE "iwlwifi-5000-"
-#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE __stringify(api) ".ucode"
+#define IWL5000_FW_PRE "iwlwifi-5000"
+#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL5150_FW_PRE "iwlwifi-5150-"
-#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE __stringify(api) ".ucode"
+#define IWL5150_FW_PRE "iwlwifi-5150"
+#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl5000_base_params = {
.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
index 20929e59c2f4..f013cf420569 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2018 - 2020 Intel Corporation
+ * Copyright(c) 2018 - 2020, 2023 Intel Corporation
*****************************************************************************/
#include <linux/module.h>
@@ -37,17 +37,17 @@
#define EEPROM_6035_TX_POWER_VERSION (6)
#define EEPROM_6035_EEPROM_VERSION (0x753)
-#define IWL6000_FW_PRE "iwlwifi-6000-"
-#define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE __stringify(api) ".ucode"
+#define IWL6000_FW_PRE "iwlwifi-6000"
+#define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL6050_FW_PRE "iwlwifi-6050-"
-#define IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE __stringify(api) ".ucode"
+#define IWL6050_FW_PRE "iwlwifi-6050"
+#define IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL6005_FW_PRE "iwlwifi-6000g2a-"
-#define IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE __stringify(api) ".ucode"
+#define IWL6005_FW_PRE "iwlwifi-6000g2a"
+#define IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL6030_FW_PRE "iwlwifi-6000g2b-"
-#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE __stringify(api) ".ucode"
+#define IWL6030_FW_PRE "iwlwifi-6000g2b"
+#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl6000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_2K,
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c
index b24dc5523a52..4e2afdedf4c6 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2020 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2020, 2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015 Intel Deutschland GmbH
*/
@@ -34,20 +34,20 @@
#define IWL3160_DCCM_LEN 0x10000
#define IWL7265_DCCM_LEN 0x17A00
-#define IWL7260_FW_PRE "iwlwifi-7260-"
-#define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode"
+#define IWL7260_FW_PRE "iwlwifi-7260"
+#define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL3160_FW_PRE "iwlwifi-3160-"
-#define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode"
+#define IWL3160_FW_PRE "iwlwifi-3160"
+#define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL3168_FW_PRE "iwlwifi-3168-"
-#define IWL3168_MODULE_FIRMWARE(api) IWL3168_FW_PRE __stringify(api) ".ucode"
+#define IWL3168_FW_PRE "iwlwifi-3168"
+#define IWL3168_MODULE_FIRMWARE(api) IWL3168_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL7265_FW_PRE "iwlwifi-7265-"
-#define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode"
+#define IWL7265_FW_PRE "iwlwifi-7265"
+#define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL7265D_FW_PRE "iwlwifi-7265D-"
-#define IWL7265D_MODULE_FIRMWARE(api) IWL7265D_FW_PRE __stringify(api) ".ucode"
+#define IWL7265D_FW_PRE "iwlwifi-7265D"
+#define IWL7265D_MODULE_FIRMWARE(api) IWL7265D_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl7000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_16K,
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c
index a6454287d506..d09cf8d7dc01 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2014, 2018-2020 Intel Corporation
+ * Copyright (C) 2014, 2018-2020, 2023 Intel Corporation
* Copyright (C) 2014-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016 Intel Deutschland GmbH
*/
@@ -27,13 +27,13 @@
#define IWL8260_SMEM_OFFSET 0x400000
#define IWL8260_SMEM_LEN 0x68000
-#define IWL8000_FW_PRE "iwlwifi-8000C-"
+#define IWL8000_FW_PRE "iwlwifi-8000C"
#define IWL8000_MODULE_FIRMWARE(api) \
- IWL8000_FW_PRE __stringify(api) ".ucode"
+ IWL8000_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL8265_FW_PRE "iwlwifi-8265-"
+#define IWL8265_FW_PRE "iwlwifi-8265"
#define IWL8265_MODULE_FIRMWARE(api) \
- IWL8265_FW_PRE __stringify(api) ".ucode"
+ IWL8265_FW_PRE "-" __stringify(api) ".ucode"
#define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C"
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
index 7a7ca06d46c1..0130d9a9b78b 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2021 Intel Corporation
+ * Copyright (C) 2018-2021, 2023 Intel Corporation
*/
#include <linux/module.h>
#include <linux/stringify.h>
@@ -26,12 +26,12 @@
#define IWL9000_SMEM_OFFSET 0x400000
#define IWL9000_SMEM_LEN 0x68000
-#define IWL9000_FW_PRE "iwlwifi-9000-pu-b0-jf-b0-"
-#define IWL9260_FW_PRE "iwlwifi-9260-th-b0-jf-b0-"
+#define IWL9000_FW_PRE "iwlwifi-9000-pu-b0-jf-b0"
+#define IWL9260_FW_PRE "iwlwifi-9260-th-b0-jf-b0"
#define IWL9000_MODULE_FIRMWARE(api) \
- IWL9000_FW_PRE __stringify(api) ".ucode"
+ IWL9000_FW_PRE "-" __stringify(api) ".ucode"
#define IWL9260_MODULE_FIRMWARE(api) \
- IWL9260_FW_PRE __stringify(api) ".ucode"
+ IWL9260_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl9000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c
new file mode 100644
index 000000000000..8d5f9dce71d5
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c
@@ -0,0 +1,301 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2015-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018-2023 Intel Corporation
+ */
+#include <linux/module.h>
+#include <linux/stringify.h>
+#include "iwl-config.h"
+#include "iwl-prph.h"
+#include "fw/api/txq.h"
+
+/* Highest firmware API version supported */
+#define IWL_AX210_UCODE_API_MAX 83
+
+/* Lowest firmware API version supported */
+#define IWL_AX210_UCODE_API_MIN 59
+
+/* NVM versions */
+#define IWL_AX210_NVM_VERSION 0x0a1d
+
+/* Memory offsets and lengths */
+#define IWL_AX210_DCCM_OFFSET 0x800000 /* LMAC1 */
+#define IWL_AX210_DCCM_LEN 0x10000 /* LMAC1 */
+#define IWL_AX210_DCCM2_OFFSET 0x880000
+#define IWL_AX210_DCCM2_LEN 0x8000
+#define IWL_AX210_SMEM_OFFSET 0x400000
+#define IWL_AX210_SMEM_LEN 0xD0000
+
+#define IWL_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0"
+#define IWL_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0"
+#define IWL_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0"
+#define IWL_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0"
+#define IWL_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0"
+#define IWL_SO_A_MR_A_FW_PRE "iwlwifi-so-a0-mr-a0"
+#define IWL_MA_A_HR_B_FW_PRE "iwlwifi-ma-a0-hr-b0"
+#define IWL_MA_A_GF_A_FW_PRE "iwlwifi-ma-a0-gf-a0"
+#define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0"
+#define IWL_MA_A_MR_A_FW_PRE "iwlwifi-ma-a0-mr-a0"
+#define IWL_MA_B_HR_B_FW_PRE "iwlwifi-ma-b0-hr-b0"
+#define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0"
+#define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0"
+#define IWL_MA_B_MR_A_FW_PRE "iwlwifi-ma-b0-mr-a0"
+
+#define IWL_SO_A_JF_B_MODULE_FIRMWARE(api) \
+ IWL_SO_A_JF_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SO_A_HR_B_MODULE_FIRMWARE(api) \
+ IWL_SO_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SO_A_GF_A_MODULE_FIRMWARE(api) \
+ IWL_SO_A_GF_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_TY_A_GF_A_MODULE_FIRMWARE(api) \
+ IWL_TY_A_GF_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_A_GF_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_A_MR_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_B_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_B_GF_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_B_GF4_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_B_MR_A_FW_PRE "-" __stringify(api) ".ucode"
+
+static const struct iwl_base_params iwl_ax210_base_params = {
+ .eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
+ .num_of_queues = 512,
+ .max_tfd_queue_size = 65536,
+ .shadow_ram_support = true,
+ .led_compensation = 57,
+ .wd_timeout = IWL_LONG_WD_TIMEOUT,
+ .max_event_log_size = 512,
+ .shadow_reg_enable = true,
+ .pcie_l1_allowed = true,
+};
+
+#define IWL_DEVICE_AX210_COMMON \
+ .ucode_api_min = IWL_AX210_UCODE_API_MIN, \
+ .led_mode = IWL_LED_RF_STATE, \
+ .nvm_hw_section_num = 10, \
+ .non_shared_ant = ANT_B, \
+ .dccm_offset = IWL_AX210_DCCM_OFFSET, \
+ .dccm_len = IWL_AX210_DCCM_LEN, \
+ .dccm2_offset = IWL_AX210_DCCM2_OFFSET, \
+ .dccm2_len = IWL_AX210_DCCM2_LEN, \
+ .smem_offset = IWL_AX210_SMEM_OFFSET, \
+ .smem_len = IWL_AX210_SMEM_LEN, \
+ .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
+ .apmg_not_supported = true, \
+ .trans.mq_rx_supported = true, \
+ .vht_mu_mimo_supported = true, \
+ .mac_addr_from_csr = 0x380, \
+ .ht_params = &iwl_22000_ht_params, \
+ .nvm_ver = IWL_AX210_NVM_VERSION, \
+ .trans.rf_id = true, \
+ .trans.gen2 = true, \
+ .nvm_type = IWL_NVM_EXT, \
+ .dbgc_supported = true, \
+ .min_umac_error_event_table = 0x400000, \
+ .d3_debug_data_base_addr = 0x401000, \
+ .d3_debug_data_length = 60 * 1024, \
+ .mon_smem_regs = { \
+ .write_ptr = { \
+ .addr = LDBG_M2S_BUF_WPTR, \
+ .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
+ }, \
+ .cycle_cnt = { \
+ .addr = LDBG_M2S_BUF_WRAP_CNT, \
+ .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
+ }, \
+ }
+
+#define IWL_DEVICE_AX210 \
+ IWL_DEVICE_AX210_COMMON, \
+ .ucode_api_max = IWL_AX210_UCODE_API_MAX, \
+ .trans.umac_prph_offset = 0x300000, \
+ .trans.device_family = IWL_DEVICE_FAMILY_AX210, \
+ .trans.base_params = &iwl_ax210_base_params, \
+ .min_txq_size = 128, \
+ .gp2_reg_addr = 0xd02c68, \
+ .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_HE, \
+ .mon_dram_regs = { \
+ .write_ptr = { \
+ .addr = DBGC_CUR_DBGBUF_STATUS, \
+ .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
+ }, \
+ .cycle_cnt = { \
+ .addr = DBGC_DBGBUF_WRAP_AROUND, \
+ .mask = 0xffffffff, \
+ }, \
+ .cur_frag = { \
+ .addr = DBGC_CUR_DBGBUF_STATUS, \
+ .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
+ }, \
+ }
+
+const struct iwl_cfg_trans_params iwl_so_trans_cfg = {
+ .mq_rx_supported = true,
+ .rf_id = true,
+ .gen2 = true,
+ .device_family = IWL_DEVICE_FAMILY_AX210,
+ .base_params = &iwl_ax210_base_params,
+ .umac_prph_offset = 0x300000,
+ .integrated = true,
+ /* TODO: the following values need to be checked */
+ .xtal_latency = 500,
+ .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_200US,
+};
+
+const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg = {
+ .mq_rx_supported = true,
+ .rf_id = true,
+ .gen2 = true,
+ .device_family = IWL_DEVICE_FAMILY_AX210,
+ .base_params = &iwl_ax210_base_params,
+ .umac_prph_offset = 0x300000,
+ .integrated = true,
+ .low_latency_xtal = true,
+ .xtal_latency = 12000,
+ .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
+};
+
+const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg = {
+ .mq_rx_supported = true,
+ .rf_id = true,
+ .gen2 = true,
+ .device_family = IWL_DEVICE_FAMILY_AX210,
+ .base_params = &iwl_ax210_base_params,
+ .umac_prph_offset = 0x300000,
+ .integrated = true,
+ .low_latency_xtal = true,
+ .xtal_latency = 12000,
+ .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
+ .imr_enabled = true,
+};
+
+/*
+ * If the device doesn't support HE, no need to have that many buffers.
+ * AX210 devices can split multiple frames into a single RB, so fewer are
+ * needed; AX210 cannot (but use smaller RBs by default) - these sizes
+ * were picked according to 8 MSDUs inside 256 A-MSDUs in an A-MPDU, with
+ * additional overhead to account for processing time.
+ */
+#define IWL_NUM_RBDS_NON_HE 512
+#define IWL_NUM_RBDS_AX210_HE 4096
+
+const struct iwl_cfg_trans_params iwl_ma_trans_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_AX210,
+ .base_params = &iwl_ax210_base_params,
+ .mq_rx_supported = true,
+ .rf_id = true,
+ .gen2 = true,
+ .integrated = true,
+ .umac_prph_offset = 0x300000
+};
+
+const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz";
+const char iwl_ax221_name[] = "Intel(R) Wi-Fi 6E AX221 160MHz";
+const char iwl_ax231_name[] = "Intel(R) Wi-Fi 6E AX231 160MHz";
+const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6E AX411 160MHz";
+
+const char iwl_ax210_killer_1675w_name[] =
+ "Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)";
+const char iwl_ax210_killer_1675x_name[] =
+ "Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)";
+const char iwl_ax211_killer_1675s_name[] =
+ "Killer(R) Wi-Fi 6E AX1675s 160MHz Wireless Network Adapter (211NGW)";
+const char iwl_ax211_killer_1675i_name[] =
+ "Killer(R) Wi-Fi 6E AX1675i 160MHz Wireless Network Adapter (211NGW)";
+const char iwl_ax411_killer_1690s_name[] =
+ "Killer(R) Wi-Fi 6E AX1690s 160MHz Wireless Network Adapter (411D2W)";
+const char iwl_ax411_killer_1690i_name[] =
+ "Killer(R) Wi-Fi 6E AX1690i 160MHz Wireless Network Adapter (411NGW)";
+
+const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0 = {
+ .name = "Intel(R) Wireless-AC 9560 160MHz",
+ .fw_name_pre = IWL_SO_A_JF_B_FW_PRE,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_NON_HE,
+};
+
+const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0 = {
+ .name = iwl_ax211_name,
+ .fw_name_pre = IWL_SO_A_GF_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
+const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long = {
+ .name = iwl_ax211_name,
+ .fw_name_pre = IWL_SO_A_GF_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+ .trans.xtal_latency = 12000,
+ .trans.low_latency_xtal = true,
+};
+
+const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = {
+ .name = "Intel(R) Wi-Fi 6 AX210 160MHz",
+ .fw_name_pre = IWL_TY_A_GF_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
+const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0 = {
+ .name = iwl_ax411_name,
+ .fw_name_pre = IWL_SO_A_GF4_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
+const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0_long = {
+ .name = iwl_ax411_name,
+ .fw_name_pre = IWL_SO_A_GF4_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+ .trans.xtal_latency = 12000,
+ .trans.low_latency_xtal = true,
+};
+
+const struct iwl_cfg iwl_cfg_so_a0_ms_a0 = {
+ .fw_name_pre = IWL_SO_A_MR_A_FW_PRE,
+ .uhb_supported = false,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
+const struct iwl_cfg iwl_cfg_ma = {
+ .fw_name_mac = "ma",
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
+const struct iwl_cfg iwl_cfg_so_a0_hr_a0 = {
+ .fw_name_pre = IWL_SO_A_HR_B_FW_PRE,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
+MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SO_A_GF_A_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_TY_A_GF_A_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
new file mode 100644
index 000000000000..b9893b22e41d
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2015-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018-2023 Intel Corporation
+ */
+#include <linux/module.h>
+#include <linux/stringify.h>
+#include "iwl-config.h"
+#include "iwl-prph.h"
+#include "fw/api/txq.h"
+
+/* Highest firmware API version supported */
+#define IWL_BZ_UCODE_API_MAX 83
+
+/* Lowest firmware API version supported */
+#define IWL_BZ_UCODE_API_MIN 80
+
+/* NVM versions */
+#define IWL_BZ_NVM_VERSION 0x0a1d
+
+/* Memory offsets and lengths */
+#define IWL_BZ_DCCM_OFFSET 0x800000 /* LMAC1 */
+#define IWL_BZ_DCCM_LEN 0x10000 /* LMAC1 */
+#define IWL_BZ_DCCM2_OFFSET 0x880000
+#define IWL_BZ_DCCM2_LEN 0x8000
+#define IWL_BZ_SMEM_OFFSET 0x400000
+#define IWL_BZ_SMEM_LEN 0xD0000
+
+#define IWL_BZ_A_HR_B_FW_PRE "iwlwifi-bz-a0-hr-b0"
+#define IWL_BZ_A_GF_A_FW_PRE "iwlwifi-bz-a0-gf-a0"
+#define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0"
+#define IWL_BZ_A_FM_B_FW_PRE "iwlwifi-bz-a0-fm-b0"
+#define IWL_BZ_A_FM_C_FW_PRE "iwlwifi-bz-a0-fm-c0"
+#define IWL_BZ_A_FM4_B_FW_PRE "iwlwifi-bz-a0-fm4-b0"
+#define IWL_GL_B_FM_B_FW_PRE "iwlwifi-gl-b0-fm-b0"
+#define IWL_GL_C_FM_C_FW_PRE "iwlwifi-gl-c0-fm-c0"
+
+#define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \
+ IWL_BZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_BZ_A_GF_A_MODULE_FIRMWARE(api) \
+ IWL_BZ_A_GF_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_BZ_A_GF4_A_MODULE_FIRMWARE(api) \
+ IWL_BZ_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_BZ_A_FM_B_MODULE_FIRMWARE(api) \
+ IWL_BZ_A_FM_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_BZ_A_FM_C_MODULE_FIRMWARE(api) \
+ IWL_BZ_A_FM_C_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_BZ_A_FM4_B_MODULE_FIRMWARE(api) \
+ IWL_BZ_A_FM4_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_GL_B_FM_B_MODULE_FIRMWARE(api) \
+ IWL_GL_B_FM_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_GL_C_FM_C_MODULE_FIRMWARE(api) \
+ IWL_GL_C_FM_C_FW_PRE "-" __stringify(api) ".ucode"
+
+static const struct iwl_base_params iwl_bz_base_params = {
+ .eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
+ .num_of_queues = 512,
+ .max_tfd_queue_size = 65536,
+ .shadow_ram_support = true,
+ .led_compensation = 57,
+ .wd_timeout = IWL_LONG_WD_TIMEOUT,
+ .max_event_log_size = 512,
+ .shadow_reg_enable = true,
+ .pcie_l1_allowed = true,
+};
+
+#define IWL_DEVICE_BZ_COMMON \
+ .ucode_api_max = IWL_BZ_UCODE_API_MAX, \
+ .ucode_api_min = IWL_BZ_UCODE_API_MIN, \
+ .led_mode = IWL_LED_RF_STATE, \
+ .nvm_hw_section_num = 10, \
+ .non_shared_ant = ANT_B, \
+ .dccm_offset = IWL_BZ_DCCM_OFFSET, \
+ .dccm_len = IWL_BZ_DCCM_LEN, \
+ .dccm2_offset = IWL_BZ_DCCM2_OFFSET, \
+ .dccm2_len = IWL_BZ_DCCM2_LEN, \
+ .smem_offset = IWL_BZ_SMEM_OFFSET, \
+ .smem_len = IWL_BZ_SMEM_LEN, \
+ .apmg_not_supported = true, \
+ .trans.mq_rx_supported = true, \
+ .vht_mu_mimo_supported = true, \
+ .mac_addr_from_csr = 0x30, \
+ .nvm_ver = IWL_BZ_NVM_VERSION, \
+ .trans.rf_id = true, \
+ .trans.gen2 = true, \
+ .nvm_type = IWL_NVM_EXT, \
+ .dbgc_supported = true, \
+ .min_umac_error_event_table = 0xD0000, \
+ .d3_debug_data_base_addr = 0x401000, \
+ .d3_debug_data_length = 60 * 1024, \
+ .mon_smem_regs = { \
+ .write_ptr = { \
+ .addr = LDBG_M2S_BUF_WPTR, \
+ .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
+ }, \
+ .cycle_cnt = { \
+ .addr = LDBG_M2S_BUF_WRAP_CNT, \
+ .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
+ }, \
+ }, \
+ .trans.umac_prph_offset = 0x300000, \
+ .trans.device_family = IWL_DEVICE_FAMILY_BZ, \
+ .trans.base_params = &iwl_bz_base_params, \
+ .min_txq_size = 128, \
+ .gp2_reg_addr = 0xd02c68, \
+ .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT, \
+ .mon_dram_regs = { \
+ .write_ptr = { \
+ .addr = DBGC_CUR_DBGBUF_STATUS, \
+ .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
+ }, \
+ .cycle_cnt = { \
+ .addr = DBGC_DBGBUF_WRAP_AROUND, \
+ .mask = 0xffffffff, \
+ }, \
+ .cur_frag = { \
+ .addr = DBGC_CUR_DBGBUF_STATUS, \
+ .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
+ }, \
+ }, \
+ .mon_dbgi_regs = { \
+ .write_ptr = { \
+ .addr = DBGI_SRAM_FIFO_POINTERS, \
+ .mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK, \
+ }, \
+ }
+
+#define IWL_DEVICE_BZ \
+ IWL_DEVICE_BZ_COMMON, \
+ .ht_params = &iwl_22000_ht_params
+
+#define IWL_DEVICE_GL_A \
+ IWL_DEVICE_BZ_COMMON, \
+ .ht_params = &iwl_gl_a_ht_params
+
+/*
+ * If the device doesn't support HE, no need to have that many buffers.
+ * These sizes were picked according to 8 MSDUs inside 256 A-MSDUs in an
+ * A-MPDU, with additional overhead to account for processing time.
+ */
+#define IWL_NUM_RBDS_NON_HE 512
+#define IWL_NUM_RBDS_BZ_HE 4096
+
+const struct iwl_cfg_trans_params iwl_bz_trans_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_BZ,
+ .base_params = &iwl_bz_base_params,
+ .mq_rx_supported = true,
+ .rf_id = true,
+ .gen2 = true,
+ .integrated = true,
+ .umac_prph_offset = 0x300000,
+ .xtal_latency = 12000,
+ .low_latency_xtal = true,
+ .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
+};
+
+const char iwl_bz_name[] = "Intel(R) TBD Bz device";
+
+const struct iwl_cfg iwl_cfg_bz = {
+ .fw_name_mac = "bz",
+ .uhb_supported = true,
+ IWL_DEVICE_BZ,
+ .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
+ .num_rbds = IWL_NUM_RBDS_BZ_HE,
+};
+
+const struct iwl_cfg iwl_cfg_gl = {
+ .fw_name_mac = "gl",
+ .uhb_supported = true,
+ IWL_DEVICE_BZ,
+ .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
+ .num_rbds = IWL_NUM_RBDS_BZ_HE,
+};
+
+
+MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_BZ_A_FM_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_BZ_A_FM_C_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_BZ_A_FM4_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_GL_B_FM_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_GL_C_FM_C_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
new file mode 100644
index 000000000000..ad283fd22e2a
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2015-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018-2023 Intel Corporation
+ */
+#include <linux/module.h>
+#include <linux/stringify.h>
+#include "iwl-config.h"
+#include "iwl-prph.h"
+#include "fw/api/txq.h"
+
+/* Highest firmware API version supported */
+#define IWL_SC_UCODE_API_MAX 83
+
+/* Lowest firmware API version supported */
+#define IWL_SC_UCODE_API_MIN 82
+
+/* NVM versions */
+#define IWL_SC_NVM_VERSION 0x0a1d
+
+/* Memory offsets and lengths */
+#define IWL_SC_DCCM_OFFSET 0x800000 /* LMAC1 */
+#define IWL_SC_DCCM_LEN 0x10000 /* LMAC1 */
+#define IWL_SC_DCCM2_OFFSET 0x880000
+#define IWL_SC_DCCM2_LEN 0x8000
+#define IWL_SC_SMEM_OFFSET 0x400000
+#define IWL_SC_SMEM_LEN 0xD0000
+
+#define IWL_SC_A_FM_B_FW_PRE "iwlwifi-sc-a0-fm-b0"
+#define IWL_SC_A_FM_C_FW_PRE "iwlwifi-sc-a0-fm-c0"
+#define IWL_SC_A_HR_A_FW_PRE "iwlwifi-sc-a0-hr-b0"
+#define IWL_SC_A_HR_B_FW_PRE "iwlwifi-sc-a0-hr-b0"
+#define IWL_SC_A_GF_A_FW_PRE "iwlwifi-sc-a0-gf-a0"
+#define IWL_SC_A_GF4_A_FW_PRE "iwlwifi-sc-a0-gf4-a0"
+#define IWL_SC_A_WH_A_FW_PRE "iwlwifi-sc-a0-wh-a0"
+
+#define IWL_SC_A_FM_B_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_FM_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SC_A_FM_C_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_FM_C_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_HR_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SC_A_GF_A_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_GF_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SC_A_GF4_A_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SC_A_WH_A_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_WH_A_FW_PRE "-" __stringify(api) ".ucode"
+
+static const struct iwl_base_params iwl_sc_base_params = {
+ .eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
+ .num_of_queues = 512,
+ .max_tfd_queue_size = 65536,
+ .shadow_ram_support = true,
+ .led_compensation = 57,
+ .wd_timeout = IWL_LONG_WD_TIMEOUT,
+ .max_event_log_size = 512,
+ .shadow_reg_enable = true,
+ .pcie_l1_allowed = true,
+};
+
+#define IWL_DEVICE_BZ_COMMON \
+ .ucode_api_max = IWL_SC_UCODE_API_MAX, \
+ .ucode_api_min = IWL_SC_UCODE_API_MIN, \
+ .led_mode = IWL_LED_RF_STATE, \
+ .nvm_hw_section_num = 10, \
+ .non_shared_ant = ANT_B, \
+ .dccm_offset = IWL_SC_DCCM_OFFSET, \
+ .dccm_len = IWL_SC_DCCM_LEN, \
+ .dccm2_offset = IWL_SC_DCCM2_OFFSET, \
+ .dccm2_len = IWL_SC_DCCM2_LEN, \
+ .smem_offset = IWL_SC_SMEM_OFFSET, \
+ .smem_len = IWL_SC_SMEM_LEN, \
+ .apmg_not_supported = true, \
+ .trans.mq_rx_supported = true, \
+ .vht_mu_mimo_supported = true, \
+ .mac_addr_from_csr = 0x30, \
+ .nvm_ver = IWL_SC_NVM_VERSION, \
+ .trans.rf_id = true, \
+ .trans.gen2 = true, \
+ .nvm_type = IWL_NVM_EXT, \
+ .dbgc_supported = true, \
+ .min_umac_error_event_table = 0xD0000, \
+ .d3_debug_data_base_addr = 0x401000, \
+ .d3_debug_data_length = 60 * 1024, \
+ .mon_smem_regs = { \
+ .write_ptr = { \
+ .addr = LDBG_M2S_BUF_WPTR, \
+ .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
+ }, \
+ .cycle_cnt = { \
+ .addr = LDBG_M2S_BUF_WRAP_CNT, \
+ .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
+ }, \
+ }, \
+ .trans.umac_prph_offset = 0x300000, \
+ .trans.device_family = IWL_DEVICE_FAMILY_SC, \
+ .trans.base_params = &iwl_sc_base_params, \
+ .min_txq_size = 128, \
+ .gp2_reg_addr = 0xd02c68, \
+ .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT, \
+ .mon_dram_regs = { \
+ .write_ptr = { \
+ .addr = DBGC_CUR_DBGBUF_STATUS, \
+ .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
+ }, \
+ .cycle_cnt = { \
+ .addr = DBGC_DBGBUF_WRAP_AROUND, \
+ .mask = 0xffffffff, \
+ }, \
+ .cur_frag = { \
+ .addr = DBGC_CUR_DBGBUF_STATUS, \
+ .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
+ }, \
+ }, \
+ .mon_dbgi_regs = { \
+ .write_ptr = { \
+ .addr = DBGI_SRAM_FIFO_POINTERS, \
+ .mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK, \
+ }, \
+ }
+
+#define IWL_DEVICE_SC \
+ IWL_DEVICE_BZ_COMMON, \
+ .ht_params = &iwl_22000_ht_params
+
+/*
+ * If the device doesn't support HE, no need to have that many buffers.
+ * These sizes were picked according to 8 MSDUs inside 256 A-MSDUs in an
+ * A-MPDU, with additional overhead to account for processing time.
+ */
+#define IWL_NUM_RBDS_NON_HE 512
+#define IWL_NUM_RBDS_SC_HE 4096
+
+const struct iwl_cfg_trans_params iwl_sc_trans_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_SC,
+ .base_params = &iwl_sc_base_params,
+ .mq_rx_supported = true,
+ .rf_id = true,
+ .gen2 = true,
+ .integrated = true,
+ .umac_prph_offset = 0x300000,
+ .xtal_latency = 12000,
+ .low_latency_xtal = true,
+ .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
+};
+
+const char iwl_sc_name[] = "Intel(R) TBD Sc device";
+
+const struct iwl_cfg iwl_cfg_sc = {
+ .fw_name_mac = "sc",
+ .uhb_supported = true,
+ IWL_DEVICE_SC,
+ .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
+ .num_rbds = IWL_NUM_RBDS_SC_HE,
+};
+
+MODULE_FIRMWARE(IWL_SC_A_FM_B_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SC_A_FM_C_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SC_A_GF_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SC_A_GF4_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SC_A_WH_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c
index 687c906a9d72..f4a6f76cf193 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
- * Copyright (C) 2019 - 2020, 2022 Intel Corporation
+ * Copyright (C) 2019 - 2020, 2022 - 2023 Intel Corporation
*****************************************************************************/
#include <linux/kernel.h>
#include <linux/skbuff.h>
@@ -125,7 +125,7 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
return idx;
}
- return -1;
+ return IWL_RATE_INVALID;
}
static void rs_rate_scale_perform(struct iwl_priv *priv,
@@ -203,23 +203,6 @@ static const u16 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = {
{0, 0, 0, 0, 277, 0, 478, 624, 737, 911, 1026, 1070, 1109}, /* AGG+SGI */
};
-/* mbps, mcs */
-static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
- { "1", "BPSK DSSS"},
- { "2", "QPSK DSSS"},
- {"5.5", "BPSK CCK"},
- { "11", "QPSK CCK"},
- { "6", "BPSK 1/2"},
- { "9", "BPSK 1/2"},
- { "12", "QPSK 1/2"},
- { "18", "QPSK 3/4"},
- { "24", "16QAM 1/2"},
- { "36", "16QAM 3/4"},
- { "48", "64QAM 2/3"},
- { "54", "64QAM 3/4"},
- { "60", "64QAM 5/6"},
-};
-
#define MCS_INDEX_PER_STREAM (8)
static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
@@ -3089,6 +3072,23 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
int index = 0;
ssize_t ret;
+ /* mbps, mcs */
+ static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
+ { "1", "BPSK DSSS"},
+ { "2", "QPSK DSSS"},
+ {"5.5", "BPSK CCK"},
+ { "11", "QPSK CCK"},
+ { "6", "BPSK 1/2"},
+ { "9", "BPSK 1/2"},
+ { "12", "QPSK 1/2"},
+ { "18", "QPSK 3/4"},
+ { "24", "16QAM 1/2"},
+ { "36", "16QAM 3/4"},
+ { "48", "64QAM 2/3"},
+ { "54", "64QAM 3/4"},
+ { "60", "64QAM 5/6"},
+ };
+
struct iwl_lq_sta *lq_sta = file->private_data;
struct iwl_priv *priv;
struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
@@ -3146,7 +3146,10 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
index = iwl_hwrate_to_plcp_idx(
le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags));
- if (is_legacy(tbl->lq_type)) {
+ if (index == IWL_RATE_INVALID) {
+ desc += sprintf(buff + desc, " rate[%d] 0x%X invalid rate\n",
+ i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags));
+ } else if (is_legacy(tbl->lq_type)) {
desc += sprintf(buff+desc, " rate[%d] 0x%X %smbps\n",
i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags),
iwl_rate_mcs[index].mbps);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
index cb9181f05501..dfe8357036eb 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2019-2022 Intel Corporation
+ * Copyright (C) 2019-2023 Intel Corporation
*/
#include <linux/uuid.h>
#include <linux/dmi.h>
@@ -41,6 +41,34 @@ static const struct dmi_system_id dmi_ppag_approved_list[] = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
},
},
+ { .ident = "GOOGLE-HP",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Google"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
+ },
+ },
+ { .ident = "GOOGLE-ASUS",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Google"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek COMPUTER INC."),
+ },
+ },
+ { .ident = "GOOGLE-SAMSUNG",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Google"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
+ },
+ },
+ { .ident = "DELL",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ },
+ },
+ { .ident = "DELL",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ },
+ },
{}
};
@@ -66,7 +94,7 @@ static int iwl_acpi_get_handle(struct device *dev, acpi_string method,
return 0;
}
-void *iwl_acpi_get_object(struct device *dev, acpi_string method)
+static void *iwl_acpi_get_object(struct device *dev, acpi_string method)
{
struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_handle handle;
@@ -87,7 +115,6 @@ void *iwl_acpi_get_object(struct device *dev, acpi_string method)
}
return buf.pointer;
}
-IWL_EXPORT_SYMBOL(iwl_acpi_get_object);
/*
* Generic function for evaluating a method defined in the device specific
@@ -209,11 +236,12 @@ int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,
}
IWL_EXPORT_SYMBOL(iwl_acpi_get_dsm_u32);
-union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev,
- union acpi_object *data,
- int min_data_size,
- int max_data_size,
- int *tbl_rev)
+static union acpi_object *
+iwl_acpi_get_wifi_pkg_range(struct device *dev,
+ union acpi_object *data,
+ int min_data_size,
+ int max_data_size,
+ int *tbl_rev)
{
int i;
union acpi_object *wifi_pkg;
@@ -264,7 +292,16 @@ union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev,
found:
return wifi_pkg;
}
-IWL_EXPORT_SYMBOL(iwl_acpi_get_wifi_pkg_range);
+
+static union acpi_object *
+iwl_acpi_get_wifi_pkg(struct device *dev,
+ union acpi_object *data,
+ int data_size, int *tbl_rev)
+{
+ return iwl_acpi_get_wifi_pkg_range(dev, data, data_size, data_size,
+ tbl_rev);
+}
+
int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
union iwl_tas_config_cmd *cmd, int fw_ver)
@@ -1141,33 +1178,48 @@ int iwl_read_ppag_table(struct iwl_fw_runtime *fwrt, union iwl_ppag_table_cmd *c
*/
cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags);
+ IWL_DEBUG_RADIO(fwrt, "PPAG cmd ver is %d\n", cmd_ver);
if (cmd_ver == 1) {
num_sub_bands = IWL_NUM_SUB_BANDS_V1;
gain = cmd->v1.gain[0];
*cmd_size = sizeof(cmd->v1);
if (fwrt->ppag_ver == 1 || fwrt->ppag_ver == 2) {
+ /* in this case FW supports revision 0 */
IWL_DEBUG_RADIO(fwrt,
- "PPAG table rev is %d but FW supports v1, sending truncated table\n",
+ "PPAG table rev is %d, send truncated table\n",
fwrt->ppag_ver);
- cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
}
} else if (cmd_ver >= 2 && cmd_ver <= 4) {
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
gain = cmd->v2.gain[0];
*cmd_size = sizeof(cmd->v2);
if (fwrt->ppag_ver == 0) {
+ /* in this case FW supports revisions 1 or 2 */
IWL_DEBUG_RADIO(fwrt,
- "PPAG table is v1 but FW supports v2, sending padded table\n");
- } else if (cmd_ver == 2 && fwrt->ppag_ver == 2) {
- IWL_DEBUG_RADIO(fwrt,
- "PPAG table is v3 but FW supports v2, sending partial bitmap.\n");
- cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
+ "PPAG table rev is 0, send padded table\n");
}
} else {
IWL_DEBUG_RADIO(fwrt, "Unsupported PPAG command version\n");
return -EINVAL;
}
+ /* ppag mode */
+ IWL_DEBUG_RADIO(fwrt,
+ "PPAG MODE bits were read from bios: %d\n",
+ cmd->v1.flags & cpu_to_le32(ACPI_PPAG_MASK));
+ if ((cmd_ver == 1 && !fw_has_capa(&fwrt->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) ||
+ (cmd_ver == 2 && fwrt->ppag_ver == 2)) {
+ cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
+ IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n");
+ } else {
+ IWL_DEBUG_RADIO(fwrt, "isn't masking ppag China bit\n");
+ }
+
+ IWL_DEBUG_RADIO(fwrt,
+ "PPAG MODE bits going to be sent: %d\n",
+ cmd->v1.flags & cpu_to_le32(ACPI_PPAG_MASK));
+
for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
for (j = 0; j < num_sub_bands; j++) {
gain[i * num_sub_bands + j] =
@@ -1196,3 +1248,40 @@ bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt)
return true;
}
IWL_EXPORT_SYMBOL(iwl_acpi_is_ppag_approved);
+
+void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
+ struct iwl_phy_specific_cfg *filters)
+{
+ struct iwl_phy_specific_cfg tmp = {};
+ union acpi_object *wifi_pkg, *data;
+ int tbl_rev, i;
+
+ data = iwl_acpi_get_object(fwrt->dev, ACPI_WPFC_METHOD);
+ if (IS_ERR(data))
+ return;
+
+ /* try to read wtas table revision 1 or revision 0*/
+ wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
+ ACPI_WPFC_WIFI_DATA_SIZE,
+ &tbl_rev);
+ if (IS_ERR(wifi_pkg))
+ goto out_free;
+
+ if (tbl_rev != 0)
+ goto out_free;
+
+ BUILD_BUG_ON(ARRAY_SIZE(filters->filter_cfg_chains) != ACPI_WPFC_WIFI_DATA_SIZE);
+
+ for (i = 0; i < ARRAY_SIZE(filters->filter_cfg_chains); i++) {
+ if (wifi_pkg->package.elements[i].type != ACPI_TYPE_INTEGER)
+ return;
+ tmp.filter_cfg_chains[i] =
+ cpu_to_le32(wifi_pkg->package.elements[i].integer.value);
+ }
+
+ IWL_DEBUG_RADIO(fwrt, "Loaded WPFC filter config from ACPI\n");
+ *filters = tmp;
+out_free:
+ kfree(data);
+}
+IWL_EXPORT_SYMBOL(iwl_acpi_get_phy_filters);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
index 6f361c59106f..c36c62d6414d 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#ifndef __iwl_fw_acpi__
#define __iwl_fw_acpi__
@@ -11,6 +11,7 @@
#include "fw/api/power.h"
#include "fw/api/phy.h"
#include "fw/api/nvm-reg.h"
+#include "fw/api/config.h"
#include "fw/img.h"
#include "iwl-trans.h"
@@ -23,6 +24,7 @@
#define ACPI_ECKV_METHOD "ECKV"
#define ACPI_PPAG_METHOD "PPAG"
#define ACPI_WTAS_METHOD "WTAS"
+#define ACPI_WPFC_METHOD "WPFC"
#define ACPI_WIFI_DOMAIN (0x07)
@@ -54,6 +56,7 @@
#define ACPI_EWRD_WIFI_DATA_SIZE_REV2 ((ACPI_SAR_PROFILE_NUM - 1) * \
ACPI_SAR_NUM_CHAINS_REV2 * \
ACPI_SAR_NUM_SUB_BANDS_REV2 + 3)
+#define ACPI_WPFC_WIFI_DATA_SIZE 4 /* 4 filter config words */
/* revision 0 and 1 are identical, except for the semantics in the FW */
#define ACPI_GEO_NUM_BANDS_REV0 2
@@ -168,19 +171,12 @@ struct iwl_fw_runtime;
extern const guid_t iwl_guid;
extern const guid_t iwl_rfi_guid;
-void *iwl_acpi_get_object(struct device *dev, acpi_string method);
-
int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func,
const guid_t *guid, u8 *value);
int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,
const guid_t *guid, u32 *value);
-union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev,
- union acpi_object *data,
- int min_data_size,
- int max_data_size,
- int *tbl_rev);
/**
* iwl_acpi_get_mcc - read MCC from ACPI, if available
*
@@ -232,12 +228,10 @@ int iwl_read_ppag_table(struct iwl_fw_runtime *fwrt, union iwl_ppag_table_cmd *c
bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt);
-#else /* CONFIG_ACPI */
+void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
+ struct iwl_phy_specific_cfg *filters);
-static inline void *iwl_acpi_get_object(struct device *dev, acpi_string method)
-{
- return ERR_PTR(-ENOENT);
-}
+#else /* CONFIG_ACPI */
static inline void *iwl_acpi_get_dsm_object(struct device *dev, int rev,
int func, union acpi_object *args)
@@ -257,15 +251,6 @@ static inline int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,
return -ENOENT;
}
-static inline union acpi_object *
-iwl_acpi_get_wifi_pkg_range(struct device *dev,
- union acpi_object *data,
- int min_data_size, int max_data_size,
- int *tbl_rev)
-{
- return ERR_PTR(-ENOENT);
-}
-
static inline int iwl_acpi_get_mcc(struct device *dev, char *mcc)
{
return -ENOENT;
@@ -335,15 +320,11 @@ static inline bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt)
return false;
}
-#endif /* CONFIG_ACPI */
-
-static inline union acpi_object *
-iwl_acpi_get_wifi_pkg(struct device *dev,
- union acpi_object *data,
- int data_size, int *tbl_rev)
+static inline void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
+ struct iwl_phy_specific_cfg *filters)
{
- return iwl_acpi_get_wifi_pkg_range(dev, data, data_size, data_size,
- tbl_rev);
}
+#endif /* CONFIG_ACPI */
+
#endif /* __iwl_fw_acpi__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h b/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h
index 29e2816e7052..d9044ada6a43 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2020 Intel Corporation
+ * Copyright (C) 2012-2014, 2020, 2022 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -18,7 +18,7 @@
* ( BINDING_CONTEXT_CMD = 0x2b )
* @id_and_color: ID and color of the relevant Binding,
* &enum iwl_ctxt_id_and_color
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @macs: array of MAC id and colors which belong to the binding,
* &enum iwl_ctxt_id_and_color
* @phy: PHY id and color which belongs to the binding,
@@ -38,7 +38,7 @@ struct iwl_binding_cmd_v1 {
* ( BINDING_CONTEXT_CMD = 0x2b )
* @id_and_color: ID and color of the relevant Binding,
* &enum iwl_ctxt_id_and_color
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @macs: array of MAC id and colors which belong to the binding
* &enum iwl_ctxt_id_and_color
* @phy: PHY id and color which belongs to the binding
@@ -59,14 +59,6 @@ struct iwl_binding_cmd {
#define IWL_LMAC_24G_INDEX 0
#define IWL_LMAC_5G_INDEX 1
-static inline u32 iwl_mvm_get_lmac_id(const struct iwl_fw *fw,
- enum nl80211_band band){
- if (!fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_CDB_SUPPORT) ||
- band == NL80211_BAND_2GHZ)
- return IWL_LMAC_24G_INDEX;
- return IWL_LMAC_5G_INDEX;
-}
-
/* The maximal number of fragments in the FW's schedule session */
#define IWL_MVM_MAX_QUOTA 128
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h
index 111d96cbde6f..13cb0d53a1a3 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h
@@ -139,11 +139,6 @@ enum iwl_legacy_cmds {
REMOVE_STA = 0x19,
/**
- * @FW_GET_ITEM_CMD: uses &struct iwl_fw_get_item_cmd
- */
- FW_GET_ITEM_CMD = 0x1a,
-
- /**
* @TX_CMD: uses &struct iwl_tx_cmd or &struct iwl_tx_cmd_gen2 or
* &struct iwl_tx_cmd_gen3,
* response in &struct iwl_mvm_tx_resp or
@@ -534,12 +529,6 @@ enum iwl_legacy_cmds {
PROT_OFFLOAD_CONFIG_CMD = 0xd4,
/**
- * @OFFLOADS_QUERY_CMD:
- * No data in command, response in &struct iwl_wowlan_status
- */
- OFFLOADS_QUERY_CMD = 0xd5,
-
- /**
* @D0I3_END_CMD: End D0i3/D3 state, no command data
*/
D0I3_END_CMD = 0xed,
@@ -566,18 +555,22 @@ enum iwl_legacy_cmds {
WOWLAN_TKIP_PARAM = 0xe3,
/**
- * @WOWLAN_KEK_KCK_MATERIAL: &struct iwl_wowlan_kek_kck_material_cmd
+ * @WOWLAN_KEK_KCK_MATERIAL: &struct iwl_wowlan_kek_kck_material_cmd_v2,
+ * &struct iwl_wowlan_kek_kck_material_cmd_v3 or
+ * &struct iwl_wowlan_kek_kck_material_cmd_v4
*/
WOWLAN_KEK_KCK_MATERIAL = 0xe4,
/**
- * @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status
+ * @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status_v6,
+ * &struct iwl_wowlan_status_v7, &struct iwl_wowlan_status_v9 or
+ * &struct iwl_wowlan_status_v12
*/
WOWLAN_GET_STATUSES = 0xe5,
/**
- * @SCAN_OFFLOAD_PROFILES_QUERY_CMD:
- * No command data, response is &struct iwl_scan_offload_profiles_query
+ * @SCAN_OFFLOAD_PROFILES_QUERY_CMD: No command data, response is
+ * &struct iwl_scan_offload_profiles_query_v1
*/
SCAN_OFFLOAD_PROFILES_QUERY_CMD = 0x56,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/config.h b/drivers/net/wireless/intel/iwlwifi/fw/api/config.h
index 087354b3c308..4419631604b4 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/config.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/config.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2019 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2019, 2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -67,17 +67,12 @@ enum iwl_calib_cfg {
* Sent as part of the phy configuration command (v3) to configure specific FW
* defined PHY filters that can be applied to each antenna.
*
- * @filter_cfg_chain_a: filter config id for LMAC1 chain A
- * @filter_cfg_chain_b: filter config id for LMAC1 chain B
- * @filter_cfg_chain_c: filter config id for LMAC2 chain A
- * @filter_cfg_chain_d: filter config id for LMAC2 chain B
- * values: 0 - no filter; 0xffffffff - reserved; otherwise - filter id
+ * @filter_cfg_chains: filter config id for LMAC1 chain A, LMAC1 chain B,
+ * LMAC2 chain A, LMAC2 chain B (in that order)
+ * values: 0: no filter; 0xffffffff: reserved; otherwise: filter id
*/
struct iwl_phy_specific_cfg {
- __le32 filter_cfg_chain_a;
- __le32 filter_cfg_chain_b;
- __le32 filter_cfg_chain_c;
- __le32 filter_cfg_chain_d;
+ __le32 filter_cfg_chains[4];
} __packed; /* PHY_SPECIFIC_CONFIGURATION_API_VER_1*/
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/context.h b/drivers/net/wireless/intel/iwlwifi/fw/api/context.h
index 105ba7170c3f..1fa5678c1cd6 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/context.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/context.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014 Intel Corporation
+ * Copyright (C) 2012-2014, 2022 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -26,13 +26,18 @@ enum iwl_ctxt_id_and_color {
#define FW_CMD_ID_AND_COLOR(_id, _color) (((_id) << FW_CTXT_ID_POS) |\
((_color) << FW_CTXT_COLOR_POS))
-/* Possible actions on PHYs, MACs and Bindings */
+/**
+ * enum iwl_ctxt_action - Posssible actions on PHYs, MACs, Bindings and other
+ * @FW_CTXT_ACTION_INVALID: unused, invalid action
+ * @FW_CTXT_ACTION_ADD: add the context
+ * @FW_CTXT_ACTION_MODIFY: modify the context
+ * @FW_CTXT_ACTION_REMOVE: remove the context
+ */
enum iwl_ctxt_action {
- FW_CTXT_ACTION_STUB = 0,
+ FW_CTXT_ACTION_INVALID = 0,
FW_CTXT_ACTION_ADD,
FW_CTXT_ACTION_MODIFY,
FW_CTXT_ACTION_REMOVE,
- FW_CTXT_ACTION_NUM
}; /* COMMON_CONTEXT_ACTION_API_E_VER_1 */
#endif /* __iwl_fw_api_context_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
index 8a613e150a02..72d461c47323 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -47,12 +47,14 @@ struct iwl_d3_manager_config {
* @IWL_D3_PROTO_OFFLOAD_NS: NS (Neighbor Solicitation) is enabled
* @IWL_D3_PROTO_IPV4_VALID: IPv4 data is valid
* @IWL_D3_PROTO_IPV6_VALID: IPv6 data is valid
+ * @IWL_D3_PROTO_OFFLOAD_BTM: BTM offload is enabled
*/
enum iwl_proto_offloads {
IWL_D3_PROTO_OFFLOAD_ARP = BIT(0),
IWL_D3_PROTO_OFFLOAD_NS = BIT(1),
IWL_D3_PROTO_IPV4_VALID = BIT(2),
IWL_D3_PROTO_IPV6_VALID = BIT(3),
+ IWL_D3_PROTO_OFFLOAD_BTM = BIT(4),
};
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1 2
@@ -394,6 +396,7 @@ struct iwl_wowlan_config_cmd {
#define WOWLAN_KEY_MAX_SIZE 32
#define WOWLAN_GTK_KEYS_NUM 2
#define WOWLAN_IGTK_KEYS_NUM 2
+#define WOWLAN_IGTK_MIN_INDEX 4
/*
* WOWLAN_TSC_RSC_PARAMS
@@ -610,6 +613,7 @@ struct iwl_wowlan_gtk_status_v3 {
} __packed; /* WOWLAN_GTK_MATERIAL_VER_3 */
#define IWL_WOWLAN_GTK_IDX_MASK (BIT(0) | BIT(1))
+#define IWL_WOWLAN_IGTK_BIGTK_IDX_MASK (BIT(0))
/**
* struct iwl_wowlan_igtk_status - IGTK status
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
index 6f59381b9f9a..751b596ea1a5 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
@@ -38,7 +38,9 @@ enum iwl_data_path_subcmd_ids {
WNM_80211V_TIMING_MEASUREMENT_CONFIG_CMD = 0x4,
/**
- * @STA_HE_CTXT_CMD: &struct iwl_he_sta_context_cmd
+ * @STA_HE_CTXT_CMD: &struct iwl_he_sta_context_cmd_v1,
+ * &struct iwl_he_sta_context_cmd_v2 or
+ * &struct iwl_he_sta_context_cmd_v3
*/
STA_HE_CTXT_CMD = 0x7,
@@ -447,7 +449,7 @@ struct iwl_sad_properties {
* @phy_id: PHY index
* @rlc: RLC properties, &struct iwl_rlc_properties
* @sad: SAD (single antenna diversity) options, &struct iwl_sad_properties
- * @flags: flags, &enum iwl_rlc_flags
+ * @flags: flags (unused)
* @reserved: reserved
*/
struct iwl_rlc_config_cmd {
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
index 12af94e166ed..b044990c7b87 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2021 Intel Corporation
+ * Copyright (C) 2018-2022 Intel Corporation
*/
#ifndef __iwl_fw_api_location_h__
#define __iwl_fw_api_location_h__
@@ -35,8 +35,11 @@ enum iwl_location_subcmd_ids {
*/
TOF_RANGE_REQ_EXT_CMD = 0x3,
/**
- * @TOF_RESPONDER_CONFIG_CMD: FTM responder configuration,
- * uses &struct iwl_tof_responder_config_cmd
+ * @TOF_RESPONDER_CONFIG_CMD: FTM responder configuration, one of
+ * &struct iwl_tof_responder_config_cmd_v6,
+ * &struct iwl_tof_responder_config_cmd_v7,
+ * &struct iwl_tof_responder_config_cmd_v8 or
+ * &struct iwl_tof_responder_config_cmd_v9
*/
TOF_RESPONDER_CONFIG_CMD = 0x4,
/**
@@ -69,8 +72,11 @@ enum iwl_location_subcmd_ids {
*/
TOF_MCSI_DEBUG_NOTIF = 0xFE,
/**
- * @TOF_RANGE_RESPONSE_NOTIF: ranging response, using
- * &struct iwl_tof_range_rsp_ntfy
+ * @TOF_RANGE_RESPONSE_NOTIF: ranging response, using one of
+ * &struct iwl_tof_range_rsp_ntfy_v5,
+ * &struct iwl_tof_range_rsp_ntfy_v6,
+ * &struct iwl_tof_range_rsp_ntfy_v7 or
+ * &struct iwl_tof_range_rsp_ntfy_v8
*/
TOF_RANGE_RESPONSE_NOTIF = 0xFF,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
index 74f2efbad34e..184db5a6f06f 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
@@ -140,40 +140,60 @@ struct iwl_missed_vap_notif {
*
* @id_and_color: ID and color of the MAC
*/
-struct iwl_channel_switch_start_notif {
+struct iwl_channel_switch_start_notif_v1 {
__le32 id_and_color;
} __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */
+/**
+ * struct iwl_channel_switch_start_notif - Channel switch start notification
+ *
+ * @link_id: FW link id
+ */
+struct iwl_channel_switch_start_notif {
+ __le32 link_id;
+} __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_3 */
+
#define CS_ERR_COUNT_ERROR BIT(0)
#define CS_ERR_LONG_DELAY_AFTER_CS BIT(1)
#define CS_ERR_LONG_TX_BLOCK BIT(2)
#define CS_ERR_TX_BLOCK_TIMER_EXPIRED BIT(3)
/**
- * struct iwl_channel_switch_error_notif - Channel switch error notification
+ * struct iwl_channel_switch_error_notif_v1 - Channel switch error notification
*
* @mac_id: the mac for which the ucode sends the notification for
* @csa_err_mask: mask of channel switch error that can occur
*/
-struct iwl_channel_switch_error_notif {
+struct iwl_channel_switch_error_notif_v1 {
__le32 mac_id;
__le32 csa_err_mask;
} __packed; /* CHANNEL_SWITCH_ERROR_NTFY_API_S_VER_1 */
/**
+ * struct iwl_channel_switch_error_notif - Channel switch error notification
+ *
+ * @link_id: FW link id
+ * @csa_err_mask: mask of channel switch error that can occur
+ */
+struct iwl_channel_switch_error_notif {
+ __le32 link_id;
+ __le32 csa_err_mask;
+} __packed; /* CHANNEL_SWITCH_ERROR_NTFY_API_S_VER_2 */
+
+/**
* struct iwl_cancel_channel_switch_cmd - Cancel Channel Switch command
*
- * @mac_id: the mac that should cancel the channel switch
+ * @id: the id of the link or mac that should cancel the channel switch
*/
struct iwl_cancel_channel_switch_cmd {
- __le32 mac_id;
+ __le32 id;
} __packed; /* MAC_CANCEL_CHANNEL_SWITCH_S_VER_1 */
/**
* struct iwl_chan_switch_te_cmd - Channel Switch Time Event command
*
* @mac_id: MAC ID for channel switch
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @tsf: beacon tsf
* @cs_count: channel switch count from CSA/eCSA IE
* @cs_delayed_bcn_count: if set to N (!= 0) GO/AP can delay N beacon intervals
@@ -211,17 +231,30 @@ struct iwl_mac_low_latency_cmd {
* struct iwl_mac_client_data - configuration data for client MAC context
*
* @is_assoc: 1 for associated state, 0 otherwise
+ * @esr_transition_timeout: the timeout required by the AP for the
+ * eSR transition.
+ * Available only from version 2 of the command.
+ * This values comes from the EMLSR transition delay in the EML
+ * Capabilities subfield.
+ * @medium_sync_delay: the value as it appeasr in P802.11be_D2.2 Figure 9-1002j.
* @assoc_id: unique ID assigned by the AP during association
+ * @reserved1: alignment
* @data_policy: see &enum iwl_mac_data_policy
+ * @reserved2: alignment
* @ctwin: client traffic window in TU (period after TBTT when GO is present).
* 0 indicates that there is no CT window.
*/
struct iwl_mac_client_data {
- __le32 is_assoc;
- __le32 assoc_id;
- __le32 data_policy;
+ u8 is_assoc;
+ u8 esr_transition_timeout;
+ __le16 medium_sync_delay;
+
+ __le16 assoc_id;
+ __le16 reserved1;
+ __le16 data_policy;
+ __le16 reserved2;
__le32 ctwin;
-} __packed; /* MAC_CONTEXT_CONFIG_CLIENT_DATA_API_S_VER_1 */
+} __packed; /* MAC_CONTEXT_CONFIG_CLIENT_DATA_API_S_VER_2 */
/**
* struct iwl_mac_p2p_dev_data - configuration data for P2P device MAC context
@@ -263,7 +296,7 @@ enum iwl_mac_config_filter_flags {
* ( MAC_CONTEXT_CONFIG_CMD = 0x8 )
*
* @id_and_color: ID and color of the MAC
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @mac_type: one of &enum iwl_mac_types
* @local_mld_addr: mld address
* @reserved_for_local_mld_addr: reserved
@@ -292,12 +325,12 @@ struct iwl_mac_config_cmd {
__le16 he_ap_support;
__le32 eht_support;
__le32 nic_not_ack_enabled;
- /* MAC_CONTEXT_CONFIG_SPECIFIC_DATA_API_U_VER_1 */
+ /* MAC_CONTEXT_CONFIG_SPECIFIC_DATA_API_U_VER_2 */
union {
struct iwl_mac_client_data client;
struct iwl_mac_p2p_dev_data p2p_dev;
};
-} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_1 */
+} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_2 */
/**
* enum iwl_link_ctx_modify_flags - indicate to the fw what fields are being
@@ -390,7 +423,7 @@ enum iwl_link_ctx_flags {
* in MLD API
* ( LINK_CONFIG_CMD =0x9 )
*
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @link_id: the id of the link that this cmd configures
* @mac_id: interface ID. Relevant only if action is FW_CTXT_ACTION_ADD
* @phy_id: PHY index. Can be changed only if the link was inactive
@@ -430,6 +463,7 @@ enum iwl_link_ctx_flags {
* @reserved_for_ref_bssid_addr: reserved
* @bssid_index: index of the associated VAP
* @bss_color: 11ax AP ID that is used in the HE SIG-A to mark inter BSS frame
+ * @spec_link_id: link_id as the AP knows it
* @reserved: alignment
* @ibss_bssid_addr: bssid for ibss
* @reserved_for_ibss_bssid_addr: reserved
@@ -469,7 +503,8 @@ struct iwl_link_config_cmd {
__le16 reserved_for_ref_bssid_addr;
u8 bssid_index;
u8 bss_color;
- u8 reserved[2];
+ u8 spec_link_id;
+ u8 reserved;
u8 ibss_bssid_addr[6];
__le16 reserved_for_ibss_bssid_addr;
__le32 reserved1[8];
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
index e3eda251c728..55882190251c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
@@ -295,7 +295,7 @@ struct iwl_ac_qos {
* struct iwl_mac_ctx_cmd - command structure to configure MAC contexts
* ( MAC_CONTEXT_CMD = 0x28 )
* @id_and_color: ID and color of the MAC
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @mac_type: one of &enum iwl_mac_types
* @tsf_id: TSF HW timer, one of &enum iwl_tsf_id
* @node_addr: MAC address
@@ -353,7 +353,7 @@ struct iwl_nonqos_seq_query_cmd {
} __packed; /* NON_QOS_TX_COUNTER_GET_SET_API_S_VER_1 */
/**
- * struct iwl_missed_beacons_notif - information on missed beacons
+ * struct iwl_missed_beacons_notif_ver_3 - information on missed beacons
* ( MISSED_BEACONS_NOTIFICATION = 0xa2 )
* @mac_id: interface ID
* @consec_missed_beacons_since_last_rx: number of consecutive missed
@@ -362,7 +362,7 @@ struct iwl_nonqos_seq_query_cmd {
* @num_expected_beacons: number of expected beacons
* @num_recvd_beacons: number of received beacons
*/
-struct iwl_missed_beacons_notif {
+struct iwl_missed_beacons_notif_ver_3 {
__le32 mac_id;
__le32 consec_missed_beacons_since_last_rx;
__le32 consec_missed_beacons;
@@ -371,6 +371,24 @@ struct iwl_missed_beacons_notif {
} __packed; /* MISSED_BEACON_NTFY_API_S_VER_3 */
/**
+ * struct iwl_missed_beacons_notif - information on missed beacons
+ * ( MISSED_BEACONS_NOTIFICATION = 0xa2 )
+ * @link_id: fw link ID
+ * @consec_missed_beacons_since_last_rx: number of consecutive missed
+ * beacons since last RX.
+ * @consec_missed_beacons: number of consecutive missed beacons
+ * @num_expected_beacons: number of expected beacons
+ * @num_recvd_beacons: number of received beacons
+ */
+struct iwl_missed_beacons_notif {
+ __le32 link_id;
+ __le32 consec_missed_beacons_since_last_rx;
+ __le32 consec_missed_beacons;
+ __le32 num_expected_beacons;
+ __le32 num_recvd_beacons;
+} __packed; /* MISSED_BEACON_NTFY_API_S_VER_4 */
+
+/**
* struct iwl_he_backoff_conf - used for backoff configuration
* Per each trigger-based AC, (set by MU EDCA Parameter set info-element)
* used for backoff configuration of TXF5..TXF8 trigger based.
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
index 91bfde6d5367..28bfabb399b2 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
@@ -17,7 +17,12 @@ enum iwl_regulatory_and_nvm_subcmd_ids {
NVM_ACCESS_COMPLETE = 0x0,
/**
- * @LARI_CONFIG_CHANGE: &struct iwl_lari_config_change_cmd
+ * @LARI_CONFIG_CHANGE: &struct iwl_lari_config_change_cmd_v1,
+ * &struct iwl_lari_config_change_cmd_v2,
+ * &struct iwl_lari_config_change_cmd_v3,
+ * &struct iwl_lari_config_change_cmd_v4,
+ * &struct iwl_lari_config_change_cmd_v5 or
+ * &struct iwl_lari_config_change_cmd_v6
*/
LARI_CONFIG_CHANGE = 0x1,
@@ -29,12 +34,12 @@ enum iwl_regulatory_and_nvm_subcmd_ids {
NVM_GET_INFO = 0x2,
/**
- * @TAS_CONFIG: &struct iwl_tas_config_cmd
+ * @TAS_CONFIG: &union iwl_tas_config_cmd
*/
TAS_CONFIG = 0x3,
/**
- * @SAR_OFFSET_MAPPING_TABLE_CMD: &iwl_sar_offset_mapping_cmd
+ * @SAR_OFFSET_MAPPING_TABLE_CMD: &struct iwl_sar_offset_mapping_cmd
*/
SAR_OFFSET_MAPPING_TABLE_CMD = 0x4,
@@ -317,7 +322,7 @@ struct iwl_mcc_update_resp_v3 {
} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_3 */
/**
- * struct iwl_mcc_update_resp - response to MCC_UPDATE_CMD.
+ * struct iwl_mcc_update_resp_v4 - response to MCC_UPDATE_CMD.
* Contains the new channel control profile map, if changed, and the new MCC
* (mobile country code).
* The new MCC may be different than what was requested in MCC_UPDATE_CMD.
@@ -333,7 +338,7 @@ struct iwl_mcc_update_resp_v3 {
* @channels: channel control data map, DWORD for each channel. Only the first
* 16bits are used.
*/
-struct iwl_mcc_update_resp {
+struct iwl_mcc_update_resp_v4 {
__le32 status;
__le16 mcc;
__le16 cap;
@@ -346,6 +351,37 @@ struct iwl_mcc_update_resp {
} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_4 */
/**
+ * struct iwl_mcc_update_resp_v8 - response to MCC_UPDATE_CMD.
+ * Contains the new channel control profile map, if changed, and the new MCC
+ * (mobile country code).
+ * The new MCC may be different than what was requested in MCC_UPDATE_CMD.
+ * @status: see &enum iwl_mcc_update_status
+ * @mcc: the new applied MCC
+ * @padding: padding for 2 bytes.
+ * @cap: capabilities for all channels which matches the MCC
+ * @time: time elapsed from the MCC test start (in units of 30 seconds)
+ * @geo_info: geographic specific profile information
+ * see &enum iwl_geo_information.
+ * @source_id: the MCC source, see iwl_mcc_source
+ * @reserved: for four bytes alignment.
+ * @n_channels: number of channels in @channels_data.
+ * @channels: channel control data map, DWORD for each channel. Only the first
+ * 16bits are used.
+ */
+struct iwl_mcc_update_resp_v8 {
+ __le32 status;
+ __le16 mcc;
+ u8 padding[2];
+ __le32 cap;
+ __le16 time;
+ __le16 geo_info;
+ u8 source_id;
+ u8 reserved[3];
+ __le32 n_channels;
+ __le32 channels[];
+} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_8 */
+
+/**
* struct iwl_mcc_chub_notif - chub notifies of mcc change
* (MCC_CHUB_UPDATE_CMD = 0xc9)
* The Chub (Communication Hub, CommsHUB) is a HW component that connects to
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h
index a0123f81f5d8..898bf351f6e4 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h
@@ -28,7 +28,8 @@ enum iwl_prot_offload_subcmd_ids {
D3_END_NOTIFICATION = 0xFE,
/**
- * @STORED_BEACON_NTF: &struct iwl_stored_beacon_notif
+ * @STORED_BEACON_NTF: &struct iwl_stored_beacon_notif_v2 or
+ * &struct iwl_stored_beacon_notif_v3
*/
STORED_BEACON_NTF = 0xFF,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h b/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h
index 2f7d8558becd..8fe42cff1102 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018, 2020-2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2018, 2020-2022 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -116,7 +116,7 @@ struct iwl_phy_context_cmd_tail {
* struct iwl_phy_context_cmd - config of the PHY context
* ( PHY_CONTEXT_CMD = 0x8 )
* @id_and_color: ID and color of the relevant Binding
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @apply_time: 0 means immediate apply and context switch.
* other value means apply new params after X usecs
* @tx_param_color: ???
@@ -138,7 +138,7 @@ struct iwl_phy_context_cmd_v1 {
* struct iwl_phy_context_cmd - config of the PHY context
* ( PHY_CONTEXT_CMD = 0x8 )
* @id_and_color: ID and color of the relevant Binding
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @lmac_id: the lmac id the phy context belongs to
* @ci: channel info
* @rxchain_info: ???
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h b/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h
index b1b9c29859c1..5a3f30e5e06d 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2019-2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2019-2022 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -29,12 +29,16 @@ enum iwl_phy_ops_subcmd_ids {
TEMP_REPORTING_THRESHOLDS_CMD = 0x04,
/**
- * @PER_CHAIN_LIMIT_OFFSET_CMD: &struct iwl_geo_tx_power_profiles_cmd
+ * @PER_CHAIN_LIMIT_OFFSET_CMD: &struct iwl_geo_tx_power_profiles_cmd_v1,
+ * &struct iwl_geo_tx_power_profiles_cmd_v2,
+ * &struct iwl_geo_tx_power_profiles_cmd_v3,
+ * &struct iwl_geo_tx_power_profiles_cmd_v4 or
+ * &struct iwl_geo_tx_power_profiles_cmd_v5
*/
PER_CHAIN_LIMIT_OFFSET_CMD = 0x05,
/**
- * @PER_PLATFORM_ANT_GAIN_CMD: &struct iwl_ppag_table_cmd
+ * @PER_PLATFORM_ANT_GAIN_CMD: &union iwl_ppag_table_cmd
*/
PER_PLATFORM_ANT_GAIN_CMD = 0x07,
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
index f92cac1da764..85d89f559f6c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
@@ -537,7 +537,7 @@ union iwl_ppag_table_cmd {
struct iwl_sar_offset_mapping_cmd {
u8 offset_map[MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE]
[MCC_TO_SAR_OFFSET_TABLE_COL_SIZE];
- u16 reserved;
+ __le16 reserved;
} __packed; /*SAR_OFFSET_MAPPING_TABLE_CMD_API_S*/
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
index c9a48fc5fac8..a1a272433b09 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
@@ -21,6 +21,7 @@
* @IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_2_MSK: enable HE Dual Carrier Modulation
* for BPSK (MCS 0) with 2 spatial
* streams
+ * @IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK: enable support for EHT extra LTF
*/
enum iwl_tlc_mng_cfg_flags {
IWL_TLC_MNG_CFG_FLAGS_STBC_MSK = BIT(0),
@@ -28,6 +29,7 @@ enum iwl_tlc_mng_cfg_flags {
IWL_TLC_MNG_CFG_FLAGS_HE_STBC_160MHZ_MSK = BIT(2),
IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK = BIT(3),
IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_2_MSK = BIT(4),
+ IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK = BIT(6),
};
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
index fdd8b01f09e4..25e2e23dce3d 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
@@ -292,7 +292,7 @@ enum iwl_rx_phy_he_data0 {
/* TSF overload low dword */
enum iwl_rx_phy_eht_data0 {
/* info type: EHT any */
- /* 1 bits reserved */
+ IWL_RX_PHY_DATA0_EHT_VALIDATE = BIT(0),
IWL_RX_PHY_DATA0_EHT_UPLINK = BIT(1),
IWL_RX_PHY_DATA0_EHT_BSS_COLOR_MASK = 0x000000fc,
IWL_RX_PHY_DATA0_ETH_SPATIAL_REUSE_MASK = 0x00000f00,
@@ -367,8 +367,8 @@ enum iwl_rx_phy_eht_data1 {
/* number of EHT-LTF symbols 0 - 1 EHT-LTF, 1 - 2 EHT-LTFs, 2 - 4 EHT-LTFs,
* 3 - 6 EHT-LTFs, 4 - 8 EHT-LTFs */
IWL_RX_PHY_DATA1_EHT_SIG_LTF_NUM = 0x000000e0,
- IWL_RX_PHY_DATA1_EHT_B0 = 0x00000100,
- IWL_RX_PHY_DATA1_EHT_RU_B1_B7_ALLOC = 0x0000fe00,
+ IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B0 = 0x00000100,
+ IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B1_B7 = 0x0000fe00,
};
/* goes into Metadata DW 7 */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
index ec96ba053a5c..93078f8cc08c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -727,8 +727,10 @@ enum iwl_umac_scan_general_params_flags2 {
* @iter_interval: interval between two scan iterations on one channel.
*/
struct iwl_scan_channel_cfg_umac {
+#define IWL_CHAN_CFG_FLAGS_BAND_POS 30
__le32 flags;
- /* Both versions are of the same size, so use a union without adjusting
+
+ /* All versions are of the same size, so use a union without adjusting
* the command size later
*/
union {
@@ -746,6 +748,12 @@ struct iwl_scan_channel_cfg_umac {
* SCAN_CHANNEL_CONFIG_API_S_VER_3
* SCAN_CHANNEL_CONFIG_API_S_VER_4
*/
+ struct {
+ u8 channel_num;
+ u8 psd_20;
+ u8 iter_count;
+ u8 iter_interval;
+ } v5; /* SCAN_CHANNEL_CONFIG_API_S_VER_5 */
};
} __packed;
@@ -982,7 +990,7 @@ struct iwl_scan_channel_params_v4 {
SCAN_CHANNEL_PARAMS_API_S_VER_5 */
/**
- * struct iwl_scan_channel_params_v6
+ * struct iwl_scan_channel_params_v7
* @flags: channel flags &enum iwl_scan_channel_flags
* @count: num of channels in scan request
* @n_aps_override: override the number of APs the FW uses to calculate dwell
@@ -992,7 +1000,7 @@ struct iwl_scan_channel_params_v4 {
* @channel_config: array of explicit channel configurations
* for 2.4Ghz and 5.2Ghz bands
*/
-struct iwl_scan_channel_params_v6 {
+struct iwl_scan_channel_params_v7 {
u8 flags;
u8 count;
u8 n_aps_override[2];
@@ -1003,7 +1011,8 @@ struct iwl_scan_channel_params_v6 {
* struct iwl_scan_general_params_v11
* @flags: &enum iwl_umac_scan_general_flags_v2
* @reserved: reserved for future
- * @scan_start_mac_id: report the scan start TSF time according to this mac TSF
+ * @scan_start_mac_or_link_id: report the scan start TSF time according to this
+ * mac (up to verion 11) or link (starting with version 12) TSF
* @active_dwell: dwell time for active scan per LMAC
* @adwell_default_2g: adaptive dwell default number of APs
* for 2.4GHz channel
@@ -1026,7 +1035,7 @@ struct iwl_scan_channel_params_v6 {
struct iwl_scan_general_params_v11 {
__le16 flags;
u8 reserved;
- u8 scan_start_mac_id;
+ u8 scan_start_mac_or_link_id;
u8 active_dwell[SCAN_TWO_LMACS];
u8 adwell_default_2g;
u8 adwell_default_5g;
@@ -1038,7 +1047,7 @@ struct iwl_scan_general_params_v11 {
__le32 scan_priority;
u8 passive_dwell[SCAN_TWO_LMACS];
u8 num_of_fragments[SCAN_TWO_LMACS];
-} __packed; /* SCAN_GENERAL_PARAMS_API_S_VER_11 and *_VER_10 */
+} __packed; /* SCAN_GENERAL_PARAMS_API_S_VER_12, *_VER_11 and *_VER_10 */
/**
* struct iwl_scan_periodic_parms_v1
@@ -1067,18 +1076,18 @@ struct iwl_scan_req_params_v12 {
} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_12 */
/**
- * struct iwl_scan_req_params_v15
+ * struct iwl_scan_req_params_v16
* @general_params: &struct iwl_scan_general_params_v11
- * @channel_params: &struct iwl_scan_channel_params_v6
+ * @channel_params: &struct iwl_scan_channel_params_v7
* @periodic_params: &struct iwl_scan_periodic_parms_v1
* @probe_params: &struct iwl_scan_probe_params_v4
*/
-struct iwl_scan_req_params_v15 {
+struct iwl_scan_req_params_v17 {
struct iwl_scan_general_params_v11 general_params;
- struct iwl_scan_channel_params_v6 channel_params;
+ struct iwl_scan_channel_params_v7 channel_params;
struct iwl_scan_periodic_parms_v1 periodic_params;
struct iwl_scan_probe_params_v4 probe_params;
-} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_15 and *_VER_14 */
+} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_17 - 14 */
/**
* struct iwl_scan_req_umac_v12
@@ -1093,16 +1102,16 @@ struct iwl_scan_req_umac_v12 {
} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_12 */
/**
- * struct iwl_scan_req_umac_v15
+ * struct iwl_scan_req_umac_v16
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
* @ooc_priority: out of channel priority - &enum iwl_scan_priority
* @scan_params: scan parameters
*/
-struct iwl_scan_req_umac_v15 {
+struct iwl_scan_req_umac_v17 {
__le32 uid;
__le32 ooc_priority;
- struct iwl_scan_req_params_v15 scan_params;
-} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_15 and *_VER_14 */
+ struct iwl_scan_req_params_v17 scan_params;
+} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_17 - 14 */
/**
* struct iwl_umac_scan_abort
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h
index 904cd78a9fa0..7cc706731d70 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2020 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2020, 2022 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -292,7 +292,7 @@ struct iwl_hs20_roc_req_tail {
* ( HOT_SPOT_CMD 0x53 )
*
* @id_and_color: ID and color of the MAC
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @event_unique_id: If the action FW_CTXT_ACTION_REMOVE then the
* event_unique_id should be the id of the time event assigned by ucode.
* Otherwise ignore the event_unique_id.
@@ -377,7 +377,8 @@ enum iwl_mvm_session_prot_conf_id {
* struct iwl_mvm_session_prot_cmd - configure a session protection
* @id_and_color: the id and color of the mac for which this session protection
* is sent
- * @action: can be either FW_CTXT_ACTION_ADD or FW_CTXT_ACTION_REMOVE
+ * @action: can be either FW_CTXT_ACTION_ADD or FW_CTXT_ACTION_REMOVE,
+ * see &enum iwl_ctxt_action
* @conf_id: see &enum iwl_mvm_session_prot_conf_id
* @duration_tu: the duration of the whole protection in TUs.
* @repetition_count: not used
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
index 97edf5477ba7..842360b1e995 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_tx_h__
@@ -177,17 +177,6 @@ enum iwl_tx_offload_assist_flags_pos {
#define IWL_TX_CMD_OFFLD_MH_MASK 0x1f
#define IWL_TX_CMD_OFFLD_IP_HDR_MASK 0x3f
-enum iwl_tx_offload_assist_bz {
- IWL_TX_CMD_OFFLD_BZ_RESULT_OFFS = 0x000003ff,
- IWL_TX_CMD_OFFLD_BZ_START_OFFS = 0x001ff800,
- IWL_TX_CMD_OFFLD_BZ_MH_LEN = 0x07c00000,
- IWL_TX_CMD_OFFLD_BZ_MH_PAD = 0x08000000,
- IWL_TX_CMD_OFFLD_BZ_AMSDU = 0x10000000,
- IWL_TX_CMD_OFFLD_BZ_ZERO2ONES = 0x20000000,
- IWL_TX_CMD_OFFLD_BZ_ENABLE_CSUM = 0x40000000,
- IWL_TX_CMD_OFFLD_BZ_PARTIAL_CSUM = 0x80000000,
-};
-
/* TODO: complete documentation for try_cnt and btkill_cnt */
/**
* struct iwl_tx_cmd - TX command struct to FW
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 55219974b92b..3ab6a68f1e9f 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2005-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -1038,7 +1038,7 @@ iwl_dump_ini_prph_mac_iter(struct iwl_fw_runtime *fwrt,
range->range_data_size = reg->dev_addr.size;
for (i = 0; i < le32_to_cpu(reg->dev_addr.size); i += 4) {
prph_val = iwl_read_prph(fwrt->trans, addr + i);
- if ((prph_val & ~0xf) == 0xa5a5a5a0)
+ if (iwl_trans_is_hw_error_value(prph_val))
return -EBUSY;
*val++ = cpu_to_le32(prph_val);
}
@@ -1562,7 +1562,7 @@ iwl_dump_ini_dbgi_sram_iter(struct iwl_fw_runtime *fwrt,
prph_data = iwl_read_prph_no_grab(fwrt->trans, (i % 2) ?
DBGI_SRAM_TARGET_ACCESS_RDATA_MSB :
DBGI_SRAM_TARGET_ACCESS_RDATA_LSB);
- if ((prph_data & ~0xf) == 0xa5a5a5a0) {
+ if (iwl_trans_is_hw_error_value(prph_data)) {
iwl_trans_release_nic_access(fwrt->trans);
return -EBUSY;
}
@@ -2034,7 +2034,6 @@ static u32
iwl_dump_ini_imr_get_size(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data)
{
- u32 size = 0;
u32 ranges = 0;
u32 imr_enable = fwrt->trans->dbg.imr_data.imr_enable;
u32 imr_size = fwrt->trans->dbg.imr_data.imr_size;
@@ -2044,17 +2043,16 @@ iwl_dump_ini_imr_get_size(struct iwl_fw_runtime *fwrt,
IWL_DEBUG_INFO(fwrt,
"WRT: Invalid imr data enable: %d, imr_size: %d, sram_size: %d\n",
imr_enable, imr_size, sram_size);
- return size;
+ return 0;
}
- size = imr_size;
ranges = iwl_dump_ini_imr_ranges(fwrt, reg_data);
- if (!size && !ranges) {
- IWL_ERR(fwrt, "WRT: imr_size :=%d, ranges :=%d\n", size, ranges);
+ if (!ranges) {
+ IWL_ERR(fwrt, "WRT: ranges :=%d\n", ranges);
return 0;
}
- size += sizeof(struct iwl_fw_ini_error_dump) +
+ imr_size += sizeof(struct iwl_fw_ini_error_dump) +
ranges * sizeof(struct iwl_fw_ini_error_dump_range);
- return size;
+ return imr_size;
}
/**
@@ -3156,6 +3154,51 @@ static int iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
return 0;
}
+int iwl_fw_send_timestamp_marker_cmd(struct iwl_fw_runtime *fwrt)
+{
+ struct iwl_mvm_marker marker = {
+ .dw_len = sizeof(struct iwl_mvm_marker) / 4,
+ .marker_id = MARKER_ID_SYNC_CLOCK,
+ };
+ struct iwl_host_cmd hcmd = {
+ .flags = CMD_ASYNC,
+ .id = WIDE_ID(LONG_GROUP, MARKER_CMD),
+ .dataflags = {},
+ };
+ struct iwl_mvm_marker_rsp *resp;
+ int cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
+ WIDE_ID(LONG_GROUP, MARKER_CMD),
+ IWL_FW_CMD_VER_UNKNOWN);
+ int ret;
+
+ if (cmd_ver == 1) {
+ /* the real timestamp is taken from the ftrace clock
+ * this is for finding the match between fw and kernel logs
+ */
+ marker.timestamp = cpu_to_le64(fwrt->timestamp.seq++);
+ } else if (cmd_ver == 2) {
+ marker.timestamp = cpu_to_le64(ktime_get_boottime_ns());
+ } else {
+ IWL_DEBUG_INFO(fwrt,
+ "Invalid version of Marker CMD. Ver = %d\n",
+ cmd_ver);
+ return -EINVAL;
+ }
+
+ hcmd.data[0] = &marker;
+ hcmd.len[0] = sizeof(marker);
+
+ ret = iwl_trans_send_cmd(fwrt->trans, &hcmd);
+
+ if (cmd_ver > 1 && hcmd.resp_pkt) {
+ resp = (void *)hcmd.resp_pkt->data;
+ IWL_DEBUG_INFO(fwrt, "FW GP2 time: %u\n",
+ le32_to_cpu(resp->gp2));
+ }
+
+ return ret;
+}
+
void iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_params *params,
bool stop)
@@ -3166,12 +3209,15 @@ void iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
return;
if (fw_has_capa(&fwrt->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_DBG_SUSPEND_RESUME_CMD_SUPP))
+ IWL_UCODE_TLV_CAPA_DBG_SUSPEND_RESUME_CMD_SUPP)) {
+ if (stop)
+ iwl_fw_send_timestamp_marker_cmd(fwrt);
ret = iwl_fw_dbg_suspend_resume_hcmd(fwrt->trans, stop);
- else if (stop)
+ } else if (stop) {
iwl_fw_dbg_stop_recording(fwrt->trans, params);
- else
+ } else {
ret = iwl_fw_dbg_restart_recording(fwrt->trans, params);
+ }
#ifdef CONFIG_IWLWIFI_DEBUGFS
if (!ret) {
if (stop)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
index be7806407de8..4227fbd2b977 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2018-2019, 2021-2022 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2019, 2021-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -227,6 +227,8 @@ static inline void iwl_fw_flush_dumps(struct iwl_fw_runtime *fwrt)
flush_delayed_work(&fwrt->dump.wks[i].wk);
}
+int iwl_fw_send_timestamp_marker_cmd(struct iwl_fw_runtime *fwrt);
+
#ifdef CONFIG_IWLWIFI_DEBUGFS
static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt)
{
@@ -327,4 +329,18 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt);
void iwl_send_dbg_dump_complete_cmd(struct iwl_fw_runtime *fwrt,
u32 timepoint,
u32 timepoint_data);
+
+#define IWL_FW_CHECK_FAILED(_obj, _fmt, ...) \
+ IWL_ERR_LIMIT(_obj, _fmt, __VA_ARGS__)
+
+#define IWL_FW_CHECK(_obj, _cond, _fmt, ...) \
+ ({ \
+ bool __cond = (_cond); \
+ \
+ if (unlikely(__cond)) \
+ IWL_FW_CHECK_FAILED(_obj, _fmt, __VA_ARGS__); \
+ \
+ unlikely(__cond); \
+ })
+
#endif /* __iwl_fw_dbg_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
index 607e07ed2477..3cdbc6ac7ae5 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
@@ -123,28 +123,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
#define FWRT_DEBUGFS_ADD_FILE(name, parent, mode) \
FWRT_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
-static int iwl_fw_send_timestamp_marker_cmd(struct iwl_fw_runtime *fwrt)
-{
- struct iwl_mvm_marker marker = {
- .dw_len = sizeof(struct iwl_mvm_marker) / 4,
- .marker_id = MARKER_ID_SYNC_CLOCK,
-
- /* the real timestamp is taken from the ftrace clock
- * this is for finding the match between fw and kernel logs
- */
- .timestamp = cpu_to_le64(fwrt->timestamp.seq++),
- };
-
- struct iwl_host_cmd hcmd = {
- .id = MARKER_CMD,
- .flags = CMD_ASYNC,
- .data[0] = &marker,
- .len[0] = sizeof(marker),
- };
-
- return iwl_trans_send_cmd(fwrt->trans, &hcmd);
-}
-
static int iwl_dbgfs_enabled_severities_write(struct iwl_fw_runtime *fwrt,
char *buf, size_t count)
{
@@ -354,9 +332,18 @@ static int iwl_dbgfs_fw_info_seq_show(struct seq_file *seq, void *v)
const struct iwl_fw *fw = priv->fwrt->fw;
const struct iwl_fw_cmd_version *ver;
u32 cmd_id;
-
- if (!state->pos)
+ int has_capa;
+
+ if (!state->pos) {
+ seq_puts(seq, "fw_capa:\n");
+ has_capa = fw_has_capa(&fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT) ? 1 : 0;
+ seq_printf(seq,
+ " %d: %d\n",
+ IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT,
+ has_capa);
seq_puts(seq, "fw_api_ver:\n");
+ }
ver = &fw->ucode_capa.cmd_versions[state->pos];
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c
index f86f7b4baa18..5876f917e536 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -194,7 +194,7 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu
/* check if there is a HW error */
val = iwl_trans_read_mem32(trans, base);
- if (((val & ~0xf) == 0xa5a5a5a0) || ((val & ~0xf) == 0x5a5a5a50)) {
+ if (iwl_trans_is_hw_error_value(val)) {
int err;
IWL_ERR(trans, "HW error, resetting before reading\n");
@@ -467,6 +467,10 @@ static void iwl_fwrt_dump_fseq_regs(struct iwl_fw_runtime *fwrt)
FSEQ_REG(CNVR_AUX_MISC_CHIP),
FSEQ_REG(CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM),
FSEQ_REG(CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR),
+ FSEQ_REG(FSEQ_PREV_CNVIO_INIT_VERSION),
+ FSEQ_REG(FSEQ_WIFI_FSEQ_VERSION),
+ FSEQ_REG(FSEQ_BT_FSEQ_VERSION),
+ FSEQ_REG(FSEQ_CLASS_TP_VERSION),
};
if (!iwl_trans_grab_nic_access(trans))
@@ -507,11 +511,16 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
iwl_fwrt_dump_fseq_regs(fwrt);
if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
pc_data = fwrt->trans->dbg.pc_data;
+
+ if (!iwl_trans_grab_nic_access(fwrt->trans))
+ return;
for (count = 0; count < fwrt->trans->dbg.num_pc;
count++, pc_data++)
IWL_ERR(fwrt, "%s: 0x%x\n",
pc_data->pc_name,
- pc_data->pc_address);
+ iwl_read_prph_no_grab(fwrt->trans,
+ pc_data->pc_address));
+ iwl_trans_release_nic_access(fwrt->trans);
}
if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h
index cddf09d6be1c..b36e9613a52c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/file.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h
@@ -323,6 +323,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
* is supported.
* @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC
* @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan (no longer used)
+ * @IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG: supports fragmented PNVM image
* @IWL_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT: the firmware supports setting
* stabilization latency for SoCs.
* @IWL_UCODE_TLV_CAPA_STA_PM_NOTIF: firmware will send STA PM notification
@@ -398,6 +399,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31,
/* set 1 */
+ IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG = (__force iwl_ucode_tlv_capa_t)32,
IWL_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT = (__force iwl_ucode_tlv_capa_t)37,
IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38,
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)39,
@@ -462,6 +464,10 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_BIGTK_TX_SUPPORT = (__force iwl_ucode_tlv_capa_t)109,
IWL_UCODE_TLV_CAPA_MLD_API_SUPPORT = (__force iwl_ucode_tlv_capa_t)110,
IWL_UCODE_TLV_CAPA_SCAN_DONT_TOGGLE_ANT = (__force iwl_ucode_tlv_capa_t)111,
+ IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT = (__force iwl_ucode_tlv_capa_t)112,
+ IWL_UCODE_TLV_CAPA_OFFLOAD_BTM_SUPPORT = (__force iwl_ucode_tlv_capa_t)113,
+ IWL_UCODE_TLV_CAPA_STA_EXP_MFP_SUPPORT = (__force iwl_ucode_tlv_capa_t)114,
+ IWL_UCODE_TLV_CAPA_SNIFF_VALIDATE_SUPPORT = (__force iwl_ucode_tlv_capa_t)116,
#ifdef __CHECKER__
/* sparse says it cannot increment the previous enum member */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
index c6f2672fdc73..650e4bde9c17 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright(c) 2020-2022 Intel Corporation
+ * Copyright(c) 2020-2023 Intel Corporation
*/
#include "iwl-drv.h"
@@ -31,18 +31,18 @@ static bool iwl_pnvm_complete_fn(struct iwl_notif_wait_data *notif_wait,
}
static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
- size_t len)
+ size_t len,
+ struct iwl_pnvm_image *pnvm_data)
{
const struct iwl_ucode_tlv *tlv;
u32 sha1 = 0;
u16 mac_type = 0, rf_id = 0;
- u8 *pnvm_data = NULL, *tmp;
bool hw_match = false;
- u32 size = 0;
- int ret;
IWL_DEBUG_FW(trans, "Handling PNVM section\n");
+ memset(pnvm_data, 0, sizeof(*pnvm_data));
+
while (len >= sizeof(*tlv)) {
u32 tlv_len, tlv_type;
@@ -55,8 +55,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len);
- ret = -EINVAL;
- goto out;
+ return -EINVAL;
}
data += sizeof(*tlv);
@@ -75,6 +74,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
IWL_DEBUG_FW(trans,
"Got IWL_UCODE_TLV_PNVM_VERSION %0x\n",
sha1);
+ pnvm_data->version = sha1;
break;
case IWL_UCODE_TLV_HW_TYPE:
if (tlv_len < 2 * sizeof(__le16)) {
@@ -112,26 +112,26 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
break;
}
- IWL_DEBUG_FW(trans, "Adding data (size %d)\n",
- data_len);
-
- tmp = krealloc(pnvm_data, size + data_len, GFP_KERNEL);
- if (!tmp) {
+ if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) {
IWL_DEBUG_FW(trans,
- "Couldn't allocate (more) pnvm_data\n");
-
- ret = -ENOMEM;
- goto out;
+ "too many payloads to allocate in DRAM.\n");
+ return -EINVAL;
}
- pnvm_data = tmp;
-
- memcpy(pnvm_data + size, section->data, data_len);
+ IWL_DEBUG_FW(trans, "Adding data (size %d)\n",
+ data_len);
- size += data_len;
+ pnvm_data->chunks[pnvm_data->n_chunks].data = section->data;
+ pnvm_data->chunks[pnvm_data->n_chunks].len = data_len;
+ pnvm_data->n_chunks++;
break;
}
+ case IWL_UCODE_TLV_MEM_DESC:
+ if (iwl_uefi_handle_tlv_mem_desc(trans, data, tlv_len,
+ pnvm_data))
+ return -EINVAL;
+ break;
case IWL_UCODE_TLV_PNVM_SKU:
IWL_DEBUG_FW(trans,
"New PNVM section started, stop parsing.\n");
@@ -152,26 +152,20 @@ done:
"HW mismatch, skipping PNVM section (need mac_type 0x%x rf_id 0x%x)\n",
CSR_HW_REV_TYPE(trans->hw_rev),
CSR_HW_RFID_TYPE(trans->hw_rf_id));
- ret = -ENOENT;
- goto out;
+ return -ENOENT;
}
- if (!size) {
+ if (!pnvm_data->n_chunks) {
IWL_DEBUG_FW(trans, "Empty PNVM, skipping.\n");
- ret = -ENOENT;
- goto out;
+ return -ENOENT;
}
- IWL_INFO(trans, "loaded PNVM version %08x\n", sha1);
-
- ret = iwl_trans_set_pnvm(trans, pnvm_data, size);
-out:
- kfree(pnvm_data);
- return ret;
+ return 0;
}
static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
- size_t len)
+ size_t len,
+ struct iwl_pnvm_image *pnvm_data)
{
const struct iwl_ucode_tlv *tlv;
@@ -212,7 +206,8 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) {
int ret;
- ret = iwl_pnvm_handle_section(trans, data, len);
+ ret = iwl_pnvm_handle_section(trans, data, len,
+ pnvm_data);
if (!ret)
return 0;
} else {
@@ -255,89 +250,136 @@ static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len)
return 0;
}
-int iwl_pnvm_load(struct iwl_trans *trans,
- struct iwl_notif_wait_data *notif_wait)
+static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len)
{
- u8 *data;
- size_t len;
struct pnvm_sku_package *package;
- struct iwl_notification_wait pnvm_wait;
- static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP,
- PNVM_INIT_COMPLETE_NTFY) };
- int ret;
-
- /* if the SKU_ID is empty, there's nothing to do */
- if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2])
- return 0;
-
- /*
- * If we already loaded (or tried to load) it before, we just
- * need to set it again.
- */
- if (trans->pnvm_loaded) {
- ret = iwl_trans_set_pnvm(trans, NULL, 0);
- if (ret)
- return ret;
- goto skip_parse;
- }
+ u8 *image = NULL;
/* First attempt to get the PNVM from BIOS */
- package = iwl_uefi_get_pnvm(trans, &len);
+ package = iwl_uefi_get_pnvm(trans_p, len);
if (!IS_ERR_OR_NULL(package)) {
- if (len >= sizeof(*package)) {
+ if (*len >= sizeof(*package)) {
/* we need only the data */
- len -= sizeof(*package);
- data = kmemdup(package->data, len, GFP_KERNEL);
- } else {
- data = NULL;
+ *len -= sizeof(*package);
+ image = kmemdup(package->data, *len, GFP_KERNEL);
}
-
/* free package regardless of whether kmemdup succeeded */
kfree(package);
-
- if (data)
- goto parse;
+ if (image)
+ return image;
}
/* If it's not available, try from the filesystem */
- ret = iwl_pnvm_get_from_fs(trans, &data, &len);
+ if (iwl_pnvm_get_from_fs(trans_p, &image, len))
+ return NULL;
+ return image;
+}
+
+static void iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa)
+{
+ struct iwl_pnvm_image *pnvm_data = NULL;
+ u8 *data = NULL;
+ size_t length;
+ int ret;
+
+ /* failed to get/parse the image in the past, no use trying again */
+ if (trans->fail_to_parse_pnvm_image)
+ return;
+
+ if (trans->pnvm_loaded)
+ goto set;
+
+ data = iwl_get_pnvm_image(trans, &length);
+ if (!data) {
+ trans->fail_to_parse_pnvm_image = true;
+ return;
+ }
+
+ pnvm_data = kzalloc(sizeof(*pnvm_data), GFP_KERNEL);
+ if (!pnvm_data)
+ goto free;
+
+ ret = iwl_pnvm_parse(trans, data, length, pnvm_data);
if (ret) {
- /*
- * Pretend we've loaded it - at least we've tried and
- * couldn't load it at all, so there's no point in
- * trying again over and over.
- */
- trans->pnvm_loaded = true;
-
- goto skip_parse;
+ trans->fail_to_parse_pnvm_image = true;
+ goto free;
}
-parse:
- iwl_pnvm_parse(trans, data, len);
+ ret = iwl_trans_load_pnvm(trans, pnvm_data, capa);
+ if (ret)
+ goto free;
+ IWL_INFO(trans, "loaded PNVM version %08x\n", pnvm_data->version);
+set:
+ iwl_trans_set_pnvm(trans, capa);
+free:
kfree(data);
+ kfree(pnvm_data);
+}
-skip_parse:
- /* now try to get the reduce power table, if not loaded yet */
- if (!trans->reduce_power_loaded) {
- data = iwl_uefi_get_reduced_power(trans, &len);
- if (IS_ERR_OR_NULL(data)) {
- /*
- * Pretend we've loaded it - at least we've tried and
- * couldn't load it at all, so there's no point in
- * trying again over and over.
- */
- trans->reduce_power_loaded = true;
- } else {
- ret = iwl_trans_set_reduce_power(trans, data, len);
- if (ret)
- IWL_DEBUG_FW(trans,
- "Failed to set reduce power table %d\n",
- ret);
- kfree(data);
- }
+static void
+iwl_pnvm_load_reduce_power_to_trans(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa)
+{
+ struct iwl_pnvm_image *pnvm_data = NULL;
+ u8 *data = NULL;
+ size_t length;
+ int ret;
+
+ if (trans->failed_to_load_reduce_power_image)
+ return;
+
+ if (trans->reduce_power_loaded)
+ goto set;
+
+ data = iwl_uefi_get_reduced_power(trans, &length);
+ if (IS_ERR(data)) {
+ trans->failed_to_load_reduce_power_image = true;
+ return;
}
+ pnvm_data = kzalloc(sizeof(*pnvm_data), GFP_KERNEL);
+ if (!pnvm_data)
+ goto free;
+
+ ret = iwl_uefi_reduce_power_parse(trans, data, length, pnvm_data);
+ if (ret) {
+ trans->failed_to_load_reduce_power_image = true;
+ goto free;
+ }
+
+ ret = iwl_trans_load_reduce_power(trans, pnvm_data, capa);
+ if (ret) {
+ IWL_DEBUG_FW(trans,
+ "Failed to load reduce power table %d\n",
+ ret);
+ trans->failed_to_load_reduce_power_image = true;
+ goto free;
+ }
+
+set:
+ iwl_trans_set_reduce_power(trans, capa);
+free:
+ kfree(data);
+ kfree(pnvm_data);
+}
+
+int iwl_pnvm_load(struct iwl_trans *trans,
+ struct iwl_notif_wait_data *notif_wait,
+ const struct iwl_ucode_capabilities *capa)
+{
+ struct iwl_notification_wait pnvm_wait;
+ static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP,
+ PNVM_INIT_COMPLETE_NTFY) };
+
+ /* if the SKU_ID is empty, there's nothing to do */
+ if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2])
+ return 0;
+
+ iwl_pnvm_load_pnvm_to_trans(trans, capa);
+ iwl_pnvm_load_reduce_power_to_trans(trans, capa);
+
iwl_init_notification_wait(notif_wait, &pnvm_wait,
ntf_cmds, ARRAY_SIZE(ntf_cmds),
iwl_pnvm_complete_fn, trans);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h
index 203c367dd4de..1bac3466154c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h
@@ -1,13 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
-/******************************************************************************
- *
- * Copyright(c) 2020-2021 Intel Corporation
- *
- *****************************************************************************/
-
+/*
+ * Copyright(c) 2020-2023 Intel Corporation
+ */
#ifndef __IWL_PNVM_H__
#define __IWL_PNVM_H__
+#include "iwl-drv.h"
#include "fw/notif-wait.h"
#define MVM_UCODE_PNVM_TIMEOUT (HZ / 4)
@@ -15,24 +13,17 @@
#define MAX_PNVM_NAME 64
int iwl_pnvm_load(struct iwl_trans *trans,
- struct iwl_notif_wait_data *notif_wait);
+ struct iwl_notif_wait_data *notif_wait,
+ const struct iwl_ucode_capabilities *capa);
static inline
void iwl_pnvm_get_fs_name(struct iwl_trans *trans,
u8 *pnvm_name, size_t max_len)
{
- int pre_len;
-
- /*
- * The prefix unfortunately includes a hyphen at the end, so
- * don't add the dot here...
- */
- snprintf(pnvm_name, max_len, "%spnvm", trans->cfg->fw_name_pre);
+ char _fw_name_pre[FW_NAME_PRE_BUFSIZE];
- /* ...but replace the hyphen with the dot here. */
- pre_len = strlen(trans->cfg->fw_name_pre);
- if (pre_len < max_len && pre_len > 0)
- pnvm_name[pre_len - 1] = '.';
+ snprintf(pnvm_name, max_len, "%s.pnvm",
+ iwl_drv_get_fwname_pre(trans, _fw_name_pre));
}
#endif /* __IWL_PNVM_H__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
index df689a9b7e2c..702586945533 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#ifndef __iwl_fw_runtime_h__
#define __iwl_fw_runtime_h__
@@ -146,12 +146,14 @@ struct iwl_fw_runtime {
u32 umac_minor;
} fw_ver;
} dump;
-#ifdef CONFIG_IWLWIFI_DEBUGFS
struct {
+#ifdef CONFIG_IWLWIFI_DEBUGFS
struct delayed_work wk;
u32 delay;
+#endif
u64 seq;
} timestamp;
+#ifdef CONFIG_IWLWIFI_DEBUGFS
bool tpc_enabled;
#endif /* CONFIG_IWLWIFI_DEBUGFS */
#ifdef CONFIG_ACPI
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
index 01afea33c38c..9877988db0d2 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright(c) 2021-2022 Intel Corporation
+ * Copyright(c) 2021-2023 Intel Corporation
*/
#include "iwl-drv.h"
@@ -17,52 +17,109 @@
0xb2, 0xec, 0xf5, 0xa3, \
0x59, 0x4f, 0x4a, 0xea)
-void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
+struct iwl_uefi_pnvm_mem_desc {
+ __le32 addr;
+ __le32 size;
+ const u8 data[];
+} __packed;
+
+static void *iwl_uefi_get_variable(efi_char16_t *name, efi_guid_t *guid,
+ unsigned long *data_size)
{
- void *data;
- unsigned long package_size;
efi_status_t status;
+ void *data;
- *len = 0;
+ if (!data_size)
+ return ERR_PTR(-EINVAL);
if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
return ERR_PTR(-ENODEV);
- /*
- * TODO: we hardcode a maximum length here, because reading
- * from the UEFI is not working. To implement this properly,
- * we have to call efivar_entry_size().
- */
- package_size = IWL_HARDCODED_PNVM_SIZE;
+ /* first call with NULL data to get the exact entry size */
+ *data_size = 0;
+ status = efi.get_variable(name, guid, NULL, data_size, NULL);
+ if (status != EFI_BUFFER_TOO_SMALL || !*data_size)
+ return ERR_PTR(-EIO);
- data = kmalloc(package_size, GFP_KERNEL);
+ data = kmalloc(*data_size, GFP_KERNEL);
if (!data)
return ERR_PTR(-ENOMEM);
- status = efi.get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_VAR_GUID,
- NULL, &package_size, data);
+ status = efi.get_variable(name, guid, NULL, data_size, data);
if (status != EFI_SUCCESS) {
- IWL_DEBUG_FW(trans,
- "PNVM UEFI variable not found 0x%lx (len %lu)\n",
- status, package_size);
kfree(data);
return ERR_PTR(-ENOENT);
}
+ return data;
+}
+
+void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
+{
+ unsigned long package_size;
+ void *data;
+
+ *len = 0;
+
+ data = iwl_uefi_get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_VAR_GUID,
+ &package_size);
+ if (IS_ERR(data)) {
+ IWL_DEBUG_FW(trans,
+ "PNVM UEFI variable not found 0x%lx (len %lu)\n",
+ PTR_ERR(data), package_size);
+ return data;
+ }
+
IWL_DEBUG_FW(trans, "Read PNVM from UEFI with size %lu\n", package_size);
*len = package_size;
return data;
}
-static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
- const u8 *data, size_t len)
+int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data,
+ u32 tlv_len, struct iwl_pnvm_image *pnvm_data)
+{
+ const struct iwl_uefi_pnvm_mem_desc *desc = (const void *)data;
+ u32 data_len;
+
+ if (tlv_len < sizeof(*desc)) {
+ IWL_DEBUG_FW(trans, "TLV len (%d) is too small\n", tlv_len);
+ return -EINVAL;
+ }
+
+ data_len = tlv_len - sizeof(*desc);
+
+ IWL_DEBUG_FW(trans,
+ "Handle IWL_UCODE_TLV_MEM_DESC, len %d data_len %d\n",
+ tlv_len, data_len);
+
+ if (le32_to_cpu(desc->size) != data_len) {
+ IWL_DEBUG_FW(trans, "invalid mem desc size %d\n", desc->size);
+ return -EINVAL;
+ }
+
+ if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) {
+ IWL_DEBUG_FW(trans, "too many payloads to allocate in DRAM.\n");
+ return -EINVAL;
+ }
+
+ IWL_DEBUG_FW(trans, "Adding data (size %d)\n", data_len);
+
+ pnvm_data->chunks[pnvm_data->n_chunks].data = desc->data;
+ pnvm_data->chunks[pnvm_data->n_chunks].len = data_len;
+ pnvm_data->n_chunks++;
+
+ return 0;
+}
+
+static int iwl_uefi_reduce_power_section(struct iwl_trans *trans,
+ const u8 *data, size_t len,
+ struct iwl_pnvm_image *pnvm_data)
{
const struct iwl_ucode_tlv *tlv;
- u8 *reduce_power_data = NULL, *tmp;
- u32 size = 0;
IWL_DEBUG_FW(trans, "Handling REDUCE_POWER section\n");
+ memset(pnvm_data, 0, sizeof(*pnvm_data));
while (len >= sizeof(*tlv)) {
u32 tlv_len, tlv_type;
@@ -76,39 +133,17 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len);
- kfree(reduce_power_data);
- reduce_power_data = ERR_PTR(-EINVAL);
- goto out;
+ return -EINVAL;
}
data += sizeof(*tlv);
switch (tlv_type) {
- case IWL_UCODE_TLV_MEM_DESC: {
- IWL_DEBUG_FW(trans,
- "Got IWL_UCODE_TLV_MEM_DESC len %d\n",
- tlv_len);
-
- IWL_DEBUG_FW(trans, "Adding data (size %d)\n", tlv_len);
-
- tmp = krealloc(reduce_power_data, size + tlv_len, GFP_KERNEL);
- if (!tmp) {
- IWL_DEBUG_FW(trans,
- "Couldn't allocate (more) reduce_power_data\n");
-
- kfree(reduce_power_data);
- reduce_power_data = ERR_PTR(-ENOMEM);
- goto out;
- }
-
- reduce_power_data = tmp;
-
- memcpy(reduce_power_data + size, data, tlv_len);
-
- size += tlv_len;
-
+ case IWL_UCODE_TLV_MEM_DESC:
+ if (iwl_uefi_handle_tlv_mem_desc(trans, data, tlv_len,
+ pnvm_data))
+ return -EINVAL;
break;
- }
case IWL_UCODE_TLV_PNVM_SKU:
IWL_DEBUG_FW(trans,
"New REDUCE_POWER section started, stop parsing.\n");
@@ -124,27 +159,18 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
}
done:
- if (!size) {
+ if (!pnvm_data->n_chunks) {
IWL_DEBUG_FW(trans, "Empty REDUCE_POWER, skipping.\n");
- /* Better safe than sorry, but 'reduce_power_data' should
- * always be NULL if !size.
- */
- kfree(reduce_power_data);
- reduce_power_data = ERR_PTR(-ENOENT);
- goto out;
+ return -ENOENT;
}
-
- IWL_INFO(trans, "loaded REDUCE_POWER\n");
-
-out:
- return reduce_power_data;
+ return 0;
}
-static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
- const u8 *data, size_t len)
+int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
+ const u8 *data, size_t len,
+ struct iwl_pnvm_image *pnvm_data)
{
const struct iwl_ucode_tlv *tlv;
- void *sec_data;
IWL_DEBUG_FW(trans, "Parsing REDUCE_POWER data\n");
@@ -160,7 +186,7 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len);
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
}
if (tlv_type == IWL_UCODE_TLV_PNVM_SKU) {
@@ -181,11 +207,11 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
if (trans->sku_id[0] == le32_to_cpu(sku_id->data[0]) &&
trans->sku_id[1] == le32_to_cpu(sku_id->data[1]) &&
trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) {
- sec_data = iwl_uefi_reduce_power_section(trans,
- data,
- len);
- if (!IS_ERR(sec_data))
- return sec_data;
+ int ret = iwl_uefi_reduce_power_section(trans,
+ data, len,
+ pnvm_data);
+ if (!ret)
+ return 0;
} else {
IWL_DEBUG_FW(trans, "SKU ID didn't match!\n");
}
@@ -195,51 +221,45 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
}
}
- return ERR_PTR(-ENOENT);
+ return -ENOENT;
}
-void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
+u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
{
struct pnvm_sku_package *package;
- void *data = NULL;
unsigned long package_size;
- efi_status_t status;
+ u8 *data;
- *len = 0;
+ package = iwl_uefi_get_variable(IWL_UEFI_REDUCED_POWER_NAME,
+ &IWL_EFI_VAR_GUID, &package_size);
- if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
- return ERR_PTR(-ENODEV);
-
- /*
- * TODO: we hardcode a maximum length here, because reading
- * from the UEFI is not working. To implement this properly,
- * we have to call efivar_entry_size().
- */
- package_size = IWL_HARDCODED_REDUCE_POWER_SIZE;
-
- package = kmalloc(package_size, GFP_KERNEL);
- if (!package)
- return ERR_PTR(-ENOMEM);
-
- status = efi.get_variable(IWL_UEFI_REDUCED_POWER_NAME, &IWL_EFI_VAR_GUID,
- NULL, &package_size, package);
- if (status != EFI_SUCCESS) {
+ if (IS_ERR(package)) {
IWL_DEBUG_FW(trans,
"Reduced Power UEFI variable not found 0x%lx (len %lu)\n",
- status, package_size);
+ PTR_ERR(package), package_size);
+ return ERR_CAST(package);
+ }
+
+ if (package_size < sizeof(*package)) {
+ IWL_DEBUG_FW(trans,
+ "Invalid Reduced Power UEFI variable len (%lu)\n",
+ package_size);
kfree(package);
- return ERR_PTR(-ENOENT);
+ return ERR_PTR(-EINVAL);
}
IWL_DEBUG_FW(trans, "Read reduced power from UEFI with size %lu\n",
package_size);
- *len = package_size;
IWL_DEBUG_FW(trans, "rev %d, total_size %d, n_skus %d\n",
package->rev, package->total_size, package->n_skus);
- data = iwl_uefi_reduce_power_parse(trans, package->data,
- *len - sizeof(*package));
+ *len = package_size - sizeof(*package);
+ data = kmemdup(package->data, *len, GFP_KERNEL);
+ if (!data) {
+ kfree(package);
+ return ERR_PTR(-ENOMEM);
+ }
kfree(package);
@@ -264,31 +284,27 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans)
{
struct uefi_cnv_common_step_data *data;
unsigned long package_size;
- efi_status_t status;
int ret;
if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
return;
- if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
- return;
+ data = iwl_uefi_get_variable(IWL_UEFI_STEP_NAME, &IWL_EFI_VAR_GUID,
+ &package_size);
- /* TODO: we hardcode a maximum length here, because reading
- * from the UEFI is not working. To implement this properly,
- * we have to call efivar_entry_size().
- */
- package_size = IWL_HARDCODED_STEP_SIZE;
-
- data = kmalloc(package_size, GFP_KERNEL);
- if (!data)
+ if (IS_ERR(data)) {
+ IWL_DEBUG_FW(trans,
+ "STEP UEFI variable not found 0x%lx\n",
+ PTR_ERR(data));
return;
+ }
- status = efi.get_variable(IWL_UEFI_STEP_NAME, &IWL_EFI_VAR_GUID,
- NULL, &package_size, data);
- if (status != EFI_SUCCESS) {
+ if (package_size < sizeof(*data)) {
IWL_DEBUG_FW(trans,
- "STEP UEFI variable not found 0x%lx\n", status);
- goto out_free;
+ "Invalid STEP table UEFI variable len (%lu)\n",
+ package_size);
+ kfree(data);
+ return;
}
IWL_DEBUG_FW(trans, "Read STEP from UEFI with size %lu\n",
@@ -298,7 +314,6 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans)
if (ret < 0)
IWL_DEBUG_FW(trans, "Cannot read STEP tables. rev is invalid\n");
-out_free:
kfree(data);
}
IWL_EXPORT_SYMBOL(iwl_uefi_get_step_table);
@@ -341,29 +356,26 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans,
{
struct uefi_cnv_wlan_sgom_data *data;
unsigned long package_size;
- efi_status_t status;
int ret;
- if (!fwrt->geo_enabled ||
- !efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
+ if (!fwrt->geo_enabled)
return;
- /* TODO: we hardcode a maximum length here, because reading
- * from the UEFI is not working. To implement this properly,
- * we have to call efivar_entry_size().
- */
- package_size = IWL_HARDCODED_SGOM_SIZE;
-
- data = kmalloc(package_size, GFP_KERNEL);
- if (!data)
+ data = iwl_uefi_get_variable(IWL_UEFI_SGOM_NAME, &IWL_EFI_VAR_GUID,
+ &package_size);
+ if (IS_ERR(data)) {
+ IWL_DEBUG_FW(trans,
+ "SGOM UEFI variable not found 0x%lx\n",
+ PTR_ERR(data));
return;
+ }
- status = efi.get_variable(IWL_UEFI_SGOM_NAME, &IWL_EFI_VAR_GUID,
- NULL, &package_size, data);
- if (status != EFI_SUCCESS) {
+ if (package_size < sizeof(*data)) {
IWL_DEBUG_FW(trans,
- "SGOM UEFI variable not found 0x%lx\n", status);
- goto out_free;
+ "Invalid SGOM table UEFI variable len (%lu)\n",
+ package_size);
+ kfree(data);
+ return;
}
IWL_DEBUG_FW(trans, "Read SGOM from UEFI with size %lu\n",
@@ -373,9 +385,7 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans,
if (ret < 0)
IWL_DEBUG_FW(trans, "Cannot read SGOM tables. rev is invalid\n");
-out_free:
kfree(data);
-
}
IWL_EXPORT_SYMBOL(iwl_uefi_get_sgom_table);
#endif /* CONFIG_ACPI */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
index 17089bc74cf9..1369cc4855c3 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright(c) 2021-2022 Intel Corporation
+ * Copyright(c) 2021-2023 Intel Corporation
*/
#ifndef __iwl_fw_uefi__
#define __iwl_fw_uefi__
@@ -10,16 +10,7 @@
#define IWL_UEFI_SGOM_NAME L"UefiCnvWlanSarGeoOffsetMapping"
#define IWL_UEFI_STEP_NAME L"UefiCnvCommonSTEP"
-/*
- * TODO: we have these hardcoded values that the caller must pass,
- * because reading from the UEFI is not working. To implement this
- * properly, we have to change iwl_pnvm_get_from_uefi() to call
- * efivar_entry_size() and return the value to the caller instead.
- */
-#define IWL_HARDCODED_PNVM_SIZE 4096
-#define IWL_HARDCODED_REDUCE_POWER_SIZE 32768
-#define IWL_HARDCODED_SGOM_SIZE 339
-#define IWL_HARDCODED_STEP_SIZE 6
+#define IWL_SGOM_MAP_SIZE 339
struct pnvm_sku_package {
u8 rev;
@@ -31,7 +22,7 @@ struct pnvm_sku_package {
struct uefi_cnv_wlan_sgom_data {
u8 revision;
- u8 offset_map[IWL_HARDCODED_SGOM_SIZE - 1];
+ u8 offset_map[IWL_SGOM_MAP_SIZE - 1];
} __packed;
struct uefi_cnv_common_step_data {
@@ -50,24 +41,42 @@ struct uefi_cnv_common_step_data {
*/
#ifdef CONFIG_EFI
void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len);
-void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len);
+u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len);
+int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
+ const u8 *data, size_t len,
+ struct iwl_pnvm_image *pnvm_data);
void iwl_uefi_get_step_table(struct iwl_trans *trans);
+int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data,
+ u32 tlv_len, struct iwl_pnvm_image *pnvm_data);
#else /* CONFIG_EFI */
-static inline
-void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
+static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
{
return ERR_PTR(-EOPNOTSUPP);
}
-static inline
-void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
+static inline int
+iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
+ const u8 *data, size_t len,
+ struct iwl_pnvm_image *pnvm_data)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline u8 *
+iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
{
return ERR_PTR(-EOPNOTSUPP);
}
-static inline
-void iwl_uefi_get_step_table(struct iwl_trans *trans)
+static inline void iwl_uefi_get_step_table(struct iwl_trans *trans)
+{
+}
+
+static inline int
+iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data,
+ u32 tlv_len, struct iwl_pnvm_image *pnvm_data)
{
+ return 0;
}
#endif /* CONFIG_EFI */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index 411b7d4fcc9a..241a9e3f2a1a 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -2,6 +2,7 @@
/*
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
* Copyright (C) 2016-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#ifndef __IWL_CONFIG_H__
#define __IWL_CONFIG_H__
@@ -34,6 +35,7 @@ enum iwl_device_family {
IWL_DEVICE_FAMILY_22000,
IWL_DEVICE_FAMILY_AX210,
IWL_DEVICE_FAMILY_BZ,
+ IWL_DEVICE_FAMILY_SC,
};
/*
@@ -254,7 +256,6 @@ enum iwl_cfg_trans_ltr_delay {
* @xtal_latency: power up latency to get the xtal stabilized
* @extra_phy_cfg_flags: extra configuration flags to pass to the PHY
* @rf_id: need to read rf_id to determine the firmware image
- * @use_tfh: use TFH
* @gen2: 22000 and on transport operation
* @mq_rx_supported: multi-queue rx support
* @integrated: discrete or integrated
@@ -269,7 +270,6 @@ struct iwl_cfg_trans_params {
u32 xtal_latency;
u32 extra_phy_cfg_flags;
u32 rf_id:1,
- use_tfh:1,
gen2:1,
mq_rx_supported:1,
integrated:1,
@@ -307,7 +307,9 @@ struct iwl_fw_mon_regs {
* @name: Official name of the device
* @fw_name_pre: Firmware filename prefix. The api version and extension
* (.ucode) will be added to filename before loading from disk. The
- * filename is constructed as fw_name_pre<api>.ucode.
+ * filename is constructed as <fw_name_pre>-<api>.ucode.
+ * @fw_name_mac: MAC name for this config, the remaining pieces of the
+ * name will be generated dynamically
* @ucode_api_max: Highest version of uCode API supported by driver.
* @ucode_api_min: Lowest version of uCode API supported by driver.
* @max_inst_size: The maximal length of the fw inst section (only DVM)
@@ -361,6 +363,7 @@ struct iwl_cfg {
/* params specific to an individual device within a device family */
const char *name;
const char *fw_name_pre;
+ const char *fw_name_mac;
/* params likely to change within a device family */
const struct iwl_ht_params *ht_params;
const struct iwl_eeprom_params *eeprom_params;
@@ -388,7 +391,6 @@ struct iwl_cfg {
high_temp:1,
mac_addr_from_csr:10,
lp_xtal_workaround:1,
- disable_dummy_notification:1,
apmg_not_supported:1,
vht_mu_mimo_supported:1,
cdb:1,
@@ -416,17 +418,15 @@ struct iwl_cfg {
#define IWL_CFG_ANY (~0)
#define IWL_CFG_MAC_TYPE_PU 0x31
-#define IWL_CFG_MAC_TYPE_PNJ 0x32
#define IWL_CFG_MAC_TYPE_TH 0x32
#define IWL_CFG_MAC_TYPE_QU 0x33
#define IWL_CFG_MAC_TYPE_QUZ 0x35
-#define IWL_CFG_MAC_TYPE_QNJ 0x36
#define IWL_CFG_MAC_TYPE_SO 0x37
-#define IWL_CFG_MAC_TYPE_SNJ 0x42
#define IWL_CFG_MAC_TYPE_SOF 0x43
#define IWL_CFG_MAC_TYPE_MA 0x44
#define IWL_CFG_MAC_TYPE_BZ 0x46
#define IWL_CFG_MAC_TYPE_GL 0x47
+#define IWL_CFG_MAC_TYPE_SC 0x48
#define IWL_CFG_RF_TYPE_TH 0x105
#define IWL_CFG_RF_TYPE_TH1 0x108
@@ -438,6 +438,7 @@ struct iwl_cfg {
#define IWL_CFG_RF_TYPE_MR 0x110
#define IWL_CFG_RF_TYPE_MS 0x111
#define IWL_CFG_RF_TYPE_FM 0x112
+#define IWL_CFG_RF_TYPE_WH 0x113
#define IWL_CFG_RF_ID_TH 0x1
#define IWL_CFG_RF_ID_TH1 0x1
@@ -486,17 +487,16 @@ extern const struct iwl_cfg_trans_params iwl9000_trans_cfg;
extern const struct iwl_cfg_trans_params iwl9560_trans_cfg;
extern const struct iwl_cfg_trans_params iwl9560_long_latency_trans_cfg;
extern const struct iwl_cfg_trans_params iwl9560_shared_clk_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl_qnj_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_qu_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_qu_medium_latency_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_qu_long_latency_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_ax200_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl_snj_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_so_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_ma_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_bz_trans_cfg;
+extern const struct iwl_cfg_trans_params iwl_sc_trans_cfg;
extern const char iwl9162_name[];
extern const char iwl9260_name[];
extern const char iwl9260_1_name[];
@@ -535,6 +535,7 @@ extern const char iwl_ax221_name[];
extern const char iwl_ax231_name[];
extern const char iwl_ax411_name[];
extern const char iwl_bz_name[];
+extern const char iwl_sc_name[];
#if IS_ENABLED(CONFIG_IWLDVM)
extern const struct iwl_cfg iwl5300_agn_cfg;
extern const struct iwl_cfg iwl5100_agn_cfg;
@@ -580,6 +581,7 @@ extern const struct iwl_cfg iwl105_bgn_d_cfg;
extern const struct iwl_cfg iwl135_bgn_cfg;
#endif /* CONFIG_IWLDVM */
#if IS_ENABLED(CONFIG_IWLMVM)
+extern const struct iwl_ht_params iwl_22000_ht_params;
extern const struct iwl_cfg iwl7260_2ac_cfg;
extern const struct iwl_cfg iwl7260_2ac_cfg_high_temp;
extern const struct iwl_cfg iwl7260_2n_cfg;
@@ -604,7 +606,6 @@ extern const struct iwl_cfg iwl9260_2ac_cfg;
extern const struct iwl_cfg iwl9560_qu_b0_jf_b0_cfg;
extern const struct iwl_cfg iwl9560_qu_c0_jf_b0_cfg;
extern const struct iwl_cfg iwl9560_quz_a0_jf_b0_cfg;
-extern const struct iwl_cfg iwl9560_qnj_b0_jf_b0_cfg;
extern const struct iwl_cfg iwl9560_2ac_cfg_soc;
extern const struct iwl_cfg iwl_qu_b0_hr1_b0;
extern const struct iwl_cfg iwl_qu_c0_hr1_b0;
@@ -623,57 +624,23 @@ extern const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0;
extern const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0;
extern const struct iwl_cfg killer1650x_2ax_cfg;
extern const struct iwl_cfg killer1650w_2ax_cfg;
-extern const struct iwl_cfg iwl_qnj_b0_hr_b0_cfg;
extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0;
extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0;
extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long;
extern const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0;
extern const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0;
extern const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0_long;
-extern const struct iwl_cfg iwlax411_2ax_cfg_sosnj_gf4_a0;
-extern const struct iwl_cfg iwlax211_cfg_snj_gf_a0;
-extern const struct iwl_cfg iwl_cfg_snj_hr_b0;
-extern const struct iwl_cfg iwl_cfg_snj_a0_jf_b0;
-extern const struct iwl_cfg iwl_cfg_ma_a0_hr_b0;
-extern const struct iwl_cfg iwl_cfg_ma_a0_gf_a0;
-extern const struct iwl_cfg iwl_cfg_ma_a0_gf4_a0;
-extern const struct iwl_cfg iwl_cfg_ma_a0_mr_a0;
-extern const struct iwl_cfg iwl_cfg_ma_a0_ms_a0;
-extern const struct iwl_cfg iwl_cfg_ma_a0_fm_a0;
-extern const struct iwl_cfg iwl_cfg_ma_b0_hr_b0;
-extern const struct iwl_cfg iwl_cfg_ma_b0_gf_a0;
-extern const struct iwl_cfg iwl_cfg_ma_b0_gf4_a0;
-extern const struct iwl_cfg iwl_cfg_ma_b0_mr_a0;
-extern const struct iwl_cfg iwl_cfg_ma_b0_fm_a0;
-extern const struct iwl_cfg iwl_cfg_snj_a0_mr_a0;
-extern const struct iwl_cfg iwl_cfg_snj_a0_ms_a0;
+
+extern const struct iwl_cfg iwl_cfg_ma;
+
extern const struct iwl_cfg iwl_cfg_so_a0_hr_a0;
extern const struct iwl_cfg iwl_cfg_so_a0_ms_a0;
extern const struct iwl_cfg iwl_cfg_quz_a0_hr_b0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_hr_a0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_hr_b0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_gf_a0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_mr_a0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_fm_a0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_fm4_a0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_fm_b0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_fm4_b0;
-extern const struct iwl_cfg iwl_cfg_gl_a0_fm_a0;
-extern const struct iwl_cfg iwl_cfg_gl_b0_fm_b0;
-extern const struct iwl_cfg iwl_cfg_bz_z0_gf_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_a0_fm_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_a0_fm4_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_a0_gf_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_b0_gf_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_a0_gf4_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_b0_gf4_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_a0_hr_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_a0_hr_b0;
-extern const struct iwl_cfg iwl_cfg_bnj_b0_hr_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_b0_hr_b0;
-extern const struct iwl_cfg iwl_cfg_bnj_b0_fm_b0;
-extern const struct iwl_cfg iwl_cfg_bnj_b0_fm4_b0;
+
+extern const struct iwl_cfg iwl_cfg_bz;
+extern const struct iwl_cfg iwl_cfg_gl;
+
+extern const struct iwl_cfg iwl_cfg_sc;
#endif /* CONFIG_IWLMVM */
#endif /* __IWL_CONFIG_H__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h
index 3f7278014009..96bf353469b8 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h
@@ -13,6 +13,8 @@
#define CSR_IML_SIZE_ADDR 0x128
#define CSR_IML_RESP_ADDR 0x12c
+#define UNFRAGMENTED_PNVM_PAYLOADS_NUMBER 2
+
/* Set bit for enabling automatic function boot */
#define CSR_AUTO_FUNC_BOOT_ENA BIT(1)
/* Set bit for initiating function boot */
@@ -96,9 +98,9 @@ struct iwl_prph_scratch_control {
} __packed; /* PERIPH_SCRATCH_CONTROL_S */
/*
- * struct iwl_prph_scratch_pnvm_cfg - ror config
+ * struct iwl_prph_scratch_pnvm_cfg - PNVM scratch
* @pnvm_base_addr: PNVM start address
- * @pnvm_size: PNVM size in DWs
+ * @pnvm_size: the size of the PNVM image in bytes
* @reserved: reserved
*/
struct iwl_prph_scratch_pnvm_cfg {
@@ -107,6 +109,14 @@ struct iwl_prph_scratch_pnvm_cfg {
__le32 reserved;
} __packed; /* PERIPH_SCRATCH_PNVM_CFG_S */
+/**
+ * struct iwl_prph_scrath_mem_desc_addr_array
+ * @mem_descs: array of dram addresses.
+ * Each address is the beggining of a pnvm payload.
+ */
+struct iwl_prph_scrath_mem_desc_addr_array {
+ __le64 mem_descs[IPC_DRAM_MAP_ENTRY_NUM_MAX];
+} __packed; /* PERIPH_SCRATCH_MEM_DESC_ADDR_ARRAY_S_VER_1 */
/*
* struct iwl_prph_scratch_hwm_cfg - hwm config
* @hwm_base_addr: hwm start address
@@ -132,7 +142,7 @@ struct iwl_prph_scratch_rbd_cfg {
/*
* struct iwl_prph_scratch_uefi_cfg - prph scratch reduce power table
* @base_addr: reduce power table address
- * @size: table size in dwords
+ * @size: the size of the entire power table image
*/
struct iwl_prph_scratch_uefi_cfg {
__le64 base_addr;
@@ -277,10 +287,18 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
const struct fw_img *fw);
void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive);
-int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
- const void *data, u32 len);
-int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans,
- const void *data, u32 len);
+int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *pnvm_payloads,
+ const struct iwl_ucode_capabilities *capa);
+void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa);
+int
+iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *payloads,
+ const struct iwl_ucode_capabilities *capa);
+void
+iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa);
int iwl_trans_pcie_ctx_info_gen3_set_step(struct iwl_trans *trans,
u32 mbx_addr_0_step, u32 mbx_addr_1_step);
#endif /* __iwl_context_info_file_gen3_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h
index 4354d5acac9f..1a1321db137c 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2020 Intel Corporation
+ * Copyright (C) 2018-2020, 2022 Intel Corporation
*/
#ifndef __iwl_context_info_file_h__
#define __iwl_context_info_file_h__
@@ -177,6 +177,9 @@ void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans);
int iwl_pcie_init_fw_sec(struct iwl_trans *trans,
const struct fw_img *fw,
struct iwl_context_info_dram *ctxt_dram);
+void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans,
+ size_t size,
+ dma_addr_t *phys);
int iwl_pcie_ctxt_info_alloc_dma(struct iwl_trans *trans,
const void *data, u32 len,
struct iwl_dram_data *dram);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
index 898d5dcf1012..ef5baee6c9c5 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#include <linux/firmware.h>
#include "iwl-drv.h"
@@ -586,8 +586,14 @@ static int iwl_dbg_tlv_alloc_fragments(struct iwl_fw_runtime *fwrt,
fw_mon_cfg = &fwrt->trans->dbg.fw_mon_cfg[alloc_id];
fw_mon = &fwrt->trans->dbg.fw_mon_ini[alloc_id];
- if (fw_mon->num_frags ||
- fw_mon_cfg->buf_location !=
+ if (fw_mon->num_frags) {
+ for (i = 0; i < fw_mon->num_frags; i++)
+ memset(fw_mon->frags[i].block, 0,
+ fw_mon->frags[i].size);
+ return 0;
+ }
+
+ if (fw_mon_cfg->buf_location !=
cpu_to_le32(IWL_FW_INI_LOCATION_DRAM_PATH))
return 0;
@@ -738,7 +744,8 @@ static int iwl_dbg_tlv_update_dram(struct iwl_fw_runtime *fwrt,
if (le32_to_cpu(fwrt->trans->dbg.fw_mon_cfg[alloc_id].buf_location) !=
IWL_FW_INI_LOCATION_DRAM_PATH) {
- IWL_DEBUG_FW(fwrt, "DRAM_PATH is not supported alloc_id %u\n", alloc_id);
+ IWL_DEBUG_FW(fwrt, "WRT: alloc_id %u location is not in DRAM_PATH\n",
+ alloc_id);
return -1;
}
@@ -794,11 +801,14 @@ static void iwl_dbg_tlv_update_drams(struct iwl_fw_runtime *fwrt)
IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT))
return;
- dram_info->first_word = cpu_to_le32(DRAM_INFO_FIRST_MAGIC_WORD);
- dram_info->second_word = cpu_to_le32(DRAM_INFO_SECOND_MAGIC_WORD);
+ memset(dram_info, 0, sizeof(*dram_info));
for (i = IWL_FW_INI_ALLOCATION_ID_DBGC1;
i < IWL_FW_INI_ALLOCATION_NUM; i++) {
+ if (fwrt->trans->dbg.fw_mon_cfg[i].buf_location ==
+ IWL_FW_INI_LOCATION_INVALID)
+ continue;
+
ret = iwl_dbg_tlv_update_dram(fwrt, i, dram_info);
if (!ret)
dram_alloc = true;
@@ -808,11 +818,10 @@ static void iwl_dbg_tlv_update_drams(struct iwl_fw_runtime *fwrt)
i, ret);
}
- if (dram_alloc)
- IWL_DEBUG_FW(fwrt, "block data after %08x\n",
- dram_info->first_word);
- else
- memset(frags->block, 0, sizeof(*dram_info));
+ if (dram_alloc) {
+ dram_info->first_word = cpu_to_le32(DRAM_INFO_FIRST_MAGIC_WORD);
+ dram_info->second_word = cpu_to_le32(DRAM_INFO_SECOND_MAGIC_WORD);
+ }
}
static void iwl_dbg_tlv_send_hcmds(struct iwl_fw_runtime *fwrt,
@@ -1269,18 +1278,23 @@ static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt)
int ret, i;
u32 failed_alloc = 0;
- if (*ini_dest != IWL_FW_INI_LOCATION_INVALID)
- return;
-
- IWL_DEBUG_FW(fwrt,
- "WRT: Generating active triggers list, domain 0x%x\n",
- fwrt->trans->dbg.domains_bitmap);
+ if (*ini_dest == IWL_FW_INI_LOCATION_INVALID) {
+ IWL_DEBUG_FW(fwrt,
+ "WRT: Generating active triggers list, domain 0x%x\n",
+ fwrt->trans->dbg.domains_bitmap);
- for (i = 0; i < ARRAY_SIZE(fwrt->trans->dbg.time_point); i++) {
- struct iwl_dbg_tlv_time_point_data *tp =
- &fwrt->trans->dbg.time_point[i];
+ for (i = 0; i < ARRAY_SIZE(fwrt->trans->dbg.time_point); i++) {
+ struct iwl_dbg_tlv_time_point_data *tp =
+ &fwrt->trans->dbg.time_point[i];
- iwl_dbg_tlv_gen_active_trig_list(fwrt, tp);
+ iwl_dbg_tlv_gen_active_trig_list(fwrt, tp);
+ }
+ } else if (*ini_dest != IWL_FW_INI_LOCATION_DRAM_PATH) {
+ /* For DRAM, go through the loop below to clear all the buffers
+ * properly on restart, otherwise garbage may be left there and
+ * leak into new debug dumps.
+ */
+ return;
}
*ini_dest = IWL_FW_INI_LOCATION_INVALID;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index 34feb4d29adc..3d87d26845e7 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -158,12 +158,71 @@ static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc,
return 0;
}
+static inline char iwl_drv_get_step(int step)
+{
+ if (step == SILICON_Z_STEP)
+ return 'z';
+ return 'a' + step;
+}
+
+const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf)
+{
+ char mac_step, rf_step;
+ const char *rf, *cdb;
+
+ if (trans->cfg->fw_name_pre)
+ return trans->cfg->fw_name_pre;
+
+ if (WARN_ON(!trans->cfg->fw_name_mac))
+ return "unconfigured";
+
+ mac_step = iwl_drv_get_step(trans->hw_rev_step);
+
+ switch (CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
+ case IWL_CFG_RF_TYPE_HR1:
+ case IWL_CFG_RF_TYPE_HR2:
+ rf = "hr";
+ break;
+ case IWL_CFG_RF_TYPE_GF:
+ rf = "gf";
+ break;
+ case IWL_CFG_RF_TYPE_MR:
+ rf = "mr";
+ break;
+ case IWL_CFG_RF_TYPE_MS:
+ rf = "ms";
+ break;
+ case IWL_CFG_RF_TYPE_FM:
+ rf = "fm";
+ break;
+ case IWL_CFG_RF_TYPE_WH:
+ rf = "wh";
+ break;
+ default:
+ return "unknown-rf";
+ }
+
+ cdb = CSR_HW_RFID_IS_CDB(trans->hw_rf_id) ? "4" : "";
+
+ rf_step = iwl_drv_get_step(CSR_HW_RFID_STEP(trans->hw_rf_id));
+
+ scnprintf(buf, FW_NAME_PRE_BUFSIZE,
+ "iwlwifi-%s-%c0-%s%s-%c0",
+ trans->cfg->fw_name_mac, mac_step,
+ rf, cdb, rf_step);
+
+ return buf;
+}
+IWL_EXPORT_SYMBOL(iwl_drv_get_fwname_pre);
+
static void iwl_req_fw_callback(const struct firmware *ucode_raw,
void *context);
static int iwl_request_firmware(struct iwl_drv *drv, bool first)
{
const struct iwl_cfg *cfg = drv->trans->cfg;
+ char _fw_name_pre[FW_NAME_PRE_BUFSIZE];
+ const char *fw_name_pre;
if (drv->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
(drv->trans->hw_rev_step != SILICON_B_STEP &&
@@ -174,6 +233,8 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
return -EINVAL;
}
+ fw_name_pre = iwl_drv_get_fwname_pre(drv->trans, _fw_name_pre);
+
if (first)
drv->fw_index = cfg->ucode_api_max;
else
@@ -183,13 +244,13 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
IWL_ERR(drv, "no suitable firmware found!\n");
if (cfg->ucode_api_min == cfg->ucode_api_max) {
- IWL_ERR(drv, "%s%d is required\n", cfg->fw_name_pre,
+ IWL_ERR(drv, "%s-%d is required\n", fw_name_pre,
cfg->ucode_api_max);
} else {
- IWL_ERR(drv, "minimum version required: %s%d\n",
- cfg->fw_name_pre, cfg->ucode_api_min);
- IWL_ERR(drv, "maximum version supported: %s%d\n",
- cfg->fw_name_pre, cfg->ucode_api_max);
+ IWL_ERR(drv, "minimum version required: %s-%d\n",
+ fw_name_pre, cfg->ucode_api_min);
+ IWL_ERR(drv, "maximum version supported: %s-%d\n",
+ fw_name_pre, cfg->ucode_api_max);
}
IWL_ERR(drv,
@@ -197,8 +258,8 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
return -ENOENT;
}
- snprintf(drv->firmware_name, sizeof(drv->firmware_name), "%s%d.ucode",
- cfg->fw_name_pre, drv->fw_index);
+ snprintf(drv->firmware_name, sizeof(drv->firmware_name), "%s-%d.ucode",
+ fw_name_pre, drv->fw_index);
IWL_DEBUG_FW_INFO(drv, "attempting to load firmware '%s'\n",
drv->firmware_name);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
index 80073f973334..6c19989e4ab7 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2020-2021 Intel Corporation
+ * Copyright (C) 2005-2014, 2020-2021, 2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
*/
#ifndef __iwl_drv_h__
@@ -92,4 +92,8 @@ void iwl_drv_stop(struct iwl_drv *drv);
/* max retry for init flow */
#define IWL_MAX_INIT_RETRY 2
+#define FW_NAME_PRE_BUFSIZE 64
+struct iwl_trans;
+const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf);
+
#endif /* __iwl_drv_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h
index bedd78a47f67..4e4a60ddf9b2 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2021, 2023 Intel Corporation
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fh_h__
@@ -71,7 +71,7 @@
static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
unsigned int chnl)
{
- if (trans->trans_cfg->use_tfh) {
+ if (trans->trans_cfg->gen2) {
WARN_ON_ONCE(chnl >= 64);
return TFH_TFDQ_CBB_TABLE + 8 * chnl;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c
index 396f2c997da6..c60f9466c5fd 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2003-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2003-2014, 2018-2022 Intel Corporation
* Copyright (C) 2015-2016 Intel Deutschland GmbH
*/
#include <linux/delay.h>
@@ -72,6 +72,7 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
return value;
}
+ /* return as if we have a HW timeout/failure */
return 0x5a5a5a5a;
}
IWL_EXPORT_SYMBOL(iwl_read_direct32);
@@ -143,6 +144,7 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
return val;
}
+ /* return as if we have a HW timeout/failure */
return 0x5a5a5a5a;
}
IWL_EXPORT_SYMBOL(iwl_read_prph);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index 7dcb1c3ab728..8c23f57f5c89 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2005-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -173,34 +173,34 @@ enum iwl_nvm_channel_flags {
};
/**
- * enum iwl_reg_capa_flags - global flags applied for the whole regulatory
+ * enum iwl_reg_capa_flags_v1 - global flags applied for the whole regulatory
* domain.
- * @REG_CAPA_BF_CCD_LOW_BAND: Beam-forming or Cyclic Delay Diversity in the
+ * @REG_CAPA_V1_BF_CCD_LOW_BAND: Beam-forming or Cyclic Delay Diversity in the
* 2.4Ghz band is allowed.
- * @REG_CAPA_BF_CCD_HIGH_BAND: Beam-forming or Cyclic Delay Diversity in the
+ * @REG_CAPA_V1_BF_CCD_HIGH_BAND: Beam-forming or Cyclic Delay Diversity in the
* 5Ghz band is allowed.
- * @REG_CAPA_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed
+ * @REG_CAPA_V1_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed
* for this regulatory domain (valid only in 5Ghz).
- * @REG_CAPA_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed
+ * @REG_CAPA_V1_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed
* for this regulatory domain (valid only in 5Ghz).
- * @REG_CAPA_MCS_8_ALLOWED: 11ac with MCS 8 is allowed.
- * @REG_CAPA_MCS_9_ALLOWED: 11ac with MCS 9 is allowed.
- * @REG_CAPA_40MHZ_FORBIDDEN: 11n channel with a width of 40Mhz is forbidden
+ * @REG_CAPA_V1_MCS_8_ALLOWED: 11ac with MCS 8 is allowed.
+ * @REG_CAPA_V1_MCS_9_ALLOWED: 11ac with MCS 9 is allowed.
+ * @REG_CAPA_V1_40MHZ_FORBIDDEN: 11n channel with a width of 40Mhz is forbidden
* for this regulatory domain (valid only in 5Ghz).
- * @REG_CAPA_DC_HIGH_ENABLED: DC HIGH allowed.
- * @REG_CAPA_11AX_DISABLED: 11ax is forbidden for this regulatory domain.
+ * @REG_CAPA_V1_DC_HIGH_ENABLED: DC HIGH allowed.
+ * @REG_CAPA_V1_11AX_DISABLED: 11ax is forbidden for this regulatory domain.
*/
-enum iwl_reg_capa_flags {
- REG_CAPA_BF_CCD_LOW_BAND = BIT(0),
- REG_CAPA_BF_CCD_HIGH_BAND = BIT(1),
- REG_CAPA_160MHZ_ALLOWED = BIT(2),
- REG_CAPA_80MHZ_ALLOWED = BIT(3),
- REG_CAPA_MCS_8_ALLOWED = BIT(4),
- REG_CAPA_MCS_9_ALLOWED = BIT(5),
- REG_CAPA_40MHZ_FORBIDDEN = BIT(7),
- REG_CAPA_DC_HIGH_ENABLED = BIT(9),
- REG_CAPA_11AX_DISABLED = BIT(10),
-};
+enum iwl_reg_capa_flags_v1 {
+ REG_CAPA_V1_BF_CCD_LOW_BAND = BIT(0),
+ REG_CAPA_V1_BF_CCD_HIGH_BAND = BIT(1),
+ REG_CAPA_V1_160MHZ_ALLOWED = BIT(2),
+ REG_CAPA_V1_80MHZ_ALLOWED = BIT(3),
+ REG_CAPA_V1_MCS_8_ALLOWED = BIT(4),
+ REG_CAPA_V1_MCS_9_ALLOWED = BIT(5),
+ REG_CAPA_V1_40MHZ_FORBIDDEN = BIT(7),
+ REG_CAPA_V1_DC_HIGH_ENABLED = BIT(9),
+ REG_CAPA_V1_11AX_DISABLED = BIT(10),
+}; /* GEO_CHANNEL_CAPABILITIES_API_S_VER_1 */
/**
* enum iwl_reg_capa_flags_v2 - global flags applied for the whole regulatory
@@ -234,7 +234,31 @@ enum iwl_reg_capa_flags_v2 {
REG_CAPA_V2_WEATHER_DISABLED = BIT(7),
REG_CAPA_V2_40MHZ_ALLOWED = BIT(8),
REG_CAPA_V2_11AX_DISABLED = BIT(10),
-};
+}; /* GEO_CHANNEL_CAPABILITIES_API_S_VER_2 */
+
+/**
+ * enum iwl_reg_capa_flags_v4 - global flags applied for the whole regulatory
+ * domain.
+ * @REG_CAPA_V4_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed
+ * for this regulatory domain (valid only in 5Ghz).
+ * @REG_CAPA_V4_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed
+ * for this regulatory domain (valid only in 5Ghz).
+ * @REG_CAPA_V4_MCS_12_ALLOWED: 11ac with MCS 12 is allowed.
+ * @REG_CAPA_V4_MCS_13_ALLOWED: 11ac with MCS 13 is allowed.
+ * @REG_CAPA_V4_11BE_DISABLED: 11be is forbidden for this regulatory domain.
+ * @REG_CAPA_V4_11AX_DISABLED: 11ax is forbidden for this regulatory domain.
+ * @REG_CAPA_V4_320MHZ_ALLOWED: 11be channel with a width of 320Mhz is allowed
+ * for this regulatory domain (valid only in 5GHz).
+ */
+enum iwl_reg_capa_flags_v4 {
+ REG_CAPA_V4_160MHZ_ALLOWED = BIT(3),
+ REG_CAPA_V4_80MHZ_ALLOWED = BIT(4),
+ REG_CAPA_V4_MCS_12_ALLOWED = BIT(5),
+ REG_CAPA_V4_MCS_13_ALLOWED = BIT(6),
+ REG_CAPA_V4_11BE_DISABLED = BIT(8),
+ REG_CAPA_V4_11AX_DISABLED = BIT(13),
+ REG_CAPA_V4_320MHZ_ALLOWED = BIT(16),
+}; /* GEO_CHANNEL_CAPABILITIES_API_S_VER_4 */
/*
* API v2 for reg_capa_flags is relevant from version 6 and onwards of the
@@ -242,23 +266,33 @@ enum iwl_reg_capa_flags_v2 {
*/
#define REG_CAPA_V2_RESP_VER 6
+/* API v4 for reg_capa_flags is relevant from version 8 and onwards of the
+ * MCC update command response.
+ */
+#define REG_CAPA_V4_RESP_VER 8
+
/**
* struct iwl_reg_capa - struct for global regulatory capabilities, Used for
* handling the different APIs of reg_capa_flags.
*
* @allow_40mhz: 11n channel with a width of 40Mhz is allowed
- * for this regulatory domain (valid only in 5Ghz).
+ * for this regulatory domain.
* @allow_80mhz: 11ac channel with a width of 80Mhz is allowed
- * for this regulatory domain (valid only in 5Ghz).
+ * for this regulatory domain (valid only in 5 and 6 Ghz).
* @allow_160mhz: 11ac channel with a width of 160Mhz is allowed
- * for this regulatory domain (valid only in 5Ghz).
+ * for this regulatory domain (valid only in 5 and 6 Ghz).
+ * @allow_320mhz: 11be channel with a width of 320Mhz is allowed
+ * for this regulatory domain (valid only in 6 Ghz).
* @disable_11ax: 11ax is forbidden for this regulatory domain.
+ * @disable_11be: 11be is forbidden for this regulatory domain.
*/
struct iwl_reg_capa {
- u16 allow_40mhz;
- u16 allow_80mhz;
- u16 allow_160mhz;
- u16 disable_11ax;
+ bool allow_40mhz;
+ bool allow_80mhz;
+ bool allow_160mhz;
+ bool allow_320mhz;
+ bool disable_11ax;
+ bool disable_11be;
};
static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
@@ -464,6 +498,9 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans,
IEEE80211_VHT_MAX_AMPDU_1024K <<
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
+ if (!trans->cfg->ht_params->stbc)
+ vht_cap->cap &= ~IEEE80211_VHT_CAP_RXSTBC_MASK;
+
if (data->vht160_supported)
vht_cap->cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
IEEE80211_VHT_CAP_SHORT_GI_160;
@@ -479,7 +516,7 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans,
num_tx_ants = 1;
}
- if (num_tx_ants > 1)
+ if (trans->cfg->ht_params->stbc && num_tx_ants > 1)
vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC;
else
vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
@@ -643,8 +680,7 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK,
.phy_cap_info[1] =
IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK |
- IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK |
- IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK,
+ IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK,
.phy_cap_info[3] =
IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK |
IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |
@@ -853,6 +889,10 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
const struct iwl_fw *fw)
{
bool is_ap = iftype_data->types_mask & BIT(NL80211_IFTYPE_AP);
+ bool no_320;
+
+ no_320 = !trans->trans_cfg->integrated &&
+ trans->pcie_link_speed < PCI_EXP_LNKSTA_CLS_8_0GB;
if (!data->sku_cap_11be_enable || iwlwifi_mod_params.disable_11be)
iftype_data->eht_cap.has_eht = false;
@@ -879,8 +919,12 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK);
break;
case NL80211_BAND_6GHZ:
- iftype_data->eht_cap.eht_cap_elem.phy_cap_info[0] |=
- IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
+ if (!no_320) {
+ iftype_data->eht_cap.eht_cap_elem.phy_cap_info[0] |=
+ IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
+ iftype_data->eht_cap.eht_cap_elem.phy_cap_info[1] |=
+ IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK;
+ }
fallthrough;
case NL80211_BAND_5GHZ:
iftype_data->he_cap.he_cap_elem.phy_cap_info[0] |=
@@ -975,6 +1019,8 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[6] &=
~(IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK |
IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP);
+ iftype_data->eht_cap.eht_cap_elem.phy_cap_info[5] |=
+ IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF;
}
if (fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_BROADCAST_TWT))
@@ -986,6 +1032,13 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
iftype_data->vendor_elems.data = iwl_vendor_caps;
iftype_data->vendor_elems.len = ARRAY_SIZE(iwl_vendor_caps);
}
+
+ if (!trans->cfg->ht_params->stbc) {
+ iftype_data->he_cap.he_cap_elem.phy_cap_info[2] &=
+ ~IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;
+ iftype_data->he_cap.he_cap_elem.phy_cap_info[7] &=
+ ~IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ;
+ }
}
static void iwl_init_he_hw_capab(struct iwl_trans *trans,
@@ -1521,27 +1574,41 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
if (!reg_capa.allow_160mhz)
flags |= NL80211_RRF_NO_160MHZ;
+
+ if (!reg_capa.allow_320mhz)
+ flags |= NL80211_RRF_NO_320MHZ;
}
+
if (reg_capa.disable_11ax)
flags |= NL80211_RRF_NO_HE;
+ if (reg_capa.disable_11be)
+ flags |= NL80211_RRF_NO_EHT;
+
return flags;
}
-static struct iwl_reg_capa iwl_get_reg_capa(u16 flags, u8 resp_ver)
+static struct iwl_reg_capa iwl_get_reg_capa(u32 flags, u8 resp_ver)
{
- struct iwl_reg_capa reg_capa;
-
- if (resp_ver >= REG_CAPA_V2_RESP_VER) {
+ struct iwl_reg_capa reg_capa = {};
+
+ if (resp_ver >= REG_CAPA_V4_RESP_VER) {
+ reg_capa.allow_40mhz = true;
+ reg_capa.allow_80mhz = flags & REG_CAPA_V4_80MHZ_ALLOWED;
+ reg_capa.allow_160mhz = flags & REG_CAPA_V4_160MHZ_ALLOWED;
+ reg_capa.allow_320mhz = flags & REG_CAPA_V4_320MHZ_ALLOWED;
+ reg_capa.disable_11ax = flags & REG_CAPA_V4_11AX_DISABLED;
+ reg_capa.disable_11be = flags & REG_CAPA_V4_11BE_DISABLED;
+ } else if (resp_ver >= REG_CAPA_V2_RESP_VER) {
reg_capa.allow_40mhz = flags & REG_CAPA_V2_40MHZ_ALLOWED;
reg_capa.allow_80mhz = flags & REG_CAPA_V2_80MHZ_ALLOWED;
reg_capa.allow_160mhz = flags & REG_CAPA_V2_160MHZ_ALLOWED;
reg_capa.disable_11ax = flags & REG_CAPA_V2_11AX_DISABLED;
} else {
- reg_capa.allow_40mhz = !(flags & REG_CAPA_40MHZ_FORBIDDEN);
- reg_capa.allow_80mhz = flags & REG_CAPA_80MHZ_ALLOWED;
- reg_capa.allow_160mhz = flags & REG_CAPA_160MHZ_ALLOWED;
- reg_capa.disable_11ax = flags & REG_CAPA_11AX_DISABLED;
+ reg_capa.allow_40mhz = !(flags & REG_CAPA_V1_40MHZ_FORBIDDEN);
+ reg_capa.allow_80mhz = flags & REG_CAPA_V1_80MHZ_ALLOWED;
+ reg_capa.allow_160mhz = flags & REG_CAPA_V1_160MHZ_ALLOWED;
+ reg_capa.disable_11ax = flags & REG_CAPA_V1_11AX_DISABLED;
}
return reg_capa;
}
@@ -1549,7 +1616,7 @@ static struct iwl_reg_capa iwl_get_reg_capa(u16 flags, u8 resp_ver)
struct ieee80211_regdomain *
iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int num_of_ch, __le32 *channels, u16 fw_mcc,
- u16 geo_info, u16 cap, u8 resp_ver)
+ u16 geo_info, u32 cap, u8 resp_ver)
{
int ch_idx;
u16 ch_flags;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h
index e01f7751cf11..c79f72d54482 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2015, 2018-2021 Intel Corporation
+ * Copyright (C) 2005-2015, 2018-2022 Intel Corporation
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_nvm_parse_h__
@@ -50,7 +50,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
struct ieee80211_regdomain *
iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int num_of_ch, __le32 *channels, u16 fw_mcc,
- u16 geo_info, u16 cap, u8 resp_ver);
+ u16 geo_info, u32 cap, u8 resp_ver);
/**
* struct iwl_nvm_section - describes an NVM section in memory.
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
index 0dfe00eae05d..6dd381ff0f9e 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016 Intel Deutschland GmbH
*/
@@ -486,6 +486,10 @@ enum {
#define FSEQ_ALIVE_TOKEN 0xA340F0
#define FSEQ_CNVI_ID 0xA3408C
#define FSEQ_CNVR_ID 0xA34090
+#define FSEQ_PREV_CNVIO_INIT_VERSION 0xA34084
+#define FSEQ_WIFI_FSEQ_VERSION 0xA34040
+#define FSEQ_BT_FSEQ_VERSION 0xA34044
+#define FSEQ_CLASS_TP_VERSION 0xA34078
#define IWL_D3_SLEEP_STATUS_SUSPEND 0xD3
#define IWL_D3_SLEEP_STATUS_RESUME 0xD0
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
index b1af9359cea5..4bd759432d44 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
- * Copyright (C) 2019-2021 Intel Corporation
+ * Copyright (C) 2019-2021, 2023 Intel Corporation
*/
#include <linux/kernel.h>
#include <linux/bsearch.h>
@@ -42,7 +42,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty);
- if (trans->trans_cfg->use_tfh) {
+ if (trans->trans_cfg->gen2) {
trans->txqs.tfd.addr_size = 64;
trans->txqs.tfd.max_tbs = IWL_TFH_NUM_TBS;
trans->txqs.tfd.size = sizeof(struct iwl_tfh_tfd);
@@ -101,7 +101,7 @@ int iwl_trans_init(struct iwl_trans *trans)
/* Some things must not change even if the config does */
WARN_ON(trans->txqs.tfd.addr_size !=
- (trans->trans_cfg->use_tfh ? 64 : 36));
+ (trans->trans_cfg->gen2 ? 64 : 36));
snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name),
"iwl_cmd_pool:%s", dev_name(trans->dev));
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index 9f1228b5a384..d02943d0ea62 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -459,6 +459,24 @@ struct iwl_trans_rxq_dma_data {
u64 ur_bd_cb;
};
+/* maximal number of DRAM MAP entries supported by FW */
+#define IPC_DRAM_MAP_ENTRY_NUM_MAX 64
+
+/**
+ * struct iwl_pnvm_image - contains info about the parsed pnvm image
+ * @chunks: array of pointers to pnvm payloads and their sizes
+ * @n_chunks: the number of the pnvm payloads.
+ * @version: the version of the loaded PNVM image
+ */
+struct iwl_pnvm_image {
+ struct {
+ const void *data;
+ u32 len;
+ } chunks[IPC_DRAM_MAP_ENTRY_NUM_MAX];
+ u32 n_chunks;
+ u32 version;
+};
+
/**
* struct iwl_trans_ops - transport specific operations
*
@@ -541,8 +559,11 @@ struct iwl_trans_rxq_dma_data {
* Note that the transport must fill in the proper file headers.
* @debugfs_cleanup: used in the driver unload flow to make a proper cleanup
* of the trans debugfs
+ * @load_pnvm: save the pnvm data in DRAM
* @set_pnvm: set the pnvm data in the prph scratch buffer, inside the
* context info.
+ * @load_reduce_power: copy reduce power table to the corresponding DRAM memory
+ * @set_reduce_power: set reduce power table addresses in the sratch buffer
* @interrupts: disable/enable interrupts to transport
*/
struct iwl_trans_ops {
@@ -614,9 +635,17 @@ struct iwl_trans_ops {
void *sanitize_ctx);
void (*debugfs_cleanup)(struct iwl_trans *trans);
void (*sync_nmi)(struct iwl_trans *trans);
- int (*set_pnvm)(struct iwl_trans *trans, const void *data, u32 len);
- int (*set_reduce_power)(struct iwl_trans *trans,
- const void *data, u32 len);
+ int (*load_pnvm)(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *pnvm_payloads,
+ const struct iwl_ucode_capabilities *capa);
+ void (*set_pnvm)(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa);
+ int (*load_reduce_power)(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *payloads,
+ const struct iwl_ucode_capabilities *capa);
+ void (*set_reduce_power)(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa);
+
void (*interrupts)(struct iwl_trans *trans, bool enable);
int (*imr_dma_data)(struct iwl_trans *trans,
u32 dst_addr, u64 src_addr,
@@ -705,6 +734,19 @@ struct iwl_dram_data {
};
/**
+ * @drams: array of several DRAM areas that contains the pnvm and power
+ * reduction table payloads.
+ * @n_regions: number of DRAM regions that were allocated
+ * @prph_scratch_mem_desc: points to a structure allocated in dram,
+ * designed to show FW where all the payloads are.
+ */
+struct iwl_dram_regions {
+ struct iwl_dram_data drams[IPC_DRAM_MAP_ENTRY_NUM_MAX];
+ struct iwl_dram_data prph_scratch_mem_desc;
+ u8 n_regions;
+};
+
+/**
* struct iwl_fw_mon - fw monitor per allocation id
* @num_frags: number of fragments
* @frags: an array of DRAM buffer fragments
@@ -1004,6 +1046,8 @@ struct iwl_trans_txqs {
* @hw_rev_step: The mac step of the HW
* @pm_support: set to true in start_hw if link pm is supported
* @ltr_enabled: set to true if the LTR is enabled
+ * @fail_to_parse_pnvm_image: set to true if pnvm parsing failed
+ * @failed_to_load_reduce_power_image: set to true if pnvm loading failed
* @wide_cmd_header: true when ucode supports wide command header format
* @wait_command_queue: wait queue for sync commands
* @num_rx_queues: number of RX queues allocated by the transport;
@@ -1023,6 +1067,8 @@ struct iwl_trans_txqs {
* @iwl_trans_txqs: transport tx queues data.
* @mbx_addr_0_step: step address data 0
* @mbx_addr_1_step: step address data 1
+ * @pcie_link_speed: current PCIe link speed (%PCI_EXP_LNKSTA_CLS_*),
+ * only valid for discrete (not integrated) NICs
*/
struct iwl_trans {
bool csme_own;
@@ -1051,7 +1097,9 @@ struct iwl_trans {
bool pm_support;
bool ltr_enabled;
u8 pnvm_loaded:1;
+ u8 fail_to_parse_pnvm_image:1;
u8 reduce_power_loaded:1;
+ u8 failed_to_load_reduce_power_image:1;
const struct iwl_hcmd_arr *command_groups;
int command_groups_size;
@@ -1083,6 +1131,8 @@ struct iwl_trans {
u32 mbx_addr_0_step;
u32 mbx_addr_1_step;
+ u8 pcie_link_speed;
+
/* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */
char trans_specific[] __aligned(sizeof(void *));
@@ -1160,7 +1210,7 @@ static inline int iwl_trans_d3_suspend(struct iwl_trans *trans, bool test,
{
might_sleep();
if (!trans->ops->d3_suspend)
- return 0;
+ return -EOPNOTSUPP;
return trans->ops->d3_suspend(trans, test, reset);
}
@@ -1171,7 +1221,7 @@ static inline int iwl_trans_d3_resume(struct iwl_trans *trans,
{
might_sleep();
if (!trans->ops->d3_resume)
- return 0;
+ return -EOPNOTSUPP;
return trans->ops->d3_resume(trans, status, test, reset);
}
@@ -1515,33 +1565,34 @@ static inline void iwl_trans_sync_nmi(struct iwl_trans *trans)
void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr,
u32 sw_err_bit);
-static inline int iwl_trans_set_pnvm(struct iwl_trans *trans,
- const void *data, u32 len)
+static inline int iwl_trans_load_pnvm(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *pnvm_data,
+ const struct iwl_ucode_capabilities *capa)
{
- if (trans->ops->set_pnvm) {
- int ret = trans->ops->set_pnvm(trans, data, len);
-
- if (ret)
- return ret;
- }
-
- trans->pnvm_loaded = true;
-
- return 0;
+ return trans->ops->load_pnvm(trans, pnvm_data, capa);
}
-static inline int iwl_trans_set_reduce_power(struct iwl_trans *trans,
- const void *data, u32 len)
+static inline void iwl_trans_set_pnvm(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa)
{
- if (trans->ops->set_reduce_power) {
- int ret = trans->ops->set_reduce_power(trans, data, len);
+ if (trans->ops->set_pnvm)
+ trans->ops->set_pnvm(trans, capa);
+}
- if (ret)
- return ret;
- }
+static inline int iwl_trans_load_reduce_power
+ (struct iwl_trans *trans,
+ const struct iwl_pnvm_image *payloads,
+ const struct iwl_ucode_capabilities *capa)
+{
+ return trans->ops->load_reduce_power(trans, payloads, capa);
+}
- trans->reduce_power_loaded = true;
- return 0;
+static inline void
+iwl_trans_set_reduce_power(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa)
+{
+ if (trans->ops->set_reduce_power)
+ trans->ops->set_reduce_power(trans, capa);
}
static inline bool iwl_trans_dbg_ini_valid(struct iwl_trans *trans)
@@ -1566,6 +1617,11 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
int iwl_trans_init(struct iwl_trans *trans);
void iwl_trans_free(struct iwl_trans *trans);
+static inline bool iwl_trans_is_hw_error_value(u32 val)
+{
+ return ((val & ~0xf) == 0xa5a5a5a0) || ((val & ~0xf) == 0x5a5a5a50);
+}
+
/*****************************************************
* driver (transport) register/unregister functions
******************************************************/
diff --git a/drivers/net/wireless/intel/iwlwifi/mei/main.c b/drivers/net/wireless/intel/iwlwifi/mei/main.c
index 0a29fb013005..54445f39fd55 100644
--- a/drivers/net/wireless/intel/iwlwifi/mei/main.c
+++ b/drivers/net/wireless/intel/iwlwifi/mei/main.c
@@ -1791,9 +1791,8 @@ int iwl_mei_register(void *priv, const struct iwl_mei_ops *ops)
if (iwl_mei_is_connected()) {
if (mei->amt_enabled)
iwl_mei_send_sap_msg(mei->cldev,
- SAP_MSG_NOTIF_WIFIDR_UP,
- false);
- ops->rfkill(priv, mei->link_prot_state);
+ SAP_MSG_NOTIF_WIFIDR_UP);
+ ops->rfkill(priv, mei->link_prot_state, false);
}
}
ret = 0;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/binding.c b/drivers/net/wireless/intel/iwlwifi/mvm/binding.c
index ef50ccabcc73..458b97930059 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/binding.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/binding.c
@@ -32,7 +32,7 @@ static int iwl_mvm_binding_cmd(struct iwl_mvm *mvm, u32 action,
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT)) {
size = sizeof(cmd);
- cmd.lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm->fw,
+ cmd.lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm,
phyctxt->channel->band));
} else {
size = IWL_BINDING_CMD_SIZE_V1;
@@ -164,3 +164,11 @@ int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
return ret;
}
+
+u32 iwl_mvm_get_lmac_id(struct iwl_mvm *mvm, enum nl80211_band band)
+{
+ if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_CDB_SUPPORT) ||
+ band == NL80211_BAND_2GHZ)
+ return IWL_LMAC_24G_INDEX;
+ return IWL_LMAC_5G_INDEX;
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
index c604f9f39b24..243eccc68cb0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
- * Copyright (C) 2013-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2013-2014, 2018-2023 Intel Corporation
* Copyright (C) 2015 Intel Deutschland GmbH
*/
#ifndef __MVM_CONSTANTS_H
@@ -109,10 +109,6 @@
#define IWL_MVM_USE_TWT true
#define IWL_MVM_AMPDU_CONSEC_DROPS_DELBA 20
#define IWL_MVM_USE_NSSN_SYNC 0
-#define IWL_MVM_PHY_FILTER_CHAIN_A 0
-#define IWL_MVM_PHY_FILTER_CHAIN_B 0
-#define IWL_MVM_PHY_FILTER_CHAIN_C 0
-#define IWL_MVM_PHY_FILTER_CHAIN_D 0
#define IWL_MVM_FTM_INITIATOR_ENABLE_SMOOTH false
#define IWL_MVM_FTM_INITIATOR_SMOOTH_ALPHA 40
/* 20016 pSec is 6 meter RTT, meaning 3 meter range */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index 6d1007f24b4a..f6488b4bbe68 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -1380,6 +1380,14 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
return __iwl_mvm_suspend(hw, wowlan, false);
}
+struct iwl_multicast_key_data {
+ u8 key[WOWLAN_KEY_MAX_SIZE];
+ u8 len;
+ u8 flags;
+ u8 id;
+ u8 ipn[6];
+};
+
/* converted data from the different status responses */
struct iwl_wowlan_status_data {
u64 replay_ctr;
@@ -1398,7 +1406,8 @@ struct iwl_wowlan_status_data {
u8 key[WOWLAN_KEY_MAX_SIZE];
u8 len;
u8 flags;
- } gtk;
+ u8 id;
+ } gtk[WOWLAN_GTK_KEYS_NUM];
struct {
/*
@@ -1428,12 +1437,7 @@ struct iwl_wowlan_status_data {
} tkip, aes;
} ptk;
- struct {
- u64 ipn;
- u8 key[WOWLAN_KEY_MAX_SIZE];
- u8 len;
- u8 flags;
- } igtk;
+ struct iwl_multicast_key_data igtk;
u8 *wake_packet;
};
@@ -1758,7 +1762,7 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,
s8 new_key_id = -1;
if (status->num_of_gtk_rekeys)
- new_key_id = status->gtk.flags &
+ new_key_id = status->gtk[0].flags &
IWL_WOWLAN_GTK_IDX_MASK;
/* Don't install a new key's value to an old key */
@@ -1777,20 +1781,18 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,
struct iwl_mvm_d3_gtk_iter_data {
struct iwl_mvm *mvm;
struct iwl_wowlan_status_data *status;
- void *last_gtk;
- u32 cipher;
- bool find_phase, unhandled_cipher;
+ u32 gtk_cipher, igtk_cipher;
+ bool unhandled_cipher, igtk_support;
int num_keys;
};
-static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key,
- void *_data)
+static void iwl_mvm_d3_find_last_keys(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key,
+ void *_data)
{
struct iwl_mvm_d3_gtk_iter_data *data = _data;
- struct iwl_wowlan_status_data *status = data->status;
if (data->unhandled_cipher)
return;
@@ -1805,51 +1807,230 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
case WLAN_CIPHER_SUITE_GCMP_256:
case WLAN_CIPHER_SUITE_TKIP:
/* we support these */
+ data->gtk_cipher = key->cipher;
+ break;
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+ case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ /* we support these */
+ if (data->igtk_support &&
+ (key->keyidx == 4 || key->keyidx == 5)) {
+ data->igtk_cipher = key->cipher;
+ } else {
+ data->unhandled_cipher = true;
+ return;
+ }
break;
default:
- /* everything else (even CMAC for MFP) - disconnect from AP */
+ /* everything else - disconnect from AP */
data->unhandled_cipher = true;
return;
}
data->num_keys++;
+}
- /*
- * pairwise key - update sequence counters only;
- * note that this assumes no TDLS sessions are active
- */
- if (sta) {
- if (data->find_phase)
- return;
+static void
+iwl_mvm_d3_set_igtk_bigtk_ipn(const struct iwl_multicast_key_data *key,
+ struct ieee80211_key_seq *seq, u32 cipher)
+{
+ switch (cipher) {
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+ BUILD_BUG_ON(sizeof(seq->aes_gmac.pn) != sizeof(key->ipn));
+ memcpy(seq->aes_gmac.pn, key->ipn, sizeof(seq->aes_gmac.pn));
+ break;
+ case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+ BUILD_BUG_ON(sizeof(seq->aes_cmac.pn) != sizeof(key->ipn));
+ memcpy(seq->aes_cmac.pn, key->ipn, sizeof(seq->aes_cmac.pn));
+ break;
+ }
+}
+
+static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key,
+ void *_data)
+{
+ struct iwl_mvm_d3_gtk_iter_data *data = _data;
+ struct iwl_wowlan_status_data *status = data->status;
+ s8 keyidx;
+
+ if (data->unhandled_cipher)
+ return;
- switch (key->cipher) {
- case WLAN_CIPHER_SUITE_CCMP:
- case WLAN_CIPHER_SUITE_GCMP:
- case WLAN_CIPHER_SUITE_GCMP_256:
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ /* ignore WEP completely, nothing to do */
+ return;
+ case WLAN_CIPHER_SUITE_CCMP:
+ case WLAN_CIPHER_SUITE_GCMP:
+ case WLAN_CIPHER_SUITE_GCMP_256:
+ if (sta) {
atomic64_set(&key->tx_pn, status->ptk.aes.tx_pn);
iwl_mvm_set_aes_ptk_rx_seq(data->mvm, status, sta, key);
- break;
- case WLAN_CIPHER_SUITE_TKIP:
+ return;
+ }
+ fallthrough;
+ case WLAN_CIPHER_SUITE_TKIP:
+ if (sta) {
atomic64_set(&key->tx_pn, status->ptk.tkip.tx_pn);
iwl_mvm_set_key_rx_seq_tids(key, status->ptk.tkip.seq);
- break;
+ return;
}
+ keyidx = key->keyidx;
+ /* The current key is always sent by the FW, even if it wasn't
+ * rekeyed during D3.
+ * We remove an existing key if it has the same index as
+ * a new key
+ */
+ if (status->num_of_gtk_rekeys &&
+ ((status->gtk[0].len && keyidx == status->gtk[0].id) ||
+ (status->gtk[1].len && keyidx == status->gtk[1].id))) {
+ ieee80211_remove_key(key);
+ } else {
+ iwl_mvm_set_key_rx_seq(key, data->status, false);
+ }
+ break;
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+ case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ if (key->keyidx == 4 || key->keyidx == 5) {
+ /* remove rekeyed key */
+ if (status->num_of_gtk_rekeys) {
+ ieee80211_remove_key(key);
+ } else {
+ struct ieee80211_key_seq seq;
- /* that's it for this key */
- return;
+ iwl_mvm_d3_set_igtk_bigtk_ipn(&status->igtk,
+ &seq,
+ key->cipher);
+ ieee80211_set_key_rx_seq(key, 0, &seq);
+ }
+ }
}
+}
- if (data->find_phase) {
- data->last_gtk = key;
- data->cipher = key->cipher;
- return;
+static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status,
+ struct ieee80211_vif *vif,
+ struct iwl_mvm *mvm, u32 gtk_cipher)
+{
+ int i;
+ struct ieee80211_key_conf *key;
+ struct {
+ struct ieee80211_key_conf conf;
+ u8 key[32];
+ } conf = {
+ .conf.cipher = gtk_cipher,
+ };
+
+ BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP);
+ BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP);
+ BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256);
+ BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP);
+ BUILD_BUG_ON(sizeof(conf.key) < sizeof(status->gtk[0].key));
+
+ switch (gtk_cipher) {
+ case WLAN_CIPHER_SUITE_CCMP:
+ case WLAN_CIPHER_SUITE_GCMP:
+ conf.conf.keylen = WLAN_KEY_LEN_CCMP;
+ break;
+ case WLAN_CIPHER_SUITE_GCMP_256:
+ conf.conf.keylen = WLAN_KEY_LEN_GCMP_256;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ conf.conf.keylen = WLAN_KEY_LEN_TKIP;
+ break;
+ default:
+ WARN_ON(1);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(status->gtk); i++) {
+ if (!status->gtk[i].len)
+ continue;
+
+ conf.conf.keyidx = status->gtk[i].id;
+ IWL_DEBUG_WOWLAN(mvm,
+ "Received from FW GTK cipher %d, key index %d\n",
+ conf.conf.cipher, conf.conf.keyidx);
+ memcpy(conf.conf.key, status->gtk[i].key,
+ sizeof(status->gtk[i].key));
+
+ key = ieee80211_gtk_rekey_add(vif, &conf.conf);
+ if (IS_ERR(key))
+ return false;
+ iwl_mvm_set_key_rx_seq_idx(key, status, i);
}
- if (data->status->num_of_gtk_rekeys)
- ieee80211_remove_key(key);
+ return true;
+}
+
+static bool
+iwl_mvm_d3_igtk_bigtk_rekey_add(struct iwl_wowlan_status_data *status,
+ struct ieee80211_vif *vif, u32 cipher,
+ struct iwl_multicast_key_data *key_data)
+{
+ struct ieee80211_key_conf *key_config;
+ struct {
+ struct ieee80211_key_conf conf;
+ u8 key[WOWLAN_KEY_MAX_SIZE];
+ } conf = {
+ .conf.cipher = cipher,
+ .conf.keyidx = key_data->id,
+ };
+ struct ieee80211_key_seq seq;
+
+ if (!key_data->len)
+ return true;
+
+ iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, conf.conf.cipher);
+
+ switch (cipher) {
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+ conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_128;
+ break;
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+ conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_256;
+ break;
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ conf.conf.keylen = WLAN_KEY_LEN_AES_CMAC;
+ break;
+ case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+ conf.conf.keylen = WLAN_KEY_LEN_BIP_CMAC_256;
+ break;
+ default:
+ WARN_ON(1);
+ }
+ BUILD_BUG_ON(sizeof(conf.key) < sizeof(key_data->key));
+ memcpy(conf.conf.key, key_data->key, conf.conf.keylen);
+
+ key_config = ieee80211_gtk_rekey_add(vif, &conf.conf);
+ if (IS_ERR(key_config))
+ return false;
+ ieee80211_set_key_rx_seq(key_config, 0, &seq);
+ return true;
+}
+
+static int iwl_mvm_lookup_wowlan_status_ver(struct iwl_mvm *mvm)
+{
+ u8 notif_ver;
+
+ if (!fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL))
+ return 6;
+
+ /* default to 7 (when we have IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL) */
+ notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP,
+ WOWLAN_GET_STATUSES, 0);
+ if (!notif_ver)
+ notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
+ WOWLAN_GET_STATUSES, 7);
- if (data->last_gtk == key)
- iwl_mvm_set_key_rx_seq(key, data->status, false);
+ return notif_ver;
}
static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
@@ -1871,71 +2052,41 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
if (status->wakeup_reasons & disconnection_reasons)
return false;
+ if (iwl_mvm_lookup_wowlan_status_ver(mvm) > 6 ||
+ iwl_fw_lookup_notif_ver(mvm->fw, PROT_OFFLOAD_GROUP,
+ WOWLAN_INFO_NOTIFICATION,
+ 0))
+ gtkdata.igtk_support = true;
+
/* find last GTK that we used initially, if any */
- gtkdata.find_phase = true;
ieee80211_iter_keys(mvm->hw, vif,
- iwl_mvm_d3_update_keys, &gtkdata);
+ iwl_mvm_d3_find_last_keys, &gtkdata);
/* not trying to keep connections with MFP/unhandled ciphers */
if (gtkdata.unhandled_cipher)
return false;
if (!gtkdata.num_keys)
goto out;
- if (!gtkdata.last_gtk)
- return false;
/*
* invalidate all other GTKs that might still exist and update
* the one that we used
*/
- gtkdata.find_phase = false;
ieee80211_iter_keys(mvm->hw, vif,
iwl_mvm_d3_update_keys, &gtkdata);
- IWL_DEBUG_WOWLAN(mvm, "num of GTK rekeying %d\n",
- status->num_of_gtk_rekeys);
if (status->num_of_gtk_rekeys) {
- struct ieee80211_key_conf *key;
- struct {
- struct ieee80211_key_conf conf;
- u8 key[32];
- } conf = {
- .conf.cipher = gtkdata.cipher,
- .conf.keyidx =
- status->gtk.flags & IWL_WOWLAN_GTK_IDX_MASK,
- };
- __be64 replay_ctr;
+ __be64 replay_ctr = cpu_to_be64(status->replay_ctr);
- IWL_DEBUG_WOWLAN(mvm,
- "Received from FW GTK cipher %d, key index %d\n",
- conf.conf.cipher, conf.conf.keyidx);
-
- BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP);
- BUILD_BUG_ON(sizeof(conf.key) < sizeof(status->gtk.key));
+ IWL_DEBUG_WOWLAN(mvm, "num of GTK rekeying %d\n",
+ status->num_of_gtk_rekeys);
- memcpy(conf.conf.key, status->gtk.key, sizeof(status->gtk.key));
-
- switch (gtkdata.cipher) {
- case WLAN_CIPHER_SUITE_CCMP:
- case WLAN_CIPHER_SUITE_GCMP:
- conf.conf.keylen = WLAN_KEY_LEN_CCMP;
- break;
- case WLAN_CIPHER_SUITE_GCMP_256:
- conf.conf.keylen = WLAN_KEY_LEN_GCMP_256;
- break;
- case WLAN_CIPHER_SUITE_TKIP:
- conf.conf.keylen = WLAN_KEY_LEN_TKIP;
- break;
- }
-
- key = ieee80211_gtk_rekey_add(vif, &conf.conf);
- if (IS_ERR(key))
+ if (!iwl_mvm_gtk_rekey(status, vif, mvm, gtkdata.gtk_cipher))
return false;
- iwl_mvm_set_key_rx_seq(key, status, true);
- replay_ctr = cpu_to_be64(status->replay_ctr);
+ if (!iwl_mvm_d3_igtk_bigtk_rekey_add(status, vif,
+ gtkdata.igtk_cipher,
+ &status->igtk))
+ return false;
ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,
(void *)&replay_ctr, GFP_KERNEL);
@@ -1955,60 +2106,70 @@ out:
static void iwl_mvm_convert_gtk_v2(struct iwl_wowlan_status_data *status,
struct iwl_wowlan_gtk_status_v2 *data)
{
- BUILD_BUG_ON(sizeof(status->gtk.key) < sizeof(data->key));
+ BUILD_BUG_ON(sizeof(status->gtk[0].key) < sizeof(data->key));
BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +
sizeof(data->tkip_mic_key) >
- sizeof(status->gtk.key));
+ sizeof(status->gtk[0].key));
- status->gtk.len = data->key_len;
- status->gtk.flags = data->key_flags;
+ status->gtk[0].len = data->key_len;
+ status->gtk[0].flags = data->key_flags;
- memcpy(status->gtk.key, data->key, sizeof(data->key));
+ memcpy(status->gtk[0].key, data->key, sizeof(data->key));
/* if it's as long as the TKIP encryption key, copy MIC key */
- if (status->gtk.len == NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
- memcpy(status->gtk.key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
+ if (status->gtk[0].len == NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
+ memcpy(status->gtk[0].key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
data->tkip_mic_key, sizeof(data->tkip_mic_key));
}
static void iwl_mvm_convert_gtk_v3(struct iwl_wowlan_status_data *status,
struct iwl_wowlan_gtk_status_v3 *data)
{
- /* The parts we need are identical in v2 and v3 */
-#define CHECK(_f) do { \
- BUILD_BUG_ON(offsetof(struct iwl_wowlan_gtk_status_v2, _f) != \
- offsetof(struct iwl_wowlan_gtk_status_v3, _f)); \
- BUILD_BUG_ON(offsetofend(struct iwl_wowlan_gtk_status_v2, _f) !=\
- offsetofend(struct iwl_wowlan_gtk_status_v3, _f)); \
-} while (0)
+ int data_idx, status_idx = 0;
- CHECK(key);
- CHECK(key_len);
- CHECK(key_flags);
- CHECK(tkip_mic_key);
-#undef CHECK
+ BUILD_BUG_ON(sizeof(status->gtk[0].key) < sizeof(data[0].key));
+ BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +
+ sizeof(data[0].tkip_mic_key) >
+ sizeof(status->gtk[0].key));
+ BUILD_BUG_ON(ARRAY_SIZE(status->gtk) < WOWLAN_GTK_KEYS_NUM);
+ for (data_idx = 0; data_idx < ARRAY_SIZE(status->gtk); data_idx++) {
+ if (!(data[data_idx].key_len))
+ continue;
+ status->gtk[status_idx].len = data[data_idx].key_len;
+ status->gtk[status_idx].flags = data[data_idx].key_flags;
+ status->gtk[status_idx].id = status->gtk[status_idx].flags &
+ IWL_WOWLAN_GTK_IDX_MASK;
- iwl_mvm_convert_gtk_v2(status, (void *)data);
+ memcpy(status->gtk[status_idx].key, data[data_idx].key,
+ sizeof(data[data_idx].key));
+
+ /* if it's as long as the TKIP encryption key, copy MIC key */
+ if (status->gtk[status_idx].len ==
+ NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
+ memcpy(status->gtk[status_idx].key +
+ NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
+ data[data_idx].tkip_mic_key,
+ sizeof(data[data_idx].tkip_mic_key));
+ status_idx++;
+ }
}
static void iwl_mvm_convert_igtk(struct iwl_wowlan_status_data *status,
struct iwl_wowlan_igtk_status *data)
{
- const u8 *ipn = data->ipn;
-
BUILD_BUG_ON(sizeof(status->igtk.key) < sizeof(data->key));
+ if (!data->key_len)
+ return;
+
status->igtk.len = data->key_len;
status->igtk.flags = data->key_flags;
+ status->igtk.id = u32_get_bits(data->key_flags,
+ IWL_WOWLAN_IGTK_BIGTK_IDX_MASK)
+ + WOWLAN_IGTK_MIN_INDEX;
memcpy(status->igtk.key, data->key, sizeof(data->key));
-
- status->igtk.ipn = ((u64)ipn[5] << 0) |
- ((u64)ipn[4] << 8) |
- ((u64)ipn[3] << 16) |
- ((u64)ipn[2] << 24) |
- ((u64)ipn[1] << 32) |
- ((u64)ipn[0] << 40);
+ memcpy(status->igtk.ipn, data->ipn, sizeof(data->ipn));
}
static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
@@ -2031,7 +2192,7 @@ static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
}
iwl_mvm_convert_key_counters_v5(status, &data->gtk[0].sc);
- iwl_mvm_convert_gtk_v3(status, &data->gtk[0]);
+ iwl_mvm_convert_gtk_v3(status, data->gtk);
iwl_mvm_convert_igtk(status, &data->igtk[0]);
status->replay_ctr = le64_to_cpu(data->replay_ctr);
@@ -2139,14 +2300,9 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
len = iwl_rx_packet_payload_len(cmd.resp_pkt);
/* default to 7 (when we have IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL) */
- notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP,
- WOWLAN_GET_STATUSES, 0);
- if (!notif_ver)
- notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
- WOWLAN_GET_STATUSES, 7);
+ notif_ver = iwl_mvm_lookup_wowlan_status_ver(mvm);
- if (!fw_has_api(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL)) {
+ if (notif_ver < 7) {
struct iwl_wowlan_status_v6 *v6 = (void *)cmd.resp_pkt->data;
status = iwl_mvm_parse_wowlan_status_common_v6(mvm, v6, len);
@@ -2154,29 +2310,29 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
goto out_free_resp;
BUILD_BUG_ON(sizeof(v6->gtk.decrypt_key) >
- sizeof(status->gtk.key));
+ sizeof(status->gtk[0].key));
BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +
sizeof(v6->gtk.tkip_mic_key) >
- sizeof(status->gtk.key));
+ sizeof(status->gtk[0].key));
/* copy GTK info to the right place */
- memcpy(status->gtk.key, v6->gtk.decrypt_key,
+ memcpy(status->gtk[0].key, v6->gtk.decrypt_key,
sizeof(v6->gtk.decrypt_key));
- memcpy(status->gtk.key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
+ memcpy(status->gtk[0].key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
v6->gtk.tkip_mic_key,
sizeof(v6->gtk.tkip_mic_key));
iwl_mvm_convert_key_counters(status, &v6->gtk.rsc.all_tsc_rsc);
/* hardcode the key length to 16 since v6 only supports 16 */
- status->gtk.len = 16;
+ status->gtk[0].len = 16;
/*
* The key index only uses 2 bits (values 0 to 3) and
* we always set bit 7 which means this is the
* currently used key.
*/
- status->gtk.flags = v6->gtk.key_index | BIT(7);
+ status->gtk[0].flags = v6->gtk.key_index | BIT(7);
} else if (notif_ver == 7) {
struct iwl_wowlan_status_v7 *v7 = (void *)cmd.resp_pkt->data;
@@ -2210,7 +2366,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
goto out_free_resp;
iwl_mvm_convert_key_counters_v5(status, &v12->gtk[0].sc);
- iwl_mvm_convert_gtk_v3(status, &v12->gtk[0]);
+ iwl_mvm_convert_gtk_v3(status, v12->gtk);
iwl_mvm_convert_igtk(status, &v12->igtk[0]);
status->tid_tear_down = v12->tid_tear_down;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
index 3613b1fdc5d9..cb4ecad6103f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -554,7 +554,7 @@ static ssize_t iwl_dbgfs_uapsd_misbehaving_read(struct file *file,
char buf[20];
int len;
- len = sprintf(buf, "%pM\n", mvmvif->uapsd_misbehaving_bssid);
+ len = sprintf(buf, "%pM\n", mvmvif->uapsd_misbehaving_ap_addr);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -567,7 +567,7 @@ static ssize_t iwl_dbgfs_uapsd_misbehaving_write(struct ieee80211_vif *vif,
bool ret;
mutex_lock(&mvm->mutex);
- ret = mac_pton(buf, mvmvif->uapsd_misbehaving_bssid);
+ ret = mac_pton(buf, mvmvif->uapsd_misbehaving_ap_addr);
mutex_unlock(&mvm->mutex);
return ret ? count : -EINVAL;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index 84a488538427..cf27f106d4d5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -15,6 +15,7 @@
#include "iwl-io.h"
#include "debugfs.h"
#include "iwl-modparams.h"
+#include "iwl-drv.h"
#include "fw/error-dump.h"
#include "fw/api/phy-ctxt.h"
@@ -391,13 +392,14 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
-static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf,
+static ssize_t iwl_dbgfs_rs_data_read(struct ieee80211_link_sta *link_sta,
+ struct iwl_mvm_sta *mvmsta,
+ struct iwl_mvm *mvm,
+ struct iwl_mvm_link_sta *mvm_link_sta,
+ char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ieee80211_sta *sta = file->private_data;
- struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
- struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->deflink.lq_sta.rs_fw;
- struct iwl_mvm *mvm = lq_sta->pers.drv;
+ struct iwl_lq_sta_rs_fw *lq_sta = &mvm_link_sta->lq_sta.rs_fw;
static const size_t bufsz = 2048;
char *buff;
int desc = 0;
@@ -407,8 +409,6 @@ static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf,
if (!buff)
return -ENOMEM;
- mutex_lock(&mvm->mutex);
-
desc += scnprintf(buff + desc, bufsz - desc, "sta_id %d\n",
lq_sta->pers.sta_id);
desc += scnprintf(buff + desc, bufsz - desc,
@@ -429,18 +429,19 @@ static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf,
lq_sta->last_rate_n_flags);
if (desc < bufsz - 1)
buff[desc++] = '\n';
- mutex_unlock(&mvm->mutex);
ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
kfree(buff);
return ret;
}
-static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_sta *sta,
+static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_link_sta *link_sta,
+ struct iwl_mvm_sta *mvmsta,
+ struct iwl_mvm *mvm,
+ struct iwl_mvm_link_sta *mvm_link_sta,
char *buf, size_t count,
loff_t *ppos)
{
- struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
int i;
u16 amsdu_len;
@@ -448,36 +449,39 @@ static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_sta *sta,
return -EINVAL;
/* only change from debug set <-> debug unset */
- if (amsdu_len && mvmsta->orig_amsdu_len)
+ if (amsdu_len && mvm_link_sta->orig_amsdu_len)
return -EBUSY;
if (amsdu_len) {
- mvmsta->orig_amsdu_len = sta->cur->max_amsdu_len;
- sta->deflink.agg.max_amsdu_len = amsdu_len;
- sta->deflink.agg.max_amsdu_len = amsdu_len;
- for (i = 0; i < ARRAY_SIZE(sta->deflink.agg.max_tid_amsdu_len); i++)
- sta->deflink.agg.max_tid_amsdu_len[i] = amsdu_len;
+ mvm_link_sta->orig_amsdu_len = link_sta->agg.max_amsdu_len;
+ link_sta->agg.max_amsdu_len = amsdu_len;
+ link_sta->agg.max_amsdu_len = amsdu_len;
+ for (i = 0; i < ARRAY_SIZE(link_sta->agg.max_tid_amsdu_len); i++)
+ link_sta->agg.max_tid_amsdu_len[i] = amsdu_len;
} else {
- sta->deflink.agg.max_amsdu_len = mvmsta->orig_amsdu_len;
- mvmsta->orig_amsdu_len = 0;
+ link_sta->agg.max_amsdu_len = mvm_link_sta->orig_amsdu_len;
+ mvm_link_sta->orig_amsdu_len = 0;
}
+ ieee80211_sta_recalc_aggregates(link_sta->sta);
+
return count;
}
-static ssize_t iwl_dbgfs_amsdu_len_read(struct file *file,
+static ssize_t iwl_dbgfs_amsdu_len_read(struct ieee80211_link_sta *link_sta,
+ struct iwl_mvm_sta *mvmsta,
+ struct iwl_mvm *mvm,
+ struct iwl_mvm_link_sta *mvm_link_sta,
char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ieee80211_sta *sta = file->private_data;
- struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
-
char buf[32];
int pos;
- pos = scnprintf(buf, sizeof(buf), "current %d ", sta->cur->max_amsdu_len);
+ pos = scnprintf(buf, sizeof(buf), "current %d ",
+ link_sta->agg.max_amsdu_len);
pos += scnprintf(buf + pos, sizeof(buf) - pos, "stored %d\n",
- mvmsta->orig_amsdu_len);
+ mvm_link_sta->orig_amsdu_len);
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
@@ -712,6 +716,7 @@ static ssize_t iwl_dbgfs_fw_ver_read(struct file *file, char __user *user_buf,
struct iwl_mvm *mvm = file->private_data;
char *buff, *pos, *endpos;
static const size_t bufsz = 1024;
+ char _fw_name_pre[FW_NAME_PRE_BUFSIZE];
int ret;
buff = kmalloc(bufsz, GFP_KERNEL);
@@ -722,7 +727,7 @@ static ssize_t iwl_dbgfs_fw_ver_read(struct file *file, char __user *user_buf,
endpos = pos + bufsz;
pos += scnprintf(pos, endpos - pos, "FW prefix: %s\n",
- mvm->trans->cfg->fw_name_pre);
+ iwl_drv_get_fwname_pre(mvm->trans, _fw_name_pre));
pos += scnprintf(pos, endpos - pos, "FW: %s\n",
mvm->fwrt.fw->human_readable);
pos += scnprintf(pos, endpos - pos, "Device: %s\n",
@@ -1596,17 +1601,127 @@ static ssize_t iwl_dbgfs_dbg_time_point_write(struct iwl_mvm *mvm,
#define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \
MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
-#define MVM_DEBUGFS_WRITE_STA_FILE_OPS(name, bufsz) \
- _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_sta)
-#define MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(name, bufsz) \
- _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_sta)
+static ssize_t
+_iwl_dbgfs_link_sta_wrap_write(ssize_t (*real)(struct ieee80211_link_sta *,
+ struct iwl_mvm_sta *,
+ struct iwl_mvm *,
+ struct iwl_mvm_link_sta *,
+ char *,
+ size_t, loff_t *),
+ struct file *file,
+ char *buf, size_t buf_size, loff_t *ppos)
+{
+ struct ieee80211_link_sta *link_sta = file->private_data;
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(link_sta->sta);
+ struct iwl_mvm *mvm = iwl_mvm_vif_from_mac80211(mvmsta->vif)->mvm;
+ struct iwl_mvm_link_sta *mvm_link_sta;
+ ssize_t ret;
-#define MVM_DEBUGFS_ADD_STA_FILE_ALIAS(alias, name, parent, mode) do { \
- debugfs_create_file(alias, mode, parent, sta, \
- &iwl_dbgfs_##name##_ops); \
- } while (0)
-#define MVM_DEBUGFS_ADD_STA_FILE(name, parent, mode) \
- MVM_DEBUGFS_ADD_STA_FILE_ALIAS(#name, name, parent, mode)
+ mutex_lock(&mvm->mutex);
+
+ mvm_link_sta = rcu_dereference_protected(mvmsta->link[link_sta->link_id],
+ lockdep_is_held(&mvm->mutex));
+ if (WARN_ON(!mvm_link_sta)) {
+ mutex_unlock(&mvm->mutex);
+ return -ENODEV;
+ }
+
+ ret = real(link_sta, mvmsta, mvm, mvm_link_sta, buf, buf_size, ppos);
+
+ mutex_unlock(&mvm->mutex);
+
+ return ret;
+}
+
+static ssize_t
+_iwl_dbgfs_link_sta_wrap_read(ssize_t (*real)(struct ieee80211_link_sta *,
+ struct iwl_mvm_sta *,
+ struct iwl_mvm *,
+ struct iwl_mvm_link_sta *,
+ char __user *,
+ size_t, loff_t *),
+ struct file *file,
+ char __user *user_buf, size_t count, loff_t *ppos)
+{
+ struct ieee80211_link_sta *link_sta = file->private_data;
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(link_sta->sta);
+ struct iwl_mvm *mvm = iwl_mvm_vif_from_mac80211(mvmsta->vif)->mvm;
+ struct iwl_mvm_link_sta *mvm_link_sta;
+ ssize_t ret;
+
+ mutex_lock(&mvm->mutex);
+
+ mvm_link_sta = rcu_dereference_protected(mvmsta->link[link_sta->link_id],
+ lockdep_is_held(&mvm->mutex));
+ if (WARN_ON(!mvm_link_sta)) {
+ mutex_unlock(&mvm->mutex);
+ return -ENODEV;
+ }
+
+ ret = real(link_sta, mvmsta, mvm, mvm_link_sta, user_buf, count, ppos);
+
+ mutex_unlock(&mvm->mutex);
+
+ return ret;
+}
+
+#define MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, buflen) \
+static ssize_t _iwl_dbgfs_link_sta_##name##_write(struct file *file, \
+ const char __user *user_buf, \
+ size_t count, loff_t *ppos) \
+{ \
+ char buf[buflen] = {}; \
+ size_t buf_size = min(count, sizeof(buf) - 1); \
+ \
+ if (copy_from_user(buf, user_buf, sizeof(buf))) \
+ return -EFAULT; \
+ \
+ return _iwl_dbgfs_link_sta_wrap_write(iwl_dbgfs_##name##_write, \
+ file, \
+ buf, buf_size, ppos); \
+} \
+
+#define MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name) \
+static ssize_t _iwl_dbgfs_link_sta_##name##_read(struct file *file, \
+ char __user *user_buf, \
+ size_t count, loff_t *ppos) \
+{ \
+ return _iwl_dbgfs_link_sta_wrap_read(iwl_dbgfs_##name##_read, \
+ file, \
+ user_buf, count, ppos); \
+} \
+
+#define MVM_DEBUGFS_WRITE_LINK_STA_FILE_OPS(name, bufsz) \
+MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, bufsz) \
+static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = { \
+ .write = _iwl_dbgfs_link_sta_##name##_write, \
+ .open = simple_open, \
+ .llseek = generic_file_llseek, \
+}
+
+#define MVM_DEBUGFS_READ_LINK_STA_FILE_OPS(name) \
+MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name) \
+static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = { \
+ .read = _iwl_dbgfs_link_sta_##name##_read, \
+ .open = simple_open, \
+ .llseek = generic_file_llseek, \
+}
+
+#define MVM_DEBUGFS_READ_WRITE_LINK_STA_FILE_OPS(name, bufsz) \
+MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name) \
+MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, bufsz) \
+static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = { \
+ .read = _iwl_dbgfs_link_sta_##name##_read, \
+ .write = _iwl_dbgfs_link_sta_##name##_write, \
+ .open = simple_open, \
+ .llseek = generic_file_llseek, \
+}
+
+#define MVM_DEBUGFS_ADD_LINK_STA_FILE_ALIAS(alias, name, parent, mode) \
+ debugfs_create_file(alias, mode, parent, link_sta, \
+ &iwl_dbgfs_link_sta_##name##_ops)
+#define MVM_DEBUGFS_ADD_LINK_STA_FILE(name, parent, mode) \
+ MVM_DEBUGFS_ADD_LINK_STA_FILE_ALIAS(#name, name, parent, mode)
static ssize_t
iwl_dbgfs_prph_reg_read(struct file *file,
@@ -1891,7 +2006,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64);
MVM_DEBUGFS_READ_FILE_OPS(nic_temp);
MVM_DEBUGFS_READ_FILE_OPS(stations);
-MVM_DEBUGFS_READ_FILE_OPS(rs_data);
+MVM_DEBUGFS_READ_LINK_STA_FILE_OPS(rs_data);
MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64);
@@ -1921,7 +2036,7 @@ MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile);
MVM_DEBUGFS_READ_FILE_OPS(wifi_6e_enable);
#endif
-MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(amsdu_len, 16);
+MVM_DEBUGFS_READ_WRITE_LINK_STA_FILE_OPS(amsdu_len, 16);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(he_sniffer_params, 32);
@@ -2068,17 +2183,18 @@ static const struct file_operations iwl_dbgfs_mem_ops = {
.llseek = default_llseek,
};
-void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct dentry *dir)
+void iwl_mvm_link_sta_add_debugfs(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_link_sta *link_sta,
+ struct dentry *dir)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
if (iwl_mvm_has_tlc_offload(mvm)) {
- MVM_DEBUGFS_ADD_STA_FILE(rs_data, dir, 0400);
+ MVM_DEBUGFS_ADD_LINK_STA_FILE(rs_data, dir, 0400);
}
- MVM_DEBUGFS_ADD_STA_FILE(amsdu_len, dir, 0600);
+
+ MVM_DEBUGFS_ADD_LINK_STA_FILE(amsdu_len, dir, 0600);
}
void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
index 652a603c4500..233ae81884a0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
@@ -72,15 +72,24 @@ int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* the TK is already configured for this station, so it
* shouldn't be set again here.
*/
- if (vif->cfg.assoc &&
- !memcmp(addr, vif->bss_conf.bssid, ETH_ALEN)) {
+ if (vif->cfg.assoc) {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct ieee80211_bss_conf *link_conf;
+ unsigned int link_id;
struct ieee80211_sta *sta;
+ u8 sta_id;
rcu_read_lock();
- sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->deflink.ap_sta_id]);
- if (!IS_ERR_OR_NULL(sta) && sta->mfp)
- expected_tk_len = 0;
+ for_each_vif_active_link(vif, link_conf, link_id) {
+ if (memcmp(addr, link_conf->bssid, ETH_ALEN))
+ continue;
+
+ sta_id = mvmvif->link[link_id]->ap_sta_id;
+ sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
+ if (!IS_ERR_OR_NULL(sta) && sta->mfp)
+ expected_tk_len = 0;
+ break;
+ }
rcu_read_unlock();
}
@@ -518,25 +527,30 @@ iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_ftm_put_target_common(mvm, peer, target);
- if (vif->cfg.assoc &&
- !memcmp(peer->addr, vif->bss_conf.bssid, ETH_ALEN)) {
+ if (vif->cfg.assoc) {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_sta *sta;
+ struct ieee80211_bss_conf *link_conf;
+ unsigned int link_id;
rcu_read_lock();
+ for_each_vif_active_link(vif, link_conf, link_id) {
+ if (memcmp(peer->addr, link_conf->bssid, ETH_ALEN))
+ continue;
+
+ target->sta_id = mvmvif->link[link_id]->ap_sta_id;
+ sta = rcu_dereference(mvm->fw_id_to_mac_id[target->sta_id]);
+ if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) {
+ rcu_read_unlock();
+ return PTR_ERR_OR_ZERO(sta);
+ }
- sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->deflink.ap_sta_id]);
- if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) {
- rcu_read_unlock();
- return PTR_ERR_OR_ZERO(sta);
+ if (sta->mfp && (peer->ftm.trigger_based ||
+ peer->ftm.non_trigger_based))
+ FTM_PUT_FLAG(PMF);
+ break;
}
-
- if (sta->mfp && (peer->ftm.trigger_based || peer->ftm.non_trigger_based))
- FTM_PUT_FLAG(PMF);
-
rcu_read_unlock();
-
- target->sta_id = mvmvif->deflink.ap_sta_id;
} else {
target->sta_id = IWL_MVM_INVALID_STA;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
index 1b6fb73ddfc7..b49781d1a07a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
@@ -104,7 +104,8 @@ iwl_mvm_ftm_responder_set_ndp(struct iwl_mvm *mvm,
static int
iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- struct cfg80211_chan_def *chandef)
+ struct cfg80211_chan_def *chandef,
+ struct ieee80211_bss_conf *link_conf)
{
u32 cmd_id = WIDE_ID(LOCATION_GROUP, TOF_RESPONDER_CONFIG_CMD);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -119,7 +120,7 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO |
IWL_TOF_RESPONDER_CMD_VALID_BSSID |
IWL_TOF_RESPONDER_CMD_VALID_STA_ID),
- .sta_id = mvmvif->deflink.bcast_sta.sta_id,
+ .sta_id = mvmvif->link[link_conf->link_id]->bcast_sta.sta_id,
};
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 6);
int err;
@@ -386,7 +387,8 @@ int iwl_mvm_ftm_resp_remove_pasn_sta(struct iwl_mvm *mvm,
return -EINVAL;
}
-int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_ftm_responder_params *params;
@@ -395,11 +397,11 @@ int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
struct iwl_mvm_phy_ctxt *phy_ctxt;
int ret;
- params = vif->bss_conf.ftmr_params;
+ params = bss_conf->ftmr_params;
lockdep_assert_held(&mvm->mutex);
- if (WARN_ON_ONCE(!vif->bss_conf.ftm_responder))
+ if (WARN_ON_ONCE(!bss_conf->ftm_responder))
return -EINVAL;
if (vif->p2p || vif->type != NL80211_IFTYPE_AP ||
@@ -409,7 +411,7 @@ int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
}
rcu_read_lock();
- pctx = rcu_dereference(vif->bss_conf.chanctx_conf);
+ pctx = rcu_dereference(bss_conf->chanctx_conf);
/* Copy the ctx to unlock the rcu and send the phy ctxt. We don't care
* about changes in the ctx after releasing the lock because the driver
* is still protected by the mutex. */
@@ -424,7 +426,7 @@ int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (ret)
return ret;
- ret = iwl_mvm_ftm_responder_cmd(mvm, vif, &ctx.def);
+ ret = iwl_mvm_ftm_responder_cmd(mvm, vif, &ctx.def, bss_conf);
if (ret)
return ret;
@@ -446,13 +448,14 @@ void iwl_mvm_ftm_responder_clear(struct iwl_mvm *mvm,
}
void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf)
{
- if (!vif->bss_conf.ftm_responder)
+ if (!bss_conf->ftm_responder)
return;
iwl_mvm_ftm_responder_clear(mvm, vif);
- iwl_mvm_ftm_start_responder(mvm, vif);
+ iwl_mvm_ftm_start_responder(mvm, vif, bss_conf);
}
void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 205c09bc9863..1f5db65a088d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -433,7 +433,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
/* if reached this point, Alive notification was received */
iwl_mei_alive_notif(true);
- ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait);
+ ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait,
+ &mvm->fw->ucode_capa);
if (ret) {
IWL_ERR(mvm, "Timeout waiting for PNVM load!\n");
iwl_fw_set_current_image(&mvm->fwrt, old_type);
@@ -477,40 +478,13 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
return 0;
}
-#ifdef CONFIG_ACPI
-static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
- struct iwl_phy_specific_cfg *phy_filters)
-{
- /*
- * TODO: read specific phy config from BIOS
- * ACPI table for this feature has not been defined yet,
- * so for now we use hardcoded values.
- */
-
- if (IWL_MVM_PHY_FILTER_CHAIN_A) {
- phy_filters->filter_cfg_chain_a =
- cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_A);
- }
- if (IWL_MVM_PHY_FILTER_CHAIN_B) {
- phy_filters->filter_cfg_chain_b =
- cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_B);
- }
- if (IWL_MVM_PHY_FILTER_CHAIN_C) {
- phy_filters->filter_cfg_chain_c =
- cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_C);
- }
- if (IWL_MVM_PHY_FILTER_CHAIN_D) {
- phy_filters->filter_cfg_chain_d =
- cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_D);
- }
-}
-#else /* CONFIG_ACPI */
-
static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
struct iwl_phy_specific_cfg *phy_filters)
{
-}
+#ifdef CONFIG_ACPI
+ *phy_filters = mvm->phy_filters;
#endif /* CONFIG_ACPI */
+}
#if defined(CONFIG_ACPI) && defined(CONFIG_EFI)
static int iwl_mvm_sgom_init(struct iwl_mvm *mvm)
@@ -559,7 +533,6 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
u32 cmd_id = PHY_CONFIGURATION_CMD;
struct iwl_phy_cfg_cmd_v3 phy_cfg_cmd;
enum iwl_ucode_type ucode_type = mvm->fwrt.cur_fw_img;
- struct iwl_phy_specific_cfg phy_filters = {};
u8 cmd_ver;
size_t cmd_size;
@@ -590,11 +563,8 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id,
IWL_FW_CMD_VER_UNKNOWN);
- if (cmd_ver == 3) {
- iwl_mvm_phy_filter_init(mvm, &phy_filters);
- memcpy(&phy_cfg_cmd.phy_specific_cfg, &phy_filters,
- sizeof(struct iwl_phy_specific_cfg));
- }
+ if (cmd_ver >= 3)
+ iwl_mvm_phy_filter_init(mvm, &phy_cfg_cmd.phy_specific_cfg);
IWL_DEBUG_INFO(mvm, "Sending Phy CFG command: 0x%x\n",
phy_cfg_cmd.phy_cfg);
@@ -1104,7 +1074,26 @@ static const struct dmi_system_id dmi_tas_approved_list[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
},
},
-
+ { .ident = "Acer",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ },
+ },
+ { .ident = "ASUS",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ },
+ },
+ { .ident = "MSI",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."),
+ },
+ },
+ { .ident = "Honor",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HONOR"),
+ },
+ },
/* keep last */
{}
};
@@ -1162,7 +1151,7 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
if (ret == 0)
return;
- if (!dmi_check_system(dmi_tas_approved_list)) {
+ if (!iwl_mvm_is_vendor_in_approved_list()) {
IWL_DEBUG_RADIO(mvm,
"System vendor '%s' is not in the approved list, disabling TAS in US and Canada.\n",
dmi_get_system_info(DMI_SYS_VENDOR));
@@ -1176,6 +1165,10 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
"Unable to add US/Canada to TAS block list, disabling TAS\n");
return;
}
+ } else {
+ IWL_DEBUG_RADIO(mvm,
+ "System vendor '%s' is in the approved list.\n",
+ dmi_get_system_info(DMI_SYS_VENDOR));
}
/* v4 is the same size as v3, so no need to differentiate here */
@@ -1356,6 +1349,8 @@ void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm)
/* we don't fail if the table is not available */
}
}
+
+ iwl_acpi_get_phy_filters(&mvm->fwrt, &mvm->phy_filters);
}
#else /* CONFIG_ACPI */
@@ -1571,6 +1566,8 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error;
}
+ iwl_mvm_lari_cfg(mvm);
+
/* Init RSS configuration */
ret = iwl_configure_rxq(&mvm->fwrt);
if (ret)
@@ -1591,6 +1588,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
RCU_INIT_POINTER(mvm->fw_id_to_link_sta[i], NULL);
}
+ for (i = 0; i < IWL_MVM_FW_MAX_LINK_ID + 1; i++)
+ RCU_INIT_POINTER(mvm->link_id_to_link_conf[i], NULL);
+
memset(&mvm->fw_link_ids_map, 0, sizeof(mvm->fw_link_ids_map));
mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA;
@@ -1610,7 +1610,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
* internal aux station for all aux activities that don't
* requires a dedicated data queue.
*/
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) < 12) {
+ if (!iwl_mvm_has_new_station_api(mvm->fw)) {
/*
* In old version the aux station uses mac id like other
* station and not lmac id
@@ -1678,7 +1678,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (ret)
goto error;
- iwl_mvm_lari_cfg(mvm);
/*
* RTNL is not taken during Ct-kill, but we don't need to scan/Tx
* anyway, so don't init MCC.
@@ -1699,9 +1698,11 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_UPDATE_DB);
- iwl_mvm_time_sync_config(mvm, mvm->time_sync.peer_addr,
- IWL_TIME_SYNC_PROTOCOL_TM |
- IWL_TIME_SYNC_PROTOCOL_FTM);
+
+ if (mvm->time_sync.active)
+ iwl_mvm_time_sync_config(mvm, mvm->time_sync.peer_addr,
+ IWL_TIME_SYNC_PROTOCOL_TM |
+ IWL_TIME_SYNC_PROTOCOL_FTM);
}
if (!mvm->ptp_data.ptp_clock)
@@ -1777,7 +1778,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
RCU_INIT_POINTER(mvm->fw_id_to_link_sta[i], NULL);
}
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) < 12) {
+ if (!iwl_mvm_has_new_station_api(mvm->fw)) {
/*
* Add auxiliary station for scanning.
* Newer versions of this command implies that the fw uses
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
index 3814915cb1a6..ace82e2c5bd9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
@@ -63,6 +63,9 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvmvif);
if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID)
return -EINVAL;
+
+ rcu_assign_pointer(mvm->link_id_to_link_conf[link_info->fw_link_id],
+ link_conf);
}
/* Update SF - Disable if needed. if this fails, SF might still be on
@@ -73,6 +76,7 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
cmd.link_id = cpu_to_le32(link_info->fw_link_id);
cmd.mac_id = cpu_to_le32(mvmvif->id);
+ cmd.spec_link_id = link_conf->link_id;
/* P2P-Device already has a valid PHY context during add */
phyctxt = link_info->phy_ctxt;
if (phyctxt)
@@ -85,6 +89,8 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid)
memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN);
+ cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac);
+
return iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_ADD);
}
@@ -114,24 +120,6 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (!link_info->phy_ctxt)
return 0;
- /* check there aren't too many active links */
- if (!link_info->active && active) {
- int i, count = 0;
-
- /* link with phy_ctxt is active in FW */
- for_each_mvm_vif_valid_link(mvmvif, i)
- if (mvmvif->link[i]->phy_ctxt)
- count++;
-
- if (vif->type == NL80211_IFTYPE_AP) {
- if (count > mvm->fw->ucode_capa.num_beacons)
- return -EOPNOTSUPP;
- /* this should be per HW or such */
- } else if (count >= IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM) {
- return -EOPNOTSUPP;
- }
- }
-
/* Catch early if driver tries to activate or deactivate a link
* twice.
*/
@@ -163,10 +151,6 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid)
memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN);
- /* TODO: set a value to cmd.listen_lmac when system requiremens
- * will define it
- */
-
iwl_mvm_set_fw_basic_rates(mvm, vif, link_conf,
&cmd.cck_rates, &cmd.ofdm_rates);
@@ -179,7 +163,7 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
&cmd.protection_flags,
ht_flag, LINK_PROT_FLG_TGG_PROTECT);
- iwl_mvm_set_fw_qos_params(mvm, vif, link_conf, &cmd.ac[0],
+ iwl_mvm_set_fw_qos_params(mvm, vif, link_conf, cmd.ac,
&cmd.qos_flags);
@@ -204,7 +188,7 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
/* TODO how to set ndp_fdbk_buff_th_exp? */
- if (iwl_mvm_set_fw_mu_edca_params(mvm, mvmvif,
+ if (iwl_mvm_set_fw_mu_edca_params(mvm, mvmvif->link[link_id],
&cmd.trig_based_txf[0])) {
flags |= LINK_FLG_MU_EDCA_CW;
flags_mask |= LINK_FLG_MU_EDCA_CW;
@@ -241,6 +225,8 @@ send_cmd:
cmd.modify_mask = cpu_to_le32(changes);
cmd.flags = cpu_to_le32(flags);
cmd.flags_mask = cpu_to_le32(flags_mask);
+ cmd.spec_link_id = link_conf->link_id;
+ cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac);
ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_MODIFY);
if (!ret && (changes & LINK_CONTEXT_MODIFY_ACTIVE))
@@ -262,9 +248,12 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID))
return -EINVAL;
+ RCU_INIT_POINTER(mvm->link_id_to_link_conf[link_info->fw_link_id],
+ NULL);
cmd.link_id = cpu_to_le32(link_info->fw_link_id);
iwl_mvm_release_fw_link_id(mvm, link_info->fw_link_id);
link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
+ cmd.spec_link_id = link_conf->link_id;
ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_REMOVE);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index cc90f2884cff..7369a45f7f2b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -470,19 +470,24 @@ void iwl_mvm_set_fw_qos_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_ac_qos *ac, __le32 *qos_flags)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_vif_link_info *mvm_link =
+ mvmvif->link[link_conf->link_id];
int i;
+ if (!mvm_link)
+ return;
+
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
u8 txf = iwl_mvm_mac_ac_to_tx_fifo(mvm, i);
u8 ucode_ac = iwl_mvm_mac80211_ac_to_ucode_ac(i);
ac[ucode_ac].cw_min =
- cpu_to_le16(mvmvif->deflink.queue_params[i].cw_min);
+ cpu_to_le16(mvm_link->queue_params[i].cw_min);
ac[ucode_ac].cw_max =
- cpu_to_le16(mvmvif->deflink.queue_params[i].cw_max);
+ cpu_to_le16(mvm_link->queue_params[i].cw_max);
ac[ucode_ac].edca_txop =
- cpu_to_le16(mvmvif->deflink.queue_params[i].txop * 32);
- ac[ucode_ac].aifsn = mvmvif->deflink.queue_params[i].aifs;
+ cpu_to_le16(mvm_link->queue_params[i].txop * 32);
+ ac[ucode_ac].aifsn = mvm_link->queue_params[i].aifs;
ac[ucode_ac].fifos_mask = BIT(txf);
}
@@ -558,7 +563,7 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
cmd->filter_flags = 0;
- iwl_mvm_set_fw_qos_params(mvm, vif, &vif->bss_conf, &cmd->ac[0],
+ iwl_mvm_set_fw_qos_params(mvm, vif, &vif->bss_conf, cmd->ac,
&cmd->qos_flags);
/* The fw does not distinguish between ht and fat */
@@ -629,17 +634,17 @@ __le32 iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(struct iwl_mvm *mvm,
IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
}
-__le32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
+u32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
{
- __le32 twt_policy = cpu_to_le32(0);
+ u32 twt_policy = 0;
if (vif->bss_conf.twt_requester && IWL_MVM_USE_TWT)
- twt_policy |= cpu_to_le32(TWT_SUPPORTED);
+ twt_policy |= TWT_SUPPORTED;
if (vif->bss_conf.twt_protected)
- twt_policy |= cpu_to_le32(PROTECTED_TWT_SUPPORTED);
+ twt_policy |= PROTECTED_TWT_SUPPORTED;
if (vif->bss_conf.twt_broadcast)
- twt_policy |= cpu_to_le32(BROADCAST_TWT_SUPPORTED);
+ twt_policy |= BROADCAST_TWT_SUPPORTED;
return twt_policy;
}
@@ -711,7 +716,7 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) {
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX);
ctxt_sta->data_policy |=
- iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif);
+ cpu_to_le32(iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif));
}
@@ -888,7 +893,7 @@ u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm,
u8 rate;
u32 i;
- if (link_id == IEEE80211_LINK_UNSPECIFIED && vif->valid_links) {
+ if (link_id == IEEE80211_LINK_UNSPECIFIED && ieee80211_vif_is_mld(vif)) {
for (i = 0; i < ARRAY_SIZE(mvmvif->link); i++) {
if (!mvmvif->link[i])
continue;
@@ -1111,6 +1116,10 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
beacon_cmd.flags = cpu_to_le16(flags);
beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
+
+ if (WARN_ON(!mvmvif->link[link_conf->link_id]))
+ return -EINVAL;
+
if (iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD, 0) > 12)
beacon_cmd.link_id =
cpu_to_le32(mvmvif->link[link_conf->link_id]->fw_link_id);
@@ -1555,21 +1564,38 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
u32 stop_trig_missed_bcon, stop_trig_missed_bcon_since_rx;
u32 rx_missed_bcon, rx_missed_bcon_since_rx;
struct ieee80211_vif *vif;
- u32 id = le32_to_cpu(mb->mac_id);
+ /* Id can be mac/link id depending on the notification version */
+ u32 id = le32_to_cpu(mb->link_id);
union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt };
u32 mac_type;
+ u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
+ MISSED_BEACONS_NOTIFICATION,
+ 0);
+
+ rcu_read_lock();
+
+ /* before version four the ID in the notification refers to mac ID */
+ if (notif_ver < 4) {
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
+ } else {
+ struct ieee80211_bss_conf *bss_conf =
+ iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, true);
+
+ if (!bss_conf)
+ goto out;
+
+ vif = bss_conf->vif;
+ }
IWL_DEBUG_INFO(mvm,
- "missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n",
- le32_to_cpu(mb->mac_id),
+ "missed bcn %s_id=%u, consecutive=%u (%u, %u, %u)\n",
+ notif_ver < 4 ? "mac" : "link",
+ id,
le32_to_cpu(mb->consec_missed_beacons),
le32_to_cpu(mb->consec_missed_beacons_since_last_rx),
le32_to_cpu(mb->num_recvd_beacons),
le32_to_cpu(mb->num_expected_beacons));
- rcu_read_lock();
-
- vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
if (!vif)
goto out;
@@ -1730,20 +1756,47 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_channel_switch_start_notif *notif = (void *)pkt->data;
struct ieee80211_vif *csa_vif, *vif;
- struct iwl_mvm_vif *mvmvif;
- u32 id_n_color, csa_id, mac_id;
+ struct iwl_mvm_vif *mvmvif, *csa_mvmvif;
+ u32 id_n_color, csa_id;
+ /* save mac_id or link_id to use later to cancel csa if needed */
+ u32 id;
+ u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP,
+ CHANNEL_SWITCH_START_NOTIF, 0);
+ bool csa_active;
- id_n_color = le32_to_cpu(notif->id_and_color);
- mac_id = id_n_color & FW_CTXT_ID_MSK;
+ rcu_read_lock();
- if (WARN_ON_ONCE(mac_id >= NUM_MAC_INDEX_DRIVER))
- return;
+ if (notif_ver < 3) {
+ struct iwl_channel_switch_start_notif_v1 *notif = (void *)pkt->data;
+ u32 mac_id;
+
+ id_n_color = le32_to_cpu(notif->id_and_color);
+ mac_id = id_n_color & FW_CTXT_ID_MSK;
+
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, mac_id, true);
+ if (!vif)
+ goto out_unlock;
+
+ id = mac_id;
+ csa_active = vif->bss_conf.csa_active;
+ } else {
+ struct iwl_channel_switch_start_notif *notif = (void *)pkt->data;
+ u32 link_id = le32_to_cpu(notif->link_id);
+ struct ieee80211_bss_conf *bss_conf =
+ iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, link_id, true);
+
+ if (!bss_conf)
+ goto out_unlock;
+
+ id = link_id;
+ vif = bss_conf->vif;
+ csa_active = bss_conf->csa_active;
+ }
- rcu_read_lock();
- vif = rcu_dereference(mvm->vif_id_to_mac[mac_id]);
mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ if (notif_ver >= 3)
+ id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color);
switch (vif->type) {
case NL80211_IFTYPE_AP:
@@ -1752,7 +1805,8 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
csa_vif != vif))
goto out_unlock;
- csa_id = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color);
+ csa_mvmvif = iwl_mvm_vif_from_mac80211(csa_vif);
+ csa_id = FW_CMD_ID_AND_COLOR(csa_mvmvif->id, csa_mvmvif->color);
if (WARN(csa_id != id_n_color,
"channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)",
csa_id, id_n_color))
@@ -1777,9 +1831,9 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
*/
if (iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP,
CHANNEL_SWITCH_ERROR_NOTIF,
- 0) && !vif->bss_conf.csa_active) {
+ 0) && !csa_active) {
IWL_DEBUG_INFO(mvm, "Channel Switch was canceled\n");
- iwl_mvm_cancel_channel_switch(mvm, vif, mac_id);
+ iwl_mvm_cancel_channel_switch(mvm, vif, id);
break;
}
@@ -1802,7 +1856,7 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_channel_switch_error_notif *notif = (void *)pkt->data;
struct ieee80211_vif *vif;
- u32 id = le32_to_cpu(notif->mac_id);
+ u32 id = le32_to_cpu(notif->link_id);
u32 csa_err_mask = le32_to_cpu(notif->csa_err_mask);
rcu_read_lock();
@@ -1812,7 +1866,7 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
return;
}
- IWL_DEBUG_INFO(mvm, "FW reports CSA error: mac_id=%u, csa_err_mask=%u\n",
+ IWL_DEBUG_INFO(mvm, "FW reports CSA error: id=%u, csa_err_mask=%u\n",
id, csa_err_mask);
if (csa_err_mask & (CS_ERR_COUNT_ERROR |
CS_ERR_LONG_DELAY_AFTER_CS |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 17f788a5ff6b..ce7905faa08f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -108,7 +108,7 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
struct ieee80211_regdomain *regd = NULL;
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- struct iwl_mcc_update_resp *resp;
+ struct iwl_mcc_update_resp_v8 *resp;
u8 resp_ver;
IWL_DEBUG_LAR(mvm, "Getting regdomain data for %s from FW\n", alpha2);
@@ -138,7 +138,7 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
resp->channels,
__le16_to_cpu(resp->mcc),
__le16_to_cpu(resp->geo_info),
- __le16_to_cpu(resp->cap), resp_ver);
+ le32_to_cpu(resp->cap), resp_ver);
/* Store the return source id */
src_id = resp->source_id;
if (IS_ERR_OR_NULL(regd)) {
@@ -245,12 +245,21 @@ static const u8 tm_if_types_ext_capa_sta[] = {
/* Additional interface types for which extended capabilities are
* specified separately
*/
+
+#define IWL_MVM_EMLSR_CAPA (IEEE80211_EML_CAP_EMLSR_SUPP | \
+ IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_32US << \
+ __bf_shf(IEEE80211_EML_CAP_EMLSR_PADDING_DELAY) | \
+ IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_64US << \
+ __bf_shf(IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY))
+
static const struct wiphy_iftype_ext_capab add_iftypes_ext_capa[] = {
{
.iftype = NL80211_IFTYPE_STATION,
.extended_capabilities = he_if_types_ext_capa_sta,
.extended_capabilities_mask = he_if_types_ext_capa_sta,
.extended_capabilities_len = sizeof(he_if_types_ext_capa_sta),
+ /* relevant only if EHT is supported */
+ .eml_capabilities = IWL_MVM_EMLSR_CAPA,
},
{
.iftype = NL80211_IFTYPE_STATION,
@@ -258,7 +267,7 @@ static const struct wiphy_iftype_ext_capab add_iftypes_ext_capa[] = {
.extended_capabilities_mask = tm_if_types_ext_capa_sta,
.extended_capabilities_len = sizeof(tm_if_types_ext_capa_sta),
/* relevant only if EHT is supported */
- .eml_capabilities = IEEE80211_EML_CAP_EMLSR_SUPP,
+ .eml_capabilities = IWL_MVM_EMLSR_CAPA,
},
};
@@ -1029,6 +1038,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
mvmvif->link[link_id]->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
mvmvif->link[link_id]->phy_ctxt = NULL;
mvmvif->link[link_id]->active = 0;
+ mvmvif->link[link_id]->igtk = NULL;
}
probe_data = rcu_dereference_protected(mvmvif->deflink.probe_resp_data,
@@ -1233,7 +1243,7 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
/* async_handlers_wk is now blocked */
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) < 12)
+ if (!iwl_mvm_has_new_station_api(mvm->fw))
iwl_mvm_rm_aux_sta(mvm);
iwl_mvm_stop_device(mvm);
@@ -1478,21 +1488,37 @@ iwl_mvm_chandef_get_primary_80(struct cfg80211_chan_def *chandef)
return (control_start - data_start) / 80;
}
-/*
- * Returns true if addding the interface is done
- * (either with success or failure)
- *
- * FIXME: remove this again and merge it in
- */
-static bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm,
- struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- int *ret)
+static int iwl_mvm_alloc_bcast_mcast_sta(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ int ret;
lockdep_assert_held(&mvm->mutex);
+ ret = iwl_mvm_alloc_bcast_sta(mvm, vif);
+ if (ret) {
+ IWL_ERR(mvm, "Failed to allocate bcast sta\n");
+ return ret;
+ }
+
+ /* Only queue for this station is the mcast queue,
+ * which shouldn't be in TFD mask anyway
+ */
+ return iwl_mvm_allocate_int_sta(mvm, &mvmvif->deflink.mcast_sta, 0,
+ vif->type,
+ IWL_STA_MULTICAST);
+}
+
+static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ int ret;
+
+ mutex_lock(&mvm->mutex);
+
mvmvif->mvm = mvm;
/* the first link always points to the default one */
@@ -1510,12 +1536,18 @@ static bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm,
mvmvif->deflink.beacon_stats.num_beacons;
/* Allocate resources for the MAC context, and add it to the fw */
- *ret = iwl_mvm_mac_ctxt_init(mvm, vif);
- if (*ret)
- return true;
+ ret = iwl_mvm_mac_ctxt_init(mvm, vif);
+ if (ret)
+ goto out;
rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif);
+ /* Currently not much to do for NAN */
+ if (vif->type == NL80211_IFTYPE_NAN) {
+ ret = 0;
+ goto out;
+ }
+
/*
* The AP binding flow can be done only after the beacon
* template is configured (which happens only in the mac80211
@@ -1530,50 +1562,12 @@ static bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm,
if (vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_ADHOC) {
iwl_mvm_vif_dbgfs_register(mvm, vif);
- return true;
+ ret = 0;
+ goto out;
}
mvmvif->features |= hw->netdev_features;
- return false;
-}
-
-static int iwl_mvm_alloc_bcast_mcast_sta(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- int ret;
-
- lockdep_assert_held(&mvm->mutex);
-
- ret = iwl_mvm_alloc_bcast_sta(mvm, vif);
- if (ret) {
- IWL_ERR(mvm, "Failed to allocate bcast sta\n");
- return ret;
- }
-
- /*
- * Only queue for this station is the mcast queue,
- * which shouldn't be in TFD mask anyway
- */
- return iwl_mvm_allocate_int_sta(mvm, &mvmvif->deflink.mcast_sta, 0,
- vif->type,
- IWL_STA_MULTICAST);
-}
-
-static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
-{
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- int ret;
-
- mutex_lock(&mvm->mutex);
-
- /* Common for MLD and non-MLD API */
- if (iwl_mvm_mac_add_interface_common(mvm, hw, vif, &ret))
- goto out;
-
ret = iwl_mvm_mac_ctxt_add(mvm, vif);
if (ret)
goto out_unlock;
@@ -2246,7 +2240,7 @@ int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm,
* is enabled or not
*/
bool iwl_mvm_set_fw_mu_edca_params(struct iwl_mvm *mvm,
- struct iwl_mvm_vif *mvmvif,
+ const struct iwl_mvm_vif_link_info *link_info,
struct iwl_he_backoff_conf *trig_based_txf)
{
int i;
@@ -2254,11 +2248,11 @@ bool iwl_mvm_set_fw_mu_edca_params(struct iwl_mvm *mvm,
bool mu_edca_enabled = true;
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
- struct ieee80211_he_mu_edca_param_ac_rec *mu_edca =
- &mvmvif->deflink.queue_params[i].mu_edca_param_rec;
+ const struct ieee80211_he_mu_edca_param_ac_rec *mu_edca =
+ &link_info->queue_params[i].mu_edca_param_rec;
u8 ac = iwl_mvm_mac80211_ac_to_ucode_ac(i);
- if (!mvmvif->deflink.queue_params[i].mu_edca) {
+ if (!link_info->queue_params[i].mu_edca) {
mu_edca_enabled = false;
break;
}
@@ -2285,8 +2279,7 @@ bool iwl_mvm_is_nic_ack_enabled(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
* so take it from one of them.
*/
sband = mvm->hw->wiphy->bands[NL80211_BAND_2GHZ];
- own_he_cap = ieee80211_get_he_iftype_cap(sband,
- ieee80211_vif_type_p2p(vif));
+ own_he_cap = ieee80211_get_he_iftype_cap_vif(sband, vif);
return (own_he_cap && (own_he_cap->he_cap_elem.mac_cap_info[2] &
IEEE80211_HE_MAC_CAP2_ACK_EN));
@@ -2405,7 +2398,7 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
rcu_read_unlock();
- if (iwl_mvm_set_fw_mu_edca_params(mvm, mvmvif,
+ if (iwl_mvm_set_fw_mu_edca_params(mvm, &mvmvif->deflink,
&sta_ctxt_cmd.trig_based_txf[0]))
flags |= STA_CTXT_HE_MU_EDCA_CW;
@@ -2898,7 +2891,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
if (iwl_mvm_phy_ctx_count(mvm) > 1)
iwl_mvm_teardown_tdls_peers(mvm);
- iwl_mvm_ftm_restart_responder(mvm, vif);
+ iwl_mvm_ftm_restart_responder(mvm, vif, &vif->bss_conf);
goto out_unlock;
@@ -3040,7 +3033,7 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
IWL_WARN(mvm, "Failed updating beacon data\n");
if (changes & BSS_CHANGED_FTM_RESPONDER) {
- int ret = iwl_mvm_ftm_start_responder(mvm, vif);
+ int ret = iwl_mvm_ftm_start_responder(mvm, vif, &vif->bss_conf);
if (ret)
IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n",
@@ -3054,7 +3047,7 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *bss_conf,
u64 changes)
{
- struct iwl_mvm_bss_info_changed_ops callbacks = {
+ static const struct iwl_mvm_bss_info_changed_ops callbacks = {
.bss_info_changed_sta = iwl_mvm_bss_info_changed_station,
.bss_info_changed_ap_ibss = iwl_mvm_bss_info_changed_ap_ibss,
};
@@ -3067,7 +3060,7 @@ void
iwl_mvm_bss_info_changed_common(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
- struct iwl_mvm_bss_info_changed_ops *callbacks,
+ const struct iwl_mvm_bss_info_changed_ops *callbacks,
u64 changes)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
@@ -3468,8 +3461,7 @@ static void iwl_mvm_reset_cca_40mhz_workaround(struct iwl_mvm *mvm,
sband->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- he_cap = ieee80211_get_he_iftype_cap(sband,
- ieee80211_vif_type_p2p(vif));
+ he_cap = ieee80211_get_he_iftype_cap_vif(sband, vif);
if (he_cap) {
/* we know that ours is writable */
@@ -3564,7 +3556,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
enum ieee80211_sta_state old_state,
enum ieee80211_sta_state new_state)
{
- struct iwl_mvm_sta_state_ops callbacks = {
+ static const struct iwl_mvm_sta_state_ops callbacks = {
.add_sta = iwl_mvm_add_sta,
.update_sta = iwl_mvm_update_sta,
.rm_sta = iwl_mvm_rm_sta,
@@ -3669,7 +3661,7 @@ static int
iwl_mvm_sta_state_notexist_to_none(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
- struct iwl_mvm_sta_state_ops *callbacks)
+ const struct iwl_mvm_sta_state_ops *callbacks)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_link_sta *link_sta;
@@ -3713,7 +3705,7 @@ iwl_mvm_sta_state_auth_to_assoc(struct ieee80211_hw *hw,
struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
- struct iwl_mvm_sta_state_ops *callbacks)
+ const struct iwl_mvm_sta_state_ops *callbacks)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
@@ -3770,7 +3762,7 @@ static int
iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
- struct iwl_mvm_sta_state_ops *callbacks)
+ const struct iwl_mvm_sta_state_ops *callbacks)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
@@ -3805,11 +3797,10 @@ static int
iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
- struct iwl_mvm_sta_state_ops *callbacks)
+ const struct iwl_mvm_sta_state_ops *callbacks)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
- int ret;
lockdep_assert_held(&mvm->mutex);
@@ -3828,10 +3819,7 @@ iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm,
mvmvif->authorized = 0;
/* disable beacon filtering */
- ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
- WARN_ON(ret &&
- !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
- &mvm->status));
+ iwl_mvm_disable_beacon_filter(mvm, vif, 0);
}
return 0;
@@ -3843,11 +3831,12 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
enum ieee80211_sta_state old_state,
enum ieee80211_sta_state new_state,
- struct iwl_mvm_sta_state_ops *callbacks)
+ const struct iwl_mvm_sta_state_ops *callbacks)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+ struct ieee80211_link_sta *link_sta;
unsigned int link_id;
int ret;
@@ -3889,7 +3878,7 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
mutex_lock(&mvm->mutex);
/* this would be a mac80211 bug ... but don't crash */
- for_each_mvm_vif_valid_link(mvmvif, link_id) {
+ for_each_sta_active_link(vif, sta, link_sta, link_id) {
if (WARN_ON_ONCE(!mvmvif->link[link_id]->phy_ctxt)) {
mutex_unlock(&mvm->mutex);
return test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
@@ -4533,7 +4522,7 @@ static int iwl_mvm_add_aux_sta_for_hs20(struct iwl_mvm *mvm, u32 lmac_id)
return -EINVAL;
}
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12) {
+ if (iwl_mvm_has_new_station_api(mvm->fw)) {
ret = iwl_mvm_add_aux_sta(mvm, lmac_id);
WARN(ret, "Failed to allocate aux station");
}
@@ -4573,7 +4562,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
int duration,
enum ieee80211_roc_type type)
{
- struct iwl_mvm_roc_ops ops = {
+ static const struct iwl_mvm_roc_ops ops = {
.add_aux_sta_for_hs20 = iwl_mvm_add_aux_sta_for_hs20,
.switch_phy_ctxt = iwl_mvm_roc_switch_binding,
};
@@ -4585,7 +4574,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_channel *channel, int duration,
enum ieee80211_roc_type type,
- struct iwl_mvm_roc_ops *ops)
+ const struct iwl_mvm_roc_ops *ops)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -4608,7 +4597,7 @@ int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
switch (vif->type) {
case NL80211_IFTYPE_STATION:
- lmac_id = iwl_mvm_get_lmac_id(mvm->fw, channel->band);
+ lmac_id = iwl_mvm_get_lmac_id(mvm, channel->band);
/* Use aux roc framework (HS20) */
ret = ops->add_aux_sta_for_hs20(mvm, lmac_id);
@@ -5092,7 +5081,7 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
static int
iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,
struct ieee80211_vif_chanctx_switch *vifs,
- struct iwl_mvm_switch_vif_chanctx_ops *ops)
+ const struct iwl_mvm_switch_vif_chanctx_ops *ops)
{
int ret;
@@ -5151,7 +5140,7 @@ out:
static int
iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm,
struct ieee80211_vif_chanctx_switch *vifs,
- struct iwl_mvm_switch_vif_chanctx_ops *ops)
+ const struct iwl_mvm_switch_vif_chanctx_ops *ops)
{
int ret;
@@ -5194,7 +5183,7 @@ iwl_mvm_switch_vif_chanctx_common(struct ieee80211_hw *hw,
struct ieee80211_vif_chanctx_switch *vifs,
int n_vifs,
enum ieee80211_chanctx_switch_mode mode,
- struct iwl_mvm_switch_vif_chanctx_ops *ops)
+ const struct iwl_mvm_switch_vif_chanctx_ops *ops)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
@@ -5223,7 +5212,7 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
int n_vifs,
enum ieee80211_chanctx_switch_mode mode)
{
- struct iwl_mvm_switch_vif_chanctx_ops ops = {
+ static const struct iwl_mvm_switch_vif_chanctx_ops ops = {
.__assign_vif_chanctx = __iwl_mvm_assign_vif_chanctx,
.__unassign_vif_chanctx = __iwl_mvm_unassign_vif_chanctx,
};
@@ -5664,6 +5653,30 @@ void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
iwl_trans_wait_tx_queues_empty(mvm->trans, msk);
}
+void iwl_mvm_mac_flush_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ int i;
+
+ mutex_lock(&mvm->mutex);
+ for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
+ struct iwl_mvm_sta *mvmsta;
+ struct ieee80211_sta *tmp;
+
+ tmp = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
+ lockdep_is_held(&mvm->mutex));
+ if (tmp != sta)
+ continue;
+
+ mvmsta = iwl_mvm_sta_from_mac80211(sta);
+
+ if (iwl_mvm_flush_sta(mvm, mvmsta, false))
+ IWL_ERR(mvm, "flush request fail\n");
+ }
+ mutex_unlock(&mvm->mutex);
+}
+
int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
struct survey_info *survey)
{
@@ -6154,10 +6167,6 @@ static bool iwl_mvm_mac_can_aggregate(struct ieee80211_hw *hw,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- if (iwl_mvm_has_new_tx_csum(mvm))
- return iwl_mvm_tx_csum_bz(mvm, head, true) ==
- iwl_mvm_tx_csum_bz(mvm, skb, true);
-
/* For now don't aggregate IPv6 in AMSDU */
if (skb->protocol != htons(ETH_P_IP))
return false;
@@ -6220,6 +6229,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx,
.mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover,
.flush = iwl_mvm_mac_flush,
+ .flush_sta = iwl_mvm_mac_flush_sta,
.sched_scan_start = iwl_mvm_mac_sched_scan_start,
.sched_scan_stop = iwl_mvm_mac_sched_scan_stop,
.set_key = iwl_mvm_mac_set_key,
@@ -6277,7 +6287,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.can_aggregate_in_amsdu = iwl_mvm_mac_can_aggregate,
#ifdef CONFIG_IWLWIFI_DEBUGFS
- .sta_add_debugfs = iwl_mvm_sta_add_debugfs,
+ .link_sta_add_debugfs = iwl_mvm_link_sta_add_debugfs,
#endif
.set_hw_timestamp = iwl_mvm_set_hw_timestamp,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
index 8853821b3716..2c9f2f71b083 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2022 Intel Corporation
+ * Copyright (C) 2022 - 2023 Intel Corporation
*/
#include <linux/kernel.h>
#include <net/mac80211.h>
@@ -42,7 +42,7 @@ static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm,
* Of course the same can be done during add as well, but we must do
* it during remove, since we don't have the mvmvif->ap_sta pointer.
*/
- if (!sta && (keyconf->link_id >= 0 || !vif->valid_links))
+ if (!sta && (keyconf->link_id >= 0 || !ieee80211_vif_is_mld(vif)))
return BIT(link_info->ap_sta_id);
/* STA should be non-NULL now, but iwl_mvm_sta_fw_id_mask() checks */
@@ -51,10 +51,10 @@ static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm,
return iwl_mvm_sta_fw_id_mask(mvm, sta, keyconf->link_id);
}
-static u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *keyconf)
+u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *keyconf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u32 flags = 0;
@@ -164,13 +164,9 @@ static int __iwl_mvm_sec_key_del(struct iwl_mvm *mvm, u32 sta_mask,
return iwl_mvm_send_cmd_pdu(mvm, cmd_id, flags, sizeof(cmd), &cmd);
}
-int iwl_mvm_sec_key_add(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *keyconf)
+int iwl_mvm_mld_send_key(struct iwl_mvm *mvm, u32 sta_mask, u32 key_flags,
+ struct ieee80211_key_conf *keyconf)
{
- u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf);
- u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf);
u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
struct iwl_sec_key_cmd cmd = {
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
@@ -179,9 +175,14 @@ int iwl_mvm_sec_key_add(struct iwl_mvm *mvm,
.u.add.key_flags = cpu_to_le32(key_flags),
.u.add.tx_seq = cpu_to_le64(atomic64_read(&keyconf->tx_pn)),
};
+ int max_key_len = sizeof(cmd.u.add.key);
int ret;
- if (WARN_ON(keyconf->keylen > sizeof(cmd.u.add.key)))
+ if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+ keyconf->cipher == WLAN_CIPHER_SUITE_WEP104)
+ max_key_len -= IWL_SEC_WEP_KEY_OFFSET;
+
+ if (WARN_ON(keyconf->keylen > max_key_len))
return -EINVAL;
if (WARN_ON(!sta_mask))
@@ -223,6 +224,58 @@ int iwl_mvm_sec_key_add(struct iwl_mvm *mvm,
return ret;
}
+int iwl_mvm_sec_key_add(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *keyconf)
+{
+ u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf);
+ u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf);
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_vif_link_info *mvm_link = NULL;
+ int ret;
+
+ if (keyconf->keyidx == 4 || keyconf->keyidx == 5) {
+ unsigned int link_id = 0;
+
+ /* set to -1 for non-MLO right now */
+ if (keyconf->link_id >= 0)
+ link_id = keyconf->link_id;
+
+ mvm_link = mvmvif->link[link_id];
+ if (WARN_ON(!mvm_link))
+ return -EINVAL;
+
+ if (mvm_link->igtk) {
+ IWL_DEBUG_MAC80211(mvm, "remove old IGTK %d\n",
+ mvm_link->igtk->keyidx);
+ ret = iwl_mvm_sec_key_del(mvm, vif, sta,
+ mvm_link->igtk);
+ if (ret)
+ IWL_ERR(mvm,
+ "failed to remove old IGTK (ret=%d)\n",
+ ret);
+ }
+
+ WARN_ON(mvm_link->igtk);
+ }
+
+ ret = iwl_mvm_mld_send_key(mvm, sta_mask, key_flags, keyconf);
+ if (ret)
+ return ret;
+
+ if (mvm_link)
+ mvm_link->igtk = keyconf;
+
+ /* We don't really need this, but need it to be not invalid,
+ * and if we switch links multiple times it might go to be
+ * invalid when removed.
+ */
+ keyconf->hw_key_idx = 0;
+
+ return 0;
+}
+
static int _iwl_mvm_sec_key_del(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -231,11 +284,31 @@ static int _iwl_mvm_sec_key_del(struct iwl_mvm *mvm,
{
u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf);
u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf);
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
if (WARN_ON(!sta_mask))
return -EINVAL;
+ if (keyconf->keyidx == 4 || keyconf->keyidx == 5) {
+ struct iwl_mvm_vif_link_info *mvm_link;
+ unsigned int link_id = 0;
+
+ /* set to -1 for non-MLO right now */
+ if (keyconf->link_id >= 0)
+ link_id = keyconf->link_id;
+
+ mvm_link = mvmvif->link[link_id];
+ if (WARN_ON(!mvm_link))
+ return -EINVAL;
+
+ if (mvm_link->igtk == keyconf) {
+ /* no longer in HW - mark for later */
+ mvm_link->igtk->hw_key_idx = STA_KEY_IDX_INVALID;
+ mvm_link->igtk = NULL;
+ }
+ }
+
ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, keyconf->keyidx,
flags);
if (ret)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
index 1717fb52dc12..f313a8d771e4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2022 Intel Corporation
+ * Copyright (C) 2022 - 2023 Intel Corporation
*/
#include "mvm.h"
@@ -50,7 +50,7 @@ static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
* the association response successfully, so just skip all that
* and enable both when we have MLO.
*/
- if (vif->valid_links) {
+ if (ieee80211_vif_is_mld(vif)) {
iwl_mvm_mld_set_he_support(mvm, vif, cmd);
cmd->eht_support = cpu_to_le32(1);
return;
@@ -96,6 +96,7 @@ static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
u32 action, bool force_assoc_off)
{
struct iwl_mac_config_cmd cmd = {};
+ u16 esr_transition_timeout;
WARN_ON(vif->type != NL80211_IFTYPE_STATION);
@@ -115,16 +116,16 @@ static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
if (vif->cfg.assoc && !force_assoc_off) {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- cmd.client.is_assoc = cpu_to_le32(1);
+ cmd.client.is_assoc = 1;
if (!mvmvif->authorized &&
fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO))
cmd.client.data_policy |=
- cpu_to_le32(COEX_HIGH_PRIORITY_ENABLE);
+ cpu_to_le16(COEX_HIGH_PRIORITY_ENABLE);
} else {
- cmd.client.is_assoc = cpu_to_le32(0);
+ cmd.client.is_assoc = 0;
/* Allow beacons to pass through as long as we are not
* associated, or we do not have dtim period information.
@@ -132,14 +133,25 @@ static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_BEACON);
}
- cmd.client.assoc_id = cpu_to_le32(vif->cfg.aid);
+ cmd.client.assoc_id = cpu_to_le16(vif->cfg.aid);
+ if (ieee80211_vif_is_mld(vif)) {
+ esr_transition_timeout =
+ u16_get_bits(vif->cfg.eml_cap,
+ IEEE80211_EML_CAP_TRANSITION_TIMEOUT);
+
+ cmd.client.esr_transition_timeout =
+ min_t(u16, IEEE80211_EML_CAP_TRANSITION_TIMEOUT_128TU,
+ esr_transition_timeout);
+ cmd.client.medium_sync_delay =
+ cpu_to_le16(vif->cfg.eml_med_sync_delay);
+ }
if (vif->probe_req_reg && vif->cfg.assoc && vif->p2p)
cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_PROBE_REQ);
if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax)
cmd.client.data_policy |=
- iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif);
+ cpu_to_le16(iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif));
return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 7fb66c570959..8b6c641772ee 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2022 Intel Corporation
+ * Copyright (C) 2022-2023 Intel Corporation
*/
#include "mvm.h"
@@ -215,6 +215,53 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&mvm->mutex);
}
+static unsigned int iwl_mvm_mld_count_active_links(struct ieee80211_vif *vif)
+{
+ unsigned int n_active = 0;
+ int i;
+
+ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
+ struct ieee80211_bss_conf *link_conf;
+
+ link_conf = link_conf_dereference_protected(vif, i);
+ if (link_conf &&
+ rcu_access_pointer(link_conf->chanctx_conf))
+ n_active++;
+ }
+
+ return n_active;
+}
+
+static int iwl_mvm_esr_mode_active(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ int link_id, ret = 0;
+
+ mvmvif->esr_active = true;
+
+ /* Disable SMPS overrideing by user */
+ vif->driver_flags |= IEEE80211_VIF_DISABLE_SMPS_OVERRIDE;
+
+ iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW,
+ IEEE80211_SMPS_OFF);
+
+ for_each_mvm_vif_valid_link(mvmvif, link_id) {
+ struct iwl_mvm_vif_link_info *link = mvmvif->link[link_id];
+
+ if (!link->phy_ctxt)
+ continue;
+
+ ret = iwl_mvm_phy_send_rlc(mvm, link->phy_ctxt, 2, 2);
+ if (ret)
+ break;
+
+ link->phy_ctxt->rlc_disabled = true;
+ }
+
+ return ret;
+}
+
static int
__iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
@@ -224,10 +271,18 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
{
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
+ unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
unsigned int link_id = link_conf->link_id;
int ret;
+ /* if the assigned one was not counted yet, count it now */
+ if (!rcu_access_pointer(link_conf->chanctx_conf))
+ n_active++;
+
+ if (n_active > iwl_mvm_max_active_links(mvm, vif))
+ return -EOPNOTSUPP;
+
if (WARN_ON_ONCE(!mvmvif->link[link_id]))
return -EINVAL;
@@ -243,6 +298,15 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
}
}
+ if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) {
+ mvmvif->link[link_id]->listen_lmac = true;
+ ret = iwl_mvm_esr_mode_active(mvm, vif);
+ if (ret) {
+ IWL_ERR(mvm, "failed to activate ESR mode (%d)\n", ret);
+ return ret;
+ }
+ }
+
mvmvif->link[link_id]->phy_ctxt = phy_ctxt;
if (switching_chanctx) {
@@ -326,14 +390,62 @@ static int iwl_mvm_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
return ret;
}
+static int iwl_mvm_esr_mode_inactive(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct ieee80211_bss_conf *link_conf;
+ int link_id, ret = 0;
+
+ mvmvif->esr_active = false;
+
+ vif->driver_flags &= ~IEEE80211_VIF_DISABLE_SMPS_OVERRIDE;
+
+ iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW,
+ IEEE80211_SMPS_AUTOMATIC);
+
+ for_each_vif_active_link(vif, link_conf, link_id) {
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct iwl_mvm_phy_ctxt *phy_ctxt;
+ u8 static_chains, dynamic_chains;
+
+ mvmvif->link[link_id]->listen_lmac = false;
+
+ rcu_read_lock();
+
+ chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
+ phy_ctxt = mvmvif->link[link_id]->phy_ctxt;
+
+ if (!chanctx_conf || !phy_ctxt) {
+ rcu_read_unlock();
+ continue;
+ }
+
+ phy_ctxt->rlc_disabled = false;
+ static_chains = chanctx_conf->rx_chains_static;
+ dynamic_chains = chanctx_conf->rx_chains_dynamic;
+
+ rcu_read_unlock();
+
+ ret = iwl_mvm_phy_send_rlc(mvm, phy_ctxt, static_chains,
+ dynamic_chains);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
static void
__iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx,
bool switching_chanctx)
+
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
unsigned int link_id = link_conf->link_id;
/* shouldn't happen, but verify link_id is valid before accessing */
@@ -352,6 +464,14 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
mvmvif->ap_ibss_active = false;
}
+ if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) {
+ int ret = iwl_mvm_esr_mode_inactive(mvm, vif);
+
+ if (ret)
+ IWL_ERR(mvm, "failed to deactivate ESR mode (%d)\n",
+ ret);
+ }
+
if (vif->type == NL80211_IFTYPE_MONITOR)
iwl_mvm_mld_rm_snif_sta(mvm, vif);
@@ -422,7 +542,7 @@ static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,
if (iwl_mvm_phy_ctx_count(mvm) > 1)
iwl_mvm_teardown_tdls_peers(mvm);
- iwl_mvm_ftm_restart_responder(mvm, vif);
+ iwl_mvm_ftm_restart_responder(mvm, vif, link_conf);
goto out_unlock;
@@ -492,7 +612,7 @@ static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw,
enum ieee80211_sta_state old_state,
enum ieee80211_sta_state new_state)
{
- struct iwl_mvm_sta_state_ops callbacks = {
+ static const struct iwl_mvm_sta_state_ops callbacks = {
.add_sta = iwl_mvm_mld_add_sta,
.update_sta = iwl_mvm_mld_update_sta,
.rm_sta = iwl_mvm_mld_rm_sta,
@@ -697,7 +817,11 @@ iwl_mvm_mld_link_info_changed_ap_ibss(struct iwl_mvm *mvm,
if (link_conf->he_support)
link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
- if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT |
+ if (changes & BSS_CHANGED_ERP_SLOT)
+ link_changes |= LINK_CONTEXT_MODIFY_RATES_INFO;
+
+ if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_SLOT |
+ BSS_CHANGED_HT |
BSS_CHANGED_BANDWIDTH | BSS_CHANGED_QOS |
BSS_CHANGED_HE_BSS_COLOR) &&
iwl_mvm_link_changed(mvm, vif, link_conf,
@@ -711,7 +835,7 @@ iwl_mvm_mld_link_info_changed_ap_ibss(struct iwl_mvm *mvm,
/* FIXME: need to decide if we need FTM responder per link */
if (changes & BSS_CHANGED_FTM_RESPONDER) {
- int ret = iwl_mvm_ftm_start_responder(mvm, vif);
+ int ret = iwl_mvm_ftm_start_responder(mvm, vif, link_conf);
if (ret)
IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n",
@@ -779,7 +903,7 @@ iwl_mvm_mld_switch_vif_chanctx(struct ieee80211_hw *hw,
int n_vifs,
enum ieee80211_chanctx_switch_mode mode)
{
- struct iwl_mvm_switch_vif_chanctx_ops ops = {
+ static const struct iwl_mvm_switch_vif_chanctx_ops ops = {
.__assign_vif_chanctx = __iwl_mvm_mld_assign_vif_chanctx,
.__unassign_vif_chanctx = __iwl_mvm_mld_unassign_vif_chanctx,
};
@@ -816,8 +940,12 @@ iwl_mvm_mld_mac_conf_tx(struct ieee80211_hw *hw,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_vif_link_info *mvm_link = mvmvif->link[link_id];
- mvmvif->deflink.queue_params[ac] = *params;
+ if (!mvm_link)
+ return -EINVAL;
+
+ mvm_link->queue_params[ac] = *params;
/* No need to update right away, we'll get BSS_CHANGED_QOS
* The exception is P2P_DEVICE interface which needs immediate update.
@@ -871,7 +999,7 @@ static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_channel *channel, int duration,
enum ieee80211_roc_type type)
{
- struct iwl_mvm_roc_ops ops = {
+ static const struct iwl_mvm_roc_ops ops = {
.add_aux_sta_for_hs20 = iwl_mvm_mld_add_aux_sta,
.switch_phy_ctxt = iwl_mvm_link_switch_phy_ctx,
};
@@ -886,33 +1014,16 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
{
struct iwl_mvm_vif_link_info *new_link[IEEE80211_MLD_MAX_NUM_LINKS] = {};
+ unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
u16 removed = old_links & ~new_links;
u16 added = new_links & ~old_links;
int err, i;
- if (hweight16(new_links) > 2) {
+ if (hweight16(new_links) > 1 &&
+ n_active > iwl_mvm_max_active_links(mvm, vif))
return -EOPNOTSUPP;
- } else if (hweight16(new_links) > 1) {
- unsigned int n_active = 0;
-
- for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
- struct ieee80211_bss_conf *link_conf;
-
- link_conf = link_conf_dereference_protected(vif, i);
- if (link_conf &&
- rcu_access_pointer(link_conf->chanctx_conf))
- n_active++;
- }
-
- if (vif->type == NL80211_IFTYPE_AP) {
- if (n_active > mvm->fw->ucode_capa.num_beacons)
- return -EOPNOTSUPP;
- } else if (n_active > 1) {
- return -EOPNOTSUPP;
- }
- }
for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
int r;
@@ -956,9 +1067,7 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
goto out_err;
kfree(mvmvif->link[i]);
mvmvif->link[i] = NULL;
- }
-
- if (added & BIT(i)) {
+ } else if (added & BIT(i)) {
struct ieee80211_bss_conf *link_conf;
link_conf = link_conf_dereference_protected(vif, i);
@@ -975,6 +1084,9 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
}
}
+ if (err)
+ goto out_err;
+
err = 0;
if (new_links == 0) {
mvmvif->link[0] = &mvmvif->deflink;
@@ -1037,6 +1149,7 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx,
.mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover,
.flush = iwl_mvm_mac_flush,
+ .flush_sta = iwl_mvm_mac_flush_sta,
.sched_scan_start = iwl_mvm_mac_sched_scan_start,
.sched_scan_stop = iwl_mvm_mac_sched_scan_stop,
.set_key = iwl_mvm_mac_set_key,
@@ -1093,7 +1206,7 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.abort_pmsr = iwl_mvm_abort_pmsr,
#ifdef CONFIG_IWLWIFI_DEBUGFS
- .sta_add_debugfs = iwl_mvm_sta_add_debugfs,
+ .link_sta_add_debugfs = iwl_mvm_link_sta_add_debugfs,
#endif
.set_hw_timestamp = iwl_mvm_set_hw_timestamp,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index 85a4ce8449ad..524852cf5cd2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2022 Intel Corporation
+ * Copyright (C) 2022-2023 Intel Corporation
*/
#include "mvm.h"
#include "time-sync.h"
@@ -71,6 +71,11 @@ static int iwl_mvm_mld_add_int_sta_to_fw(struct iwl_mvm *mvm,
cmd.station_type = cpu_to_le32(sta->type);
+ if (fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_STA_EXP_MFP_SUPPORT) &&
+ sta->type == STATION_TYPE_BCAST_MGMT)
+ cmd.mfp = cpu_to_le32(1);
+
if (addr) {
memcpy(cmd.peer_mld_address, addr, ETH_ALEN);
memcpy(cmd.peer_link_address, addr, ETH_ALEN);
@@ -128,11 +133,11 @@ static int iwl_mvm_add_aux_sta_to_fw(struct iwl_mvm *mvm,
/*
* Adds an internal sta to the FW table with its queues
*/
-static int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm,
- struct iwl_mvm_int_sta *sta,
- const u8 *addr, int link_id,
- u16 *queue, u8 tid,
- unsigned int *_wdg_timeout)
+int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm,
+ struct iwl_mvm_int_sta *sta,
+ const u8 *addr, int link_id,
+ u16 *queue, u8 tid,
+ unsigned int *_wdg_timeout)
{
int ret, txq;
unsigned int wdg_timeout = _wdg_timeout ? *_wdg_timeout :
@@ -364,6 +369,9 @@ int iwl_mvm_mld_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
lockdep_assert_held(&mvm->mutex);
+ if (WARN_ON(!link))
+ return -EIO;
+
switch (vif->type) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_ADHOC:
@@ -393,6 +401,9 @@ int iwl_mvm_mld_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
lockdep_assert_held(&mvm->mutex);
+ if (WARN_ON(!link))
+ return -EIO;
+
return iwl_mvm_mld_rm_int_sta(mvm, &link->mcast_sta, true, 0,
&link->cab_queue);
}
@@ -442,6 +453,11 @@ static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
if (mvm_sta->sta_state >= IEEE80211_STA_ASSOC)
cmd.assoc_id = cpu_to_le32(sta->aid);
+ if (fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_STA_EXP_MFP_SUPPORT) &&
+ (sta->mfp || mvm_sta->sta_state < IEEE80211_STA_AUTHORIZED))
+ cmd.mfp = cpu_to_le32(1);
+
switch (link_sta->rx_nss) {
case 1:
cmd.mimo = cpu_to_le32(0);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 9e5008e0e47f..b18c91c5dd5d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -104,6 +104,7 @@ struct iwl_mvm_phy_ctxt {
/* track for RLC config command */
u32 center_freq1;
+ bool rlc_disabled;
};
struct iwl_mvm_time_event_data {
@@ -300,6 +301,8 @@ struct iwl_probe_resp_data {
* @he_ru_2mhz_block: 26-tone RU OFDMA transmissions should be blocked
* @queue_params: QoS params for this MAC
* @mgmt_queue: queue number for unbufferable management frames
+ * @igtk: the current IGTK programmed into the firmware
+ * @listen_lmac: indicates this link is allocated to the listen LMAC
*/
struct iwl_mvm_vif_link_info {
u8 bssid[ETH_ALEN];
@@ -317,8 +320,11 @@ struct iwl_mvm_vif_link_info {
enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ];
struct iwl_probe_resp_data __rcu *probe_resp_data;
+ struct ieee80211_key_conf *igtk;
+
bool he_ru_2mhz_block;
bool active;
+ bool listen_lmac;
u16 cab_queue;
/* Assigned while mac80211 has the link in a channel context,
@@ -370,6 +376,7 @@ struct iwl_mvm_vif {
bool ap_ibss_active;
bool pm_enabled;
bool monitor_active;
+ bool esr_active;
u8 low_latency: 6;
u8 low_latency_actual: 1;
@@ -415,7 +422,7 @@ struct iwl_mvm_vif {
#endif
/* FW identified misbehaving AP */
- u8 uapsd_misbehaving_bssid[ETH_ALEN];
+ u8 uapsd_misbehaving_ap_addr[ETH_ALEN] __aligned(2);
struct delayed_work uapsd_nonagg_detected_wk;
bool csa_countdown;
@@ -1003,6 +1010,8 @@ struct iwl_mvm {
struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER];
+ struct ieee80211_bss_conf __rcu *link_id_to_link_conf[IWL_MVM_FW_MAX_LINK_ID + 1];
+
/* -1 for always, 0 for never, >0 for that many times */
s8 fw_restart;
u8 *error_recovery_buf;
@@ -1174,6 +1183,10 @@ struct iwl_mvm {
__le16 cur_aid;
u8 cur_bssid[ETH_ALEN];
+#ifdef CONFIG_ACPI
+ struct iwl_phy_specific_cfg phy_filters;
+#endif
+
unsigned long last_6ghz_passive_scan_jiffies;
unsigned long last_reset_or_resume_time_jiffies;
@@ -1302,6 +1315,19 @@ iwl_mvm_rcu_dereference_vif_id(struct iwl_mvm *mvm, u8 vif_id, bool rcu)
lockdep_is_held(&mvm->mutex));
}
+static inline struct ieee80211_bss_conf *
+iwl_mvm_rcu_fw_link_id_to_link_conf(struct iwl_mvm *mvm, u8 link_id, bool rcu)
+{
+ if (WARN_ON(link_id >= ARRAY_SIZE(mvm->link_id_to_link_conf)))
+ return NULL;
+
+ if (rcu)
+ return rcu_dereference(mvm->link_id_to_link_conf[link_id]);
+
+ return rcu_dereference_protected(mvm->link_id_to_link_conf[link_id],
+ lockdep_is_held(&mvm->mutex));
+}
+
static inline bool iwl_mvm_is_adaptive_dwell_supported(struct iwl_mvm *mvm)
{
return fw_has_api(&mvm->fw->ucode_capa,
@@ -1415,10 +1441,16 @@ static inline bool iwl_mvm_has_mld_api(const struct iwl_fw *fw)
IWL_UCODE_TLV_CAPA_MLD_API_SUPPORT);
}
+static inline bool iwl_mvm_has_new_station_api(const struct iwl_fw *fw)
+{
+ return iwl_mvm_has_mld_api(fw) ||
+ iwl_fw_lookup_cmd_ver(fw, ADD_STA, 0) >= 12;
+}
+
static inline bool iwl_mvm_has_new_tx_api(struct iwl_mvm *mvm)
{
/* TODO - replace with TLV once defined */
- return mvm->trans->trans_cfg->use_tfh;
+ return mvm->trans->trans_cfg->gen2;
}
static inline bool iwl_mvm_has_unified_ucode(struct iwl_mvm *mvm)
@@ -1516,17 +1548,30 @@ static inline bool iwl_mvm_is_ctdp_supported(struct iwl_mvm *mvm)
IWL_UCODE_TLV_CAPA_CTDP_SUPPORT);
}
-static inline bool iwl_mvm_has_new_tx_csum(struct iwl_mvm *mvm)
+static inline bool iwl_mvm_is_esr_supported(struct iwl_trans *trans)
+{
+ if ((CSR_HW_RFID_TYPE(trans->hw_rf_id) == IWL_CFG_RF_TYPE_FM) &&
+ !CSR_HW_RFID_IS_CDB(trans->hw_rf_id))
+ /* Step A doesn't support eSR */
+ return CSR_HW_RFID_STEP(trans->hw_rf_id);
+
+ return false;
+}
+
+static inline int iwl_mvm_max_active_links(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
{
- if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
- return false;
+ struct iwl_trans *trans = mvm->fwrt.trans;
+
+ if (vif->type == NL80211_IFTYPE_AP)
+ return mvm->fw->ucode_capa.num_beacons;
- if (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_BZ &&
- CSR_HW_REV_TYPE(mvm->trans->hw_rev) == IWL_CFG_MAC_TYPE_GL &&
- mvm->trans->hw_rev_step <= SILICON_B_STEP)
- return false;
+ if (iwl_mvm_is_esr_supported(trans) ||
+ (CSR_HW_RFID_TYPE(trans->hw_rf_id) == IWL_CFG_RF_TYPE_FM &&
+ CSR_HW_RFID_IS_CDB(trans->hw_rf_id)))
+ return IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM;
- return true;
+ return 1;
}
extern const u8 iwl_mvm_ac_to_tx_fifo[];
@@ -1606,7 +1651,6 @@ void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
unsigned int tid);
-u32 iwl_mvm_tx_csum_bz(struct iwl_mvm *mvm, struct sk_buff *skb, bool amsdu);
#ifdef CONFIG_IWLWIFI_DEBUG
const char *iwl_mvm_get_tx_fail_reason(u32 status);
@@ -1741,6 +1785,8 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm,
int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm);
u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef);
u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef);
+int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
+ u8 chains_static, u8 chains_dynamic);
/* MAC (virtual interface) programming */
@@ -1758,7 +1804,7 @@ void iwl_mvm_set_fw_qos_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
struct iwl_ac_qos *ac, __le32 *qos_flags);
bool iwl_mvm_set_fw_mu_edca_params(struct iwl_mvm *mvm,
- struct iwl_mvm_vif *mvmvif,
+ const struct iwl_mvm_vif_link_info *link_info,
struct iwl_he_backoff_conf *trig_based_txf);
void iwl_mvm_set_fw_dtim_tbtt(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
@@ -1774,8 +1820,8 @@ void iwl_mvm_mac_ctxt_cmd_ap_set_filter_flags(struct iwl_mvm *mvm,
int iwl_mvm_get_mac_type(struct ieee80211_vif *vif);
__le32 iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
-__le32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif);
+u32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif);
int iwl_mvm_mld_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mld_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool force_assoc_off);
@@ -1826,6 +1872,7 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
/* Bindings */
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+u32 iwl_mvm_get_lmac_id(struct iwl_mvm *mvm, enum nl80211_band band);
/* Links */
int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -1873,7 +1920,7 @@ void
iwl_mvm_bss_info_changed_common(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
- struct iwl_mvm_bss_info_changed_ops *callbacks,
+ const struct iwl_mvm_bss_info_changed_ops *callbacks,
u64 changes);
void
iwl_mvm_bss_info_changed_station_common(struct iwl_mvm *mvm,
@@ -1907,7 +1954,7 @@ struct iwl_mvm_roc_ops {
int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_channel *channel, int duration,
enum ieee80211_roc_type type,
- struct iwl_mvm_roc_ops *ops);
+ const struct iwl_mvm_roc_ops *ops);
int iwl_mvm_cancel_roc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
/*Session Protection */
@@ -2204,7 +2251,7 @@ static inline void iwl_mvm_vendor_cmds_register(struct iwl_mvm *mvm) {}
#endif
/* Location Aware Regulatory */
-struct iwl_mcc_update_resp *
+struct iwl_mcc_update_resp_v8 *
iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
enum iwl_mcc_source src_id);
int iwl_mvm_init_mcc(struct iwl_mvm *mvm);
@@ -2224,9 +2271,11 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool added_vif);
/* FTM responder */
-int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf);
void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif);
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf);
void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
int iwl_mvm_ftm_resp_remove_pasn_sta(struct iwl_mvm *mvm,
@@ -2322,10 +2371,10 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm);
int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm);
void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm);
#ifdef CONFIG_IWLWIFI_DEBUGFS
-void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct dentry *dir);
+void iwl_mvm_link_sta_add_debugfs(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_link_sta *link_sta,
+ struct dentry *dir);
#endif
/* new MLD related APIs */
@@ -2346,6 +2395,12 @@ int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
u32 old_sta_mask,
u32 new_sta_mask);
+int iwl_mvm_mld_send_key(struct iwl_mvm *mvm, u32 sta_mask, u32 key_flags,
+ struct ieee80211_key_conf *keyconf);
+u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *keyconf);
bool iwl_rfi_supported(struct iwl_mvm *mvm);
int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm,
@@ -2406,7 +2461,7 @@ iwl_mvm_switch_vif_chanctx_common(struct ieee80211_hw *hw,
struct ieee80211_vif_chanctx_switch *vifs,
int n_vifs,
enum ieee80211_chanctx_switch_mode mode,
- struct iwl_mvm_switch_vif_chanctx_ops *ops);
+ const struct iwl_mvm_switch_vif_chanctx_ops *ops);
/* Channel info utils */
static inline bool iwl_mvm_has_ultra_hb_channel(struct iwl_mvm *mvm)
@@ -2604,6 +2659,8 @@ void iwl_mvm_mac_mgd_complete_tx(struct ieee80211_hw *hw,
struct ieee80211_prep_tx_info *info);
void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop);
+void iwl_mvm_mac_flush_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
index fdf60afb0f3f..f67ab8ee18c2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
@@ -404,7 +404,7 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
return ret < 0 ? ret : 0;
}
-struct iwl_mcc_update_resp *
+struct iwl_mcc_update_resp_v8 *
iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
enum iwl_mcc_source src_id)
{
@@ -412,7 +412,7 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
.mcc = cpu_to_le16(alpha2[0] << 8 | alpha2[1]),
.source_id = (u8)src_id,
};
- struct iwl_mcc_update_resp *resp_cp;
+ struct iwl_mcc_update_resp_v8 *resp_cp;
struct iwl_rx_packet *pkt;
struct iwl_host_cmd cmd = {
.id = MCC_UPDATE_CMD,
@@ -420,7 +420,7 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
.data = { &mcc_update_cmd },
};
- int ret;
+ int ret, resp_ver;
u32 status;
int resp_len, n_channels;
u16 mcc;
@@ -439,24 +439,60 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
pkt = cmd.resp_pkt;
+ resp_ver = iwl_fw_lookup_notif_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP,
+ MCC_UPDATE_CMD, 0);
+
/* Extract MCC response */
- if (fw_has_capa(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT)) {
- struct iwl_mcc_update_resp *mcc_resp = (void *)pkt->data;
+ if (resp_ver >= 8) {
+ struct iwl_mcc_update_resp_v8 *mcc_resp_v8 = (void *)pkt->data;
+
+ n_channels = __le32_to_cpu(mcc_resp_v8->n_channels);
+ if (iwl_rx_packet_payload_len(pkt) !=
+ struct_size(mcc_resp_v8, channels, n_channels)) {
+ resp_cp = ERR_PTR(-EINVAL);
+ goto exit;
+ }
+ resp_len = struct_size(resp_cp, channels, n_channels);
+ resp_cp = kzalloc(resp_len, GFP_KERNEL);
+ if (!resp_cp) {
+ resp_cp = ERR_PTR(-ENOMEM);
+ goto exit;
+ }
+ resp_cp->status = mcc_resp_v8->status;
+ resp_cp->mcc = mcc_resp_v8->mcc;
+ resp_cp->cap = mcc_resp_v8->cap;
+ resp_cp->source_id = mcc_resp_v8->source_id;
+ resp_cp->time = mcc_resp_v8->time;
+ resp_cp->geo_info = mcc_resp_v8->geo_info;
+ resp_cp->n_channels = mcc_resp_v8->n_channels;
+ memcpy(resp_cp->channels, mcc_resp_v8->channels,
+ n_channels * sizeof(__le32));
+ } else if (fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT)) {
+ struct iwl_mcc_update_resp_v4 *mcc_resp_v4 = (void *)pkt->data;
- n_channels = __le32_to_cpu(mcc_resp->n_channels);
+ n_channels = __le32_to_cpu(mcc_resp_v4->n_channels);
if (iwl_rx_packet_payload_len(pkt) !=
- struct_size(mcc_resp, channels, n_channels)) {
+ struct_size(mcc_resp_v4, channels, n_channels)) {
resp_cp = ERR_PTR(-EINVAL);
goto exit;
}
- resp_len = sizeof(struct iwl_mcc_update_resp) +
- n_channels * sizeof(__le32);
- resp_cp = kmemdup(mcc_resp, resp_len, GFP_KERNEL);
+ resp_len = struct_size(resp_cp, channels, n_channels);
+ resp_cp = kzalloc(resp_len, GFP_KERNEL);
if (!resp_cp) {
resp_cp = ERR_PTR(-ENOMEM);
goto exit;
}
+
+ resp_cp->status = mcc_resp_v4->status;
+ resp_cp->mcc = mcc_resp_v4->mcc;
+ resp_cp->cap = cpu_to_le32(le16_to_cpu(mcc_resp_v4->cap));
+ resp_cp->source_id = mcc_resp_v4->source_id;
+ resp_cp->time = mcc_resp_v4->time;
+ resp_cp->geo_info = mcc_resp_v4->geo_info;
+ resp_cp->n_channels = mcc_resp_v4->n_channels;
+ memcpy(resp_cp->channels, mcc_resp_v4->channels,
+ n_channels * sizeof(__le32));
} else {
struct iwl_mcc_update_resp_v3 *mcc_resp_v3 = (void *)pkt->data;
@@ -466,8 +502,7 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
resp_cp = ERR_PTR(-EINVAL);
goto exit;
}
- resp_len = sizeof(struct iwl_mcc_update_resp) +
- n_channels * sizeof(__le32);
+ resp_len = struct_size(resp_cp, channels, n_channels);
resp_cp = kzalloc(resp_len, GFP_KERNEL);
if (!resp_cp) {
resp_cp = ERR_PTR(-ENOMEM);
@@ -476,7 +511,7 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
resp_cp->status = mcc_resp_v3->status;
resp_cp->mcc = mcc_resp_v3->mcc;
- resp_cp->cap = cpu_to_le16(mcc_resp_v3->cap);
+ resp_cp->cap = cpu_to_le32(mcc_resp_v3->cap);
resp_cp->source_id = mcc_resp_v3->source_id;
resp_cp->time = mcc_resp_v3->time;
resp_cp->geo_info = mcc_resp_v3->geo_info;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c b/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c
index a8bd0f5f795c..dfb16ca5b438 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c
@@ -198,6 +198,10 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
memcpy(common->arp_mac_addr, vif->addr, ETH_ALEN);
}
+ if (fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_OFFLOAD_BTM_SUPPORT))
+ enabled |= IWL_D3_PROTO_OFFLOAD_BTM;
+
if (!disable_offloading)
common->enabled = cpu_to_le32(enabled);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 32625bfacaae..5336a4afde4d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2020 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -192,8 +192,7 @@ static void iwl_mvm_rx_monitor_notif(struct iwl_mvm *mvm,
WARN_ON(!(sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40));
sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- he_cap = ieee80211_get_he_iftype_cap(sband,
- ieee80211_vif_type_p2p(vif));
+ he_cap = ieee80211_get_he_iftype_cap_vif(sband, vif);
if (he_cap) {
/* we know that ours is writable */
@@ -449,7 +448,6 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(ADD_STA_KEY),
HCMD_NAME(ADD_STA),
HCMD_NAME(REMOVE_STA),
- HCMD_NAME(FW_GET_ITEM_CMD),
HCMD_NAME(TX_CMD),
HCMD_NAME(SCD_QUEUE_CFG),
HCMD_NAME(TXPATH_FLUSH),
@@ -512,7 +510,6 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(REPLY_BEACON_FILTERING_CMD),
HCMD_NAME(D3_CONFIG_CMD),
HCMD_NAME(PROT_OFFLOAD_CONFIG_CMD),
- HCMD_NAME(OFFLOADS_QUERY_CMD),
HCMD_NAME(MATCH_FOUND_NOTIFICATION),
HCMD_NAME(DTS_MEASUREMENT_NOTIFICATION),
HCMD_NAME(WOWLAN_PATTERNS),
@@ -1604,7 +1601,9 @@ static void iwl_mvm_rx_common(struct iwl_mvm *mvm,
if (rx_h->cmd_id != WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd))
continue;
- if (unlikely(pkt_len < rx_h->min_size))
+ if (IWL_FW_CHECK(mvm, pkt_len < rx_h->min_size,
+ "unexpected notification 0x%04x size %d, need %d\n",
+ rx_h->cmd_id, pkt_len, rx_h->min_size))
return;
if (rx_h->context == RX_HANDLER_SYNC) {
@@ -1743,8 +1742,11 @@ static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode,
else
set_bit(IWL_MVM_TXQ_STATE_STOP_FULL, &mvmtxq->state);
- if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST)
+ if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST) {
+ local_bh_disable();
iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
+ local_bh_enable();
+ }
}
out:
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
index 3ab6fb83a175..a5b432bc9e2f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2017 Intel Deutschland GmbH
*/
@@ -151,7 +151,7 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
struct cfg80211_chan_def *chandef,
u8 chains_static, u8 chains_dynamic)
{
- cmd->lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm->fw,
+ cmd->lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm,
chandef->chan->band));
/* Set the channel info data */
@@ -163,15 +163,18 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
chains_static, chains_dynamic);
}
-static int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm,
- struct iwl_mvm_phy_ctxt *ctxt,
- u8 chains_static, u8 chains_dynamic)
+int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
+ u8 chains_static, u8 chains_dynamic)
{
struct iwl_rlc_config_cmd cmd = {
.phy_id = cpu_to_le32(ctxt->id),
};
- if (iwl_fw_lookup_cmd_ver(mvm->fw, WIDE_ID(DATA_PATH_GROUP, RLC_CONFIG_CMD), 0) < 2)
+ if (ctxt->rlc_disabled)
+ return 0;
+
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, WIDE_ID(DATA_PATH_GROUP,
+ RLC_CONFIG_CMD), 0) < 2)
return 0;
BUILD_BUG_ON(IWL_RLC_CHAIN_INFO_DRIVER_FORCE !=
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
index ac1dae52556f..9131b5f1bc76 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2019, 2021-2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -237,8 +237,8 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
- ETH_ALEN))
+ if (ether_addr_equal(mvmvif->uapsd_misbehaving_ap_addr,
+ vif->cfg.ap_addr))
return false;
/*
@@ -327,12 +327,11 @@ static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm,
if (WARN_ON(!dtimper_tu))
return;
- /* configure skip over dtim up to 306TU - 314 msec */
- skip = max_t(u8, 1, 306 / dtimper_tu);
+ /* configure skip over dtim up to 900 TU DTIM interval */
+ skip = max_t(u8, 1, 900 / dtimper_tu);
}
- /* the firmware really expects "look at every X DTIMs", so add 1 */
- cmd->skip_dtim_periods = 1 + skip;
+ cmd->skip_dtim_periods = skip;
cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
}
@@ -502,9 +501,9 @@ void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- if (memcmp(vif->bss_conf.bssid, mvmvif->uapsd_misbehaving_bssid,
- ETH_ALEN))
- eth_zero_addr(mvmvif->uapsd_misbehaving_bssid);
+ if (!ether_addr_equal(mvmvif->uapsd_misbehaving_ap_addr,
+ vif->cfg.ap_addr))
+ eth_zero_addr(mvmvif->uapsd_misbehaving_ap_addr);
}
static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac,
@@ -512,14 +511,23 @@ static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac,
{
u8 *ap_sta_id = _data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct ieee80211_bss_conf *link_conf;
+ unsigned int link_id;
- /* The ap_sta_id is not expected to change during current association
- * so no explicit protection is needed
- */
- if (mvmvif->deflink.ap_sta_id == *ap_sta_id)
- memcpy(mvmvif->uapsd_misbehaving_bssid,
- vif->bss_conf.bssid,
- ETH_ALEN);
+ rcu_read_lock();
+ for_each_vif_active_link(vif, link_conf, link_id) {
+ struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id];
+
+ /* The ap_sta_id is not expected to change during current
+ * association so no explicit protection is needed
+ */
+ if (link_info->ap_sta_id == *ap_sta_id) {
+ ether_addr_copy(mvmvif->uapsd_misbehaving_ap_addr,
+ vif->cfg.ap_addr);
+ break;
+ }
+ }
+ rcu_read_unlock();
}
void iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
@@ -647,30 +655,32 @@ static void iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
return;
/* enable PM on bss if bss stand alone */
- if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) {
+ if (bss_mvmvif && vifs->bss_active && !vifs->p2p_active &&
+ !vifs->ap_active) {
bss_mvmvif->pm_enabled = true;
return;
}
/* enable PM on p2p if p2p stand alone */
- if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active) {
+ if (p2p_mvmvif && vifs->p2p_active && !vifs->bss_active &&
+ !vifs->ap_active) {
p2p_mvmvif->pm_enabled = true;
return;
}
- if (vifs->bss_active && vifs->p2p_active)
+ if (p2p_mvmvif && bss_mvmvif && vifs->bss_active && vifs->p2p_active)
client_same_channel =
iwl_mvm_have_links_same_channel(bss_mvmvif, p2p_mvmvif);
- if (vifs->bss_active && vifs->ap_active)
+ if (bss_mvmvif && ap_mvmvif && vifs->bss_active && vifs->ap_active)
ap_same_channel =
iwl_mvm_have_links_same_channel(bss_mvmvif, ap_mvmvif);
/* clients are not stand alone: enable PM if DCM */
if (!(client_same_channel || ap_same_channel)) {
- if (vifs->bss_active)
+ if (bss_mvmvif && vifs->bss_active)
bss_mvmvif->pm_enabled = true;
- if (vifs->p2p_active)
+ if (p2p_mvmvif && vifs->p2p_active)
p2p_mvmvif->pm_enabled = true;
return;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
index c3a00bfbeef2..6cba8a353b53 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#include "rs.h"
#include "fw-api.h"
@@ -63,12 +63,11 @@ static u8 rs_fw_sgi_cw_support(struct ieee80211_link_sta *link_sta)
static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_link_sta *link_sta,
- struct ieee80211_supported_band *sband)
+ const struct ieee80211_sta_he_cap *sband_he_cap)
{
struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;
struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap;
struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap;
- const struct ieee80211_sta_he_cap *sband_he_cap;
bool vht_ena = vht_cap->vht_supported;
u16 flags = 0;
@@ -94,8 +93,6 @@ static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
- sband_he_cap = ieee80211_get_he_iftype_cap(sband,
- ieee80211_vif_type_p2p(vif));
if (sband_he_cap &&
!(sband_he_cap->he_cap_elem.phy_cap_info[1] &
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
@@ -197,16 +194,14 @@ static u16 rs_fw_he_ieee80211_mcs_to_rs_mcs(u16 mcs)
static void
rs_fw_he_set_enabled_rates(const struct ieee80211_link_sta *link_sta,
- struct ieee80211_supported_band *sband,
+ const struct ieee80211_sta_he_cap *sband_he_cap,
struct iwl_tlc_config_cmd_v4 *cmd)
{
const struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap;
u16 mcs_160 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
u16 mcs_80 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
- u16 tx_mcs_80 =
- le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_80);
- u16 tx_mcs_160 =
- le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160);
+ u16 tx_mcs_80 = le16_to_cpu(sband_he_cap->he_mcs_nss_supp.tx_mcs_80);
+ u16 tx_mcs_160 = le16_to_cpu(sband_he_cap->he_mcs_nss_supp.tx_mcs_160);
int i;
u8 nss = link_sta->rx_nss;
@@ -289,7 +284,8 @@ rs_fw_rs_mcs2eht_mcs(enum IWL_TLC_MCS_PER_BW bw,
static void
rs_fw_eht_set_enabled_rates(struct ieee80211_vif *vif,
const struct ieee80211_link_sta *link_sta,
- struct ieee80211_supported_band *sband,
+ const struct ieee80211_sta_he_cap *sband_he_cap,
+ const struct ieee80211_sta_eht_cap *sband_eht_cap,
struct iwl_tlc_config_cmd_v4 *cmd)
{
/* peer RX mcs capa */
@@ -297,7 +293,7 @@ rs_fw_eht_set_enabled_rates(struct ieee80211_vif *vif,
&link_sta->eht_cap.eht_mcs_nss_supp;
/* our TX mcs capa */
const struct ieee80211_eht_mcs_nss_supp *eht_tx_mcs =
- &sband->iftype_data->eht_cap.eht_mcs_nss_supp;
+ &sband_eht_cap->eht_mcs_nss_supp;
enum IWL_TLC_MCS_PER_BW bw;
struct ieee80211_eht_mcs_nss_supp_20mhz_only mcs_rx_20;
@@ -316,7 +312,7 @@ rs_fw_eht_set_enabled_rates(struct ieee80211_vif *vif,
}
/* nic is 20Mhz only */
- if (!(sband->iftype_data->he_cap.he_cap_elem.phy_cap_info[0] &
+ if (!(sband_he_cap->he_cap_elem.phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) {
mcs_tx_20 = eht_tx_mcs->only_20mhz;
} else {
@@ -370,6 +366,8 @@ rs_fw_eht_set_enabled_rates(struct ieee80211_vif *vif,
static void rs_fw_set_supp_rates(struct ieee80211_vif *vif,
struct ieee80211_link_sta *link_sta,
struct ieee80211_supported_band *sband,
+ const struct ieee80211_sta_he_cap *sband_he_cap,
+ const struct ieee80211_sta_eht_cap *sband_eht_cap,
struct iwl_tlc_config_cmd_v4 *cmd)
{
int i;
@@ -388,12 +386,13 @@ static void rs_fw_set_supp_rates(struct ieee80211_vif *vif,
cmd->mode = IWL_TLC_MNG_MODE_NON_HT;
/* HT/VHT rates */
- if (link_sta->eht_cap.has_eht) {
+ if (link_sta->eht_cap.has_eht && sband_he_cap && sband_eht_cap) {
cmd->mode = IWL_TLC_MNG_MODE_EHT;
- rs_fw_eht_set_enabled_rates(vif, link_sta, sband, cmd);
- } else if (he_cap->has_he) {
+ rs_fw_eht_set_enabled_rates(vif, link_sta, sband_he_cap,
+ sband_eht_cap, cmd);
+ } else if (he_cap->has_he && sband_he_cap) {
cmd->mode = IWL_TLC_MNG_MODE_HE;
- rs_fw_he_set_enabled_rates(link_sta, sband, cmd);
+ rs_fw_he_set_enabled_rates(link_sta, sband_he_cap, cmd);
} else if (vht_cap->vht_supported) {
cmd->mode = IWL_TLC_MNG_MODE_VHT;
rs_fw_vht_set_enabled_rates(link_sta, vht_cap, cmd);
@@ -479,7 +478,7 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
IWL_DEBUG_RATE(mvm, "new rate: %s\n", pretty_rate);
}
- if (flags & IWL_TLC_NOTIF_FLAG_AMSDU && !mvmsta->orig_amsdu_len) {
+ if (flags & IWL_TLC_NOTIF_FLAG_AMSDU && !mvm_link_sta->orig_amsdu_len) {
u16 size = le32_to_cpu(notif->amsdu_size);
int i;
@@ -489,7 +488,7 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
* so also check with orig_amsdu_len which holds the
* original data before debugfs changed the value
*/
- WARN_ON(mvmsta->orig_amsdu_len < size);
+ WARN_ON(mvm_link_sta->orig_amsdu_len < size);
goto out;
}
@@ -524,6 +523,7 @@ u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta,
{
const struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap;
const struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;
+ const struct ieee80211_sta_eht_cap *eht_cap = &link_sta->eht_cap;
if (WARN_ON_ONCE(!link_conf->chandef.chan))
return IEEE80211_MAX_MPDU_LEN_VHT_3895;
@@ -538,8 +538,18 @@ u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta,
default:
return IEEE80211_MAX_MPDU_LEN_VHT_3895;
}
- } else
- if (vht_cap->vht_supported) {
+ } else if (link_conf->chandef.chan->band == NL80211_BAND_2GHZ &&
+ eht_cap->has_eht) {
+ switch (u8_get_bits(eht_cap->eht_cap_elem.mac_cap_info[0],
+ IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK)) {
+ case IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_11454:
+ return IEEE80211_MAX_MPDU_LEN_VHT_11454;
+ case IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_7991:
+ return IEEE80211_MAX_MPDU_LEN_VHT_7991;
+ default:
+ return IEEE80211_MAX_MPDU_LEN_VHT_3895;
+ }
+ } else if (vht_cap->vht_supported) {
switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
return IEEE80211_MAX_MPDU_LEN_VHT_11454;
@@ -576,13 +586,17 @@ void iwl_mvm_rs_fw_rate_init(struct iwl_mvm *mvm,
u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, TLC_MNG_CONFIG_CMD);
struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
u16 max_amsdu_len = rs_fw_get_max_amsdu_len(sta, link_conf, link_sta);
+ const struct ieee80211_sta_he_cap *sband_he_cap =
+ ieee80211_get_he_iftype_cap_vif(sband, vif);
+ const struct ieee80211_sta_eht_cap *sband_eht_cap =
+ ieee80211_get_eht_iftype_cap_vif(sband, vif);
struct iwl_mvm_link_sta *mvm_link_sta;
struct iwl_lq_sta_rs_fw *lq_sta;
struct iwl_tlc_config_cmd_v4 cfg_cmd = {
.max_ch_width = mvmsta->authorized ?
rs_fw_bw_from_sta_bw(link_sta) : IWL_TLC_MNG_CH_WIDTH_20MHZ,
.flags = cpu_to_le16(rs_fw_get_config_flags(mvm, vif, link_sta,
- sband)),
+ sband_he_cap)),
.chains = rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm)),
.sgi_ch_width_supp = rs_fw_sgi_cw_support(link_sta),
.max_mpdu_len = iwl_mvm_is_csum_supported(mvm) ?
@@ -592,6 +606,21 @@ void iwl_mvm_rs_fw_rate_init(struct iwl_mvm *mvm,
int cmd_ver;
int ret;
+ /* Enable external EHT LTF only for GL device and if there's
+ * mutual support by AP and client
+ */
+ if (CSR_HW_REV_TYPE(mvm->trans->hw_rev) == IWL_CFG_MAC_TYPE_GL &&
+ sband_eht_cap &&
+ sband_eht_cap->eht_cap_elem.phy_cap_info[5] &
+ IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF &&
+ link_sta->eht_cap.has_eht &&
+ link_sta->eht_cap.eht_cap_elem.phy_cap_info[5] &
+ IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF) {
+ IWL_DEBUG_RATE(mvm, "Set support for Extra EHT LTF\n");
+ cfg_cmd.flags |=
+ cpu_to_le16(IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK);
+ }
+
rcu_read_lock();
mvm_link_sta = rcu_dereference(mvmsta->link[link_id]);
if (WARN_ON_ONCE(!mvm_link_sta)) {
@@ -609,7 +638,9 @@ void iwl_mvm_rs_fw_rate_init(struct iwl_mvm *mvm,
#ifdef CONFIG_IWLWIFI_DEBUGFS
iwl_mvm_reset_frame_stats(mvm);
#endif
- rs_fw_set_supp_rates(vif, link_sta, sband, &cfg_cmd);
+ rs_fw_set_supp_rates(vif, link_sta, sband,
+ sband_he_cap, sband_eht_cap,
+ &cfg_cmd);
/*
* since TLC offload works with one mode we can assume
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
index 9a20468345e4..481d68cbbbd8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/******************************************************************************
*
- * Copyright(c) 2005 - 2014, 2018 - 2022 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014, 2018 - 2023 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*****************************************************************************/
@@ -1070,10 +1070,13 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
rate->bw = RATE_MCS_CHAN_WIDTH_20;
- WARN_ON_ONCE(rate->index < IWL_RATE_MCS_0_INDEX ||
- rate->index > IWL_RATE_MCS_9_INDEX);
+ if (WARN_ON_ONCE(rate->index < IWL_RATE_MCS_0_INDEX))
+ rate->index = rs_ht_to_legacy[IWL_RATE_MCS_0_INDEX];
+ else if (WARN_ON_ONCE(rate->index > IWL_RATE_MCS_9_INDEX))
+ rate->index = rs_ht_to_legacy[IWL_RATE_MCS_9_INDEX];
+ else
+ rate->index = rs_ht_to_legacy[rate->index];
- rate->index = rs_ht_to_legacy[rate->index];
rate->ldpc = false;
} else {
/* Downgrade to SISO with same MCS if in MIMO */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index b38b24246675..542c192698a4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -213,8 +213,12 @@ static void iwl_mvm_rx_handle_tcm(struct iwl_mvm *mvm,
};
u16 thr;
- if (ieee80211_is_data_qos(hdr->frame_control))
- ac = tid_to_mac80211_ac[ieee80211_get_tid(hdr)];
+ if (ieee80211_is_data_qos(hdr->frame_control)) {
+ u8 tid = ieee80211_get_tid(hdr);
+
+ if (tid < IWL_MAX_TID_COUNT)
+ ac = tid_to_mac80211_ac[tid];
+ }
mvmsta = iwl_mvm_sta_from_mac80211(sta);
mac = mvmsta->mac_id_n_color & FW_CTXT_ID_MSK;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index 6226e4e54a51..8d1e44fd9de7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -279,7 +279,8 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
struct ieee80211_hdr *hdr,
struct iwl_rx_mpdu_desc *desc,
- u32 status)
+ u32 status,
+ struct ieee80211_rx_status *stats)
{
struct iwl_mvm_sta *mvmsta;
struct iwl_mvm_vif *mvmvif;
@@ -308,8 +309,10 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
/* good cases */
if (likely(status & IWL_RX_MPDU_STATUS_MIC_OK &&
- !(status & IWL_RX_MPDU_STATUS_REPLAY_ERROR)))
+ !(status & IWL_RX_MPDU_STATUS_REPLAY_ERROR))) {
+ stats->flag |= RX_FLAG_DECRYPTED;
return 0;
+ }
if (!sta)
return -1;
@@ -378,7 +381,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
if (unlikely(ieee80211_is_mgmt(hdr->frame_control) &&
!ieee80211_has_protected(hdr->frame_control)))
- return iwl_mvm_rx_mgmt_prot(sta, hdr, desc, status);
+ return iwl_mvm_rx_mgmt_prot(sta, hdr, desc, status, stats);
if (!ieee80211_has_protected(hdr->frame_control) ||
(status & IWL_RX_MPDU_STATUS_SEC_MASK) ==
@@ -484,7 +487,7 @@ static void iwl_mvm_rx_csum(struct iwl_mvm *mvm,
}
/*
- * returns true if a packet is a duplicate and should be dropped.
+ * returns true if a packet is a duplicate or invalid tid and should be dropped.
* Updates AMSDU PN tracking info
*/
static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
@@ -513,11 +516,14 @@ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
return false;
}
- if (ieee80211_is_data_qos(hdr->frame_control))
+ if (ieee80211_is_data_qos(hdr->frame_control)) {
/* frame has qos control */
tid = ieee80211_get_tid(hdr);
- else
+ if (tid >= IWL_MAX_TID_COUNT)
+ return true;
+ } else {
tid = IWL_MAX_TID_COUNT;
+ }
/* If this wasn't a part of an A-MSDU the sub-frame index will be 0 */
sub_frame_idx = desc->amsdu_info &
@@ -985,10 +991,12 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
sta_mask = iwl_mvm_sta_fw_id_mask(mvm, sta, -1);
rcu_read_unlock();
- if (WARN(tid != baid_data->tid ||
- !(sta_mask & baid_data->sta_mask),
- "baid 0x%x is mapped to sta_mask:0x%x tid:%d, but was received for sta_mask:0x%x tid:%d\n",
- baid, baid_data->sta_mask, baid_data->tid, sta_mask, tid))
+ if (IWL_FW_CHECK(mvm,
+ tid != baid_data->tid ||
+ !(sta_mask & baid_data->sta_mask),
+ "baid 0x%x is mapped to sta_mask:0x%x tid:%d, but was received for sta_mask:0x%x tid:%d\n",
+ baid, baid_data->sta_mask, baid_data->tid,
+ sta_mask, tid))
return false;
nssn = reorder & IWL_RX_MPDU_REORDER_NSSN_MASK;
@@ -1773,6 +1781,15 @@ static void iwl_mvm_decode_eht_phy_data(struct iwl_mvm *mvm,
IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR);
}
+ if (fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_SNIFF_VALIDATE_SUPPORT)) {
+ usig->common |=
+ cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_CHECKED);
+ usig->common |=
+ LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_VALIDATE,
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_OK);
+ }
+
eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_SPATIAL_REUSE);
eht->data[0] |= LE32_DEC_ENC(data0,
IWL_RX_PHY_DATA0_ETH_SPATIAL_REUSE_MASK,
@@ -1782,9 +1799,9 @@ static void iwl_mvm_decode_eht_phy_data(struct iwl_mvm *mvm,
eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_RU_ALLOC_TB_FMT);
eht->data[8] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PS160,
IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_PS_160);
- eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_B0,
+ eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B0,
IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B0);
- eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_B1_B7_ALLOC,
+ eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B1_B7,
IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B7_B1);
iwl_mvm_decode_eht_ru(mvm, rx_status, eht);
@@ -2633,6 +2650,8 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
phy_data.energy_b = u32_get_bits(rssi, RX_NO_DATA_CHAIN_B_MSK);
phy_data.channel = u32_get_bits(rssi, RX_NO_DATA_CHANNEL_MSK);
phy_data.with_data = false;
+ phy_data.rx_vec[0] = desc->rx_vec[0];
+ phy_data.rx_vec[1] = desc->rx_vec[1];
if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP,
RX_NO_DATA_NOTIF, 0) < 2) {
@@ -2651,7 +2670,8 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
sizeof(struct iwl_rx_no_data_ver_3)))
/* invalid len for ver 3 */
return;
- memcpy(phy_data.rx_vec, desc->rx_vec, sizeof(phy_data.rx_vec));
+ phy_data.rx_vec[2] = desc->rx_vec[2];
+ phy_data.rx_vec[3] = desc->rx_vec[3];
} else {
if (format == RATE_MCS_EHT_MSK)
/* no support for EHT before version 3 API */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index 175615755d9d..c1d9ce753468 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -647,7 +647,7 @@ static void iwl_mvm_scan_fill_tx_cmd(struct iwl_mvm *mvm,
NL80211_BAND_2GHZ,
no_cck);
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) < 12) {
+ if (!iwl_mvm_has_new_station_api(mvm->fw)) {
tx_cmd[0].sta_id = mvm->aux_sta.sta_id;
tx_cmd[1].sta_id = mvm->aux_sta.sta_id;
@@ -1084,7 +1084,7 @@ static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config,
memcpy(&cfg->mac_addr, &mvm->addresses[0].addr, ETH_ALEN);
/* This function should not be called when using ADD_STA ver >=12 */
- WARN_ON_ONCE(iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12);
+ WARN_ON_ONCE(iwl_mvm_has_new_station_api(mvm->fw));
cfg->bcast_sta_id = mvm->aux_sta.sta_id;
cfg->channel_flags = channel_flags;
@@ -1135,7 +1135,7 @@ static void iwl_mvm_fill_scan_config_v2(struct iwl_mvm *mvm, void *config,
memcpy(&cfg->mac_addr, &mvm->addresses[0].addr, ETH_ALEN);
/* This function should not be called when using ADD_STA ver >=12 */
- WARN_ON_ONCE(iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12);
+ WARN_ON_ONCE(iwl_mvm_has_new_station_api(mvm->fw));
cfg->bcast_sta_id = mvm->aux_sta.sta_id;
cfg->channel_flags = channel_flags;
@@ -1250,7 +1250,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
memset(&cfg, 0, sizeof(cfg));
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) < 12) {
+ if (!iwl_mvm_has_new_station_api(mvm->fw)) {
cfg.bcast_sta_id = mvm->aux_sta.sta_id;
} else if (iwl_fw_lookup_cmd_ver(mvm->fw, SCAN_CFG_CMD, 0) < 5) {
/*
@@ -1627,11 +1627,11 @@ iwl_mvm_umac_scan_cfg_channels_v4(struct iwl_mvm *mvm,
}
static void
-iwl_mvm_umac_scan_cfg_channels_v6(struct iwl_mvm *mvm,
+iwl_mvm_umac_scan_cfg_channels_v7(struct iwl_mvm *mvm,
struct ieee80211_channel **channels,
- struct iwl_scan_channel_params_v6 *cp,
+ struct iwl_scan_channel_params_v7 *cp,
int n_channels, u32 flags,
- enum nl80211_iftype vif_type)
+ enum nl80211_iftype vif_type, u32 version)
{
int i;
@@ -1641,14 +1641,19 @@ iwl_mvm_umac_scan_cfg_channels_v6(struct iwl_mvm *mvm,
u32 n_aps_flag =
iwl_mvm_scan_ch_n_aps_flag(vif_type,
channels[i]->hw_value);
+ u8 iwl_band = iwl_mvm_phy_band_from_nl80211(band);
cfg->flags = cpu_to_le32(flags | n_aps_flag);
cfg->v2.channel_num = channels[i]->hw_value;
- cfg->v2.band = iwl_mvm_phy_band_from_nl80211(band);
if (cfg80211_channel_is_psc(channels[i]))
cfg->flags = 0;
cfg->v2.iter_count = 1;
cfg->v2.iter_interval = 0;
+ if (version < 17)
+ cfg->v2.band = iwl_band;
+ else
+ cfg->flags |= cpu_to_le32((iwl_band <<
+ IWL_CHAN_CFG_FLAGS_BAND_POS));
}
}
@@ -1723,14 +1728,15 @@ iwl_mvm_umac_scan_fill_6g_chan_list(struct iwl_mvm *mvm,
pp->bssid_num = idex_b;
}
-/* TODO: this function can be merged with iwl_mvm_scan_umac_fill_ch_p_v6 */
+/* TODO: this function can be merged with iwl_mvm_scan_umac_fill_ch_p_v7 */
static u32
-iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm *mvm,
+iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params,
u32 n_channels,
struct iwl_scan_probe_params_v4 *pp,
- struct iwl_scan_channel_params_v6 *cp,
- enum nl80211_iftype vif_type)
+ struct iwl_scan_channel_params_v7 *cp,
+ enum nl80211_iftype vif_type,
+ u32 version)
{
int i;
struct cfg80211_scan_6ghz_params *scan_6ghz_params =
@@ -1745,6 +1751,7 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm *mvm,
u8 j, k, s_max = 0, b_max = 0, n_used_bssid_entries;
bool force_passive, found = false, allow_passive = true,
unsolicited_probe_on_chan = false, psc_no_listen = false;
+ s8 psd_20 = IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED;
/*
* Avoid performing passive scan on non PSC channels unless the
@@ -1756,9 +1763,14 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm *mvm,
continue;
cfg->v1.channel_num = params->channels[i]->hw_value;
- cfg->v2.band = 2;
- cfg->v2.iter_count = 1;
- cfg->v2.iter_interval = 0;
+ if (version < 17)
+ cfg->v2.band = PHY_BAND_6;
+ else
+ cfg->flags |= cpu_to_le32(PHY_BAND_6 <<
+ IWL_CHAN_CFG_FLAGS_BAND_POS);
+
+ cfg->v5.iter_count = 1;
+ cfg->v5.iter_interval = 0;
/*
* The optimize the scan time, i.e., reduce the scan dwell time
@@ -1769,9 +1781,22 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm *mvm,
*/
n_used_bssid_entries = 3;
for (j = 0; j < params->n_6ghz_params; j++) {
+ s8 tmp_psd_20;
+
if (!(scan_6ghz_params[j].channel_idx == i))
continue;
+ /* Use the highest PSD value allowed as advertised by
+ * APs for this channel
+ */
+ tmp_psd_20 = scan_6ghz_params[j].psd_20;
+ if (tmp_psd_20 !=
+ IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED &&
+ (psd_20 ==
+ IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED ||
+ psd_20 < tmp_psd_20))
+ psd_20 = tmp_psd_20;
+
found = false;
unsolicited_probe_on_chan |=
scan_6ghz_params[j].unsolicited_probe;
@@ -1875,6 +1900,9 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm *mvm,
flags |= bssid_bitmap | (s_ssid_bitmap << 16);
cfg->flags |= cpu_to_le32(flags);
+ if (version >= 17)
+ cfg->v5.psd_20 = psd_20;
+
ch_cnt++;
}
@@ -2292,11 +2320,12 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
}
static void
-iwl_mvm_scan_umac_fill_general_p_v11(struct iwl_mvm *mvm,
+iwl_mvm_scan_umac_fill_general_p_v12(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params,
struct ieee80211_vif *vif,
struct iwl_scan_general_params_v11 *gp,
- u16 gen_flags, u8 gen_flags2)
+ u16 gen_flags, u8 gen_flags2,
+ u32 version)
{
struct iwl_mvm_vif *scan_vif = iwl_mvm_vif_from_mac80211(vif);
@@ -2313,7 +2342,23 @@ iwl_mvm_scan_umac_fill_general_p_v11(struct iwl_mvm *mvm,
if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2)
gp->num_of_fragments[SCAN_HB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS;
- gp->scan_start_mac_id = scan_vif->id;
+ if (version < 12) {
+ gp->scan_start_mac_or_link_id = scan_vif->id;
+ } else {
+ struct iwl_mvm_vif_link_info *link_info;
+ u8 link_id = 0;
+
+ /* Use one of the active link (if any). In the future it would
+ * be possible that the link ID would be part of the scan
+ * request coming from upper layers so we would need to use it.
+ */
+ if (vif->active_links)
+ link_id = ffs(vif->active_links) - 1;
+
+ link_info = scan_vif->link[link_id];
+ if (!WARN_ON(!link_info))
+ gp->scan_start_mac_or_link_id = link_info->fw_link_id;
+ }
}
static void
@@ -2352,21 +2397,22 @@ iwl_mvm_scan_umac_fill_ch_p_v4(struct iwl_mvm *mvm,
}
static void
-iwl_mvm_scan_umac_fill_ch_p_v6(struct iwl_mvm *mvm,
+iwl_mvm_scan_umac_fill_ch_p_v7(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params,
struct ieee80211_vif *vif,
- struct iwl_scan_channel_params_v6 *cp,
- u32 channel_cfg_flags)
+ struct iwl_scan_channel_params_v7 *cp,
+ u32 channel_cfg_flags,
+ u32 version)
{
cp->flags = iwl_mvm_scan_umac_chan_flags_v2(mvm, params, vif);
cp->count = params->n_channels;
cp->n_aps_override[0] = IWL_SCAN_ADWELL_N_APS_GO_FRIENDLY;
cp->n_aps_override[1] = IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS;
- iwl_mvm_umac_scan_cfg_channels_v6(mvm, params->channels, cp,
+ iwl_mvm_umac_scan_cfg_channels_v7(mvm, params->channels, cp,
params->n_channels,
channel_cfg_flags,
- vif->type);
+ vif->type, version);
if (params->enable_6ghz_passive) {
struct ieee80211_supported_band *sband =
@@ -2383,11 +2429,19 @@ iwl_mvm_scan_umac_fill_ch_p_v6(struct iwl_mvm *mvm,
if (!cfg80211_channel_is_psc(channel))
continue;
- cfg->flags = 0;
- cfg->v2.channel_num = channel->hw_value;
- cfg->v2.band = PHY_BAND_6;
- cfg->v2.iter_count = 1;
- cfg->v2.iter_interval = 0;
+ cfg->v5.channel_num = channel->hw_value;
+ cfg->v5.iter_count = 1;
+ cfg->v5.iter_interval = 0;
+
+ if (version < 17) {
+ cfg->flags = 0;
+ cfg->v2.band = PHY_BAND_6;
+ } else {
+ cfg->flags = cpu_to_le32(PHY_BAND_6 <<
+ IWL_CHAN_CFG_FLAGS_BAND_POS);
+ cfg->v5.psd_20 =
+ IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED;
+ }
cp->count++;
}
}
@@ -2408,9 +2462,9 @@ static int iwl_mvm_scan_umac_v12(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
cmd->uid = cpu_to_le32(uid);
gen_flags = iwl_mvm_scan_umac_flags_v2(mvm, params, vif, type);
- iwl_mvm_scan_umac_fill_general_p_v11(mvm, params, vif,
+ iwl_mvm_scan_umac_fill_general_p_v12(mvm, params, vif,
&scan_p->general_params,
- gen_flags, 0);
+ gen_flags, 0, 12);
ret = iwl_mvm_fill_scan_sched_params(params,
scan_p->periodic_params.schedule,
@@ -2430,9 +2484,9 @@ static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params,
int type, int uid, u32 version)
{
- struct iwl_scan_req_umac_v15 *cmd = mvm->scan_cmd;
- struct iwl_scan_req_params_v15 *scan_p = &cmd->scan_params;
- struct iwl_scan_channel_params_v6 *cp = &scan_p->channel_params;
+ struct iwl_scan_req_umac_v17 *cmd = mvm->scan_cmd;
+ struct iwl_scan_req_params_v17 *scan_p = &cmd->scan_params;
+ struct iwl_scan_channel_params_v7 *cp = &scan_p->channel_params;
struct iwl_scan_probe_params_v4 *pb = &scan_p->probe_params;
int ret;
u16 gen_flags;
@@ -2451,9 +2505,9 @@ static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm,
else
gen_flags2 = 0;
- iwl_mvm_scan_umac_fill_general_p_v11(mvm, params, vif,
+ iwl_mvm_scan_umac_fill_general_p_v12(mvm, params, vif,
&scan_p->general_params,
- gen_flags, gen_flags2);
+ gen_flags, gen_flags2, version);
ret = iwl_mvm_fill_scan_sched_params(params,
scan_p->periodic_params.schedule,
@@ -2462,11 +2516,13 @@ static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm,
return ret;
if (!params->scan_6ghz) {
- iwl_mvm_scan_umac_fill_probe_p_v4(params, &scan_p->probe_params,
- &bitmap_ssid);
- iwl_mvm_scan_umac_fill_ch_p_v6(mvm, params, vif,
- &scan_p->channel_params, bitmap_ssid);
-
+ iwl_mvm_scan_umac_fill_probe_p_v4(params,
+ &scan_p->probe_params,
+ &bitmap_ssid);
+ iwl_mvm_scan_umac_fill_ch_p_v7(mvm, params, vif,
+ &scan_p->channel_params,
+ bitmap_ssid,
+ version);
return 0;
} else {
pb->preq = params->preq;
@@ -2478,9 +2534,10 @@ static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm,
iwl_mvm_umac_scan_fill_6g_chan_list(mvm, params, pb);
- cp->count = iwl_mvm_umac_scan_cfg_channels_v6_6g(mvm, params,
+ cp->count = iwl_mvm_umac_scan_cfg_channels_v7_6g(mvm, params,
params->n_channels,
- pb, cp, vif->type);
+ pb, cp, vif->type,
+ version);
if (!cp->count) {
mvm->scan_uid_status[uid] = 0;
return -EINVAL;
@@ -2507,6 +2564,20 @@ static int iwl_mvm_scan_umac_v15(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return iwl_mvm_scan_umac_v14_and_above(mvm, vif, params, type, uid, 15);
}
+static int iwl_mvm_scan_umac_v16(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct iwl_mvm_scan_params *params, int type,
+ int uid)
+{
+ return iwl_mvm_scan_umac_v14_and_above(mvm, vif, params, type, uid, 16);
+}
+
+static int iwl_mvm_scan_umac_v17(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct iwl_mvm_scan_params *params, int type,
+ int uid)
+{
+ return iwl_mvm_scan_umac_v14_and_above(mvm, vif, params, type, uid, 17);
+}
+
static int iwl_mvm_num_scans(struct iwl_mvm *mvm)
{
return hweight32(mvm->scan_status & IWL_MVM_SCAN_MASK);
@@ -2622,6 +2693,8 @@ struct iwl_scan_umac_handler {
static const struct iwl_scan_umac_handler iwl_scan_umac_handlers[] = {
/* set the newest version first to shorten the list traverse time */
+ IWL_SCAN_UMAC_HANDLER(17),
+ IWL_SCAN_UMAC_HANDLER(16),
IWL_SCAN_UMAC_HANDLER(15),
IWL_SCAN_UMAC_HANDLER(14),
IWL_SCAN_UMAC_HANDLER(12),
@@ -3210,7 +3283,9 @@ static size_t iwl_scan_req_umac_get_size(u8 scan_ver)
return sizeof(struct iwl_scan_req_umac_v12);
case 14:
case 15:
- return sizeof(struct iwl_scan_req_umac_v15);
+ case 16:
+ case 17:
+ return sizeof(struct iwl_scan_req_umac_v17);
}
return 0;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
index 98f330fcf678..30d4233595e8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2013-2014, 2018-2019, 2022 Intel Corporation
+ * Copyright (C) 2013-2014, 2018-2019, 2022-2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
*/
#include "mvm.h"
@@ -180,9 +180,6 @@ static int iwl_mvm_sf_config(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
};
int ret = 0;
- if (mvm->cfg->disable_dummy_notification)
- sf_cmd.state |= cpu_to_le32(SF_CFG_DUMMY_NOTIF_OFF);
-
/*
* If an associated AP sta changed its antenna configuration, the state
* will remain FULL_ON but SF parameters need to be reconsidered.
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 05a54a69c135..3b9a343d4f67 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2015, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2015, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -60,22 +60,27 @@ u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_link_sta *link_sta,
if (WARN_ON(!link_sta))
return 0;
- if (link_sta->ht_cap.ht_supported)
+ /* Note that we always use only legacy & highest supported PPDUs, so
+ * of Draft P802.11be D.30 Table 10-12a--Fields used for calculating
+ * the maximum A-MPDU size of various PPDU types in different bands,
+ * we only need to worry about the highest supported PPDU type here.
+ */
+
+ if (link_sta->ht_cap.ht_supported) {
+ agg_size = link_sta->ht_cap.ampdu_factor;
mpdu_dens = link_sta->ht_cap.ampdu_density;
+ }
- if (link_conf->chandef.chan->band ==
- NL80211_BAND_6GHZ) {
+ if (link_conf->chandef.chan->band == NL80211_BAND_6GHZ) {
+ /* overwrite HT values on 6 GHz */
mpdu_dens = le16_get_bits(link_sta->he_6ghz_capa.capa,
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START);
agg_size = le16_get_bits(link_sta->he_6ghz_capa.capa,
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
} else if (link_sta->vht_cap.vht_supported) {
- agg_size = link_sta->vht_cap.cap &
- IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
- agg_size >>=
- IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
- } else if (link_sta->ht_cap.ht_supported) {
- agg_size = link_sta->ht_cap.ampdu_factor;
+ /* if VHT supported overwrite HT value */
+ agg_size = u32_get_bits(link_sta->vht_cap.cap,
+ IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK);
}
/* D6.0 10.12.2 A-MPDU length limit rules
@@ -91,10 +96,13 @@ u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_link_sta *link_sta,
u8_get_bits(link_sta->he_cap.he_cap_elem.mac_cap_info[3],
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK);
+ if (link_sta->eht_cap.has_eht)
+ agg_size += u8_get_bits(link_sta->eht_cap.eht_cap_elem.mac_cap_info[1],
+ IEEE80211_EHT_MAC_CAP1_MAX_AMPDU_LEN_MASK);
+
/* Limit to max A-MPDU supported by FW */
- if (agg_size > (STA_FLG_MAX_AGG_SIZE_4M >> STA_FLG_MAX_AGG_SIZE_SHIFT))
- agg_size = (STA_FLG_MAX_AGG_SIZE_4M >>
- STA_FLG_MAX_AGG_SIZE_SHIFT);
+ agg_size = min_t(u32, agg_size,
+ STA_FLG_MAX_AGG_SIZE_4M >> STA_FLG_MAX_AGG_SIZE_SHIFT);
*_agg_size = agg_size;
return mpdu_dens;
@@ -1679,7 +1687,7 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,
memset(&cmd, 0, sizeof(cmd));
cmd.sta_id = sta->sta_id;
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12 &&
+ if (iwl_mvm_has_new_station_api(mvm->fw) &&
sta->type == IWL_STA_AUX_ACTIVITY)
cmd.mac_id_n_color = cpu_to_le32(mac_id);
else
@@ -1859,6 +1867,8 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
ret = iwl_mvm_sta_init(mvm, vif, sta, sta_id,
sta->tdls ? IWL_STA_TDLS_LINK : IWL_STA_LINK);
+ if (ret)
+ goto err;
update_fw:
ret = iwl_mvm_sta_send_to_fw(mvm, sta, sta_update, sta_flags);
@@ -2070,13 +2080,6 @@ bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
cancel_delayed_work(&mvm->tdls_cs.dwork);
}
- /*
- * Make sure that the tx response code sees the station as -EBUSY and
- * calls the drain worker.
- */
- spin_lock_bh(&mvm_sta->lock);
- spin_unlock_bh(&mvm_sta->lock);
-
return false;
}
@@ -2882,7 +2885,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
}
if (iwl_mvm_has_new_rx_api(mvm) && start) {
- u16 reorder_buf_size = buf_size * sizeof(baid_data->entries[0]);
+ u32 reorder_buf_size = buf_size * sizeof(baid_data->entries[0]);
/* sparse doesn't like the __align() so don't check */
#ifndef __CHECKER__
@@ -4306,16 +4309,27 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
u16 queue;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_key_conf *keyconf;
+ unsigned int wdg_timeout =
+ iwl_mvm_get_wd_timeout(mvm, vif, false, false);
+ bool mld = iwl_mvm_has_mld_api(mvm->fw);
+ u32 type = mld ? STATION_TYPE_PEER : IWL_STA_LINK;
ret = iwl_mvm_allocate_int_sta(mvm, sta, 0,
- NL80211_IFTYPE_UNSPECIFIED,
- IWL_STA_LINK);
+ NL80211_IFTYPE_UNSPECIFIED, type);
if (ret)
return ret;
- ret = iwl_mvm_add_int_sta_with_queue(mvm, mvmvif->id, mvmvif->color,
- addr, sta, &queue,
- IWL_MVM_TX_FIFO_BE);
+ if (mld)
+ ret = iwl_mvm_mld_add_int_sta_with_queue(mvm, sta, addr,
+ mvmvif->deflink.fw_link_id,
+ &queue,
+ IWL_MAX_TID_COUNT,
+ &wdg_timeout);
+ else
+ ret = iwl_mvm_add_int_sta_with_queue(mvm, mvmvif->id,
+ mvmvif->color, addr, sta,
+ &queue,
+ IWL_MVM_TX_FIFO_BE);
if (ret)
goto out;
@@ -4328,9 +4342,23 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
keyconf->cipher = cipher;
memcpy(keyconf->key, key, key_len);
keyconf->keylen = key_len;
+ keyconf->flags = IEEE80211_KEY_FLAG_PAIRWISE;
+
+ if (mld) {
+ /* The MFP flag is set according to the station mfp field. Since
+ * we don't have a station, set it manually.
+ */
+ u32 key_flags =
+ iwl_mvm_get_sec_flags(mvm, vif, NULL, keyconf) |
+ IWL_SEC_KEY_FLAG_MFP;
+ u32 sta_mask = BIT(sta->sta_id);
+
+ ret = iwl_mvm_mld_send_key(mvm, sta_mask, key_flags, keyconf);
+ } else {
+ ret = iwl_mvm_send_sta_key(mvm, sta->sta_id, keyconf, false,
+ 0, NULL, 0, 0, true);
+ }
- ret = iwl_mvm_send_sta_key(mvm, sta->sta_id, keyconf, false,
- 0, NULL, 0, 0, true);
kfree(keyconf);
return 0;
out:
@@ -4340,10 +4368,10 @@ out:
void iwl_mvm_cancel_channel_switch(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- u32 mac_id)
+ u32 id)
{
struct iwl_cancel_channel_switch_cmd cancel_channel_switch_cmd = {
- .mac_id = cpu_to_le32(mac_id),
+ .id = cpu_to_le32(id),
};
int ret;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index a61d4f88125f..7364346a1209 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -336,6 +336,9 @@ struct iwl_mvm_rxq_dup_data {
* @sta_id: the index of the station in the fw
* @lq_sta: holds rate scaling data, either for the case when RS is done in
* the driver - %rs_drv or in the FW - %rs_fw.
+ * @orig_amsdu_len: used to save the original amsdu_len when it is changed via
+ * debugfs. If it's set to 0, it means that it is it's not set via
+ * debugfs.
* @avg_energy: energy as reported by FW statistics notification
*/
struct iwl_mvm_link_sta {
@@ -346,6 +349,8 @@ struct iwl_mvm_link_sta {
struct iwl_lq_sta rs_drv;
} lq_sta;
+ u16 orig_amsdu_len;
+
u8 avg_energy;
};
@@ -365,6 +370,7 @@ struct iwl_mvm_link_sta {
* and from Tx response flow, it needs a spinlock.
* @tid_data: per tid data + mgmt. Look at %iwl_mvm_tid_data.
* @tid_to_baid: a simple map of TID to baid
+ * @vif: a vif pointer
* @reserved_queue: the queue reserved for this STA for DQA purposes
* Every STA has is given one reserved queue to allow it to operate. If no
* such queue can be guaranteed, the STA addition will fail.
@@ -374,10 +380,8 @@ struct iwl_mvm_link_sta {
* @amsdu_enabled: bitmap of TX AMSDU allowed TIDs.
* In case TLC offload is not active it is either 0xFFFF or 0.
* @max_amsdu_len: max AMSDU length
- * @orig_amsdu_len: used to save the original amsdu_len when it is changed via
- * debugfs. If it's set to 0, it means that it is it's not set via
- * debugfs.
* @agg_tids: bitmap of tids whose status is operational aggregated (IWL_AGG_ON)
+ * @sleeping: sta sleep transitions in power management
* @sleep_tx_count: the number of frames that we told the firmware to let out
* even when that station is asleep. This is useful in case the queue
* gets empty before all the frames were sent, which can happen when
@@ -427,7 +431,6 @@ struct iwl_mvm_sta {
bool disable_tx;
u16 amsdu_enabled;
u16 max_amsdu_len;
- u16 orig_amsdu_len;
bool sleeping;
u8 agg_tids;
u8 sleep_tx_count;
@@ -580,7 +583,7 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
u8 *key, u32 key_len);
void iwl_mvm_cancel_channel_switch(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- u32 mac_id);
+ u32 id);
/* Queues */
int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
@@ -616,7 +619,7 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
enum ieee80211_sta_state old_state,
enum ieee80211_sta_state new_state,
- struct iwl_mvm_sta_state_ops *callbacks);
+ const struct iwl_mvm_sta_state_ops *callbacks);
/* New MLD STA related APIs */
/* STA */
@@ -646,6 +649,11 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
u16 old_links, u16 new_links);
u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
int filter_link_id);
+int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm,
+ struct iwl_mvm_int_sta *sta,
+ const u8 *addr, int link_id,
+ u16 *queue, u8 tid,
+ unsigned int *_wdg_timeout);
/* Queues */
void iwl_mvm_mld_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
index 6b7b6250f1bb..5f0e7144a951 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2017 Intel Deutschland GmbH
*/
@@ -103,7 +103,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
/* In newer version of this command an aux station is added only
* in cases of dedicated tx queue and need to be removed in end
* of use */
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12)
+ if (iwl_mvm_has_new_station_api(mvm->fw))
iwl_mvm_rm_aux_sta(mvm);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 00719e130438..36d70d589aed 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -1,12 +1,13 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#include <linux/ieee80211.h>
#include <linux/etherdevice.h>
#include <linux/tcp.h>
+#include <net/gso.h>
#include <net/ip.h>
#include <net/ipv6.h>
@@ -40,13 +41,14 @@ iwl_mvm_bar_check_trigger(struct iwl_mvm *mvm, const u8 *addr,
#define OPT_HDR(type, skb, off) \
(type *)(skb_network_header(skb) + (off))
-static u16 iwl_mvm_tx_csum_pre_bz(struct iwl_mvm *mvm, struct sk_buff *skb,
- struct ieee80211_tx_info *info, bool amsdu)
+static u32 iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
+ struct ieee80211_tx_info *info,
+ bool amsdu)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
+ u16 mh_len = ieee80211_hdrlen(hdr->frame_control);
u16 offload_assist = 0;
#if IS_ENABLED(CONFIG_INET)
- u16 mh_len = ieee80211_hdrlen(hdr->frame_control);
u8 protocol = 0;
/* Do not compute checksum if already computed */
@@ -118,6 +120,8 @@ static u16 iwl_mvm_tx_csum_pre_bz(struct iwl_mvm *mvm, struct sk_buff *skb,
else
udp_hdr(skb)->check = 0;
+out:
+#endif
/*
* mac header len should include IV, size is in words unless
* the IV is added by the firmware like in WEP.
@@ -130,8 +134,6 @@ static u16 iwl_mvm_tx_csum_pre_bz(struct iwl_mvm *mvm, struct sk_buff *skb,
mh_len /= 2;
offload_assist |= mh_len << TX_CMD_OFFLD_MH_SIZE;
-out:
-#endif
if (amsdu)
offload_assist |= BIT(TX_CMD_OFFLD_AMSDU);
else if (ieee80211_hdrlen(hdr->frame_control) % 4)
@@ -141,54 +143,6 @@ out:
return offload_assist;
}
-u32 iwl_mvm_tx_csum_bz(struct iwl_mvm *mvm, struct sk_buff *skb, bool amsdu)
-{
- struct ieee80211_hdr *hdr = (void *)skb->data;
- u32 offload_assist = IWL_TX_CMD_OFFLD_BZ_PARTIAL_CSUM;
- unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
- unsigned int csum_start = skb_checksum_start_offset(skb);
-
- offload_assist |= u32_encode_bits(hdrlen / 2,
- IWL_TX_CMD_OFFLD_BZ_MH_LEN);
- if (amsdu)
- offload_assist |= IWL_TX_CMD_OFFLD_BZ_AMSDU;
- else if (hdrlen % 4)
- /* padding is inserted later in transport */
- offload_assist |= IWL_TX_CMD_OFFLD_BZ_MH_PAD;
-
- if (skb->ip_summed != CHECKSUM_PARTIAL)
- return offload_assist;
-
- offload_assist |= IWL_TX_CMD_OFFLD_BZ_ENABLE_CSUM |
- IWL_TX_CMD_OFFLD_BZ_ZERO2ONES;
-
- /*
- * mac80211 will always calculate checksum in software for
- * non-fast-xmit, and so we can only do offloaded checksum
- * for fast-xmit frames. In this case, we always have the
- * RFC 1042 header present. skb_checksum_start_offset()
- * returns the offset from the beginning, but the hardware
- * needs it from after the header & SNAP header.
- */
- csum_start -= hdrlen + 8;
-
- offload_assist |= u32_encode_bits(csum_start,
- IWL_TX_CMD_OFFLD_BZ_START_OFFS);
- offload_assist |= u32_encode_bits(csum_start + skb->csum_offset,
- IWL_TX_CMD_OFFLD_BZ_RESULT_OFFS);
-
- return offload_assist;
-}
-
-static u32 iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
- struct ieee80211_tx_info *info,
- bool amsdu)
-{
- if (!iwl_mvm_has_new_tx_csum(mvm))
- return iwl_mvm_tx_csum_pre_bz(mvm, skb, info, amsdu);
- return iwl_mvm_tx_csum_bz(mvm, skb, amsdu);
-}
-
/*
* Sets most of the Tx cmd's fields
*/
@@ -288,7 +242,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
tx_cmd->sta_id = sta_id;
tx_cmd->offload_assist =
- cpu_to_le16(iwl_mvm_tx_csum_pre_bz(mvm, skb, info, amsdu));
+ cpu_to_le16(iwl_mvm_tx_csum(mvm, skb, info, amsdu));
}
static u32 iwl_mvm_get_tx_ant(struct iwl_mvm *mvm,
@@ -308,6 +262,54 @@ static u32 iwl_mvm_get_tx_ant(struct iwl_mvm *mvm,
return BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS;
}
+static u32 iwl_mvm_get_inject_tx_rate(struct iwl_mvm *mvm,
+ struct ieee80211_tx_info *info)
+{
+ struct ieee80211_tx_rate *rate = &info->control.rates[0];
+ u32 result;
+
+ /*
+ * we only care about legacy/HT/VHT so far, so we can
+ * build in v1 and use iwl_new_rate_from_v1()
+ */
+
+ if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
+ u8 mcs = ieee80211_rate_get_vht_mcs(rate);
+ u8 nss = ieee80211_rate_get_vht_nss(rate);
+
+ result = RATE_MCS_VHT_MSK_V1;
+ result |= u32_encode_bits(mcs, RATE_VHT_MCS_RATE_CODE_MSK);
+ result |= u32_encode_bits(nss, RATE_MCS_NSS_MSK);
+ if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+ result |= RATE_MCS_SGI_MSK_V1;
+ if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ result |= u32_encode_bits(1, RATE_MCS_CHAN_WIDTH_MSK_V1);
+ else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
+ result |= u32_encode_bits(2, RATE_MCS_CHAN_WIDTH_MSK_V1);
+ else if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
+ result |= u32_encode_bits(3, RATE_MCS_CHAN_WIDTH_MSK_V1);
+ } else if (rate->flags & IEEE80211_TX_RC_MCS) {
+ result = RATE_MCS_HT_MSK_V1;
+ result |= u32_encode_bits(rate->idx,
+ RATE_HT_MCS_RATE_CODE_MSK_V1 |
+ RATE_HT_MCS_NSS_MSK_V1);
+ if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+ result |= RATE_MCS_SGI_MSK_V1;
+ if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ result |= u32_encode_bits(1, RATE_MCS_CHAN_WIDTH_MSK_V1);
+ if (info->flags & IEEE80211_TX_CTL_LDPC)
+ result |= RATE_MCS_LDPC_MSK_V1;
+ if (u32_get_bits(info->flags, IEEE80211_TX_CTL_STBC))
+ result |= RATE_MCS_STBC_MSK;
+ } else {
+ return 0;
+ }
+
+ if (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP, TX_CMD, 0) > 6)
+ return iwl_new_rate_from_v1(result);
+ return result;
+}
+
static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta, __le16 fc)
@@ -317,8 +319,15 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,
u32 rate_flags = 0;
bool is_cck;
- /* info->control is only relevant for non HW rate control */
- if (!ieee80211_hw_check(mvm->hw, HAS_RATE_CONTROL)) {
+ if (unlikely(info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT)) {
+ u32 result = iwl_mvm_get_inject_tx_rate(mvm, info);
+
+ if (result)
+ return result;
+ rate_idx = info->control.rates[0].idx;
+ } else if (!ieee80211_hw_check(mvm->hw, HAS_RATE_CONTROL)) {
+ /* info->control is only relevant for non HW rate control */
+
/* HT rate doesn't make sense for a non data frame */
WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS &&
!ieee80211_is_data(fc),
@@ -398,7 +407,8 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd,
* table is controlled by LINK_QUALITY commands
*/
- if (ieee80211_is_data(fc) && sta) {
+ if (likely(ieee80211_is_data(fc) && sta &&
+ !(info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT))) {
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
if (mvmsta->sta_state >= IEEE80211_STA_AUTHORIZED) {
@@ -556,9 +566,8 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
cmd->rate_n_flags = cpu_to_le32(rate_n_flags);
} else {
struct iwl_tx_cmd_gen2 *cmd = (void *)dev_cmd->payload;
- u16 offload_assist = iwl_mvm_tx_csum_pre_bz(mvm, skb,
- info,
- amsdu);
+ u16 offload_assist = iwl_mvm_tx_csum(mvm, skb,
+ info, amsdu);
cmd->offload_assist = cpu_to_le16(offload_assist);
@@ -749,6 +758,8 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
}
link = mvmvif->link[link_id];
+ if (WARN_ON(!link))
+ return -1;
if (!ieee80211_is_data(hdr->frame_control))
sta_id = link->bcast_sta.sta_id;
@@ -840,7 +851,7 @@ unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm,
band = mvmsta->vif->bss_conf.chandef.chan->band;
}
- lmac = iwl_mvm_get_lmac_id(mvm->fw, band);
+ lmac = iwl_mvm_get_lmac_id(mvm, band);
} else if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CDB_SUPPORT)) {
/* for real MLO restrict to both LMACs if they exist */
@@ -2065,7 +2076,8 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
u16 tfd_cnt;
int i;
- if (unlikely(sizeof(*ba_res) > pkt_len))
+ if (IWL_FW_CHECK(mvm, sizeof(*ba_res) > pkt_len,
+ "short BA notification (%d)\n", pkt_len))
return;
sta_id = ba_res->sta_id;
@@ -2077,7 +2089,13 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
(void *)(uintptr_t)ba_res->reduced_txp;
tfd_cnt = le16_to_cpu(ba_res->tfd_cnt);
- if (!tfd_cnt || struct_size(ba_res, tfd, tfd_cnt) > pkt_len)
+ if (!tfd_cnt)
+ return;
+
+ if (IWL_FW_CHECK(mvm,
+ struct_size(ba_res, tfd, tfd_cnt) > pkt_len,
+ "short BA notification (tfds:%d, size:%d)\n",
+ tfd_cnt, pkt_len))
return;
rcu_read_lock();
@@ -2135,7 +2153,9 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
rcu_read_lock();
mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, sta_id);
- if (WARN_ON_ONCE(!mvmsta)) {
+ if (IWL_FW_CHECK(mvm, !mvmsta,
+ "invalid STA ID %d in BA notif\n",
+ sta_id)) {
rcu_read_unlock();
return;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index af31b09c3966..48016b4343d2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -312,6 +312,10 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
smps_mode = IEEE80211_SMPS_DYNAMIC;
}
+ /* SMPS is disabled in eSR */
+ if (mvmvif->esr_active)
+ smps_mode = IEEE80211_SMPS_OFF;
+
ieee80211_request_smps(vif, link_id, smps_mode);
}
@@ -413,16 +417,20 @@ static void iwl_mvm_diversity_iter(void *_data, u8 *mac,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_diversity_iter_data *data = _data;
- int i;
+ int i, link_id;
- if (mvmvif->deflink.phy_ctxt != data->ctxt)
- return;
+ for_each_mvm_vif_valid_link(mvmvif, link_id) {
+ struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id];
- for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) {
- if (mvmvif->deflink.smps_requests[i] == IEEE80211_SMPS_STATIC ||
- mvmvif->deflink.smps_requests[i] == IEEE80211_SMPS_DYNAMIC) {
- data->result = false;
- break;
+ if (link_info->phy_ctxt != data->ctxt)
+ continue;
+
+ for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) {
+ if (link_info->smps_requests[i] == IEEE80211_SMPS_STATIC ||
+ link_info->smps_requests[i] == IEEE80211_SMPS_DYNAMIC) {
+ data->result = false;
+ break;
+ }
}
}
}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
index cb60ba40fe97..fa4a14546860 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#include "iwl-trans.h"
#include "iwl-fh.h"
@@ -281,70 +281,273 @@ void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive)
trans_pcie->prph_info = NULL;
}
-int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
- const void *data, u32 len)
+static int iwl_pcie_load_payloads_continuously(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *pnvm_data,
+ struct iwl_dram_data *dram)
+{
+ u32 len, len0, len1;
+
+ if (pnvm_data->n_chunks != UNFRAGMENTED_PNVM_PAYLOADS_NUMBER) {
+ IWL_DEBUG_FW(trans, "expected 2 payloads, got %d.\n",
+ pnvm_data->n_chunks);
+ return -EINVAL;
+ }
+
+ len0 = pnvm_data->chunks[0].len;
+ len1 = pnvm_data->chunks[1].len;
+ if (len1 > 0xFFFFFFFF - len0) {
+ IWL_DEBUG_FW(trans, "sizes of payloads overflow.\n");
+ return -EINVAL;
+ }
+ len = len0 + len1;
+
+ dram->block = iwl_pcie_ctxt_info_dma_alloc_coherent(trans, len,
+ &dram->physical);
+ if (!dram->block) {
+ IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA.\n");
+ return -ENOMEM;
+ }
+
+ dram->size = len;
+ memcpy(dram->block, pnvm_data->chunks[0].data, len0);
+ memcpy((u8 *)dram->block + len0, pnvm_data->chunks[1].data, len1);
+
+ return 0;
+}
+
+static int iwl_pcie_load_payloads_segments
+ (struct iwl_trans *trans,
+ struct iwl_dram_regions *dram_regions,
+ const struct iwl_pnvm_image *pnvm_data)
+{
+ struct iwl_dram_data *cur_payload_dram = &dram_regions->drams[0];
+ struct iwl_dram_data *desc_dram = &dram_regions->prph_scratch_mem_desc;
+ struct iwl_prph_scrath_mem_desc_addr_array *addresses;
+ const void *data;
+ u32 len;
+ int i;
+
+ /* allocate and init DRAM descriptors array */
+ len = sizeof(struct iwl_prph_scrath_mem_desc_addr_array);
+ desc_dram->block = iwl_pcie_ctxt_info_dma_alloc_coherent
+ (trans,
+ len,
+ &desc_dram->physical);
+ if (!desc_dram->block) {
+ IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA.\n");
+ return -ENOMEM;
+ }
+ desc_dram->size = len;
+ memset(desc_dram->block, 0, len);
+
+ /* allocate DRAM region for each payload */
+ dram_regions->n_regions = 0;
+ for (i = 0; i < pnvm_data->n_chunks; i++) {
+ len = pnvm_data->chunks[i].len;
+ data = pnvm_data->chunks[i].data;
+
+ if (iwl_pcie_ctxt_info_alloc_dma(trans,
+ data,
+ len,
+ cur_payload_dram)) {
+ iwl_trans_pcie_free_pnvm_dram_regions(dram_regions,
+ trans->dev);
+ return -ENOMEM;
+ }
+
+ dram_regions->n_regions++;
+ cur_payload_dram++;
+ }
+
+ /* fill desc with the DRAM payloads addresses */
+ addresses = desc_dram->block;
+ for (i = 0; i < pnvm_data->n_chunks; i++) {
+ addresses->mem_descs[i] =
+ cpu_to_le64(dram_regions->drams[i].physical);
+ }
+
+ return 0;
+
+}
+
+int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *pnvm_payloads,
+ const struct iwl_ucode_capabilities *capa)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
&trans_pcie->prph_scratch->ctrl_cfg;
- int ret;
+ struct iwl_dram_regions *dram_regions = &trans_pcie->pnvm_data;
+ int ret = 0;
+
+ /* only allocate the DRAM if not allocated yet */
+ if (trans->pnvm_loaded)
+ return 0;
+
+ if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size))
+ return -EBUSY;
if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
return 0;
- /* only allocate the DRAM if not allocated yet */
- if (!trans->pnvm_loaded) {
- if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size))
- return -EBUSY;
-
- ret = iwl_pcie_ctxt_info_alloc_dma(trans, data, len,
- &trans_pcie->pnvm_dram);
- if (ret < 0) {
- IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA %d.\n",
- ret);
- return ret;
+ if (!pnvm_payloads->n_chunks) {
+ IWL_DEBUG_FW(trans, "no payloads\n");
+ return -EINVAL;
+ }
+
+ /* save payloads in several DRAM sections */
+ if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) {
+ ret = iwl_pcie_load_payloads_segments(trans,
+ dram_regions,
+ pnvm_payloads);
+ if (!ret)
+ trans->pnvm_loaded = true;
+ } else {
+ /* save only in one DRAM section */
+ ret = iwl_pcie_load_payloads_continuously
+ (trans,
+ pnvm_payloads,
+ &dram_regions->drams[0]);
+ if (!ret) {
+ dram_regions->n_regions = 1;
+ trans->pnvm_loaded = true;
}
}
+ return ret;
+}
+
+static inline size_t
+iwl_dram_regions_size(const struct iwl_dram_regions *dram_regions)
+{
+ size_t total_size = 0;
+ int i;
+
+ for (i = 0; i < dram_regions->n_regions; i++)
+ total_size += dram_regions->drams[i].size;
+
+ return total_size;
+}
+
+static void iwl_pcie_set_pnvm_segments(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
+ &trans_pcie->prph_scratch->ctrl_cfg;
+ struct iwl_dram_regions *dram_regions = &trans_pcie->pnvm_data;
+
prph_sc_ctrl->pnvm_cfg.pnvm_base_addr =
- cpu_to_le64(trans_pcie->pnvm_dram.physical);
+ cpu_to_le64(dram_regions->prph_scratch_mem_desc.physical);
prph_sc_ctrl->pnvm_cfg.pnvm_size =
- cpu_to_le32(trans_pcie->pnvm_dram.size);
+ cpu_to_le32(iwl_dram_regions_size(dram_regions));
+}
- return 0;
+static void iwl_pcie_set_continuous_pnvm(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
+ &trans_pcie->prph_scratch->ctrl_cfg;
+
+ prph_sc_ctrl->pnvm_cfg.pnvm_base_addr =
+ cpu_to_le64(trans_pcie->pnvm_data.drams[0].physical);
+ prph_sc_ctrl->pnvm_cfg.pnvm_size =
+ cpu_to_le32(trans_pcie->pnvm_data.drams[0].size);
+}
+
+void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa)
+{
+ if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ return;
+
+ if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG))
+ iwl_pcie_set_pnvm_segments(trans);
+ else
+ iwl_pcie_set_continuous_pnvm(trans);
}
-int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans,
- const void *data, u32 len)
+int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *payloads,
+ const struct iwl_ucode_capabilities *capa)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
&trans_pcie->prph_scratch->ctrl_cfg;
- int ret;
+ struct iwl_dram_regions *dram_regions = &trans_pcie->reduced_tables_data;
+ int ret = 0;
+
+ /* only allocate the DRAM if not allocated yet */
+ if (trans->reduce_power_loaded)
+ return 0;
if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
return 0;
- /* only allocate the DRAM if not allocated yet */
- if (!trans->reduce_power_loaded) {
- if (WARN_ON(prph_sc_ctrl->reduce_power_cfg.size))
- return -EBUSY;
+ if (WARN_ON(prph_sc_ctrl->reduce_power_cfg.size))
+ return -EBUSY;
- ret = iwl_pcie_ctxt_info_alloc_dma(trans, data, len,
- &trans_pcie->reduce_power_dram);
- if (ret < 0) {
- IWL_DEBUG_FW(trans,
- "Failed to allocate reduce power DMA %d.\n",
- ret);
- return ret;
+ if (!payloads->n_chunks) {
+ IWL_DEBUG_FW(trans, "no payloads\n");
+ return -EINVAL;
+ }
+
+ /* save payloads in several DRAM sections */
+ if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) {
+ ret = iwl_pcie_load_payloads_segments(trans,
+ dram_regions,
+ payloads);
+ if (!ret)
+ trans->reduce_power_loaded = true;
+ } else {
+ /* save only in one DRAM section */
+ ret = iwl_pcie_load_payloads_continuously
+ (trans,
+ payloads,
+ &dram_regions->drams[0]);
+ if (!ret) {
+ dram_regions->n_regions = 1;
+ trans->reduce_power_loaded = true;
}
}
+ return ret;
+}
+
+static void iwl_pcie_set_reduce_power_segments(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
+ &trans_pcie->prph_scratch->ctrl_cfg;
+ struct iwl_dram_regions *dram_regions = &trans_pcie->reduced_tables_data;
+
prph_sc_ctrl->reduce_power_cfg.base_addr =
- cpu_to_le64(trans_pcie->reduce_power_dram.physical);
+ cpu_to_le64(dram_regions->prph_scratch_mem_desc.physical);
prph_sc_ctrl->reduce_power_cfg.size =
- cpu_to_le32(trans_pcie->reduce_power_dram.size);
+ cpu_to_le32(iwl_dram_regions_size(dram_regions));
+}
- return 0;
+static void iwl_pcie_set_continuous_reduce_power(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
+ &trans_pcie->prph_scratch->ctrl_cfg;
+
+ prph_sc_ctrl->reduce_power_cfg.base_addr =
+ cpu_to_le64(trans_pcie->reduced_tables_data.drams[0].physical);
+ prph_sc_ctrl->reduce_power_cfg.size =
+ cpu_to_le32(trans_pcie->reduced_tables_data.drams[0].size);
+}
+
+void
+iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa)
+{
+ if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ return;
+
+ if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG))
+ iwl_pcie_set_reduce_power_segments(trans);
+ else
+ iwl_pcie_set_continuous_reduce_power(trans);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
index 74ce31fdf45e..5f55efe64bf5 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2021 Intel Corporation
+ * Copyright (C) 2018-2022 Intel Corporation
*/
#include "iwl-trans.h"
#include "iwl-fh.h"
@@ -38,9 +38,9 @@ static void *_iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans,
return result;
}
-static void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans,
- size_t size,
- dma_addr_t *phys)
+void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans,
+ size_t size,
+ dma_addr_t *phys)
{
return _iwl_pcie_ctxt_info_dma_alloc_coherent(trans, size, phys, 0);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 79115eb1c285..73c1fb3c0c5e 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -484,17 +484,15 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x43F0, PCI_ANY_ID, iwl_qu_long_latency_trans_cfg)},
{IWL_PCI_DEVICE(0xA0F0, PCI_ANY_ID, iwl_qu_long_latency_trans_cfg)},
- {IWL_PCI_DEVICE(0x2720, PCI_ANY_ID, iwl_qnj_trans_cfg)},
-
{IWL_PCI_DEVICE(0x2723, PCI_ANY_ID, iwl_ax200_trans_cfg)},
/* So devices */
{IWL_PCI_DEVICE(0x2725, PCI_ANY_ID, iwl_so_trans_cfg)},
- {IWL_PCI_DEVICE(0x2726, PCI_ANY_ID, iwl_snj_trans_cfg)},
{IWL_PCI_DEVICE(0x7A70, PCI_ANY_ID, iwl_so_long_latency_imr_trans_cfg)},
{IWL_PCI_DEVICE(0x7AF0, PCI_ANY_ID, iwl_so_trans_cfg)},
{IWL_PCI_DEVICE(0x51F0, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)},
{IWL_PCI_DEVICE(0x51F1, PCI_ANY_ID, iwl_so_long_latency_imr_trans_cfg)},
+ {IWL_PCI_DEVICE(0x51F1, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)},
{IWL_PCI_DEVICE(0x54F0, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)},
{IWL_PCI_DEVICE(0x7F70, PCI_ANY_ID, iwl_so_trans_cfg)},
@@ -507,6 +505,9 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x272b, PCI_ANY_ID, iwl_bz_trans_cfg)},
{IWL_PCI_DEVICE(0xA840, PCI_ANY_ID, iwl_bz_trans_cfg)},
{IWL_PCI_DEVICE(0x7740, PCI_ANY_ID, iwl_bz_trans_cfg)},
+
+/* Sc devices */
+ {IWL_PCI_DEVICE(0xE440, PCI_ANY_ID, iwl_sc_trans_cfg)},
#endif /* CONFIG_IWLMVM */
{0}
@@ -514,17 +515,16 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
#define _IWL_DEV_INFO(_device, _subdevice, _mac_type, _mac_step, _rf_type, \
- _rf_id, _rf_step, _no_160, _cores, _cdb, _jacket, _cfg, \
- _name) \
+ _rf_id, _rf_step, _no_160, _cores, _cdb, _cfg, _name) \
{ .device = (_device), .subdevice = (_subdevice), .cfg = &(_cfg), \
.name = _name, .mac_type = _mac_type, .rf_type = _rf_type, .rf_step = _rf_step, \
.no_160 = _no_160, .cores = _cores, .rf_id = _rf_id, \
- .mac_step = _mac_step, .cdb = _cdb, .jacket = _jacket }
+ .mac_step = _mac_step, .cdb = _cdb, .jacket = IWL_CFG_ANY }
#define IWL_DEV_INFO(_device, _subdevice, _cfg, _name) \
- _IWL_DEV_INFO(_device, _subdevice, IWL_CFG_ANY, IWL_CFG_ANY, \
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, \
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, _cfg, _name)
+ _IWL_DEV_INFO(_device, _subdevice, IWL_CFG_ANY, IWL_CFG_ANY, \
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, \
+ IWL_CFG_ANY, _cfg, _name)
static const struct iwl_dev_info iwl_dev_info_table[] = {
#if IS_ENABLED(CONFIG_IWLMVM)
@@ -544,6 +544,7 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_DEV_INFO(0x51F0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name),
IWL_DEV_INFO(0x51F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
IWL_DEV_INFO(0x51F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
+ IWL_DEV_INFO(0x51F1, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
IWL_DEV_INFO(0x54F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
IWL_DEV_INFO(0x54F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
IWL_DEV_INFO(0x7A70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
@@ -552,8 +553,8 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_DEV_INFO(0x7AF0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
IWL_DEV_INFO(0x271C, 0x0214, iwl9260_2ac_cfg, iwl9260_1_name),
- IWL_DEV_INFO(0x7E40, 0x1691, iwl_cfg_ma_a0_gf4_a0, iwl_ax411_killer_1690s_name),
- IWL_DEV_INFO(0x7E40, 0x1692, iwl_cfg_ma_a0_gf4_a0, iwl_ax411_killer_1690i_name),
+ IWL_DEV_INFO(0x7E40, 0x1691, iwl_cfg_ma, iwl_ax411_killer_1690s_name),
+ IWL_DEV_INFO(0x7E40, 0x1692, iwl_cfg_ma, iwl_ax411_killer_1690i_name),
/* AX200 */
IWL_DEV_INFO(0x2723, IWL_CFG_ANY, iwl_ax200_cfg_cc, iwl_ax200_name),
@@ -663,25 +664,13 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_DEV_INFO(0x7AF0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name),
IWL_DEV_INFO(0x7AF0, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name),
- /* SnJ with HR */
- IWL_DEV_INFO(0x2725, 0x00B0, iwlax411_2ax_cfg_sosnj_gf4_a0, NULL),
- IWL_DEV_INFO(0x2726, 0x0090, iwlax211_cfg_snj_gf_a0, NULL),
- IWL_DEV_INFO(0x2726, 0x0098, iwlax211_cfg_snj_gf_a0, NULL),
- IWL_DEV_INFO(0x2726, 0x00B0, iwlax411_2ax_cfg_sosnj_gf4_a0, NULL),
- IWL_DEV_INFO(0x2726, 0x00B4, iwlax411_2ax_cfg_sosnj_gf4_a0, NULL),
- IWL_DEV_INFO(0x2726, 0x0510, iwlax211_cfg_snj_gf_a0, NULL),
- IWL_DEV_INFO(0x2726, 0x1651, iwl_cfg_snj_hr_b0, iwl_ax201_killer_1650s_name),
- IWL_DEV_INFO(0x2726, 0x1652, iwl_cfg_snj_hr_b0, iwl_ax201_killer_1650i_name),
- IWL_DEV_INFO(0x2726, 0x1691, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690s_name),
- IWL_DEV_INFO(0x2726, 0x1692, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690i_name),
- IWL_DEV_INFO(0x7F70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
- IWL_DEV_INFO(0x7F70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
-
/* SO with GF2 */
IWL_DEV_INFO(0x2726, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),
IWL_DEV_INFO(0x2726, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),
IWL_DEV_INFO(0x51F0, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),
IWL_DEV_INFO(0x51F0, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),
+ IWL_DEV_INFO(0x51F1, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),
+ IWL_DEV_INFO(0x51F1, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),
IWL_DEV_INFO(0x54F0, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),
IWL_DEV_INFO(0x54F0, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),
IWL_DEV_INFO(0x7A70, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),
@@ -692,93 +681,72 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_DEV_INFO(0x7F70, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),
/* MA with GF2 */
- IWL_DEV_INFO(0x7E40, 0x1671, iwl_cfg_ma_a0_gf_a0, iwl_ax211_killer_1675s_name),
- IWL_DEV_INFO(0x7E40, 0x1672, iwl_cfg_ma_a0_gf_a0, iwl_ax211_killer_1675i_name),
+ IWL_DEV_INFO(0x7E40, 0x1671, iwl_cfg_ma, iwl_ax211_killer_1675s_name),
+ IWL_DEV_INFO(0x7E40, 0x1672, iwl_cfg_ma, iwl_ax211_killer_1675i_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_2ac_cfg_soc, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_2ac_cfg_soc, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_2ac_cfg_soc, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_2ac_cfg_soc, iwl9462_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_2ac_cfg_soc, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_2ac_cfg_soc, iwl9560_name),
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9260_2ac_cfg, iwl9461_160_name),
- _IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9260_2ac_cfg, iwl9461_name),
- _IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9260_2ac_cfg, iwl9462_160_name),
- _IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9260_2ac_cfg, iwl9462_name),
-
- _IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB,
iwl9260_2ac_cfg, iwl9270_160_name),
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB,
iwl9260_2ac_cfg, iwl9270_name),
_IWL_DEV_INFO(0x271B, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_TH1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9260_2ac_cfg, iwl9162_160_name),
_IWL_DEV_INFO(0x271B, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_TH1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9260_2ac_cfg, iwl9162_name),
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9260_2ac_cfg, iwl9260_160_name),
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9260_2ac_cfg, iwl9260_name),
/* Qu with Jf */
@@ -786,585 +754,341 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_b0_jf_b0_cfg, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_b0_jf_b0_cfg, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_b0_jf_b0_cfg, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_b0_jf_b0_cfg, iwl9462_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_b0_jf_b0_cfg, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_b0_jf_b0_cfg, iwl9560_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_b0_jf_b0_cfg, iwl9560_killer_1550s_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_b0_jf_b0_cfg, iwl9560_killer_1550i_name),
/* Qu C step */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_c0_jf_b0_cfg, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_c0_jf_b0_cfg, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_c0_jf_b0_cfg, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_c0_jf_b0_cfg, iwl9462_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_c0_jf_b0_cfg, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_c0_jf_b0_cfg, iwl9560_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_c0_jf_b0_cfg, iwl9560_killer_1550s_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_c0_jf_b0_cfg, iwl9560_killer_1550i_name),
/* QuZ */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_quz_a0_jf_b0_cfg, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_quz_a0_jf_b0_cfg, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_quz_a0_jf_b0_cfg, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_quz_a0_jf_b0_cfg, iwl9462_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_quz_a0_jf_b0_cfg, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_quz_a0_jf_b0_cfg, iwl9560_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_quz_a0_jf_b0_cfg, iwl9560_killer_1550s_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_quz_a0_jf_b0_cfg, iwl9560_killer_1550i_name),
- /* QnJ */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9560_qnj_b0_jf_b0_cfg, iwl9461_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9560_qnj_b0_jf_b0_cfg, iwl9461_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9560_qnj_b0_jf_b0_cfg, iwl9462_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9560_qnj_b0_jf_b0_cfg, iwl9462_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9560_qnj_b0_jf_b0_cfg, iwl9560_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9560_qnj_b0_jf_b0_cfg, iwl9560_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9560_qnj_b0_jf_b0_cfg, iwl9560_killer_1550s_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9560_qnj_b0_jf_b0_cfg, iwl9560_killer_1550i_name),
-
/* Qu with Hr */
/* Qu B step */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_qu_b0_hr1_b0, iwl_ax101_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_qu_b0_hr_b0, iwl_ax203_name),
/* Qu C step */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_qu_c0_hr1_b0, iwl_ax101_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_qu_c0_hr_b0, iwl_ax203_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_qu_c0_hr_b0, iwl_ax201_name),
/* QuZ */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_quz_a0_hr1_b0, iwl_ax101_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, SILICON_B_STEP,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_quz_a0_hr_b0, iwl_ax203_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, SILICON_B_STEP,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_quz_a0_hr_b0, iwl_ax201_name),
-/* QnJ with Hr */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_qnj_b0_hr_b0_cfg, iwl_ax201_name),
-
-/* SnJ with Jf */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_a0_jf_b0, iwl9461_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_a0_jf_b0, iwl9461_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_a0_jf_b0, iwl9462_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_a0_jf_b0, iwl9462_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_a0_jf_b0, iwl9560_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_a0_jf_b0, iwl9560_name),
-
-/* SnJ with Hr */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_hr_b0, iwl_ax101_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_hr_b0, iwl_ax201_name),
-
/* Ma */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_a0_hr_b0, iwl_ax201_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_a0_gf_a0, iwl_ax211_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_a0_gf4_a0, iwl_ax211_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_a0_mr_a0, iwl_ax221_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_a0_fm_a0, iwl_ax231_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_a0_mr_a0, iwl_ax221_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP,
+ IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_b0_hr_b0, iwl_ax201_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_b0_gf_a0, iwl_ax211_name),
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
+ iwl_cfg_ma, iwl_ax201_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP,
+ IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_b0_gf4_a0, iwl_ax211_name),
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ iwl_cfg_ma, iwl_ax211_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP,
+ IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_b0_mr_a0, iwl_ax221_name),
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
+ iwl_cfg_ma, iwl_ax221_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP,
+ IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_b0_fm_a0, iwl_ax231_name),
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
+ iwl_cfg_ma, iwl_ax231_name),
/* So with Hr */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_hr_a0, iwl_ax203_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_hr_a0, iwl_ax101_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_hr_a0, iwl_ax201_name),
/* So-F with Hr */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_hr_a0, iwl_ax203_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_hr_a0, iwl_ax101_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_hr_a0, iwl_ax201_name),
/* So-F with Gf */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB,
iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_name),
/* Bz */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bz_a0_hr_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bz_a0_hr_b0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bz_a0_gf_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY,
- iwl_cfg_bz_a0_gf4_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bz_a0_mr_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bz_a0_fm_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_NO_JACKET,
- iwl_cfg_bz_a0_fm4_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bz_a0_fm_b0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bz_a0_fm4_b0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_NO_JACKET,
- iwl_cfg_gl_a0_fm_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_NO_JACKET,
- iwl_cfg_gl_b0_fm_b0, iwl_bz_name),
-
-/* BZ Z step */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, SILICON_Z_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bz_z0_gf_a0, iwl_bz_name),
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ iwl_cfg_bz, iwl_bz_name),
-/* BNJ */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bnj_a0_fm_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bnj_b0_fm_b0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bnj_a0_fm4_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bnj_b0_fm4_b0, iwl_bz_name),
+/* Ga (Gl) */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_GL, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bnj_a0_gf_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bnj_b0_gf_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bnj_a0_gf4_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bnj_b0_gf4_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bnj_a0_hr_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bnj_a0_hr_b0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bnj_b0_hr_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bnj_b0_hr_b0, iwl_bz_name),
+ IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
+ iwl_cfg_gl, iwl_bz_name),
/* SoF with JF2 */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9560_name),
/* SoF with JF */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9462_name),
/* So with GF */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB,
iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_name),
/* So with JF2 */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9560_name),
/* So with JF */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9462_name),
/* MsP */
@@ -1372,24 +1096,25 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_ms_a0, iwl_ax204_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_ms_a0, iwl_ax204_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_a0_ms_a0, iwl_ax204_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_a0_ms_a0, iwl_ax204_name)
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
+ iwl_cfg_ma, iwl_ax204_name),
+/* Sc */
+ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_SC, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ iwl_cfg_sc, iwl_sc_name),
#endif /* CONFIG_IWLMVM */
};
@@ -1669,17 +1394,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
#if IS_ENABLED(CONFIG_IWLMVM)
-
- /*
- * Workaround for problematic SnJ device: sometimes when
- * certain RF modules are connected to SnJ, the device ID
- * changes to QnJ's ID. So we are using QnJ's trans_cfg until
- * here. But if we detect that the MAC type is actually SnJ,
- * we should switch to it here to avoid problems later.
- */
- if (CSR_HW_REV_TYPE(iwl_trans->hw_rev) == IWL_CFG_MAC_TYPE_SNJ)
- iwl_trans->trans_cfg = &iwl_so_trans_cfg;
-
/*
* special-case 7265D, it has the same PCI IDs.
*
@@ -1752,6 +1466,15 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
trans_pcie->num_rx_bufs = RX_QUEUE_SIZE;
}
+ if (!iwl_trans->trans_cfg->integrated) {
+ u16 link_status;
+
+ pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &link_status);
+
+ iwl_trans->pcie_link_speed =
+ u16_get_bits(link_status, PCI_EXP_LNKSTA_CLS);
+ }
+
ret = iwl_trans_init(iwl_trans);
if (ret)
goto out_free_trans;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
index 69b95ad5993b..0adcf0e13e85 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
@@ -23,6 +23,7 @@
#include "iwl-op-mode.h"
#include "iwl-drv.h"
#include "queue/tx.h"
+#include "iwl-context-info.h"
/*
* RX related structures and functions
@@ -306,7 +307,9 @@ enum iwl_pcie_imr_status {
* @trans: pointer to the generic transport area
* @scd_base_addr: scheduler sram base address in SRAM
* @kw: keep warm address
- * @pnvm_dram: DRAM area that contains the PNVM data
+ * @pnvm_data: holds info about pnvm payloads allocated in DRAM
+ * @reduced_tables_data: holds info about power reduced tablse
+ * payloads allocated in DRAM
* @pci_dev: basic pci-network driver stuff
* @hw_base: pci hardware address support
* @ucode_write_complete: indicates that the ucode has been copied.
@@ -380,8 +383,9 @@ struct iwl_trans_pcie {
u32 scd_base_addr;
struct iwl_dma_ptr kw;
- struct iwl_dram_data pnvm_dram;
- struct iwl_dram_data reduce_power_dram;
+ /* pnvm data */
+ struct iwl_dram_regions pnvm_data;
+ struct iwl_dram_regions reduced_tables_data;
struct iwl_txq *txq_memory;
@@ -478,6 +482,8 @@ struct iwl_trans
const struct pci_device_id *ent,
const struct iwl_cfg_trans_params *cfg_trans);
void iwl_trans_pcie_free(struct iwl_trans *trans);
+void iwl_trans_pcie_free_pnvm_dram_regions(struct iwl_dram_regions *dram_regions,
+ struct device *dev);
bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans);
#define _iwl_trans_pcie_grab_nic_access(trans) \
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
index 0d7890f99a5f..f87b28edc267 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
@@ -699,17 +699,25 @@ static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans,
rxq->used_bd = NULL;
}
+static size_t iwl_pcie_rb_stts_size(struct iwl_trans *trans)
+{
+ bool use_rx_td = (trans->trans_cfg->device_family >=
+ IWL_DEVICE_FAMILY_AX210);
+
+ if (use_rx_td)
+ return sizeof(__le16);
+
+ return sizeof(struct iwl_rb_status);
+}
+
static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
struct iwl_rxq *rxq)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ size_t rb_stts_size = iwl_pcie_rb_stts_size(trans);
struct device *dev = trans->dev;
int i;
int free_size;
- bool use_rx_td = (trans->trans_cfg->device_family >=
- IWL_DEVICE_FAMILY_AX210);
- size_t rb_stts_size = use_rx_td ? sizeof(__le16) :
- sizeof(struct iwl_rb_status);
spin_lock_init(&rxq->lock);
if (trans->trans_cfg->mq_rx_supported)
@@ -757,11 +765,9 @@ err:
static int iwl_pcie_rx_alloc(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ size_t rb_stts_size = iwl_pcie_rb_stts_size(trans);
struct iwl_rb_allocator *rba = &trans_pcie->rba;
int i, ret;
- size_t rb_stts_size = trans->trans_cfg->device_family >=
- IWL_DEVICE_FAMILY_AX210 ?
- sizeof(__le16) : sizeof(struct iwl_rb_status);
if (WARN_ON(trans_pcie->rxq))
return -EINVAL;
@@ -1193,11 +1199,9 @@ int iwl_pcie_gen2_rx_init(struct iwl_trans *trans)
void iwl_pcie_rx_free(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ size_t rb_stts_size = iwl_pcie_rb_stts_size(trans);
struct iwl_rb_allocator *rba = &trans_pcie->rba;
int i;
- size_t rb_stts_size = trans->trans_cfg->device_family >=
- IWL_DEVICE_FAMILY_AX210 ?
- sizeof(__le16) : sizeof(struct iwl_rb_status);
/*
* if rxq is NULL, it means that nothing has been allocated,
@@ -1636,14 +1640,14 @@ irqreturn_t iwl_pcie_irq_rx_msix_handler(int irq, void *dev_id)
struct msix_entry *entry = dev_id;
struct iwl_trans_pcie *trans_pcie = iwl_pcie_get_trans_pcie(entry);
struct iwl_trans *trans = trans_pcie->trans;
- struct iwl_rxq *rxq = &trans_pcie->rxq[entry->entry];
+ struct iwl_rxq *rxq;
trace_iwlwifi_dev_irq_msix(trans->dev, entry, false, 0, 0);
if (WARN_ON(entry->entry >= trans->num_rx_queues))
return IRQ_NONE;
- if (!rxq) {
+ if (!trans_pcie->rxq) {
if (net_ratelimit())
IWL_ERR(trans,
"[%d] Got MSI-X interrupt before we have Rx queues\n",
@@ -1651,6 +1655,7 @@ irqreturn_t iwl_pcie_irq_rx_msix_handler(int irq, void *dev_id)
return IRQ_NONE;
}
+ rxq = &trans_pcie->rxq[entry->entry];
lock_map_acquire(&trans->sync_cmd_lockdep_map);
IWL_DEBUG_ISR(trans, "[%d] Got interrupt\n", entry->entry);
@@ -1873,7 +1878,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
return IRQ_NONE;
}
- if (unlikely(inta == 0xFFFFFFFF || (inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
+ if (unlikely(inta == 0xFFFFFFFF || iwl_trans_is_hw_error_value(inta))) {
/*
* Hardware disappeared. It might have
* already raised an interrupt.
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
index 73b395841ca8..fa46dad5fd68 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#include "iwl-trans.h"
#include "iwl-prph.h"
@@ -117,9 +117,14 @@ static void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans)
trans_pcie->fw_reset_state != FW_RESET_REQUESTED,
FW_RESET_TIMEOUT);
if (!ret || trans_pcie->fw_reset_state == FW_RESET_ERROR) {
- IWL_INFO(trans,
- "firmware didn't ACK the reset - continue anyway\n");
- iwl_trans_fw_error(trans, true);
+ u32 inta_hw = iwl_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD);
+
+ IWL_ERR(trans,
+ "timeout waiting for FW reset ACK (inta_hw=0x%x)\n",
+ inta_hw);
+
+ if (!(inta_hw & MSIX_HW_INT_CAUSES_REG_RESET_DONE))
+ iwl_trans_fw_error(trans, true);
}
trans_pcie->fw_reset_state = FW_RESET_IDLE;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index b281850fbf7a..3e988da44973 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2007-2015, 2018-2022 Intel Corporation
+ * Copyright (C) 2007-2015, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -131,13 +131,15 @@ static int iwl_trans_pcie_sw_reset(struct iwl_trans *trans,
bool retake_ownership)
{
/* Reset entire device - do controller reset (results in SHRD_HW_RST) */
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
iwl_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_SW_RESET);
- else
+ usleep_range(10000, 20000);
+ } else {
iwl_set_bit(trans, CSR_RESET,
CSR_RESET_REG_FLAG_SW_RESET);
- usleep_range(5000, 6000);
+ usleep_range(5000, 6000);
+ }
if (retake_ownership)
return iwl_pcie_prepare_card_hw(trans);
@@ -161,7 +163,7 @@ static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans)
}
static void iwl_pcie_alloc_fw_monitor_block(struct iwl_trans *trans,
- u8 max_power, u8 min_power)
+ u8 max_power)
{
struct iwl_dram_data *fw_mon = &trans->dbg.fw_mon;
void *block = NULL;
@@ -169,10 +171,13 @@ static void iwl_pcie_alloc_fw_monitor_block(struct iwl_trans *trans,
u32 size = 0;
u8 power;
- if (fw_mon->size)
+ if (fw_mon->size) {
+ memset(fw_mon->block, 0, fw_mon->size);
return;
+ }
- for (power = max_power; power >= min_power; power--) {
+ /* need at least 2 KiB, so stop at 11 */
+ for (power = max_power; power >= 11; power--) {
size = BIT(power);
block = dma_alloc_coherent(trans->dev, size, &physical,
GFP_KERNEL | __GFP_NOWARN);
@@ -213,10 +218,7 @@ void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power)
max_power))
return;
- if (trans->dbg.fw_mon.size)
- return;
-
- iwl_pcie_alloc_fw_monitor_block(trans, max_power, 11);
+ iwl_pcie_alloc_fw_monitor_block(trans, max_power);
}
static u32 iwl_trans_pcie_read_shr(struct iwl_trans *trans, u32 reg)
@@ -475,7 +477,7 @@ void iwl_pcie_apm_stop_master(struct iwl_trans *trans)
CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,
CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,
100);
- msleep(100);
+ usleep_range(10000, 20000);
} else {
iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
@@ -817,7 +819,7 @@ static int iwl_pcie_load_cpu_sections_8000(struct iwl_trans *trans,
iwl_enable_interrupts(trans);
- if (trans->trans_cfg->use_tfh) {
+ if (trans->trans_cfg->gen2) {
if (cpu == 1)
iwl_write_prph(trans, UREG_UCODE_LOAD_STATUS,
0xFFFF);
@@ -1786,7 +1788,7 @@ static int iwl_trans_pcie_clear_persistence_bit(struct iwl_trans *trans)
}
hpm = iwl_read_umac_prph_no_grab(trans, HPM_DEBUG);
- if (hpm != 0xa5a5a5a0 && (hpm & PERSISTENCE_BIT)) {
+ if (!iwl_trans_is_hw_error_value(hpm) && (hpm & PERSISTENCE_BIT)) {
u32 wprot_val = iwl_read_umac_prph_no_grab(trans, wprot);
if (wprot_val & PREG_WFPM_ACCESS) {
@@ -1993,6 +1995,29 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans,
trans_pcie->fw_reset_handshake = trans_cfg->fw_reset_handshake;
}
+void iwl_trans_pcie_free_pnvm_dram_regions(struct iwl_dram_regions *dram_regions,
+ struct device *dev)
+{
+ u8 i;
+ struct iwl_dram_data *desc_dram = &dram_regions->prph_scratch_mem_desc;
+
+ /* free DRAM payloads */
+ for (i = 0; i < dram_regions->n_regions; i++) {
+ dma_free_coherent(dev, dram_regions->drams[i].size,
+ dram_regions->drams[i].block,
+ dram_regions->drams[i].physical);
+ }
+ dram_regions->n_regions = 0;
+
+ /* free DRAM addresses array */
+ if (desc_dram->block) {
+ dma_free_coherent(dev, desc_dram->size,
+ desc_dram->block,
+ desc_dram->physical);
+ }
+ memset(desc_dram, 0, sizeof(*desc_dram));
+}
+
void iwl_trans_pcie_free(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -2025,16 +2050,10 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
iwl_pcie_free_fw_monitor(trans);
- if (trans_pcie->pnvm_dram.size)
- dma_free_coherent(trans->dev, trans_pcie->pnvm_dram.size,
- trans_pcie->pnvm_dram.block,
- trans_pcie->pnvm_dram.physical);
-
- if (trans_pcie->reduce_power_dram.size)
- dma_free_coherent(trans->dev,
- trans_pcie->reduce_power_dram.size,
- trans_pcie->reduce_power_dram.block,
- trans_pcie->reduce_power_dram.physical);
+ iwl_trans_pcie_free_pnvm_dram_regions(&trans_pcie->pnvm_data,
+ trans->dev);
+ iwl_trans_pcie_free_pnvm_dram_regions(&trans_pcie->reduced_tables_data,
+ trans->dev);
mutex_destroy(&trans_pcie->mutex);
iwl_trans_free(trans);
@@ -3375,7 +3394,7 @@ iwl_trans_pcie_dump_data(struct iwl_trans *trans,
u8 tfdidx;
u32 caplen, cmdlen;
- if (trans->trans_cfg->use_tfh)
+ if (trans->trans_cfg->gen2)
tfdidx = idx;
else
tfdidx = ptr;
@@ -3534,7 +3553,9 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = {
.txq_free = iwl_txq_dyn_free,
.wait_txq_empty = iwl_trans_pcie_wait_txq_empty,
.rxq_dma_data = iwl_trans_pcie_rxq_dma_data,
+ .load_pnvm = iwl_trans_pcie_ctx_info_gen3_load_pnvm,
.set_pnvm = iwl_trans_pcie_ctx_info_gen3_set_pnvm,
+ .load_reduce_power = iwl_trans_pcie_ctx_info_gen3_load_reduce_power,
.set_reduce_power = iwl_trans_pcie_ctx_info_gen3_set_reduce_power,
#ifdef CONFIG_IWLWIFI_DEBUGFS
.debugfs_cleanup = iwl_trans_pcie_debugfs_cleanup,
@@ -3576,7 +3597,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
init_waitqueue_head(&trans_pcie->imr_waitq);
trans_pcie->rba.alloc_wq = alloc_workqueue("rb_allocator",
- WQ_HIGHPRI | WQ_UNBOUND, 1);
+ WQ_HIGHPRI | WQ_UNBOUND, 0);
if (!trans_pcie->rba.alloc_wq) {
ret = -ENOMEM;
goto out_free_trans;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
index 3546c5269c3b..790e5b124740 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2003-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2003-2014, 2018-2021, 2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -364,7 +364,7 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans)
for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues;
txq_id++) {
struct iwl_txq *txq = trans->txqs.txq[txq_id];
- if (trans->trans_cfg->use_tfh)
+ if (trans->trans_cfg->gen2)
iwl_write_direct64(trans,
FH_MEM_CBBC_QUEUE(trans, txq_id),
txq->dma_addr);
@@ -1547,6 +1547,9 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
/* there must be data left over for TB1 or this code must be changed */
BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_FIRST_TB_SIZE);
+ BUILD_BUG_ON(sizeof(struct iwl_cmd_header) +
+ offsetofend(struct iwl_tx_cmd, scratch) >
+ IWL_FIRST_TB_SIZE);
/* map the data for TB1 */
tb1_addr = ((u8 *)&dev_cmd->hdr) + IWL_FIRST_TB_SIZE;
diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.c b/drivers/net/wireless/intel/iwlwifi/queue/tx.c
index d1c39c214f95..5bb3cc3367c9 100644
--- a/drivers/net/wireless/intel/iwlwifi/queue/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2020-2022 Intel Corporation
+ * Copyright (C) 2020-2023 Intel Corporation
*/
#include <net/tso.h>
#include <linux/tcp.h>
@@ -648,6 +648,13 @@ struct iwl_tfh_tfd *iwl_txq_gen2_build_tfd(struct iwl_trans *trans,
/* There must be data left over for TB1 or this code must be changed */
BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen2) < IWL_FIRST_TB_SIZE);
+ BUILD_BUG_ON(sizeof(struct iwl_cmd_header) +
+ offsetofend(struct iwl_tx_cmd_gen2, dram_info) >
+ IWL_FIRST_TB_SIZE);
+ BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen3) < IWL_FIRST_TB_SIZE);
+ BUILD_BUG_ON(sizeof(struct iwl_cmd_header) +
+ offsetofend(struct iwl_tx_cmd_gen3, dram_info) >
+ IWL_FIRST_TB_SIZE);
memset(tfd, 0, sizeof(*tfd));
@@ -978,7 +985,7 @@ void iwl_txq_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq)
bool active;
u8 fifo;
- if (trans->trans_cfg->use_tfh) {
+ if (trans->trans_cfg->gen2) {
IWL_ERR(trans, "Queue %d is stuck %d %d\n", txq_id,
txq->read_ptr, txq->write_ptr);
/* TODO: access new SCD registers and dump them */
@@ -1027,10 +1034,13 @@ int iwl_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num,
size_t tb0_buf_sz;
int i;
+ if (WARN_ONCE(slots_num <= 0, "Invalid slots num:%d\n", slots_num))
+ return -EINVAL;
+
if (WARN_ON(txq->entries || txq->tfds))
return -EINVAL;
- if (trans->trans_cfg->use_tfh)
+ if (trans->trans_cfg->gen2)
tfd_sz = trans->txqs.tfd.size * slots_num;
timer_setup(&txq->stuck_timer, iwl_txq_stuck_timer, 0);
@@ -1337,7 +1347,7 @@ static inline dma_addr_t iwl_txq_gen1_tfd_tb_get_addr(struct iwl_trans *trans,
dma_addr_t addr;
dma_addr_t hi_len;
- if (trans->trans_cfg->use_tfh) {
+ if (trans->trans_cfg->gen2) {
struct iwl_tfh_tfd *tfh_tfd = _tfd;
struct iwl_tfh_tb *tfh_tb = &tfh_tfd->tbs[idx];
@@ -1398,7 +1408,7 @@ void iwl_txq_gen1_tfd_unmap(struct iwl_trans *trans,
meta->tbs = 0;
- if (trans->trans_cfg->use_tfh) {
+ if (trans->trans_cfg->gen2) {
struct iwl_tfh_tfd *tfd_fh = (void *)tfd;
tfd_fh->num_tbs = 0;
@@ -1615,7 +1625,7 @@ void iwl_txq_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
txq->entries[read_ptr].skb = NULL;
- if (!trans->trans_cfg->use_tfh)
+ if (!trans->trans_cfg->gen2)
iwl_txq_gen1_inval_byte_cnt_tbl(trans, txq);
iwl_txq_free_tfd(trans, txq);
diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.h b/drivers/net/wireless/intel/iwlwifi/queue/tx.h
index eca53bfd326d..1e4a24ab9bab 100644
--- a/drivers/net/wireless/intel/iwlwifi/queue/tx.h
+++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2020-2022 Intel Corporation
+ * Copyright (C) 2020-2023 Intel Corporation
*/
#ifndef __iwl_trans_queue_tx_h__
#define __iwl_trans_queue_tx_h__
@@ -38,7 +38,7 @@ static inline void iwl_wake_queue(struct iwl_trans *trans,
static inline void *iwl_txq_get_tfd(struct iwl_trans *trans,
struct iwl_txq *txq, int idx)
{
- if (trans->trans_cfg->use_tfh)
+ if (trans->trans_cfg->gen2)
idx = iwl_txq_get_cmd_index(txq, idx);
return (u8 *)txq->tfds + trans->txqs.tfd.size * idx;
@@ -135,7 +135,7 @@ static inline u8 iwl_txq_gen1_tfd_get_num_tbs(struct iwl_trans *trans,
{
struct iwl_tfd *tfd;
- if (trans->trans_cfg->use_tfh) {
+ if (trans->trans_cfg->gen2) {
struct iwl_tfh_tfd *tfh_tfd = _tfd;
return le16_to_cpu(tfh_tfd->num_tbs) & 0x1f;
@@ -151,7 +151,7 @@ static inline u16 iwl_txq_gen1_tfd_tb_get_len(struct iwl_trans *trans,
struct iwl_tfd *tfd;
struct iwl_tfd_tb *tb;
- if (trans->trans_cfg->use_tfh) {
+ if (trans->trans_cfg->gen2) {
struct iwl_tfh_tfd *tfh_tfd = _tfd;
struct iwl_tfh_tb *tfh_tb = &tfh_tfd->tbs[idx];
diff --git a/drivers/net/wireless/intersil/hostap/Kconfig b/drivers/net/wireless/intersil/hostap/Kconfig
index c865d3156cea..2edff8efbcbb 100644
--- a/drivers/net/wireless/intersil/hostap/Kconfig
+++ b/drivers/net/wireless/intersil/hostap/Kconfig
@@ -56,7 +56,7 @@ config HOSTAP_FIRMWARE_NVRAM
config HOSTAP_PLX
tristate "Host AP driver for Prism2/2.5/3 in PLX9052 PCI adaptors"
- depends on PCI && HOSTAP
+ depends on PCI && HOSTAP && HAS_IOPORT
help
Host AP driver's version for Prism2/2.5/3 PC Cards in PLX9052 based
PCI adaptors.
diff --git a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c
index 26287b129d18..b4adfc190ae8 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c
@@ -3630,7 +3630,7 @@ static int prism2_ioctl_get_encryption(local_info_t *local,
param->u.crypt.key_len = 0;
param->u.crypt.idx = 0xff;
} else {
- strncpy(param->u.crypt.alg, (*crypt)->ops->name,
+ strscpy(param->u.crypt.alg, (*crypt)->ops->name,
HOSTAP_CRYPT_ALG_NAME_LEN);
param->u.crypt.key_len = 0;
diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_cs.c b/drivers/net/wireless/intersil/orinoco/orinoco_cs.c
index a956f965a1e5..03bfd2482656 100644
--- a/drivers/net/wireless/intersil/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/intersil/orinoco/orinoco_cs.c
@@ -96,6 +96,7 @@ orinoco_cs_probe(struct pcmcia_device *link)
{
struct orinoco_private *priv;
struct orinoco_pccard *card;
+ int ret;
priv = alloc_orinocodev(sizeof(*card), &link->dev,
orinoco_cs_hard_reset, NULL);
@@ -107,8 +108,16 @@ orinoco_cs_probe(struct pcmcia_device *link)
card->p_dev = link;
link->priv = priv;
- return orinoco_cs_config(link);
-} /* orinoco_cs_attach */
+ ret = orinoco_cs_config(link);
+ if (ret)
+ goto err_free_orinocodev;
+
+ return 0;
+
+err_free_orinocodev:
+ free_orinocodev(priv);
+ return ret;
+}
static void orinoco_cs_detach(struct pcmcia_device *link)
{
diff --git a/drivers/net/wireless/intersil/orinoco/spectrum_cs.c b/drivers/net/wireless/intersil/orinoco/spectrum_cs.c
index 291ef97ed45e..841d623c621a 100644
--- a/drivers/net/wireless/intersil/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/intersil/orinoco/spectrum_cs.c
@@ -157,6 +157,7 @@ spectrum_cs_probe(struct pcmcia_device *link)
{
struct orinoco_private *priv;
struct orinoco_pccard *card;
+ int ret;
priv = alloc_orinocodev(sizeof(*card), &link->dev,
spectrum_cs_hard_reset,
@@ -169,8 +170,16 @@ spectrum_cs_probe(struct pcmcia_device *link)
card->p_dev = link;
link->priv = priv;
- return spectrum_cs_config(link);
-} /* spectrum_cs_attach */
+ ret = spectrum_cs_config(link);
+ if (ret)
+ goto err_free_orinocodev;
+
+ return 0;
+
+err_free_orinocodev:
+ free_orinocodev(priv);
+ return ret;
+}
static void spectrum_cs_detach(struct pcmcia_device *link)
{
diff --git a/drivers/net/wireless/intersil/p54/p54spi.c b/drivers/net/wireless/intersil/p54/p54spi.c
index 19152fd449ba..ce0179b8ab36 100644
--- a/drivers/net/wireless/intersil/p54/p54spi.c
+++ b/drivers/net/wireless/intersil/p54/p54spi.c
@@ -28,6 +28,7 @@
#endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */
MODULE_FIRMWARE("3826.arm");
+MODULE_FIRMWARE("3826.eeprom");
/* gpios should be handled in board files and provided via platform data,
* but because it's currently impossible for p54spi to have a header file
diff --git a/drivers/net/wireless/legacy/ray_cs.c b/drivers/net/wireless/legacy/ray_cs.c
index 1f57a0055bbd..8ace797ce951 100644
--- a/drivers/net/wireless/legacy/ray_cs.c
+++ b/drivers/net/wireless/legacy/ray_cs.c
@@ -270,13 +270,14 @@ static int ray_probe(struct pcmcia_device *p_dev)
{
ray_dev_t *local;
struct net_device *dev;
+ int ret;
dev_dbg(&p_dev->dev, "ray_attach()\n");
/* Allocate space for private device-specific data */
dev = alloc_etherdev(sizeof(ray_dev_t));
if (!dev)
- goto fail_alloc_dev;
+ return -ENOMEM;
local = netdev_priv(dev);
local->finder = p_dev;
@@ -313,16 +314,20 @@ static int ray_probe(struct pcmcia_device *p_dev)
timer_setup(&local->timer, NULL, 0);
this_device = p_dev;
- return ray_config(p_dev);
+ ret = ray_config(p_dev);
+ if (ret)
+ goto err_free_dev;
-fail_alloc_dev:
- return -ENOMEM;
-} /* ray_attach */
+ return 0;
+
+err_free_dev:
+ free_netdev(dev);
+ return ret;
+}
static void ray_detach(struct pcmcia_device *link)
{
struct net_device *dev;
- ray_dev_t *local;
dev_dbg(&link->dev, "ray_detach\n");
@@ -331,9 +336,6 @@ static void ray_detach(struct pcmcia_device *link)
ray_release(link);
- local = netdev_priv(dev);
- del_timer_sync(&local->timer);
-
if (link->priv) {
unregister_netdev(dev);
free_netdev(dev);
@@ -625,7 +627,7 @@ static void init_startup_params(ray_dev_t *local)
local->sparm.b4.a_acting_as_ap_status = TYPE_STA;
if (essid != NULL)
- strncpy(local->sparm.b4.a_current_ess_id, essid, ESSID_SIZE);
+ strscpy(local->sparm.b4.a_current_ess_id, essid, ESSID_SIZE);
} /* init_startup_params */
/*===========================================================================*/
@@ -734,11 +736,14 @@ static void ray_release(struct pcmcia_device *link)
dev_dbg(&link->dev, "ray_release\n");
- del_timer(&local->timer);
+ del_timer_sync(&local->timer);
- iounmap(local->sram);
- iounmap(local->rmem);
- iounmap(local->amem);
+ if (local->sram)
+ iounmap(local->sram);
+ if (local->rmem)
+ iounmap(local->rmem);
+ if (local->amem)
+ iounmap(local->amem);
pcmcia_disable_device(link);
dev_dbg(&link->dev, "ray_release ending\n");
diff --git a/drivers/net/wireless/legacy/rayctl.h b/drivers/net/wireless/legacy/rayctl.h
index 2b0f332043d7..1f3bde8ac73d 100644
--- a/drivers/net/wireless/legacy/rayctl.h
+++ b/drivers/net/wireless/legacy/rayctl.h
@@ -577,7 +577,7 @@ struct tx_msg {
struct tib_structure tib;
struct phy_header phy;
struct mac_header mac;
- UCHAR var[1];
+ UCHAR var[];
};
/****** ECF Receive Control Structure (RCS) Area at Shared RAM offset 0x0800 */
diff --git a/drivers/net/wireless/legacy/wl3501_cs.c b/drivers/net/wireless/legacy/wl3501_cs.c
index 7fb2f9513476..c45c4b7cbbaf 100644
--- a/drivers/net/wireless/legacy/wl3501_cs.c
+++ b/drivers/net/wireless/legacy/wl3501_cs.c
@@ -1862,6 +1862,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
{
struct net_device *dev;
struct wl3501_card *this;
+ int ret;
/* The io structure describes IO port mapping */
p_dev->resource[0]->end = 16;
@@ -1873,8 +1874,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
dev = alloc_etherdev(sizeof(struct wl3501_card));
if (!dev)
- goto out_link;
-
+ return -ENOMEM;
dev->netdev_ops = &wl3501_netdev_ops;
dev->watchdog_timeo = 5 * HZ;
@@ -1887,9 +1887,15 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
netif_stop_queue(dev);
p_dev->priv = dev;
- return wl3501_config(p_dev);
-out_link:
- return -ENOMEM;
+ ret = wl3501_config(p_dev);
+ if (ret)
+ goto out_free_etherdev;
+
+ return 0;
+
+out_free_etherdev:
+ free_netdev(dev);
+ return ret;
}
static int wl3501_config(struct pcmcia_device *link)
diff --git a/drivers/net/wireless/marvell/mwifiex/11n.h b/drivers/net/wireless/marvell/mwifiex/11n.h
index 94b5e3e4ba08..7738ebe1fec1 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n.h
+++ b/drivers/net/wireless/marvell/mwifiex/11n.h
@@ -102,14 +102,14 @@ static inline u8 mwifiex_space_avail_for_new_ba_stream(
{
struct mwifiex_private *priv;
u8 i;
- u32 ba_stream_num = 0, ba_stream_max;
+ size_t ba_stream_num = 0, ba_stream_max;
ba_stream_max = MWIFIEX_MAX_TX_BASTREAM_SUPPORTED;
for (i = 0; i < adapter->priv_num; i++) {
priv = adapter->priv[i];
if (priv)
- ba_stream_num += mwifiex_wmm_list_len(
+ ba_stream_num += list_count_nodes(
&priv->tx_ba_stream_tbl_ptr);
}
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index bcd564dc3554..813d1cbebe19 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -3127,7 +3127,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC%s",
WQ_HIGHPRI |
WQ_MEM_RECLAIM |
- WQ_UNBOUND, 1, name);
+ WQ_UNBOUND, 0, name);
if (!priv->dfs_cac_workqueue) {
mwifiex_dbg(adapter, ERROR, "cannot alloc DFS CAC queue\n");
ret = -ENOMEM;
@@ -3138,7 +3138,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
priv->dfs_chan_sw_workqueue = alloc_workqueue("MWIFIEX_DFS_CHSW%s",
WQ_HIGHPRI | WQ_UNBOUND |
- WQ_MEM_RECLAIM, 1, name);
+ WQ_MEM_RECLAIM, 0, name);
if (!priv->dfs_chan_sw_workqueue) {
mwifiex_dbg(adapter, ERROR, "cannot alloc DFS channel sw queue\n");
ret = -ENOMEM;
@@ -3753,10 +3753,10 @@ static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy,
*/
static int
mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
- const u8 *peer, u8 action_code, u8 dialog_token,
- u16 status_code, u32 peer_capability,
- bool initiator, const u8 *extra_ies,
- size_t extra_ies_len)
+ const u8 *peer, int link_id, u8 action_code,
+ u8 dialog_token, u16 status_code,
+ u32 peer_capability, bool initiator,
+ const u8 *extra_ies, size_t extra_ies_len)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
int ret;
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index ea22a08e6c08..1cd9d20cca16 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1547,7 +1547,7 @@ mwifiex_reinit_sw(struct mwifiex_adapter *adapter)
adapter->workqueue =
alloc_workqueue("MWIFIEX_WORK_QUEUE",
- WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+ WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 0);
if (!adapter->workqueue)
goto err_kmalloc;
@@ -1557,7 +1557,7 @@ mwifiex_reinit_sw(struct mwifiex_adapter *adapter)
adapter->rx_workqueue = alloc_workqueue("MWIFIEX_RX_WORK_QUEUE",
WQ_HIGHPRI |
WQ_MEM_RECLAIM |
- WQ_UNBOUND, 1);
+ WQ_UNBOUND, 0);
if (!adapter->rx_workqueue)
goto err_kmalloc;
INIT_WORK(&adapter->rx_work, mwifiex_rx_work_queue);
@@ -1702,7 +1702,7 @@ mwifiex_add_card(void *card, struct completion *fw_done,
adapter->workqueue =
alloc_workqueue("MWIFIEX_WORK_QUEUE",
- WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+ WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 0);
if (!adapter->workqueue)
goto err_kmalloc;
@@ -1712,7 +1712,7 @@ mwifiex_add_card(void *card, struct completion *fw_done,
adapter->rx_workqueue = alloc_workqueue("MWIFIEX_RX_WORK_QUEUE",
WQ_HIGHPRI |
WQ_MEM_RECLAIM |
- WQ_UNBOUND, 1);
+ WQ_UNBOUND, 0);
if (!adapter->rx_workqueue)
goto err_kmalloc;
diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c
index ac8001c84293..644b1e134b01 100644
--- a/drivers/net/wireless/marvell/mwifiex/scan.c
+++ b/drivers/net/wireless/marvell/mwifiex/scan.c
@@ -2187,9 +2187,9 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
if (nd_config) {
adapter->nd_info =
- kzalloc(sizeof(struct cfg80211_wowlan_nd_match) +
- sizeof(struct cfg80211_wowlan_nd_match *) *
- scan_rsp->number_of_sets, GFP_ATOMIC);
+ kzalloc(struct_size(adapter->nd_info, matches,
+ scan_rsp->number_of_sets),
+ GFP_ATOMIC);
if (adapter->nd_info)
adapter->nd_info->n_matches = scan_rsp->number_of_sets;
diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.h b/drivers/net/wireless/marvell/mwifiex/wmm.h
index 4f53a271dae0..d7659e688933 100644
--- a/drivers/net/wireless/marvell/mwifiex/wmm.h
+++ b/drivers/net/wireless/marvell/mwifiex/wmm.h
@@ -39,21 +39,6 @@ mwifiex_get_tid(struct mwifiex_ra_list_tbl *ptr)
}
/*
- * This function gets the length of a list.
- */
-static inline int
-mwifiex_wmm_list_len(struct list_head *head)
-{
- struct list_head *pos;
- int count = 0;
-
- list_for_each(pos, head)
- ++count;
-
- return count;
-}
-
-/*
* This function checks if a RA list is empty or not.
*/
static inline u8
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
index 68e88224b8b1..ccedea7e8a50 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
@@ -128,12 +128,12 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)
case MT_EE_5GHZ:
dev->mphy.cap.has_5ghz = true;
break;
- case MT_EE_2GHZ:
- dev->mphy.cap.has_2ghz = true;
- break;
case MT_EE_DBDC:
dev->dbdc_support = true;
fallthrough;
+ case MT_EE_2GHZ:
+ dev->mphy.cap.has_2ghz = true;
+ break;
default:
dev->mphy.cap.has_2ghz = true;
dev->mphy.cap.has_5ghz = true;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
index f0a80c2b476a..4153cd6c2a01 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
@@ -231,10 +231,6 @@ int mt7921_dma_init(struct mt7921_dev *dev)
if (ret)
return ret;
- ret = mt7921_wfsys_reset(dev);
- if (ret)
- return ret;
-
/* init tx queue */
ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7921_TXQ_BAND0,
MT7921_TX_RING_SIZE,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index c69ce6df4956..f55caa00ac69 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -476,12 +476,6 @@ static int mt7921_load_firmware(struct mt7921_dev *dev)
{
int ret;
- ret = mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY);
- if (ret && mt76_is_mmio(&dev->mt76)) {
- dev_dbg(dev->mt76.dev, "Firmware is already download\n");
- goto fw_loaded;
- }
-
ret = mt76_connac2_load_patch(&dev->mt76, mt7921_patch_name(dev));
if (ret)
return ret;
@@ -504,8 +498,6 @@ static int mt7921_load_firmware(struct mt7921_dev *dev)
return -EIO;
}
-fw_loaded:
-
#ifdef CONFIG_PM
dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support;
#endif /* CONFIG_PM */
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
index ddb1fa4ee01d..95610a117d2f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
@@ -325,6 +325,10 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
bus_ops->rmw = mt7921_rmw;
dev->mt76.bus = bus_ops;
+ ret = mt7921e_mcu_fw_pmctrl(dev);
+ if (ret)
+ goto err_free_dev;
+
ret = __mt7921e_mcu_drv_pmctrl(dev);
if (ret)
goto err_free_dev;
@@ -333,6 +337,10 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
(mt7921_l1_rr(dev, MT_HW_REV) & 0xff);
dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
+ ret = mt7921_wfsys_reset(dev);
+ if (ret)
+ goto err_free_dev;
+
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
diff --git a/drivers/net/wireless/mediatek/mt7601u/debugfs.c b/drivers/net/wireless/mediatek/mt7601u/debugfs.c
index 230b0e1061a7..dbddf256921b 100644
--- a/drivers/net/wireless/mediatek/mt7601u/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt7601u/debugfs.c
@@ -127,8 +127,6 @@ void mt7601u_init_debugfs(struct mt7601u_dev *dev)
struct dentry *dir;
dir = debugfs_create_dir("mt7601u", dev->hw->wiphy->debugfsdir);
- if (!dir)
- return;
debugfs_create_u8("temperature", 0400, dir, &dev->raw_temp);
debugfs_create_u32("temp_mode", 0400, dir, &dev->temp_mode);
diff --git a/drivers/net/wireless/mediatek/mt7601u/trace.h b/drivers/net/wireless/mediatek/mt7601u/trace.h
index 5a6ba015085f..07696b672161 100644
--- a/drivers/net/wireless/mediatek/mt7601u/trace.h
+++ b/drivers/net/wireless/mediatek/mt7601u/trace.h
@@ -16,7 +16,7 @@
#define MAXNAME 32
#define DEV_ENTRY __array(char, wiphy_name, 32)
-#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \
+#define DEV_ASSIGN strscpy(__entry->wiphy_name, \
wiphy_name(dev->hw->wiphy), MAXNAME)
#define DEV_PR_FMT "%s "
#define DEV_PR_ARG __entry->wiphy_name
diff --git a/drivers/net/wireless/microchip/wilc1000/hif.c b/drivers/net/wireless/microchip/wilc1000/hif.c
index 5adc69d5bcae..a28da5938481 100644
--- a/drivers/net/wireless/microchip/wilc1000/hif.c
+++ b/drivers/net/wireless/microchip/wilc1000/hif.c
@@ -485,6 +485,9 @@ void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
int rsn_ie_len = sizeof(struct element) + rsn_ie[1];
int offset = 8;
+ param->mode_802_11i = 2;
+ param->rsn_found = true;
+
/* extract RSN capabilities */
if (offset < rsn_ie_len) {
/* skip over pairwise suites */
@@ -494,11 +497,8 @@ void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
/* skip over authentication suites */
offset += (rsn_ie[offset] * 4) + 2;
- if (offset + 1 < rsn_ie_len) {
- param->mode_802_11i = 2;
- param->rsn_found = true;
+ if (offset + 1 < rsn_ie_len)
memcpy(param->rsn_cap, &rsn_ie[offset], 2);
- }
}
}
}
diff --git a/drivers/net/wireless/microchip/wilc1000/hif.h b/drivers/net/wireless/microchip/wilc1000/hif.h
index baa2881f4465..8e386db72e45 100644
--- a/drivers/net/wireless/microchip/wilc1000/hif.h
+++ b/drivers/net/wireless/microchip/wilc1000/hif.h
@@ -30,8 +30,6 @@ enum {
WILC_GET_CFG
};
-#define WILC_MAX_ASSOC_RESP_FRAME_SIZE 256
-
struct rf_info {
u8 link_speed;
s8 rssi;
diff --git a/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h b/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h
index 614c5673f232..7038b74f8e8f 100644
--- a/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h
+++ b/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h
@@ -30,7 +30,7 @@ struct wilc_cfg_str {
struct wilc_cfg_str_vals {
u8 mac_address[7];
u8 firmware_version[129];
- u8 assoc_rsp[256];
+ u8 assoc_rsp[WILC_MAX_ASSOC_RESP_FRAME_SIZE];
};
struct wilc_cfg {
diff --git a/drivers/net/wireless/microchip/wilc1000/wlan_if.h b/drivers/net/wireless/microchip/wilc1000/wlan_if.h
index df2f5a63bdf6..254a046e3b1b 100644
--- a/drivers/net/wireless/microchip/wilc1000/wlan_if.h
+++ b/drivers/net/wireless/microchip/wilc1000/wlan_if.h
@@ -10,6 +10,8 @@
#include <linux/netdevice.h>
#include "fw.h"
+#define WILC_MAX_ASSOC_RESP_FRAME_SIZE 512
+
/********************************************
*
* Wlan Configuration ID
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
index b052c96347d6..6cf7e7c997c2 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
@@ -192,7 +192,7 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
return;
/*
- * Frame was received successfully since non-succesfull
+ * Frame was received successfully since non-successful
* frames would have been dropped by the hardware.
*/
qual->rx_success++;
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/Kconfig b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig
index 82bcaf44a65f..44ad94757a03 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/Kconfig
+++ b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig
@@ -11,7 +11,8 @@ config RTL8XXXU
parts written to utilize the Linux mac80211 stack.
The driver is known to work with a number of RTL8723AU,
RL8188CU, RTL8188RU, RTL8191CU, RTL8192CU, RTL8723BU, RTL8192EU,
- RTL8188FU, RTL8188EU, and RTL8710BU (aka RTL8188GU) devices.
+ RTL8188FU, RTL8188EU, RTL8710BU (aka RTL8188GU), and RTL8192FU
+ devices.
This driver is under development and has a limited feature
set. In particular it does not yet support 40MHz channels
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/Makefile b/drivers/net/wireless/realtek/rtl8xxxu/Makefile
index 1bf083c15dcd..fa466589eccb 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/Makefile
+++ b/drivers/net/wireless/realtek/rtl8xxxu/Makefile
@@ -3,4 +3,4 @@ obj-$(CONFIG_RTL8XXXU) += rtl8xxxu.o
rtl8xxxu-y := rtl8xxxu_core.o rtl8xxxu_8192e.o rtl8xxxu_8723b.o \
rtl8xxxu_8723a.o rtl8xxxu_8192c.o rtl8xxxu_8188f.o \
- rtl8xxxu_8188e.o rtl8xxxu_8710b.o
+ rtl8xxxu_8188e.o rtl8xxxu_8710b.o rtl8xxxu_8192f.o
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
index 808c1c895113..4695fb4e2d2d 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
@@ -39,6 +39,7 @@
#define TX_TOTAL_PAGE_NUM_8188E 0xa9
#define TX_TOTAL_PAGE_NUM_8192E 0xf3
#define TX_TOTAL_PAGE_NUM_8723B 0xf7
+#define TX_TOTAL_PAGE_NUM_8192F 0xf7
/* (HPQ + LPQ + NPQ + PUBQ) = TX_TOTAL_PAGE_NUM */
#define TX_PAGE_NUM_PUBQ 0xe7
#define TX_PAGE_NUM_HI_PQ 0x0c
@@ -65,6 +66,11 @@
#define TX_PAGE_NUM_LO_PQ_8723B 0x02
#define TX_PAGE_NUM_NORM_PQ_8723B 0x02
+#define TX_PAGE_NUM_PUBQ_8192F 0xde
+#define TX_PAGE_NUM_HI_PQ_8192F 0x08
+#define TX_PAGE_NUM_LO_PQ_8192F 0x08
+#define TX_PAGE_NUM_NORM_PQ_8192F 0x08
+
#define RTL_FW_PAGE_SIZE 4096
#define RTL8XXXU_FIRMWARE_POLL_MAX 1000
@@ -81,6 +87,7 @@
#define EFUSE_REAL_CONTENT_LEN_8723A 512
#define EFUSE_BT_MAP_LEN_8723A 1024
#define EFUSE_MAX_WORD_UNIT 4
+#define EFUSE_UNDEFINED 0xff
enum rtl8xxxu_rtl_chip {
RTL8192S = 0x81920,
@@ -105,6 +112,7 @@ enum rtl8xxxu_rtl_chip {
RTL8195A = 0x8195a,
RTL8188F = 0x8188f,
RTL8710B = 0x8710b,
+ RTL8192F = 0x8192f,
};
enum rtl8xxxu_rx_type {
@@ -1246,6 +1254,40 @@ struct rtl8710bu_efuse {
u8 res7[0x3c];
} __packed;
+struct rtl8192fu_efuse {
+ __le16 rtl_id;
+ u8 res0[0x0e];
+ struct rtl8192eu_efuse_tx_power tx_power_index_A; /* 0x10 */
+ struct rtl8192eu_efuse_tx_power tx_power_index_B; /* 0x3a */
+ u8 res2[0x54];
+ u8 channel_plan; /* 0xb8 */
+ u8 xtal_k; /* 0xb9 */
+ u8 thermal_meter; /* 0xba */
+ u8 iqk_lck; /* 0xbb */
+ u8 pa_type; /* 0xbc */
+ u8 lna_type_2g; /* 0xbd */
+ u8 res3[1];
+ u8 lna_type_5g; /* 0xbf */
+ u8 res4[1];
+ u8 rf_board_option; /* 0xc1 */
+ u8 rf_feature_option; /* 0xc2 */
+ u8 rf_bt_setting; /* 0xc3 */
+ u8 eeprom_version; /* 0xc4 */
+ u8 eeprom_customer_id; /* 0xc5 */
+ u8 res5[3];
+ u8 rf_antenna_option; /* 0xc9 */
+ u8 rfe_option; /* 0xca */
+ u8 country_code; /* 0xcb */
+ u8 res6[52];
+ u8 vid[2]; /* 0x100 */
+ u8 pid[2]; /* 0x102 */
+ u8 usb_optional_function; /* 0x104 */
+ u8 res7[2];
+ u8 mac_addr[ETH_ALEN]; /* 0x107 */
+ u8 device_info[80]; /* 0x10d */
+ u8 res9[163];
+} __packed;
+
struct rtl8xxxu_reg8val {
u16 reg;
u8 val;
@@ -1280,6 +1322,9 @@ struct rtl8xxxu_rfregs {
#define H2C_JOIN_BSS_DISCONNECT 0
#define H2C_JOIN_BSS_CONNECT 1
+#define H2C_MACID_ROLE_STA 1
+#define H2C_MACID_ROLE_AP 2
+
/*
* H2C (firmware) commands differ between the older generation chips
* 8188[cr]u, 819[12]cu, and 8723au, and the more recent chips 8723bu,
@@ -1727,6 +1772,8 @@ struct rtl8xxxu_cfo_tracking {
};
#define RTL8XXXU_HW_LED_CONTROL 2
+#define RTL8XXXU_MAX_MAC_ID_NUM 128
+#define RTL8XXXU_BC_MC_MACID 0
struct rtl8xxxu_priv {
struct ieee80211_hw *hw;
@@ -1791,6 +1838,7 @@ struct rtl8xxxu_priv {
u32 cck_agc_report_type:1;
u32 cck_new_agc:1;
u8 default_crystal_cap;
+ u8 rfe_type;
unsigned int pipe_interrupt;
unsigned int pipe_in;
unsigned int pipe_out[TXDESC_QUEUE_MAX];
@@ -1831,6 +1879,7 @@ struct rtl8xxxu_priv {
struct rtl8188fu_efuse efuse8188fu;
struct rtl8188eu_efuse efuse8188eu;
struct rtl8710bu_efuse efuse8710bu;
+ struct rtl8192fu_efuse efuse8192fu;
} efuse_wifi;
u32 adda_backup[RTL8XXXU_ADDA_REGS];
u32 mac_backup[RTL8XXXU_MAC_REGS];
@@ -1851,6 +1900,7 @@ struct rtl8xxxu_priv {
struct delayed_work ra_watchdog;
struct work_struct c2hcmd_work;
struct sk_buff_head c2hcmd_queue;
+ struct work_struct update_beacon_work;
struct rtl8xxxu_btcoex bt_coex;
struct rtl8xxxu_ra_report ra_report;
struct rtl8xxxu_cfo_tracking cfo_tracking;
@@ -1859,6 +1909,14 @@ struct rtl8xxxu_priv {
bool led_registered;
char led_name[32];
struct led_classdev led_cdev;
+ DECLARE_BITMAP(mac_id_map, RTL8XXXU_MAX_MAC_ID_NUM);
+};
+
+struct rtl8xxxu_sta_info {
+ struct ieee80211_sta *sta;
+ struct ieee80211_vif *vif;
+
+ u8 macid;
};
struct rtl8xxxu_rx_urb {
@@ -1903,15 +1961,16 @@ struct rtl8xxxu_fileops {
void (*set_tx_power) (struct rtl8xxxu_priv *priv, int channel,
bool ht40);
void (*update_rate_mask) (struct rtl8xxxu_priv *priv,
- u32 ramask, u8 rateid, int sgi, int txbw_40mhz);
+ u32 ramask, u8 rateid, int sgi, int txbw_40mhz,
+ u8 macid);
void (*report_connect) (struct rtl8xxxu_priv *priv,
- u8 macid, bool connect);
+ u8 macid, u8 role, bool connect);
void (*report_rssi) (struct rtl8xxxu_priv *priv, u8 macid, u8 rssi);
void (*fill_txdesc) (struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *tx_info,
struct rtl8xxxu_txdesc32 *tx_desc, bool sgi,
bool short_preamble, bool ampdu_enable,
- u32 rts_rate);
+ u32 rts_rate, u8 macid);
void (*set_crystal_cap) (struct rtl8xxxu_priv *priv, u8 crystal_cap);
s8 (*cck_rssi) (struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats);
int (*led_classdev_brightness_set) (struct led_classdev *led_cdev,
@@ -1929,6 +1988,9 @@ struct rtl8xxxu_fileops {
u8 init_reg_hmtfr:1;
u8 ampdu_max_time;
u8 ustime_tsf_edca;
+ u16 max_aggr_num;
+ u8 supports_ap:1;
+ u16 max_macid_num;
u32 adda_1t_init;
u32 adda_1t_path_on;
u32 adda_2t_path_on_a;
@@ -2015,6 +2077,7 @@ void rtl8xxxu_gen1_phy_iq_calibrate(struct rtl8xxxu_priv *priv);
void rtl8xxxu_gen1_init_phy_bb(struct rtl8xxxu_priv *priv);
void rtl8xxxu_gen1_set_tx_power(struct rtl8xxxu_priv *priv,
int channel, bool ht40);
+void rtl8188f_channel_to_group(int channel, int *group, int *cck_group);
void rtl8188f_set_tx_power(struct rtl8xxxu_priv *priv,
int channel, bool ht40);
void rtl8xxxu_gen1_config_channel(struct ieee80211_hw *hw);
@@ -2022,13 +2085,13 @@ void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw);
void rtl8xxxu_gen1_usb_quirks(struct rtl8xxxu_priv *priv);
void rtl8xxxu_gen2_usb_quirks(struct rtl8xxxu_priv *priv);
void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv,
- u32 ramask, u8 rateid, int sgi, int txbw_40mhz);
+ u32 ramask, u8 rateid, int sgi, int txbw_40mhz, u8 macid);
void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv,
- u32 ramask, u8 rateid, int sgi, int txbw_40mhz);
+ u32 ramask, u8 rateid, int sgi, int txbw_40mhz, u8 macid);
void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv,
- u8 macid, bool connect);
+ u8 macid, u8 role, bool connect);
void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv,
- u8 macid, bool connect);
+ u8 macid, u8 role, bool connect);
void rtl8xxxu_gen1_report_rssi(struct rtl8xxxu_priv *priv, u8 macid, u8 rssi);
void rtl8xxxu_gen2_report_rssi(struct rtl8xxxu_priv *priv, u8 macid, u8 rssi);
void rtl8xxxu_gen1_init_aggregation(struct rtl8xxxu_priv *priv);
@@ -2057,17 +2120,17 @@ void rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *tx_info,
struct rtl8xxxu_txdesc32 *tx_desc, bool sgi,
bool short_preamble, bool ampdu_enable,
- u32 rts_rate);
+ u32 rts_rate, u8 macid);
void rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *tx_info,
struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi,
bool short_preamble, bool ampdu_enable,
- u32 rts_rate);
+ u32 rts_rate, u8 macid);
void rtl8xxxu_fill_txdesc_v3(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *tx_info,
struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi,
bool short_preamble, bool ampdu_enable,
- u32 rts_rate);
+ u32 rts_rate, u8 macid);
void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv,
u8 arg1, u8 arg2, u8 arg3, u8 arg4, u8 arg5);
void rtl8723bu_phy_init_antenna_selection(struct rtl8xxxu_priv *priv);
@@ -2079,6 +2142,7 @@ void rtl8xxxu_update_ra_report(struct rtl8xxxu_ra_report *rarpt,
void rtl8188e_ra_info_init_all(struct rtl8xxxu_ra_info *ra);
void rtl8188e_handle_ra_tx_report2(struct rtl8xxxu_priv *priv, struct sk_buff *skb);
+extern struct rtl8xxxu_fileops rtl8192fu_fops;
extern struct rtl8xxxu_fileops rtl8710bu_fops;
extern struct rtl8xxxu_fileops rtl8188fu_fops;
extern struct rtl8xxxu_fileops rtl8188eu_fops;
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c
index 8986783ae8fa..6d0f975f891b 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c
@@ -1794,7 +1794,8 @@ static void rtl8188e_arfb_refresh(struct rtl8xxxu_ra_info *ra)
static void
rtl8188e_update_rate_mask(struct rtl8xxxu_priv *priv,
- u32 ramask, u8 rateid, int sgi, int txbw_40mhz)
+ u32 ramask, u8 rateid, int sgi, int txbw_40mhz,
+ u8 macid)
{
struct rtl8xxxu_ra_info *ra = &priv->ra_info;
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
index dbdfd7787465..1e1c8fa194cb 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
@@ -351,7 +351,7 @@ out:
return ret;
}
-static void rtl8188f_channel_to_group(int channel, int *group, int *cck_group)
+void rtl8188f_channel_to_group(int channel, int *group, int *cck_group)
{
if (channel < 3)
*group = 0;
@@ -654,7 +654,7 @@ static void rtl8188fu_config_channel(struct ieee80211_hw *hw)
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RX_BB2, val32);
/* RC Corner */
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00140);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00140);
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RX_G2, 0x01c6c);
}
@@ -854,8 +854,8 @@ static int rtl8188fu_iqk_path_a(struct rtl8xxxu_priv *priv, u32 *lok_result)
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0x07ff7);
/* PA,PAD gain adjust */
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x980);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x5102a);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x980);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x5102a);
/* enter IQK mode */
val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
@@ -886,7 +886,7 @@ static int rtl8188fu_iqk_path_a(struct rtl8xxxu_priv *priv, u32 *lok_result)
val32 &= 0x000000ff;
rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180);
/* save LOK result */
*lok_result = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC);
@@ -927,8 +927,8 @@ static int rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result)
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf1173);
/* PA,PAD gain adjust */
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x980);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x5102a);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x980);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x5102a);
/*
* Enter IQK mode
@@ -967,7 +967,7 @@ static int rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result)
val32 &= 0x000000ff;
rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180);
/* Check failed */
reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
@@ -1002,8 +1002,8 @@ static int rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result)
/*
* PA, PAD setting
*/
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x980);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x51000);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x980);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x51000);
/*
* Enter IQK mode
@@ -1041,7 +1041,7 @@ static int rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result)
val32 &= 0x000000ff;
rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180);
/* reload LOK value */
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC, lok_result);
@@ -1748,6 +1748,9 @@ struct rtl8xxxu_fileops rtl8188fu_fops = {
.init_reg_hmtfr = 1,
.ampdu_max_time = 0x70,
.ustime_tsf_edca = 0x28,
+ .max_aggr_num = 0x0c14,
+ .supports_ap = 1,
+ .max_macid_num = 16,
.adda_1t_init = 0x03c00014,
.adda_1t_path_on = 0x03c00014,
.trxff_boundary = 0x3f7f,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
index fcc2926ea938..f673aa9ba15a 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
@@ -716,7 +716,7 @@ static int rtl8192eu_iqk_path_a(struct rtl8xxxu_priv *priv)
* PA/PAD controlled by 0x0
*/
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00180);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00180);
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0);
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x20000);
@@ -776,8 +776,8 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf1173);
/* PA/PAD control by 0x56, and set = 0x0 */
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00980);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x511e0);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00980);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x511e0);
/* Enter IQK mode */
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
@@ -816,7 +816,7 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
} else {
/* PA/PAD controlled by 0x0 */
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180);
goto out;
}
@@ -838,8 +838,8 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf7ff2);
/* PA/PAD control by 0x56, and set = 0x0 */
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00980);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x510e0);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00980);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x510e0);
/* Enter IQK mode */
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
@@ -869,7 +869,7 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2);
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180);
if (!(reg_eac & BIT(27)) &&
((reg_ea4 & 0x03ff0000) != 0x01320000) &&
@@ -889,7 +889,7 @@ static int rtl8192eu_iqk_path_b(struct rtl8xxxu_priv *priv)
int result = 0;
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
- rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00180);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00180);
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0);
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x20000);
@@ -952,8 +952,8 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv)
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf1173);
/* PA/PAD control by 0x56, and set = 0x0 */
- rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00980);
- rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x511e0);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00980);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_PAD_TXG, 0x511e0);
/* Enter IQK mode */
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
@@ -995,7 +995,7 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv)
* Vendor driver restores RF_A here which I believe is a bug
*/
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
- rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x180);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x180);
goto out;
}
@@ -1017,8 +1017,8 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv)
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf7ff2);
/* PA/PAD control by 0x56, and set = 0x0 */
- rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00980);
- rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x510e0);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00980);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_PAD_TXG, 0x510e0);
/* Enter IQK mode */
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
@@ -1049,7 +1049,7 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv)
reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2);
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
- rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x180);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x180);
if (!(reg_eac & BIT(30)) &&
((reg_ec4 & 0x03ff0000) != 0x01320000) &&
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c
new file mode 100644
index 000000000000..18dc5221a9c0
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c
@@ -0,0 +1,2090 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * RTL8XXXU mac80211 USB driver - 8192fu specific subdriver
+ *
+ * Copyright (c) 2023 Bitterblue Smith <rtl8821cerfe2@gmail.com>
+ *
+ * Portions copied from existing rtl8xxxu code:
+ * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com>
+ *
+ * Portions, notably calibration code:
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/usb.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/wireless.h>
+#include <linux/firmware.h>
+#include <linux/moduleparam.h>
+#include <net/mac80211.h>
+#include "rtl8xxxu.h"
+#include "rtl8xxxu_regs.h"
+
+static const struct rtl8xxxu_reg8val rtl8192f_mac_init_table[] = {
+ {0x420, 0x00}, {0x422, 0x78}, {0x428, 0x0a}, {0x429, 0x10},
+ {0x430, 0x00}, {0x431, 0x00}, {0x432, 0x00}, {0x433, 0x01},
+ {0x434, 0x04}, {0x435, 0x05}, {0x436, 0x07}, {0x437, 0x08},
+ {0x43c, 0x04}, {0x43d, 0x05}, {0x43e, 0x07}, {0x43f, 0x08},
+ {0x440, 0x5d}, {0x441, 0x01}, {0x442, 0x00}, {0x444, 0x10},
+ {0x445, 0xf0}, {0x446, 0x0e}, {0x447, 0x1f}, {0x448, 0x00},
+ {0x449, 0x00}, {0x44a, 0x00}, {0x44b, 0x00}, {0x44c, 0x10},
+ {0x44d, 0xf0}, {0x44e, 0x0e}, {0x44f, 0x00}, {0x450, 0x00},
+ {0x451, 0x00}, {0x452, 0x00}, {0x453, 0x00}, {0x480, 0x20},
+ {0x49c, 0x30}, {0x49d, 0xf0}, {0x49e, 0x03}, {0x49f, 0x3e},
+ {0x4a0, 0x00}, {0x4a1, 0x00}, {0x4a2, 0x00}, {0x4a3, 0x00},
+ {0x4a4, 0x15}, {0x4a5, 0xf0}, {0x4a6, 0x01}, {0x4a7, 0x0e},
+ {0x4a8, 0xe0}, {0x4a9, 0x00}, {0x4aa, 0x00}, {0x4ab, 0x00},
+ {0x2448, 0x06}, {0x244a, 0x06}, {0x244c, 0x06}, {0x244e, 0x06},
+ {0x4c7, 0x80}, {0x4c8, 0xff}, {0x4c9, 0x08}, {0x4ca, 0x3c},
+ {0x4cb, 0x3c}, {0x4cc, 0xff}, {0x4cd, 0xff}, {0x4ce, 0x01},
+ {0x500, 0x26}, {0x501, 0xa2}, {0x502, 0x2f}, {0x503, 0x00},
+ {0x504, 0x28}, {0x505, 0xa3}, {0x506, 0x5e}, {0x507, 0x00},
+ {0x508, 0x2b}, {0x509, 0xa4}, {0x50a, 0x5e}, {0x50b, 0x00},
+ {0x50c, 0x4f}, {0x50d, 0xa4}, {0x50e, 0x00}, {0x50f, 0x00},
+ {0x512, 0x1c}, {0x514, 0x0a}, {0x516, 0x0a}, {0x521, 0x2f},
+ {0x525, 0x0f}, {0x550, 0x10}, {0x551, 0x10}, {0x559, 0x02},
+ {0x55c, 0x50}, {0x55d, 0xff}, {0x605, 0x30}, {0x608, 0x0e},
+ {0x609, 0x2a}, {0x60c, 0x18}, {0x620, 0xff}, {0x621, 0xff},
+ {0x622, 0xff}, {0x623, 0xff}, {0x624, 0xff}, {0x625, 0xff},
+ {0x626, 0xff}, {0x627, 0xff}, {0x638, 0x50}, {0x63c, 0x0a},
+ {0x63d, 0x0a}, {0x63e, 0x0e}, {0x63f, 0x0e}, {0x640, 0x40},
+ {0x642, 0x40}, {0x643, 0x00}, {0x652, 0xc8}, {0x66e, 0x05},
+ {0x6a0, 0xff}, {0x6a1, 0xff}, {0x6a2, 0xff}, {0x6a3, 0xff},
+ {0x6a4, 0xff}, {0x6a5, 0xff}, {0x6de, 0x84}, {0x700, 0x21},
+ {0x701, 0x43}, {0x702, 0x65}, {0x703, 0x87}, {0x708, 0x21},
+ {0x709, 0x43}, {0x70a, 0x65}, {0x70b, 0x87}, {0x718, 0x40},
+ {0x7c0, 0x38}, {0x7c2, 0x0f}, {0x7c3, 0xc0}, {0x073, 0x04},
+ {0x7c4, 0x77}, {0x024, 0xc7}, {0x7ec, 0xff}, {0x7ed, 0xff},
+ {0x7ee, 0xff}, {0x7ef, 0xff},
+ {0xffff, 0xff},
+};
+
+/* If updating the phy init table, also update rtl8192f_revise_cck_tx_psf(). */
+static const struct rtl8xxxu_reg32val rtl8192fu_phy_init_table[] = {
+ {0x800, 0x80006C00}, {0x804, 0x00004001},
+ {0x808, 0x0000FC00}, {0x80C, 0x00000000},
+ {0x810, 0x20200322}, {0x814, 0x020C3910},
+ {0x818, 0x00000385}, {0x81C, 0x07000000},
+ {0x820, 0x01000100}, {0x824, 0x00390204},
+ {0x828, 0x01000100}, {0x82C, 0x00390204},
+ {0x830, 0x25252525}, {0x834, 0x25252525},
+ {0x838, 0x25252525}, {0x83C, 0x25252525},
+ {0x840, 0x00010000}, {0x844, 0x00010000},
+ {0x848, 0x25252525}, {0x84C, 0x25252525},
+ {0x850, 0x00031FE0}, {0x854, 0x00000000},
+ {0x858, 0x569A569A}, {0x85C, 0x00400040},
+ {0x860, 0x66F60000}, {0x864, 0x061F0000},
+ {0x868, 0x25252525}, {0x86C, 0x25252525},
+ {0x870, 0x00000300}, {0x874, 0x04003400},
+ {0x878, 0x08080808}, {0x87C, 0x004F0201},
+ {0x880, 0xD8001402}, {0x884, 0xC0000120},
+ {0x888, 0x00000000}, {0x88C, 0xCC0000C0},
+ {0x890, 0x00000000}, {0x894, 0xFFFFFFFE},
+ {0x898, 0x40302010}, {0x89C, 0x00706050},
+ {0x900, 0x00000000}, {0x904, 0x00000023},
+ {0x908, 0x00000F00}, {0x90C, 0x81121313},
+ {0x910, 0x024C0000}, {0x914, 0x00000000},
+ {0x918, 0x00000000}, {0x91C, 0x00000000},
+ {0x920, 0x00000000}, {0x924, 0x00000000},
+ {0x928, 0x00000000}, {0x92C, 0x00000000},
+ {0x930, 0x88000000}, {0x934, 0x00000245},
+ {0x938, 0x00024588}, {0x93C, 0x00000000},
+ {0x940, 0x000007FF}, {0x944, 0x3F3F0000},
+ {0x948, 0x000001A3}, {0x94C, 0x20200008},
+ {0x950, 0x00338A98}, {0x954, 0x00000000},
+ {0x958, 0xCBCAD87A}, {0x95C, 0x06EB5735},
+ {0x960, 0x00000000}, {0x964, 0x00000000},
+ {0x968, 0x00000000}, {0x96C, 0x00000003},
+ {0x970, 0x00000000}, {0x974, 0x00000000},
+ {0x978, 0x00000000}, {0x97C, 0x10030000},
+ {0x980, 0x00000000}, {0x984, 0x02800280},
+ {0x988, 0x020A5704}, {0x98C, 0x1461C826},
+ {0x990, 0x0001469E}, {0x994, 0x008858D1},
+ {0x998, 0x400086C9}, {0x99C, 0x44444242},
+ {0x9A0, 0x00000000}, {0x9A4, 0x00000000},
+ {0x9A8, 0x00000000}, {0x9AC, 0xC0000000},
+ {0xA00, 0x00D047C8}, {0xA04, 0xC1FF0008},
+ {0xA08, 0x88838300}, {0xA0C, 0x2E20100F},
+ {0xA10, 0x9500BB78}, {0xA14, 0x11144028},
+ {0xA18, 0x00881117}, {0xA1C, 0x89140F00},
+ {0xA20, 0xE82C0001}, {0xA24, 0x64B80C1C},
+ {0xA28, 0x00158810}, {0xA2C, 0x10BB8000},
+ {0xA70, 0x00008000}, {0xA74, 0x80800100},
+ {0xA78, 0x000089F0}, {0xA7C, 0x225B0606},
+ {0xA80, 0x20803210}, {0xA84, 0x00200200},
+ {0xA88, 0x00000000}, {0xA8C, 0x00000000},
+ {0xA90, 0x00000000}, {0xA94, 0x00000000},
+ {0xA98, 0x00000000}, {0xA9C, 0x00460000},
+ {0xAA0, 0x00000000}, {0xAA4, 0x00020014},
+ {0xAA8, 0xBA0A0008}, {0xAAC, 0x01235667},
+ {0xAB0, 0x00000000}, {0xAB4, 0x00201402},
+ {0xAB8, 0x0000001C}, {0xABC, 0x0000F7FF},
+ {0xAC0, 0xD4C0A742}, {0xAC4, 0x00000000},
+ {0xAC8, 0x00000F08}, {0xACC, 0x00000F07},
+ {0xAD0, 0xA1052A10}, {0xAD4, 0x0D9D8452},
+ {0xAD8, 0x9E024024}, {0xADC, 0x0023C001},
+ {0xAE0, 0x00000391}, {0xB2C, 0x00000000},
+ {0xC00, 0x00000080}, {0xC04, 0x6F005433},
+ {0xC08, 0x000004E4}, {0xC0C, 0x6C6C6C6C},
+ {0xC10, 0x22000000}, {0xC14, 0x40000100},
+ {0xC18, 0x22000000}, {0xC1C, 0x40000100},
+ {0xC20, 0x00000000}, {0xC24, 0x40000100},
+ {0xC28, 0x00000000}, {0xC2C, 0x40000100},
+ {0xC30, 0x0401E809}, {0xC34, 0x30000020},
+ {0xC38, 0x23808080}, {0xC3C, 0x00002F44},
+ {0xC40, 0x1CF8403F}, {0xC44, 0x000100C7},
+ {0xC48, 0xEC060106}, {0xC4C, 0x007F037F},
+ {0xC50, 0x00E48020}, {0xC54, 0x04008017},
+ {0xC58, 0x00000020}, {0xC5C, 0x00708492},
+ {0xC60, 0x09280200}, {0xC64, 0x5014838B},
+ {0xC68, 0x47C006C7}, {0xC6C, 0x00000035},
+ {0xC70, 0x00001007}, {0xC74, 0x02815269},
+ {0xC78, 0x0FE07F1F}, {0xC7C, 0x00B91612},
+ {0xC80, 0x40000100}, {0xC84, 0x32000000},
+ {0xC88, 0x40000100}, {0xC8C, 0xA0240000},
+ {0xC90, 0x400E161E}, {0xC94, 0x00000F00},
+ {0xC98, 0x400E161E}, {0xC9C, 0x0000BDC8},
+ {0xCA0, 0x00000000}, {0xCA4, 0x098300A0},
+ {0xCA8, 0x00006B00}, {0xCAC, 0x87F45B1A},
+ {0xCB0, 0x0000002D}, {0xCB4, 0x00000000},
+ {0xCB8, 0x00000000}, {0xCBC, 0x28100200},
+ {0xCC0, 0x0010A3D0}, {0xCC4, 0x00000F7D},
+ {0xCC8, 0x00000000}, {0xCCC, 0x00000000},
+ {0xCD0, 0x593659AD}, {0xCD4, 0xB7545121},
+ {0xCD8, 0x64B22427}, {0xCDC, 0x00766932},
+ {0xCE0, 0x40201000}, {0xCE4, 0x00000000},
+ {0xCE8, 0x40E04407}, {0xCEC, 0x2E572000},
+ {0xD00, 0x000D8780}, {0xD04, 0x40020403},
+ {0xD08, 0x0002907F}, {0xD0C, 0x20010201},
+ {0xD10, 0x06288888}, {0xD14, 0x8888367B},
+ {0xD18, 0x7D806DB3}, {0xD1C, 0x0000007F},
+ {0xD20, 0x567600B8}, {0xD24, 0x0000018B},
+ {0xD28, 0xD513FF7D}, {0xD2C, 0xCC979975},
+ {0xD30, 0x04928000}, {0xD34, 0x40608000},
+ {0xD38, 0x88DDA000}, {0xD3C, 0x00026EE2},
+ {0xD50, 0x67270001}, {0xD54, 0x20500000},
+ {0xD58, 0x16161616}, {0xD5C, 0x71F20064},
+ {0xD60, 0x4653DA60}, {0xD64, 0x3E718A3C},
+ {0xD68, 0x00000183}, {0xD7C, 0x00000000},
+ {0xD80, 0x50000000}, {0xD84, 0x31310400},
+ {0xD88, 0xF5B50000}, {0xD8C, 0x00000000},
+ {0xD90, 0x00000000}, {0xD94, 0x44BBBB44},
+ {0xD98, 0x44BB44FF}, {0xD9C, 0x06033688},
+ {0xE00, 0x25252525}, {0xE04, 0x25252525},
+ {0xE08, 0x25252525}, {0xE10, 0x25252525},
+ {0xE14, 0x25252525}, {0xE18, 0x25252525},
+ {0xE1C, 0x25252525}, {0xE20, 0x00000000},
+ {0xE24, 0x00200000}, {0xE28, 0x00000000},
+ {0xE2C, 0x00000000}, {0xE30, 0x01007C00},
+ {0xE34, 0x01004800}, {0xE38, 0x10008C0F},
+ {0xE3C, 0x3C008C0F}, {0xE40, 0x01007C00},
+ {0xE44, 0x00000000}, {0xE48, 0x00000000},
+ {0xE4C, 0x00000000}, {0xE50, 0x01007C00},
+ {0xE54, 0x01004800}, {0xE58, 0x10008C0F},
+ {0xE5C, 0x3C008C0F}, {0xE60, 0x02100000},
+ {0xE64, 0xBBBBBBBB}, {0xE68, 0x40404040},
+ {0xE6C, 0x80408040}, {0xE70, 0x80408040},
+ {0xE74, 0x40404040}, {0xE78, 0x00400040},
+ {0xE7C, 0x40404040}, {0xE80, 0x00FF0000},
+ {0xE84, 0x80408040}, {0xE88, 0x40404040},
+ {0xE8C, 0x80408040}, {0xED0, 0x80408040},
+ {0xED4, 0x80408040}, {0xED8, 0x80408040},
+ {0xEDC, 0xC040C040}, {0xEE0, 0xC040C040},
+ {0xEE4, 0x00400040}, {0xEE8, 0xD8001402},
+ {0xEEC, 0xC0000120}, {0xEF0, 0x02000B09},
+ {0xEF4, 0x00000001}, {0xEF8, 0x00000000},
+ {0xF00, 0x00000300}, {0xF04, 0x00000002},
+ {0xF08, 0x00007D0C}, {0xF0C, 0x0000A907},
+ {0xF10, 0x00005807}, {0xF14, 0x00000003},
+ {0xF18, 0x07D003E8}, {0xF1C, 0x8000001F},
+ {0xF20, 0x00000000}, {0xF24, 0x00000000},
+ {0xF28, 0x00000000}, {0xF2C, 0x00000000},
+ {0xF30, 0x00000000}, {0xF34, 0x00000000},
+ {0xF38, 0x00030055}, {0xF3C, 0x0000003A},
+ {0xF40, 0x00000002}, {0xF44, 0x00000000},
+ {0xF48, 0x00000000}, {0xF4C, 0x0B000000},
+ {0xF50, 0x00000000},
+ {0xffff, 0xffffffff},
+};
+
+static const struct rtl8xxxu_reg32val rtl8192f_agc_table[] = {
+ {0xC78, 0x0FA0001F}, {0xC78, 0x0FA0011F},
+ {0xC78, 0x0FA0021F}, {0xC78, 0x0FA0031F},
+ {0xC78, 0x0FA0041F}, {0xC78, 0x0FA0051F},
+ {0xC78, 0x0F90061F}, {0xC78, 0x0F80071F},
+ {0xC78, 0x0F70081F}, {0xC78, 0x0F60091F},
+ {0xC78, 0x0F500A1F}, {0xC78, 0x0F400B1F},
+ {0xC78, 0x0F300C1F}, {0xC78, 0x0F200D1F},
+ {0xC78, 0x0F100E1F}, {0xC78, 0x0F000F1F},
+ {0xC78, 0x0EF0101F}, {0xC78, 0x0EE0111F},
+ {0xC78, 0x0ED0121F}, {0xC78, 0x0EC0131F},
+ {0xC78, 0x0EB0141F}, {0xC78, 0x0EA0151F},
+ {0xC78, 0x0E90161F}, {0xC78, 0x0E80171F},
+ {0xC78, 0x0E70181F}, {0xC78, 0x0E60191F},
+ {0xC78, 0x0E501A1F}, {0xC78, 0x0E401B1F},
+ {0xC78, 0x0E301C1F}, {0xC78, 0x0C701D1F},
+ {0xC78, 0x0C601E1F}, {0xC78, 0x0C501F1F},
+ {0xC78, 0x0C40201F}, {0xC78, 0x0C30211F},
+ {0xC78, 0x0A60221F}, {0xC78, 0x0A50231F},
+ {0xC78, 0x0A40241F}, {0xC78, 0x0A30251F},
+ {0xC78, 0x0860261F}, {0xC78, 0x0850271F},
+ {0xC78, 0x0840281F}, {0xC78, 0x0830291F},
+ {0xC78, 0x06702A1F}, {0xC78, 0x06602B1F},
+ {0xC78, 0x06502C1F}, {0xC78, 0x06402D1F},
+ {0xC78, 0x06302E1F}, {0xC78, 0x04602F1F},
+ {0xC78, 0x0450301F}, {0xC78, 0x0440311F},
+ {0xC78, 0x0430321F}, {0xC78, 0x0260331F},
+ {0xC78, 0x0250341F}, {0xC78, 0x0240351F},
+ {0xC78, 0x0230361F}, {0xC78, 0x0050371F},
+ {0xC78, 0x0040381F}, {0xC78, 0x0030391F},
+ {0xC78, 0x00203A1F}, {0xC78, 0x00103B1F},
+ {0xC78, 0x00003C1F}, {0xC78, 0x00003D1F},
+ {0xC78, 0x00003E1F}, {0xC78, 0x00003F1F},
+
+ {0xC78, 0x0FA0401F}, {0xC78, 0x0FA0411F},
+ {0xC78, 0x0FA0421F}, {0xC78, 0x0FA0431F},
+ {0xC78, 0x0F90441F}, {0xC78, 0x0F80451F},
+ {0xC78, 0x0F70461F}, {0xC78, 0x0F60471F},
+ {0xC78, 0x0F50481F}, {0xC78, 0x0F40491F},
+ {0xC78, 0x0F304A1F}, {0xC78, 0x0F204B1F},
+ {0xC78, 0x0F104C1F}, {0xC78, 0x0F004D1F},
+ {0xC78, 0x0EF04E1F}, {0xC78, 0x0EE04F1F},
+ {0xC78, 0x0ED0501F}, {0xC78, 0x0EC0511F},
+ {0xC78, 0x0EB0521F}, {0xC78, 0x0EA0531F},
+ {0xC78, 0x0E90541F}, {0xC78, 0x0E80551F},
+ {0xC78, 0x0E70561F}, {0xC78, 0x0E60571F},
+ {0xC78, 0x0E50581F}, {0xC78, 0x0E40591F},
+ {0xC78, 0x0E305A1F}, {0xC78, 0x0E205B1F},
+ {0xC78, 0x0E105C1F}, {0xC78, 0x0C505D1F},
+ {0xC78, 0x0C405E1F}, {0xC78, 0x0C305F1F},
+ {0xC78, 0x0C20601F}, {0xC78, 0x0C10611F},
+ {0xC78, 0x0A40621F}, {0xC78, 0x0A30631F},
+ {0xC78, 0x0A20641F}, {0xC78, 0x0A10651F},
+ {0xC78, 0x0840661F}, {0xC78, 0x0830671F},
+ {0xC78, 0x0820681F}, {0xC78, 0x0810691F},
+ {0xC78, 0x06506A1F}, {0xC78, 0x06406B1F},
+ {0xC78, 0x06306C1F}, {0xC78, 0x06206D1F},
+ {0xC78, 0x06106E1F}, {0xC78, 0x04406F1F},
+ {0xC78, 0x0430701F}, {0xC78, 0x0420711F},
+ {0xC78, 0x0410721F}, {0xC78, 0x0240731F},
+ {0xC78, 0x0230741F}, {0xC78, 0x0220751F},
+ {0xC78, 0x0210761F}, {0xC78, 0x0030771F},
+ {0xC78, 0x0020781F}, {0xC78, 0x0010791F},
+ {0xC78, 0x00007A1F}, {0xC78, 0x00007B1F},
+ {0xC78, 0x00007C1F}, {0xC78, 0x00007D1F},
+ {0xC78, 0x00007E1F}, {0xC78, 0x00007F1F},
+
+ {0xC78, 0x0FA0801F}, {0xC78, 0x0FA0811F},
+ {0xC78, 0x0FA0821F}, {0xC78, 0x0FA0831F},
+ {0xC78, 0x0FA0841F}, {0xC78, 0x0FA0851F},
+ {0xC78, 0x0F90861F}, {0xC78, 0x0F80871F},
+ {0xC78, 0x0F70881F}, {0xC78, 0x0F60891F},
+ {0xC78, 0x0F508A1F}, {0xC78, 0x0F408B1F},
+ {0xC78, 0x0F308C1F}, {0xC78, 0x0F208D1F},
+ {0xC78, 0x0F108E1F}, {0xC78, 0x0B908F1F},
+ {0xC78, 0x0B80901F}, {0xC78, 0x0B70911F},
+ {0xC78, 0x0B60921F}, {0xC78, 0x0B50931F},
+ {0xC78, 0x0B40941F}, {0xC78, 0x0B30951F},
+ {0xC78, 0x0B20961F}, {0xC78, 0x0B10971F},
+ {0xC78, 0x0B00981F}, {0xC78, 0x0AF0991F},
+ {0xC78, 0x0AE09A1F}, {0xC78, 0x0AD09B1F},
+ {0xC78, 0x0AC09C1F}, {0xC78, 0x0AB09D1F},
+ {0xC78, 0x0AA09E1F}, {0xC78, 0x0A909F1F},
+ {0xC78, 0x0A80A01F}, {0xC78, 0x0A70A11F},
+ {0xC78, 0x0A60A21F}, {0xC78, 0x0A50A31F},
+ {0xC78, 0x0A40A41F}, {0xC78, 0x0A30A51F},
+ {0xC78, 0x0A20A61F}, {0xC78, 0x0A10A71F},
+ {0xC78, 0x0A00A81F}, {0xC78, 0x0830A91F},
+ {0xC78, 0x0820AA1F}, {0xC78, 0x0810AB1F},
+ {0xC78, 0x0800AC1F}, {0xC78, 0x0640AD1F},
+ {0xC78, 0x0630AE1F}, {0xC78, 0x0620AF1F},
+ {0xC78, 0x0610B01F}, {0xC78, 0x0600B11F},
+ {0xC78, 0x0430B21F}, {0xC78, 0x0420B31F},
+ {0xC78, 0x0410B41F}, {0xC78, 0x0400B51F},
+ {0xC78, 0x0230B61F}, {0xC78, 0x0220B71F},
+ {0xC78, 0x0210B81F}, {0xC78, 0x0200B91F},
+ {0xC78, 0x0000BA1F}, {0xC78, 0x0000BB1F},
+ {0xC78, 0x0000BC1F}, {0xC78, 0x0000BD1F},
+ {0xC78, 0x0000BE1F}, {0xC78, 0x0000BF1F},
+ {0xC50, 0x00E48024}, {0xC50, 0x00E48020},
+ {0xffff, 0xffffffff}
+};
+
+static const struct rtl8xxxu_rfregval rtl8192fu_radioa_init_table[] = {
+ {0x00, 0x30000}, {0x18, 0x0FC07}, {0x81, 0x0FC00}, {0x82, 0x003C0},
+ {0x84, 0x00005}, {0x86, 0xA33A5}, {0x87, 0x00000}, {0x88, 0x58010},
+ {0x8E, 0x64540}, {0x8F, 0x282D8}, {0x51, 0x02C06}, {0x52, 0x7A007},
+ {0x53, 0x10061}, {0x54, 0x60018}, {0x55, 0x82020}, {0x56, 0x08CC6},
+ {0x57, 0x2CC00}, {0x58, 0x00000}, {0x5A, 0x50000}, {0x5B, 0x00006},
+ {0x5C, 0x00015}, {0x65, 0x20000}, {0x6E, 0x38319}, {0xF5, 0x43180},
+ {0xEF, 0x00002}, {0x33, 0x00301}, {0x33, 0x1032A}, {0x33, 0x2032A},
+ {0xEF, 0x00000}, {0xDF, 0x00002}, {0x35, 0x00000}, {0xF0, 0x08008},
+ {0xEF, 0x00800}, {0x33, 0x0040E}, {0x33, 0x04845}, {0x33, 0x08848},
+ {0x33, 0x0C84B}, {0x33, 0x1088A}, {0x33, 0x14C50}, {0x33, 0x18C8E},
+ {0x33, 0x1CCCD}, {0x33, 0x20CD0}, {0x33, 0x24CD3}, {0x33, 0x28CD6},
+ {0x33, 0x4002B}, {0x33, 0x4402E}, {0x33, 0x48846}, {0x33, 0x4C849},
+ {0x33, 0x50888}, {0x33, 0x54CC6}, {0x33, 0x58CC9}, {0x33, 0x5CCCC},
+ {0x33, 0x60CCF}, {0x33, 0x64CD2}, {0x33, 0x68CD5}, {0xEF, 0x00000},
+ {0xEF, 0x00400}, {0x33, 0x01C23}, {0x33, 0x05C23}, {0x33, 0x09D23},
+ {0x33, 0x0DD23}, {0x33, 0x11FA3}, {0x33, 0x15FA3}, {0x33, 0x19FAB},
+ {0x33, 0x1DFAB}, {0xEF, 0x00000}, {0xEF, 0x00200}, {0x33, 0x00030},
+ {0x33, 0x04030}, {0x33, 0x08030}, {0x33, 0x0C030}, {0x33, 0x10030},
+ {0x33, 0x14030}, {0x33, 0x18030}, {0x33, 0x1C030}, {0x33, 0x20030},
+ {0x33, 0x24030}, {0x33, 0x28030}, {0x33, 0x2C030}, {0x33, 0x30030},
+ {0x33, 0x34030}, {0x33, 0x38030}, {0x33, 0x3C030}, {0xEF, 0x00000},
+ {0xEF, 0x00100}, {0x33, 0x44001}, {0x33, 0x48001}, {0x33, 0x4C001},
+ {0x33, 0x50001}, {0x33, 0x54001}, {0x33, 0x58001}, {0x33, 0x5C001},
+ {0x33, 0x60001}, {0x33, 0x64001}, {0x33, 0x68001}, {0x33, 0x6C001},
+ {0x33, 0x70001}, {0x33, 0x74001}, {0x33, 0x78001}, {0x33, 0x04000},
+ {0x33, 0x08000}, {0x33, 0x0C000}, {0x33, 0x10000}, {0x33, 0x14000},
+ {0x33, 0x18001}, {0x33, 0x1C002}, {0x33, 0x20002}, {0x33, 0x24002},
+ {0x33, 0x28002}, {0x33, 0x2C002}, {0x33, 0x30002}, {0x33, 0x34002},
+ {0x33, 0x38002}, {0xEF, 0x00000}, {0x84, 0x00000}, {0xEF, 0x80010},
+ {0x30, 0x20000}, {0x31, 0x0006F}, {0x32, 0x01FF7}, {0xEF, 0x00000},
+ {0x84, 0x00000}, {0xEF, 0x80000}, {0x30, 0x30000}, {0x31, 0x0006F},
+ {0x32, 0xF1DF3}, {0xEF, 0x00000}, {0x84, 0x00000}, {0xEF, 0x80000},
+ {0x30, 0x38000}, {0x31, 0x0006F}, {0x32, 0xF1FF2}, {0xEF, 0x00000},
+ {0x1B, 0x746CE}, {0xEF, 0x20000}, {0x33, 0x30000}, {0x33, 0x38000},
+ {0x33, 0x70000}, {0x33, 0x78000}, {0xEF, 0x00000}, {0xDF, 0x08000},
+ {0xB0, 0xFFBCB}, {0xB3, 0x06000}, {0xB7, 0x18DF0}, {0xB8, 0x38FF0},
+ {0xC9, 0x00600}, {0xDF, 0x00000}, {0xB1, 0x33B8F}, {0xB2, 0x33762},
+ {0xB4, 0x141F0}, {0xB5, 0x14080}, {0xB6, 0x12425}, {0xB9, 0xC0008},
+ {0xBA, 0x40005}, {0xC2, 0x02C01}, {0xC3, 0x0000B}, {0xC4, 0x81E2F},
+ {0xC5, 0x5C28F}, {0xC6, 0x000A0}, {0xCA, 0x02000}, {0xFE, 0x00000},
+ {0x18, 0x08C07}, {0xFE, 0x00000}, {0xFE, 0x00000}, {0xFE, 0x00000},
+ {0x00, 0x31DD5},
+ {0xff, 0xffffffff}
+};
+
+static const struct rtl8xxxu_rfregval rtl8192fu_radiob_init_table[] = {
+ {0x00, 0x30000}, {0x81, 0x0FC00}, {0x82, 0x003C0}, {0x84, 0x00005},
+ {0x86, 0xA33A5}, {0x87, 0x00000}, {0x88, 0x58010}, {0x8E, 0x64540},
+ {0x8F, 0x282D8}, {0x51, 0x02C06}, {0x52, 0x7A007}, {0x53, 0x10061},
+ {0x54, 0x60018}, {0x55, 0x82020}, {0x56, 0x08CC6}, {0x57, 0x2CC00},
+ {0x58, 0x00000}, {0x5A, 0x50000}, {0x5B, 0x00006}, {0x5C, 0x00015},
+ {0x65, 0x20000}, {0x6E, 0x38319}, {0xF5, 0x43180}, {0xEF, 0x00002},
+ {0x33, 0x00301}, {0x33, 0x1032A}, {0x33, 0x2032A}, {0xEF, 0x00000},
+ {0xDF, 0x00002}, {0x35, 0x00000}, {0xF0, 0x08008}, {0xEF, 0x00800},
+ {0x33, 0x0040E}, {0x33, 0x04845}, {0x33, 0x08848}, {0x33, 0x0C84B},
+ {0x33, 0x1088A}, {0x33, 0x14CC8}, {0x33, 0x18CCB}, {0x33, 0x1CCCE},
+ {0x33, 0x20CD1}, {0x33, 0x24CD4}, {0x33, 0x28CD7}, {0x33, 0x4002B},
+ {0x33, 0x4402E}, {0x33, 0x48846}, {0x33, 0x4C849}, {0x33, 0x50888},
+ {0x33, 0x54CC6}, {0x33, 0x58CC9}, {0x33, 0x5CCCC}, {0x33, 0x60CCF},
+ {0x33, 0x64CD2}, {0x33, 0x68CD5}, {0xEF, 0x00000}, {0xEF, 0x00400},
+ {0x33, 0x01D23}, {0x33, 0x05D23}, {0x33, 0x09FA3}, {0x33, 0x0DFA3},
+ {0x33, 0x11D2B}, {0x33, 0x15D2B}, {0x33, 0x19FAB}, {0x33, 0x1DFAB},
+ {0xEF, 0x00000}, {0xEF, 0x00200}, {0x33, 0x00030}, {0x33, 0x04030},
+ {0x33, 0x08030}, {0x33, 0x0C030}, {0x33, 0x10030}, {0x33, 0x14030},
+ {0x33, 0x18030}, {0x33, 0x1C030}, {0x33, 0x20030}, {0x33, 0x24030},
+ {0x33, 0x28030}, {0x33, 0x2C030}, {0x33, 0x30030}, {0x33, 0x34030},
+ {0x33, 0x38030}, {0x33, 0x3C030}, {0xEF, 0x00000}, {0xEF, 0x00100},
+ {0x33, 0x44000}, {0x33, 0x48000}, {0x33, 0x4C000}, {0x33, 0x50000},
+ {0x33, 0x54000}, {0x33, 0x58000}, {0x33, 0x5C000}, {0x33, 0x60000},
+ {0x33, 0x64000}, {0x33, 0x68000}, {0x33, 0x6C000}, {0x33, 0x70000},
+ {0x33, 0x74000}, {0x33, 0x78000}, {0x33, 0x04000}, {0x33, 0x08000},
+ {0x33, 0x0C000}, {0x33, 0x10000}, {0x33, 0x14000}, {0x33, 0x18000},
+ {0x33, 0x1C001}, {0x33, 0x20001}, {0x33, 0x24001}, {0x33, 0x28001},
+ {0x33, 0x2C001}, {0x33, 0x30001}, {0x33, 0x34001}, {0x33, 0x38001},
+ {0xEF, 0x00000}, {0x84, 0x00000}, {0xEF, 0x80010}, {0x30, 0x20000},
+ {0x31, 0x0006F}, {0x32, 0x01FF7}, {0xEF, 0x00000}, {0x84, 0x00000},
+ {0xEF, 0x80000}, {0x30, 0x30000}, {0x31, 0x0006F}, {0x32, 0xF1DF3},
+ {0xEF, 0x00000}, {0x84, 0x00000}, {0xEF, 0x80000}, {0x30, 0x38000},
+ {0x31, 0x0006F}, {0x32, 0xF1FF2}, {0xEF, 0x00000}, {0x1B, 0x746CE},
+ {0xEF, 0x20000}, {0x33, 0x30000}, {0x33, 0x38000}, {0x33, 0x70000},
+ {0x33, 0x78000}, {0xEF, 0x00000}, {0x00, 0x31DD5},
+ {0xff, 0xffffffff}
+};
+
+static int rtl8192fu_identify_chip(struct rtl8xxxu_priv *priv)
+{
+ struct device *dev = &priv->udev->dev;
+ u32 sys_cfg, vendor, val32;
+
+ strscpy(priv->chip_name, "8192FU", sizeof(priv->chip_name));
+ priv->rtl_chip = RTL8192F;
+ priv->rf_paths = 2;
+ priv->rx_paths = 2;
+ priv->tx_paths = 2;
+
+ sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG);
+ priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK);
+ if (sys_cfg & SYS_CFG_TRP_VAUX_EN) {
+ dev_info(dev, "Unsupported test chip\n");
+ return -EOPNOTSUPP;
+ }
+
+ val32 = rtl8xxxu_read32(priv, REG_MULTI_FUNC_CTRL);
+ priv->has_wifi = u32_get_bits(val32, MULTI_WIFI_FUNC_EN);
+ priv->has_bluetooth = u32_get_bits(val32, MULTI_BT_FUNC_EN);
+ priv->has_gps = u32_get_bits(val32, MULTI_GPS_FUNC_EN);
+ priv->is_multi_func = 1;
+
+ vendor = sys_cfg & SYS_CFG_VENDOR_ID;
+ rtl8xxxu_identify_vendor_1bit(priv, vendor);
+
+ val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS);
+ priv->rom_rev = u32_get_bits(val32, GPIO_RF_RL_ID);
+
+ return rtl8xxxu_config_endpoints_no_sie(priv);
+}
+
+static void
+rtl8192f_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40)
+{
+ u8 cck, ofdmbase, mcsbase;
+ u32 val32, ofdm, mcs;
+ int group, cck_group;
+
+ rtl8188f_channel_to_group(channel, &group, &cck_group);
+
+ cck = priv->cck_tx_power_index_A[cck_group];
+
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_CCK1_MCS32, 0x00007f00, cck);
+
+ val32 = (cck << 16) | (cck << 8) | cck;
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_CCK11_A_CCK2_11,
+ 0x7f7f7f00, val32);
+
+ ofdmbase = priv->ht40_1s_tx_power_index_A[group];
+ ofdmbase += priv->ofdm_tx_power_diff[RF_A].a;
+ ofdm = ofdmbase | ofdmbase << 8 | ofdmbase << 16 | ofdmbase << 24;
+
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_RATE18_06, 0x7f7f7f7f, ofdm);
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_RATE54_24, 0x7f7f7f7f, ofdm);
+
+ mcsbase = priv->ht40_1s_tx_power_index_A[group];
+ if (ht40)
+ mcsbase += priv->ht40_tx_power_diff[RF_A].a;
+ else
+ mcsbase += priv->ht20_tx_power_diff[RF_A].a;
+ mcs = mcsbase | mcsbase << 8 | mcsbase << 16 | mcsbase << 24;
+
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_MCS03_MCS00, 0x7f7f7f7f, mcs);
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_MCS07_MCS04, 0x7f7f7f7f, mcs);
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_MCS11_MCS08, 0x7f7f7f7f, mcs);
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_MCS15_MCS12, 0x7f7f7f7f, mcs);
+
+ if (priv->tx_paths == 1)
+ return;
+
+ cck = priv->cck_tx_power_index_B[cck_group];
+
+ val32 = (cck << 16) | (cck << 8) | cck;
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_CCK1_55_MCS32,
+ 0x7f7f7f00, val32);
+
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_CCK11_A_CCK2_11,
+ 0x0000007f, cck);
+
+ ofdmbase = priv->ht40_1s_tx_power_index_B[group];
+ ofdmbase += priv->ofdm_tx_power_diff[RF_B].b;
+ ofdm = ofdmbase | ofdmbase << 8 | ofdmbase << 16 | ofdmbase << 24;
+
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_RATE18_06, 0x7f7f7f7f, ofdm);
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_RATE54_24, 0x7f7f7f7f, ofdm);
+
+ mcsbase = priv->ht40_1s_tx_power_index_B[group];
+ if (ht40)
+ mcsbase += priv->ht40_tx_power_diff[RF_B].b;
+ else
+ mcsbase += priv->ht20_tx_power_diff[RF_B].b;
+ mcs = mcsbase | mcsbase << 8 | mcsbase << 16 | mcsbase << 24;
+
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_MCS03_MCS00, 0x7f7f7f7f, mcs);
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_MCS07_MCS04, 0x7f7f7f7f, mcs);
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_MCS11_MCS08, 0x7f7f7f7f, mcs);
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_MCS15_MCS12, 0x7f7f7f7f, mcs);
+}
+
+static void rtl8192f_revise_cck_tx_psf(struct rtl8xxxu_priv *priv, u8 channel)
+{
+ if (channel == 13) {
+ /* Special value for channel 13 */
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER1, 0xf8fe0001);
+ /* Normal values */
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER2, 0x64B80C1C);
+ rtl8xxxu_write16(priv, REG_CCK0_DEBUG_PORT, 0x8810);
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER3, 0x01235667);
+ } else if (channel == 14) {
+ /* Normal value */
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER1, 0xE82C0001);
+ /* Special values for channel 14 */
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER2, 0x0000B81C);
+ rtl8xxxu_write16(priv, REG_CCK0_DEBUG_PORT, 0x0000);
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER3, 0x00003667);
+ } else {
+ /* Restore normal values from the phy init table */
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER1, 0xE82C0001);
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER2, 0x64B80C1C);
+ rtl8xxxu_write16(priv, REG_CCK0_DEBUG_PORT, 0x8810);
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER3, 0x01235667);
+ }
+}
+
+static void rtl8192fu_config_kfree(struct rtl8xxxu_priv *priv, u8 channel)
+{
+ u8 bb_gain[3] = { EFUSE_UNDEFINED, EFUSE_UNDEFINED, EFUSE_UNDEFINED };
+ u8 bb_gain_path_mask[2] = { 0x0f, 0xf0 };
+ enum rtl8xxxu_rfpath rfpath;
+ u8 bb_gain_for_path;
+ u8 channel_idx = 0;
+
+ if (channel >= 1 && channel <= 3)
+ channel_idx = 0;
+ if (channel >= 4 && channel <= 9)
+ channel_idx = 1;
+ if (channel >= 10 && channel <= 14)
+ channel_idx = 2;
+
+ rtl8xxxu_read_efuse8(priv, 0x1ee, &bb_gain[1]);
+ rtl8xxxu_read_efuse8(priv, 0x1ec, &bb_gain[0]);
+ rtl8xxxu_read_efuse8(priv, 0x1ea, &bb_gain[2]);
+
+ if (bb_gain[1] == EFUSE_UNDEFINED)
+ return;
+
+ if (bb_gain[0] == EFUSE_UNDEFINED)
+ bb_gain[0] = bb_gain[1];
+
+ if (bb_gain[2] == EFUSE_UNDEFINED)
+ bb_gain[2] = bb_gain[1];
+
+ for (rfpath = RF_A; rfpath < priv->rf_paths; rfpath++) {
+ /* power_trim based on 55[19:14] */
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_UNKNOWN_55,
+ BIT(5), 1);
+
+ /* enable 55[14] for 0.5db step */
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_GAIN_CTRL,
+ BIT(18), 1);
+
+ /* enter power_trim debug mode */
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_GAIN_CCA,
+ BIT(7), 1);
+
+ /* write enable */
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_WE_LUT, BIT(7), 1);
+
+ bb_gain_for_path = (bb_gain[channel_idx] & bb_gain_path_mask[rfpath]);
+ bb_gain_for_path >>= __ffs(bb_gain_path_mask[rfpath]);
+
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3,
+ 0x70000, channel_idx * 2);
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3,
+ 0x3f, bb_gain_for_path);
+
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3,
+ 0x70000, channel_idx * 2 + 1);
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3,
+ 0x3f, bb_gain_for_path);
+
+ /* leave power_trim debug mode */
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_GAIN_CCA,
+ BIT(7), 0);
+
+ /* write disable */
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_WE_LUT, BIT(7), 0);
+ }
+}
+
+static void rtl8192fu_config_channel(struct ieee80211_hw *hw)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ bool ht40 = conf_is_ht40(&hw->conf);
+ u8 channel, subchannel = 0;
+ bool sec_ch_above = 0;
+ u32 val32;
+
+ channel = (u8)hw->conf.chandef.chan->hw_value;
+
+ if (conf_is_ht40_plus(&hw->conf)) {
+ sec_ch_above = 1;
+ channel += 2;
+ subchannel = 2;
+ } else if (conf_is_ht40_minus(&hw->conf)) {
+ sec_ch_above = 0;
+ channel -= 2;
+ subchannel = 1;
+ }
+
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_MODE_AG);
+
+ rtl8192f_revise_cck_tx_psf(priv, channel);
+
+ /* Set channel */
+ val32 &= ~(BIT(18) | BIT(17)); /* select the 2.4G band(?) */
+ u32p_replace_bits(&val32, channel, 0xff);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, val32);
+ if (priv->rf_paths > 1)
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_MODE_AG, val32);
+
+ rtl8192fu_config_kfree(priv, channel);
+
+ rtl8xxxu_write8(priv, REG_DATA_SUBCHANNEL, subchannel);
+
+ /* small BW */
+ rtl8xxxu_write32_clear(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT, GENMASK(31, 30));
+
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_RF_MODE, FPGA_RF_MODE, ht40);
+ rtl8xxxu_write32_mask(priv, REG_FPGA1_RF_MODE, FPGA_RF_MODE, ht40);
+
+ /* ADC clock = 160M */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_RF_MODE, GENMASK(10, 8), 4);
+
+ /* DAC clock = 80M */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_RF_MODE, BIT(13) | BIT(12), 2);
+
+ /* ADC buffer clk */
+ rtl8xxxu_write32_mask(priv, REG_ANTDIV_PARA1, BIT(27) | BIT(26), 2);
+
+ if (ht40)
+ /* Set Control channel to upper or lower. */
+ rtl8xxxu_write32_mask(priv, REG_CCK0_SYSTEM,
+ CCK0_SIDEBAND, !sec_ch_above);
+
+ /* Enable CCK */
+ rtl8xxxu_write32_set(priv, REG_FPGA0_RF_MODE, FPGA_RF_MODE_CCK);
+
+ /* RF TRX_BW */
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_MODE_AG);
+ val32 &= ~MODE_AG_BW_MASK;
+ if (ht40)
+ val32 |= MODE_AG_BW_40MHZ_8723B;
+ else
+ val32 |= MODE_AG_BW_20MHZ_8723B;
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, val32);
+ if (priv->rf_paths > 1)
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_MODE_AG, val32);
+
+ /* Modify RX DFIR parameters */
+ rtl8xxxu_write32_mask(priv, REG_TAP_UPD_97F, BIT(21) | BIT(20), 2);
+
+ rtl8xxxu_write32_mask(priv, REG_DOWNSAM_FACTOR, BIT(29) | BIT(28), 2);
+
+ if (ht40)
+ val32 = 0x3;
+ else
+ val32 = 0x1a3;
+ rtl8xxxu_write32_mask(priv, REG_RX_DFIR_MOD_97F, 0x1ff, val32);
+}
+
+static void rtl8192fu_init_aggregation(struct rtl8xxxu_priv *priv)
+{
+ u32 agg_rx;
+ u8 agg_ctrl;
+
+ /* RX aggregation */
+ agg_ctrl = rtl8xxxu_read8(priv, REG_TRXDMA_CTRL);
+ agg_ctrl &= ~TRXDMA_CTRL_RXDMA_AGG_EN;
+
+ agg_rx = rtl8xxxu_read32(priv, REG_RXDMA_AGG_PG_TH);
+ agg_rx &= ~RXDMA_USB_AGG_ENABLE;
+ agg_rx &= ~0xFF0F; /* reset agg size and timeout */
+
+ rtl8xxxu_write8(priv, REG_TRXDMA_CTRL, agg_ctrl);
+ rtl8xxxu_write32(priv, REG_RXDMA_AGG_PG_TH, agg_rx);
+}
+
+static int rtl8192fu_parse_efuse(struct rtl8xxxu_priv *priv)
+{
+ struct rtl8192fu_efuse *efuse = &priv->efuse_wifi.efuse8192fu;
+ int i;
+
+ if (efuse->rtl_id != cpu_to_le16(0x8129))
+ return -EINVAL;
+
+ ether_addr_copy(priv->mac_addr, efuse->mac_addr);
+
+ memcpy(priv->cck_tx_power_index_A, efuse->tx_power_index_A.cck_base,
+ sizeof(efuse->tx_power_index_A.cck_base));
+ memcpy(priv->cck_tx_power_index_B, efuse->tx_power_index_B.cck_base,
+ sizeof(efuse->tx_power_index_B.cck_base));
+
+ memcpy(priv->ht40_1s_tx_power_index_A,
+ efuse->tx_power_index_A.ht40_base,
+ sizeof(efuse->tx_power_index_A.ht40_base));
+ memcpy(priv->ht40_1s_tx_power_index_B,
+ efuse->tx_power_index_B.ht40_base,
+ sizeof(efuse->tx_power_index_B.ht40_base));
+
+ priv->ht20_tx_power_diff[0].a =
+ efuse->tx_power_index_A.ht20_ofdm_1s_diff.b;
+ priv->ht20_tx_power_diff[0].b =
+ efuse->tx_power_index_B.ht20_ofdm_1s_diff.b;
+
+ priv->ht40_tx_power_diff[0].a = 0;
+ priv->ht40_tx_power_diff[0].b = 0;
+
+ for (i = 1; i < RTL8723B_TX_COUNT; i++) {
+ priv->ofdm_tx_power_diff[i].a =
+ efuse->tx_power_index_A.pwr_diff[i - 1].ofdm;
+ priv->ofdm_tx_power_diff[i].b =
+ efuse->tx_power_index_B.pwr_diff[i - 1].ofdm;
+
+ priv->ht20_tx_power_diff[i].a =
+ efuse->tx_power_index_A.pwr_diff[i - 1].ht20;
+ priv->ht20_tx_power_diff[i].b =
+ efuse->tx_power_index_B.pwr_diff[i - 1].ht20;
+
+ priv->ht40_tx_power_diff[i].a =
+ efuse->tx_power_index_A.pwr_diff[i - 1].ht40;
+ priv->ht40_tx_power_diff[i].b =
+ efuse->tx_power_index_B.pwr_diff[i - 1].ht40;
+ }
+
+ priv->default_crystal_cap = efuse->xtal_k & 0x3f;
+
+ priv->rfe_type = efuse->rfe_option & 0x1f;
+
+ if (priv->rfe_type != 5 && priv->rfe_type != 1)
+ dev_warn(&priv->udev->dev,
+ "%s: RFE type %d was not tested. Please send an email to linux-wireless@vger.kernel.org about this.\n",
+ __func__, priv->rfe_type);
+
+ return 0;
+}
+
+static int rtl8192fu_load_firmware(struct rtl8xxxu_priv *priv)
+{
+ return rtl8xxxu_load_firmware(priv, "rtlwifi/rtl8192fufw.bin");
+}
+
+static void rtl8192fu_init_phy_bb(struct rtl8xxxu_priv *priv)
+{
+ /* Enable BB and RF */
+ rtl8xxxu_write16_set(priv, REG_SYS_FUNC,
+ SYS_FUNC_BBRSTB | SYS_FUNC_BB_GLB_RSTN);
+
+ rtl8xxxu_write8(priv, REG_RF_CTRL, RF_ENABLE | RF_RSTB | RF_SDMRSTB);
+
+ /* To Fix MAC loopback mode fail. */
+ rtl8xxxu_write8(priv, REG_LDOHCI12_CTRL, 0xf);
+ rtl8xxxu_write8(priv, REG_SYS_SWR_CTRL2 + 1, 0xe9);
+
+ rtl8xxxu_init_phy_regs(priv, rtl8192fu_phy_init_table);
+
+ rtl8xxxu_init_phy_regs(priv, rtl8192f_agc_table);
+}
+
+static int rtl8192fu_init_phy_rf(struct rtl8xxxu_priv *priv)
+{
+ int ret;
+
+ ret = rtl8xxxu_init_phy_rf(priv, rtl8192fu_radioa_init_table, RF_A);
+ if (ret)
+ return ret;
+
+ return rtl8xxxu_init_phy_rf(priv, rtl8192fu_radiob_init_table, RF_B);
+}
+
+static void rtl8192f_phy_lc_calibrate(struct rtl8xxxu_priv *priv)
+{
+ u32 backup_mask = BIT(31) | BIT(30);
+ u32 backup;
+ u32 val32;
+
+ /* Aries's NarrowBand */
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT);
+ backup = u32_get_bits(val32, backup_mask);
+
+ u32p_replace_bits(&val32, 0, backup_mask);
+ rtl8xxxu_write32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT, val32);
+
+ rtl8188f_phy_lc_calibrate(priv);
+
+ /* Aries's NarrowBand */
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT);
+ u32p_replace_bits(&val32, backup, backup_mask);
+ rtl8xxxu_write32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT, val32);
+
+ /* reset OFDM state */
+ rtl8xxxu_write32_clear(priv, REG_FPGA0_RF_MODE, FPGA_RF_MODE_OFDM);
+ rtl8xxxu_write32_set(priv, REG_FPGA0_RF_MODE, FPGA_RF_MODE_OFDM);
+}
+
+static int rtl8192fu_iqk_path_a(struct rtl8xxxu_priv *priv)
+{
+ u32 reg_eac, reg_e94, reg_e9c, val32;
+ u32 rf_0x58_i, rf_0x58_q;
+ u8 rfe = priv->rfe_type;
+ int result = 0;
+ int ktime, i;
+
+ /* Leave IQK mode */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0);
+ rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44);
+ rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040);
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403);
+ rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4);
+ rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400);
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(4), 1);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(11), 1);
+ if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12)
+ val32 = 0x30;
+ else
+ val32 = 0xe9;
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_PAD_TXG, 0x003ff, val32);
+
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000);
+
+ /* path-A IQK setting */
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x18008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
+
+ rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x8214000f);
+ rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28140000);
+
+ rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00);
+ rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
+
+ /* LO calibration setting */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00e62911);
+
+ /* One shot, path A LOK & IQK */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800);
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800);
+
+ mdelay(15);
+
+ ktime = 0;
+ while (rtl8xxxu_read32(priv, REG_IQK_RPT_TXA) == 0 && ktime < 21) {
+ mdelay(5);
+ ktime += 5;
+ }
+
+ /* Check failed */
+ reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
+ reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A);
+ reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A);
+
+ /* reload 0xdf and CCK_IND off */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_WE_LUT, BIT(4), 1);
+
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_TXMOD);
+ rf_0x58_i = u32_get_bits(val32, 0xfc000);
+ rf_0x58_q = u32_get_bits(val32, 0x003f0);
+
+ for (i = 0; i < 8; i++) {
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_TXPA_G3,
+ 0x1c000, i);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_TXPA_G3,
+ 0x00fc0, rf_0x58_i);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_TXPA_G3,
+ 0x0003f, rf_0x58_q);
+ }
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_AC, BIT(14), 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_WE_LUT, BIT(4), 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00810, 0);
+
+ if (!(reg_eac & BIT(28)) &&
+ ((reg_e94 & 0x03ff0000) != 0x01420000) &&
+ ((reg_e9c & 0x03ff0000) != 0x00420000))
+ result |= 0x01;
+
+ return result;
+}
+
+static int rtl8192fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
+{
+ u32 reg_ea4, reg_eac, reg_e94, reg_e9c, val32;
+ int result = 0;
+ int ktime;
+
+ /* Leave IQK mode */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ /* PA/PAD control by 0x56, and set = 0x0 */
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(1), 1);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_P1, 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(11), 1);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_PAD_TXG, 0x003ff, 0x27);
+
+ /* Enter IQK mode */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000);
+
+ /* path-A IQK setting */
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x18008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
+
+ rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160027);
+ rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28160000);
+
+ /* Tx IQK setting */
+ rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00);
+ rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
+
+ /* LO calibration setting */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0086a911);
+
+ /* One shot, path A LOK & IQK */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800);
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800);
+
+ mdelay(15);
+
+ ktime = 0;
+ while (rtl8xxxu_read32(priv, REG_IQK_RPT_TXA) == 0 && ktime < 21) {
+ mdelay(5);
+ ktime += 5;
+ }
+
+ /* Check failed */
+ reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
+ reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A);
+ reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A);
+
+ if (!(reg_eac & BIT(28)) &&
+ ((reg_e94 & 0x03ff0000) != 0x01420000) &&
+ ((reg_e9c & 0x03ff0000) != 0x00420000)) {
+ result |= 0x01;
+ } else { /* If TX not OK, ignore RX */
+ /* PA/PAD controlled by 0x0 */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA,
+ BIT(11), 0);
+
+ return result;
+ }
+
+ val32 = 0x80007c00 | (reg_e94 & 0x3ff0000) | ((reg_e9c & 0x3ff0000) >> 16);
+ rtl8xxxu_write32(priv, REG_TX_IQK, val32);
+
+ /* Modify RX IQK mode table */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ /* PA/PAD control by 0x56, and set = 0x0 */
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(1), 1);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_P1, 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(11), 1);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_PAD_TXG, 0x003ff, 0x1e0);
+
+ rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0);
+ rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44);
+ rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040);
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403);
+ rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4);
+ rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400);
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100);
+
+ /* Enter IQK mode */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000);
+
+ /* path-A IQK setting */
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x18008c1c);
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
+
+ rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82170000);
+ rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28170000);
+
+ /* RX IQK setting */
+ rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
+
+ /* LO calibration setting */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a8d1);
+
+ /* One shot, path A LOK & IQK */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800);
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800);
+
+ mdelay(15);
+
+ ktime = 0;
+ while (rtl8xxxu_read32(priv, REG_IQK_RPT_RXA) == 0 && ktime < 21) {
+ mdelay(5);
+ ktime += 5;
+ }
+
+ /* Check failed */
+ reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
+ reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2);
+
+ /* Leave IQK mode */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(11), 0);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_P1, 0x02000);
+
+ if (!(reg_eac & BIT(27)) &&
+ ((reg_ea4 & 0x03ff0000) != 0x01320000) &&
+ ((reg_eac & 0x03ff0000) != 0x00360000))
+ result |= 0x02;
+
+ return result;
+}
+
+static int rtl8192fu_iqk_path_b(struct rtl8xxxu_priv *priv)
+{
+ u32 reg_eac, reg_eb4, reg_ebc, val32;
+ u32 rf_0x58_i, rf_0x58_q;
+ u8 rfe = priv->rfe_type;
+ int result = 0;
+ int ktime, i;
+
+ /* PA/PAD controlled by 0x0 */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0);
+ rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44);
+ rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040);
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403);
+ rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4);
+ rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400);
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000000);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(4), 1);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(11), 1);
+ if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12)
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_PAD_TXG,
+ 0x003ff, 0x30);
+ else
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_PAD_TXG,
+ 0x00fff, 0xe9);
+
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000);
+
+ /* Path B IQK setting */
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
+
+ rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x8214000F);
+ rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28140000);
+
+ rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00);
+ rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
+
+ /* LO calibration setting */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00e62911);
+
+ /* One shot, path B LOK & IQK */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800);
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800);
+
+ mdelay(15);
+
+ ktime = 0;
+ while (rtl8xxxu_read32(priv, REG_IQK_RPT_TXB) == 0 && ktime < 21) {
+ mdelay(5);
+ ktime += 5;
+ }
+
+ /* Check failed */
+ reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
+ reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B);
+ reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B);
+
+ /* reload 0xdf and CCK_IND off */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_WE_LUT, BIT(4), 1);
+
+ val32 = rtl8xxxu_read_rfreg(priv, RF_B, RF6052_REG_TXMOD);
+ rf_0x58_i = u32_get_bits(val32, 0xfc000);
+ rf_0x58_q = u32_get_bits(val32, 0x003f0);
+
+ for (i = 0; i < 8; i++) {
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_TXPA_G3,
+ 0x1c000, i);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_TXPA_G3,
+ 0x00fc0, rf_0x58_i);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_TXPA_G3,
+ 0x0003f, rf_0x58_q);
+ }
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_AC, BIT(14), 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_WE_LUT, BIT(4), 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00810, 0);
+
+ if (!(reg_eac & BIT(31)) &&
+ ((reg_eb4 & 0x03ff0000) != 0x01420000) &&
+ ((reg_ebc & 0x03ff0000) != 0x00420000))
+ result |= 0x01;
+ else
+ dev_warn(&priv->udev->dev, "%s: Path B IQK failed!\n",
+ __func__);
+
+ return result;
+}
+
+static int rtl8192fu_rx_iqk_path_b(struct rtl8xxxu_priv *priv)
+{
+ u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc, val32;
+ int result = 0;
+ int ktime;
+
+ /* Leave IQK mode */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(1), 1);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_P1, 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(11), 1);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_PAD_TXG, 0x003ff, 0x67);
+
+ rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0);
+ rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44);
+ rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040);
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403);
+ rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4);
+ rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400);
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000000);
+
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000);
+
+ /* path-B IQK setting */
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
+
+ rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82160027);
+ rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28160000);
+
+ /* LO calibration setting */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0086a911);
+
+ /* One shot, path A LOK & IQK */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800);
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800);
+
+ mdelay(15);
+
+ ktime = 0;
+ while (rtl8xxxu_read32(priv, REG_IQK_RPT_TXB) == 0 && ktime < 21) {
+ mdelay(5);
+ ktime += 5;
+ }
+
+ /* Check failed */
+ reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
+ reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B);
+ reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B);
+
+ if (!(reg_eac & BIT(31)) &&
+ ((reg_eb4 & 0x03ff0000) != 0x01420000) &&
+ ((reg_ebc & 0x03ff0000) != 0x00420000)) {
+ result |= 0x01;
+ } else {
+ /* PA/PAD controlled by 0x0 */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA,
+ BIT(11), 0);
+
+ return result;
+ }
+
+ val32 = 0x80007c00 | (reg_eb4 & 0x03ff0000) | ((reg_ebc >> 16) & 0x03ff);
+ rtl8xxxu_write32(priv, REG_TX_IQK, val32);
+
+ /* Modify RX IQK mode table */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(1), 1);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_P1, 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(11), 1);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_PAD_TXG, 0x003ff, 0x1e0);
+
+ rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0);
+ rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44);
+ rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040);
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403);
+ rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4);
+ rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400);
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000000);
+
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000);
+
+ /* Path B IQK setting */
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x18008c1c);
+
+ rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82170000);
+ rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28170000);
+
+ /* IQK setting */
+ rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
+
+ /* LO calibration setting */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a911);
+
+ /* One shot, path A LOK & IQK */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800);
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800);
+
+ mdelay(15);
+
+ ktime = 0;
+ while (rtl8xxxu_read32(priv, REG_IQK_RPT_RXB) == 0 && ktime < 21) {
+ mdelay(5);
+ ktime += 5;
+ }
+
+ reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
+ reg_ec4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2);
+ reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2);
+
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(11), 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(1), 0);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_P1, 0x02000);
+
+ if (!(reg_eac & BIT(30)) &&
+ ((reg_ec4 & 0x03ff0000) != 0x01320000) &&
+ ((reg_ecc & 0x03ff0000) != 0x00360000))
+ result |= 0x02;
+ else
+ dev_warn(&priv->udev->dev, "%s: Path B RX IQK failed!\n",
+ __func__);
+
+ return result;
+}
+
+static void rtl8192fu_phy_iqcalibrate(struct rtl8xxxu_priv *priv,
+ int result[][8], int t)
+{
+ static const u32 adda_regs[2] = {
+ REG_ANAPWR1, REG_RX_WAIT_CCA
+ };
+ static const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = {
+ REG_TXPAUSE, REG_BEACON_CTRL,
+ REG_BEACON_CTRL_1, REG_GPIO_MUXCFG
+ };
+ static const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = {
+ REG_OFDM0_TRX_PATH_ENABLE, REG_OFDM0_TR_MUX_PAR,
+ REG_FPGA0_XCD_RF_SW_CTRL, REG_CONFIG_ANT_A, REG_CONFIG_ANT_B,
+ REG_DPDT_CTRL, REG_RFE_CTRL_ANTA_SRC,
+ REG_RFE_CTRL_ANT_SRC2, REG_CCK0_AFE_SETTING
+ };
+ u32 rx_initial_gain_a, rx_initial_gain_b;
+ struct device *dev = &priv->udev->dev;
+ int path_a_ok, path_b_ok;
+ u8 rfe = priv->rfe_type;
+ int retry = 2;
+ u32 i, val32;
+
+ /*
+ * Note: IQ calibration must be performed after loading
+ * PHY_REG.txt , and radio_a, radio_b.txt
+ */
+
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rx_initial_gain_a = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1);
+ rx_initial_gain_b = rtl8xxxu_read32(priv, REG_OFDM0_XB_AGC_CORE1);
+
+ if (t == 0) {
+ /* Save ADDA parameters, turn Path A ADDA on */
+ rtl8xxxu_save_regs(priv, adda_regs, priv->adda_backup,
+ ARRAY_SIZE(adda_regs));
+ rtl8xxxu_save_mac_regs(priv, iqk_mac_regs, priv->mac_backup);
+ rtl8xxxu_save_regs(priv, iqk_bb_regs,
+ priv->bb_backup, RTL8XXXU_BB_REGS);
+ }
+
+ /* Instead of rtl8xxxu_path_adda_on */
+ rtl8xxxu_write32_set(priv, REG_FPGA0_XCD_RF_PARM, BIT(31));
+
+ /* MAC settings */
+ rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff);
+ rtl8xxxu_write8_clear(priv, REG_GPIO_MUXCFG, GPIO_MUXCFG_IO_SEL_ENBT);
+
+ if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12) {
+ /* in ePA IQK, rfe_func_config & SW both pull down */
+ /* path A */
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, 0xF, 0x7);
+ rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x1, 0x0);
+
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, 0xF00, 0x7);
+ rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x4, 0x0);
+
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, 0xF000, 0x7);
+ rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x8, 0x0);
+
+ /* path B */
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC2, 0xF0, 0x7);
+ rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x20000, 0x0);
+
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC2, 0xF0000, 0x7);
+ rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x100000, 0x0);
+
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC3, 0xF000, 0x7);
+ rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x8000000, 0x0);
+ }
+
+ if (priv->rf_paths > 1) {
+ /* path B standby */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x000000);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC, 0x10000);
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000);
+ }
+
+ for (i = 0; i < retry; i++) {
+ path_a_ok = rtl8192fu_iqk_path_a(priv);
+
+ if (path_a_ok == 0x01) {
+ val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A);
+ result[t][0] = (val32 >> 16) & 0x3ff;
+
+ val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A);
+ result[t][1] = (val32 >> 16) & 0x3ff;
+ break;
+ } else {
+ result[t][0] = 0x100;
+ result[t][1] = 0x0;
+ }
+ }
+
+ for (i = 0; i < retry; i++) {
+ path_a_ok = rtl8192fu_rx_iqk_path_a(priv);
+
+ if (path_a_ok == 0x03) {
+ val32 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2);
+ result[t][2] = (val32 >> 16) & 0x3ff;
+
+ val32 = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
+ result[t][3] = (val32 >> 16) & 0x3ff;
+ break;
+ } else {
+ result[t][2] = 0x100;
+ result[t][3] = 0x0;
+ }
+ }
+
+ if (!path_a_ok)
+ dev_warn(dev, "%s: Path A IQK failed!\n", __func__);
+
+ if (priv->rf_paths > 1) {
+ for (i = 0; i < retry; i++) {
+ path_b_ok = rtl8192fu_iqk_path_b(priv);
+
+ if (path_b_ok == 0x01) {
+ val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B);
+ result[t][4] = (val32 >> 16) & 0x3ff;
+
+ val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B);
+ result[t][5] = (val32 >> 16) & 0x3ff;
+ break;
+ } else {
+ result[t][4] = 0x100;
+ result[t][5] = 0x0;
+ }
+ }
+
+ for (i = 0; i < retry; i++) {
+ path_b_ok = rtl8192fu_rx_iqk_path_b(priv);
+
+ if (path_b_ok == 0x03) {
+ val32 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2);
+ result[t][6] = (val32 >> 16) & 0x3ff;
+
+ val32 = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2);
+ result[t][7] = (val32 >> 16) & 0x3ff;
+ break;
+ } else {
+ result[t][6] = 0x100;
+ result[t][7] = 0x0;
+ }
+ }
+
+ if (!path_b_ok)
+ dev_warn(dev, "%s: Path B IQK failed!\n", __func__);
+ }
+
+ /* Back to BB mode, load original value */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xcc0000c0);
+
+ rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44bbbb44);
+ rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x80408040);
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005433);
+ rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000004e4);
+ rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04003400);
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100);
+
+ /* Reload ADDA power saving parameters */
+ rtl8xxxu_restore_regs(priv, adda_regs, priv->adda_backup,
+ ARRAY_SIZE(adda_regs));
+
+ /* Reload MAC parameters */
+ rtl8xxxu_restore_mac_regs(priv, iqk_mac_regs, priv->mac_backup);
+
+ /* Reload BB parameters */
+ rtl8xxxu_restore_regs(priv, iqk_bb_regs, priv->bb_backup, RTL8XXXU_BB_REGS);
+
+ rtl8xxxu_write32_clear(priv, REG_FPGA0_XCD_RF_PARM, BIT(31));
+
+ /* Restore RX initial gain */
+ rtl8xxxu_write32_mask(priv, REG_OFDM0_XA_AGC_CORE1, 0xff, 0x50);
+ rtl8xxxu_write32_mask(priv, REG_OFDM0_XA_AGC_CORE1, 0xff,
+ rx_initial_gain_a & 0xff);
+ if (priv->rf_paths > 1) {
+ rtl8xxxu_write32_mask(priv, REG_OFDM0_XB_AGC_CORE1, 0xff, 0x50);
+ rtl8xxxu_write32_mask(priv, REG_OFDM0_XB_AGC_CORE1, 0xff,
+ rx_initial_gain_b & 0xff);
+ }
+}
+
+static void rtl8192fu_phy_iq_calibrate(struct rtl8xxxu_priv *priv)
+{
+ s32 reg_e94, reg_e9c, reg_ea4, reg_eac;
+ s32 reg_eb4, reg_ebc, reg_ec4, reg_ecc;
+ struct device *dev = &priv->udev->dev;
+ u32 path_a_0xdf, path_a_0x35;
+ u32 path_b_0xdf, path_b_0x35;
+ bool path_a_ok, path_b_ok;
+ u8 rfe = priv->rfe_type;
+ u32 rfe_path_select;
+ int result[4][8]; /* last is final result */
+ int i, candidate;
+ s32 reg_tmp = 0;
+ bool simu;
+ u32 val32;
+
+ rfe_path_select = rtl8xxxu_read32(priv, REG_RFE_PATH_SELECT);
+
+ path_a_0xdf = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA);
+ path_a_0x35 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_P1);
+ path_b_0xdf = rtl8xxxu_read_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA);
+ path_b_0x35 = rtl8xxxu_read_rfreg(priv, RF_B, RF6052_REG_GAIN_P1);
+
+ memset(result, 0, sizeof(result));
+ candidate = -1;
+
+ path_a_ok = false;
+ path_b_ok = false;
+
+ for (i = 0; i < 3; i++) {
+ rtl8192fu_phy_iqcalibrate(priv, result, i);
+
+ if (i == 1) {
+ simu = rtl8xxxu_gen2_simularity_compare(priv, result, 0, 1);
+ if (simu) {
+ candidate = 0;
+ break;
+ }
+ }
+
+ if (i == 2) {
+ simu = rtl8xxxu_gen2_simularity_compare(priv, result, 0, 2);
+ if (simu) {
+ candidate = 0;
+ break;
+ }
+
+ simu = rtl8xxxu_gen2_simularity_compare(priv, result, 1, 2);
+ if (simu) {
+ candidate = 1;
+ } else {
+ for (i = 0; i < 8; i++)
+ reg_tmp += result[3][i];
+
+ if (reg_tmp)
+ candidate = 3;
+ else
+ candidate = -1;
+ }
+ }
+ }
+
+ if (candidate >= 0) {
+ reg_e94 = result[candidate][0];
+ reg_e9c = result[candidate][1];
+ reg_ea4 = result[candidate][2];
+ reg_eac = result[candidate][3];
+ reg_eb4 = result[candidate][4];
+ reg_ebc = result[candidate][5];
+ reg_ec4 = result[candidate][6];
+ reg_ecc = result[candidate][7];
+
+ dev_dbg(dev, "%s: candidate is %x\n", __func__, candidate);
+ dev_dbg(dev, "%s: e94=%x e9c=%x ea4=%x eac=%x eb4=%x ebc=%x ec4=%x ecc=%c\n",
+ __func__, reg_e94, reg_e9c, reg_ea4, reg_eac,
+ reg_eb4, reg_ebc, reg_ec4, reg_ecc);
+
+ path_a_ok = true;
+ path_b_ok = true;
+ }
+
+ rtl8xxxu_write32_mask(priv, REG_TX_IQK_TONE_A, 0x3ff00000, 0x100);
+ rtl8xxxu_write32_mask(priv, REG_NP_ANTA, 0x3ff, 0);
+ rtl8xxxu_write32_mask(priv, REG_TX_IQK_TONE_B, 0x3ff00000, 0x100);
+ rtl8xxxu_write32_mask(priv, REG_TAP_UPD_97F, 0x3ff, 0);
+
+ if (candidate >= 0) {
+ if (reg_e94)
+ rtl8xxxu_fill_iqk_matrix_a(priv, path_a_ok, result,
+ candidate, (reg_ea4 == 0));
+
+ if (reg_eb4)
+ rtl8xxxu_fill_iqk_matrix_b(priv, path_b_ok, result,
+ candidate, (reg_ec4 == 0));
+ }
+
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, path_a_0xdf);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_P1, path_a_0x35);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, path_b_0xdf);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_P1, path_b_0x35);
+
+ if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12) {
+ rtl8xxxu_write32_set(priv, REG_SW_GPIO_SHARE_CTRL_1, 0x70000);
+ rtl8xxxu_write32_clear(priv, REG_LEDCFG0, 0x6c00000);
+ rtl8xxxu_write32_set(priv, REG_PAD_CTRL1, BIT(29) | BIT(28));
+ rtl8xxxu_write32_clear(priv, REG_SW_GPIO_SHARE_CTRL_0,
+ 0x600000 | BIT(4));
+
+ /*
+ * Originally:
+ * odm_set_bb_reg(dm, R_0x944, BIT(11) | 0x1F, 0x3F);
+ *
+ * It clears bit 11 and sets bits 0..4. The mask doesn't cover
+ * bit 5 so it's not modified. Is that what it's supposed to
+ * accomplish?
+ */
+ val32 = rtl8xxxu_read32(priv, REG_RFE_BUFFER);
+ val32 &= ~BIT(11);
+ val32 |= 0x1f;
+ rtl8xxxu_write32(priv, REG_RFE_BUFFER, val32);
+
+ if (rfe == 7) {
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC,
+ 0xfffff, 0x23200);
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC2,
+ 0xfffff, 0x23200);
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC1,
+ 0xf000, 0x3);
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC3,
+ 0xf000, 0x3);
+ } else {
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC,
+ 0xfffff, 0x22200);
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC2,
+ 0xfffff, 0x22200);
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC1,
+ 0xf000, 0x2);
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC3,
+ 0xf000, 0x2);
+ }
+
+ rtl8xxxu_write32_clear(priv, REG_RFE_OPT62, BIT(2));
+
+ if (rfe == 7)
+ rtl8xxxu_write32(priv, REG_RFE_OPT, 0x03000003);
+
+ rtl8xxxu_write32(priv, REG_RFE_PATH_SELECT, rfe_path_select);
+ }
+}
+
+static void rtl8192fu_disabled_to_emu(struct rtl8xxxu_priv *priv)
+{
+ rtl8xxxu_write16_clear(priv, REG_APS_FSMCO,
+ APS_FSMCO_HW_POWERDOWN | APS_FSMCO_HW_SUSPEND);
+
+ rtl8xxxu_write32_clear(priv, REG_GPIO_INTM, BIT(16));
+
+ rtl8xxxu_write16_clear(priv, REG_APS_FSMCO,
+ APS_FSMCO_PCIE | APS_FSMCO_HW_SUSPEND);
+}
+
+static int rtl8192fu_emu_to_active(struct rtl8xxxu_priv *priv)
+{
+ u32 val32;
+ u16 val16;
+ int count;
+
+ /* enable LDOA12 MACRO block for all interface */
+ rtl8xxxu_write8_set(priv, REG_LDOA15_CTRL, LDOA15_ENABLE);
+
+ /* disable BT_GPS_SEL pins */
+ rtl8xxxu_write32_clear(priv, REG_PAD_CTRL1, BIT(28));
+
+ mdelay(1);
+
+ /* release analog Ips to digital */
+ rtl8xxxu_write8_clear(priv, REG_SYS_ISO_CTRL, SYS_ISO_ANALOG_IPS);
+
+ val16 = APS_FSMCO_PCIE | APS_FSMCO_HW_SUSPEND | APS_FSMCO_SW_LPS;
+ rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, val16);
+
+ /* wait till 0x04[17] = 1 power ready */
+ for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
+ val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
+ if (val32 & BIT(17))
+ break;
+
+ udelay(10);
+ }
+
+ if (!count)
+ return -EBUSY;
+
+ rtl8xxxu_write32_set(priv, REG_APS_FSMCO, APS_FSMCO_WLON_RESET);
+
+ for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
+ val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
+ if ((val32 & (APS_FSMCO_MAC_ENABLE | APS_FSMCO_MAC_OFF)) == 0)
+ break;
+
+ udelay(10);
+ }
+
+ if (!count)
+ return -EBUSY;
+
+ /* SWR OCP enable */
+ rtl8xxxu_write32_set(priv, REG_AFE_MISC, BIT(18));
+
+ rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, APS_FSMCO_HW_POWERDOWN);
+
+ rtl8xxxu_write16_clear(priv, REG_APS_FSMCO,
+ APS_FSMCO_PCIE | APS_FSMCO_HW_SUSPEND);
+
+ /* 0x7c[31]=1, LDO has max output capability */
+ rtl8xxxu_write32_set(priv, REG_LDO_SW_CTRL, BIT(31));
+
+ rtl8xxxu_write16_set(priv, REG_APS_FSMCO, APS_FSMCO_MAC_ENABLE);
+
+ for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
+ val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
+ if ((val32 & APS_FSMCO_MAC_ENABLE) == 0)
+ break;
+
+ udelay(10);
+ }
+
+ if (!count)
+ return -EBUSY;
+
+ /* Enable WL control XTAL setting */
+ rtl8xxxu_write8_set(priv, REG_AFE_MISC, AFE_MISC_WL_XTAL_CTRL);
+
+ /* Enable falling edge triggering interrupt */
+ rtl8xxxu_write16_set(priv, REG_GPIO_INTM, GPIO_INTM_EDGE_TRIG_IRQ);
+
+ /* Enable GPIO9 data mode */
+ rtl8xxxu_write16_clear(priv, REG_GPIO_IO_SEL_2, GPIO_IO_SEL_2_GPIO09_IRQ);
+
+ /* Enable GPIO9 input mode */
+ rtl8xxxu_write16_clear(priv, REG_GPIO_IO_SEL_2, GPIO_IO_SEL_2_GPIO09_INPUT);
+
+ /* Enable HSISR GPIO[C:0] interrupt */
+ rtl8xxxu_write8_set(priv, REG_HSIMR, BIT(0));
+
+ /* RF HW ON/OFF Enable */
+ rtl8xxxu_write8_clear(priv, REG_MULTI_FUNC_CTRL, MULTI_WIFI_HW_ROF_EN);
+
+ /* Register Lock Disable */
+ rtl8xxxu_write8_set(priv, REG_RSV_CTRL, BIT(7));
+
+ /* For GPIO9 internal pull high setting */
+ rtl8xxxu_write16_set(priv, REG_MULTI_FUNC_CTRL, BIT(14));
+
+ /* reset RF path S1 */
+ rtl8xxxu_write8(priv, REG_RF_CTRL, 0);
+
+ /* reset RF path S0 */
+ rtl8xxxu_write8(priv, REG_AFE_CTRL4 + 3, 0);
+
+ /* enable RF path S1 */
+ rtl8xxxu_write8(priv, REG_RF_CTRL, RF_SDMRSTB | RF_RSTB | RF_ENABLE);
+
+ /* enable RF path S0 */
+ rtl8xxxu_write8(priv, REG_AFE_CTRL4 + 3, RF_SDMRSTB | RF_RSTB | RF_ENABLE);
+
+ /* AFE_Ctrl */
+ rtl8xxxu_write8_set(priv, REG_RSVD_1, BIT(5));
+
+ /* AFE_Ctrl */
+ rtl8xxxu_write8(priv, REG_RSVD_4, 0xcc);
+
+ /* AFE_Ctrl 0x24[4:3]=00 for xtal gmn */
+ rtl8xxxu_write8_clear(priv, REG_AFE_XTAL_CTRL, BIT(4) | BIT(3));
+
+ /* GPIO_A[31:0] Pull down software register */
+ rtl8xxxu_write32(priv, REG_GPIO_A0, 0xffffffff);
+
+ /* GPIO_B[7:0] Pull down software register */
+ rtl8xxxu_write8(priv, REG_GPIO_B0, 0xff);
+
+ /* Register Lock Enable */
+ rtl8xxxu_write8_clear(priv, REG_RSV_CTRL, BIT(7));
+
+ return 0;
+}
+
+static int rtl8192fu_active_to_emu(struct rtl8xxxu_priv *priv)
+{
+ u32 val32;
+ int count;
+
+ /* Reset BB, RF enter Power Down mode */
+ rtl8xxxu_write8_clear(priv, REG_SYS_FUNC, SYS_FUNC_BBRSTB);
+
+ /* Enable rising edge triggering interrupt */
+ rtl8xxxu_write16_clear(priv, REG_GPIO_INTM, GPIO_INTM_EDGE_TRIG_IRQ);
+
+ /* release WLON reset */
+ rtl8xxxu_write32_set(priv, REG_APS_FSMCO, APS_FSMCO_WLON_RESET);
+
+ /* turn off MAC by HW state machine */
+ rtl8xxxu_write16_set(priv, REG_APS_FSMCO, APS_FSMCO_MAC_OFF);
+
+ for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
+ val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
+ if ((val32 & APS_FSMCO_MAC_OFF) == 0)
+ break;
+
+ udelay(10);
+ }
+
+ if (!count)
+ return -EBUSY;
+
+ /* analog Ips to digital, 1:isolation */
+ rtl8xxxu_write8_set(priv, REG_SYS_ISO_CTRL, SYS_ISO_ANALOG_IPS);
+
+ /* disable LDOA12 MACRO block */
+ rtl8xxxu_write8_clear(priv, REG_LDOA15_CTRL, LDOA15_ENABLE);
+
+ return 0;
+}
+
+static int rtl8192fu_emu_to_disabled(struct rtl8xxxu_priv *priv)
+{
+ u16 val16;
+
+ /* SOP option to disable BG/MB */
+ rtl8xxxu_write8(priv, REG_APS_FSMCO + 3, 0x20);
+
+ /* 0x04[12:11] = 2b'01 enable WL suspend */
+ val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO);
+ val16 &= ~APS_FSMCO_PCIE;
+ val16 |= APS_FSMCO_HW_SUSPEND;
+ rtl8xxxu_write16(priv, REG_APS_FSMCO, val16);
+
+ /* enable GPIO9 as EXT WAKEUP */
+ rtl8xxxu_write32_set(priv, REG_GPIO_INTM, BIT(16));
+
+ return 0;
+}
+
+static int rtl8192fu_active_to_lps(struct rtl8xxxu_priv *priv)
+{
+ struct device *dev = &priv->udev->dev;
+ u16 val16;
+ u32 val32;
+ int retry;
+
+ /* Tx Pause */
+ rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff);
+
+ retry = 100;
+
+ /* Poll 32 bit wide REG_SCH_TX_CMD for 0 to ensure no TX is pending. */
+ do {
+ val32 = rtl8xxxu_read32(priv, REG_SCH_TX_CMD);
+ if (!val32)
+ break;
+
+ udelay(10);
+ } while (retry--);
+
+ if (!retry) {
+ dev_warn(dev, "%s: Failed to flush TX queue\n", __func__);
+ return -EBUSY;
+ }
+
+ /* Disable CCK and OFDM, clock gated */
+ rtl8xxxu_write8_clear(priv, REG_SYS_FUNC, SYS_FUNC_BBRSTB);
+
+ udelay(2);
+
+ /* Whole BB is reset */
+ rtl8xxxu_write8_clear(priv, REG_SYS_FUNC, SYS_FUNC_BB_GLB_RSTN);
+
+ /* Reset MAC TRX */
+ val16 = rtl8xxxu_read16(priv, REG_CR);
+ val16 &= 0xff00;
+ val16 |= CR_HCI_RXDMA_ENABLE | CR_HCI_TXDMA_ENABLE;
+ val16 &= ~CR_SECURITY_ENABLE;
+ rtl8xxxu_write16(priv, REG_CR, val16);
+
+ /* Respond TxOK to scheduler */
+ rtl8xxxu_write8_set(priv, REG_DUAL_TSF_RST, DUAL_TSF_TX_OK);
+
+ return 0;
+}
+
+static int rtl8192fu_power_on(struct rtl8xxxu_priv *priv)
+{
+ u16 val16;
+ int ret;
+
+ rtl8xxxu_write8(priv, REG_USB_ACCESS_TIMEOUT, 0x80);
+
+ rtl8192fu_disabled_to_emu(priv);
+
+ ret = rtl8192fu_emu_to_active(priv);
+ if (ret)
+ return ret;
+
+ rtl8xxxu_write16(priv, REG_CR, 0);
+
+ val16 = rtl8xxxu_read16(priv, REG_CR);
+
+ val16 |= CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE |
+ CR_TXDMA_ENABLE | CR_RXDMA_ENABLE |
+ CR_PROTOCOL_ENABLE | CR_SCHEDULE_ENABLE |
+ CR_SECURITY_ENABLE | CR_CALTIMER_ENABLE;
+ rtl8xxxu_write16(priv, REG_CR, val16);
+
+ return 0;
+}
+
+static void rtl8192fu_power_off(struct rtl8xxxu_priv *priv)
+{
+ rtl8xxxu_flush_fifo(priv);
+
+ /* Stop Tx Report Timer. 0x4EC[Bit1]=b'0 */
+ rtl8xxxu_write8_clear(priv, REG_TX_REPORT_CTRL,
+ TX_REPORT_CTRL_TIMER_ENABLE);
+
+ /* stop rx */
+ rtl8xxxu_write8(priv, REG_CR, 0x00);
+
+ rtl8192fu_active_to_lps(priv);
+
+ /* Reset Firmware if running in RAM */
+ if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_RAM_SEL)
+ rtl8xxxu_firmware_self_reset(priv);
+
+ /* Reset MCU */
+ rtl8xxxu_write16_clear(priv, REG_SYS_FUNC, SYS_FUNC_CPU_ENABLE);
+
+ /* Reset MCU ready status */
+ rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00);
+
+ rtl8192fu_active_to_emu(priv);
+ rtl8192fu_emu_to_disabled(priv);
+}
+
+static void rtl8192f_reset_8051(struct rtl8xxxu_priv *priv)
+{
+ rtl8xxxu_write8_clear(priv, REG_RSV_CTRL, BIT(1));
+
+ rtl8xxxu_write8_clear(priv, REG_RSV_CTRL + 1, BIT(0));
+
+ rtl8xxxu_write16_clear(priv, REG_SYS_FUNC, SYS_FUNC_CPU_ENABLE);
+
+ rtl8xxxu_write8_clear(priv, REG_RSV_CTRL, BIT(1));
+
+ rtl8xxxu_write8_set(priv, REG_RSV_CTRL + 1, BIT(0));
+
+ rtl8xxxu_write16_set(priv, REG_SYS_FUNC, SYS_FUNC_CPU_ENABLE);
+}
+
+static void rtl8192f_enable_rf(struct rtl8xxxu_priv *priv)
+{
+ u32 val32;
+
+ rtl8xxxu_write8(priv, REG_RF_CTRL, RF_ENABLE | RF_RSTB | RF_SDMRSTB);
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE);
+ val32 &= ~(OFDM_RF_PATH_RX_MASK | OFDM_RF_PATH_TX_MASK);
+ val32 |= OFDM_RF_PATH_RX_A | OFDM_RF_PATH_RX_B |
+ OFDM_RF_PATH_TX_A | OFDM_RF_PATH_TX_B;
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32);
+
+ rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00);
+}
+
+static void rtl8192f_disable_rf(struct rtl8xxxu_priv *priv)
+{
+ u32 val32;
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE);
+ val32 &= ~OFDM_RF_PATH_TX_MASK;
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32);
+
+ /* Power down RF module */
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, 0);
+}
+
+static void rtl8192f_usb_quirks(struct rtl8xxxu_priv *priv)
+{
+ u16 val16;
+
+ rtl8xxxu_gen2_usb_quirks(priv);
+
+ val16 = rtl8xxxu_read16(priv, REG_CR);
+ val16 |= (CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE);
+ rtl8xxxu_write16(priv, REG_CR, val16);
+}
+
+#define XTAL1 GENMASK(6, 1)
+#define XTAL0 GENMASK(30, 25)
+
+static void rtl8192f_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap)
+{
+ struct rtl8xxxu_cfo_tracking *cfo = &priv->cfo_tracking;
+ u32 xtal1, xtal0;
+
+ if (crystal_cap == cfo->crystal_cap)
+ return;
+
+ xtal1 = rtl8xxxu_read32(priv, REG_AFE_PLL_CTRL);
+ xtal0 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL);
+
+ dev_dbg(&priv->udev->dev,
+ "%s: Adjusting crystal cap from 0x%x (actually 0x%x 0x%x) to 0x%x\n",
+ __func__,
+ cfo->crystal_cap,
+ u32_get_bits(xtal1, XTAL1),
+ u32_get_bits(xtal0, XTAL0),
+ crystal_cap);
+
+ u32p_replace_bits(&xtal1, crystal_cap, XTAL1);
+ u32p_replace_bits(&xtal0, crystal_cap, XTAL0);
+ rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, xtal1);
+ rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, xtal0);
+
+ cfo->crystal_cap = crystal_cap;
+}
+
+static s8 rtl8192f_cck_rssi(struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats)
+{
+ struct jaguar2_phy_stats_type0 *phy_stats0 = (struct jaguar2_phy_stats_type0 *)phy_stats;
+ u8 lna_idx = (phy_stats0->lna_h << 3) | phy_stats0->lna_l;
+ u8 vga_idx = phy_stats0->vga;
+ s8 rx_pwr_all;
+
+ switch (lna_idx) {
+ case 7:
+ rx_pwr_all = -44 - (2 * vga_idx);
+ break;
+ case 5:
+ rx_pwr_all = -28 - (2 * vga_idx);
+ break;
+ case 3:
+ rx_pwr_all = -10 - (2 * vga_idx);
+ break;
+ case 0:
+ rx_pwr_all = 14 - (2 * vga_idx);
+ break;
+ default:
+ rx_pwr_all = 0;
+ break;
+ }
+
+ return rx_pwr_all;
+}
+
+static int rtl8192fu_led_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ struct rtl8xxxu_priv *priv = container_of(led_cdev,
+ struct rtl8xxxu_priv,
+ led_cdev);
+ u16 ledcfg;
+
+ /* Values obtained by observing the USB traffic from the Windows driver. */
+ rtl8xxxu_write32(priv, REG_SW_GPIO_SHARE_CTRL_0, 0x20080);
+ rtl8xxxu_write32(priv, REG_SW_GPIO_SHARE_CTRL_1, 0x1b0000);
+
+ ledcfg = rtl8xxxu_read16(priv, REG_LEDCFG0);
+
+ if (brightness == LED_OFF) {
+ /* Value obtained like above. */
+ ledcfg = BIT(1) | BIT(7);
+ } else if (brightness == LED_ON) {
+ /* Value obtained like above. */
+ ledcfg = BIT(1) | BIT(7) | BIT(11);
+ } else if (brightness == RTL8XXXU_HW_LED_CONTROL) {
+ /* Value obtained by brute force. */
+ ledcfg = BIT(8) | BIT(9);
+ }
+
+ rtl8xxxu_write16(priv, REG_LEDCFG0, ledcfg);
+
+ return 0;
+}
+
+struct rtl8xxxu_fileops rtl8192fu_fops = {
+ .identify_chip = rtl8192fu_identify_chip,
+ .parse_efuse = rtl8192fu_parse_efuse,
+ .load_firmware = rtl8192fu_load_firmware,
+ .power_on = rtl8192fu_power_on,
+ .power_off = rtl8192fu_power_off,
+ .read_efuse = rtl8xxxu_read_efuse,
+ .reset_8051 = rtl8192f_reset_8051,
+ .llt_init = rtl8xxxu_auto_llt_table,
+ .init_phy_bb = rtl8192fu_init_phy_bb,
+ .init_phy_rf = rtl8192fu_init_phy_rf,
+ .phy_lc_calibrate = rtl8192f_phy_lc_calibrate,
+ .phy_iq_calibrate = rtl8192fu_phy_iq_calibrate,
+ .config_channel = rtl8192fu_config_channel,
+ .parse_rx_desc = rtl8xxxu_parse_rxdesc24,
+ .parse_phystats = jaguar2_rx_parse_phystats,
+ .init_aggregation = rtl8192fu_init_aggregation,
+ .init_burst = rtl8xxxu_init_burst,
+ .enable_rf = rtl8192f_enable_rf,
+ .disable_rf = rtl8192f_disable_rf,
+ .usb_quirks = rtl8192f_usb_quirks,
+ .set_tx_power = rtl8192f_set_tx_power,
+ .update_rate_mask = rtl8xxxu_gen2_update_rate_mask,
+ .report_connect = rtl8xxxu_gen2_report_connect,
+ .report_rssi = rtl8xxxu_gen2_report_rssi,
+ .fill_txdesc = rtl8xxxu_fill_txdesc_v2,
+ .set_crystal_cap = rtl8192f_set_crystal_cap,
+ .cck_rssi = rtl8192f_cck_rssi,
+ .led_classdev_brightness_set = rtl8192fu_led_brightness_set,
+ .writeN_block_size = 254,
+ .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24),
+ .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40),
+ .has_tx_report = 1,
+ .gen2_thermal_meter = 1,
+ .needs_full_init = 1,
+ .init_reg_rxfltmap = 1,
+ .init_reg_pkt_life_time = 1,
+ .init_reg_hmtfr = 1,
+ .ampdu_max_time = 0x5e,
+ .ustime_tsf_edca = 0x50,
+ .max_aggr_num = 0x1f1f,
+ .trxff_boundary = 0x3f3f,
+ .pbp_rx = PBP_PAGE_SIZE_256,
+ .pbp_tx = PBP_PAGE_SIZE_256,
+ .mactable = rtl8192f_mac_init_table,
+ .total_page_num = TX_TOTAL_PAGE_NUM_8192F,
+ .page_num_hi = TX_PAGE_NUM_HI_PQ_8192F,
+ .page_num_lo = TX_PAGE_NUM_LO_PQ_8192F,
+ .page_num_norm = TX_PAGE_NUM_NORM_PQ_8192F,
+};
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c
index 22d4704dd31e..f0d17b75c5f1 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c
@@ -1031,12 +1031,12 @@ static int rtl8710bu_iqk_path_a(struct rtl8xxxu_priv *priv, u32 *lok_result)
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0x07ff7);
/* PA,PAD gain adjust */
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA);
val32 |= BIT(11);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32);
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_PAD_TXG);
u32p_replace_bits(&val32, 0x1ed, 0x00fff);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, val32);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, val32);
/* enter IQK mode */
val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
@@ -1068,9 +1068,9 @@ static int rtl8710bu_iqk_path_a(struct rtl8xxxu_priv *priv, u32 *lok_result)
u32p_replace_bits(&val32, 0, 0xffffff00);
rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA);
val32 &= ~BIT(11);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32);
/* save LOK result */
*lok_result = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC);
@@ -1113,12 +1113,12 @@ static int rtl8710bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result)
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf1173);
/* PA,PAD gain adjust */
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA);
val32 |= BIT(11);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32);
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_PAD_TXG);
u32p_replace_bits(&val32, 0xf, 0x003e0);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, val32);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, val32);
/*
* Enter IQK mode
@@ -1170,9 +1170,9 @@ static int rtl8710bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result)
u32p_replace_bits(&val32, 0, 0xffffff00);
rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA);
val32 &= ~BIT(11);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32);
return result;
}
@@ -1197,12 +1197,12 @@ static int rtl8710bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result)
/*
* PA, PAD setting
*/
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA);
val32 |= BIT(11);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32);
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_PAD_TXG);
u32p_replace_bits(&val32, 0x2a, 0x00fff);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, val32);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, val32);
/*
* Enter IQK mode
@@ -1241,9 +1241,9 @@ static int rtl8710bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result)
u32p_replace_bits(&val32, 0, 0xffffff00);
rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA);
val32 &= ~BIT(11);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32);
/* reload LOK value */
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC, lok_result);
@@ -1874,6 +1874,7 @@ struct rtl8xxxu_fileops rtl8710bu_fops = {
* but in rtl8xxxu 0x50 causes slow upload and random packet loss. Why?
*/
.ustime_tsf_edca = 0x28,
+ .max_aggr_num = 0x0c14,
.adda_1t_init = 0x03c00016,
.adda_1t_path_on = 0x03c00016,
.trxff_boundary = 0x3f7f,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
index abc56c7de6f7..13ad5d5b73f4 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
@@ -824,7 +824,7 @@ static int rtl8723bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
/*
* PA, PAD setting
*/
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0xf80);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0xf80);
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_55, 0x4021f);
/*
@@ -888,7 +888,7 @@ static int rtl8723bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x780);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x780);
val32 = (reg_eac >> 16) & 0x3ff;
if (val32 & 0x200)
@@ -1741,6 +1741,7 @@ struct rtl8xxxu_fileops rtl8723bu_fops = {
.init_reg_hmtfr = 1,
.ampdu_max_time = 0x5e,
.ustime_tsf_edca = 0x50,
+ .max_aggr_num = 0x0c14,
.adda_1t_init = 0x01c00014,
.adda_1t_path_on = 0x01c00014,
.adda_2t_path_on_a = 0x01c00014,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index 831639d73657..5d102a1246a3 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -56,6 +56,7 @@ MODULE_FIRMWARE("rtlwifi/rtl8723bu_bt.bin");
MODULE_FIRMWARE("rtlwifi/rtl8188fufw.bin");
MODULE_FIRMWARE("rtlwifi/rtl8710bufw_SMIC.bin");
MODULE_FIRMWARE("rtlwifi/rtl8710bufw_UMC.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8192fufw.bin");
module_param_named(debug, rtl8xxxu_debug, int, 0600);
MODULE_PARM_DESC(debug, "Set debug mask");
@@ -642,7 +643,7 @@ const u32 rtl8xxxu_iqk_phy_iq_bb_reg[RTL8XXXU_BB_REGS] = {
REG_OFDM0_XA_RX_IQ_IMBALANCE,
REG_OFDM0_XB_RX_IQ_IMBALANCE,
REG_OFDM0_ENERGY_CCA_THRES,
- REG_OFDM0_AGCR_SSI_TABLE,
+ REG_OFDM0_AGC_RSSI_TABLE,
REG_OFDM0_XA_TX_IQ_IMBALANCE,
REG_OFDM0_XB_TX_IQ_IMBALANCE,
REG_OFDM0_XC_TX_AFE,
@@ -1185,6 +1186,20 @@ static void rtl8xxxu_stop_tx_beacon(struct rtl8xxxu_priv *priv)
rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 2, val8);
}
+static void rtl8xxxu_start_tx_beacon(struct rtl8xxxu_priv *priv)
+{
+ u8 val8;
+
+ val8 = rtl8xxxu_read8(priv, REG_FWHW_TXQ_CTRL + 2);
+ val8 |= EN_BCNQ_DL >> 16;
+ rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL + 2, val8);
+
+ rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 1, 0x80);
+ val8 = rtl8xxxu_read8(priv, REG_TBTT_PROHIBIT + 2);
+ val8 &= 0xF0;
+ rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 2, val8);
+}
+
/*
* The rtl8723a has 3 channel groups for it's efuse settings. It only
@@ -2006,12 +2021,18 @@ exit:
static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv)
{
int pages, remainder, i, ret;
+ u16 reg_fw_start_address;
u16 reg_mcu_fw_dl;
u8 val8;
u16 val16;
u32 val32;
u8 *fwptr;
+ if (priv->rtl_chip == RTL8192F)
+ reg_fw_start_address = REG_FW_START_ADDRESS_8192F;
+ else
+ reg_fw_start_address = REG_FW_START_ADDRESS;
+
if (priv->rtl_chip == RTL8710B) {
reg_mcu_fw_dl = REG_8051FW_CTRL_V1_8710B;
} else {
@@ -2067,7 +2088,7 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv)
val8 |= i;
rtl8xxxu_write8(priv, reg_mcu_fw_dl + 2, val8);
- ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS,
+ ret = rtl8xxxu_writeN(priv, reg_fw_start_address,
fwptr, RTL_FW_PAGE_SIZE);
if (ret != RTL_FW_PAGE_SIZE) {
ret = -EAGAIN;
@@ -2081,7 +2102,7 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv)
val8 = rtl8xxxu_read8(priv, reg_mcu_fw_dl + 2) & 0xF8;
val8 |= i;
rtl8xxxu_write8(priv, reg_mcu_fw_dl + 2, val8);
- ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS,
+ ret = rtl8xxxu_writeN(priv, reg_fw_start_address,
fwptr, remainder);
if (ret != remainder) {
ret = -EAGAIN;
@@ -2135,6 +2156,7 @@ int rtl8xxxu_load_firmware(struct rtl8xxxu_priv *priv, const char *fw_name)
case 0x2300:
case 0x88f0:
case 0x10b0:
+ case 0x92f0:
break;
default:
ret = -EINVAL;
@@ -2581,6 +2603,7 @@ static int rtl8xxxu_init_queue_priority(struct rtl8xxxu_priv *priv)
u16 hiq, mgq, bkq, beq, viq, voq;
int hip, mgp, bkp, bep, vip, vop;
int ret = 0;
+ u32 val32;
switch (priv->ep_tx_count) {
case 1:
@@ -2663,15 +2686,28 @@ static int rtl8xxxu_init_queue_priority(struct rtl8xxxu_priv *priv)
* queue here .... why?
*/
if (!ret) {
- val16 = rtl8xxxu_read16(priv, REG_TRXDMA_CTRL);
- val16 &= 0x7;
- val16 |= (voq << TRXDMA_CTRL_VOQ_SHIFT) |
- (viq << TRXDMA_CTRL_VIQ_SHIFT) |
- (beq << TRXDMA_CTRL_BEQ_SHIFT) |
- (bkq << TRXDMA_CTRL_BKQ_SHIFT) |
- (mgq << TRXDMA_CTRL_MGQ_SHIFT) |
- (hiq << TRXDMA_CTRL_HIQ_SHIFT);
- rtl8xxxu_write16(priv, REG_TRXDMA_CTRL, val16);
+ /* Only RTL8192F seems to do it like this. */
+ if (priv->rtl_chip == RTL8192F) {
+ val32 = rtl8xxxu_read32(priv, REG_TRXDMA_CTRL);
+ val32 &= 0x7;
+ val32 |= (voq << TRXDMA_CTRL_VOQ_SHIFT_8192F) |
+ (viq << TRXDMA_CTRL_VIQ_SHIFT_8192F) |
+ (beq << TRXDMA_CTRL_BEQ_SHIFT_8192F) |
+ (bkq << TRXDMA_CTRL_BKQ_SHIFT_8192F) |
+ (mgq << TRXDMA_CTRL_MGQ_SHIFT_8192F) |
+ (hiq << TRXDMA_CTRL_HIQ_SHIFT_8192F);
+ rtl8xxxu_write32(priv, REG_TRXDMA_CTRL, val32);
+ } else {
+ val16 = rtl8xxxu_read16(priv, REG_TRXDMA_CTRL);
+ val16 &= 0x7;
+ val16 |= (voq << TRXDMA_CTRL_VOQ_SHIFT) |
+ (viq << TRXDMA_CTRL_VIQ_SHIFT) |
+ (beq << TRXDMA_CTRL_BEQ_SHIFT) |
+ (bkq << TRXDMA_CTRL_BKQ_SHIFT) |
+ (mgq << TRXDMA_CTRL_MGQ_SHIFT) |
+ (hiq << TRXDMA_CTRL_HIQ_SHIFT);
+ rtl8xxxu_write16(priv, REG_TRXDMA_CTRL, val16);
+ }
priv->pipe_out[TXDESC_QUEUE_VO] =
usb_sndbulkpipe(priv->udev, priv->out_ep[vop]);
@@ -2842,10 +2878,14 @@ void rtl8xxxu_fill_iqk_matrix_b(struct rtl8xxxu_priv *priv, bool iqk_ok,
reg = (result[candidate][7] >> 6) & 0xf;
- val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGCR_SSI_TABLE);
- val32 &= ~0x0000f000;
- val32 |= (reg << 12);
- rtl8xxxu_write32(priv, REG_OFDM0_AGCR_SSI_TABLE, val32);
+ if (priv->rtl_chip == RTL8192F) {
+ rtl8xxxu_write32_mask(priv, REG_RXIQB_EXT, 0x000000f0, reg);
+ } else {
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGC_RSSI_TABLE);
+ val32 &= ~0x0000f000;
+ val32 |= (reg << 12);
+ rtl8xxxu_write32(priv, REG_OFDM0_AGC_RSSI_TABLE, val32);
+ }
}
#define MAX_TOLERANCE 5
@@ -3944,13 +3984,14 @@ void rtl8xxxu_init_burst(struct rtl8xxxu_priv *priv)
val8 |= HT_SINGLE_AMPDU_ENABLE;
rtl8xxxu_write8(priv, REG_HT_SINGLE_AMPDU_8723B, val8);
- rtl8xxxu_write16(priv, REG_MAX_AGGR_NUM, 0x0c14);
+ rtl8xxxu_write16(priv, REG_MAX_AGGR_NUM, priv->fops->max_aggr_num);
rtl8xxxu_write8(priv, REG_AMPDU_MAX_TIME_8723B,
priv->fops->ampdu_max_time);
rtl8xxxu_write32(priv, REG_AGGLEN_LMT, 0xffffffff);
rtl8xxxu_write8(priv, REG_RX_PKT_LIMIT, 0x18);
rtl8xxxu_write8(priv, REG_PIFS, 0x00);
- if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B) {
+ if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B ||
+ priv->rtl_chip == RTL8192F) {
rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL, FWHW_TXQ_CTRL_AMPDU_RETRY);
rtl8xxxu_write32(priv, REG_FAST_EDCA_CTRL, 0x03086666);
}
@@ -3963,6 +4004,34 @@ void rtl8xxxu_init_burst(struct rtl8xxxu_priv *priv)
rtl8xxxu_write8(priv, REG_RSV_CTRL, val8);
}
+static u8 rtl8xxxu_acquire_macid(struct rtl8xxxu_priv *priv)
+{
+ u8 macid;
+
+ macid = find_first_zero_bit(priv->mac_id_map, RTL8XXXU_MAX_MAC_ID_NUM);
+ if (macid < RTL8XXXU_MAX_MAC_ID_NUM)
+ set_bit(macid, priv->mac_id_map);
+
+ return macid;
+}
+
+static void rtl8xxxu_release_macid(struct rtl8xxxu_priv *priv, u8 macid)
+{
+ clear_bit(macid, priv->mac_id_map);
+}
+
+static inline u8 rtl8xxxu_get_macid(struct rtl8xxxu_priv *priv,
+ struct ieee80211_sta *sta)
+{
+ struct rtl8xxxu_sta_info *sta_info;
+
+ if (!priv->vif || priv->vif->type == NL80211_IFTYPE_STATION || !sta)
+ return 0;
+
+ sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv;
+ return sta_info->macid;
+}
+
static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
{
struct rtl8xxxu_priv *priv = hw->priv;
@@ -4036,9 +4105,14 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
if (ret)
goto exit;
+ /* Mac APLL Setting */
+ if (priv->rtl_chip == RTL8192F)
+ rtl8xxxu_write16_set(priv, REG_AFE_CTRL4, BIT(4) | BIT(15));
+
/* RFSW Control - clear bit 14 ?? */
if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E &&
- priv->rtl_chip != RTL8188E && priv->rtl_chip != RTL8710B)
+ priv->rtl_chip != RTL8188E && priv->rtl_chip != RTL8710B &&
+ priv->rtl_chip != RTL8192F)
rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003);
val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW |
@@ -4052,7 +4126,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
/* 0x860[6:5]= 00 - why? - this sets antenna B */
if (priv->rtl_chip != RTL8192E && priv->rtl_chip != RTL8188E &&
- priv->rtl_chip != RTL8710B)
+ priv->rtl_chip != RTL8710B && priv->rtl_chip != RTL8192F)
rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, 0x66f60210);
if (!macpower) {
@@ -4126,7 +4200,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
rtl8xxxu_write8(priv, 0xa3, val8);
}
- if (priv->rtl_chip == RTL8710B)
+ if (priv->rtl_chip == RTL8710B || priv->rtl_chip == RTL8192F)
rtl8xxxu_write8(priv, REG_EARLY_MODE_CONTROL_8710B, 0);
}
@@ -4153,7 +4227,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
rtl8xxxu_write8(priv, REG_USB_SPECIAL_OPTION, val8);
} else if (priv->rtl_chip == RTL8710B) {
rtl8xxxu_write32(priv, REG_HIMR0_8710B, 0);
- } else {
+ } else if (priv->rtl_chip != RTL8192F) {
/*
* Enable all interrupts - not obvious USB needs to do this
*/
@@ -4242,7 +4316,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
val16 = BEACON_DISABLE_TSF_UPDATE | (BEACON_DISABLE_TSF_UPDATE << 8);
rtl8xxxu_write16(priv, REG_BEACON_CTRL, val16);
rtl8xxxu_write16(priv, REG_TBTT_PROHIBIT, 0x6404);
- if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8710B)
+ if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8710B &&
+ priv->rtl_chip != RTL8192F)
/* Firmware will control REG_DRVERLYINT when power saving is enable, */
/* so don't set this register on STA mode. */
rtl8xxxu_write8(priv, REG_DRIVER_EARLY_INT, DRIVER_EARLY_INT_TIME);
@@ -4293,7 +4368,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
/* Disable BAR - not sure if this has any effect on USB */
rtl8xxxu_write32(priv, REG_BAR_MODE_CTRL, 0x0201ffff);
- if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8188E && priv->rtl_chip != RTL8710B)
+ if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8188E &&
+ priv->rtl_chip != RTL8710B && priv->rtl_chip != RTL8192F)
rtl8xxxu_write16(priv, REG_FAST_EDCA_CTRL, 0);
if (fops->init_statistics)
@@ -4311,9 +4387,10 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
* Reset USB mode switch setting
*/
rtl8xxxu_write8(priv, REG_ACLK_MON, 0x00);
- } else if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8188E) {
+ } else if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8188E ||
+ priv->rtl_chip == RTL8192F) {
/*
- * Init GPIO settings for 8188f, 8188e
+ * Init GPIO settings for 8188f, 8188e, 8192f
*/
val8 = rtl8xxxu_read8(priv, REG_GPIO_MUXCFG);
val8 &= ~GPIO_MUXCFG_IO_SEL_ENBT;
@@ -4433,6 +4510,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
if (priv->rtl_chip == RTL8188E)
rtl8188e_ra_info_init_all(&priv->ra_info);
+ set_bit(RTL8XXXU_BC_MC_MACID, priv->mac_id_map);
+
exit:
return ret;
}
@@ -4490,6 +4569,16 @@ int rtl8xxxu_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
return 0;
}
+static int rtl8xxxu_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+ bool set)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+
+ schedule_work(&priv->update_beacon_work);
+
+ return 0;
+}
+
static void rtl8xxxu_sw_scan_start(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, const u8 *mac)
{
@@ -4513,7 +4602,8 @@ static void rtl8xxxu_sw_scan_complete(struct ieee80211_hw *hw,
}
void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv,
- u32 ramask, u8 rateid, int sgi, int txbw_40mhz)
+ u32 ramask, u8 rateid, int sgi, int txbw_40mhz,
+ u8 macid)
{
struct h2c_cmd h2c;
@@ -4533,7 +4623,8 @@ void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv,
}
void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv,
- u32 ramask, u8 rateid, int sgi, int txbw_40mhz)
+ u32 ramask, u8 rateid, int sgi, int txbw_40mhz,
+ u8 macid)
{
struct h2c_cmd h2c;
u8 bw;
@@ -4550,6 +4641,7 @@ void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv,
h2c.b_macid_cfg.ramask1 = (ramask >> 8) & 0xff;
h2c.b_macid_cfg.ramask2 = (ramask >> 16) & 0xff;
h2c.b_macid_cfg.ramask3 = (ramask >> 24) & 0xff;
+ h2c.b_macid_cfg.macid = macid;
h2c.b_macid_cfg.data1 = rateid;
if (sgi)
@@ -4563,7 +4655,7 @@ void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv,
}
void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv,
- u8 macid, bool connect)
+ u8 macid, u8 role, bool connect)
{
struct h2c_cmd h2c;
@@ -4580,7 +4672,7 @@ void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv,
}
void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv,
- u8 macid, bool connect)
+ u8 macid, u8 role, bool connect)
{
/*
* The firmware turns on the rate control when it knows it's
@@ -4596,6 +4688,9 @@ void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv,
else
h2c.media_status_rpt.parm &= ~BIT(0);
+ h2c.media_status_rpt.parm |= ((role << 4) & 0xf0);
+ h2c.media_status_rpt.macid = macid;
+
rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.media_status_rpt));
}
@@ -4912,7 +5007,8 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
priv->vif = vif;
priv->rssi_level = RTL8XXXU_RATR_STA_INIT;
- priv->fops->update_rate_mask(priv, ramask, 0, sgi, bw == RATE_INFO_BW_40);
+ priv->fops->update_rate_mask(priv, ramask, 0, sgi,
+ bw == RATE_INFO_BW_40, 0);
rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff);
@@ -4922,13 +5018,13 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
rtl8xxxu_write16(priv, REG_BCN_PSR_RPT,
0xc000 | vif->cfg.aid);
- priv->fops->report_connect(priv, 0, true);
+ priv->fops->report_connect(priv, 0, H2C_MACID_ROLE_AP, true);
} else {
val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
val8 |= BEACON_DISABLE_TSF_UPDATE;
rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8);
- priv->fops->report_connect(priv, 0, false);
+ priv->fops->report_connect(priv, 0, H2C_MACID_ROLE_AP, false);
}
}
@@ -4965,10 +5061,35 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
dev_dbg(dev, "Changed BASIC_RATES!\n");
rtl8xxxu_set_basic_rates(priv, bss_conf->basic_rates);
}
+
+ if (changed & BSS_CHANGED_BEACON_ENABLED) {
+ if (bss_conf->enable_beacon)
+ rtl8xxxu_start_tx_beacon(priv);
+ else
+ rtl8xxxu_stop_tx_beacon(priv);
+ }
+
+ if (changed & BSS_CHANGED_BEACON)
+ schedule_work(&priv->update_beacon_work);
+
error:
return;
}
+static int rtl8xxxu_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ struct device *dev = &priv->udev->dev;
+
+ dev_dbg(dev, "Start AP mode\n");
+ rtl8xxxu_set_bssid(priv, vif->bss_conf.bssid);
+ rtl8xxxu_write16(priv, REG_BCN_INTERVAL, vif->bss_conf.beacon_int);
+ priv->fops->report_connect(priv, RTL8XXXU_BC_MC_MACID, 0, true);
+
+ return 0;
+}
+
static u32 rtl8xxxu_80211_to_rtl_queue(u32 queue)
{
u32 rtlqueue;
@@ -4997,7 +5118,9 @@ static u32 rtl8xxxu_queue_select(struct ieee80211_hdr *hdr, struct sk_buff *skb)
{
u32 queue;
- if (ieee80211_is_mgmt(hdr->frame_control))
+ if (unlikely(ieee80211_is_beacon(hdr->frame_control)))
+ queue = TXDESC_QUEUE_BEACON;
+ else if (ieee80211_is_mgmt(hdr->frame_control))
queue = TXDESC_QUEUE_MGNT;
else
queue = rtl8xxxu_80211_to_rtl_queue(skb_get_queue_mapping(skb));
@@ -5160,23 +5283,16 @@ void
rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *tx_info,
struct rtl8xxxu_txdesc32 *tx_desc, bool sgi,
- bool short_preamble, bool ampdu_enable, u32 rts_rate)
+ bool short_preamble, bool ampdu_enable, u32 rts_rate,
+ u8 macid)
{
- struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info);
struct rtl8xxxu_priv *priv = hw->priv;
struct device *dev = &priv->udev->dev;
u8 *qc = ieee80211_get_qos_ctl(hdr);
u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
- u32 rate;
- u16 rate_flags = tx_info->control.rates[0].flags;
+ u32 rate = 0;
u16 seq_number;
- if (rate_flags & IEEE80211_TX_RC_MCS &&
- !ieee80211_is_mgmt(hdr->frame_control))
- rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0;
- else
- rate = tx_rate->hw_value;
-
if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX)
dev_info(dev, "%s: TX rate: %d, pkt size %u\n",
__func__, rate, le16_to_cpu(tx_desc->pkt_size));
@@ -5215,10 +5331,10 @@ rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
* rts_rate is zero if RTS/CTS or CTS to SELF are not enabled
*/
tx_desc->txdw4 |= cpu_to_le32(rts_rate << TXDESC32_RTS_RATE_SHIFT);
- if (ampdu_enable || (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS)) {
+ if (ampdu_enable || tx_info->control.use_rts) {
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_RTS_CTS_ENABLE);
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE);
- } else if (rate_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+ } else if (tx_info->control.use_cts_prot) {
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_CTS_SELF_ENABLE);
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE);
}
@@ -5232,30 +5348,25 @@ void
rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *tx_info,
struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi,
- bool short_preamble, bool ampdu_enable, u32 rts_rate)
+ bool short_preamble, bool ampdu_enable, u32 rts_rate,
+ u8 macid)
{
- struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info);
struct rtl8xxxu_priv *priv = hw->priv;
struct device *dev = &priv->udev->dev;
struct rtl8xxxu_txdesc40 *tx_desc40;
u8 *qc = ieee80211_get_qos_ctl(hdr);
u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
- u32 rate;
- u16 rate_flags = tx_info->control.rates[0].flags;
+ u32 rate = 0;
u16 seq_number;
tx_desc40 = (struct rtl8xxxu_txdesc40 *)tx_desc32;
- if (rate_flags & IEEE80211_TX_RC_MCS &&
- !ieee80211_is_mgmt(hdr->frame_control))
- rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0;
- else
- rate = tx_rate->hw_value;
-
if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX)
dev_info(dev, "%s: TX rate: %d, pkt size %u\n",
__func__, rate, le16_to_cpu(tx_desc40->pkt_size));
+ tx_desc40->txdw1 |= cpu_to_le32(macid << TXDESC40_MACID_SHIFT);
+
seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
tx_desc40->txdw4 = cpu_to_le32(rate);
@@ -5279,17 +5390,21 @@ rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
tx_desc40->txdw4 |= cpu_to_le32(TXDESC40_RETRY_LIMIT_ENABLE);
}
+ if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
+ tx_desc40->txdw8 |= cpu_to_le32(TXDESC40_HW_SEQ_ENABLE);
+
if (short_preamble)
tx_desc40->txdw5 |= cpu_to_le32(TXDESC40_SHORT_PREAMBLE);
tx_desc40->txdw4 |= cpu_to_le32(rts_rate << TXDESC40_RTS_RATE_SHIFT);
+
/*
* rts_rate is zero if RTS/CTS or CTS to SELF are not enabled
*/
- if (ampdu_enable || (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS)) {
+ if (ampdu_enable || tx_info->control.use_rts) {
tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_RTS_CTS_ENABLE);
tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_HW_RTS_ENABLE);
- } else if (rate_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+ } else if (tx_info->control.use_cts_prot) {
/*
* For some reason the vendor driver doesn't set
* TXDESC40_HW_RTS_ENABLE for CTS to SELF
@@ -5307,24 +5422,17 @@ void
rtl8xxxu_fill_txdesc_v3(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *tx_info,
struct rtl8xxxu_txdesc32 *tx_desc, bool sgi,
- bool short_preamble, bool ampdu_enable, u32 rts_rate)
+ bool short_preamble, bool ampdu_enable, u32 rts_rate,
+ u8 macid)
{
- struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info);
struct rtl8xxxu_priv *priv = hw->priv;
struct device *dev = &priv->udev->dev;
struct rtl8xxxu_ra_info *ra = &priv->ra_info;
u8 *qc = ieee80211_get_qos_ctl(hdr);
u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
- u32 rate;
- u16 rate_flags = tx_info->control.rates[0].flags;
+ u32 rate = 0;
u16 seq_number;
- if (rate_flags & IEEE80211_TX_RC_MCS &&
- !ieee80211_is_mgmt(hdr->frame_control))
- rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0;
- else
- rate = tx_rate->hw_value;
-
seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
if (ieee80211_is_data(hdr->frame_control)) {
@@ -5377,10 +5485,10 @@ rtl8xxxu_fill_txdesc_v3(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
* rts_rate is zero if RTS/CTS or CTS to SELF are not enabled
*/
tx_desc->txdw4 |= cpu_to_le32(rts_rate << TXDESC32_RTS_RATE_SHIFT);
- if (ampdu_enable || (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS)) {
+ if (ampdu_enable || tx_info->control.use_rts) {
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_RTS_CTS_ENABLE);
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE);
- } else if (rate_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+ } else if (tx_info->control.use_cts_prot) {
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_CTS_SELF_ENABLE);
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE);
}
@@ -5404,8 +5512,8 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
struct device *dev = &priv->udev->dev;
u32 queue, rts_rate;
u16 pktlen = skb->len;
- u16 rate_flag = tx_info->control.rates[0].flags;
int tx_desc_size = priv->fops->tx_desc_size;
+ u8 macid;
int ret;
bool ampdu_enable, sgi = false, short_preamble = false;
@@ -5444,8 +5552,10 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
tx_desc->pkt_size = cpu_to_le16(pktlen);
tx_desc->pkt_offset = tx_desc_size;
- tx_desc->txdw0 =
- TXDESC_OWN | TXDESC_FIRST_SEGMENT | TXDESC_LAST_SEGMENT;
+ /* These bits mean different things to the RTL8192F. */
+ if (priv->rtl_chip != RTL8192F)
+ tx_desc->txdw0 =
+ TXDESC_OWN | TXDESC_FIRST_SEGMENT | TXDESC_LAST_SEGMENT;
if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
tx_desc->txdw0 |= TXDESC_BROADMULTICAST;
@@ -5488,31 +5598,34 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
}
}
- if (rate_flag & IEEE80211_TX_RC_SHORT_GI ||
- (ieee80211_is_data_qos(hdr->frame_control) &&
- sta && sta->deflink.ht_cap.cap &
- (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20)))
+ if (ieee80211_is_data_qos(hdr->frame_control) &&
+ sta && sta->deflink.ht_cap.cap &
+ (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20))
sgi = true;
- if (rate_flag & IEEE80211_TX_RC_USE_SHORT_PREAMBLE ||
- (sta && vif && vif->bss_conf.use_short_preamble))
+ if (sta && vif && vif->bss_conf.use_short_preamble)
short_preamble = true;
- if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS)
- rts_rate = ieee80211_get_rts_cts_rate(hw, tx_info)->hw_value;
- else if (rate_flag & IEEE80211_TX_RC_USE_CTS_PROTECT)
- rts_rate = ieee80211_get_rts_cts_rate(hw, tx_info)->hw_value;
+ if (skb->len > hw->wiphy->rts_threshold)
+ tx_info->control.use_rts = true;
+
+ if (sta && vif && vif->bss_conf.use_cts_prot)
+ tx_info->control.use_cts_prot = true;
+
+ if (ampdu_enable || tx_info->control.use_rts ||
+ tx_info->control.use_cts_prot)
+ rts_rate = DESC_RATE_24M;
else
rts_rate = 0;
-
+ macid = rtl8xxxu_get_macid(priv, sta);
priv->fops->fill_txdesc(hw, hdr, tx_info, tx_desc, sgi, short_preamble,
- ampdu_enable, rts_rate);
+ ampdu_enable, rts_rate, macid);
rtl8xxxu_calc_tx_desc_csum(tx_desc);
/* avoid zero checksum make tx hang */
- if (priv->rtl_chip == RTL8710B)
+ if (priv->rtl_chip == RTL8710B || priv->rtl_chip == RTL8192F)
tx_desc->csum = ~tx_desc->csum;
usb_fill_bulk_urb(&tx_urb->urb, priv->udev, priv->pipe_out[queue],
@@ -5530,6 +5643,55 @@ error:
dev_kfree_skb(skb);
}
+static void rtl8xxxu_send_beacon_frame(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ struct sk_buff *skb = ieee80211_beacon_get(hw, vif, 0);
+ struct device *dev = &priv->udev->dev;
+ int retry;
+ u8 val8;
+
+ /* BCN_VALID, write 1 to clear, cleared by SW */
+ val8 = rtl8xxxu_read8(priv, REG_TDECTRL + 2);
+ val8 |= BIT_BCN_VALID >> 16;
+ rtl8xxxu_write8(priv, REG_TDECTRL + 2, val8);
+
+ /* SW_BCN_SEL - Port0 */
+ val8 = rtl8xxxu_read8(priv, REG_DWBCN1_CTRL_8723B + 2);
+ val8 &= ~(BIT_SW_BCN_SEL >> 16);
+ rtl8xxxu_write8(priv, REG_DWBCN1_CTRL_8723B + 2, val8);
+
+ if (skb)
+ rtl8xxxu_tx(hw, NULL, skb);
+
+ retry = 100;
+ do {
+ val8 = rtl8xxxu_read8(priv, REG_TDECTRL + 2);
+ if (val8 & (BIT_BCN_VALID >> 16))
+ break;
+ usleep_range(10, 20);
+ } while (--retry);
+
+ if (!retry)
+ dev_err(dev, "%s: Failed to read beacon valid bit\n", __func__);
+}
+
+static void rtl8xxxu_update_beacon_work_callback(struct work_struct *work)
+{
+ struct rtl8xxxu_priv *priv =
+ container_of(work, struct rtl8xxxu_priv, update_beacon_work);
+ struct ieee80211_hw *hw = priv->hw;
+ struct ieee80211_vif *vif = priv->vif;
+
+ if (!vif) {
+ WARN_ONCE(true, "no vif to update beacon\n");
+ return;
+ }
+
+ rtl8xxxu_send_beacon_frame(hw, vif);
+}
+
void rtl8723au_rx_parse_phystats(struct rtl8xxxu_priv *priv,
struct ieee80211_rx_status *rx_status,
struct rtl8723au_phy_stats *phy_stats,
@@ -6198,61 +6360,98 @@ int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb)
int rtl8xxxu_parse_rxdesc24(struct rtl8xxxu_priv *priv, struct sk_buff *skb)
{
struct ieee80211_hw *hw = priv->hw;
- struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
- struct rtl8xxxu_rxdesc24 *rx_desc =
- (struct rtl8xxxu_rxdesc24 *)skb->data;
+ struct ieee80211_rx_status *rx_status;
+ struct rtl8xxxu_rxdesc24 *rx_desc;
struct rtl8723au_phy_stats *phy_stats;
- __le32 *_rx_desc_le = (__le32 *)skb->data;
- u32 *_rx_desc = (u32 *)skb->data;
+ struct sk_buff *next_skb = NULL;
+ __le32 *_rx_desc_le;
+ u32 *_rx_desc;
int drvinfo_sz, desc_shift;
- int i;
+ int i, pkt_len, urb_len, pkt_offset;
- for (i = 0; i < (sizeof(struct rtl8xxxu_rxdesc24) / sizeof(u32)); i++)
- _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]);
+ urb_len = skb->len;
- memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
+ if (urb_len < sizeof(struct rtl8xxxu_rxdesc24)) {
+ kfree_skb(skb);
+ return RX_TYPE_ERROR;
+ }
- skb_pull(skb, sizeof(struct rtl8xxxu_rxdesc24));
+ do {
+ rx_desc = (struct rtl8xxxu_rxdesc24 *)skb->data;
+ _rx_desc_le = (__le32 *)skb->data;
+ _rx_desc = (u32 *)skb->data;
- phy_stats = (struct rtl8723au_phy_stats *)skb->data;
+ for (i = 0; i < (sizeof(struct rtl8xxxu_rxdesc24) / sizeof(u32)); i++)
+ _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]);
- drvinfo_sz = rx_desc->drvinfo_sz * 8;
- desc_shift = rx_desc->shift;
- skb_pull(skb, drvinfo_sz + desc_shift);
+ pkt_len = rx_desc->pktlen;
- if (rx_desc->rpt_sel) {
- struct device *dev = &priv->udev->dev;
- dev_dbg(dev, "%s: C2H packet\n", __func__);
- rtl8723bu_handle_c2h(priv, skb);
- return RX_TYPE_C2H;
- }
+ drvinfo_sz = rx_desc->drvinfo_sz * 8;
+ desc_shift = rx_desc->shift;
+ pkt_offset = roundup(pkt_len + drvinfo_sz + desc_shift +
+ sizeof(struct rtl8xxxu_rxdesc24), 8);
+
+ /*
+ * Only clone the skb if there's enough data at the end to
+ * at least cover the rx descriptor
+ */
+ if (urb_len >= (pkt_offset + sizeof(struct rtl8xxxu_rxdesc24)))
+ next_skb = skb_clone(skb, GFP_ATOMIC);
- if (rx_desc->phy_stats)
- priv->fops->parse_phystats(priv, rx_status, phy_stats,
- rx_desc->rxmcs, (struct ieee80211_hdr *)skb->data,
- rx_desc->crc32 || rx_desc->icverr);
+ rx_status = IEEE80211_SKB_RXCB(skb);
+ memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
- rx_status->mactime = rx_desc->tsfl;
- rx_status->flag |= RX_FLAG_MACTIME_START;
+ skb_pull(skb, sizeof(struct rtl8xxxu_rxdesc24));
- if (!rx_desc->swdec)
- rx_status->flag |= RX_FLAG_DECRYPTED;
- if (rx_desc->crc32)
- rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
- if (rx_desc->bw)
- rx_status->bw = RATE_INFO_BW_40;
+ phy_stats = (struct rtl8723au_phy_stats *)skb->data;
- if (rx_desc->rxmcs >= DESC_RATE_MCS0) {
- rx_status->encoding = RX_ENC_HT;
- rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0;
- } else {
- rx_status->rate_idx = rx_desc->rxmcs;
- }
+ skb_pull(skb, drvinfo_sz + desc_shift);
- rx_status->freq = hw->conf.chandef.chan->center_freq;
- rx_status->band = hw->conf.chandef.chan->band;
+ skb_trim(skb, pkt_len);
+
+ if (rx_desc->rpt_sel) {
+ struct device *dev = &priv->udev->dev;
+ dev_dbg(dev, "%s: C2H packet\n", __func__);
+ rtl8723bu_handle_c2h(priv, skb);
+ } else {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+
+ if (rx_desc->phy_stats)
+ priv->fops->parse_phystats(priv, rx_status, phy_stats,
+ rx_desc->rxmcs, hdr,
+ rx_desc->crc32 || rx_desc->icverr);
+
+ rx_status->mactime = rx_desc->tsfl;
+ rx_status->flag |= RX_FLAG_MACTIME_START;
+
+ if (!rx_desc->swdec)
+ rx_status->flag |= RX_FLAG_DECRYPTED;
+ if (rx_desc->crc32)
+ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+ if (rx_desc->bw)
+ rx_status->bw = RATE_INFO_BW_40;
+
+ if (rx_desc->rxmcs >= DESC_RATE_MCS0) {
+ rx_status->encoding = RX_ENC_HT;
+ rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0;
+ } else {
+ rx_status->rate_idx = rx_desc->rxmcs;
+ }
+
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
+
+ ieee80211_rx_irqsafe(hw, skb);
+ }
+
+ skb = next_skb;
+ if (skb)
+ skb_pull(next_skb, pkt_offset);
+
+ urb_len -= pkt_offset;
+ next_skb = NULL;
+ } while (skb && urb_len >= sizeof(struct rtl8xxxu_rxdesc24));
- ieee80211_rx_irqsafe(hw, skb);
return RX_TYPE_DATA_PKT;
}
@@ -6282,7 +6481,6 @@ static void rtl8xxxu_rx_complete(struct urb *urb)
cleanup:
usb_free_urb(urb);
dev_kfree_skb(skb);
- return;
}
static int rtl8xxxu_submit_rx_urb(struct rtl8xxxu_priv *priv,
@@ -6372,12 +6570,13 @@ static int rtl8xxxu_add_interface(struct ieee80211_hw *hw,
int ret;
u8 val8;
+ if (!priv->vif)
+ priv->vif = vif;
+ else
+ return -EOPNOTSUPP;
+
switch (vif->type) {
case NL80211_IFTYPE_STATION:
- if (!priv->vif)
- priv->vif = vif;
- else
- return -EOPNOTSUPP;
rtl8xxxu_stop_tx_beacon(priv);
val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
@@ -6386,11 +6585,33 @@ static int rtl8xxxu_add_interface(struct ieee80211_hw *hw,
rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8);
ret = 0;
break;
+ case NL80211_IFTYPE_AP:
+ rtl8xxxu_write8(priv, REG_BEACON_CTRL,
+ BEACON_DISABLE_TSF_UPDATE | BEACON_CTRL_MBSSID);
+ rtl8xxxu_write8(priv, REG_ATIMWND, 0x0c); /* 12ms */
+ rtl8xxxu_write16(priv, REG_TSFTR_SYN_OFFSET, 0x7fff); /* ~32ms */
+ rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, DUAL_TSF_RESET_TSF0);
+
+ /* enable BCN0 function */
+ rtl8xxxu_write8(priv, REG_BEACON_CTRL,
+ BEACON_DISABLE_TSF_UPDATE |
+ BEACON_FUNCTION_ENABLE | BEACON_CTRL_MBSSID |
+ BEACON_CTRL_TX_BEACON_RPT);
+
+ /* select BCN on port 0 */
+ val8 = rtl8xxxu_read8(priv, REG_CCK_CHECK);
+ val8 &= ~BIT_BCN_PORT_SEL;
+ rtl8xxxu_write8(priv, REG_CCK_CHECK, val8);
+
+ ret = 0;
+ break;
default:
ret = -EOPNOTSUPP;
}
rtl8xxxu_set_linktype(priv, vif->type);
+ ether_addr_copy(priv->mac_addr, vif->addr);
+ rtl8xxxu_set_mac(priv);
return ret;
}
@@ -6521,22 +6742,22 @@ static void rtl8xxxu_configure_filter(struct ieee80211_hw *hw,
*/
if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
- rcr &= ~RCR_CHECK_BSSID_BEACON;
+ rcr &= ~(RCR_CHECK_BSSID_BEACON | RCR_CHECK_BSSID_MATCH);
else
- rcr |= RCR_CHECK_BSSID_BEACON;
+ rcr |= RCR_CHECK_BSSID_BEACON | RCR_CHECK_BSSID_MATCH;
+
+ if (priv->vif && priv->vif->type == NL80211_IFTYPE_AP)
+ rcr &= ~RCR_CHECK_BSSID_MATCH;
if (*total_flags & FIF_CONTROL)
rcr |= RCR_ACCEPT_CTRL_FRAME;
else
rcr &= ~RCR_ACCEPT_CTRL_FRAME;
- if (*total_flags & FIF_OTHER_BSS) {
+ if (*total_flags & FIF_OTHER_BSS)
rcr |= RCR_ACCEPT_AP;
- rcr &= ~RCR_CHECK_BSSID_MATCH;
- } else {
+ else
rcr &= ~RCR_ACCEPT_AP;
- rcr |= RCR_CHECK_BSSID_MATCH;
- }
if (*total_flags & FIF_PSPOLL)
rcr |= RCR_ACCEPT_PM;
@@ -6557,7 +6778,7 @@ static void rtl8xxxu_configure_filter(struct ieee80211_hw *hw,
static int rtl8xxxu_set_rts_threshold(struct ieee80211_hw *hw, u32 rts)
{
- if (rts > 2347)
+ if (rts > 2347 && rts != (u32)-1)
return -EINVAL;
return 0;
@@ -6706,7 +6927,8 @@ static u8 rtl8xxxu_signal_to_snr(int signal)
}
static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv,
- int signal, struct ieee80211_sta *sta)
+ int signal, struct ieee80211_sta *sta,
+ bool force)
{
struct ieee80211_hw *hw = priv->hw;
u16 wireless_mode;
@@ -6714,6 +6936,7 @@ static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv,
u8 txbw_40mhz;
u8 snr, snr_thresh_high, snr_thresh_low;
u8 go_up_gap = 5;
+ u8 macid = rtl8xxxu_get_macid(priv, sta);
rssi_level = priv->rssi_level;
snr = rtl8xxxu_signal_to_snr(signal);
@@ -6740,7 +6963,7 @@ static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv,
else
rssi_level = RTL8XXXU_RATR_STA_LOW;
- if (rssi_level != priv->rssi_level) {
+ if (rssi_level != priv->rssi_level || force) {
int sgi = 0;
u32 rate_bitmap = 0;
@@ -6833,7 +7056,7 @@ static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv,
}
priv->rssi_level = rssi_level;
- priv->fops->update_rate_mask(priv, rate_bitmap, ratr_idx, sgi, txbw_40mhz);
+ priv->fops->update_rate_mask(priv, rate_bitmap, ratr_idx, sgi, txbw_40mhz, macid);
}
}
@@ -6956,7 +7179,7 @@ static void rtl8xxxu_watchdog_callback(struct work_struct *work)
if (priv->fops->set_crystal_cap)
rtl8xxxu_track_cfo(priv);
- rtl8xxxu_refresh_rate_mask(priv, signal, sta);
+ rtl8xxxu_refresh_rate_mask(priv, signal, sta, false);
}
out:
@@ -7087,6 +7310,38 @@ static void rtl8xxxu_stop(struct ieee80211_hw *hw)
rtl8xxxu_free_tx_resources(priv);
}
+static int rtl8xxxu_sta_add(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv;
+ struct rtl8xxxu_priv *priv = hw->priv;
+
+ if (vif->type == NL80211_IFTYPE_AP) {
+ sta_info->macid = rtl8xxxu_acquire_macid(priv);
+ if (sta_info->macid >= RTL8XXXU_MAX_MAC_ID_NUM)
+ return -ENOSPC;
+
+ rtl8xxxu_refresh_rate_mask(priv, 0, sta, true);
+ priv->fops->report_connect(priv, sta_info->macid, H2C_MACID_ROLE_STA, true);
+ }
+
+ return 0;
+}
+
+static int rtl8xxxu_sta_remove(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv;
+ struct rtl8xxxu_priv *priv = hw->priv;
+
+ if (vif->type == NL80211_IFTYPE_AP)
+ rtl8xxxu_release_macid(priv, sta_info->macid);
+
+ return 0;
+}
+
static const struct ieee80211_ops rtl8xxxu_ops = {
.tx = rtl8xxxu_tx,
.wake_tx_queue = ieee80211_handle_wake_tx_queue,
@@ -7095,6 +7350,7 @@ static const struct ieee80211_ops rtl8xxxu_ops = {
.config = rtl8xxxu_config,
.conf_tx = rtl8xxxu_conf_tx,
.bss_info_changed = rtl8xxxu_bss_info_changed,
+ .start_ap = rtl8xxxu_start_ap,
.configure_filter = rtl8xxxu_configure_filter,
.set_rts_threshold = rtl8xxxu_set_rts_threshold,
.start = rtl8xxxu_start,
@@ -7105,6 +7361,9 @@ static const struct ieee80211_ops rtl8xxxu_ops = {
.ampdu_action = rtl8xxxu_ampdu_action,
.sta_statistics = rtl8xxxu_sta_statistics,
.get_antenna = rtl8xxxu_get_antenna,
+ .set_tim = rtl8xxxu_set_tim,
+ .sta_add = rtl8xxxu_sta_add,
+ .sta_remove = rtl8xxxu_sta_remove,
};
static int rtl8xxxu_parse_usb(struct rtl8xxxu_priv *priv,
@@ -7240,6 +7499,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
case 0xf179:
case 0x8179:
case 0xb711:
+ case 0xf192:
untested = 0;
break;
}
@@ -7264,6 +7524,10 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
if (id->idProduct == 0x0109)
untested = 0;
break;
+ case 0x0b05:
+ if (id->idProduct == 0x18f1)
+ untested = 0;
+ break;
default:
break;
}
@@ -7296,6 +7560,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
spin_lock_init(&priv->rx_urb_lock);
INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work);
INIT_DELAYED_WORK(&priv->ra_watchdog, rtl8xxxu_watchdog_callback);
+ INIT_WORK(&priv->update_beacon_work, rtl8xxxu_update_beacon_work_callback);
skb_queue_head_init(&priv->c2hcmd_queue);
usb_set_intfdata(interface, hw);
@@ -7347,7 +7612,11 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
hw->wiphy->max_scan_ssids = 1;
hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
+ if (priv->fops->max_macid_num)
+ hw->wiphy->max_ap_assoc_sta = priv->fops->max_macid_num - 1;
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+ if (priv->fops->supports_ap)
+ hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP);
hw->queues = 4;
sband = &rtl8xxxu_supported_band;
@@ -7525,6 +7794,16 @@ static const struct usb_device_id dev_table[] = {
/* TOTOLINK N150UA V5 / N150UA-B */
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x2005, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8710bu_fops},
+/* Comfast CF-826F */
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0xf192, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192fu_fops},
+/* Asus USB-N13 rev C1 */
+{USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x18f1, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192fu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xb722, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192fu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x318b, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192fu_fops},
#ifdef CONFIG_RTL8XXXU_UNTESTED
/* Still supported by rtlwifi */
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8176, 0xff, 0xff, 0xff),
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h
index 4dffbab494c3..920ee50e2115 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h
@@ -67,6 +67,7 @@
#define REG_SPS0_CTRL 0x0011
#define REG_SPS_OCP_CFG 0x0018
#define REG_8192E_LDOV12_CTRL 0x0014
+#define REG_SYS_SWR_CTRL2 0x0014
#define REG_RSV_CTRL 0x001c
#define RSV_CTRL_WLOCK_1C BIT(5)
#define RSV_CTRL_DIS_PRST BIT(6)
@@ -215,6 +216,8 @@
#define REG_HMBOX_EXT_2 0x008c
#define REG_HMBOX_EXT_3 0x008e
+#define REG_RSVD_1 0x0097
+
/* Interrupt registers for 8192e/8723bu/8812 */
#define REG_HIMR0 0x00b0
#define IMR0_TXCCK BIT(30) /* TXRPT interrupt when CCX bit
@@ -283,6 +286,7 @@
#define REG_BIST_SCAN 0x00d0
#define REG_BIST_RPT 0x00d4
#define REG_BIST_ROM_RPT 0x00d8
+#define REG_RSVD_4 0x00dc
#define REG_USB_SIE_INTF 0x00e0
#define REG_PCIE_MIO_INTF 0x00e4
#define REG_PCIE_MIO_INTD 0x00e8
@@ -390,6 +394,12 @@
#define TRXDMA_CTRL_BKQ_SHIFT 10
#define TRXDMA_CTRL_MGQ_SHIFT 12
#define TRXDMA_CTRL_HIQ_SHIFT 14
+#define TRXDMA_CTRL_VOQ_SHIFT_8192F 4
+#define TRXDMA_CTRL_VIQ_SHIFT_8192F 7
+#define TRXDMA_CTRL_BEQ_SHIFT_8192F 10
+#define TRXDMA_CTRL_BKQ_SHIFT_8192F 13
+#define TRXDMA_CTRL_MGQ_SHIFT_8192F 16
+#define TRXDMA_CTRL_HIQ_SHIFT_8192F 19
#define TRXDMA_QUEUE_LOW 1
#define TRXDMA_QUEUE_NORMAL 2
#define TRXDMA_QUEUE_HIGH 3
@@ -439,7 +449,7 @@
#define LLT_OP_READ (0x2 << 30)
#define LLT_OP_MASK (0x3 << 30)
-#define REG_BB_ACCEESS_CTRL 0x01e8
+#define REG_BB_ACCESS_CTRL 0x01e8
#define REG_BB_ACCESS_DATA 0x01ec
#define REG_HMBOX_EXT0_8723B 0x01f0
@@ -456,6 +466,7 @@
#define REG_FIFOPAGE 0x0204
#define REG_TDECTRL 0x0208
+#define BIT_BCN_VALID BIT(16)
#define REG_DWBCN0_CTRL_8188F REG_TDECTRL
@@ -470,6 +481,7 @@
#define AUTO_LLT_INIT_LLT BIT(16)
#define REG_DWBCN1_CTRL_8723B 0x0228
+#define BIT_SW_BCN_SEL BIT(20)
/* 0x0280 ~ 0x02FF RXDMA Configuration */
#define REG_RXDMA_AGG_PG_TH 0x0280 /* 0-7 : USB DMA size bits
@@ -516,6 +528,7 @@
#define REG_FWHW_TXQ_CTRL 0x0420
#define FWHW_TXQ_CTRL_AMPDU_RETRY BIT(7)
#define FWHW_TXQ_CTRL_XMIT_MGMT_ACK BIT(12)
+#define EN_BCNQ_DL BIT(22)
#define REG_HWSEQ_CTRL 0x0423
#define REG_TXPKTBUF_BCNQ_BDNY 0x0424
@@ -572,6 +585,8 @@
#define REG_ARFR1 0x0448
#define REG_ARFR2 0x044c
#define REG_ARFR3 0x0450
+#define REG_CCK_CHECK 0x0454
+#define BIT_BCN_PORT_SEL BIT(5)
#define REG_AMPDU_MAX_TIME_8723B 0x0456
#define REG_AGGLEN_LMT 0x0458
#define REG_AMPDU_MIN_SPACE 0x045c
@@ -968,12 +983,18 @@
#define FPGA1_TX_OFDM_TXSC_MASK 0x30000000
#define REG_ANT_MAPPING1 0x0914
+#define REG_RFE_OPT 0x0920
#define REG_DPDT_CTRL 0x092c /* 8723BU */
#define REG_RFE_CTRL_ANTA_SRC 0x0930 /* 8723BU */
+#define REG_RFE_CTRL_ANT_SRC1 0x0934
+#define REG_RFE_CTRL_ANT_SRC2 0x0938
+#define REG_RFE_CTRL_ANT_SRC3 0x093c
#define REG_RFE_PATH_SELECT 0x0940 /* 8723BU */
#define REG_RFE_BUFFER 0x0944 /* 8723BU */
#define REG_S0S1_PATH_SWITCH 0x0948 /* 8723BU */
+#define REG_RX_DFIR_MOD_97F 0x0948
#define REG_OFDM_RX_DFIR 0x954
+#define REG_RFE_OPT62 0x0968
#define REG_CCK0_SYSTEM 0x0a00
#define CCK0_SIDEBAND BIT(4)
@@ -1033,6 +1054,8 @@
#define REG_OFDM0_FA_RSTC 0x0c0c
+#define REG_DOWNSAM_FACTOR 0x0c10
+
#define REG_OFDM0_XA_RX_AFE 0x0c10
#define REG_OFDM0_XA_RX_IQ_IMBALANCE 0x0c14
#define REG_OFDM0_XB_RX_IQ_IMBALANCE 0x0c1c
@@ -1054,7 +1077,7 @@
#define REG_OFDM0_AGC_PARM1 0x0c70
-#define REG_OFDM0_AGCR_SSI_TABLE 0x0c78
+#define REG_OFDM0_AGC_RSSI_TABLE 0x0c78
#define REG_OFDM0_XA_TX_IQ_IMBALANCE 0x0c80
#define REG_OFDM0_XB_TX_IQ_IMBALANCE 0x0c88
@@ -1069,6 +1092,8 @@
/* 8188eu */
#define REG_ANTDIV_PARA1 0x0ca4
+#define REG_RXIQB_EXT 0x0ca8
+
/* 8723bu */
#define REG_OFDM0_TX_PSDO_NOISE_WEIGHT 0x0ce4
@@ -1088,6 +1113,8 @@
#define REG_OFDM1_CSI_FIX_MASK1 0x0d40
#define REG_OFDM1_CSI_FIX_MASK2 0x0d44
+#define REG_ANAPWR1 0x0d94
+
#define REG_TX_AGC_A_RATE18_06 0x0e00
#define REG_TX_AGC_A_RATE54_24 0x0e04
#define REG_TX_AGC_A_CCK1_MCS32 0x0e08
@@ -1096,6 +1123,10 @@
#define REG_TX_AGC_A_MCS11_MCS08 0x0e18
#define REG_TX_AGC_A_MCS15_MCS12 0x0e1c
+#define REG_NP_ANTA 0x0e20
+
+#define REG_TAP_UPD_97F 0x0e24
+
#define REG_FPGA0_IQK 0x0e28
#define REG_TX_IQK_TONE_A 0x0e30
@@ -1124,19 +1155,23 @@
#define REG_RX_CCK 0x0e8c
#define REG_TX_POWER_BEFORE_IQK_A 0x0e94
+#define REG_IQK_RPT_TXA 0x0e98
#define REG_TX_POWER_AFTER_IQK_A 0x0e9c
#define REG_RX_POWER_BEFORE_IQK_A 0x0ea0
#define REG_RX_POWER_BEFORE_IQK_A_2 0x0ea4
#define REG_RX_POWER_AFTER_IQK_A 0x0ea8
+#define REG_IQK_RPT_RXA 0x0ea8
#define REG_RX_POWER_AFTER_IQK_A_2 0x0eac
#define REG_TX_POWER_BEFORE_IQK_B 0x0eb4
+#define REG_IQK_RPT_TXB 0x0eb8
#define REG_TX_POWER_AFTER_IQK_B 0x0ebc
#define REG_RX_POWER_BEFORE_IQK_B 0x0ec0
#define REG_RX_POWER_BEFORE_IQK_B_2 0x0ec4
#define REG_RX_POWER_AFTER_IQK_B 0x0ec8
+#define REG_IQK_RPT_RXB 0x0ec8
#define REG_RX_POWER_AFTER_IQK_B_2 0x0ecc
#define REG_RX_OFDM 0x0ed0
@@ -1147,6 +1182,12 @@
#define REG_PMPD_ANAEN 0x0eec
#define REG_FW_START_ADDRESS 0x1000
+#define REG_FW_START_ADDRESS_8192F 0x4000
+
+#define REG_SW_GPIO_SHARE_CTRL_0 0x1038
+#define REG_SW_GPIO_SHARE_CTRL_1 0x103c
+#define REG_GPIO_A0 0x1050
+#define REG_GPIO_B0 0x105b
#define REG_USB_INFO 0xfe17
#define REG_USB_HIMR 0xfe38
@@ -1311,12 +1352,15 @@
/*
* NextGen regs: 8723BU
*/
+#define RF6052_REG_GAIN_P1 0x35
#define RF6052_REG_T_METER_8723B 0x42
#define RF6052_REG_UNKNOWN_43 0x43
#define RF6052_REG_UNKNOWN_55 0x55
-#define RF6052_REG_UNKNOWN_56 0x56
+#define RF6052_REG_PAD_TXG 0x56
+#define RF6052_REG_TXMOD 0x58
#define RF6052_REG_RXG_MIX_SWBW 0x87
#define RF6052_REG_S0S1 0xb0
-#define RF6052_REG_UNKNOWN_DF 0xdf
+#define RF6052_REG_GAIN_CCA 0xdf
#define RF6052_REG_UNKNOWN_ED 0xed
#define RF6052_REG_WE_LUT 0xef
+#define RF6052_REG_GAIN_CTRL 0xf5
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
index 9e7e98b55eff..807a53a97325 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -452,8 +452,7 @@ static int _rtl_init_deferred_work(struct ieee80211_hw *hw)
/* <1> timer */
timer_setup(&rtlpriv->works.watchdog_timer,
rtl_watch_dog_timer_callback, 0);
- timer_setup(&rtlpriv->works.dualmac_easyconcurrent_retrytimer,
- rtl_easy_concurrent_retrytimer_callback, 0);
+
/* <2> work queue */
rtlpriv->works.hw = hw;
rtlpriv->works.rtl_wq = wq;
@@ -1905,7 +1904,7 @@ EXPORT_SYMBOL(rtl_rx_ampdu_apply);
void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
return;
@@ -1991,7 +1990,7 @@ void rtl_scan_list_expire(struct ieee80211_hw *hw)
void rtl_collect_scan_list(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
unsigned long flags;
@@ -2366,19 +2365,6 @@ static void rtl_c2hcmd_wq_callback(struct work_struct *work)
rtl_c2hcmd_launcher(hw, 1);
}
-void rtl_easy_concurrent_retrytimer_callback(struct timer_list *t)
-{
- struct rtl_priv *rtlpriv =
- from_timer(rtlpriv, t, works.dualmac_easyconcurrent_retrytimer);
- struct ieee80211_hw *hw = rtlpriv->hw;
- struct rtl_priv *buddy_priv = rtlpriv->buddy_priv;
-
- if (buddy_priv == NULL)
- return;
-
- rtlpriv->cfg->ops->dualmac_easy_concurrent(hw);
-}
-
/*********************************************************
*
* frame process functions
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h
index 0e4f8a8ae3a5..f081a9a90563 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.h
+++ b/drivers/net/wireless/realtek/rtlwifi/base.h
@@ -124,7 +124,6 @@ int rtl_send_smps_action(struct ieee80211_hw *hw,
u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie);
void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len);
u8 rtl_tid_to_ac(u8 tid);
-void rtl_easy_concurrent_retrytimer_callback(struct timer_list *t);
extern struct rtl_global_var rtl_global_var;
void rtl_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation);
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
index 6f10727cdb94..4fb16f5f6f83 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -1908,6 +1908,16 @@ bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb)
return true;
}
EXPORT_SYMBOL(rtl_cmd_send_packet);
+
+void rtl_init_sw_leds(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpriv->ledctl.sw_led0 = LED_PIN_LED0;
+ rtlpriv->ledctl.sw_led1 = LED_PIN_LED1;
+}
+EXPORT_SYMBOL(rtl_init_sw_leds);
+
const struct ieee80211_ops rtl_ops = {
.start = rtl_op_start,
.stop = rtl_op_stop,
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.h b/drivers/net/wireless/realtek/rtlwifi/core.h
index 345161b47442..42c2d9e13bb8 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.h
+++ b/drivers/net/wireless/realtek/rtlwifi/core.h
@@ -51,6 +51,8 @@ enum dm_dig_connect_e {
};
extern const struct ieee80211_ops rtl_ops;
+
+void rtl_init_sw_leds(struct ieee80211_hw *hw);
void rtl_fw_cb(const struct firmware *firmware, void *context);
void rtl_wowlan_fw_cb(const struct firmware *firmware, void *context);
void rtl_addr_delay(u32 addr);
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index ca79f652fef3..9886e719739b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -482,11 +482,6 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw)
if (!rtlpriv->rtlhal.earlymode_enable)
return;
- if (rtlpriv->dm.supp_phymode_switch &&
- (rtlpriv->easy_concurrent_ctl.switch_in_process ||
- (rtlpriv->buddy_priv &&
- rtlpriv->buddy_priv->easy_concurrent_ctl.switch_in_process)))
- return;
/* we just use em for BE/BK/VI/VO */
for (tid = 7; tid >= 0; tid--) {
u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(tid)];
@@ -2265,7 +2260,7 @@ int rtl_pci_probe(struct pci_dev *pdev,
err = -ENODEV;
goto fail3;
}
- rtlpriv->cfg->ops->init_sw_leds(hw);
+ rtl_init_sw_leds(hw);
/*aspm */
rtl_pci_init_aspm(hw);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c
index de61c9c0ddec..58b1a46066b5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c
@@ -803,17 +803,17 @@ static void _rtl88ee_gen_refresh_led_state(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
if (rtlpriv->rtlhal.up_first_time)
return;
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
- rtl88ee_sw_led_on(hw, pled0);
+ rtl88ee_sw_led_on(hw, pin0);
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
- rtl88ee_sw_led_on(hw, pled0);
+ rtl88ee_sw_led_on(hw, pin0);
else
- rtl88ee_sw_led_off(hw, pled0);
+ rtl88ee_sw_led_off(hw, pin0);
}
static bool _rtl88ee_init_mac(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c
index 006b979da1c6..b57ba45902f9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c
@@ -6,23 +6,15 @@
#include "reg.h"
#include "led.h"
-static void _rtl88ee_init_led(struct ieee80211_hw *hw,
- struct rtl_led *pled, enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl88ee_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -36,21 +28,20 @@ void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
default:
rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
- "switch case %#x not processed\n", pled->ledpin);
+ "switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl88ee_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 ledcfg;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -73,34 +64,25 @@ void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
default:
rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
- "switch case %#x not processed\n", pled->ledpin);
+ "switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
-}
-
-void rtl88ee_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl88ee_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl88ee_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
}
static void _rtl88ee_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
switch (ledaction) {
case LED_CTL_POWER_ON:
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
- rtl88ee_sw_led_on(hw, pled0);
+ rtl88ee_sw_led_on(hw, pin0);
break;
case LED_CTL_POWER_OFF:
- rtl88ee_sw_led_off(hw, pled0);
+ rtl88ee_sw_led_off(hw, pin0);
break;
default:
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h
index 67d3dc389ba0..e5cc35d4c298 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h
@@ -4,9 +4,8 @@
#ifndef __RTL92CE_LED_H__
#define __RTL92CE_LED_H__
-void rtl88ee_init_sw_leds(struct ieee80211_hw *hw);
-void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl88ee_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl88ee_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl88ee_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
index 02b77521b5cd..b77937fe2448 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
@@ -230,7 +230,6 @@ static struct rtl_hal_ops rtl8188ee_hal_ops = {
.tx_polling = rtl88ee_tx_polling,
.enable_hw_sec = rtl88ee_enable_hw_security_config,
.set_key = rtl88ee_set_key,
- .init_sw_leds = rtl88ee_init_sw_leds,
.get_bbreg = rtl88e_phy_query_bb_reg,
.set_bbreg = rtl88e_phy_set_bb_reg,
.get_rfreg = rtl88e_phy_query_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c
index 6e4741e9483f..65ebe52883d3 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c
@@ -674,7 +674,7 @@ void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw,
u8 fw_queue = QSLT_BEACON;
__le32 *pdesc = (__le32 *)pdesc8;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
__le16 fc = hdr->frame_control;
dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
index dc480323c9cb..049c4fe9eeed 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
@@ -639,17 +639,17 @@ static void _rtl92ce_gen_refresh_led_state(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
if (rtlpci->up_first_time)
return;
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
- rtl92ce_sw_led_on(hw, pled0);
+ rtl92ce_sw_led_on(hw, pin0);
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
- rtl92ce_sw_led_on(hw, pled0);
+ rtl92ce_sw_led_on(hw, pin0);
else
- rtl92ce_sw_led_off(hw, pled0);
+ rtl92ce_sw_led_off(hw, pin0);
}
static bool _rtl92ce_init_mac(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c
index 57132278eb5c..9d3ffed13ba8 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c
@@ -6,25 +6,17 @@
#include "reg.h"
#include "led.h"
-static void _rtl92ce_init_led(struct ieee80211_hw *hw,
- struct rtl_led *pled, enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92ce_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
- REG_LEDCFG2, pled->ledpin);
+ REG_LEDCFG2, pin);
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -35,24 +27,22 @@ void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5));
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92ce_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 ledcfg;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
- REG_LEDCFG2, pled->ledpin);
+ REG_LEDCFG2, pin);
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -69,34 +59,25 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3)));
break;
default:
- pr_info("switch case %#x not processed\n", pled->ledpin);
+ pr_info("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
-}
-
-void rtl92ce_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl92ce_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl92ce_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
}
static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
switch (ledaction) {
case LED_CTL_POWER_ON:
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
- rtl92ce_sw_led_on(hw, pled0);
+ rtl92ce_sw_led_on(hw, pin0);
break;
case LED_CTL_POWER_OFF:
- rtl92ce_sw_led_off(hw, pled0);
+ rtl92ce_sw_led_off(hw, pin0);
break;
default:
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h
index 97ab1e00af5f..66dc28d62003 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h
@@ -4,9 +4,8 @@
#ifndef __RTL92CE_LED_H__
#define __RTL92CE_LED_H__
-void rtl92ce_init_sw_leds(struct ieee80211_hw *hw);
-void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92ce_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl92ce_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl92ce_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
index ed68c850f9a2..e452275d8789 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
@@ -207,7 +207,6 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = {
.tx_polling = rtl92ce_tx_polling,
.enable_hw_sec = rtl92ce_enable_hw_security_config,
.set_key = rtl92ce_set_key,
- .init_sw_leds = rtl92ce_init_sw_leds,
.get_bbreg = rtl92c_phy_query_bb_reg,
.set_bbreg = rtl92c_phy_set_bb_reg,
.set_rfreg = rtl92ce_phy_set_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
index 730c7e939bd2..5376bb34251f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
@@ -527,7 +527,7 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
u8 fw_queue = QSLT_BEACON;
__le32 *pdesc = (__le32 *)pdesc8;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
__le16 fc = hdr->frame_control;
dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c
index 1488f52a2d2f..bfc07efd0eb0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c
@@ -6,27 +6,15 @@
#include "reg.h"
#include "led.h"
-static void _rtl92cu_init_led(struct ieee80211_hw *hw,
- struct rtl_led *pled, enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-static void rtl92cu_deinit_led(struct rtl_led *pled)
-{
-}
-
-void rtl92cu_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92cu_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
- REG_LEDCFG2, pled->ledpin);
+ REG_LEDCFG2, pin);
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -37,22 +25,20 @@ void rtl92cu_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5));
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92cu_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 ledcfg;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
- REG_LEDCFG2, pled->ledpin);
+ REG_LEDCFG2, pin);
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -69,36 +55,13 @@ void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3)));
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
-}
-
-void rtl92cu_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl92cu_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl92cu_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
-}
-
-void rtl92cu_deinit_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- rtl92cu_deinit_led(&rtlpriv->ledctl.sw_led0);
- rtl92cu_deinit_led(&rtlpriv->ledctl.sw_led1);
-}
-
-static void _rtl92cu_sw_led_control(struct ieee80211_hw *hw,
- enum led_ctl_mode ledaction)
-{
}
void rtl92cu_led_control(struct ieee80211_hw *hw,
- enum led_ctl_mode ledaction)
+ enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
@@ -114,5 +77,4 @@ void rtl92cu_led_control(struct ieee80211_hw *hw,
return;
}
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d\n", ledaction);
- _rtl92cu_sw_led_control(hw, ledaction);
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h
index 3fc1e7c8f78b..8175f8bddd6d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h
@@ -4,10 +4,8 @@
#ifndef __RTL92CU_LED_H__
#define __RTL92CU_LED_H__
-void rtl92cu_init_sw_leds(struct ieee80211_hw *hw);
-void rtl92cu_deinit_sw_leds(struct ieee80211_hw *hw);
-void rtl92cu_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92cu_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl92cu_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl92cu_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
index 876c14d46c2f..e6403d4c937c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
@@ -115,8 +115,6 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = {
.led_control = rtl92cu_led_control,
.enable_hw_sec = rtl92cu_enable_hw_security_config,
.set_key = rtl92c_set_key,
- .init_sw_leds = rtl92cu_init_sw_leds,
- .deinit_sw_leds = rtl92cu_deinit_sw_leds,
.get_bbreg = rtl92c_phy_query_bb_reg,
.set_bbreg = rtl92c_phy_set_bb_reg,
.get_rfreg = rtl92cu_phy_query_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
index ae3c4f97637e..b70767e72f3d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
@@ -394,7 +394,7 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb)
(struct rx_desc_92c *)rxdesc, p_drvinfo);
}
skb_pull(skb, (drvinfo_len + RTL_RX_DESC_SIZE));
- hdr = (struct ieee80211_hdr *)(skb->data);
+ hdr = rtl_get_hdr(skb);
fc = hdr->frame_control;
bv = ieee80211_is_probe_resp(fc);
if (bv)
@@ -632,7 +632,7 @@ void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw,
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 fw_queue = QSLT_BEACON;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
__le16 fc = hdr->frame_control;
__le32 *pdesc = (__le32 *)pdesc8;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c
index df1e36fbc348..31a18bbface9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c
@@ -595,16 +595,16 @@ static void _rtl92de_gen_refresh_led_state(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
if (rtlpci->up_first_time)
return;
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
- rtl92de_sw_led_on(hw, pled0);
+ rtl92de_sw_led_on(hw, pin0);
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
- rtl92de_sw_led_on(hw, pled0);
+ rtl92de_sw_led_on(hw, pin0);
else
- rtl92de_sw_led_off(hw, pled0);
+ rtl92de_sw_led_off(hw, pin0);
}
static bool _rtl92de_init_mac(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c
index 93d1c6a610c3..4bd708570992 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c
@@ -6,23 +6,15 @@
#include "reg.h"
#include "led.h"
-static void _rtl92ce_init_led(struct ieee80211_hw *hw,
- struct rtl_led *pled, enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92de_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
- REG_LEDCFG2, pled->ledpin);
+ REG_LEDCFG2, pin);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -44,24 +36,22 @@ void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5));
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92de_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 ledcfg;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
- REG_LEDCFG2, pled->ledpin);
+ REG_LEDCFG2, pin);
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -78,35 +68,25 @@ void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3)));
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
-}
-
-void rtl92de_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl92ce_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl92ce_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
}
static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
switch (ledaction) {
case LED_CTL_POWER_ON:
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
- rtl92de_sw_led_on(hw, pled0);
+ rtl92de_sw_led_on(hw, pin0);
break;
case LED_CTL_POWER_OFF:
- rtl92de_sw_led_off(hw, pled0);
+ rtl92de_sw_led_off(hw, pin0);
break;
default:
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h
index 7599c7e5ecc3..33e544ad6f99 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h
@@ -4,9 +4,8 @@
#ifndef __RTL92CE_LED_H__
#define __RTL92CE_LED_H__
-void rtl92de_init_sw_leds(struct ieee80211_hw *hw);
-void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92de_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl92de_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl92de_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
index a74724c971b9..11f319c97124 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
@@ -220,7 +220,6 @@ static struct rtl_hal_ops rtl8192de_hal_ops = {
.tx_polling = rtl92de_tx_polling,
.enable_hw_sec = rtl92de_enable_hw_security_config,
.set_key = rtl92de_set_key,
- .init_sw_leds = rtl92de_init_sw_leds,
.get_bbreg = rtl92d_phy_query_bb_reg,
.set_bbreg = rtl92d_phy_set_bb_reg,
.get_rfreg = rtl92d_phy_query_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
index 807b66c16e11..c09c0c312665 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
@@ -665,7 +665,7 @@ void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw,
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 fw_queue = QSLT_BEACON;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
__le16 fc = hdr->frame_control;
__le32 *pdesc = (__le32 *)pdesc8;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
index 47d8999e31c0..ebb7abd0c9ad 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
@@ -714,17 +714,17 @@ static void _rtl92ee_gen_refresh_led_state(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
if (rtlpriv->rtlhal.up_first_time)
return;
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
- rtl92ee_sw_led_on(hw, pled0);
+ rtl92ee_sw_led_on(hw, pin0);
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
- rtl92ee_sw_led_on(hw, pled0);
+ rtl92ee_sw_led_on(hw, pin0);
else
- rtl92ee_sw_led_off(hw, pled0);
+ rtl92ee_sw_led_off(hw, pin0);
}
static bool _rtl92ee_init_mac(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c
index fb4ea3a8481f..a9b5e3c884ee 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c
@@ -6,23 +6,15 @@
#include "reg.h"
#include "led.h"
-static void _rtl92ee_init_led(struct ieee80211_hw *hw,
- struct rtl_led *pled, enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-void rtl92ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92ee_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u32 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -39,21 +31,20 @@ void rtl92ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
default:
rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
- "switch case %#x not processed\n", pled->ledpin);
+ "switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl92ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92ee_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 ledcfg;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -69,34 +60,25 @@ void rtl92ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
default:
rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
- "switch case %#x not processed\n", pled->ledpin);
+ "switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
-}
-
-void rtl92ee_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl92ee_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl92ee_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
}
static void _rtl92ee_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
switch (ledaction) {
case LED_CTL_POWER_ON:
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
- rtl92ee_sw_led_on(hw, pled0);
+ rtl92ee_sw_led_on(hw, pin0);
break;
case LED_CTL_POWER_OFF:
- rtl92ee_sw_led_off(hw, pled0);
+ rtl92ee_sw_led_off(hw, pin0);
break;
default:
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h
index 6d775e14846f..08b8ff328b63 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h
@@ -4,9 +4,8 @@
#ifndef __RTL92E_LED_H__
#define __RTL92E_LED_H__
-void rtl92ee_init_sw_leds(struct ieee80211_hw *hw);
-void rtl92ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl92ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92ee_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl92ee_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl92ee_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
index 7a16563b3a5d..616a47d8d97a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
@@ -220,7 +220,6 @@ static struct rtl_hal_ops rtl8192ee_hal_ops = {
.tx_polling = rtl92ee_tx_polling,
.enable_hw_sec = rtl92ee_enable_hw_security_config,
.set_key = rtl92ee_set_key,
- .init_sw_leds = rtl92ee_init_sw_leds,
.get_bbreg = rtl92ee_phy_query_bb_reg,
.set_bbreg = rtl92ee_phy_set_bb_reg,
.get_rfreg = rtl92ee_phy_query_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c
index a8b5bf45b1bb..e5775b94f04e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c
@@ -731,12 +731,12 @@ static void _rtl92se_macconfig_before_fwdownload(struct ieee80211_hw *hw)
/* After MACIO reset,we must refresh LED state. */
if ((ppsc->rfoff_reason == RF_CHANGE_BY_IPS) ||
(ppsc->rfoff_reason == 0)) {
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
enum rf_pwrstate rfpwr_state_toset;
rfpwr_state_toset = _rtl92se_rf_onoff_detect(hw);
if (rfpwr_state_toset == ERFON)
- rtl92se_sw_led_on(hw, pled0);
+ rtl92se_sw_led_on(hw, pin0);
}
}
@@ -1302,7 +1302,7 @@ static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw)
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
u8 u1btmp;
- if (rtlhal->driver_going2unload)
+ if (rtlhal->driver_is_goingto_unload)
rtl_write_byte(rtlpriv, 0x560, 0x0);
/* Power save for BB/RF */
@@ -1323,7 +1323,7 @@ static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw)
rtl_write_word(rtlpriv, CMDR, 0x57FC);
rtl_write_word(rtlpriv, CMDR, 0x0000);
- if (rtlhal->driver_going2unload) {
+ if (rtlhal->driver_is_goingto_unload) {
u1btmp = rtl_read_byte(rtlpriv, (REG_SYS_FUNC_EN + 1));
u1btmp &= ~(BIT(0));
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, u1btmp);
@@ -1345,7 +1345,7 @@ static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw)
/* Power save for MAC */
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS &&
- !rtlhal->driver_going2unload) {
+ !rtlhal->driver_is_goingto_unload) {
/* enable LED function */
rtl_write_byte(rtlpriv, 0x03, 0xF9);
/* SW/HW radio off or halt adapter!! For example S3/S4 */
@@ -1371,15 +1371,15 @@ static void _rtl92se_gen_refreshledstate(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
if (rtlpci->up_first_time)
return;
if (rtlpriv->psc.rfoff_reason == RF_CHANGE_BY_IPS)
- rtl92se_sw_led_on(hw, pled0);
+ rtl92se_sw_led_on(hw, pin0);
else
- rtl92se_sw_led_off(hw, pled0);
+ rtl92se_sw_led_off(hw, pin0);
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c
index ecbf425f679f..db16a325c5e6 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c
@@ -6,33 +6,17 @@
#include "reg.h"
#include "led.h"
-static void _rtl92se_init_led(struct ieee80211_hw *hw,
- struct rtl_led *pled, enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-void rtl92se_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl92se_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl92se_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
-}
-
-void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92se_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
- LEDCFG, pled->ledpin);
+ LEDCFG, pin);
ledcfg = rtl_read_byte(rtlpriv, LEDCFG);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -42,14 +26,12 @@ void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, LEDCFG, ledcfg & 0x0f);
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92se_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv;
u8 ledcfg;
@@ -58,11 +40,11 @@ void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
if (!rtlpriv || rtlpriv->max_fw_size)
return;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
- LEDCFG, pled->ledpin);
+ LEDCFG, pin);
ledcfg = rtl_read_byte(rtlpriv, LEDCFG);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -77,27 +59,25 @@ void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3)));
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
}
static void _rtl92se_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
switch (ledaction) {
case LED_CTL_POWER_ON:
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
- rtl92se_sw_led_on(hw, pled0);
+ rtl92se_sw_led_on(hw, pin0);
break;
case LED_CTL_POWER_OFF:
- rtl92se_sw_led_off(hw, pled0);
+ rtl92se_sw_led_off(hw, pin0);
break;
default:
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h
index c9e481a8d943..43fcc3c77bc1 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h
@@ -4,9 +4,8 @@
#ifndef __REALTEK_PCI92SE_LED_H__
#define __REALTEK_PCI92SE_LED_H__
-void rtl92se_init_sw_leds(struct ieee80211_hw *hw);
-void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92se_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl92se_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl92se_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
index 6d352a3161b8..30bce381c3bb 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
@@ -260,7 +260,6 @@ static struct rtl_hal_ops rtl8192se_hal_ops = {
.tx_polling = rtl92se_tx_polling,
.enable_hw_sec = rtl92se_enable_hw_security_config,
.set_key = rtl92se_set_key,
- .init_sw_leds = rtl92se_init_sw_leds,
.get_bbreg = rtl92s_phy_query_bb_reg,
.set_bbreg = rtl92s_phy_set_bb_reg,
.get_rfreg = rtl92s_phy_query_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
index 965d98b9b09f..d26d4c4314a3 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
@@ -643,17 +643,17 @@ static void _rtl8723e_gen_refresh_led_state(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
if (rtlpriv->rtlhal.up_first_time)
return;
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
- rtl8723e_sw_led_on(hw, pled0);
+ rtl8723e_sw_led_on(hw, pin0);
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
- rtl8723e_sw_led_on(hw, pled0);
+ rtl8723e_sw_led_on(hw, pin0);
else
- rtl8723e_sw_led_off(hw, pled0);
+ rtl8723e_sw_led_off(hw, pin0);
}
static bool _rtl8712e_init_mac(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c
index 7fab02e01a8c..90d3f6ae82d5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c
@@ -6,23 +6,15 @@
#include "reg.h"
#include "led.h"
-static void _rtl8723e_init_led(struct ieee80211_hw *hw,
- struct rtl_led *pled, enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-void rtl8723e_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl8723e_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -36,24 +28,22 @@ void rtl8723e_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10);
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl8723e_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl8723e_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 ledcfg;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -77,35 +67,25 @@ void rtl8723e_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
-}
-
-void rtl8723e_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl8723e_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl8723e_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
}
static void _rtl8723e_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
switch (ledaction) {
case LED_CTL_POWER_ON:
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
- rtl8723e_sw_led_on(hw, pled0);
+ rtl8723e_sw_led_on(hw, pin0);
break;
case LED_CTL_POWER_OFF:
- rtl8723e_sw_led_off(hw, pled0);
+ rtl8723e_sw_led_off(hw, pin0);
break;
default:
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h
index 9f85845d23cd..6db5290da806 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h
@@ -4,9 +4,8 @@
#ifndef __RTL92CE_LED_H__
#define __RTL92CE_LED_H__
-void rtl8723e_init_sw_leds(struct ieee80211_hw *hw);
-void rtl8723e_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl8723e_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl8723e_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl8723e_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl8723e_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
index 7828acb1de3f..c821436a1991 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
@@ -223,7 +223,6 @@ static struct rtl_hal_ops rtl8723e_hal_ops = {
.tx_polling = rtl8723e_tx_polling,
.enable_hw_sec = rtl8723e_enable_hw_security_config,
.set_key = rtl8723e_set_key,
- .init_sw_leds = rtl8723e_init_sw_leds,
.get_bbreg = rtl8723_phy_query_bb_reg,
.set_bbreg = rtl8723_phy_set_bb_reg,
.get_rfreg = rtl8723e_phy_query_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c
index 27fddbcade32..7f294e698994 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c
@@ -528,7 +528,7 @@ void rtl8723e_tx_fill_cmddesc(struct ieee80211_hw *hw,
u8 fw_queue = QSLT_BEACON;
__le32 *pdesc = (__le32 *)pdesc8;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
__le16 fc = hdr->frame_control;
dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
index 0ba3bbed6ed3..15575644551f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
@@ -793,17 +793,17 @@ static void _rtl8723be_gen_refresh_led_state(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
if (rtlpriv->rtlhal.up_first_time)
return;
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
- rtl8723be_sw_led_on(hw, pled0);
+ rtl8723be_sw_led_on(hw, pin0);
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
- rtl8723be_sw_led_on(hw, pled0);
+ rtl8723be_sw_led_on(hw, pin0);
else
- rtl8723be_sw_led_off(hw, pled0);
+ rtl8723be_sw_led_off(hw, pin0);
}
static bool _rtl8723be_init_mac(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c
index 3954624ab314..462fe1d0262b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c
@@ -6,23 +6,15 @@
#include "reg.h"
#include "led.h"
-static void _rtl8723be_init_led(struct ieee80211_hw *hw, struct rtl_led *pled,
- enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-void rtl8723be_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl8723be_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -35,24 +27,22 @@ void rtl8723be_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10);
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl8723be_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl8723be_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 ledcfg;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -76,35 +66,25 @@ void rtl8723be_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
-}
-
-void rtl8723be_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl8723be_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl8723be_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
}
static void _rtl8723be_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
switch (ledaction) {
case LED_CTL_POWER_ON:
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
- rtl8723be_sw_led_on(hw, pled0);
+ rtl8723be_sw_led_on(hw, pin0);
break;
case LED_CTL_POWER_OFF:
- rtl8723be_sw_led_off(hw, pled0);
+ rtl8723be_sw_led_off(hw, pin0);
break;
default:
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h
index 8ac59374b632..3ca9277152f7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h
@@ -4,9 +4,8 @@
#ifndef __RTL8723BE_LED_H__
#define __RTL8723BE_LED_H__
-void rtl8723be_init_sw_leds(struct ieee80211_hw *hw);
-void rtl8723be_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl8723be_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl8723be_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl8723be_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl8723be_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
index d220e8955e37..43b611d5288d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
@@ -227,7 +227,6 @@ static struct rtl_hal_ops rtl8723be_hal_ops = {
.tx_polling = rtl8723be_tx_polling,
.enable_hw_sec = rtl8723be_enable_hw_security_config,
.set_key = rtl8723be_set_key,
- .init_sw_leds = rtl8723be_init_sw_leds,
.get_bbreg = rtl8723_phy_query_bb_reg,
.set_bbreg = rtl8723_phy_set_bb_reg,
.get_rfreg = rtl8723be_phy_query_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
index a7e3250957dc..3f8f6da33b12 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
@@ -869,7 +869,7 @@ static void _rtl8821ae_gen_refresh_led_state(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
if (rtlpriv->rtlhal.up_first_time)
@@ -877,19 +877,19 @@ static void _rtl8821ae_gen_refresh_led_state(struct ieee80211_hw *hw)
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
- rtl8812ae_sw_led_on(hw, pled0);
+ rtl8812ae_sw_led_on(hw, pin0);
else
- rtl8821ae_sw_led_on(hw, pled0);
+ rtl8821ae_sw_led_on(hw, pin0);
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
- rtl8812ae_sw_led_on(hw, pled0);
+ rtl8812ae_sw_led_on(hw, pin0);
else
- rtl8821ae_sw_led_on(hw, pled0);
+ rtl8821ae_sw_led_on(hw, pin0);
else
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
- rtl8812ae_sw_led_off(hw, pled0);
+ rtl8812ae_sw_led_off(hw, pin0);
else
- rtl8821ae_sw_led_off(hw, pled0);
+ rtl8821ae_sw_led_off(hw, pin0);
}
static bool _rtl8821ae_init_mac(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c
index 7d6fb134c10f..fb003f9ce1ac 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c
@@ -6,24 +6,15 @@
#include "reg.h"
#include "led.h"
-static void _rtl8821ae_init_led(struct ieee80211_hw *hw,
- struct rtl_led *pled,
- enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -38,19 +29,18 @@ void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
default:
rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
- "switch case %#x not processed\n", pled->ledpin);
+ "switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u16 ledreg = REG_LEDCFG1;
u8 ledcfg = 0;
struct rtl_priv *rtlpriv = rtl_priv(hw);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_LED0:
ledreg = REG_LEDCFG1;
break;
@@ -66,27 +56,26 @@ void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
"In SwLedOn, LedAddr:%X LEDPIN=%d\n",
- ledreg, pled->ledpin);
+ ledreg, pin);
ledcfg = rtl_read_byte(rtlpriv, ledreg);
ledcfg |= BIT(5); /*Set 0x4c[21]*/
ledcfg &= ~(BIT(7) | BIT(6) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
/*Clear 0x4c[23:22] and 0x4c[19:16]*/
rtl_write_byte(rtlpriv, ledreg, ledcfg); /*SW control led0 on.*/
- pled->ledon = true;
}
-void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 ledcfg;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -110,18 +99,17 @@ void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
default:
rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
- "switch case %#x not processed\n", pled->ledpin);
+ "switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
}
-void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u16 ledreg = REG_LEDCFG1;
struct rtl_priv *rtlpriv = rtl_priv(hw);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_LED0:
ledreg = REG_LEDCFG1;
break;
@@ -137,7 +125,7 @@ void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
"In SwLedOff,LedAddr:%X LEDPIN=%d\n",
- ledreg, pled->ledpin);
+ ledreg, pin);
/*Open-drain arrangement for controlling the LED*/
if (rtlpriv->ledctl.led_opendrain) {
u8 ledcfg = rtl_read_byte(rtlpriv, ledreg);
@@ -152,23 +140,13 @@ void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
} else {
rtl_write_byte(rtlpriv, ledreg, 0x28);
}
-
- pled->ledon = false;
-}
-
-void rtl8821ae_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl8821ae_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl8821ae_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
}
static void _rtl8821ae_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
switch (ledaction) {
@@ -176,15 +154,15 @@ static void _rtl8821ae_sw_led_control(struct ieee80211_hw *hw,
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
- rtl8812ae_sw_led_on(hw, pled0);
+ rtl8812ae_sw_led_on(hw, pin0);
else
- rtl8821ae_sw_led_on(hw, pled0);
+ rtl8821ae_sw_led_on(hw, pin0);
break;
case LED_CTL_POWER_OFF:
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
- rtl8812ae_sw_led_off(hw, pled0);
+ rtl8812ae_sw_led_off(hw, pin0);
else
- rtl8821ae_sw_led_off(hw, pled0);
+ rtl8821ae_sw_led_off(hw, pin0);
break;
default:
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h
index 249a37a8d9db..76d5c0b0e39e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h
@@ -4,11 +4,10 @@
#ifndef __RTL8821AE_LED_H__
#define __RTL8821AE_LED_H__
-void rtl8821ae_init_sw_leds(struct ieee80211_hw *hw);
-void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl8821ae_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
index 950542a24e31..0bca542e103f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
@@ -269,7 +269,6 @@ static struct rtl_hal_ops rtl8821ae_hal_ops = {
.tx_polling = rtl8821ae_tx_polling,
.enable_hw_sec = rtl8821ae_enable_hw_security_config,
.set_key = rtl8821ae_set_key,
- .init_sw_leds = rtl8821ae_init_sw_leds,
.get_bbreg = rtl8821ae_phy_query_bb_reg,
.set_bbreg = rtl8821ae_phy_set_bb_reg,
.get_rfreg = rtl8821ae_phy_query_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
index a8eebafb9a7e..30bf2775a335 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
@@ -164,13 +164,17 @@ static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val,
u16 wvalue;
u16 index;
__le32 data;
+ int ret;
request = REALTEK_USB_VENQT_CMD_REQ;
index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
wvalue = (u16)(addr&0x0000ffff);
data = cpu_to_le32(val);
- _usbctrl_vendorreq_async_write(udev, request, wvalue, index, &data,
- len);
+
+ ret = _usbctrl_vendorreq_async_write(udev, request, wvalue,
+ index, &data, len);
+ if (ret < 0)
+ dev_err(&udev->dev, "error %d writing at 0x%x\n", ret, addr);
}
static void _usb_write8_async(struct rtl_priv *rtlpriv, u32 addr, u8 val)
@@ -194,28 +198,6 @@ static void _usb_write32_async(struct rtl_priv *rtlpriv, u32 addr, u32 val)
_usb_write_async(to_usb_device(dev), addr, val, 4);
}
-static void _usb_writen_sync(struct rtl_priv *rtlpriv, u32 addr, void *data,
- u16 len)
-{
- struct device *dev = rtlpriv->io.dev;
- struct usb_device *udev = to_usb_device(dev);
- u8 request = REALTEK_USB_VENQT_CMD_REQ;
- u8 reqtype = REALTEK_USB_VENQT_WRITE;
- u16 wvalue;
- u16 index = REALTEK_USB_VENQT_CMD_IDX;
- int pipe = usb_sndctrlpipe(udev, 0); /* write_out */
- u8 *buffer;
-
- wvalue = (u16)(addr & 0x0000ffff);
- buffer = kmemdup(data, len, GFP_ATOMIC);
- if (!buffer)
- return;
- usb_control_msg(udev, pipe, request, reqtype, wvalue,
- index, buffer, len, 50);
-
- kfree(buffer);
-}
-
static void _rtl_usb_io_handler_init(struct device *dev,
struct ieee80211_hw *hw)
{
@@ -229,7 +211,6 @@ static void _rtl_usb_io_handler_init(struct device *dev,
rtlpriv->io.read8_sync = _usb_read8_sync;
rtlpriv->io.read16_sync = _usb_read16_sync;
rtlpriv->io.read32_sync = _usb_read32_sync;
- rtlpriv->io.writen_sync = _usb_writen_sync;
}
static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw)
@@ -433,7 +414,7 @@ static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw,
skb_pull(skb, RTL_RX_DESC_SIZE);
rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb);
skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift));
- hdr = (struct ieee80211_hdr *)(skb->data);
+ hdr = rtl_get_hdr(skb);
fc = hdr->frame_control;
if (!stats.crc) {
memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
@@ -475,7 +456,7 @@ static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw,
skb_pull(skb, RTL_RX_DESC_SIZE);
rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb);
skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift));
- hdr = (struct ieee80211_hdr *)(skb->data);
+ hdr = rtl_get_hdr(skb);
fc = hdr->frame_control;
if (!stats.crc) {
memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
@@ -926,7 +907,7 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct rtl_tx_desc *pdesc = NULL;
struct rtl_tcb_desc tcb_desc;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
__le16 fc = hdr->frame_control;
u8 *pda_addr = hdr->addr1;
@@ -961,7 +942,7 @@ static int rtl_usb_tx(struct ieee80211_hw *hw,
{
struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
__le16 fc = hdr->frame_control;
u16 hw_queue;
@@ -1068,7 +1049,7 @@ int rtl_usb_probe(struct usb_interface *intf,
pr_err("Can't init_sw_vars\n");
goto error_out;
}
- rtlpriv->cfg->ops->init_sw_leds(hw);
+ rtl_init_sw_leds(hw);
err = ieee80211_register_hw(hw);
if (err) {
@@ -1117,7 +1098,6 @@ void rtl_usb_disconnect(struct usb_interface *intf)
rtl_usb_deinit(hw);
rtl_deinit_core(hw);
kfree(rtlpriv->usb_data);
- rtlpriv->cfg->ops->deinit_sw_leds(hw);
rtlpriv->cfg->ops->deinit_sw_vars(hw);
_rtl_usb_io_handler_release(hw);
usb_put_dev(rtlusb->udev);
diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h
index 082af216760f..2e7e04f91279 100644
--- a/drivers/net/wireless/realtek/rtlwifi/wifi.h
+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
@@ -1070,18 +1070,10 @@ struct rtl_probe_rsp {
struct rtl_info_element info_element[];
} __packed;
-/*LED related.*/
-/*ledpin Identify how to implement this SW led.*/
-struct rtl_led {
- void *hw;
- enum rtl_led_pin ledpin;
- bool ledon;
-};
-
struct rtl_led_ctl {
bool led_opendrain;
- struct rtl_led sw_led0;
- struct rtl_led sw_led1;
+ enum rtl_led_pin sw_led0;
+ enum rtl_led_pin sw_led1;
};
struct rtl_qos_parameters {
@@ -1465,8 +1457,6 @@ struct rtl_io {
void (*write8_async)(struct rtl_priv *rtlpriv, u32 addr, u8 val);
void (*write16_async)(struct rtl_priv *rtlpriv, u32 addr, u16 val);
void (*write32_async)(struct rtl_priv *rtlpriv, u32 addr, u32 val);
- void (*writen_sync)(struct rtl_priv *rtlpriv, u32 addr, void *buf,
- u16 len);
u8 (*read8_sync)(struct rtl_priv *rtlpriv, u32 addr);
u16 (*read16_sync)(struct rtl_priv *rtlpriv, u32 addr);
@@ -1673,8 +1663,6 @@ struct rtl_hal {
bool fw_clk_change_in_progress;
bool allow_sw_to_change_hwclc;
u8 fw_ps_state;
- /**/
- bool driver_going2unload;
/*AMPDU init min space*/
u8 minspace_cfg; /*For Min spacing configurations */
@@ -2289,8 +2277,6 @@ struct rtl_hal_ops {
void (*set_key)(struct ieee80211_hw *hw, u32 key_index,
u8 *macaddr, bool is_group, u8 enc_algo,
bool is_wepkey, bool clear_all);
- void (*init_sw_leds)(struct ieee80211_hw *hw);
- void (*deinit_sw_leds)(struct ieee80211_hw *hw);
u32 (*get_bbreg)(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask);
void (*set_bbreg)(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask,
u32 data);
@@ -2300,7 +2286,6 @@ struct rtl_hal_ops {
u32 regaddr, u32 bitmask, u32 data);
void (*linked_set_reg)(struct ieee80211_hw *hw);
void (*chk_switch_dmdp)(struct ieee80211_hw *hw);
- void (*dualmac_easy_concurrent)(struct ieee80211_hw *hw);
void (*dualmac_switch_to_dmdp)(struct ieee80211_hw *hw);
bool (*phy_rf6052_config)(struct ieee80211_hw *hw);
void (*phy_rf6052_set_cck_txpower)(struct ieee80211_hw *hw,
@@ -2465,7 +2450,6 @@ struct rtl_works {
/*timer */
struct timer_list watchdog_timer;
- struct timer_list dualmac_easyconcurrent_retrytimer;
struct timer_list fw_clockoff_timer;
struct timer_list fast_antenna_training_timer;
/*task */
@@ -2498,14 +2482,6 @@ struct rtl_debug {
#define MIMO_PS_DYNAMIC 1
#define MIMO_PS_NOLIMIT 3
-struct rtl_dualmac_easy_concurrent_ctl {
- enum band_type currentbandtype_backfordmdp;
- bool close_bbandrf_for_dmsp;
- bool change_to_dmdp;
- bool change_to_dmsp;
- bool switch_in_process;
-};
-
struct rtl_dmsp_ctl {
bool activescan_for_slaveofdmsp;
bool scan_for_anothermac_fordmsp;
@@ -2746,7 +2722,6 @@ struct rtl_priv {
struct list_head list;
struct rtl_priv *buddy_priv;
struct rtl_global_var *glb_var;
- struct rtl_dualmac_easy_concurrent_ctl easy_concurrent_ctl;
struct rtl_dmsp_ctl dmsp_ctl;
struct rtl_locks locks;
struct rtl_works works;
diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig
index 29eb2f8e0eb7..cffad1c01249 100644
--- a/drivers/net/wireless/realtek/rtw88/Kconfig
+++ b/drivers/net/wireless/realtek/rtw88/Kconfig
@@ -111,6 +111,17 @@ config RTW88_8723DE
802.11n PCIe wireless network adapter
+config RTW88_8723DS
+ tristate "Realtek 8723DS SDIO wireless network adapter"
+ depends on MMC
+ select RTW88_CORE
+ select RTW88_SDIO
+ select RTW88_8723D
+ help
+ Select this option will enable support for 8723DS chipset
+
+ 802.11n SDIO wireless network adapter
+
config RTW88_8723DU
tristate "Realtek 8723DU USB wireless network adapter"
depends on USB
diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile
index 82979b30ae8d..fd212c09d88a 100644
--- a/drivers/net/wireless/realtek/rtw88/Makefile
+++ b/drivers/net/wireless/realtek/rtw88/Makefile
@@ -50,6 +50,9 @@ rtw88_8723d-objs := rtw8723d.o rtw8723d_table.o
obj-$(CONFIG_RTW88_8723DE) += rtw88_8723de.o
rtw88_8723de-objs := rtw8723de.o
+obj-$(CONFIG_RTW88_8723DS) += rtw88_8723ds.o
+rtw88_8723ds-objs := rtw8723ds.o
+
obj-$(CONFIG_RTW88_8723DU) += rtw88_8723du.o
rtw88_8723du-objs := rtw8723du.o
diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c
index fa3d73b333ba..f8ba133baff0 100644
--- a/drivers/net/wireless/realtek/rtw88/debug.c
+++ b/drivers/net/wireless/realtek/rtw88/debug.c
@@ -183,8 +183,8 @@ static int rtw_debugfs_copy_from_user(char tmp[], int size,
tmp_len = (count > size - 1 ? size - 1 : count);
- if (!buffer || copy_from_user(tmp, buffer, tmp_len))
- return count;
+ if (copy_from_user(tmp, buffer, tmp_len))
+ return -EFAULT;
tmp[tmp_len] = '\0';
@@ -201,13 +201,16 @@ static ssize_t rtw_debugfs_set_read_reg(struct file *filp,
char tmp[32 + 1];
u32 addr, len;
int num;
+ int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2);
+ if (ret)
+ return ret;
num = sscanf(tmp, "%x %x", &addr, &len);
if (num != 2)
- return count;
+ return -EINVAL;
if (len != 1 && len != 2 && len != 4) {
rtw_warn(rtwdev, "read reg setting wrong len\n");
@@ -288,8 +291,11 @@ static ssize_t rtw_debugfs_set_rsvd_page(struct file *filp,
char tmp[32 + 1];
u32 offset, page_num;
int num;
+ int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2);
+ if (ret)
+ return ret;
num = sscanf(tmp, "%d %d", &offset, &page_num);
@@ -314,8 +320,11 @@ static ssize_t rtw_debugfs_set_single_input(struct file *filp,
char tmp[32 + 1];
u32 input;
int num;
+ int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+ if (ret)
+ return ret;
num = kstrtoint(tmp, 0, &input);
@@ -338,14 +347,17 @@ static ssize_t rtw_debugfs_set_write_reg(struct file *filp,
char tmp[32 + 1];
u32 addr, val, len;
int num;
+ int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
+ if (ret)
+ return ret;
/* write BB/MAC register */
num = sscanf(tmp, "%x %x %x", &addr, &val, &len);
if (num != 3)
- return count;
+ return -EINVAL;
switch (len) {
case 1:
@@ -381,8 +393,11 @@ static ssize_t rtw_debugfs_set_h2c(struct file *filp,
char tmp[32 + 1];
u8 param[8];
int num;
+ int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
+ if (ret)
+ return ret;
num = sscanf(tmp, "%hhx,%hhx,%hhx,%hhx,%hhx,%hhx,%hhx,%hhx",
&param[0], &param[1], &param[2], &param[3],
@@ -408,14 +423,17 @@ static ssize_t rtw_debugfs_set_rf_write(struct file *filp,
char tmp[32 + 1];
u32 path, addr, mask, val;
int num;
+ int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 4);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 4);
+ if (ret)
+ return ret;
num = sscanf(tmp, "%x %x %x %x", &path, &addr, &mask, &val);
if (num != 4) {
rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n");
- return count;
+ return -EINVAL;
}
mutex_lock(&rtwdev->mutex);
@@ -438,14 +456,17 @@ static ssize_t rtw_debugfs_set_rf_read(struct file *filp,
char tmp[32 + 1];
u32 path, addr, mask;
int num;
+ int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
+ if (ret)
+ return ret;
num = sscanf(tmp, "%x %x %x", &path, &addr, &mask);
if (num != 3) {
rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n");
- return count;
+ return -EINVAL;
}
debugfs_priv->rf_path = path;
@@ -467,7 +488,9 @@ static ssize_t rtw_debugfs_set_fix_rate(struct file *filp,
char tmp[32 + 1];
int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+ if (ret)
+ return ret;
ret = kstrtou8(tmp, 0, &fix_rate);
if (ret) {
@@ -860,7 +883,9 @@ static ssize_t rtw_debugfs_set_coex_enable(struct file *filp,
bool enable;
int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+ if (ret)
+ return ret;
ret = kstrtobool(tmp, &enable);
if (ret) {
@@ -930,7 +955,9 @@ static ssize_t rtw_debugfs_set_fw_crash(struct file *filp,
bool input;
int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+ if (ret)
+ return ret;
ret = kstrtobool(tmp, &input);
if (ret)
diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
index 2a8ccc8a7f60..567bbedd8ee0 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.c
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -308,6 +308,57 @@ void rtw_fw_c2h_cmd_isr(struct rtw_dev *rtwdev)
}
EXPORT_SYMBOL(rtw_fw_c2h_cmd_isr);
+static void rtw_fw_send_h2c_command_register(struct rtw_dev *rtwdev,
+ struct rtw_h2c_register *h2c)
+{
+ u32 box_reg, box_ex_reg;
+ u8 box_state, box;
+ int ret;
+
+ rtw_dbg(rtwdev, RTW_DBG_FW, "send H2C content %08x %08x\n", h2c->w0,
+ h2c->w1);
+
+ lockdep_assert_held(&rtwdev->mutex);
+
+ box = rtwdev->h2c.last_box_num;
+ switch (box) {
+ case 0:
+ box_reg = REG_HMEBOX0;
+ box_ex_reg = REG_HMEBOX0_EX;
+ break;
+ case 1:
+ box_reg = REG_HMEBOX1;
+ box_ex_reg = REG_HMEBOX1_EX;
+ break;
+ case 2:
+ box_reg = REG_HMEBOX2;
+ box_ex_reg = REG_HMEBOX2_EX;
+ break;
+ case 3:
+ box_reg = REG_HMEBOX3;
+ box_ex_reg = REG_HMEBOX3_EX;
+ break;
+ default:
+ WARN(1, "invalid h2c mail box number\n");
+ return;
+ }
+
+ ret = read_poll_timeout_atomic(rtw_read8, box_state,
+ !((box_state >> box) & 0x1), 100, 3000,
+ false, rtwdev, REG_HMETFR);
+
+ if (ret) {
+ rtw_err(rtwdev, "failed to send h2c command\n");
+ return;
+ }
+
+ rtw_write32(rtwdev, box_ex_reg, h2c->w1);
+ rtw_write32(rtwdev, box_reg, h2c->w0);
+
+ if (++rtwdev->h2c.last_box_num >= 4)
+ rtwdev->h2c.last_box_num = 0;
+}
+
static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev,
u8 *h2c)
{
@@ -468,6 +519,23 @@ void rtw_fw_query_bt_info(struct rtw_dev *rtwdev)
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
}
+void rtw_fw_default_port(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
+{
+ struct rtw_h2c_register h2c = {};
+
+ if (rtwvif->net_type != RTW_NET_MGD_LINKED)
+ return;
+
+ /* Leave LPS before default port H2C so FW timer is correct */
+ rtw_leave_lps(rtwdev);
+
+ h2c.w0 = u32_encode_bits(H2C_CMD_DEFAULT_PORT, RTW_H2C_W0_CMDID) |
+ u32_encode_bits(rtwvif->port, RTW_H2C_DEFAULT_PORT_W0_PORTID) |
+ u32_encode_bits(rtwvif->mac_id, RTW_H2C_DEFAULT_PORT_W0_MACID);
+
+ rtw_fw_send_h2c_command_register(rtwdev, &h2c);
+}
+
void rtw_fw_wl_ch_info(struct rtw_dev *rtwdev, u8 link, u8 ch, u8 bw)
{
u8 h2c_pkt[H2C_PKT_SIZE] = {0};
diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h
index 397cbc3f6af6..43ccdf9965ac 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.h
+++ b/drivers/net/wireless/realtek/rtw88/fw.h
@@ -81,6 +81,17 @@ struct rtw_c2h_adaptivity {
u8 option;
} __packed;
+struct rtw_h2c_register {
+ u32 w0;
+ u32 w1;
+} __packed;
+
+#define RTW_H2C_W0_CMDID GENMASK(7, 0)
+
+/* H2C_CMD_DEFAULT_PORT command */
+#define RTW_H2C_DEFAULT_PORT_W0_PORTID GENMASK(15, 8)
+#define RTW_H2C_DEFAULT_PORT_W0_MACID GENMASK(23, 16)
+
struct rtw_h2c_cmd {
__le32 msg;
__le32 msg_ext;
@@ -530,6 +541,7 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
#define H2C_CMD_MEDIA_STATUS_RPT 0x01
#define H2C_CMD_SET_PWR_MODE 0x20
#define H2C_CMD_LPS_PG_INFO 0x2b
+#define H2C_CMD_DEFAULT_PORT 0x2c
#define H2C_CMD_RA_INFO 0x40
#define H2C_CMD_RSSI_MONITOR 0x42
#define H2C_CMD_BCN_FILTER_OFFLOAD_P0 0x56
@@ -801,6 +813,7 @@ void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb);
void rtw_fw_send_general_info(struct rtw_dev *rtwdev);
void rtw_fw_send_phydm_info(struct rtw_dev *rtwdev);
+void rtw_fw_default_port(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif);
void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para);
void rtw_fw_inform_rfk_status(struct rtw_dev *rtwdev, bool start);
diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c
index a168f36c38ec..298663b03580 100644
--- a/drivers/net/wireless/realtek/rtw88/mac.c
+++ b/drivers/net/wireless/realtek/rtw88/mac.c
@@ -794,8 +794,10 @@ static int __rtw_download_firmware(struct rtw_dev *rtwdev,
wlan_cpu_enable(rtwdev, true);
- if (!ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp))
- return -EBUSY;
+ if (!ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp)) {
+ ret = -EBUSY;
+ goto dlfw_fail;
+ }
ret = download_firmware_validate(rtwdev);
if (ret)
diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
index 144618bb94c8..a99b53d44267 100644
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -43,7 +43,11 @@ static void rtw_ops_wake_tx_queue(struct ieee80211_hw *hw,
list_add_tail(&rtwtxq->list, &rtwdev->txqs);
spin_unlock_bh(&rtwdev->txq_lock);
- queue_work(rtwdev->tx_wq, &rtwdev->tx_work);
+ /* ensure to dequeue EAPOL (4/4) at the right time */
+ if (txq->ac == IEEE80211_AC_VO)
+ __rtw_tx_work(rtwdev);
+ else
+ queue_work(rtwdev->tx_wq, &rtwdev->tx_work);
}
static int rtw_ops_start(struct ieee80211_hw *hw)
@@ -164,8 +168,10 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw,
mutex_lock(&rtwdev->mutex);
port = find_first_zero_bit(rtwdev->hw_port, RTW_PORT_NUM);
- if (port >= RTW_PORT_NUM)
+ if (port >= RTW_PORT_NUM) {
+ mutex_unlock(&rtwdev->mutex);
return -EINVAL;
+ }
set_bit(port, rtwdev->hw_port);
rtwvif->port = port;
@@ -376,6 +382,7 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
rtw_fw_download_rsvd_page(rtwdev);
rtw_send_rsvd_page_h2c(rtwdev);
+ rtw_fw_default_port(rtwdev, rtwvif);
rtw_coex_media_status_notify(rtwdev, vif->cfg.assoc);
if (rtw_bf_support)
rtw_bf_assoc(rtwdev, vif, conf);
@@ -447,6 +454,7 @@ static int rtw_ops_start_ap(struct ieee80211_hw *hw,
const struct rtw_chip_info *chip = rtwdev->chip;
mutex_lock(&rtwdev->mutex);
+ rtw_write32_set(rtwdev, REG_TCR, BIT_TCR_UPDATE_HGQMD);
rtwdev->ap_active = true;
rtw_store_op_chan(rtwdev, true);
chip->ops->phy_calibration(rtwdev);
@@ -462,6 +470,7 @@ static void rtw_ops_stop_ap(struct ieee80211_hw *hw,
struct rtw_dev *rtwdev = hw->priv;
mutex_lock(&rtwdev->mutex);
+ rtw_write32_clr(rtwdev, REG_TCR, BIT_TCR_UPDATE_HGQMD);
rtwdev->ap_active = false;
if (!rtw_core_check_sta_active(rtwdev))
rtw_clear_op_chan(rtwdev);
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index 9447a3aae3b5..c853e2f2d448 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -334,12 +334,15 @@ int rtw_sta_add(struct rtw_dev *rtwdev, struct ieee80211_sta *sta,
struct ieee80211_vif *vif)
{
struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
+ struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
int i;
si->mac_id = rtw_acquire_macid(rtwdev);
if (si->mac_id >= RTW_MAX_MAC_ID_NUM)
return -ENOSPC;
+ if (vif->type == NL80211_IFTYPE_STATION && vif->cfg.assoc == 0)
+ rtwvif->mac_id = si->mac_id;
si->rtwdev = rtwdev;
si->sta = sta;
si->vif = vif;
@@ -2340,6 +2343,9 @@ static void rtw_port_switch_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
rtw_dbg(rtwdev, RTW_DBG_STATE, "AP port switch from %d -> %d\n",
rtwvif_ap->port, rtwvif_target->port);
+ /* Leave LPS so the value swapped are not in PS mode */
+ rtw_leave_lps(rtwdev);
+
reg1 = &rtwvif_ap->conf->net_type;
reg2 = &rtwvif_target->conf->net_type;
rtw_swap_reg_mask(rtwdev, reg1, reg2);
@@ -2358,6 +2364,8 @@ static void rtw_port_switch_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
swap(rtwvif_target->port, rtwvif_ap->port);
swap(rtwvif_target->conf, rtwvif_ap->conf);
+
+ rtw_fw_default_port(rtwdev, rtwvif_target);
}
void rtw_core_port_switch(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
@@ -2403,10 +2411,13 @@ void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable)
if (!rtwdev->ap_active)
return;
- if (enable)
+ if (enable) {
rtw_write32_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
- else
+ rtw_write32_clr(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE);
+ } else {
rtw_write32_clr(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
+ rtw_write32_set(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE);
+ }
}
MODULE_AUTHOR("Realtek Corporation");
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 9e841f6991a9..f9dd2ab941c8 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -803,6 +803,7 @@ struct rtw_bf_info {
struct rtw_vif {
enum rtw_net_type net_type;
u16 aid;
+ u8 mac_id; /* for STA mode only */
u8 mac_addr[ETH_ALEN];
u8 bssid[ETH_ALEN];
u8 port;
diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
index 672ddde80816..44a8fff34cdd 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.c
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
@@ -738,8 +738,9 @@ static void __rtw_pci_flush_queues(struct rtw_dev *rtwdev, u32 pci_queues,
u8 q;
for (q = 0; q < RTK_MAX_TX_QUEUE_NUM; q++) {
- /* It may be not necessary to flush BCN and H2C tx queues. */
- if (q == RTW_TX_QUEUE_BCN || q == RTW_TX_QUEUE_H2C)
+ /* Unnecessary to flush BCN, H2C and HI tx queues. */
+ if (q == RTW_TX_QUEUE_BCN || q == RTW_TX_QUEUE_H2C ||
+ q == RTW_TX_QUEUE_HI0)
continue;
if (pci_queues & BIT(q))
diff --git a/drivers/net/wireless/realtek/rtw88/ps.c b/drivers/net/wireless/realtek/rtw88/ps.c
index 53933fb38a33..43e80a3a8136 100644
--- a/drivers/net/wireless/realtek/rtw88/ps.c
+++ b/drivers/net/wireless/realtek/rtw88/ps.c
@@ -18,6 +18,7 @@ static int rtw_ips_pwr_up(struct rtw_dev *rtwdev)
if (ret)
rtw_err(rtwdev, "leave idle state failed\n");
+ rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE);
rtw_set_channel(rtwdev);
return ret;
@@ -63,8 +64,6 @@ int rtw_leave_ips(struct rtw_dev *rtwdev)
rtw_iterate_vifs(rtwdev, rtw_restore_port_cfg_iter, rtwdev);
- rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE);
-
return 0;
}
diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h
index 2a2ae2081f34..7c6c11d50ff3 100644
--- a/drivers/net/wireless/realtek/rtw88/reg.h
+++ b/drivers/net/wireless/realtek/rtw88/reg.h
@@ -378,6 +378,7 @@
#define BIT_SIFS_BK_EN BIT(12)
#define REG_TXPAUSE 0x0522
#define BIT_AC_QUEUE GENMASK(7, 0)
+#define BIT_HIGH_QUEUE BIT(5)
#define REG_RD_CTRL 0x0524
#define BIT_EDCCA_MSK_CNTDOWN_EN BIT(11)
#define BIT_DIS_TXOP_CFE BIT(10)
@@ -410,6 +411,7 @@
#define REG_TCR 0x0604
#define BIT_PWRMGT_HWDATA_EN BIT(7)
#define BIT_TCR_UPDATE_TIMIE BIT(5)
+#define BIT_TCR_UPDATE_HGQMD BIT(4)
#define REG_RCR 0x0608
#define BIT_APP_FCS BIT(31)
#define BIT_APP_MIC BIT(30)
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index 06e7454c9ca6..c575476a0020 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -216,6 +216,12 @@ static void rtw8723du_efuse_parsing(struct rtw_efuse *efuse,
ether_addr_copy(efuse->addr, map->u.mac_addr);
}
+static void rtw8723ds_efuse_parsing(struct rtw_efuse *efuse,
+ struct rtw8723d_efuse *map)
+{
+ ether_addr_copy(efuse->addr, map->s.mac_addr);
+}
+
static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
{
struct rtw_efuse *efuse = &rtwdev->efuse;
@@ -248,6 +254,9 @@ static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
case RTW_HCI_TYPE_USB:
rtw8723du_efuse_parsing(efuse, map);
break;
+ case RTW_HCI_TYPE_SDIO:
+ rtw8723ds_efuse_parsing(efuse, map);
+ break;
default:
/* unsupported now */
return -ENOTSUPP;
@@ -1961,15 +1970,17 @@ static void rtw8723d_fill_txdesc_checksum(struct rtw_dev *rtwdev,
size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */
__le16 chksum = 0;
__le16 *data = (__le16 *)(txdesc);
+ struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)txdesc;
- SET_TX_DESC_TXDESC_CHECKSUM(txdesc, 0x0000);
+ le32p_replace_bits(&tx_desc->w7, 0, RTW_TX_DESC_W7_TXDESC_CHECKSUM);
while (words--)
chksum ^= *data++;
chksum = ~chksum;
- SET_TX_DESC_TXDESC_CHECKSUM(txdesc, __le16_to_cpu(chksum));
+ le32p_replace_bits(&tx_desc->w7, __le16_to_cpu(chksum),
+ RTW_TX_DESC_W7_TXDESC_CHECKSUM);
}
static struct rtw_chip_ops rtw8723d_ops = {
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
index a356318a5c15..3642a2c7f80c 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
@@ -49,6 +49,11 @@ struct rtw8723du_efuse {
u8 mac_addr[ETH_ALEN]; /* 0x107 */
};
+struct rtw8723ds_efuse {
+ u8 res4[0x4a]; /* 0xd0 */
+ u8 mac_addr[ETH_ALEN]; /* 0x11a */
+};
+
struct rtw8723d_efuse {
__le16 rtl_id;
u8 rsvd[2];
@@ -80,6 +85,7 @@ struct rtw8723d_efuse {
union {
struct rtw8723de_efuse e;
struct rtw8723du_efuse u;
+ struct rtw8723ds_efuse s;
};
};
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723ds.c b/drivers/net/wireless/realtek/rtw88/rtw8723ds.c
new file mode 100644
index 000000000000..e5b6960ba0a0
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723ds.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ */
+
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/module.h>
+#include "main.h"
+#include "rtw8723d.h"
+#include "sdio.h"
+
+static const struct sdio_device_id rtw_8723ds_id_table[] = {
+ {
+ SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK,
+ SDIO_DEVICE_ID_REALTEK_RTW8723DS_1ANT),
+ .driver_data = (kernel_ulong_t)&rtw8723d_hw_spec,
+ },
+ {
+ SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK,
+ SDIO_DEVICE_ID_REALTEK_RTW8723DS_2ANT),
+ .driver_data = (kernel_ulong_t)&rtw8723d_hw_spec,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(sdio, rtw_8723ds_id_table);
+
+static struct sdio_driver rtw_8723ds_driver = {
+ .name = "rtw_8723ds",
+ .probe = rtw_sdio_probe,
+ .remove = rtw_sdio_remove,
+ .id_table = rtw_8723ds_id_table,
+ .drv = {
+ .pm = &rtw_sdio_pm_ops,
+ .shutdown = rtw_sdio_shutdown,
+ }
+};
+module_sdio_driver(rtw_8723ds_driver);
+
+MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
+MODULE_DESCRIPTION("Realtek 802.11n wireless 8723ds driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
index 06fce7c3adda..2c1fb2dabd40 100644
--- a/drivers/net/wireless/realtek/rtw88/sdio.c
+++ b/drivers/net/wireless/realtek/rtw88/sdio.c
@@ -998,9 +998,9 @@ static void rtw_sdio_rxfifo_recv(struct rtw_dev *rtwdev, u32 rx_len)
static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev)
{
- u32 rx_len, total_rx_bytes = 0;
+ u32 rx_len, hisr, total_rx_bytes = 0;
- while (total_rx_bytes < SZ_64K) {
+ do {
if (rtw_chip_wcpu_11n(rtwdev))
rx_len = rtw_read16(rtwdev, REG_SDIO_RX0_REQ_LEN);
else
@@ -1012,7 +1012,25 @@ static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev)
rtw_sdio_rxfifo_recv(rtwdev, rx_len);
total_rx_bytes += rx_len;
- }
+
+ if (rtw_chip_wcpu_11n(rtwdev)) {
+ /* Stop if no more RX requests are pending, even if
+ * rx_len could be greater than zero in the next
+ * iteration. This is needed because the RX buffer may
+ * already contain data while either HW or FW are not
+ * done filling that buffer yet. Still reading the
+ * buffer can result in packets where
+ * rtw_rx_pkt_stat.pkt_len is zero or points beyond the
+ * end of the buffer.
+ */
+ hisr = rtw_read32(rtwdev, REG_SDIO_HISR);
+ } else {
+ /* RTW_WCPU_11AC chips have improved hardware or
+ * firmware and can use rx_len unconditionally.
+ */
+ hisr = REG_SDIO_HISR_RX_REQUEST;
+ }
+ } while (total_rx_bytes < SZ_64K && hisr & REG_SDIO_HISR_RX_REQUEST);
}
static void rtw_sdio_handle_interrupt(struct sdio_func *sdio_func)
diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c
index bb5c7492c98b..2821119dc930 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.c
+++ b/drivers/net/wireless/realtek/rtw88/tx.c
@@ -34,43 +34,57 @@ void rtw_tx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb)
{
- __le32 *txdesc = (__le32 *)skb->data;
-
- SET_TX_DESC_TXPKTSIZE(txdesc, pkt_info->tx_pkt_size);
- SET_TX_DESC_OFFSET(txdesc, pkt_info->offset);
- SET_TX_DESC_PKT_OFFSET(txdesc, pkt_info->pkt_offset);
- SET_TX_DESC_QSEL(txdesc, pkt_info->qsel);
- SET_TX_DESC_BMC(txdesc, pkt_info->bmc);
- SET_TX_DESC_RATE_ID(txdesc, pkt_info->rate_id);
- SET_TX_DESC_DATARATE(txdesc, pkt_info->rate);
- SET_TX_DESC_DISDATAFB(txdesc, pkt_info->dis_rate_fallback);
- SET_TX_DESC_USE_RATE(txdesc, pkt_info->use_rate);
- SET_TX_DESC_SEC_TYPE(txdesc, pkt_info->sec_type);
- SET_TX_DESC_DATA_BW(txdesc, pkt_info->bw);
- SET_TX_DESC_SW_SEQ(txdesc, pkt_info->seq);
- SET_TX_DESC_MAX_AGG_NUM(txdesc, pkt_info->ampdu_factor);
- SET_TX_DESC_AMPDU_DENSITY(txdesc, pkt_info->ampdu_density);
- SET_TX_DESC_DATA_STBC(txdesc, pkt_info->stbc);
- SET_TX_DESC_DATA_LDPC(txdesc, pkt_info->ldpc);
- SET_TX_DESC_AGG_EN(txdesc, pkt_info->ampdu_en);
- SET_TX_DESC_LS(txdesc, pkt_info->ls);
- SET_TX_DESC_DATA_SHORT(txdesc, pkt_info->short_gi);
- SET_TX_DESC_SPE_RPT(txdesc, pkt_info->report);
- SET_TX_DESC_SW_DEFINE(txdesc, pkt_info->sn);
- SET_TX_DESC_USE_RTS(txdesc, pkt_info->rts);
+ struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)skb->data;
+ bool more_data = false;
+
+ if (pkt_info->qsel == TX_DESC_QSEL_HIGH)
+ more_data = true;
+
+ tx_desc->w0 = le32_encode_bits(pkt_info->tx_pkt_size, RTW_TX_DESC_W0_TXPKTSIZE) |
+ le32_encode_bits(pkt_info->offset, RTW_TX_DESC_W0_OFFSET) |
+ le32_encode_bits(pkt_info->bmc, RTW_TX_DESC_W0_BMC) |
+ le32_encode_bits(pkt_info->ls, RTW_TX_DESC_W0_LS) |
+ le32_encode_bits(pkt_info->dis_qselseq, RTW_TX_DESC_W0_DISQSELSEQ);
+
+ tx_desc->w1 = le32_encode_bits(pkt_info->qsel, RTW_TX_DESC_W1_QSEL) |
+ le32_encode_bits(pkt_info->rate_id, RTW_TX_DESC_W1_RATE_ID) |
+ le32_encode_bits(pkt_info->sec_type, RTW_TX_DESC_W1_SEC_TYPE) |
+ le32_encode_bits(pkt_info->pkt_offset, RTW_TX_DESC_W1_PKT_OFFSET) |
+ le32_encode_bits(more_data, RTW_TX_DESC_W1_MORE_DATA);
+
+ tx_desc->w2 = le32_encode_bits(pkt_info->ampdu_en, RTW_TX_DESC_W2_AGG_EN) |
+ le32_encode_bits(pkt_info->report, RTW_TX_DESC_W2_SPE_RPT) |
+ le32_encode_bits(pkt_info->ampdu_density, RTW_TX_DESC_W2_AMPDU_DEN) |
+ le32_encode_bits(pkt_info->bt_null, RTW_TX_DESC_W2_BT_NULL);
+
+ tx_desc->w3 = le32_encode_bits(pkt_info->hw_ssn_sel, RTW_TX_DESC_W3_HW_SSN_SEL) |
+ le32_encode_bits(pkt_info->use_rate, RTW_TX_DESC_W3_USE_RATE) |
+ le32_encode_bits(pkt_info->dis_rate_fallback, RTW_TX_DESC_W3_DISDATAFB) |
+ le32_encode_bits(pkt_info->rts, RTW_TX_DESC_W3_USE_RTS) |
+ le32_encode_bits(pkt_info->nav_use_hdr, RTW_TX_DESC_W3_NAVUSEHDR) |
+ le32_encode_bits(pkt_info->ampdu_factor, RTW_TX_DESC_W3_MAX_AGG_NUM);
+
+ tx_desc->w4 = le32_encode_bits(pkt_info->rate, RTW_TX_DESC_W4_DATARATE);
+
+ tx_desc->w5 = le32_encode_bits(pkt_info->short_gi, RTW_TX_DESC_W5_DATA_SHORT) |
+ le32_encode_bits(pkt_info->bw, RTW_TX_DESC_W5_DATA_BW) |
+ le32_encode_bits(pkt_info->ldpc, RTW_TX_DESC_W5_DATA_LDPC) |
+ le32_encode_bits(pkt_info->stbc, RTW_TX_DESC_W5_DATA_STBC);
+
+ tx_desc->w6 = le32_encode_bits(pkt_info->sn, RTW_TX_DESC_W6_SW_DEFINE);
+
+ tx_desc->w8 = le32_encode_bits(pkt_info->en_hwseq, RTW_TX_DESC_W8_EN_HWSEQ);
+
+ tx_desc->w9 = le32_encode_bits(pkt_info->seq, RTW_TX_DESC_W9_SW_SEQ);
+
if (pkt_info->rts) {
- SET_TX_DESC_RTSRATE(txdesc, DESC_RATE24M);
- SET_TX_DESC_DATA_RTS_SHORT(txdesc, 1);
- }
- SET_TX_DESC_DISQSELSEQ(txdesc, pkt_info->dis_qselseq);
- SET_TX_DESC_EN_HWSEQ(txdesc, pkt_info->en_hwseq);
- SET_TX_DESC_HW_SSN_SEL(txdesc, pkt_info->hw_ssn_sel);
- SET_TX_DESC_NAVUSEHDR(txdesc, pkt_info->nav_use_hdr);
- SET_TX_DESC_BT_NULL(txdesc, pkt_info->bt_null);
- if (pkt_info->tim_offset) {
- SET_TX_DESC_TIM_EN(txdesc, 1);
- SET_TX_DESC_TIM_OFFSET(txdesc, pkt_info->tim_offset);
+ tx_desc->w4 |= le32_encode_bits(DESC_RATE24M, RTW_TX_DESC_W4_RTSRATE);
+ tx_desc->w5 |= le32_encode_bits(1, RTW_TX_DESC_W5_DATA_RTS_SHORT);
}
+
+ if (pkt_info->tim_offset)
+ tx_desc->w9 |= le32_encode_bits(1, RTW_TX_DESC_W9_TIM_EN) |
+ le32_encode_bits(pkt_info->tim_offset, RTW_TX_DESC_W9_TIM_OFFSET);
}
EXPORT_SYMBOL(rtw_tx_fill_tx_desc);
@@ -635,9 +649,8 @@ static void rtw_txq_push(struct rtw_dev *rtwdev,
rcu_read_unlock();
}
-void rtw_tx_work(struct work_struct *w)
+void __rtw_tx_work(struct rtw_dev *rtwdev)
{
- struct rtw_dev *rtwdev = container_of(w, struct rtw_dev, tx_work);
struct rtw_txq *rtwtxq, *tmp;
spin_lock_bh(&rtwdev->txq_lock);
@@ -658,6 +671,13 @@ void rtw_tx_work(struct work_struct *w)
spin_unlock_bh(&rtwdev->txq_lock);
}
+void rtw_tx_work(struct work_struct *w)
+{
+ struct rtw_dev *rtwdev = container_of(w, struct rtw_dev, tx_work);
+
+ __rtw_tx_work(rtwdev);
+}
+
void rtw_txq_init(struct rtw_dev *rtwdev, struct ieee80211_txq *txq)
{
struct rtw_txq *rtwtxq;
diff --git a/drivers/net/wireless/realtek/rtw88/tx.h b/drivers/net/wireless/realtek/rtw88/tx.h
index 197d5868c8ad..324189606257 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.h
+++ b/drivers/net/wireless/realtek/rtw88/tx.h
@@ -9,76 +9,53 @@
#define RTW_TX_PROBE_TIMEOUT msecs_to_jiffies(500)
-#define SET_TX_DESC_TXPKTSIZE(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, GENMASK(15, 0))
-#define SET_TX_DESC_OFFSET(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, GENMASK(23, 16))
-#define SET_TX_DESC_PKT_OFFSET(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(28, 24))
-#define SET_TX_DESC_QSEL(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(12, 8))
-#define SET_TX_DESC_BMC(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(24))
-#define SET_TX_DESC_RATE_ID(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(20, 16))
-#define SET_TX_DESC_DATARATE(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x04, value, GENMASK(6, 0))
-#define SET_TX_DESC_DISDATAFB(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(10))
-#define SET_TX_DESC_USE_RATE(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(8))
-#define SET_TX_DESC_SEC_TYPE(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(23, 22))
-#define SET_TX_DESC_DATA_BW(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, GENMASK(6, 5))
-#define SET_TX_DESC_SW_SEQ(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x09, value, GENMASK(23, 12))
-#define SET_TX_DESC_TIM_EN(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x09, value, BIT(7))
-#define SET_TX_DESC_TIM_OFFSET(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x09, value, GENMASK(6, 0))
-#define SET_TX_DESC_MAX_AGG_NUM(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, GENMASK(21, 17))
-#define SET_TX_DESC_USE_RTS(tx_desc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(12))
-#define SET_TX_DESC_RTSRATE(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x04, value, GENMASK(28, 24))
-#define SET_TX_DESC_DATA_RTS_SHORT(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(12))
-#define SET_TX_DESC_AMPDU_DENSITY(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, GENMASK(22, 20))
-#define SET_TX_DESC_DATA_STBC(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, GENMASK(9, 8))
-#define SET_TX_DESC_DATA_LDPC(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(7))
-#define SET_TX_DESC_AGG_EN(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(12))
-#define SET_TX_DESC_LS(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(26))
-#define SET_TX_DESC_DATA_SHORT(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(4))
-#define SET_TX_DESC_SPE_RPT(tx_desc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(19))
-#define SET_TX_DESC_SW_DEFINE(tx_desc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x06, value, GENMASK(11, 0))
-#define SET_TX_DESC_DISQSELSEQ(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(31))
-#define SET_TX_DESC_EN_HWSEQ(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x08, value, BIT(15))
-#define SET_TX_DESC_HW_SSN_SEL(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, GENMASK(7, 6))
-#define SET_TX_DESC_NAVUSEHDR(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(15))
-#define SET_TX_DESC_BT_NULL(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(23))
-#define SET_TX_DESC_TXDESC_CHECKSUM(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x07, value, GENMASK(15, 0))
-#define SET_TX_DESC_DMA_TXAGG_NUM(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x07, value, GENMASK(31, 24))
-#define GET_TX_DESC_PKT_OFFSET(txdesc) \
- le32_get_bits(*((__le32 *)(txdesc) + 0x01), GENMASK(28, 24))
-#define GET_TX_DESC_QSEL(txdesc) \
- le32_get_bits(*((__le32 *)(txdesc) + 0x01), GENMASK(12, 8))
+struct rtw_tx_desc {
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+ __le32 w3;
+ __le32 w4;
+ __le32 w5;
+ __le32 w6;
+ __le32 w7;
+ __le32 w8;
+ __le32 w9;
+} __packed;
+
+#define RTW_TX_DESC_W0_TXPKTSIZE GENMASK(15, 0)
+#define RTW_TX_DESC_W0_OFFSET GENMASK(23, 16)
+#define RTW_TX_DESC_W0_BMC BIT(24)
+#define RTW_TX_DESC_W0_LS BIT(26)
+#define RTW_TX_DESC_W0_DISQSELSEQ BIT(31)
+#define RTW_TX_DESC_W1_QSEL GENMASK(12, 8)
+#define RTW_TX_DESC_W1_RATE_ID GENMASK(20, 16)
+#define RTW_TX_DESC_W1_SEC_TYPE GENMASK(23, 22)
+#define RTW_TX_DESC_W1_PKT_OFFSET GENMASK(28, 24)
+#define RTW_TX_DESC_W1_MORE_DATA BIT(29)
+#define RTW_TX_DESC_W2_AGG_EN BIT(12)
+#define RTW_TX_DESC_W2_SPE_RPT BIT(19)
+#define RTW_TX_DESC_W2_AMPDU_DEN GENMASK(22, 20)
+#define RTW_TX_DESC_W2_BT_NULL BIT(23)
+#define RTW_TX_DESC_W3_HW_SSN_SEL GENMASK(7, 6)
+#define RTW_TX_DESC_W3_USE_RATE BIT(8)
+#define RTW_TX_DESC_W3_DISDATAFB BIT(10)
+#define RTW_TX_DESC_W3_USE_RTS BIT(12)
+#define RTW_TX_DESC_W3_NAVUSEHDR BIT(15)
+#define RTW_TX_DESC_W3_MAX_AGG_NUM GENMASK(21, 17)
+#define RTW_TX_DESC_W4_DATARATE GENMASK(6, 0)
+#define RTW_TX_DESC_W4_RTSRATE GENMASK(28, 24)
+#define RTW_TX_DESC_W5_DATA_SHORT BIT(4)
+#define RTW_TX_DESC_W5_DATA_BW GENMASK(6, 5)
+#define RTW_TX_DESC_W5_DATA_LDPC BIT(7)
+#define RTW_TX_DESC_W5_DATA_STBC GENMASK(9, 8)
+#define RTW_TX_DESC_W5_DATA_RTS_SHORT BIT(12)
+#define RTW_TX_DESC_W6_SW_DEFINE GENMASK(11, 0)
+#define RTW_TX_DESC_W7_TXDESC_CHECKSUM GENMASK(15, 0)
+#define RTW_TX_DESC_W7_DMA_TXAGG_NUM GENMASK(31, 24)
+#define RTW_TX_DESC_W8_EN_HWSEQ BIT(15)
+#define RTW_TX_DESC_W9_SW_SEQ GENMASK(23, 12)
+#define RTW_TX_DESC_W9_TIM_EN BIT(7)
+#define RTW_TX_DESC_W9_TIM_OFFSET GENMASK(6, 0)
enum rtw_tx_desc_queue_select {
TX_DESC_QSEL_TID0 = 0,
@@ -111,6 +88,7 @@ void rtw_tx(struct rtw_dev *rtwdev,
void rtw_txq_init(struct rtw_dev *rtwdev, struct ieee80211_txq *txq);
void rtw_txq_cleanup(struct rtw_dev *rtwdev, struct ieee80211_txq *txq);
void rtw_tx_work(struct work_struct *w);
+void __rtw_tx_work(struct rtw_dev *rtwdev);
void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
struct ieee80211_sta *sta,
@@ -139,13 +117,15 @@ void fill_txdesc_checksum_common(u8 *txdesc, size_t words)
{
__le16 chksum = 0;
__le16 *data = (__le16 *)(txdesc);
+ struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)txdesc;
- SET_TX_DESC_TXDESC_CHECKSUM(txdesc, 0x0000);
+ le32p_replace_bits(&tx_desc->w7, 0, RTW_TX_DESC_W7_TXDESC_CHECKSUM);
while (words--)
chksum ^= *data++;
- SET_TX_DESC_TXDESC_CHECKSUM(txdesc, __le16_to_cpu(chksum));
+ le32p_replace_bits(&tx_desc->w7, __le16_to_cpu(chksum),
+ RTW_TX_DESC_W7_TXDESC_CHECKSUM);
}
static inline void rtw_tx_fill_txdesc_checksum(struct rtw_dev *rtwdev,
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
index 44a5fafb9905..4a57efdba97b 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.c
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
@@ -24,11 +24,12 @@ struct rtw_usb_txcb {
static void rtw_usb_fill_tx_checksum(struct rtw_usb *rtwusb,
struct sk_buff *skb, int agg_num)
{
+ struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)skb->data;
struct rtw_dev *rtwdev = rtwusb->rtwdev;
struct rtw_tx_pkt_info pkt_info;
- SET_TX_DESC_DMA_TXAGG_NUM(skb->data, agg_num);
- pkt_info.pkt_offset = GET_TX_DESC_PKT_OFFSET(skb->data);
+ le32p_replace_bits(&tx_desc->w7, agg_num, RTW_TX_DESC_W7_DMA_TXAGG_NUM);
+ pkt_info.pkt_offset = le32_get_bits(tx_desc->w1, RTW_TX_DESC_W1_PKT_OFFSET);
rtw_tx_fill_txdesc_checksum(rtwdev, &pkt_info, skb->data);
}
@@ -306,11 +307,13 @@ static int rtw_usb_write_port(struct rtw_dev *rtwdev, u8 qsel, struct sk_buff *s
static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list)
{
struct rtw_dev *rtwdev = rtwusb->rtwdev;
+ struct rtw_tx_desc *tx_desc;
struct rtw_usb_txcb *txcb;
struct sk_buff *skb_head;
struct sk_buff *skb_iter;
int agg_num = 0;
unsigned int align_next = 0;
+ u8 qsel;
if (skb_queue_empty(list))
return false;
@@ -363,9 +366,10 @@ static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list
queue:
skb_queue_tail(&txcb->tx_ack_queue, skb_head);
+ tx_desc = (struct rtw_tx_desc *)skb_head->data;
+ qsel = le32_get_bits(tx_desc->w1, RTW_TX_DESC_W1_QSEL);
- rtw_usb_write_port(rtwdev, GET_TX_DESC_QSEL(skb_head->data), skb_head,
- rtw_usb_write_port_tx_complete, txcb);
+ rtw_usb_write_port(rtwdev, qsel, skb_head, rtw_usb_write_port_tx_complete, txcb);
return true;
}
@@ -465,6 +469,9 @@ static u8 rtw_usb_tx_queue_mapping_to_qsel(struct sk_buff *skb)
if (unlikely(ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)))
qsel = TX_DESC_QSEL_MGMT;
+ else if (is_broadcast_ether_addr(hdr->addr1) ||
+ is_multicast_ether_addr(hdr->addr1))
+ qsel = TX_DESC_QSEL_HIGH;
else if (skb_get_queue_mapping(skb) <= IEEE80211_AC_BK)
qsel = skb->priority;
else
@@ -535,7 +542,7 @@ static void rtw_usb_rx_handler(struct work_struct *work)
}
if (skb_queue_len(&rtwusb->rx_queue) >= RTW_USB_MAX_RXQ_LEN) {
- rtw_err(rtwdev, "failed to get rx_queue, overflow\n");
+ dev_dbg_ratelimited(rtwdev->dev, "failed to get rx_queue, overflow\n");
dev_kfree_skb_any(skb);
continue;
}
diff --git a/drivers/net/wireless/realtek/rtw89/Kconfig b/drivers/net/wireless/realtek/rtw89/Kconfig
index 2b20cf8bbf3a..90ffbab7cc4c 100644
--- a/drivers/net/wireless/realtek/rtw89/Kconfig
+++ b/drivers/net/wireless/realtek/rtw89/Kconfig
@@ -16,6 +16,9 @@ config RTW89_CORE
config RTW89_PCI
tristate
+config RTW89_8851B
+ tristate
+
config RTW89_8852A
tristate
@@ -25,6 +28,17 @@ config RTW89_8852B
config RTW89_8852C
tristate
+config RTW89_8851BE
+ tristate "Realtek 8851BE PCI wireless network (Wi-Fi 6) adapter"
+ depends on PCI
+ select RTW89_CORE
+ select RTW89_PCI
+ select RTW89_8851B
+ help
+ Select this option will enable support for 8851BE chipset
+
+ 802.11ax PCIe wireless network (Wi-Fi 6) adapter
+
config RTW89_8852AE
tristate "Realtek 8852AE PCI wireless network (Wi-Fi 6) adapter"
depends on PCI
diff --git a/drivers/net/wireless/realtek/rtw89/Makefile b/drivers/net/wireless/realtek/rtw89/Makefile
index 2dc48fa10c6b..41940099af1b 100644
--- a/drivers/net/wireless/realtek/rtw89/Makefile
+++ b/drivers/net/wireless/realtek/rtw89/Makefile
@@ -13,10 +13,20 @@ rtw89_core-y += core.o \
coex.o \
ps.o \
chan.o \
- ser.o
+ ser.o \
+ acpi.o
rtw89_core-$(CONFIG_PM) += wow.o
+obj-$(CONFIG_RTW89_8851B) += rtw89_8851b.o
+rtw89_8851b-objs := rtw8851b.o \
+ rtw8851b_table.o \
+ rtw8851b_rfk.o \
+ rtw8851b_rfk_table.o
+
+obj-$(CONFIG_RTW89_8851BE) += rtw89_8851be.o
+rtw89_8851be-objs := rtw8851be.o
+
obj-$(CONFIG_RTW89_8852A) += rtw89_8852a.o
rtw89_8852a-objs := rtw8852a.o \
rtw8852a_table.o \
diff --git a/drivers/net/wireless/realtek/rtw89/acpi.c b/drivers/net/wireless/realtek/rtw89/acpi.c
new file mode 100644
index 000000000000..8aaf83a2a6b4
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/acpi.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2021-2023 Realtek Corporation
+ */
+
+#include <linux/acpi.h>
+#include <linux/uuid.h>
+
+#include "acpi.h"
+#include "debug.h"
+
+static const guid_t rtw89_guid = GUID_INIT(0xD2A8C3E8, 0x4B69, 0x4F00,
+ 0x82, 0xBD, 0xFE, 0x86,
+ 0x07, 0x80, 0x3A, 0xA7);
+
+static int rtw89_acpi_dsm_get(struct rtw89_dev *rtwdev, union acpi_object *obj,
+ u8 *value)
+{
+ switch (obj->type) {
+ case ACPI_TYPE_INTEGER:
+ *value = (u8)obj->integer.value;
+ break;
+ case ACPI_TYPE_BUFFER:
+ *value = obj->buffer.pointer[0];
+ break;
+ default:
+ rtw89_debug(rtwdev, RTW89_DBG_UNEXP,
+ "acpi dsm return unhandled type: %d\n", obj->type);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
+ enum rtw89_acpi_dsm_func func, u8 *value)
+{
+ union acpi_object *obj;
+ int ret;
+
+ obj = acpi_evaluate_dsm(ACPI_HANDLE(rtwdev->dev), &rtw89_guid,
+ 0, func, NULL);
+ if (!obj) {
+ rtw89_debug(rtwdev, RTW89_DBG_UNEXP,
+ "acpi dsm fail to evaluate func: %d\n", func);
+ return -ENOENT;
+ }
+
+ ret = rtw89_acpi_dsm_get(rtwdev, obj, value);
+
+ ACPI_FREE(obj);
+ return ret;
+}
diff --git a/drivers/net/wireless/realtek/rtw89/acpi.h b/drivers/net/wireless/realtek/rtw89/acpi.h
new file mode 100644
index 000000000000..ed74d8ceb733
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/acpi.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2021-2023 Realtek Corporation
+ */
+
+#ifndef __RTW89_ACPI_H__
+#define __RTW89_ACPI_H__
+
+#include "core.h"
+
+enum rtw89_acpi_dsm_func {
+ RTW89_ACPI_DSM_FUNC_IDN_BAND_SUP = 2,
+ RTW89_ACPI_DSM_FUNC_6G_DIS = 3,
+ RTW89_ACPI_DSM_FUNC_6G_BP = 4,
+ RTW89_ACPI_DSM_FUNC_TAS_EN = 5,
+ RTW89_ACPI_DSM_FUNC_59G_EN = 6,
+};
+
+int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
+ enum rtw89_acpi_dsm_func func, u8 *value);
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c
index acb3fac0c96d..bda0e1e99a8c 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.c
+++ b/drivers/net/wireless/realtek/rtw89/coex.c
@@ -127,6 +127,13 @@ static const u32 cxtbl[] = {
static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
/* firmware version must be in decreasing order for each chip */
+ {RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0),
+ .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5,
+ .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1,
+ .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1,
+ .fwlrole = 1, .frptmap = 3, .fcxctrl = 1,
+ .info_buf = 1800, .max_role_num = 6,
+ },
{RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0),
.fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
.fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
@@ -199,7 +206,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
struct rtw89_btc_btf_tlv {
u8 type;
u8 len;
- u8 val[1];
+ u8 val[];
} __packed;
enum btc_btf_set_report_en {
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index bad864d56bd5..69b181fa2966 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -77,6 +77,9 @@ static struct ieee80211_channel rtw89_channels_5ghz[] = {
RTW89_DEF_CHAN_5G(5785, 157),
RTW89_DEF_CHAN_5G(5805, 161),
RTW89_DEF_CHAN_5G_NO_HT40MINUS(5825, 165),
+ RTW89_DEF_CHAN_5G(5845, 169),
+ RTW89_DEF_CHAN_5G(5865, 173),
+ RTW89_DEF_CHAN_5G(5885, 177),
};
static struct ieee80211_channel rtw89_channels_6ghz[] = {
@@ -333,8 +336,7 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev)
sub_entity_idx = RTW89_SUB_ENTITY_0;
phy_idx = RTW89_PHY_0;
chan = rtw89_chan_get(rtwdev, sub_entity_idx);
- if (chip->ops->set_txpwr)
- chip->ops->set_txpwr(rtwdev, chan, phy_idx);
+ chip->ops->set_txpwr(rtwdev, chan, phy_idx);
}
void rtw89_set_channel(struct rtw89_dev *rtwdev)
@@ -370,7 +372,7 @@ void rtw89_set_channel(struct rtw89_dev *rtwdev)
chip->ops->set_channel(rtwdev, &chan, mac_idx, phy_idx);
- rtw89_core_set_chip_txpwr(rtwdev);
+ chip->ops->set_txpwr(rtwdev, &chan, phy_idx);
rtw89_chip_set_channel_done(rtwdev, &bak, &chan, mac_idx, phy_idx);
@@ -1210,14 +1212,15 @@ static int rtw89_core_rx_process_mac_ppdu(struct rtw89_dev *rtwdev,
struct sk_buff *skb,
struct rtw89_rx_phy_ppdu *phy_ppdu)
{
+ const struct rtw89_rxinfo *rxinfo = (const struct rtw89_rxinfo *)skb->data;
bool rx_cnt_valid = false;
u8 plcp_size = 0;
u8 usr_num = 0;
u8 *phy_sts;
- rx_cnt_valid = RTW89_GET_RXINFO_RX_CNT_VLD(skb->data);
- plcp_size = RTW89_GET_RXINFO_PLCP_LEN(skb->data) << 3;
- usr_num = RTW89_GET_RXINFO_USR_NUM(skb->data);
+ rx_cnt_valid = le32_get_bits(rxinfo->w0, RTW89_RXINFO_W0_RX_CNT_VLD);
+ plcp_size = le32_get_bits(rxinfo->w1, RTW89_RXINFO_W1_PLCP_LEN) << 3;
+ usr_num = le32_get_bits(rxinfo->w0, RTW89_RXINFO_W0_USR_NUM);
if (usr_num > RTW89_PPDU_MAX_USR) {
rtw89_warn(rtwdev, "Invalid user number in mac info\n");
return -EINVAL;
@@ -1244,18 +1247,40 @@ static void rtw89_core_rx_process_phy_ppdu_iter(void *data,
struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
struct rtw89_rx_phy_ppdu *phy_ppdu = (struct rtw89_rx_phy_ppdu *)data;
struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num;
+ u8 ant_pos = U8_MAX;
+ u8 evm_pos = 0;
int i;
- if (rtwsta->mac_id == phy_ppdu->mac_id && phy_ppdu->to_self) {
- ewma_rssi_add(&rtwsta->avg_rssi, phy_ppdu->rssi_avg);
+ if (rtwsta->mac_id != phy_ppdu->mac_id || !phy_ppdu->to_self)
+ return;
+
+ if (hal->ant_diversity && hal->antenna_rx) {
+ ant_pos = __ffs(hal->antenna_rx);
+ evm_pos = ant_pos;
+ }
+
+ ewma_rssi_add(&rtwsta->avg_rssi, phy_ppdu->rssi_avg);
+
+ if (ant_pos < ant_num) {
+ ewma_rssi_add(&rtwsta->rssi[ant_pos], phy_ppdu->rssi[0]);
+ } else {
for (i = 0; i < rtwdev->chip->rf_path_num; i++)
ewma_rssi_add(&rtwsta->rssi[i], phy_ppdu->rssi[i]);
}
+
+ if (phy_ppdu->ofdm.has) {
+ ewma_snr_add(&rtwsta->avg_snr, phy_ppdu->ofdm.avg_snr);
+ ewma_evm_add(&rtwsta->evm_min[evm_pos], phy_ppdu->ofdm.evm_min);
+ ewma_evm_add(&rtwsta->evm_max[evm_pos], phy_ppdu->ofdm.evm_max);
+ }
}
#define VAR_LEN 0xff
#define VAR_LEN_UNIT 8
-static u16 rtw89_core_get_phy_status_ie_len(struct rtw89_dev *rtwdev, u8 *addr)
+static u16 rtw89_core_get_phy_status_ie_len(struct rtw89_dev *rtwdev,
+ const struct rtw89_phy_sts_iehdr *iehdr)
{
static const u8 physts_ie_len_tab[32] = {
16, 32, 24, 24, 8, 8, 8, 8, VAR_LEN, 8, VAR_LEN, 176, VAR_LEN,
@@ -1265,45 +1290,58 @@ static u16 rtw89_core_get_phy_status_ie_len(struct rtw89_dev *rtwdev, u8 *addr)
u16 ie_len;
u8 ie;
- ie = RTW89_GET_PHY_STS_IE_TYPE(addr);
+ ie = le32_get_bits(iehdr->w0, RTW89_PHY_STS_IEHDR_TYPE);
if (physts_ie_len_tab[ie] != VAR_LEN)
ie_len = physts_ie_len_tab[ie];
else
- ie_len = RTW89_GET_PHY_STS_IE_LEN(addr) * VAR_LEN_UNIT;
+ ie_len = le32_get_bits(iehdr->w0, RTW89_PHY_STS_IEHDR_LEN) * VAR_LEN_UNIT;
return ie_len;
}
-static void rtw89_core_parse_phy_status_ie01(struct rtw89_dev *rtwdev, u8 *addr,
+static void rtw89_core_parse_phy_status_ie01(struct rtw89_dev *rtwdev,
+ const struct rtw89_phy_sts_iehdr *iehdr,
struct rtw89_rx_phy_ppdu *phy_ppdu)
{
+ const struct rtw89_phy_sts_ie0 *ie = (const struct rtw89_phy_sts_ie0 *)iehdr;
s16 cfo;
+ u32 t;
- phy_ppdu->chan_idx = RTW89_GET_PHY_STS_IE01_CH_IDX(addr);
+ phy_ppdu->chan_idx = le32_get_bits(ie->w0, RTW89_PHY_STS_IE01_W0_CH_IDX);
if (phy_ppdu->rate < RTW89_HW_RATE_OFDM6)
return;
if (!phy_ppdu->to_self)
return;
+ phy_ppdu->ofdm.avg_snr = le32_get_bits(ie->w2, RTW89_PHY_STS_IE01_W2_AVG_SNR);
+ phy_ppdu->ofdm.evm_max = le32_get_bits(ie->w2, RTW89_PHY_STS_IE01_W2_EVM_MAX);
+ phy_ppdu->ofdm.evm_min = le32_get_bits(ie->w2, RTW89_PHY_STS_IE01_W2_EVM_MIN);
+ phy_ppdu->ofdm.has = true;
+
/* sign conversion for S(12,2) */
- if (rtwdev->chip->cfo_src_fd)
- cfo = sign_extend32(RTW89_GET_PHY_STS_IE01_FD_CFO(addr), 11);
- else
- cfo = sign_extend32(RTW89_GET_PHY_STS_IE01_PREMB_CFO(addr), 11);
+ if (rtwdev->chip->cfo_src_fd) {
+ t = le32_get_bits(ie->w1, RTW89_PHY_STS_IE01_W1_FD_CFO);
+ cfo = sign_extend32(t, 11);
+ } else {
+ t = le32_get_bits(ie->w1, RTW89_PHY_STS_IE01_W1_PREMB_CFO);
+ cfo = sign_extend32(t, 11);
+ }
rtw89_phy_cfo_parse(rtwdev, cfo, phy_ppdu);
}
-static int rtw89_core_process_phy_status_ie(struct rtw89_dev *rtwdev, u8 *addr,
+static int rtw89_core_process_phy_status_ie(struct rtw89_dev *rtwdev,
+ const struct rtw89_phy_sts_iehdr *iehdr,
struct rtw89_rx_phy_ppdu *phy_ppdu)
{
u8 ie;
- ie = RTW89_GET_PHY_STS_IE_TYPE(addr);
+ ie = le32_get_bits(iehdr->w0, RTW89_PHY_STS_IEHDR_TYPE);
+
switch (ie) {
case RTW89_PHYSTS_IE01_CMN_OFDM:
- rtw89_core_parse_phy_status_ie01(rtwdev, addr, phy_ppdu);
+ rtw89_core_parse_phy_status_ie01(rtwdev, iehdr, phy_ppdu);
break;
default:
break;
@@ -1314,28 +1352,30 @@ static int rtw89_core_process_phy_status_ie(struct rtw89_dev *rtwdev, u8 *addr,
static void rtw89_core_update_phy_ppdu(struct rtw89_rx_phy_ppdu *phy_ppdu)
{
+ const struct rtw89_phy_sts_hdr *hdr = phy_ppdu->buf;
u8 *rssi = phy_ppdu->rssi;
- u8 *buf = phy_ppdu->buf;
- phy_ppdu->ie = RTW89_GET_PHY_STS_IE_MAP(buf);
- phy_ppdu->rssi_avg = RTW89_GET_PHY_STS_RSSI_AVG(buf);
- rssi[RF_PATH_A] = RTW89_GET_PHY_STS_RSSI_A(buf);
- rssi[RF_PATH_B] = RTW89_GET_PHY_STS_RSSI_B(buf);
- rssi[RF_PATH_C] = RTW89_GET_PHY_STS_RSSI_C(buf);
- rssi[RF_PATH_D] = RTW89_GET_PHY_STS_RSSI_D(buf);
+ phy_ppdu->ie = le32_get_bits(hdr->w0, RTW89_PHY_STS_HDR_W0_IE_MAP);
+ phy_ppdu->rssi_avg = le32_get_bits(hdr->w0, RTW89_PHY_STS_HDR_W0_RSSI_AVG);
+ rssi[RF_PATH_A] = le32_get_bits(hdr->w1, RTW89_PHY_STS_HDR_W1_RSSI_A);
+ rssi[RF_PATH_B] = le32_get_bits(hdr->w1, RTW89_PHY_STS_HDR_W1_RSSI_B);
+ rssi[RF_PATH_C] = le32_get_bits(hdr->w1, RTW89_PHY_STS_HDR_W1_RSSI_C);
+ rssi[RF_PATH_D] = le32_get_bits(hdr->w1, RTW89_PHY_STS_HDR_W1_RSSI_D);
}
static int rtw89_core_rx_process_phy_ppdu(struct rtw89_dev *rtwdev,
struct rtw89_rx_phy_ppdu *phy_ppdu)
{
- if (RTW89_GET_PHY_STS_LEN(phy_ppdu->buf) << 3 != phy_ppdu->len) {
+ const struct rtw89_phy_sts_hdr *hdr = phy_ppdu->buf;
+ u32 len_from_header;
+
+ len_from_header = le32_get_bits(hdr->w0, RTW89_PHY_STS_HDR_W0_LEN) << 3;
+
+ if (len_from_header != phy_ppdu->len) {
rtw89_debug(rtwdev, RTW89_DBG_UNEXP, "phy ppdu len mismatch\n");
return -EINVAL;
}
rtw89_core_update_phy_ppdu(phy_ppdu);
- ieee80211_iterate_stations_atomic(rtwdev->hw,
- rtw89_core_rx_process_phy_ppdu_iter,
- phy_ppdu);
return 0;
}
@@ -1344,17 +1384,19 @@ static int rtw89_core_rx_parse_phy_sts(struct rtw89_dev *rtwdev,
struct rtw89_rx_phy_ppdu *phy_ppdu)
{
u16 ie_len;
- u8 *pos, *end;
+ void *pos, *end;
/* mark invalid reports and bypass them */
if (phy_ppdu->ie < RTW89_CCK_PKT)
return -EINVAL;
- pos = (u8 *)phy_ppdu->buf + PHY_STS_HDR_LEN;
- end = (u8 *)phy_ppdu->buf + phy_ppdu->len;
+ pos = phy_ppdu->buf + PHY_STS_HDR_LEN;
+ end = phy_ppdu->buf + phy_ppdu->len;
while (pos < end) {
- ie_len = rtw89_core_get_phy_status_ie_len(rtwdev, pos);
- rtw89_core_process_phy_status_ie(rtwdev, pos, phy_ppdu);
+ const struct rtw89_phy_sts_iehdr *iehdr = pos;
+
+ ie_len = rtw89_core_get_phy_status_ie_len(rtwdev, iehdr);
+ rtw89_core_process_phy_status_ie(rtwdev, iehdr, phy_ppdu);
pos += ie_len;
if (pos > end || ie_len == 0) {
rtw89_debug(rtwdev, RTW89_DBG_TXRX,
@@ -1363,6 +1405,8 @@ static int rtw89_core_rx_parse_phy_sts(struct rtw89_dev *rtwdev,
}
}
+ rtw89_phy_antdiv_parse(rtwdev, phy_ppdu);
+
return 0;
}
@@ -1376,6 +1420,10 @@ static void rtw89_core_rx_process_phy_sts(struct rtw89_dev *rtwdev,
rtw89_debug(rtwdev, RTW89_DBG_TXRX, "parse phy sts failed\n");
else
phy_ppdu->valid = true;
+
+ ieee80211_iterate_stations_atomic(rtwdev->hw,
+ rtw89_core_rx_process_phy_ppdu_iter,
+ phy_ppdu);
}
static u8 rtw89_rxdesc_to_nl_he_gi(struct rtw89_dev *rtwdev,
@@ -1481,6 +1529,34 @@ static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev,
}
}
+static void rtw89_cancel_6ghz_probe_work(struct work_struct *work)
+{
+ struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
+ cancel_6ghz_probe_work);
+ struct list_head *pkt_list = rtwdev->scan_info.pkt_list;
+ struct rtw89_pktofld_info *info;
+
+ mutex_lock(&rtwdev->mutex);
+
+ if (!rtwdev->scanning)
+ goto out;
+
+ list_for_each_entry(info, &pkt_list[NL80211_BAND_6GHZ], list) {
+ if (!info->cancel || !test_bit(info->id, rtwdev->pkt_offload))
+ continue;
+
+ rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id);
+
+ /* Don't delete/free info from pkt_list at this moment. Let it
+ * be deleted/freed in rtw89_release_pkt_list() after scanning,
+ * since if during scanning, pkt_list is accessed in bottom half.
+ */
+ }
+
+out:
+ mutex_unlock(&rtwdev->mutex);
+}
+
static void rtw89_core_cancel_6ghz_probe_tx(struct rtw89_dev *rtwdev,
struct sk_buff *skb)
{
@@ -1489,6 +1565,7 @@ static void rtw89_core_cancel_6ghz_probe_tx(struct rtw89_dev *rtwdev,
struct list_head *pkt_list = rtwdev->scan_info.pkt_list;
struct rtw89_pktofld_info *info;
const u8 *ies = mgmt->u.beacon.variable, *ssid_ie;
+ bool queue_work = false;
if (rx_status->band != NL80211_BAND_6GHZ)
return;
@@ -1497,16 +1574,22 @@ static void rtw89_core_cancel_6ghz_probe_tx(struct rtw89_dev *rtwdev,
list_for_each_entry(info, &pkt_list[NL80211_BAND_6GHZ], list) {
if (ether_addr_equal(info->bssid, mgmt->bssid)) {
- rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id);
+ info->cancel = true;
+ queue_work = true;
continue;
}
if (!ssid_ie || ssid_ie[1] != info->ssid_len || info->ssid_len == 0)
continue;
- if (memcmp(&ssid_ie[2], info->ssid, info->ssid_len) == 0)
- rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id);
+ if (memcmp(&ssid_ie[2], info->ssid, info->ssid_len) == 0) {
+ info->cancel = true;
+ queue_work = true;
+ }
}
+
+ if (queue_work)
+ ieee80211_queue_work(rtwdev->hw, &rtwdev->cancel_6ghz_probe_work);
}
static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
@@ -1722,43 +1805,47 @@ void rtw89_core_query_rxdesc(struct rtw89_dev *rtwdev,
u8 shift_len, drv_info_len;
rxd_s = (struct rtw89_rxdesc_short *)(data + data_offset);
- desc_info->pkt_size = RTW89_GET_RXWD_PKT_SIZE(rxd_s);
- desc_info->drv_info_size = RTW89_GET_RXWD_DRV_INFO_SIZE(rxd_s);
- desc_info->long_rxdesc = RTW89_GET_RXWD_LONG_RXD(rxd_s);
- desc_info->pkt_type = RTW89_GET_RXWD_RPKT_TYPE(rxd_s);
- desc_info->mac_info_valid = RTW89_GET_RXWD_MAC_INFO_VALID(rxd_s);
+ desc_info->pkt_size = le32_get_bits(rxd_s->dword0, AX_RXD_RPKT_LEN_MASK);
+ desc_info->drv_info_size = le32_get_bits(rxd_s->dword0, AX_RXD_DRV_INFO_SIZE_MASK);
+ desc_info->long_rxdesc = le32_get_bits(rxd_s->dword0, AX_RXD_LONG_RXD);
+ desc_info->pkt_type = le32_get_bits(rxd_s->dword0, AX_RXD_RPKT_TYPE_MASK);
+ desc_info->mac_info_valid = le32_get_bits(rxd_s->dword0, AX_RXD_MAC_INFO_VLD);
if (chip->chip_id == RTL8852C)
- desc_info->bw = RTW89_GET_RXWD_BW_V1(rxd_s);
+ desc_info->bw = le32_get_bits(rxd_s->dword1, AX_RXD_BW_v1_MASK);
else
- desc_info->bw = RTW89_GET_RXWD_BW(rxd_s);
- desc_info->data_rate = RTW89_GET_RXWD_DATA_RATE(rxd_s);
- desc_info->gi_ltf = RTW89_GET_RXWD_GI_LTF(rxd_s);
- desc_info->user_id = RTW89_GET_RXWD_USER_ID(rxd_s);
- desc_info->sr_en = RTW89_GET_RXWD_SR_EN(rxd_s);
- desc_info->ppdu_cnt = RTW89_GET_RXWD_PPDU_CNT(rxd_s);
- desc_info->ppdu_type = RTW89_GET_RXWD_PPDU_TYPE(rxd_s);
- desc_info->free_run_cnt = RTW89_GET_RXWD_FREE_RUN_CNT(rxd_s);
- desc_info->icv_err = RTW89_GET_RXWD_ICV_ERR(rxd_s);
- desc_info->crc32_err = RTW89_GET_RXWD_CRC32_ERR(rxd_s);
- desc_info->hw_dec = RTW89_GET_RXWD_HW_DEC(rxd_s);
- desc_info->sw_dec = RTW89_GET_RXWD_SW_DEC(rxd_s);
- desc_info->addr1_match = RTW89_GET_RXWD_A1_MATCH(rxd_s);
+ desc_info->bw = le32_get_bits(rxd_s->dword1, AX_RXD_BW_MASK);
+ desc_info->data_rate = le32_get_bits(rxd_s->dword1, AX_RXD_RX_DATARATE_MASK);
+ desc_info->gi_ltf = le32_get_bits(rxd_s->dword1, AX_RXD_RX_GI_LTF_MASK);
+ desc_info->user_id = le32_get_bits(rxd_s->dword1, AX_RXD_USER_ID_MASK);
+ desc_info->sr_en = le32_get_bits(rxd_s->dword1, AX_RXD_SR_EN);
+ desc_info->ppdu_cnt = le32_get_bits(rxd_s->dword1, AX_RXD_PPDU_CNT_MASK);
+ desc_info->ppdu_type = le32_get_bits(rxd_s->dword1, AX_RXD_PPDU_TYPE_MASK);
+ desc_info->free_run_cnt = le32_get_bits(rxd_s->dword2, AX_RXD_FREERUN_CNT_MASK);
+ desc_info->icv_err = le32_get_bits(rxd_s->dword3, AX_RXD_ICV_ERR);
+ desc_info->crc32_err = le32_get_bits(rxd_s->dword3, AX_RXD_CRC32_ERR);
+ desc_info->hw_dec = le32_get_bits(rxd_s->dword3, AX_RXD_HW_DEC);
+ desc_info->sw_dec = le32_get_bits(rxd_s->dword3, AX_RXD_SW_DEC);
+ desc_info->addr1_match = le32_get_bits(rxd_s->dword3, AX_RXD_A1_MATCH);
shift_len = desc_info->shift << 1; /* 2-byte unit */
drv_info_len = desc_info->drv_info_size << 3; /* 8-byte unit */
desc_info->offset = data_offset + shift_len + drv_info_len;
+ if (desc_info->long_rxdesc)
+ desc_info->rxd_len = sizeof(struct rtw89_rxdesc_long);
+ else
+ desc_info->rxd_len = sizeof(struct rtw89_rxdesc_short);
desc_info->ready = true;
if (!desc_info->long_rxdesc)
return;
rxd_l = (struct rtw89_rxdesc_long *)(data + data_offset);
- desc_info->frame_type = RTW89_GET_RXWD_TYPE(rxd_l);
- desc_info->addr_cam_valid = RTW89_GET_RXWD_ADDR_CAM_VLD(rxd_l);
- desc_info->addr_cam_id = RTW89_GET_RXWD_ADDR_CAM_ID(rxd_l);
- desc_info->sec_cam_id = RTW89_GET_RXWD_SEC_CAM_ID(rxd_l);
- desc_info->mac_id = RTW89_GET_RXWD_MAC_ID(rxd_l);
- desc_info->rx_pl_id = RTW89_GET_RXWD_RX_PL_ID(rxd_l);
+ desc_info->frame_type = le32_get_bits(rxd_l->dword4, AX_RXD_TYPE_MASK);
+ desc_info->addr_cam_valid = le32_get_bits(rxd_l->dword5, AX_RXD_ADDR_CAM_VLD);
+ desc_info->addr_cam_id = le32_get_bits(rxd_l->dword5, AX_RXD_ADDR_CAM_MASK);
+ desc_info->sec_cam_id = le32_get_bits(rxd_l->dword5, AX_RXD_SEC_CAM_IDX_MASK);
+ desc_info->mac_id = le32_get_bits(rxd_l->dword5, AX_RXD_MAC_ID_MASK);
+ desc_info->rx_pl_id = le32_get_bits(rxd_l->dword5, AX_RXD_RX_PL_ID_MASK);
}
EXPORT_SYMBOL(rtw89_core_query_rxdesc);
@@ -2593,6 +2680,7 @@ static void rtw89_track_work(struct work_struct *work)
rtw89_phy_ra_update(rtwdev);
rtw89_phy_cfo_track(rtwdev);
rtw89_phy_tx_path_div_track(rtwdev);
+ rtw89_phy_antdiv_track(rtwdev);
rtw89_phy_ul_tb_ctrl_track(rtwdev);
if (rtwdev->lps_enabled && !rtwdev->btc.lps)
@@ -2756,6 +2844,8 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev,
{
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num;
int i;
int ret;
@@ -2769,12 +2859,18 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev,
rtw89_core_txq_init(rtwdev, sta->txq[i]);
ewma_rssi_init(&rtwsta->avg_rssi);
- for (i = 0; i < rtwdev->chip->rf_path_num; i++)
+ ewma_snr_init(&rtwsta->avg_snr);
+ for (i = 0; i < ant_num; i++) {
ewma_rssi_init(&rtwsta->rssi[i]);
+ ewma_evm_init(&rtwsta->evm_min[i]);
+ ewma_evm_init(&rtwsta->evm_max[i]);
+ }
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
/* for station mode, assign the mac_id from itself */
rtwsta->mac_id = rtwvif->mac_id;
+ /* must do rtw89_reg_6ghz_power_recalc() before rfk channel */
+ rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif, true);
rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta,
BTC_ROLE_MSTS_STA_CONN_START);
rtw89_chip_rfk_channel(rtwdev);
@@ -2948,10 +3044,11 @@ int rtw89_core_sta_remove(struct rtw89_dev *rtwdev,
struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
int ret;
- if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
+ if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
+ rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif, false);
rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta,
BTC_ROLE_MSTS_STA_DIS_CONN);
- else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) {
+ } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) {
rtw89_core_release_bit_map(rtwdev->mac_id_map, rtwsta->mac_id);
ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta,
@@ -3292,8 +3389,10 @@ static void rtw89_core_clr_supported_band(struct rtw89_dev *rtwdev)
{
struct ieee80211_hw *hw = rtwdev->hw;
- kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data);
- kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data);
+ if (hw->wiphy->bands[NL80211_BAND_2GHZ])
+ kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data);
+ if (hw->wiphy->bands[NL80211_BAND_5GHZ])
+ kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data);
if (hw->wiphy->bands[NL80211_BAND_6GHZ])
kfree(hw->wiphy->bands[NL80211_BAND_6GHZ]->iftype_data);
kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]);
@@ -3430,6 +3529,7 @@ void rtw89_core_stop(struct rtw89_dev *rtwdev)
mutex_unlock(&rtwdev->mutex);
cancel_work_sync(&rtwdev->c2h_work);
+ cancel_work_sync(&rtwdev->cancel_6ghz_probe_work);
cancel_work_sync(&btc->eapol_notify_work);
cancel_work_sync(&btc->arp_notify_work);
cancel_work_sync(&btc->dhcp_notify_work);
@@ -3441,6 +3541,7 @@ void rtw89_core_stop(struct rtw89_dev *rtwdev)
cancel_delayed_work_sync(&rtwdev->coex_rfk_chk_work);
cancel_delayed_work_sync(&rtwdev->cfo_track_work);
cancel_delayed_work_sync(&rtwdev->forbid_ba_work);
+ cancel_delayed_work_sync(&rtwdev->antdiv_work);
mutex_lock(&rtwdev->mutex);
@@ -3476,6 +3577,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
INIT_DELAYED_WORK(&rtwdev->coex_rfk_chk_work, rtw89_coex_rfk_chk_work);
INIT_DELAYED_WORK(&rtwdev->cfo_track_work, rtw89_phy_cfo_track_work);
INIT_DELAYED_WORK(&rtwdev->forbid_ba_work, rtw89_forbid_ba_work);
+ INIT_DELAYED_WORK(&rtwdev->antdiv_work, rtw89_phy_antdiv_work);
rtwdev->txq_wq = alloc_workqueue("rtw89_tx_wq", WQ_UNBOUND | WQ_HIGHPRI, 0);
if (!rtwdev->txq_wq)
return -ENOMEM;
@@ -3486,10 +3588,12 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
rtwdev->total_sta_assoc = 0;
rtw89_init_wait(&rtwdev->mcc.wait);
+ rtw89_init_wait(&rtwdev->mac.fw_ofld_wait);
INIT_WORK(&rtwdev->c2h_work, rtw89_fw_c2h_work);
INIT_WORK(&rtwdev->ips_work, rtw89_ips_work);
INIT_WORK(&rtwdev->load_firmware_work, rtw89_load_firmware_work);
+ INIT_WORK(&rtwdev->cancel_6ghz_probe_work, rtw89_cancel_6ghz_probe_work);
skb_queue_head_init(&rtwdev->c2h_queue);
rtw89_core_ppdu_sts_init(rtwdev);
@@ -3584,7 +3688,7 @@ static void rtw89_read_chip_ver(struct rtw89_dev *rtwdev)
if (chip->chip_id == RTL8852B || chip->chip_id == RTL8851B) {
ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_CV, &val);
- if (!ret)
+ if (ret)
return;
rtwdev->hal.acv = u8_get_bits(val, XTAL_SI_ACV_MASK);
@@ -3693,6 +3797,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
{
struct ieee80211_hw *hw = rtwdev->hw;
struct rtw89_efuse *efuse = &rtwdev->efuse;
+ struct rtw89_hal *hal = &rtwdev->hal;
int ret;
int tx_headroom = IEEE80211_HT_CTL_LEN;
@@ -3731,8 +3836,13 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO);
- hw->wiphy->available_antennas_tx = BIT(rtwdev->chip->rf_path_num) - 1;
- hw->wiphy->available_antennas_rx = BIT(rtwdev->chip->rf_path_num) - 1;
+ if (hal->ant_diversity) {
+ hw->wiphy->available_antennas_tx = 0x3;
+ hw->wiphy->available_antennas_rx = 0x3;
+ } else {
+ hw->wiphy->available_antennas_tx = BIT(rtwdev->chip->rf_path_num) - 1;
+ hw->wiphy->available_antennas_rx = BIT(rtwdev->chip->rf_path_num) - 1;
+ }
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
WIPHY_FLAG_TDLS_EXTERNAL_SETUP |
@@ -3760,7 +3870,12 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
return ret;
}
- hw->wiphy->reg_notifier = rtw89_regd_notifier;
+ ret = rtw89_regd_setup(rtwdev);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to set up regd\n");
+ goto err_free_supported_band;
+ }
+
hw->wiphy->sar_capa = &rtw89_sar_capa;
ret = ieee80211_register_hw(hw);
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 6df386a38fb4..d2c67db97db1 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -122,6 +122,13 @@ enum rtw89_cv {
CHIP_CV_INVALID = CHIP_CV_MAX,
};
+enum rtw89_bacam_ver {
+ RTW89_BACAM_V0,
+ RTW89_BACAM_V1,
+
+ RTW89_BACAM_V0_EXT = 99,
+};
+
enum rtw89_core_tx_type {
RTW89_CORE_TX_TYPE_DATA,
RTW89_CORE_TX_TYPE_MGMT,
@@ -244,7 +251,7 @@ enum rtw89_band {
RTW89_BAND_2G = 0,
RTW89_BAND_5G = 1,
RTW89_BAND_6G = 2,
- RTW89_BAND_MAX,
+ RTW89_BAND_NUM,
};
enum rtw89_hw_rate {
@@ -427,27 +434,27 @@ enum rtw89_rate_section {
RTW89_RS_MCS, /* for HT/VHT/HE */
RTW89_RS_HEDCM,
RTW89_RS_OFFSET,
- RTW89_RS_MAX,
+ RTW89_RS_NUM,
RTW89_RS_LMT_NUM = RTW89_RS_MCS + 1,
RTW89_RS_TX_SHAPE_NUM = RTW89_RS_OFDM + 1,
};
-enum rtw89_rate_max {
- RTW89_RATE_CCK_MAX = 4,
- RTW89_RATE_OFDM_MAX = 8,
- RTW89_RATE_MCS_MAX = 12,
- RTW89_RATE_HEDCM_MAX = 4, /* for HEDCM MCS0/1/3/4 */
- RTW89_RATE_OFFSET_MAX = 5, /* for HE(HEDCM)/VHT/HT/OFDM/CCK offset */
+enum rtw89_rate_num {
+ RTW89_RATE_CCK_NUM = 4,
+ RTW89_RATE_OFDM_NUM = 8,
+ RTW89_RATE_MCS_NUM = 12,
+ RTW89_RATE_HEDCM_NUM = 4, /* for HEDCM MCS0/1/3/4 */
+ RTW89_RATE_OFFSET_NUM = 5, /* for HE(HEDCM)/VHT/HT/OFDM/CCK offset */
};
enum rtw89_nss {
RTW89_NSS_1 = 0,
RTW89_NSS_2 = 1,
/* HE DCM only support 1ss and 2ss */
- RTW89_NSS_HEDCM_MAX = RTW89_NSS_2 + 1,
+ RTW89_NSS_HEDCM_NUM = RTW89_NSS_2 + 1,
RTW89_NSS_3 = 2,
RTW89_NSS_4 = 3,
- RTW89_NSS_MAX,
+ RTW89_NSS_NUM,
};
enum rtw89_ntx {
@@ -481,6 +488,15 @@ enum rtw89_regulation_type {
RTW89_REGD_NUM,
};
+enum rtw89_reg_6ghz_power {
+ RTW89_REG_6GHZ_POWER_VLP = 0,
+ RTW89_REG_6GHZ_POWER_LPI = 1,
+ RTW89_REG_6GHZ_POWER_STD = 2,
+
+ NUM_OF_RTW89_REG_6GHZ_POWER,
+ RTW89_REG_6GHZ_POWER_DFLT = RTW89_REG_6GHZ_POWER_VLP,
+};
+
enum rtw89_fw_pkt_ofld_type {
RTW89_PKT_OFLD_TYPE_PROBE_RSP = 0,
RTW89_PKT_OFLD_TYPE_PS_POLL = 1,
@@ -496,11 +512,11 @@ enum rtw89_fw_pkt_ofld_type {
};
struct rtw89_txpwr_byrate {
- s8 cck[RTW89_RATE_CCK_MAX];
- s8 ofdm[RTW89_RATE_OFDM_MAX];
- s8 mcs[RTW89_NSS_MAX][RTW89_RATE_MCS_MAX];
- s8 hedcm[RTW89_NSS_HEDCM_MAX][RTW89_RATE_HEDCM_MAX];
- s8 offset[RTW89_RATE_OFFSET_MAX];
+ s8 cck[RTW89_RATE_CCK_NUM];
+ s8 ofdm[RTW89_RATE_OFDM_NUM];
+ s8 mcs[RTW89_NSS_NUM][RTW89_RATE_MCS_NUM];
+ s8 hedcm[RTW89_NSS_HEDCM_NUM][RTW89_RATE_HEDCM_NUM];
+ s8 offset[RTW89_RATE_OFFSET_NUM];
};
enum rtw89_bandwidth_section_num {
@@ -543,7 +559,7 @@ struct rtw89_rate_desc {
#define RF_PATH_MAX 4
#define RTW89_MAX_PPDU_CNT 8
struct rtw89_rx_phy_ppdu {
- u8 *buf;
+ void *buf;
u32 len;
u8 rssi_avg;
u8 rssi[RF_PATH_MAX];
@@ -551,6 +567,12 @@ struct rtw89_rx_phy_ppdu {
u8 chan_idx;
u8 ie;
u16 rate;
+ struct {
+ bool has;
+ u8 avg_snr;
+ u8 evm_max;
+ u8 evm_min;
+ } ofdm;
bool to_self;
bool valid;
};
@@ -763,6 +785,7 @@ struct rtw89_rx_desc_info {
u8 sec_cam_id;
u8 mac_id;
u16 offset;
+ u16 rxd_len;
bool ready;
};
@@ -1382,7 +1405,6 @@ struct rtw89_btc_wl_nhm {
u8 current_status;
u8 refresh;
bool start_flag;
- u8 last_ccx_rpt_stamp;
s8 pwr_max;
s8 pwr_min;
};
@@ -2533,6 +2555,8 @@ struct rtw89_ra_report {
};
DECLARE_EWMA(rssi, 10, 16);
+DECLARE_EWMA(evm, 10, 16);
+DECLARE_EWMA(snr, 10, 16);
struct rtw89_ba_cam_entry {
struct list_head list;
@@ -2595,6 +2619,9 @@ struct rtw89_sta {
u8 prev_rssi;
struct ewma_rssi avg_rssi;
struct ewma_rssi rssi[RF_PATH_MAX];
+ struct ewma_snr avg_snr;
+ struct ewma_evm evm_min[RF_PATH_MAX];
+ struct ewma_evm evm_max[RF_PATH_MAX];
struct rtw89_ampdu_params ampdu_params[IEEE80211_NUM_TIDS];
struct ieee80211_rx_status rx_status;
u16 rx_hw_rate;
@@ -2663,6 +2690,7 @@ struct rtw89_vif {
struct rtw89_dev *rtwdev;
struct rtw89_roc roc;
enum rtw89_sub_entity_idx sub_entity_idx;
+ enum rtw89_reg_6ghz_power reg_6ghz_power;
u8 mac_id;
u8 port;
@@ -2781,6 +2809,7 @@ struct rtw89_chip_ops {
int (*read_efuse)(struct rtw89_dev *rtwdev, u8 *log_map);
int (*read_phycap)(struct rtw89_dev *rtwdev, u8 *phycap_map);
void (*fem_setup)(struct rtw89_dev *rtwdev);
+ void (*rfe_gpio)(struct rtw89_dev *rtwdev);
void (*rfk_init)(struct rtw89_dev *rtwdev);
void (*rfk_channel)(struct rtw89_dev *rtwdev);
void (*rfk_band_changed)(struct rtw89_dev *rtwdev,
@@ -2805,6 +2834,9 @@ struct rtw89_chip_ops {
s8 pw_ofst, enum rtw89_mac_idx mac_idx);
int (*pwr_on_func)(struct rtw89_dev *rtwdev);
int (*pwr_off_func)(struct rtw89_dev *rtwdev);
+ void (*query_rxdesc)(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_desc_info *desc_info,
+ u8 *data, u32 data_offset);
void (*fill_txdesc)(struct rtw89_dev *rtwdev,
struct rtw89_tx_desc_info *desc_info,
void *txdesc);
@@ -3013,9 +3045,11 @@ struct rtw89_txpwr_rule_5ghz {
struct rtw89_txpwr_rule_6ghz {
const s8 (*lmt)[RTW89_6G_BW_NUM][RTW89_NTX_NUM]
[RTW89_RS_LMT_NUM][RTW89_BF_NUM]
- [RTW89_REGD_NUM][RTW89_6G_CH_NUM];
+ [RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER]
+ [RTW89_6G_CH_NUM];
const s8 (*lmt_ru)[RTW89_RU_NUM][RTW89_NTX_NUM]
- [RTW89_REGD_NUM][RTW89_6G_CH_NUM];
+ [RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER]
+ [RTW89_6G_CH_NUM];
};
struct rtw89_rfe_parms {
@@ -3090,6 +3124,12 @@ struct rtw89_imr_info {
u32 tmac_imr_set;
};
+struct rtw89_xtal_info {
+ u32 xcap_reg;
+ u32 sc_xo_mask;
+ u32 sc_xi_mask;
+};
+
struct rtw89_rrsr_cfgs {
struct rtw89_reg3_def ref_rate;
struct rtw89_reg3_def rsc;
@@ -3116,6 +3156,25 @@ struct rtw89_phy_ul_tb_info {
u8 def_if_bandedge;
};
+struct rtw89_antdiv_stats {
+ struct ewma_rssi cck_rssi_avg;
+ struct ewma_rssi ofdm_rssi_avg;
+ struct ewma_rssi non_legacy_rssi_avg;
+ u16 pkt_cnt_cck;
+ u16 pkt_cnt_ofdm;
+ u16 pkt_cnt_non_legacy;
+ u32 evm;
+};
+
+struct rtw89_antdiv_info {
+ struct rtw89_antdiv_stats target_stats;
+ struct rtw89_antdiv_stats main_stats;
+ struct rtw89_antdiv_stats aux_stats;
+ u8 training_count;
+ u8 rssi_pre;
+ bool get_stats;
+};
+
struct rtw89_chip_info {
enum rtw89_core_chip_id chip_id;
const struct rtw89_chip_ops *ops;
@@ -3123,6 +3182,7 @@ struct rtw89_chip_info {
u8 fw_format_max;
bool try_ce_fw;
u32 fifo_size;
+ bool small_fifo_size;
u32 dle_scc_rsvd_size;
u16 max_amsdu_limit;
bool dis_2g_40m_ul_ofdma;
@@ -3135,6 +3195,7 @@ struct rtw89_chip_info {
u8 support_chanctx_num;
u8 support_bands;
bool support_bw160;
+ bool support_unii4;
bool support_ul_tb_ctrl;
bool hw_sec_hdr;
u8 rf_path_num;
@@ -3145,7 +3206,7 @@ struct rtw89_chip_info {
u8 scam_num;
u8 bacam_num;
u8 bacam_dynamic_num;
- bool bacam_v1;
+ enum rtw89_bacam_ver bacam_ver;
u8 sec_ctrl_efuse_size;
u32 physical_efuse_size;
@@ -3162,6 +3223,7 @@ struct rtw89_chip_info {
const struct rtw89_phy_table *bb_gain_table;
const struct rtw89_phy_table *rf_table[RF_PATH_MAX];
const struct rtw89_phy_table *nctl_table;
+ const struct rtw89_rfk_tbl *nctl_post_table;
const struct rtw89_txpwr_table *byr_table;
const struct rtw89_phy_dig_gain_table *dig_table;
const struct rtw89_dig_regs *dig_regs;
@@ -3215,6 +3277,7 @@ struct rtw89_chip_info {
u32 dma_ch_mask;
u32 edcca_lvl_reg;
const struct wiphy_wowlan_support *wowlan_stub;
+ const struct rtw89_xtal_info *xtal_info;
};
union rtw89_bus_info {
@@ -3237,7 +3300,6 @@ enum rtw89_hcifc_mode {
struct rtw89_dle_info {
enum rtw89_qta_mode qta_mode;
- u16 wde_pg_size;
u16 ple_pg_size;
u16 c0_rx_qta;
u16 c1_rx_qta;
@@ -3248,14 +3310,6 @@ enum rtw89_host_rpr_mode {
RTW89_RPR_MODE_STF
};
-struct rtw89_mac_info {
- struct rtw89_dle_info dle_info;
- struct rtw89_hfc_param hfc_param;
- enum rtw89_qta_mode qta_mode;
- u8 rpwm_seq_num;
- u8 cpwm_seq_num;
-};
-
#define RTW89_COMPLETION_BUF_SIZE 24
#define RTW89_WAIT_COND_IDLE UINT_MAX
@@ -3278,6 +3332,17 @@ static inline void rtw89_init_wait(struct rtw89_wait_info *wait)
atomic_set(&wait->cond, RTW89_WAIT_COND_IDLE);
}
+struct rtw89_mac_info {
+ struct rtw89_dle_info dle_info;
+ struct rtw89_hfc_param hfc_param;
+ enum rtw89_qta_mode qta_mode;
+ u8 rpwm_seq_num;
+ u8 cpwm_seq_num;
+
+ /* see RTW89_FW_OFLD_WAIT_COND series for wait condition */
+ struct rtw89_wait_info fw_ofld_wait;
+};
+
enum rtw89_fw_type {
RTW89_FW_NORMAL = 1,
RTW89_FW_WOWLAN = 3,
@@ -3322,10 +3387,10 @@ struct rtw89_fw_suit {
(mfw_hdr)->ver.idx)
#define RTW89_FW_HDR_VER_CODE(fw_hdr) \
- RTW89_FW_VER_CODE(GET_FW_HDR_MAJOR_VERSION(fw_hdr), \
- GET_FW_HDR_MINOR_VERSION(fw_hdr), \
- GET_FW_HDR_SUBVERSION(fw_hdr), \
- GET_FW_HDR_SUBINDEX(fw_hdr))
+ RTW89_FW_VER_CODE(le32_get_bits((fw_hdr)->w1, FW_HDR_W1_MAJOR_VERSION), \
+ le32_get_bits((fw_hdr)->w1, FW_HDR_W1_MINOR_VERSION), \
+ le32_get_bits((fw_hdr)->w1, FW_HDR_W1_SUBVERSION), \
+ le32_get_bits((fw_hdr)->w1, FW_HDR_W1_SUBINDEX))
struct rtw89_fw_req_info {
const struct firmware *firmware;
@@ -3417,12 +3482,13 @@ struct rtw89_hal {
u32 rx_fltr;
u8 cv;
u8 acv;
- u32 sw_amsdu_max_size;
u32 antenna_tx;
u32 antenna_rx;
u8 tx_nss;
u8 rx_nss;
bool tx_path_diversity;
+ bool ant_diversity;
+ bool ant_diversity_fixed;
bool support_cckpd;
bool support_igi;
atomic_t roc_entity_idx;
@@ -3452,6 +3518,7 @@ enum rtw89_flags {
RTW89_FLAG_LOW_POWER_MODE,
RTW89_FLAG_INACTIVE_PS,
RTW89_FLAG_CRASH_SIMULATING,
+ RTW89_FLAG_SER_HANDLING,
RTW89_FLAG_WOWLAN,
RTW89_FLAG_FORBIDDEN_TRACK_WROK,
RTW89_FLAG_CHANGING_INTERFACE,
@@ -3543,7 +3610,6 @@ struct rtw89_iqk_info {
u8 iqk_band[RTW89_IQK_PATH_NR];
u8 iqk_ch[RTW89_IQK_PATH_NR];
u8 iqk_bw[RTW89_IQK_PATH_NR];
- u8 kcount;
u8 iqk_times;
u8 version;
u32 nb_txcfir[RTW89_IQK_PATH_NR];
@@ -3558,8 +3624,6 @@ struct rtw89_iqk_info {
bool iqk_xym_en;
bool iqk_sram_en;
bool iqk_cfir_en;
- u8 thermal[RTW89_IQK_PATH_NR];
- bool thermal_rek_en;
u32 syn1to2;
u8 iqk_mcc_ch[RTW89_IQK_CHS_NR][RTW89_IQK_PATH_NR];
u8 iqk_table_idx[RTW89_IQK_PATH_NR];
@@ -3749,9 +3813,14 @@ struct rtw89_power_trim_info {
u8 pa_bias_trim[RF_PATH_MAX];
};
-struct rtw89_regulatory {
+struct rtw89_regd {
char alpha2[3];
- u8 txpwr_regd[RTW89_BAND_MAX];
+ u8 txpwr_regd[RTW89_BAND_NUM];
+};
+
+struct rtw89_regulatory_info {
+ const struct rtw89_regd *regd;
+ enum rtw89_reg_6ghz_power reg_6ghz_power;
};
enum rtw89_ifs_clm_application {
@@ -3815,35 +3884,16 @@ enum rtw89_ccx_edcca_opt_bw_idx {
#define RTW89_FAHM_RPT_NUM 12
#define RTW89_IFS_CLM_NUM 4
struct rtw89_env_monitor_info {
- u32 ccx_trigger_time;
- u64 start_time;
- u8 ccx_rpt_stamp;
u8 ccx_watchdog_result;
bool ccx_ongoing;
u8 ccx_rac_lv;
bool ccx_manual_ctrl;
- u8 ccx_pre_rssi;
- u16 clm_mntr_time;
- u16 nhm_mntr_time;
u16 ifs_clm_mntr_time;
enum rtw89_ifs_clm_application ifs_clm_app;
- u16 fahm_mntr_time;
- u16 edcca_clm_mntr_time;
u16 ccx_period;
u8 ccx_unit_idx;
- enum rtw89_ccx_edcca_opt_bw_idx ccx_edcca_opt_bw_idx;
- u8 nhm_th[RTW89_NHM_TH_NUM];
u16 ifs_clm_th_l[RTW89_IFS_CLM_NUM];
u16 ifs_clm_th_h[RTW89_IFS_CLM_NUM];
- u8 fahm_numer_opt;
- u8 fahm_denom_opt;
- u8 fahm_th[RTW89_FAHM_TH_NUM];
- u16 clm_result;
- u16 nhm_result[RTW89_NHM_RPT_NUM];
- u8 nhm_wgt[RTW89_NHM_RPT_NUM];
- u16 nhm_tx_cnt;
- u16 nhm_cca_cnt;
- u16 nhm_idle_cnt;
u16 ifs_clm_tx;
u16 ifs_clm_edcca_excl_cca;
u16 ifs_clm_ofdmfa;
@@ -3854,17 +3904,6 @@ struct rtw89_env_monitor_info {
u8 ifs_clm_his[RTW89_IFS_CLM_NUM];
u16 ifs_clm_avg[RTW89_IFS_CLM_NUM];
u16 ifs_clm_cca[RTW89_IFS_CLM_NUM];
- u16 fahm_result[RTW89_FAHM_RPT_NUM];
- u16 fahm_denom_result;
- u16 edcca_clm_result;
- u8 clm_ratio;
- u8 nhm_rpt[RTW89_NHM_RPT_NUM];
- u8 nhm_tx_ratio;
- u8 nhm_cca_ratio;
- u8 nhm_idle_ratio;
- u8 nhm_ratio;
- u16 nhm_result_sum;
- u8 nhm_pwr;
u8 ifs_clm_tx_ratio;
u8 ifs_clm_edcca_excl_cca_ratio;
u8 ifs_clm_cck_fa_ratio;
@@ -3875,12 +3914,6 @@ struct rtw89_env_monitor_info {
u16 ifs_clm_ofdm_fa_permil;
u32 ifs_clm_ifs_avg[RTW89_IFS_CLM_NUM];
u32 ifs_clm_cca_avg[RTW89_IFS_CLM_NUM];
- u8 fahm_rpt[RTW89_FAHM_RPT_NUM];
- u16 fahm_result_sum;
- u8 fahm_ratio;
- u8 fahm_denom_ratio;
- u8 fahm_pwr;
- u8 edcca_clm_ratio;
};
enum rtw89_ser_rcvy_step {
@@ -3888,12 +3921,14 @@ enum rtw89_ser_rcvy_step {
RTW89_SER_DRV_STOP_RX,
RTW89_SER_DRV_STOP_RUN,
RTW89_SER_HAL_STOP_DMA,
+ RTW89_SER_SUPPRESS_LOG,
RTW89_NUM_OF_SER_FLAGS
};
struct rtw89_ser {
u8 state;
u8 alarm_event;
+ bool prehandle_l1;
struct work_struct ser_hdl_work;
struct delayed_work ser_alarm_work;
@@ -4054,6 +4089,7 @@ struct rtw89_dev {
struct work_struct c2h_work;
struct work_struct ips_work;
struct work_struct load_firmware_work;
+ struct work_struct cancel_6ghz_probe_work;
struct list_head early_h2c_list;
@@ -4075,7 +4111,7 @@ struct rtw89_dev {
bool is_bt_iqk_timeout;
struct rtw89_fem_info fem;
- struct rtw89_txpwr_byrate byr[RTW89_BAND_MAX];
+ struct rtw89_txpwr_byrate byr[RTW89_BAND_NUM];
struct rtw89_tssi_info tssi;
struct rtw89_power_trim_info pwr_trim;
@@ -4086,6 +4122,7 @@ struct rtw89_dev {
struct rtw89_phy_bb_gain_info bb_gain;
struct rtw89_phy_efuse_gain efuse_gain;
struct rtw89_phy_ul_tb_info ul_tb_info;
+ struct rtw89_antdiv_info antdiv;
struct delayed_work track_work;
struct delayed_work coex_act1_work;
@@ -4094,11 +4131,12 @@ struct rtw89_dev {
struct delayed_work cfo_track_work;
struct delayed_work forbid_ba_work;
struct delayed_work roc_work;
+ struct delayed_work antdiv_work;
struct rtw89_ppdu_sts_info ppdu_sts;
u8 total_sta_assoc;
bool scanning;
- const struct rtw89_regulatory *regd;
+ struct rtw89_regulatory_info regulatory;
struct rtw89_sar_info sar;
struct rtw89_btc btc;
@@ -4643,6 +4681,14 @@ static inline void rtw89_chip_fem_setup(struct rtw89_dev *rtwdev)
chip->ops->fem_setup(rtwdev);
}
+static inline void rtw89_chip_rfe_gpio(struct rtw89_dev *rtwdev)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
+ if (chip->ops->rfe_gpio)
+ chip->ops->rfe_gpio(rtwdev);
+}
+
static inline void rtw89_chip_bb_sethw(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
@@ -4777,7 +4823,9 @@ static inline void rtw89_load_txpwr_table(struct rtw89_dev *rtwdev,
static inline u8 rtw89_regd_get(struct rtw89_dev *rtwdev, u8 band)
{
- return rtwdev->regd->txpwr_regd[band];
+ const struct rtw89_regd *regd = rtwdev->regulatory.regd;
+
+ return regd->txpwr_regd[band];
}
static inline void rtw89_ctrl_btg(struct rtw89_dev *rtwdev, bool btg)
@@ -4789,6 +4837,16 @@ static inline void rtw89_ctrl_btg(struct rtw89_dev *rtwdev, bool btg)
}
static inline
+void rtw89_chip_query_rxdesc(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_desc_info *desc_info,
+ u8 *data, u32 data_offset)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
+ chip->ops->query_rxdesc(rtwdev, desc_info, data, data_offset);
+}
+
+static inline
void rtw89_chip_fill_txdesc(struct rtw89_dev *rtwdev,
struct rtw89_tx_desc_info *desc_info,
void *txdesc)
@@ -4990,6 +5048,7 @@ int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev,
void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc);
int rtw89_chip_info_setup(struct rtw89_dev *rtwdev);
bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate);
+int rtw89_regd_setup(struct rtw89_dev *rtwdev);
int rtw89_regd_init(struct rtw89_dev *rtwdev,
void (*reg_notifier)(struct wiphy *wiphy, struct regulatory_request *request));
void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request);
@@ -5008,5 +5067,7 @@ void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
const u8 *mac_addr, bool hw_scan);
void rtw89_core_scan_complete(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif, bool hw_scan);
+void rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev,
+ struct rtw89_vif *rtwvif, bool active);
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index 1e5b7a998716..a4bbac916e22 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -30,7 +30,7 @@ struct rtw89_debugfs_priv {
u32 cb_data;
struct {
u32 addr;
- u8 len;
+ u32 len;
} read_reg;
struct {
u32 addr;
@@ -164,12 +164,15 @@ static int rtw89_debug_priv_read_reg_get(struct seq_file *m, void *v)
{
struct rtw89_debugfs_priv *debugfs_priv = m->private;
struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
- u32 addr, data;
- u8 len;
+ u32 addr, end, data, k;
+ u32 len;
len = debugfs_priv->read_reg.len;
addr = debugfs_priv->read_reg.addr;
+ if (len > 4)
+ goto ndata;
+
switch (len) {
case 1:
data = rtw89_read8(rtwdev, addr);
@@ -188,6 +191,20 @@ static int rtw89_debug_priv_read_reg_get(struct seq_file *m, void *v)
seq_printf(m, "get %d bytes at 0x%08x=0x%08x\n", len, addr, data);
return 0;
+
+ndata:
+ end = addr + len;
+
+ for (; addr < end; addr += 16) {
+ seq_printf(m, "%08xh : ", 0x18600000 + addr);
+ for (k = 0; k < 16; k += 4) {
+ data = rtw89_read32(rtwdev, addr + k);
+ seq_printf(m, "%08x ", data);
+ }
+ seq_puts(m, "\n");
+ }
+
+ return 0;
}
static ssize_t rtw89_debug_priv_write_reg_set(struct file *filp,
@@ -359,6 +376,7 @@ struct txpwr_map {
u8 size;
u32 addr_from;
u32 addr_to;
+ u32 addr_to_1ss;
};
#define __GEN_TXPWR_ENT2(_t, _e0, _e1) \
@@ -396,6 +414,7 @@ static const struct txpwr_map __txpwr_map_byr = {
.size = ARRAY_SIZE(__txpwr_ent_byr),
.addr_from = R_AX_PWR_BY_RATE,
.addr_to = R_AX_PWR_BY_RATE_MAX,
+ .addr_to_1ss = R_AX_PWR_BY_RATE_1SS_MAX,
};
static const struct txpwr_ent __txpwr_ent_lmt[] = {
@@ -451,6 +470,7 @@ static const struct txpwr_map __txpwr_map_lmt = {
.size = ARRAY_SIZE(__txpwr_ent_lmt),
.addr_from = R_AX_PWR_LMT,
.addr_to = R_AX_PWR_LMT_MAX,
+ .addr_to_1ss = R_AX_PWR_LMT_1SS_MAX,
};
static const struct txpwr_ent __txpwr_ent_lmt_ru[] = {
@@ -478,6 +498,7 @@ static const struct txpwr_map __txpwr_map_lmt_ru = {
.size = ARRAY_SIZE(__txpwr_ent_lmt_ru),
.addr_from = R_AX_PWR_RU_LMT,
.addr_to = R_AX_PWR_RU_LMT_MAX,
+ .addr_to_1ss = R_AX_PWR_RU_LMT_1SS_MAX,
};
static u8 __print_txpwr_ent(struct seq_file *m, const struct txpwr_ent *ent,
@@ -510,6 +531,8 @@ static int __print_txpwr_map(struct seq_file *m, struct rtw89_dev *rtwdev,
const struct txpwr_map *map)
{
u8 fct = rtwdev->chip->txpwr_factor_mac;
+ u8 path_num = rtwdev->chip->rf_path_num;
+ u32 max_valid_addr;
u32 val, addr;
s8 *buf, tmp;
u8 cur, i;
@@ -519,7 +542,12 @@ static int __print_txpwr_map(struct seq_file *m, struct rtw89_dev *rtwdev,
if (!buf)
return -ENOMEM;
- for (addr = map->addr_from; addr <= map->addr_to; addr += 4) {
+ if (path_num == 1)
+ max_valid_addr = map->addr_to_1ss;
+ else
+ max_valid_addr = map->addr_to;
+
+ for (addr = map->addr_from; addr <= max_valid_addr; addr += 4) {
ret = rtw89_mac_txpwr_read32(rtwdev, RTW89_PHY_0, addr, &val);
if (ret)
val = MASKDWORD;
@@ -2998,17 +3026,18 @@ static ssize_t rtw89_debug_priv_send_h2c_set(struct file *filp,
struct rtw89_debugfs_priv *debugfs_priv = filp->private_data;
struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
u8 *h2c;
+ int ret;
u16 h2c_len = count / 2;
h2c = rtw89_hex2bin_user(rtwdev, user_buf, count);
if (IS_ERR(h2c))
return -EFAULT;
- rtw89_fw_h2c_raw(rtwdev, h2c, h2c_len);
+ ret = rtw89_fw_h2c_raw(rtwdev, h2c, h2c_len);
kfree(h2c);
- return count;
+ return ret ? ret : count;
}
static int
@@ -3206,7 +3235,11 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
struct seq_file *m = (struct seq_file *)data;
struct rtw89_dev *rtwdev = rtwsta->rtwdev;
struct rtw89_hal *hal = &rtwdev->hal;
+ u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num;
+ bool ant_asterisk = hal->tx_path_diversity || hal->ant_diversity;
+ u8 evm_min, evm_max;
u8 rssi;
+ u8 snr;
int i;
seq_printf(m, "TX rate [%d]: ", rtwsta->mac_id);
@@ -3256,13 +3289,27 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
rssi = ewma_rssi_read(&rtwsta->avg_rssi);
seq_printf(m, "RSSI: %d dBm (raw=%d, prev=%d) [",
RTW89_RSSI_RAW_TO_DBM(rssi), rssi, rtwsta->prev_rssi);
- for (i = 0; i < rtwdev->chip->rf_path_num; i++) {
+ for (i = 0; i < ant_num; i++) {
rssi = ewma_rssi_read(&rtwsta->rssi[i]);
seq_printf(m, "%d%s%s", RTW89_RSSI_RAW_TO_DBM(rssi),
- hal->tx_path_diversity && (hal->antenna_tx & BIT(i)) ? "*" : "",
- i + 1 == rtwdev->chip->rf_path_num ? "" : ", ");
+ ant_asterisk && (hal->antenna_tx & BIT(i)) ? "*" : "",
+ i + 1 == ant_num ? "" : ", ");
}
seq_puts(m, "]\n");
+
+ seq_puts(m, "EVM: [");
+ for (i = 0; i < (hal->ant_diversity ? 2 : 1); i++) {
+ evm_min = ewma_evm_read(&rtwsta->evm_min[i]);
+ evm_max = ewma_evm_read(&rtwsta->evm_max[i]);
+
+ seq_printf(m, "%s(%2u.%02u, %2u.%02u)", i == 0 ? "" : " ",
+ evm_min >> 2, (evm_min & 0x3) * 25,
+ evm_max >> 2, (evm_max & 0x3) * 25);
+ }
+ seq_puts(m, "]\t");
+
+ snr = ewma_snr_read(&rtwsta->avg_snr);
+ seq_printf(m, "SNR: %u\n", snr);
}
static void
diff --git a/drivers/net/wireless/realtek/rtw89/efuse.c b/drivers/net/wireless/realtek/rtw89/efuse.c
index 7bd4f8558e03..2aaf4d013e46 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse.c
+++ b/drivers/net/wireless/realtek/rtw89/efuse.c
@@ -7,6 +7,10 @@
#include "mac.h"
#include "reg.h"
+#define EF_FV_OFSET 0x5ea
+#define EF_CV_MASK GENMASK(7, 4)
+#define EF_CV_INV 15
+
enum rtw89_efuse_bank {
RTW89_EFUSE_BANK_WIFI,
RTW89_EFUSE_BANK_BT,
@@ -328,3 +332,20 @@ out_free:
return ret;
}
+
+int rtw89_read_efuse_ver(struct rtw89_dev *rtwdev, u8 *ecv)
+{
+ int ret;
+ u8 val;
+
+ ret = rtw89_dump_physical_efuse_map(rtwdev, &val, EF_FV_OFSET, 1, false);
+ if (ret)
+ return ret;
+
+ *ecv = u8_get_bits(val, EF_CV_MASK);
+ if (*ecv == EF_CV_INV)
+ return -ENOENT;
+
+ return 0;
+}
+EXPORT_SYMBOL(rtw89_read_efuse_ver);
diff --git a/drivers/net/wireless/realtek/rtw89/efuse.h b/drivers/net/wireless/realtek/rtw89/efuse.h
index 622ff95e7476..79071aff28de 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse.h
+++ b/drivers/net/wireless/realtek/rtw89/efuse.h
@@ -9,5 +9,6 @@
int rtw89_parse_efuse_map(struct rtw89_dev *rtwdev);
int rtw89_parse_phycap_map(struct rtw89_dev *rtwdev);
+int rtw89_read_efuse_ver(struct rtw89_dev *rtwdev, u8 *efv);
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index b9b675bf9d05..9637f5e48d84 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -14,6 +14,8 @@
static void rtw89_fw_c2h_cmd_handle(struct rtw89_dev *rtwdev,
struct sk_buff *skb);
+static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb,
+ struct rtw89_wait_info *wait, unsigned int cond);
static struct sk_buff *rtw89_fw_h2c_alloc_skb(struct rtw89_dev *rtwdev, u32 len,
bool header)
@@ -87,9 +89,11 @@ int rtw89_fw_check_rdy(struct rtw89_dev *rtwdev)
static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, const u8 *fw, u32 len,
struct rtw89_fw_bin_info *info)
{
+ const struct rtw89_fw_hdr *fw_hdr = (const struct rtw89_fw_hdr *)fw;
struct rtw89_fw_hdr_section_info *section_info;
+ const struct rtw89_fw_dynhdr_hdr *fwdynhdr;
+ const struct rtw89_fw_hdr_section *section;
const u8 *fw_end = fw + len;
- const u8 *fwdynhdr;
const u8 *bin;
u32 base_hdr_len;
u32 mssc_len = 0;
@@ -98,16 +102,15 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, const u8 *fw, u32 len,
if (!info)
return -EINVAL;
- info->section_num = GET_FW_HDR_SEC_NUM(fw);
- base_hdr_len = RTW89_FW_HDR_SIZE +
- info->section_num * RTW89_FW_SECTION_HDR_SIZE;
- info->dynamic_hdr_en = GET_FW_HDR_DYN_HDR(fw);
+ info->section_num = le32_get_bits(fw_hdr->w6, FW_HDR_W6_SEC_NUM);
+ base_hdr_len = struct_size(fw_hdr, sections, info->section_num);
+ info->dynamic_hdr_en = le32_get_bits(fw_hdr->w7, FW_HDR_W7_DYN_HDR);
if (info->dynamic_hdr_en) {
- info->hdr_len = GET_FW_HDR_LEN(fw);
+ info->hdr_len = le32_get_bits(fw_hdr->w3, FW_HDR_W3_LEN);
info->dynamic_hdr_len = info->hdr_len - base_hdr_len;
- fwdynhdr = fw + base_hdr_len;
- if (GET_FW_DYNHDR_LEN(fwdynhdr) != info->dynamic_hdr_len) {
+ fwdynhdr = (const struct rtw89_fw_dynhdr_hdr *)(fw + base_hdr_len);
+ if (le32_to_cpu(fwdynhdr->hdr_len) != info->dynamic_hdr_len) {
rtw89_err(rtwdev, "[ERR]invalid fw dynamic header len\n");
return -EINVAL;
}
@@ -119,26 +122,27 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, const u8 *fw, u32 len,
bin = fw + info->hdr_len;
/* jump to section header */
- fw += RTW89_FW_HDR_SIZE;
section_info = info->section_info;
for (i = 0; i < info->section_num; i++) {
- section_info->type = GET_FWSECTION_HDR_SECTIONTYPE(fw);
+ section = &fw_hdr->sections[i];
+ section_info->type =
+ le32_get_bits(section->w1, FWSECTION_HDR_W1_SECTIONTYPE);
if (section_info->type == FWDL_SECURITY_SECTION_TYPE) {
- section_info->mssc = GET_FWSECTION_HDR_MSSC(fw);
+ section_info->mssc =
+ le32_get_bits(section->w2, FWSECTION_HDR_W2_MSSC);
mssc_len += section_info->mssc * FWDL_SECURITY_SIGLEN;
} else {
section_info->mssc = 0;
}
- section_info->len = GET_FWSECTION_HDR_SEC_SIZE(fw);
- if (GET_FWSECTION_HDR_CHECKSUM(fw))
+ section_info->len = le32_get_bits(section->w1, FWSECTION_HDR_W1_SEC_SIZE);
+ if (le32_get_bits(section->w1, FWSECTION_HDR_W1_CHECKSUM))
section_info->len += FWDL_SECTION_CHKSUM_LEN;
- section_info->redl = GET_FWSECTION_HDR_REDL(fw);
+ section_info->redl = le32_get_bits(section->w1, FWSECTION_HDR_W1_REDL);
section_info->dladdr =
- GET_FWSECTION_HDR_DL_ADDR(fw) & 0x1fffffff;
+ le32_get_bits(section->w0, FWSECTION_HDR_W0_DL_ADDR) & 0x1fffffff;
section_info->addr = bin;
bin += section_info->len;
- fw += RTW89_FW_SECTION_HDR_SIZE;
section_info++;
}
@@ -193,18 +197,18 @@ static void rtw89_fw_update_ver(struct rtw89_dev *rtwdev,
enum rtw89_fw_type type,
struct rtw89_fw_suit *fw_suit)
{
- const u8 *hdr = fw_suit->data;
-
- fw_suit->major_ver = GET_FW_HDR_MAJOR_VERSION(hdr);
- fw_suit->minor_ver = GET_FW_HDR_MINOR_VERSION(hdr);
- fw_suit->sub_ver = GET_FW_HDR_SUBVERSION(hdr);
- fw_suit->sub_idex = GET_FW_HDR_SUBINDEX(hdr);
- fw_suit->build_year = GET_FW_HDR_YEAR(hdr);
- fw_suit->build_mon = GET_FW_HDR_MONTH(hdr);
- fw_suit->build_date = GET_FW_HDR_DATE(hdr);
- fw_suit->build_hour = GET_FW_HDR_HOUR(hdr);
- fw_suit->build_min = GET_FW_HDR_MIN(hdr);
- fw_suit->cmd_ver = GET_FW_HDR_CMD_VERSERION(hdr);
+ const struct rtw89_fw_hdr *hdr = (const struct rtw89_fw_hdr *)fw_suit->data;
+
+ fw_suit->major_ver = le32_get_bits(hdr->w1, FW_HDR_W1_MAJOR_VERSION);
+ fw_suit->minor_ver = le32_get_bits(hdr->w1, FW_HDR_W1_MINOR_VERSION);
+ fw_suit->sub_ver = le32_get_bits(hdr->w1, FW_HDR_W1_SUBVERSION);
+ fw_suit->sub_idex = le32_get_bits(hdr->w1, FW_HDR_W1_SUBINDEX);
+ fw_suit->build_year = le32_get_bits(hdr->w5, FW_HDR_W5_YEAR);
+ fw_suit->build_mon = le32_get_bits(hdr->w4, FW_HDR_W4_MONTH);
+ fw_suit->build_date = le32_get_bits(hdr->w4, FW_HDR_W4_DATE);
+ fw_suit->build_hour = le32_get_bits(hdr->w4, FW_HDR_W4_HOUR);
+ fw_suit->build_min = le32_get_bits(hdr->w4, FW_HDR_W4_MIN);
+ fw_suit->cmd_ver = le32_get_bits(hdr->w7, FW_HDR_W7_CMD_VERSERION);
rtw89_info(rtwdev,
"Firmware version %u.%u.%u.%u, cmd version %u, type %u\n",
@@ -254,6 +258,9 @@ struct __fw_feat_cfg {
}
static const struct __fw_feat_cfg fw_feat_tbl[] = {
+ __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 37, 1, TX_WAKE),
+ __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 37, 1, SCAN_OFFLOAD),
+ __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 41, 0, CRASH_TRIGGER),
__CFG_FW_FEAT(RTL8852A, le, 0, 13, 29, 0, OLD_HT_RA_FORMAT),
__CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, SCAN_OFFLOAD),
__CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, TX_WAKE),
@@ -807,7 +814,7 @@ int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
}
skb_put(skb, H2C_BA_CAM_LEN);
SET_BA_CAM_MACID(skb->data, macid);
- if (chip->bacam_v1)
+ if (chip->bacam_ver == RTW89_BACAM_V0_EXT)
SET_BA_CAM_ENTRY_IDX_V1(skb->data, entry_idx);
else
SET_BA_CAM_ENTRY_IDX(skb->data, entry_idx);
@@ -823,7 +830,7 @@ int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
SET_BA_CAM_INIT_REQ(skb->data, 1);
SET_BA_CAM_SSN(skb->data, params->ssn);
- if (chip->bacam_v1) {
+ if (chip->bacam_ver == RTW89_BACAM_V0_EXT) {
SET_BA_CAM_STD_EN(skb->data, 1);
SET_BA_CAM_BAND(skb->data, rtwvif->mac_idx);
}
@@ -848,8 +855,8 @@ fail:
return ret;
}
-static int rtw89_fw_h2c_init_dynamic_ba_cam_v1(struct rtw89_dev *rtwdev,
- u8 entry_idx, u8 uid)
+static int rtw89_fw_h2c_init_ba_cam_v0_ext(struct rtw89_dev *rtwdev,
+ u8 entry_idx, u8 uid)
{
struct sk_buff *skb;
int ret;
@@ -886,7 +893,7 @@ fail:
return ret;
}
-void rtw89_fw_h2c_init_ba_cam_v1(struct rtw89_dev *rtwdev)
+void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
u8 entry_idx = chip->bacam_num;
@@ -894,7 +901,7 @@ void rtw89_fw_h2c_init_ba_cam_v1(struct rtw89_dev *rtwdev)
int i;
for (i = 0; i < chip->bacam_dynamic_num; i++) {
- rtw89_fw_h2c_init_dynamic_ba_cam_v1(rtwdev, entry_idx, uid);
+ rtw89_fw_h2c_init_ba_cam_v0_ext(rtwdev, entry_idx, uid);
entry_idx++;
uid++;
}
@@ -997,8 +1004,8 @@ void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev,
list_for_each_entry_safe(info, tmp, pkt_list, list) {
if (notify_fw)
rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id);
- rtw89_core_release_bit_map(rtwdev->pkt_offload,
- info->id);
+ else
+ rtw89_core_release_bit_map(rtwdev->pkt_offload, info->id);
list_del(&info->list);
kfree(info);
}
@@ -2440,7 +2447,9 @@ fail:
#define H2C_LEN_PKT_OFLD 4
int rtw89_fw_h2c_del_pkt_offload(struct rtw89_dev *rtwdev, u8 id)
{
+ struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
struct sk_buff *skb;
+ unsigned int cond;
u8 *cmd;
int ret;
@@ -2460,23 +2469,26 @@ int rtw89_fw_h2c_del_pkt_offload(struct rtw89_dev *rtwdev, u8 id)
H2C_FUNC_PACKET_OFLD, 1, 1,
H2C_LEN_PKT_OFLD);
- ret = rtw89_h2c_tx(rtwdev, skb, false);
- if (ret) {
- rtw89_err(rtwdev, "failed to send h2c\n");
- goto fail;
+ cond = RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(id, RTW89_PKT_OFLD_OP_DEL);
+
+ ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
+ if (ret < 0) {
+ rtw89_debug(rtwdev, RTW89_DBG_FW,
+ "failed to del pkt ofld: id %d, ret %d\n",
+ id, ret);
+ return ret;
}
+ rtw89_core_release_bit_map(rtwdev->pkt_offload, id);
return 0;
-fail:
- dev_kfree_skb_any(skb);
-
- return ret;
}
int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id,
struct sk_buff *skb_ofld)
{
+ struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
struct sk_buff *skb;
+ unsigned int cond;
u8 *cmd;
u8 alloc_id;
int ret;
@@ -2507,27 +2519,29 @@ int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id,
H2C_FUNC_PACKET_OFLD, 1, 1,
H2C_LEN_PKT_OFLD + skb_ofld->len);
- ret = rtw89_h2c_tx(rtwdev, skb, false);
- if (ret) {
- rtw89_err(rtwdev, "failed to send h2c\n");
+ cond = RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(alloc_id, RTW89_PKT_OFLD_OP_ADD);
+
+ ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
+ if (ret < 0) {
+ rtw89_debug(rtwdev, RTW89_DBG_FW,
+ "failed to add pkt ofld: id %d, ret %d\n",
+ alloc_id, ret);
rtw89_core_release_bit_map(rtwdev->pkt_offload, alloc_id);
- goto fail;
+ return ret;
}
return 0;
-fail:
- dev_kfree_skb_any(skb);
-
- return ret;
}
#define H2C_LEN_SCAN_LIST_OFFLOAD 4
int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int len,
struct list_head *chan_list)
{
+ struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
struct rtw89_mac_chinfo *ch_info;
struct sk_buff *skb;
int skb_len = H2C_LEN_SCAN_LIST_OFFLOAD + len * RTW89_MAC_CHINFO_SIZE;
+ unsigned int cond;
u8 *cmd;
int ret;
@@ -2574,27 +2588,27 @@ int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int len,
H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
H2C_FUNC_ADD_SCANOFLD_CH, 1, 1, skb_len);
- ret = rtw89_h2c_tx(rtwdev, skb, false);
+ cond = RTW89_FW_OFLD_WAIT_COND(0, H2C_FUNC_ADD_SCANOFLD_CH);
+
+ ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
if (ret) {
- rtw89_err(rtwdev, "failed to send h2c\n");
- goto fail;
+ rtw89_debug(rtwdev, RTW89_DBG_FW, "failed to add scan ofld ch\n");
+ return ret;
}
return 0;
-fail:
- dev_kfree_skb_any(skb);
-
- return ret;
}
int rtw89_fw_h2c_scan_offload(struct rtw89_dev *rtwdev,
struct rtw89_scan_option *option,
struct rtw89_vif *rtwvif)
{
+ struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
struct rtw89_chan *op = &rtwdev->scan_info.op_chan;
struct rtw89_h2c_scanofld *h2c;
u32 len = sizeof(*h2c);
struct sk_buff *skb;
+ unsigned int cond;
int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
@@ -2633,17 +2647,15 @@ int rtw89_fw_h2c_scan_offload(struct rtw89_dev *rtwdev,
H2C_FUNC_SCANOFLD, 1, 1,
len);
- ret = rtw89_h2c_tx(rtwdev, skb, false);
+ cond = RTW89_FW_OFLD_WAIT_COND(0, H2C_FUNC_SCANOFLD);
+
+ ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
if (ret) {
- rtw89_err(rtwdev, "failed to send h2c\n");
- goto fail;
+ rtw89_debug(rtwdev, RTW89_DBG_FW, "failed to scan ofld\n");
+ return ret;
}
return 0;
-fail:
- dev_kfree_skb_any(skb);
-
- return ret;
}
int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev,
@@ -2909,12 +2921,13 @@ static int rtw89_fw_write_h2c_reg(struct rtw89_dev *rtwdev,
}
len = DIV_ROUND_UP(info->content_len + RTW89_H2CREG_HDR_LEN,
- sizeof(info->h2creg[0]));
+ sizeof(info->u.h2creg[0]));
+
+ u32p_replace_bits(&info->u.hdr.w0, info->id, RTW89_H2CREG_HDR_FUNC_MASK);
+ u32p_replace_bits(&info->u.hdr.w0, len, RTW89_H2CREG_HDR_LEN_MASK);
- RTW89_SET_H2CREG_HDR_FUNC(&info->h2creg[0], info->id);
- RTW89_SET_H2CREG_HDR_LEN(&info->h2creg[0], len);
for (i = 0; i < RTW89_H2CREG_MAX; i++)
- rtw89_write32(rtwdev, h2c_reg[i], info->h2creg[i]);
+ rtw89_write32(rtwdev, h2c_reg[i], info->u.h2creg[i]);
fw_info->h2c_counter++;
rtw89_write8_mask(rtwdev, chip->h2c_counter_reg.addr,
@@ -2944,13 +2957,14 @@ static int rtw89_fw_read_c2h_reg(struct rtw89_dev *rtwdev,
}
for (i = 0; i < RTW89_C2HREG_MAX; i++)
- info->c2hreg[i] = rtw89_read32(rtwdev, c2h_reg[i]);
+ info->u.c2hreg[i] = rtw89_read32(rtwdev, c2h_reg[i]);
rtw89_write8(rtwdev, chip->c2h_ctrl_reg, 0);
- info->id = RTW89_GET_C2H_HDR_FUNC(*info->c2hreg);
- info->content_len = (RTW89_GET_C2H_HDR_LEN(*info->c2hreg) << 2) -
- RTW89_C2HREG_HDR_LEN;
+ info->id = u32_get_bits(info->u.hdr.w0, RTW89_C2HREG_HDR_FUNC_MASK);
+ info->content_len =
+ (u32_get_bits(info->u.hdr.w0, RTW89_C2HREG_HDR_LEN_MASK) << 2) -
+ RTW89_C2HREG_HDR_LEN;
fw_info->c2h_counter++;
rtw89_write8_mask(rtwdev, chip->c2h_counter_reg.addr,
@@ -3019,9 +3033,8 @@ static void rtw89_release_pkt_list(struct rtw89_dev *rtwdev)
continue;
list_for_each_entry_safe(info, tmp, &pkt_list[idx], list) {
- rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id);
- rtw89_core_release_bit_map(rtwdev->pkt_offload,
- info->id);
+ if (test_bit(info->id, rtwdev->pkt_offload))
+ rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id);
list_del(&info->list);
kfree(info);
}
@@ -3786,6 +3799,11 @@ fail:
return ret;
}
+/* Return < 0, if failures happen during waiting for the condition.
+ * Return 0, when waiting for the condition succeeds.
+ * Return > 0, if the wait is considered unreachable due to driver/FW design,
+ * where 1 means during SER.
+ */
static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb,
struct rtw89_wait_info *wait, unsigned int cond)
{
@@ -3798,6 +3816,9 @@ static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb,
return -EBUSY;
}
+ if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags))
+ return 1;
+
return rtw89_wait_for_cond(wait, cond);
}
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index 675f85c41471..45f927dc212e 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -18,15 +18,51 @@ enum rtw89_fw_dl_status {
RTW89_FWDL_WCPU_FW_INIT_RDY = 7
};
-#define RTW89_GET_C2H_HDR_FUNC(info) \
- u32_get_bits(info, GENMASK(6, 0))
-#define RTW89_GET_C2H_HDR_LEN(info) \
- u32_get_bits(info, GENMASK(11, 8))
+struct rtw89_c2hreg_hdr {
+ u32 w0;
+};
+
+#define RTW89_C2HREG_HDR_FUNC_MASK GENMASK(6, 0)
+#define RTW89_C2HREG_HDR_ACK BIT(7)
+#define RTW89_C2HREG_HDR_LEN_MASK GENMASK(11, 8)
+#define RTW89_C2HREG_HDR_SEQ_MASK GENMASK(15, 12)
+
+struct rtw89_c2hreg_phycap {
+ u32 w0;
+ u32 w1;
+ u32 w2;
+ u32 w3;
+} __packed;
+
+#define RTW89_C2HREG_PHYCAP_W0_FUNC GENMASK(6, 0)
+#define RTW89_C2HREG_PHYCAP_W0_ACK BIT(7)
+#define RTW89_C2HREG_PHYCAP_W0_LEN GENMASK(11, 8)
+#define RTW89_C2HREG_PHYCAP_W0_SEQ GENMASK(15, 12)
+#define RTW89_C2HREG_PHYCAP_W0_RX_NSS GENMASK(23, 16)
+#define RTW89_C2HREG_PHYCAP_W0_BW GENMASK(31, 24)
+#define RTW89_C2HREG_PHYCAP_W1_TX_NSS GENMASK(7, 0)
+#define RTW89_C2HREG_PHYCAP_W1_PROT GENMASK(15, 8)
+#define RTW89_C2HREG_PHYCAP_W1_NIC GENMASK(23, 16)
+#define RTW89_C2HREG_PHYCAP_W1_WL_FUNC GENMASK(31, 24)
+#define RTW89_C2HREG_PHYCAP_W2_HW_TYPE GENMASK(7, 0)
+#define RTW89_C2HREG_PHYCAP_W3_ANT_TX_NUM GENMASK(15, 8)
+#define RTW89_C2HREG_PHYCAP_W3_ANT_RX_NUM GENMASK(23, 16)
+
+struct rtw89_h2creg_hdr {
+ u32 w0;
+};
+
+#define RTW89_H2CREG_HDR_FUNC_MASK GENMASK(6, 0)
+#define RTW89_H2CREG_HDR_LEN_MASK GENMASK(11, 8)
-#define RTW89_SET_H2CREG_HDR_FUNC(info, val) \
- u32p_replace_bits(info, val, GENMASK(6, 0))
-#define RTW89_SET_H2CREG_HDR_LEN(info, val) \
- u32p_replace_bits(info, val, GENMASK(11, 8))
+struct rtw89_h2creg_sch_tx_en {
+ u32 w0;
+ u32 w1;
+} __packed;
+
+#define RTW89_H2CREG_SCH_TX_EN_W0_EN GENMASK(31, 16)
+#define RTW89_H2CREG_SCH_TX_EN_W1_MASK GENMASK(15, 0)
+#define RTW89_H2CREG_SCH_TX_EN_W1_BAND BIT(16)
#define RTW89_H2CREG_MAX 4
#define RTW89_C2HREG_MAX 4
@@ -36,13 +72,21 @@ enum rtw89_fw_dl_status {
struct rtw89_mac_c2h_info {
u8 id;
u8 content_len;
- u32 c2hreg[RTW89_C2HREG_MAX];
+ union {
+ u32 c2hreg[RTW89_C2HREG_MAX];
+ struct rtw89_c2hreg_hdr hdr;
+ struct rtw89_c2hreg_phycap phycap;
+ } u;
};
struct rtw89_mac_h2c_info {
u8 id;
u8 content_len;
- u32 h2creg[RTW89_H2CREG_MAX];
+ union {
+ u32 h2creg[RTW89_H2CREG_MAX];
+ struct rtw89_h2creg_hdr hdr;
+ struct rtw89_h2creg_sch_tx_en sch_tx_en;
+ } u;
};
enum rtw89_mac_h2c_type {
@@ -63,33 +107,6 @@ enum rtw89_mac_c2h_type {
RTW89_FWCMD_C2HREG_FUNC_NULL = 0xFF
};
-#define RTW89_GET_C2H_PHYCAP_FUNC(info) \
- u32_get_bits(*((const u32 *)(info)), GENMASK(6, 0))
-#define RTW89_GET_C2H_PHYCAP_ACK(info) \
- u32_get_bits(*((const u32 *)(info)), BIT(7))
-#define RTW89_GET_C2H_PHYCAP_LEN(info) \
- u32_get_bits(*((const u32 *)(info)), GENMASK(11, 8))
-#define RTW89_GET_C2H_PHYCAP_SEQ(info) \
- u32_get_bits(*((const u32 *)(info)), GENMASK(15, 12))
-#define RTW89_GET_C2H_PHYCAP_RX_NSS(info) \
- u32_get_bits(*((const u32 *)(info)), GENMASK(23, 16))
-#define RTW89_GET_C2H_PHYCAP_BW(info) \
- u32_get_bits(*((const u32 *)(info)), GENMASK(31, 24))
-#define RTW89_GET_C2H_PHYCAP_TX_NSS(info) \
- u32_get_bits(*((const u32 *)(info) + 1), GENMASK(7, 0))
-#define RTW89_GET_C2H_PHYCAP_PROT(info) \
- u32_get_bits(*((const u32 *)(info) + 1), GENMASK(15, 8))
-#define RTW89_GET_C2H_PHYCAP_NIC(info) \
- u32_get_bits(*((const u32 *)(info) + 1), GENMASK(23, 16))
-#define RTW89_GET_C2H_PHYCAP_WL_FUNC(info) \
- u32_get_bits(*((const u32 *)(info) + 1), GENMASK(31, 24))
-#define RTW89_GET_C2H_PHYCAP_HW_TYPE(info) \
- u32_get_bits(*((const u32 *)(info) + 2), GENMASK(7, 0))
-#define RTW89_GET_C2H_PHYCAP_ANT_TX_NUM(info) \
- u32_get_bits(*((const u32 *)(info) + 3), GENMASK(15, 8))
-#define RTW89_GET_C2H_PHYCAP_ANT_RX_NUM(info) \
- u32_get_bits(*((const u32 *)(info) + 3), GENMASK(23, 16))
-
enum rtw89_fw_c2h_category {
RTW89_C2H_CAT_TEST,
RTW89_C2H_CAT_MAC,
@@ -138,8 +155,13 @@ enum rtw89_pkt_offload_op {
RTW89_PKT_OFLD_OP_ADD,
RTW89_PKT_OFLD_OP_DEL,
RTW89_PKT_OFLD_OP_READ,
+
+ NUM_OF_RTW89_PKT_OFFLOAD_OP,
};
+#define RTW89_PKT_OFLD_WAIT_TAG(pkt_id, pkt_op) \
+ ((pkt_id) * NUM_OF_RTW89_PKT_OFFLOAD_OP + (pkt_op))
+
enum rtw89_scanofld_notify_reason {
RTW89_SCAN_DWELL_NOTIFY,
RTW89_SCAN_PRE_TX_NOTIFY,
@@ -209,17 +231,6 @@ struct rtw89_fw_macid_pause_grp {
__le32 mask_grp[4];
} __packed;
-struct rtw89_h2creg_sch_tx_en {
- u8 func:7;
- u8 ack:1;
- u8 total_len:4;
- u8 seq_num:4;
- u16 tx_en:16;
- u16 mask:16;
- u8 band:1;
- u16 rsvd:15;
-} __packed;
-
#define RTW89_H2C_MAX_SIZE 2048
#define RTW89_CHANNEL_TIME 45
#define RTW89_CHANNEL_TIME_6G 20
@@ -232,7 +243,7 @@ struct rtw89_h2creg_sch_tx_en {
#define RTW89_SCANOFLD_MAX_IE_LEN 512
#define RTW89_SCANOFLD_PKT_NONE 0xFF
#define RTW89_SCANOFLD_DEBUG_MASK 0x1F
-#define RTW89_MAC_CHINFO_SIZE 24
+#define RTW89_MAC_CHINFO_SIZE 28
#define RTW89_SCAN_LIST_GUARD 4
#define RTW89_SCAN_LIST_LIMIT \
((RTW89_H2C_MAX_SIZE / RTW89_MAC_CHINFO_SIZE) - RTW89_SCAN_LIST_GUARD)
@@ -277,6 +288,7 @@ struct rtw89_pktofld_info {
u8 ssid_len;
u8 bssid[ETH_ALEN];
u16 channel_6ghz;
+ bool cancel;
};
static inline void RTW89_SET_FWCMD_RA_IS_DIS(void *cmd, u32 val)
@@ -516,50 +528,58 @@ static inline void RTW89_SET_EDCA_PARAM(void *cmd, u32 val)
#define FWDL_SECURITY_SECTION_TYPE 9
#define FWDL_SECURITY_SIGLEN 512
-#define GET_FWSECTION_HDR_DL_ADDR(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr)), GENMASK(31, 0))
-#define GET_FWSECTION_HDR_SECTIONTYPE(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(27, 24))
-#define GET_FWSECTION_HDR_SEC_SIZE(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(23, 0))
-#define GET_FWSECTION_HDR_CHECKSUM(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 1), BIT(28))
-#define GET_FWSECTION_HDR_REDL(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 1), BIT(29))
-#define GET_FWSECTION_HDR_MSSC(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 2), GENMASK(31, 0))
-
-#define GET_FW_HDR_MAJOR_VERSION(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(7, 0))
-#define GET_FW_HDR_MINOR_VERSION(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(15, 8))
-#define GET_FW_HDR_SUBVERSION(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(23, 16))
-#define GET_FW_HDR_SUBINDEX(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(31, 24))
-#define GET_FW_HDR_LEN(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 3), GENMASK(23, 16))
-#define GET_FW_HDR_MONTH(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 4), GENMASK(7, 0))
-#define GET_FW_HDR_DATE(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 4), GENMASK(15, 8))
-#define GET_FW_HDR_HOUR(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 4), GENMASK(23, 16))
-#define GET_FW_HDR_MIN(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 4), GENMASK(31, 24))
-#define GET_FW_HDR_YEAR(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 5), GENMASK(31, 0))
-#define GET_FW_HDR_SEC_NUM(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 6), GENMASK(15, 8))
-#define GET_FW_HDR_DYN_HDR(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 7), BIT(16))
-#define GET_FW_HDR_CMD_VERSERION(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 7), GENMASK(31, 24))
-
-#define GET_FW_DYNHDR_LEN(fwdynhdr) \
- le32_get_bits(*((const __le32 *)(fwdynhdr)), GENMASK(31, 0))
-#define GET_FW_DYNHDR_COUNT(fwdynhdr) \
- le32_get_bits(*((const __le32 *)(fwdynhdr) + 1), GENMASK(31, 0))
+struct rtw89_fw_dynhdr_sec {
+ __le32 w0;
+ u8 content[];
+} __packed;
+
+struct rtw89_fw_dynhdr_hdr {
+ __le32 hdr_len;
+ __le32 setcion_count;
+ /* struct rtw89_fw_dynhdr_sec (nested flexible structures) */
+} __packed;
+
+struct rtw89_fw_hdr_section {
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+ __le32 w3;
+} __packed;
+
+#define FWSECTION_HDR_W0_DL_ADDR GENMASK(31, 0)
+#define FWSECTION_HDR_W1_METADATA GENMASK(31, 24)
+#define FWSECTION_HDR_W1_SECTIONTYPE GENMASK(27, 24)
+#define FWSECTION_HDR_W1_SEC_SIZE GENMASK(23, 0)
+#define FWSECTION_HDR_W1_CHECKSUM BIT(28)
+#define FWSECTION_HDR_W1_REDL BIT(29)
+#define FWSECTION_HDR_W2_MSSC GENMASK(31, 0)
+
+struct rtw89_fw_hdr {
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+ __le32 w3;
+ __le32 w4;
+ __le32 w5;
+ __le32 w6;
+ __le32 w7;
+ struct rtw89_fw_hdr_section sections[];
+ /* struct rtw89_fw_dynhdr_hdr (optional) */
+} __packed;
+
+#define FW_HDR_W1_MAJOR_VERSION GENMASK(7, 0)
+#define FW_HDR_W1_MINOR_VERSION GENMASK(15, 8)
+#define FW_HDR_W1_SUBVERSION GENMASK(23, 16)
+#define FW_HDR_W1_SUBINDEX GENMASK(31, 24)
+#define FW_HDR_W3_LEN GENMASK(23, 16)
+#define FW_HDR_W4_MONTH GENMASK(7, 0)
+#define FW_HDR_W4_DATE GENMASK(15, 8)
+#define FW_HDR_W4_HOUR GENMASK(23, 16)
+#define FW_HDR_W4_MIN GENMASK(31, 24)
+#define FW_HDR_W5_YEAR GENMASK(31, 0)
+#define FW_HDR_W6_SEC_NUM GENMASK(15, 8)
+#define FW_HDR_W7_DYN_HDR BIT(16)
+#define FW_HDR_W7_CMD_VERSERION GENMASK(31, 24)
static inline void SET_FW_HDR_PART_SIZE(void *fwhdr, u32 val)
{
@@ -3215,16 +3235,17 @@ static inline struct rtw89_fw_c2h_attr *RTW89_SKB_C2H_CB(struct sk_buff *skb)
#define RTW89_GET_C2H_LOG_SRT_PRT(c2h) (char *)((__le32 *)(c2h) + 2)
#define RTW89_GET_C2H_LOG_LEN(len) ((len) - RTW89_C2H_HEADER_LEN)
-#define RTW89_GET_MAC_C2H_DONE_ACK_CAT(c2h) \
- le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(1, 0))
-#define RTW89_GET_MAC_C2H_DONE_ACK_CLASS(c2h) \
- le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(7, 2))
-#define RTW89_GET_MAC_C2H_DONE_ACK_FUNC(c2h) \
- le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(15, 8))
-#define RTW89_GET_MAC_C2H_DONE_ACK_H2C_RETURN(c2h) \
- le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(23, 16))
-#define RTW89_GET_MAC_C2H_DONE_ACK_H2C_SEQ(c2h) \
- le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(31, 24))
+struct rtw89_c2h_done_ack {
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+} __packed;
+
+#define RTW89_C2H_DONE_ACK_W2_CAT GENMASK(1, 0)
+#define RTW89_C2H_DONE_ACK_W2_CLASS GENMASK(7, 2)
+#define RTW89_C2H_DONE_ACK_W2_FUNC GENMASK(15, 8)
+#define RTW89_C2H_DONE_ACK_W2_H2C_RETURN GENMASK(23, 16)
+#define RTW89_C2H_DONE_ACK_W2_H2C_SEQ GENMASK(31, 24)
#define RTW89_GET_MAC_C2H_REV_ACK_CAT(c2h) \
le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(1, 0))
@@ -3339,6 +3360,16 @@ static_assert(sizeof(struct rtw89_mac_mcc_tsf_rpt) <= RTW89_COMPLETION_BUF_SIZE)
#define RTW89_GET_MAC_C2H_MCC_STATUS_RPT_TSF_HIGH(c2h) \
le32_get_bits(*((const __le32 *)(c2h) + 4), GENMASK(31, 0))
+struct rtw89_c2h_pkt_ofld_rsp {
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+} __packed;
+
+#define RTW89_C2H_PKT_OFLD_RSP_W2_PTK_ID GENMASK(7, 0)
+#define RTW89_C2H_PKT_OFLD_RSP_W2_PTK_OP GENMASK(10, 8)
+#define RTW89_C2H_PKT_OFLD_RSP_W2_PTK_LEN GENMASK(31, 16)
+
struct rtw89_h2c_bcnfltr {
__le32 w0;
} __packed;
@@ -3369,9 +3400,6 @@ struct rtw89_h2c_ofld {
#define RTW89_H2C_OFLD_W0_TX_TP GENMASK(17, 8)
#define RTW89_H2C_OFLD_W0_RX_TP GENMASK(27, 18)
-#define RTW89_FW_HDR_SIZE 32
-#define RTW89_FW_SECTION_HDR_SIZE 16
-
#define RTW89_MFW_SIG 0xFF
struct rtw89_mfw_info {
@@ -3405,7 +3433,7 @@ struct fwcmd_hdr {
union rtw89_compat_fw_hdr {
struct rtw89_mfw_hdr mfw_hdr;
- u8 fw_hdr[RTW89_FW_HDR_SIZE];
+ struct rtw89_fw_hdr fw_hdr;
};
static inline u32 rtw89_compat_fw_hdr_ver_code(const void *fw_buf)
@@ -3497,17 +3525,28 @@ struct rtw89_fw_h2c_rf_reg_info {
/* CLASS 9 - FW offload */
#define H2C_CL_MAC_FW_OFLD 0x9
-#define H2C_FUNC_PACKET_OFLD 0x1
-#define H2C_FUNC_MAC_MACID_PAUSE 0x8
-#define H2C_FUNC_USR_EDCA 0xF
-#define H2C_FUNC_TSF32_TOGL 0x10
-#define H2C_FUNC_OFLD_CFG 0x14
-#define H2C_FUNC_ADD_SCANOFLD_CH 0x16
-#define H2C_FUNC_SCANOFLD 0x17
-#define H2C_FUNC_PKT_DROP 0x1b
-#define H2C_FUNC_CFG_BCNFLTR 0x1e
-#define H2C_FUNC_OFLD_RSSI 0x1f
-#define H2C_FUNC_OFLD_TP 0x20
+enum rtw89_fw_ofld_h2c_func {
+ H2C_FUNC_PACKET_OFLD = 0x1,
+ H2C_FUNC_MAC_MACID_PAUSE = 0x8,
+ H2C_FUNC_USR_EDCA = 0xF,
+ H2C_FUNC_TSF32_TOGL = 0x10,
+ H2C_FUNC_OFLD_CFG = 0x14,
+ H2C_FUNC_ADD_SCANOFLD_CH = 0x16,
+ H2C_FUNC_SCANOFLD = 0x17,
+ H2C_FUNC_PKT_DROP = 0x1b,
+ H2C_FUNC_CFG_BCNFLTR = 0x1e,
+ H2C_FUNC_OFLD_RSSI = 0x1f,
+ H2C_FUNC_OFLD_TP = 0x20,
+
+ NUM_OF_RTW89_FW_OFLD_H2C_FUNC,
+};
+
+#define RTW89_FW_OFLD_WAIT_COND(tag, func) \
+ ((tag) * NUM_OF_RTW89_FW_OFLD_H2C_FUNC + (func))
+
+#define RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(pkt_id, pkt_op) \
+ RTW89_FW_OFLD_WAIT_COND(RTW89_PKT_OFLD_WAIT_TAG(pkt_id, pkt_op), \
+ H2C_FUNC_PACKET_OFLD)
/* CLASS 10 - Security CAM */
#define H2C_CL_MAC_SEC_CAM 0xa
@@ -3648,7 +3687,7 @@ void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev,
void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw);
int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
bool valid, struct ieee80211_ampdu_params *params);
-void rtw89_fw_h2c_init_ba_cam_v1(struct rtw89_dev *rtwdev);
+void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev);
int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev,
struct rtw89_lps_parm *lps_param);
@@ -3711,8 +3750,8 @@ static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
- if (chip->bacam_v1)
- rtw89_fw_h2c_init_ba_cam_v1(rtwdev);
+ if (chip->bacam_ver == RTW89_BACAM_V0_EXT)
+ rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(rtwdev);
}
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 512de491a064..c93e6250cb8b 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -644,6 +644,39 @@ static void rtw89_mac_dump_err_status(struct rtw89_dev *rtwdev,
rtw89_info(rtwdev, "<---\n");
}
+static bool rtw89_mac_suppress_log(struct rtw89_dev *rtwdev, u32 err)
+{
+ struct rtw89_ser *ser = &rtwdev->ser;
+ u32 dmac_err, imr, isr;
+ int ret;
+
+ if (rtwdev->chip->chip_id == RTL8852C) {
+ ret = rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL);
+ if (ret)
+ return true;
+
+ if (err == MAC_AX_ERR_L1_ERR_DMAC) {
+ dmac_err = rtw89_read32(rtwdev, R_AX_DMAC_ERR_ISR);
+ imr = rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_IMR);
+ isr = rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_ISR);
+
+ if ((dmac_err & B_AX_TXPKTCTRL_ERR_FLAG) &&
+ ((isr & imr) & B_AX_B0_ISR_ERR_CMDPSR_FRZTO)) {
+ set_bit(RTW89_SER_SUPPRESS_LOG, ser->flags);
+ return true;
+ }
+ } else if (err == MAC_AX_ERR_L1_RESET_DISABLE_DMAC_DONE) {
+ if (test_bit(RTW89_SER_SUPPRESS_LOG, ser->flags))
+ return true;
+ } else if (err == MAC_AX_ERR_L1_RESET_RECOVERY_DONE) {
+ if (test_and_clear_bit(RTW89_SER_SUPPRESS_LOG, ser->flags))
+ return true;
+ }
+ }
+
+ return false;
+}
+
u32 rtw89_mac_get_err_status(struct rtw89_dev *rtwdev)
{
u32 err, err_scnr;
@@ -667,6 +700,9 @@ u32 rtw89_mac_get_err_status(struct rtw89_dev *rtwdev)
else if (err_scnr == RTW89_RXI300_ERROR)
err = MAC_AX_ERR_RXI300;
+ if (rtw89_mac_suppress_log(rtwdev, err))
+ return err;
+
rtw89_fw_st_dbg_dump(rtwdev);
rtw89_mac_dump_err_status(rtwdev, err);
@@ -676,6 +712,7 @@ EXPORT_SYMBOL(rtw89_mac_get_err_status);
int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err)
{
+ struct rtw89_ser *ser = &rtwdev->ser;
u32 halt;
int ret = 0;
@@ -692,6 +729,11 @@ int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err)
}
rtw89_write32(rtwdev, R_AX_HALT_H2C, err);
+
+ if (ser->prehandle_l1 &&
+ (err == MAC_AX_ERR_L1_DISABLE_EN || err == MAC_AX_ERR_L1_RCVY_EN))
+ return 0;
+
rtw89_write32(rtwdev, R_AX_HALT_H2C_CTRL, B_AX_HALT_H2C_TRIGGER);
return 0;
@@ -716,11 +758,8 @@ static int hfc_reset_param(struct rtw89_dev *rtwdev)
if (param_ini.pub_cfg)
param->pub_cfg = *param_ini.pub_cfg;
- if (param_ini.prec_cfg) {
+ if (param_ini.prec_cfg)
param->prec_cfg = *param_ini.prec_cfg;
- rtwdev->hal.sw_amsdu_max_size =
- param->prec_cfg.wp_ch07_prec * HFC_PAGE_UNIT;
- }
if (param_ini.ch_cfg)
param->ch_cfg = param_ini.ch_cfg;
@@ -1479,6 +1518,8 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
.ple_qt_52a_wow = {264, 0, 32, 20, 64, 13, 1005, 0, 64, 128, 120,},
/* 8852B PCIE WOW */
.ple_qt_52b_wow = {147, 0, 16, 20, 157, 13, 133, 0, 172, 14, 24, 0,},
+ /* 8851B PCIE WOW */
+ .ple_qt_51b_wow = {147, 0, 16, 20, 157, 13, 133, 0, 172, 14, 24, 0,},
};
EXPORT_SYMBOL(rtw89_mac_size);
@@ -1497,7 +1538,6 @@ static const struct rtw89_dle_mem *get_dle_mem_cfg(struct rtw89_dev *rtwdev,
return NULL;
}
- mac->dle_info.wde_pg_size = cfg->wde_size->pge_size;
mac->dle_info.ple_pg_size = cfg->ple_size->pge_size;
mac->dle_info.qta_mode = mode;
mac->dle_info.c0_rx_qta = cfg->ple_min_qt->cma0_dma;
@@ -2484,7 +2524,7 @@ static int cmac_dma_init(struct rtw89_dev *rtwdev, u8 mac_idx)
u32 reg;
int ret;
- if (chip_id != RTL8852A && chip_id != RTL8852B)
+ if (chip_id != RTL8852B)
return 0;
ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
@@ -2602,9 +2642,11 @@ static int rtw89_mac_read_phycap(struct rtw89_dev *rtwdev,
int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev)
{
+ struct rtw89_efuse *efuse = &rtwdev->efuse;
struct rtw89_hal *hal = &rtwdev->hal;
const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_mac_c2h_info c2h_info = {0};
+ const struct rtw89_c2hreg_phycap *phycap;
u8 tx_nss;
u8 rx_nss;
u8 tx_ant;
@@ -2615,10 +2657,12 @@ int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev)
if (ret)
return ret;
- tx_nss = RTW89_GET_C2H_PHYCAP_TX_NSS(c2h_info.c2hreg);
- rx_nss = RTW89_GET_C2H_PHYCAP_RX_NSS(c2h_info.c2hreg);
- tx_ant = RTW89_GET_C2H_PHYCAP_ANT_TX_NUM(c2h_info.c2hreg);
- rx_ant = RTW89_GET_C2H_PHYCAP_ANT_RX_NUM(c2h_info.c2hreg);
+ phycap = &c2h_info.u.phycap;
+
+ tx_nss = u32_get_bits(phycap->w1, RTW89_C2HREG_PHYCAP_W1_TX_NSS);
+ rx_nss = u32_get_bits(phycap->w0, RTW89_C2HREG_PHYCAP_W0_RX_NSS);
+ tx_ant = u32_get_bits(phycap->w3, RTW89_C2HREG_PHYCAP_W3_ANT_TX_NUM);
+ rx_ant = u32_get_bits(phycap->w3, RTW89_C2HREG_PHYCAP_W3_ANT_RX_NUM);
hal->tx_nss = tx_nss ? min_t(u8, tx_nss, chip->tx_nss) : chip->tx_nss;
hal->rx_nss = rx_nss ? min_t(u8, rx_nss, chip->rx_nss) : chip->rx_nss;
@@ -2633,6 +2677,13 @@ int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev)
hal->tx_path_diversity = true;
}
+ if (chip->rf_path_num == 1) {
+ hal->antenna_tx = RF_A;
+ hal->antenna_rx = RF_A;
+ if ((efuse->rfe_type % 3) == 2)
+ hal->ant_diversity = true;
+ }
+
rtw89_debug(rtwdev, RTW89_DBG_FW,
"phycap hal/phy/chip: tx_nss=0x%x/0x%x/0x%x rx_nss=0x%x/0x%x/0x%x\n",
hal->tx_nss, tx_nss, chip->tx_nss,
@@ -2641,6 +2692,7 @@ int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev)
"ant num/bitmap: tx=%d/0x%x rx=%d/0x%x\n",
tx_ant, hal->antenna_tx, rx_ant, hal->antenna_rx);
rtw89_debug(rtwdev, RTW89_DBG_FW, "TX path diversity=%d\n", hal->tx_path_diversity);
+ rtw89_debug(rtwdev, RTW89_DBG_FW, "Antenna diversity=%d\n", hal->ant_diversity);
return 0;
}
@@ -2651,14 +2703,14 @@ static int rtw89_hw_sch_tx_en_h2c(struct rtw89_dev *rtwdev, u8 band,
u32 ret;
struct rtw89_mac_c2h_info c2h_info = {0};
struct rtw89_mac_h2c_info h2c_info = {0};
- struct rtw89_h2creg_sch_tx_en *h2creg =
- (struct rtw89_h2creg_sch_tx_en *)h2c_info.h2creg;
+ struct rtw89_h2creg_sch_tx_en *sch_tx_en = &h2c_info.u.sch_tx_en;
h2c_info.id = RTW89_FWCMD_H2CREG_FUNC_SCH_TX_EN;
- h2c_info.content_len = sizeof(*h2creg) - RTW89_H2CREG_HDR_LEN;
- h2creg->tx_en = tx_en_u16;
- h2creg->mask = mask_u16;
- h2creg->band = band;
+ h2c_info.content_len = sizeof(*sch_tx_en) - RTW89_H2CREG_HDR_LEN;
+
+ u32p_replace_bits(&sch_tx_en->w0, tx_en_u16, RTW89_H2CREG_SCH_TX_EN_W0_EN);
+ u32p_replace_bits(&sch_tx_en->w1, mask_u16, RTW89_H2CREG_SCH_TX_EN_W1_MASK);
+ u32p_replace_bits(&sch_tx_en->w1, band, RTW89_H2CREG_SCH_TX_EN_W1_BAND);
ret = rtw89_fw_msg_reg(rtwdev, &h2c_info, &c2h_info);
if (ret)
@@ -4331,6 +4383,8 @@ rtw89_mac_c2h_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
static void
rtw89_mac_c2h_rec_ack(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
{
+ /* N.B. This will run in interrupt context. */
+
rtw89_debug(rtwdev, RTW89_DBG_FW,
"C2H rev ack recv, cat: %d, class: %d, func: %d, seq : %d\n",
RTW89_GET_MAC_C2H_REV_ACK_CAT(c2h->data),
@@ -4340,15 +4394,44 @@ rtw89_mac_c2h_rec_ack(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
}
static void
-rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
-{
+rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 len)
+{
+ /* N.B. This will run in interrupt context. */
+ struct rtw89_wait_info *fw_ofld_wait = &rtwdev->mac.fw_ofld_wait;
+ const struct rtw89_c2h_done_ack *c2h =
+ (const struct rtw89_c2h_done_ack *)skb_c2h->data;
+ u8 h2c_cat = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_CAT);
+ u8 h2c_class = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_CLASS);
+ u8 h2c_func = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_FUNC);
+ u8 h2c_return = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_H2C_RETURN);
+ u8 h2c_seq = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_H2C_SEQ);
+ struct rtw89_completion_data data = {};
+ unsigned int cond;
+
rtw89_debug(rtwdev, RTW89_DBG_FW,
"C2H done ack recv, cat: %d, class: %d, func: %d, ret: %d, seq : %d\n",
- RTW89_GET_MAC_C2H_DONE_ACK_CAT(c2h->data),
- RTW89_GET_MAC_C2H_DONE_ACK_CLASS(c2h->data),
- RTW89_GET_MAC_C2H_DONE_ACK_FUNC(c2h->data),
- RTW89_GET_MAC_C2H_DONE_ACK_H2C_RETURN(c2h->data),
- RTW89_GET_MAC_C2H_DONE_ACK_H2C_SEQ(c2h->data));
+ h2c_cat, h2c_class, h2c_func, h2c_return, h2c_seq);
+
+ if (h2c_cat != H2C_CAT_MAC)
+ return;
+
+ switch (h2c_class) {
+ default:
+ return;
+ case H2C_CL_MAC_FW_OFLD:
+ switch (h2c_func) {
+ default:
+ return;
+ case H2C_FUNC_ADD_SCANOFLD_CH:
+ case H2C_FUNC_SCANOFLD:
+ cond = RTW89_FW_OFLD_WAIT_COND(0, h2c_func);
+ break;
+ }
+
+ data.err = !!h2c_return;
+ rtw89_complete_cond(fw_ofld_wait, cond, &data);
+ return;
+ }
}
static void
@@ -4364,9 +4447,25 @@ rtw89_mac_c2h_bcn_cnt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
}
static void
-rtw89_mac_c2h_pkt_ofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
+rtw89_mac_c2h_pkt_ofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h,
u32 len)
{
+ struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
+ const struct rtw89_c2h_pkt_ofld_rsp *c2h =
+ (const struct rtw89_c2h_pkt_ofld_rsp *)skb_c2h->data;
+ u16 pkt_len = le32_get_bits(c2h->w2, RTW89_C2H_PKT_OFLD_RSP_W2_PTK_LEN);
+ u8 pkt_id = le32_get_bits(c2h->w2, RTW89_C2H_PKT_OFLD_RSP_W2_PTK_ID);
+ u8 pkt_op = le32_get_bits(c2h->w2, RTW89_C2H_PKT_OFLD_RSP_W2_PTK_OP);
+ struct rtw89_completion_data data = {};
+ unsigned int cond;
+
+ rtw89_debug(rtwdev, RTW89_DBG_FW, "pkt ofld rsp: id %d op %d len %d\n",
+ pkt_id, pkt_op, pkt_len);
+
+ data.err = !pkt_len;
+ cond = RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(pkt_id, pkt_op);
+
+ rtw89_complete_cond(wait, cond, &data);
}
static void
@@ -4574,6 +4673,21 @@ bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func)
switch (class) {
default:
return false;
+ case RTW89_MAC_C2H_CLASS_INFO:
+ switch (func) {
+ default:
+ return false;
+ case RTW89_MAC_C2H_FUNC_REC_ACK:
+ case RTW89_MAC_C2H_FUNC_DONE_ACK:
+ return true;
+ }
+ case RTW89_MAC_C2H_CLASS_OFLD:
+ switch (func) {
+ default:
+ return false;
+ case RTW89_MAC_C2H_FUNC_PKT_OFLD_RSP:
+ return true;
+ }
case RTW89_MAC_C2H_CLASS_MCC:
return true;
}
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index 6ba633ccdd03..0e1570451c2c 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -642,6 +642,7 @@ enum mac_ax_err_info {
MAC_AX_ERR_L0_PROMOTE_TO_L1 = 0x0010,
/* L1 */
+ MAC_AX_ERR_L1_PREERR_DMAC = 0x999,
MAC_AX_ERR_L1_ERR_DMAC = 0x1000,
MAC_AX_ERR_L1_RESET_DISABLE_DMAC_DONE = 0x1001,
MAC_AX_ERR_L1_RESET_RECOVERY_DONE = 0x1002,
@@ -780,6 +781,7 @@ enum mac_ax_err_info {
MAC_AX_ERR_L1_RCVY_EN = 0x0002,
MAC_AX_ERR_L1_RCVY_STOP_REQ = 0x0003,
MAC_AX_ERR_L1_RCVY_START_REQ = 0x0004,
+ MAC_AX_ERR_L1_RESET_START_DMAC = 0x000A,
MAC_AX_ERR_L0_CFG_NOTIFY = 0x0010,
MAC_AX_ERR_L0_CFG_DIS_NOTIFY = 0x0011,
MAC_AX_ERR_L0_CFG_HANDSHAKE = 0x0012,
@@ -819,6 +821,7 @@ struct rtw89_mac_size_set {
const struct rtw89_ple_quota ple_qt58;
const struct rtw89_ple_quota ple_qt_52a_wow;
const struct rtw89_ple_quota ple_qt_52b_wow;
+ const struct rtw89_ple_quota ple_qt_51b_wow;
};
extern const struct rtw89_mac_size_set rtw89_mac_size;
@@ -1115,6 +1118,8 @@ enum rtw89_mac_xtal_si_offset {
XTAL_SI_PWR_CUT = 0x10,
#define XTAL_SI_SMALL_PWR_CUT BIT(0)
#define XTAL_SI_BIG_PWR_CUT BIT(1)
+ XTAL_SI_XTAL_DRV = 0x15,
+#define XTAL_SI_DRV_LATCH BIT(4)
XTAL_SI_XTAL_XMD_2 = 0x24,
#define XTAL_SI_LDO_LPS GENMASK(6, 4)
XTAL_SI_XTAL_XMD_4 = 0x26,
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index c42e31069035..a66503eb35b8 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -146,6 +146,7 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
rtwvif->phy_idx = RTW89_PHY_0;
rtwvif->sub_entity_idx = RTW89_SUB_ENTITY_0;
rtwvif->hit_rule = 0;
+ rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
ether_addr_copy(rtwvif->mac_addr, vif->addr);
INIT_LIST_HEAD(&rtwvif->general_pkt_list);
@@ -457,8 +458,16 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw,
{
struct rtw89_dev *rtwdev = hw->priv;
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ const struct rtw89_chan *chan;
mutex_lock(&rtwdev->mutex);
+
+ chan = rtw89_chan_get(rtwdev, rtwvif->sub_entity_idx);
+ if (chan->band_type == RTW89_BAND_6G) {
+ mutex_unlock(&rtwdev->mutex);
+ return -EOPNOTSUPP;
+ }
+
ether_addr_copy(rtwvif->bssid, vif->bss_conf.bssid);
rtw89_cam_bssid_changed(rtwdev, rtwvif);
rtw89_mac_port_update(rtwdev, rtwvif);
@@ -759,13 +768,18 @@ int rtw89_ops_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
struct rtw89_dev *rtwdev = hw->priv;
struct rtw89_hal *hal = &rtwdev->hal;
- if (rx_ant != hw->wiphy->available_antennas_rx && rx_ant != hal->antenna_rx)
+ if (hal->ant_diversity) {
+ if (tx_ant != rx_ant || hweight32(tx_ant) != 1)
+ return -EINVAL;
+ } else if (rx_ant != hw->wiphy->available_antennas_rx && rx_ant != hal->antenna_rx) {
return -EINVAL;
+ }
mutex_lock(&rtwdev->mutex);
hal->antenna_tx = tx_ant;
hal->antenna_rx = rx_ant;
hal->tx_path_diversity = false;
+ hal->ant_diversity_fixed = true;
mutex_unlock(&rtwdev->mutex);
return 0;
diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
index 70b4754667c9..9402f1a0caea 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.c
+++ b/drivers/net/wireless/realtek/rtw89/pci.c
@@ -265,7 +265,7 @@ static u32 rtw89_pci_rxbd_deliver_skbs(struct rtw89_dev *rtwdev,
goto err_sync_device;
}
- rtw89_core_query_rxdesc(rtwdev, desc_info, skb->data, rxinfo_size);
+ rtw89_chip_query_rxdesc(rtwdev, desc_info, skb->data, rxinfo_size);
new = rtw89_alloc_skb_for_rx(rtwdev, desc_info->pkt_size);
if (!new)
@@ -274,9 +274,7 @@ static u32 rtw89_pci_rxbd_deliver_skbs(struct rtw89_dev *rtwdev,
rx_ring->diliver_skb = new;
/* first segment has RX desc */
- offset = desc_info->offset;
- offset += desc_info->long_rxdesc ? sizeof(struct rtw89_rxdesc_long) :
- sizeof(struct rtw89_rxdesc_short);
+ offset = desc_info->offset + desc_info->rxd_len;
} else {
offset = sizeof(struct rtw89_pci_rxbd_info);
if (!new) {
@@ -546,12 +544,10 @@ static u32 rtw89_pci_release_tx_skbs(struct rtw89_dev *rtwdev,
return cnt;
}
- rtw89_core_query_rxdesc(rtwdev, &desc_info, skb->data, rxinfo_size);
+ rtw89_chip_query_rxdesc(rtwdev, &desc_info, skb->data, rxinfo_size);
/* first segment has RX desc */
- offset = desc_info.offset;
- offset += desc_info.long_rxdesc ? sizeof(struct rtw89_rxdesc_long) :
- sizeof(struct rtw89_rxdesc_short);
+ offset = desc_info.offset + desc_info.rxd_len;
for (; offset + rpp_size <= rx_info->len; offset += rpp_size) {
rpp = (struct rtw89_pci_rpp_fmt *)(skb->data + offset);
rtw89_pci_release_rpp(rtwdev, rpp);
@@ -1003,10 +999,10 @@ static u32 __rtw89_pci_check_and_reclaim_tx_resource(struct rtw89_dev *rtwdev,
min_cnt = min(bd_cnt, wd_cnt);
if (min_cnt == 0) {
/* This message can be frequently shown in low power mode or
- * high traffic with 8852B, and we have recognized it as normal
+ * high traffic with small FIFO chips, and we have recognized it as normal
* behavior, so print with mask RTW89_DBG_TXRX in these situations.
*/
- if (rtwpci->low_power || chip->chip_id == RTL8852B)
+ if (rtwpci->low_power || chip->small_fifo_size)
debug_mask = RTW89_DBG_TXRX;
else
debug_mask = RTW89_DBG_UNEXP;
@@ -3216,11 +3212,16 @@ static void rtw89_pci_clear_resource(struct rtw89_dev *rtwdev,
void rtw89_pci_config_intr_mask(struct rtw89_dev *rtwdev)
{
struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ u32 hs0isr_ind_int_en = B_AX_HS0ISR_IND_INT_EN;
+
+ if (chip->chip_id == RTL8851B)
+ hs0isr_ind_int_en = B_AX_HS0ISR_IND_INT_EN_WKARND;
rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN | 0;
if (rtwpci->under_recovery) {
- rtwpci->intrs[0] = B_AX_HS0ISR_IND_INT_EN;
+ rtwpci->intrs[0] = hs0isr_ind_int_en;
rtwpci->intrs[1] = 0;
} else {
rtwpci->intrs[0] = B_AX_TXDMA_STUCK_INT_EN |
@@ -3230,7 +3231,7 @@ void rtw89_pci_config_intr_mask(struct rtw89_dev *rtwdev)
B_AX_RXDMA_STUCK_INT_EN |
B_AX_RDU_INT_EN |
B_AX_RPQBD_FULL_INT_EN |
- B_AX_HS0ISR_IND_INT_EN;
+ hs0isr_ind_int_en;
rtwpci->intrs[1] = B_AX_HC10ISR_IND_INT_EN;
}
diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h
index 0e4bd210b100..2f3d1ad3b0f7 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.h
+++ b/drivers/net/wireless/realtek/rtw89/pci.h
@@ -150,6 +150,7 @@
#define B_AX_HD1ISR_IND_INT_EN BIT(26)
#define B_AX_HD0ISR_IND_INT_EN BIT(25)
#define B_AX_HS0ISR_IND_INT_EN BIT(24)
+#define B_AX_HS0ISR_IND_INT_EN_WKARND BIT(23)
#define B_AX_RETRAIN_INT_EN BIT(21)
#define B_AX_RPQBD_FULL_INT_EN BIT(20)
#define B_AX_RDU_INT_EN BIT(19)
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index c7e906123416..fb15c852fdd4 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -10,6 +10,7 @@
#include "ps.h"
#include "reg.h"
#include "sar.h"
+#include "txrx.h"
#include "util.h"
static u16 get_max_amsdu_len(struct rtw89_dev *rtwdev,
@@ -1400,7 +1401,8 @@ static void rtw89_phy_init_rf_nctl(struct rtw89_dev *rtwdev)
rtw89_phy_write32_set(rtwdev, R_IOQ_IQK_DPK, 0x3);
rtw89_phy_write32_set(rtwdev, R_GNT_BT_WGT_EN, 0x1);
rtw89_phy_write32_set(rtwdev, R_P0_PATH_RST, 0x8000000);
- rtw89_phy_write32_set(rtwdev, R_P1_PATH_RST, 0x8000000);
+ if (chip->chip_id != RTL8851B)
+ rtw89_phy_write32_set(rtwdev, R_P1_PATH_RST, 0x8000000);
if (chip->chip_id == RTL8852B)
rtw89_phy_write32_set(rtwdev, R_IOQ_IQK_DPK, 0x2);
@@ -1414,6 +1416,9 @@ static void rtw89_phy_init_rf_nctl(struct rtw89_dev *rtwdev)
nctl_table = chip->nctl_table;
rtw89_phy_init_reg(rtwdev, nctl_table, rtw89_phy_config_bb_reg, NULL);
+
+ if (chip->nctl_post_table)
+ rtw89_rfk_parser(rtwdev, chip->nctl_post_table);
}
static u32 rtw89_phy0_phy1_offset(struct rtw89_dev *rtwdev, u32 addr)
@@ -1489,19 +1494,19 @@ void rtw89_phy_write_reg3_tbl(struct rtw89_dev *rtwdev,
}
EXPORT_SYMBOL(rtw89_phy_write_reg3_tbl);
-static const u8 rtw89_rs_idx_max[] = {
- [RTW89_RS_CCK] = RTW89_RATE_CCK_MAX,
- [RTW89_RS_OFDM] = RTW89_RATE_OFDM_MAX,
- [RTW89_RS_MCS] = RTW89_RATE_MCS_MAX,
- [RTW89_RS_HEDCM] = RTW89_RATE_HEDCM_MAX,
- [RTW89_RS_OFFSET] = RTW89_RATE_OFFSET_MAX,
+static const u8 rtw89_rs_idx_num[] = {
+ [RTW89_RS_CCK] = RTW89_RATE_CCK_NUM,
+ [RTW89_RS_OFDM] = RTW89_RATE_OFDM_NUM,
+ [RTW89_RS_MCS] = RTW89_RATE_MCS_NUM,
+ [RTW89_RS_HEDCM] = RTW89_RATE_HEDCM_NUM,
+ [RTW89_RS_OFFSET] = RTW89_RATE_OFFSET_NUM,
};
-static const u8 rtw89_rs_nss_max[] = {
+static const u8 rtw89_rs_nss_num[] = {
[RTW89_RS_CCK] = 1,
[RTW89_RS_OFDM] = 1,
- [RTW89_RS_MCS] = RTW89_NSS_MAX,
- [RTW89_RS_HEDCM] = RTW89_NSS_HEDCM_MAX,
+ [RTW89_RS_MCS] = RTW89_NSS_NUM,
+ [RTW89_RS_HEDCM] = RTW89_NSS_HEDCM_NUM,
[RTW89_RS_OFFSET] = 1,
};
@@ -1514,9 +1519,9 @@ static const u8 _byr_of_rs[] = {
};
#define _byr_seek(rs, raw) ((s8 *)(raw) + _byr_of_rs[rs])
-#define _byr_idx(rs, nss, idx) ((nss) * rtw89_rs_idx_max[rs] + (idx))
+#define _byr_idx(rs, nss, idx) ((nss) * rtw89_rs_idx_num[rs] + (idx))
#define _byr_chk(rs, nss, idx) \
- ((nss) < rtw89_rs_nss_max[rs] && (idx) < rtw89_rs_idx_max[rs])
+ ((nss) < rtw89_rs_nss_num[rs] && (idx) < rtw89_rs_idx_num[rs])
void rtw89_phy_load_txpwr_byrate(struct rtw89_dev *rtwdev,
const struct rtw89_txpwr_table *tbl)
@@ -1621,8 +1626,10 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz;
const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz;
const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz;
+ struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
u8 regd = rtw89_regd_get(rtwdev, band);
+ u8 reg6 = regulatory->reg_6ghz_power;
s8 lmt = 0, sar;
switch (band) {
@@ -1641,11 +1648,13 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
lmt = (*rule_5ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx];
break;
case RTW89_BAND_6G:
- lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
+ lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][regd][reg6][ch_idx];
if (lmt)
break;
- lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx];
+ lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][RTW89_WW]
+ [RTW89_REG_6GHZ_POWER_DFLT]
+ [ch_idx];
break;
default:
rtw89_warn(rtwdev, "unknown band type: %d\n", band);
@@ -1872,8 +1881,10 @@ static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz;
const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz;
const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz;
+ struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
u8 regd = rtw89_regd_get(rtwdev, band);
+ u8 reg6 = regulatory->reg_6ghz_power;
s8 lmt_ru = 0, sar;
switch (band) {
@@ -1892,11 +1903,13 @@ static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
lmt_ru = (*rule_5ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx];
break;
case RTW89_BAND_6G:
- lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][regd][ch_idx];
+ lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][regd][reg6][ch_idx];
if (lmt_ru)
break;
- lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx];
+ lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][RTW89_WW]
+ [RTW89_REG_6GHZ_POWER_DFLT]
+ [ch_idx];
break;
default:
rtw89_warn(rtwdev, "unknown band type: %d\n", band);
@@ -2071,19 +2084,19 @@ void rtw89_phy_set_txpwr_byrate(struct rtw89_dev *rtwdev,
rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
"[TXPWR] set txpwr byrate with ch=%d\n", ch);
- BUILD_BUG_ON(rtw89_rs_idx_max[RTW89_RS_CCK] % 4);
- BUILD_BUG_ON(rtw89_rs_idx_max[RTW89_RS_OFDM] % 4);
- BUILD_BUG_ON(rtw89_rs_idx_max[RTW89_RS_MCS] % 4);
- BUILD_BUG_ON(rtw89_rs_idx_max[RTW89_RS_HEDCM] % 4);
+ BUILD_BUG_ON(rtw89_rs_idx_num[RTW89_RS_CCK] % 4);
+ BUILD_BUG_ON(rtw89_rs_idx_num[RTW89_RS_OFDM] % 4);
+ BUILD_BUG_ON(rtw89_rs_idx_num[RTW89_RS_MCS] % 4);
+ BUILD_BUG_ON(rtw89_rs_idx_num[RTW89_RS_HEDCM] % 4);
addr = R_AX_PWR_BY_RATE;
for (cur.nss = 0; cur.nss < max_nss_num; cur.nss++) {
for (i = 0; i < ARRAY_SIZE(rs); i++) {
- if (cur.nss >= rtw89_rs_nss_max[rs[i]])
+ if (cur.nss >= rtw89_rs_nss_num[rs[i]])
continue;
cur.rs = rs[i];
- for (cur.idx = 0; cur.idx < rtw89_rs_idx_max[rs[i]];
+ for (cur.idx = 0; cur.idx < rtw89_rs_idx_num[rs[i]];
cur.idx++) {
v[cur.idx % 4] =
rtw89_phy_read_txpwr_byrate(rtwdev,
@@ -2116,15 +2129,15 @@ void rtw89_phy_set_txpwr_offset(struct rtw89_dev *rtwdev,
.rs = RTW89_RS_OFFSET,
};
u8 band = chan->band_type;
- s8 v[RTW89_RATE_OFFSET_MAX] = {};
+ s8 v[RTW89_RATE_OFFSET_NUM] = {};
u32 val;
rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set txpwr offset\n");
- for (desc.idx = 0; desc.idx < RTW89_RATE_OFFSET_MAX; desc.idx++)
+ for (desc.idx = 0; desc.idx < RTW89_RATE_OFFSET_NUM; desc.idx++)
v[desc.idx] = rtw89_phy_read_txpwr_byrate(rtwdev, band, &desc);
- BUILD_BUG_ON(RTW89_RATE_OFFSET_MAX != 5);
+ BUILD_BUG_ON(RTW89_RATE_OFFSET_NUM != 5);
val = FIELD_PREP(GENMASK(3, 0), v[0]) |
FIELD_PREP(GENMASK(7, 4), v[1]) |
FIELD_PREP(GENMASK(11, 8), v[2]) |
@@ -2338,27 +2351,29 @@ void rtw89_phy_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
static u8 rtw89_phy_cfo_get_xcap_reg(struct rtw89_dev *rtwdev, bool sc_xo)
{
+ const struct rtw89_xtal_info *xtal = rtwdev->chip->xtal_info;
u32 reg_mask;
if (sc_xo)
- reg_mask = B_AX_XTAL_SC_XO_MASK;
+ reg_mask = xtal->sc_xo_mask;
else
- reg_mask = B_AX_XTAL_SC_XI_MASK;
+ reg_mask = xtal->sc_xi_mask;
- return (u8)rtw89_read32_mask(rtwdev, R_AX_XTAL_ON_CTRL0, reg_mask);
+ return (u8)rtw89_read32_mask(rtwdev, xtal->xcap_reg, reg_mask);
}
static void rtw89_phy_cfo_set_xcap_reg(struct rtw89_dev *rtwdev, bool sc_xo,
u8 val)
{
+ const struct rtw89_xtal_info *xtal = rtwdev->chip->xtal_info;
u32 reg_mask;
if (sc_xo)
- reg_mask = B_AX_XTAL_SC_XO_MASK;
+ reg_mask = xtal->sc_xo_mask;
else
- reg_mask = B_AX_XTAL_SC_XI_MASK;
+ reg_mask = xtal->sc_xi_mask;
- rtw89_write32_mask(rtwdev, R_AX_XTAL_ON_CTRL0, reg_mask, val);
+ rtw89_write32_mask(rtwdev, xtal->xcap_reg, reg_mask, val);
}
static void rtw89_phy_cfo_set_crystal_cap(struct rtw89_dev *rtwdev,
@@ -2371,7 +2386,7 @@ static void rtw89_phy_cfo_set_crystal_cap(struct rtw89_dev *rtwdev,
if (!force && cfo->crystal_cap == crystal_cap)
return;
crystal_cap = clamp_t(u8, crystal_cap, 0, 127);
- if (chip->chip_id == RTL8852A) {
+ if (chip->chip_id == RTL8852A || chip->chip_id == RTL8851B) {
rtw89_phy_cfo_set_xcap_reg(rtwdev, true, crystal_cap);
rtw89_phy_cfo_set_xcap_reg(rtwdev, false, crystal_cap);
sc_xo_val = rtw89_phy_cfo_get_xcap_reg(rtwdev, true);
@@ -2946,6 +2961,126 @@ static void rtw89_phy_ul_tb_info_init(struct rtw89_dev *rtwdev)
rtw89_phy_read32_mask(rtwdev, R_BANDEDGE, B_BANDEDGE_EN);
}
+static
+void rtw89_phy_antdiv_sts_instance_reset(struct rtw89_antdiv_stats *antdiv_sts)
+{
+ ewma_rssi_init(&antdiv_sts->cck_rssi_avg);
+ ewma_rssi_init(&antdiv_sts->ofdm_rssi_avg);
+ ewma_rssi_init(&antdiv_sts->non_legacy_rssi_avg);
+ antdiv_sts->pkt_cnt_cck = 0;
+ antdiv_sts->pkt_cnt_ofdm = 0;
+ antdiv_sts->pkt_cnt_non_legacy = 0;
+ antdiv_sts->evm = 0;
+}
+
+static void rtw89_phy_antdiv_sts_instance_add(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_phy_ppdu *phy_ppdu,
+ struct rtw89_antdiv_stats *stats)
+{
+ if (GET_DATA_RATE_MODE(phy_ppdu->rate) == DATA_RATE_MODE_NON_HT) {
+ if (phy_ppdu->rate < RTW89_HW_RATE_OFDM6) {
+ ewma_rssi_add(&stats->cck_rssi_avg, phy_ppdu->rssi_avg);
+ stats->pkt_cnt_cck++;
+ } else {
+ ewma_rssi_add(&stats->ofdm_rssi_avg, phy_ppdu->rssi_avg);
+ stats->pkt_cnt_ofdm++;
+ stats->evm += phy_ppdu->ofdm.evm_min;
+ }
+ } else {
+ ewma_rssi_add(&stats->non_legacy_rssi_avg, phy_ppdu->rssi_avg);
+ stats->pkt_cnt_non_legacy++;
+ stats->evm += phy_ppdu->ofdm.evm_min;
+ }
+}
+
+static u8 rtw89_phy_antdiv_sts_instance_get_rssi(struct rtw89_antdiv_stats *stats)
+{
+ if (stats->pkt_cnt_non_legacy >= stats->pkt_cnt_cck &&
+ stats->pkt_cnt_non_legacy >= stats->pkt_cnt_ofdm)
+ return ewma_rssi_read(&stats->non_legacy_rssi_avg);
+ else if (stats->pkt_cnt_ofdm >= stats->pkt_cnt_cck &&
+ stats->pkt_cnt_ofdm >= stats->pkt_cnt_non_legacy)
+ return ewma_rssi_read(&stats->ofdm_rssi_avg);
+ else
+ return ewma_rssi_read(&stats->cck_rssi_avg);
+}
+
+static u8 rtw89_phy_antdiv_sts_instance_get_evm(struct rtw89_antdiv_stats *stats)
+{
+ return phy_div(stats->evm, stats->pkt_cnt_non_legacy + stats->pkt_cnt_ofdm);
+}
+
+void rtw89_phy_antdiv_parse(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_phy_ppdu *phy_ppdu)
+{
+ struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
+ struct rtw89_hal *hal = &rtwdev->hal;
+
+ if (!hal->ant_diversity || hal->ant_diversity_fixed)
+ return;
+
+ rtw89_phy_antdiv_sts_instance_add(rtwdev, phy_ppdu, &antdiv->target_stats);
+
+ if (!antdiv->get_stats)
+ return;
+
+ if (hal->antenna_rx == RF_A)
+ rtw89_phy_antdiv_sts_instance_add(rtwdev, phy_ppdu, &antdiv->main_stats);
+ else if (hal->antenna_rx == RF_B)
+ rtw89_phy_antdiv_sts_instance_add(rtwdev, phy_ppdu, &antdiv->aux_stats);
+}
+
+static void rtw89_phy_antdiv_reg_init(struct rtw89_dev *rtwdev)
+{
+ rtw89_phy_write32_idx(rtwdev, R_P0_TRSW, B_P0_ANT_TRAIN_EN,
+ 0x0, RTW89_PHY_0);
+ rtw89_phy_write32_idx(rtwdev, R_P0_TRSW, B_P0_TX_ANT_SEL,
+ 0x0, RTW89_PHY_0);
+
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANT_SW, B_P0_TRSW_TX_EXTEND,
+ 0x0, RTW89_PHY_0);
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANT_SW, B_P0_HW_ANTSW_DIS_BY_GNT_BT,
+ 0x0, RTW89_PHY_0);
+
+ rtw89_phy_write32_idx(rtwdev, R_P0_TRSW, B_P0_BT_FORCE_ANTIDX_EN,
+ 0x0, RTW89_PHY_0);
+
+ rtw89_phy_write32_idx(rtwdev, R_RFSW_CTRL_ANT0_BASE, B_RFSW_CTRL_ANT_MAPPING,
+ 0x0100, RTW89_PHY_0);
+
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_BTG_TRX,
+ 0x1, RTW89_PHY_0);
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_HW_CTRL,
+ 0x0, RTW89_PHY_0);
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_SW_2G,
+ 0x0, RTW89_PHY_0);
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_SW_5G,
+ 0x0, RTW89_PHY_0);
+}
+
+static void rtw89_phy_antdiv_sts_reset(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
+
+ rtw89_phy_antdiv_sts_instance_reset(&antdiv->target_stats);
+ rtw89_phy_antdiv_sts_instance_reset(&antdiv->main_stats);
+ rtw89_phy_antdiv_sts_instance_reset(&antdiv->aux_stats);
+}
+
+static void rtw89_phy_antdiv_init(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
+ struct rtw89_hal *hal = &rtwdev->hal;
+
+ if (!hal->ant_diversity)
+ return;
+
+ antdiv->get_stats = false;
+ antdiv->rssi_pre = 0;
+ rtw89_phy_antdiv_sts_reset(rtwdev);
+ rtw89_phy_antdiv_reg_init(rtwdev);
+}
+
static void rtw89_phy_stat_thermal_update(struct rtw89_dev *rtwdev)
{
struct rtw89_phy_stat *phystat = &rtwdev->phystat;
@@ -3053,11 +3188,8 @@ static void rtw89_phy_ccx_top_setting_init(struct rtw89_dev *rtwdev)
env->ccx_manual_ctrl = false;
env->ccx_ongoing = false;
env->ccx_rac_lv = RTW89_RAC_RELEASE;
- env->ccx_rpt_stamp = 0;
env->ccx_period = 0;
env->ccx_unit_idx = RTW89_CCX_32_US;
- env->ccx_trigger_time = 0;
- env->ccx_edcca_opt_bw_idx = RTW89_CCX_EDCCA_BW20_0;
rtw89_phy_set_phy_regs(rtwdev, R_CCX, B_CCX_EN_MSK, 1);
rtw89_phy_set_phy_regs(rtwdev, R_CCX, B_CCX_TRIG_OPT_MSK, 1);
@@ -3265,7 +3397,6 @@ static void rtw89_phy_ccx_trigger(struct rtw89_dev *rtwdev)
rtw89_phy_set_phy_regs(rtwdev, R_IFS_COUNTER, B_IFS_COUNTER_CLR_MSK, 1);
rtw89_phy_set_phy_regs(rtwdev, R_CCX, B_MEASUREMENT_TRIG_MSK, 1);
- env->ccx_rpt_stamp++;
env->ccx_ongoing = true;
}
@@ -4114,6 +4245,144 @@ void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev)
&done);
}
+#define ANTDIV_MAIN 0
+#define ANTDIV_AUX 1
+
+static void rtw89_phy_antdiv_set_ant(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_hal *hal = &rtwdev->hal;
+ u8 default_ant, optional_ant;
+
+ if (!hal->ant_diversity || hal->antenna_tx == 0)
+ return;
+
+ if (hal->antenna_tx == RF_B) {
+ default_ant = ANTDIV_AUX;
+ optional_ant = ANTDIV_MAIN;
+ } else {
+ default_ant = ANTDIV_MAIN;
+ optional_ant = ANTDIV_AUX;
+ }
+
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_CGCS_CTRL,
+ default_ant, RTW89_PHY_0);
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_RX_ORI,
+ default_ant, RTW89_PHY_0);
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_RX_ALT,
+ optional_ant, RTW89_PHY_0);
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_TX_ORI,
+ default_ant, RTW89_PHY_0);
+}
+
+static void rtw89_phy_swap_hal_antenna(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_hal *hal = &rtwdev->hal;
+
+ hal->antenna_rx = hal->antenna_rx == RF_A ? RF_B : RF_A;
+ hal->antenna_tx = hal->antenna_rx;
+}
+
+static void rtw89_phy_antdiv_decision_state(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ bool no_change = false;
+ u8 main_rssi, aux_rssi;
+ u8 main_evm, aux_evm;
+ u32 candidate;
+
+ antdiv->get_stats = false;
+ antdiv->training_count = 0;
+
+ main_rssi = rtw89_phy_antdiv_sts_instance_get_rssi(&antdiv->main_stats);
+ main_evm = rtw89_phy_antdiv_sts_instance_get_evm(&antdiv->main_stats);
+ aux_rssi = rtw89_phy_antdiv_sts_instance_get_rssi(&antdiv->aux_stats);
+ aux_evm = rtw89_phy_antdiv_sts_instance_get_evm(&antdiv->aux_stats);
+
+ if (main_evm > aux_evm + ANTDIV_EVM_DIFF_TH)
+ candidate = RF_A;
+ else if (aux_evm > main_evm + ANTDIV_EVM_DIFF_TH)
+ candidate = RF_B;
+ else if (main_rssi > aux_rssi + RTW89_TX_DIV_RSSI_RAW_TH)
+ candidate = RF_A;
+ else if (aux_rssi > main_rssi + RTW89_TX_DIV_RSSI_RAW_TH)
+ candidate = RF_B;
+ else
+ no_change = true;
+
+ if (no_change) {
+ /* swap back from training antenna to original */
+ rtw89_phy_swap_hal_antenna(rtwdev);
+ return;
+ }
+
+ hal->antenna_tx = candidate;
+ hal->antenna_rx = candidate;
+}
+
+static void rtw89_phy_antdiv_training_state(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
+ u64 state_period;
+
+ if (antdiv->training_count % 2 == 0) {
+ if (antdiv->training_count == 0)
+ rtw89_phy_antdiv_sts_reset(rtwdev);
+
+ antdiv->get_stats = true;
+ state_period = msecs_to_jiffies(ANTDIV_TRAINNING_INTVL);
+ } else {
+ antdiv->get_stats = false;
+ state_period = msecs_to_jiffies(ANTDIV_DELAY);
+
+ rtw89_phy_swap_hal_antenna(rtwdev);
+ rtw89_phy_antdiv_set_ant(rtwdev);
+ }
+
+ antdiv->training_count++;
+ ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->antdiv_work,
+ state_period);
+}
+
+void rtw89_phy_antdiv_work(struct work_struct *work)
+{
+ struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
+ antdiv_work.work);
+ struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
+
+ mutex_lock(&rtwdev->mutex);
+
+ if (antdiv->training_count <= ANTDIV_TRAINNING_CNT) {
+ rtw89_phy_antdiv_training_state(rtwdev);
+ } else {
+ rtw89_phy_antdiv_decision_state(rtwdev);
+ rtw89_phy_antdiv_set_ant(rtwdev);
+ }
+
+ mutex_unlock(&rtwdev->mutex);
+}
+
+void rtw89_phy_antdiv_track(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ u8 rssi, rssi_pre;
+
+ if (!hal->ant_diversity || hal->ant_diversity_fixed)
+ return;
+
+ rssi = rtw89_phy_antdiv_sts_instance_get_rssi(&antdiv->target_stats);
+ rssi_pre = antdiv->rssi_pre;
+ antdiv->rssi_pre = rssi;
+ rtw89_phy_antdiv_sts_instance_reset(&antdiv->target_stats);
+
+ if (abs((int)rssi - (int)rssi_pre) < ANTDIV_RSSI_DIFF_TH)
+ return;
+
+ antdiv->training_count = 0;
+ ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->antdiv_work, 0);
+}
+
static void rtw89_phy_env_monitor_init(struct rtw89_dev *rtwdev)
{
rtw89_phy_ccx_top_setting_init(rtwdev);
@@ -4133,6 +4402,9 @@ void rtw89_phy_dm_init(struct rtw89_dev *rtwdev)
rtw89_phy_dig_init(rtwdev);
rtw89_phy_cfo_init(rtwdev);
rtw89_phy_ul_tb_info_init(rtwdev);
+ rtw89_phy_antdiv_init(rtwdev);
+ rtw89_chip_rfe_gpio(rtwdev);
+ rtw89_phy_antdiv_set_ant(rtwdev);
rtw89_phy_init_rf_nctl(rtwdev);
rtw89_chip_rfk_init(rtwdev);
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index 7535867d0f48..ab174a0ba488 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -67,6 +67,14 @@
#define UL_TB_TF_CNT_L2H_TH 100
#define UL_TB_TF_CNT_H2L_TH 70
+#define ANTDIV_TRAINNING_CNT 2
+#define ANTDIV_TRAINNING_INTVL 30
+#define ANTDIV_DELAY 110
+#define ANTDIV_TP_DIFF_TH_HIGH 100
+#define ANTDIV_TP_DIFF_TH_LOW 5
+#define ANTDIV_EVM_DIFF_TH 8
+#define ANTDIV_RSSI_DIFF_TH 3
+
#define CCX_MAX_PERIOD 2097
#define CCX_MAX_PERIOD_UNIT 32
#define MS_TO_4US_RATIO 250
@@ -549,6 +557,10 @@ void rtw89_phy_set_phy_regs(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
void rtw89_phy_dig_reset(struct rtw89_dev *rtwdev);
void rtw89_phy_dig(struct rtw89_dev *rtwdev);
void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev);
+void rtw89_phy_antdiv_parse(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_phy_ppdu *phy_ppdu);
+void rtw89_phy_antdiv_track(struct rtw89_dev *rtwdev);
+void rtw89_phy_antdiv_work(struct work_struct *work);
void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif);
void rtw89_phy_tssi_ctrl_set_bandedge_cfg(struct rtw89_dev *rtwdev,
enum rtw89_mac_idx mac_idx,
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 266e4231b5f3..55595fde7494 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -19,6 +19,8 @@
#define B_AX_FEN_BBRSTB BIT(0)
#define R_AX_SYS_PW_CTRL 0x0004
+#define B_AX_SOP_ASWRM BIT(31)
+#define B_AX_SOP_PWMM_DSWR BIT(29)
#define B_AX_XTAL_OFF_A_DIE BIT(22)
#define B_AX_DIS_WLBT_PDNSUSEN_SOPC BIT(18)
#define B_AX_RDY_SYSPWR BIT(17)
@@ -134,6 +136,8 @@
#define B_AX_PLATFORM_EN BIT(0)
#define R_AX_WLLPS_CTRL 0x0090
+#define B_AX_LPSOP_ASWRM BIT(17)
+#define B_AX_LPSOP_DSWRM BIT(9)
#define B_AX_DIS_WLBT_LPSEN_LOPC BIT(1)
#define SW_LPS_OPTION 0x0001A0B2
@@ -222,9 +226,14 @@
#define B_AX_OCP_L1_MASK GENMASK(15, 13)
#define B_AX_VOL_L1_MASK GENMASK(3, 0)
+#define R_AX_SPSLDO_ON_CTRL1 0x0204
+#define B_AX_FPWMDELAY BIT(3)
+
#define R_AX_LDO_AON_CTRL0 0x0218
#define B_AX_PD_REGU_L BIT(16)
+#define R_AX_SPSANA_ON_CTRL1 0x0224
+
#define R_AX_WLAN_XTAL_SI_CTRL 0x0270
#define B_AX_WL_XTAL_SI_CMD_POLL BIT(31)
#define B_AX_BT_XTAL_SI_ERR_FLAG BIT(30)
@@ -237,17 +246,30 @@
#define B_AX_WL_XTAL_SI_DATA_MASK GENMASK(15, 8)
#define B_AX_WL_XTAL_SI_ADDR_MASK GENMASK(7, 0)
+#define R_AX_WLAN_XTAL_SI_CONFIG 0x0274
+#define B_AX_XTAL_SI_ADDR_NOT_CHK BIT(0)
+
#define R_AX_XTAL_ON_CTRL0 0x0280
#define B_AX_XTAL_SC_LPS BIT(31)
#define B_AX_XTAL_SC_XO_MASK GENMASK(23, 17)
#define B_AX_XTAL_SC_XI_MASK GENMASK(16, 10)
#define B_AX_XTAL_SC_MASK GENMASK(6, 0)
+#define R_AX_XTAL_ON_CTRL3 0x028C
+#define B_AX_XTAL_SC_INIT_A_BLOCK_MASK GENMASK(30, 24)
+#define B_AX_XTAL_SC_LPS_A_BLOCK_MASK GENMASK(22, 16)
+#define B_AX_XTAL_SC_XO_A_BLOCK_MASK GENMASK(14, 8)
+#define B_AX_XTAL_SC_XI_A_BLOCK_MASK GENMASK(6, 0)
+
#define R_AX_GPIO0_7_FUNC_SEL 0x02D0
#define R_AX_EECS_EESK_FUNC_SEL 0x02D8
#define B_AX_PINMUX_EESK_FUNC_SEL_MASK GENMASK(7, 4)
+#define R_AX_GPIO16_23_FUNC_SEL 0x02D8
+#define B_AX_PINMUX_GPIO17_FUNC_SEL_MASK GENMASK(7, 4)
+#define B_AX_PINMUX_GPIO16_FUNC_SEL_MASK GENMASK(3, 0)
+
#define R_AX_LED1_FUNC_SEL 0x02DC
#define B_AX_PINMUX_EESK_FUNC_SEL_V1_MASK GENMASK(27, 24)
#define PINMUX_EESK_FUNC_SEL_BT_LOG 0x1
@@ -257,6 +279,10 @@
#define B_AX_EESK_PULL_LOW_EN BIT(17)
#define B_AX_EECS_PULL_LOW_EN BIT(16)
+#define R_AX_GPIO0_16_EECS_EESK_LED1_PULL_LOW_EN 0x02E4
+#define B_AX_GPIO16_PULL_LOW_EN_V1 BIT(19)
+#define B_AX_GPIO10_PULL_LOW_EN BIT(10)
+
#define R_AX_WLRF_CTRL 0x02F0
#define B_AX_AFC_AFEDIG BIT(17)
#define B_AX_WLRF1_CTRL_7 BIT(15)
@@ -3299,10 +3325,36 @@
#define B_AX_TXAGC_BT_EN BIT(1)
#define B_AX_TXAGC_BT_MASK GENMASK(11, 3)
+#define R_AX_PWR_SWING_OTHER_CTRL0 0xD230
+#define R_AX_PWR_SWING_OTHER_CTRL0_C1 0xF230
+#define B_AX_CFIR_BY_RATE_OFF_MASK GENMASK(17, 0)
+
#define R_AX_PWR_UL_CTRL0 0xD240
#define R_AX_PWR_UL_CTRL2 0xD248
#define B_AX_PWR_UL_CFO_MASK GENMASK(2, 0)
#define B_AX_PWR_UL_CTRL2_MASK 0x07700007
+
+#define R_AX_PWR_NORM_FORCE1 0xD260
+#define R_AX_PWR_NORM_FORCE1_C1 0xF260
+#define B_AX_TXAGC_BF_PWR_BOOST_FORCE_VAL_EN BIT(29)
+#define B_AX_TXAGC_BF_PWR_BOOST_FORCE_VAL_MASK GENMASK(28, 24)
+#define B_AX_FORCE_HE_ER_SU_EN_EN BIT(23)
+#define B_AX_FORCE_HE_ER_SU_EN_VALUE BIT(22)
+#define B_AX_FORCE_MACID_CCA_TH_EN_EN BIT(21)
+#define B_AX_FORCE_MACID_CCA_TH_EN_VALUE BIT(20)
+#define B_AX_FORCE_BT_GRANT_EN BIT(19)
+#define B_AX_FORCE_BT_GRANT_VALUE BIT(18)
+#define B_AX_FORCE_RX_LTE_EN BIT(17)
+#define B_AX_FORCE_RX_LTE_VALUE BIT(16)
+#define B_AX_FORCE_TXBF_EN_EN BIT(15)
+#define B_AX_FORCE_TXBF_EN_VALUE BIT(14)
+#define B_AX_FORCE_TXSC_EN BIT(13)
+#define B_AX_FORCE_TXSC_VALUE_MASK GENMASK(12, 9)
+#define B_AX_FORCE_NTX_EN BIT(6)
+#define B_AX_FORCE_NTX_VALUE BIT(5)
+#define B_AX_FORCE_PWR_MODE_EN BIT(3)
+#define B_AX_FORCE_PWR_MODE_VALUE_MASK GENMASK(2, 0)
+
#define R_AX_PWR_UL_TB_CTRL 0xD288
#define B_AX_PWR_UL_TB_CTRL_EN BIT(31)
#define R_AX_PWR_UL_TB_1T 0xD28C
@@ -3312,16 +3364,22 @@
#define B_AX_PWR_UL_TB_2T_MASK GENMASK(4, 0)
#define B_AX_PWR_UL_TB_2T_V1_MASK GENMASK(7, 0)
#define R_AX_PWR_BY_RATE_TABLE0 0xD2C0
+#define R_AX_PWR_BY_RATE_TABLE6 0xD2D8
#define R_AX_PWR_BY_RATE_TABLE10 0xD2E8
#define R_AX_PWR_BY_RATE R_AX_PWR_BY_RATE_TABLE0
+#define R_AX_PWR_BY_RATE_1SS_MAX R_AX_PWR_BY_RATE_TABLE6
#define R_AX_PWR_BY_RATE_MAX R_AX_PWR_BY_RATE_TABLE10
#define R_AX_PWR_LMT_TABLE0 0xD2EC
+#define R_AX_PWR_LMT_TABLE9 0xD310
#define R_AX_PWR_LMT_TABLE19 0xD338
#define R_AX_PWR_LMT R_AX_PWR_LMT_TABLE0
+#define R_AX_PWR_LMT_1SS_MAX R_AX_PWR_LMT_TABLE9
#define R_AX_PWR_LMT_MAX R_AX_PWR_LMT_TABLE19
#define R_AX_PWR_RU_LMT_TABLE0 0xD33C
+#define R_AX_PWR_RU_LMT_TABLE5 0xD350
#define R_AX_PWR_RU_LMT_TABLE11 0xD368
#define R_AX_PWR_RU_LMT R_AX_PWR_RU_LMT_TABLE0
+#define R_AX_PWR_RU_LMT_1SS_MAX R_AX_PWR_RU_LMT_TABLE5
#define R_AX_PWR_RU_LMT_MAX R_AX_PWR_RU_LMT_TABLE11
#define R_AX_PWR_MACID_LMT_TABLE0 0xD36C
#define R_AX_PWR_MACID_LMT_TABLE127 0xD568
@@ -3574,6 +3632,7 @@
#define RR_MOD_MASK GENMASK(19, 16)
#define RR_MOD_DCK GENMASK(14, 10)
#define RR_MOD_RGM GENMASK(13, 4)
+#define RR_MOD_RXB GENMASK(9, 5)
#define RR_MOD_V_DOWN 0x0
#define RR_MOD_V_STANDBY 0x1
#define RR_TXAGC 0x10001
@@ -3713,6 +3772,7 @@
#define RR_RXBB 0x83
#define RR_RXBB_VOBUF GENMASK(15, 12)
#define RR_RXBB_C2G GENMASK(16, 10)
+#define RR_RXBB_C2 GENMASK(11, 8)
#define RR_RXBB_C1G GENMASK(9, 8)
#define RR_RXBB_FATT GENMASK(7, 0)
#define RR_RXBB_ATTR GENMASK(7, 4)
@@ -3727,6 +3787,7 @@
#define RR_RXA_DPK GENMASK(9, 8)
#define RR_RXA_LNA 0x8b
#define RR_RXA2 0x8c
+#define RR_RAA2_SATT GENMASK(15, 13)
#define RR_RAA2_SWATT GENMASK(15, 9)
#define RR_RXA2_C1 GENMASK(12, 10)
#define RR_RXA2_C2 GENMASK(9, 3)
@@ -3776,19 +3837,26 @@
#define RR_LOGEN 0xa3
#define RR_LOGEN_RPT GENMASK(19, 16)
#define RR_SX 0xaf
+#define RR_IBD 0xc9
+#define RR_IBD_VAL GENMASK(4, 0)
#define RR_LDO 0xb1
#define RR_LDO_SEL GENMASK(8, 6)
#define RR_VCO 0xb2
+#define RR_VCO_SEL GENMASK(9, 8)
+#define RR_VCI 0xb3
+#define RR_VCI_ON BIT(7)
#define RR_LPF 0xb7
#define RR_LPF_BUSY BIT(8)
#define RR_XTALX2 0xb8
#define RR_MALSEL 0xbe
#define RR_SYNFB 0xc5
#define RR_SYNFB_LK BIT(15)
+#define RR_AACK 0xca
#define RR_LCKST 0xcf
#define RR_LCKST_BIN BIT(0)
#define RR_LCK_TRG 0xd3
#define RR_LCK_TRGSEL BIT(8)
+#define RR_LCK_ST BIT(4)
#define RR_MMD 0xd5
#define RR_MMD_RST_EN BIT(8)
#define RR_MMD_RST_SYN BIT(6)
@@ -3807,6 +3875,7 @@
#define RR_CAL_RW BIT(19)
#define RR_LUTWE2 0xee
#define RR_LUTWE2_RTXBW BIT(2)
+#define RR_LUTWE2_DIS BIT(6)
#define RR_LUTWE 0xef
#define RR_LUTWE_LOK BIT(2)
#define RR_RFC 0xf0
@@ -3832,6 +3901,7 @@
#define R_RFE_E_A2 0x0334
#define R_RFE_O_SEL_A2 0x0338
#define R_RFE_SEL0_A2 0x033C
+#define B_RFE_SEL0_MASK GENMASK(1, 0)
#define R_RFE_SEL32_A2 0x0340
#define R_CIRST 0x035c
#define B_CIRST_SYN GENMASK(11, 10)
@@ -3852,6 +3922,9 @@
#define B_ENABLE_CCK BIT(5)
#define R_RSTB_ASYNC 0x0704
#define B_RSTB_ASYNC_ALL BIT(1)
+#define R_P0_ANT_SW 0x0728
+#define B_P0_HW_ANTSW_DIS_BY_GNT_BT BIT(12)
+#define B_P0_TRSW_TX_EXTEND GENMASK(3, 0)
#define R_MAC_PIN_SEL 0x0734
#define B_CH_IDX_SEG0 GENMASK(23, 16)
#define R_PLCP_HISTOGRAM 0x0738
@@ -3961,6 +4034,7 @@
#define R_S0_HW_SI_DIS 0x1200
#define B_S0_HW_SI_DIS_W_R_TRIG GENMASK(30, 28)
#define R_P0_RXCK 0x12A0
+#define B_P0_RXCK_ADJ GENMASK(31, 23)
#define B_P0_RXCK_BW3 BIT(30)
#define B_P0_TXCK_ALL GENMASK(19, 12)
#define B_P0_RXCK_ON BIT(19)
@@ -4034,6 +4108,7 @@
#define R_TXAGC_BB 0x1C60
#define B_TXAGC_BB_OFT GENMASK(31, 16)
#define B_TXAGC_BB GENMASK(31, 24)
+#define B_TXAGC_RF GENMASK(5, 0)
#define R_S0_ADDCK 0x1E00
#define B_S0_ADDCK_I GENMASK(9, 0)
#define B_S0_ADDCK_Q GENMASK(19, 10)
@@ -4117,8 +4192,10 @@
#define R_DCFO 0x4264
#define B_DCFO GENMASK(7, 0)
#define R_SEG0CSI 0x42AC
+#define R_SEG0CSI_V1 0x42B0
#define B_SEG0CSI_IDX GENMASK(10, 0)
#define R_SEG0CSI_EN 0x42C4
+#define R_SEG0CSI_EN_V1 0x42C8
#define B_SEG0CSI_EN BIT(23)
#define R_BSS_CLR_MAP 0x43ac
#define R_BSS_CLR_MAP_V1 0x43B0
@@ -4350,6 +4427,14 @@
#define B_PATH0_BT_BACKOFF_V1 GENMASK(23, 0)
#define R_PATH1_BT_BACKOFF_V1 0x4AEC
#define B_PATH1_BT_BACKOFF_V1 GENMASK(23, 0)
+#define R_DCFO_COMP_S0_V2 0x4B20
+#define B_DCFO_COMP_S0_MSK_V2 GENMASK(13, 0)
+#define R_PATH0_TX_CFR 0x4B30
+#define B_PATH0_TX_CFR_LGC1 GENMASK(19, 10)
+#define B_PATH0_TX_CFR_LGC0 GENMASK(9, 0)
+#define R_PATH0_TX_POLAR_CLIPPING 0x4B3C
+#define B_PATH0_TX_POLAR_CLIPPING_LGC1 GENMASK(19, 16)
+#define B_PATH0_TX_POLAR_CLIPPING_LGC0 GENMASK(15, 12)
#define R_PATH0_FRC_FIR_TYPE_V1 0x4C00
#define B_PATH0_FRC_FIR_TYPE_MSK_V1 GENMASK(1, 0)
#define R_PATH0_NOTCH 0x4C14
@@ -4455,10 +4540,29 @@
#define B_P0_RFCTM_VAL GENMASK(25, 20)
#define R_P0_RFCTM_RDY BIT(26)
#define R_P0_TRSW 0x5868
-#define B_P0_TRSW_B BIT(0)
-#define B_P0_TRSW_A BIT(1)
+#define B_P0_BT_FORCE_ANTIDX_EN BIT(12)
#define B_P0_TRSW_X BIT(2)
+#define B_P0_TRSW_A BIT(1)
+#define B_P0_TX_ANT_SEL BIT(1)
+#define B_P0_TRSW_B BIT(0)
+#define B_P0_ANT_TRAIN_EN BIT(0)
#define B_P0_TRSW_SO_A2 GENMASK(7, 5)
+#define R_P0_ANTSEL 0x586C
+#define B_P0_ANTSEL_SW_5G BIT(25)
+#define B_P0_ANTSEL_SW_2G BIT(23)
+#define B_P0_ANTSEL_BTG_TRX BIT(21)
+#define B_P0_ANTSEL_CGCS_CTRL BIT(17)
+#define B_P0_ANTSEL_HW_CTRL BIT(16)
+#define B_P0_ANTSEL_TX_ORI GENMASK(15, 12)
+#define B_P0_ANTSEL_RX_ALT GENMASK(11, 8)
+#define B_P0_ANTSEL_RX_ORI GENMASK(7, 4)
+#define R_RFSW_CTRL_ANT0_BASE 0x5870
+#define B_RFSW_CTRL_ANT_MAPPING GENMASK(15, 0)
+#define R_RFE_SEL0_BASE 0x5880
+#define B_RFE_SEL0_SRC_MASK GENMASK(3, 0)
+#define R_RFE_SEL32_BASE 0x5884
+#define RFE_SEL0_SRC_ANTSEL_0 8
+#define R_RFE_INV0 0x5890
#define R_P0_RFM 0x5894
#define B_P0_RFM_DIS_WL BIT(7)
#define B_P0_RFM_TX_OPT BIT(6)
@@ -4572,12 +4676,15 @@
#define IQK_DF4_TXT_8_25MHZ 0x021
#define R_IQK_CFG 0x8034
#define B_IQK_CFG_SET GENMASK(5, 4)
+#define R_IQK_RXA 0x8044
+#define B_IQK_RXAGC GENMASK(15, 13)
#define R_TPG_SEL 0x8068
#define R_TPG_MOD 0x806C
#define B_TPG_MOD_F GENMASK(2, 1)
#define R_MDPK_SYNC 0x8070
#define B_MDPK_SYNC_SEL BIT(31)
#define B_MDPK_SYNC_MAN GENMASK(31, 28)
+#define B_MDPK_SYNC_DMAN GENMASK(30, 28)
#define R_MDPK_RX_DCK 0x8074
#define B_MDPK_RX_DCK_EN BIT(31)
#define R_KIP_MOD 0x8078
@@ -4586,6 +4693,7 @@
#define R_KIP_SYSCFG 0x8088
#define R_KIP_CLK 0x808C
#define R_DPK_IDL 0x809C
+#define B_DPK_IDL_SEL GENMASK(10, 9)
#define B_DPK_IDL BIT(8)
#define R_LDL_NORM 0x80A0
#define B_LDL_NORM_MA BIT(16)
@@ -4604,6 +4712,10 @@
#define B_KIP_RPT1_SEL GENMASK(21, 16)
#define B_KIP_RPT1_SEL_V1 GENMASK(19, 16)
#define R_SRAM_IQRX 0x80D8
+#define R_IDL_MPA 0x80DC
+#define B_IDL_DN BIT(31)
+#define B_IDL_MD530 BIT(1)
+#define B_IDL_MD500 BIT(0)
#define R_GAPK 0x80E0
#define B_GAPK_ADR BIT(0)
#define R_SRAM_IQRX2 0x80E8
@@ -4619,6 +4731,7 @@
#define B_PRT_COM_SYNERR BIT(30)
#define B_PRT_COM_DCI GENMASK(27, 16)
#define B_PRT_COM_CORV GENMASK(15, 8)
+#define B_RPT_COM_RDY GENMASK(15, 0)
#define B_PRT_COM_DCQ GENMASK(11, 0)
#define B_PRT_COM_RXOV BIT(8)
#define B_PRT_COM_GL GENMASK(7, 4)
@@ -4690,6 +4803,7 @@
#define B_DPK_GL_A0 GENMASK(31, 28)
#define B_DPK_GL_A1 GENMASK(17, 0)
#define R_RPT_PER 0x81FC
+#define B_RPT_PER_KSET GENMASK(31, 29)
#define B_RPT_PER_TSSI GENMASK(28, 16)
#define B_RPT_PER_OF GENMASK(15, 8)
#define B_RPT_PER_TH GENMASK(5, 0)
@@ -4730,11 +4844,15 @@
#define B_IQKINF2_KCNT GENMASK(15, 8)
#define B_IQKINF2_NCTLV GENMASK(7, 0)
#define R_DCOF0 0xC000
+#define B_DCOF0_RST BIT(17)
#define B_DCOF0_V GENMASK(4, 1)
#define R_DCOF1 0xC004
+#define B_DCOF1_RST BIT(17)
#define B_DCOF1_S BIT(0)
#define R_DCOF8 0xC020
#define B_DCOF8_V GENMASK(4, 1)
+#define R_DCOF9 0xC024
+#define B_DCOF9_RST BIT(17)
#define R_DACK_S0P0 0xC040
#define B_DACK_S0P0_OK BIT(31)
#define R_DACK_BIAS00 0xc048
@@ -4779,13 +4897,19 @@
#define R_P0_CFCH_BW1 0xC0D8
#define B_P0_CFCH_EX BIT(13)
#define B_P0_CFCH_BW1 GENMASK(8, 5)
+#define R_WDADC 0xC0E4
+#define B_WDADC_SEL GENMASK(5, 4)
#define R_ADCMOD 0xC0E8
#define B_ADCMOD_LP GENMASK(31, 16)
+#define R_DCIM 0xC0EC
+#define B_DCIM_FR GENMASK(14, 13)
#define R_ADDCK0D 0xC0F0
#define B_ADDCK0D_VAL2 GENMASK(31, 26)
#define B_ADDCK0D_VAL GENMASK(25, 16)
+#define B_ADDCK_DS BIT(16)
#define R_ADDCK0 0xC0F4
#define B_ADDCK0_TRG BIT(11)
+#define B_ADDCK0_IQ BIT(10)
#define B_ADDCK0 GENMASK(9, 8)
#define B_ADDCK0_MAN GENMASK(5, 4)
#define B_ADDCK0_EN BIT(4)
@@ -4797,6 +4921,7 @@
#define B_ADDCK0_RL0 GENMASK(17, 8)
#define R_ADDCKR0 0xC0FC
#define B_ADDCKR0_A0 GENMASK(19, 10)
+#define B_ADDCKR0_DC GENMASK(15, 4)
#define B_ADDCKR0_A1 GENMASK(9, 0)
#define R_DACK10 0xC100
#define B_DACK10 GENMASK(4, 1)
@@ -4847,6 +4972,11 @@
#define R_ADDCKR1 0xC1fC
#define B_ADDCKR1_A0 GENMASK(19, 10)
#define B_ADDCKR1_A1 GENMASK(9, 0)
+#define R_DACKN0_CTL 0xC210
+#define B_DACKN0_EN BIT(0)
+#define B_DACKN0_V GENMASK(21, 14)
+#define R_DACKN1_CTL 0xC224
+#define B_DACKN1_V GENMASK(21, 14)
/* WiFi CPU local domain */
#define R_AX_WDT_CTRL 0x0040
diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c
index 6e5a740b128f..34c4d40cfa02 100644
--- a/drivers/net/wireless/realtek/rtw89/regd.c
+++ b/drivers/net/wireless/realtek/rtw89/regd.c
@@ -2,33 +2,35 @@
/* Copyright(c) 2019-2020 Realtek Corporation
*/
+#include "acpi.h"
#include "debug.h"
#include "ps.h"
+#include "util.h"
#define COUNTRY_REGD(_alpha2, _txpwr_regd...) \
{.alpha2 = (_alpha2), \
.txpwr_regd = {_txpwr_regd}, \
}
-static const struct rtw89_regulatory rtw89_ww_regd =
+static const struct rtw89_regd rtw89_ww_regd =
COUNTRY_REGD("00", RTW89_WW, RTW89_WW);
-static const struct rtw89_regulatory rtw89_regd_map[] = {
+static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("AR", RTW89_MEXICO, RTW89_MEXICO, RTW89_NA),
- COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("BR", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("CL", RTW89_CHILE, RTW89_CHILE, RTW89_CHILE),
- COUNTRY_REGD("CO", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("CO", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("CR", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("EC", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("SV", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("GT", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("SV", RTW89_FCC, RTW89_FCC, RTW89_FCC),
+ COUNTRY_REGD("GT", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("HN", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("MX", RTW89_MEXICO, RTW89_MEXICO, RTW89_NA),
COUNTRY_REGD("NI", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("PA", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("PY", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("PE", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("PE", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("US", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("UY", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("VE", RTW89_FCC, RTW89_FCC, RTW89_NA),
@@ -65,37 +67,37 @@ static const struct rtw89_regulatory rtw89_regd_map[] = {
COUNTRY_REGD("CH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("GB", RTW89_UK, RTW89_UK, RTW89_UK),
COUNTRY_REGD("AL", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("AZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("BH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("AZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("BH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("BA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("BG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("HR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("BG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("HR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("EG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("GH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("GH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("IQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("IL", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("JO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("IL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("JO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("KZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("KE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("KW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("KG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("KE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("KW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("KG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("LB", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("LS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("MZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("NA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("NG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("OM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("QA", RTW89_QATAR, RTW89_QATAR, RTW89_QATAR),
- COUNTRY_REGD("RO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("RO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("RU", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("SA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("SA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("SN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("RS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("RS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("ME", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("ZA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("TR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("TR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("UA", RTW89_UKRAINE, RTW89_UKRAINE, RTW89_UKRAINE),
COUNTRY_REGD("AE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("YE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -103,11 +105,11 @@ static const struct rtw89_regulatory rtw89_regd_map[] = {
COUNTRY_REGD("BD", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("KH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("CN", RTW89_CN, RTW89_CN, RTW89_CN),
- COUNTRY_REGD("HK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("HK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("IN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("ID", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("KR", RTW89_KCC, RTW89_KCC, RTW89_KCC),
- COUNTRY_REGD("MY", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("MY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("PK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("PH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("SG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -115,55 +117,55 @@ static const struct rtw89_regulatory rtw89_regd_map[] = {
COUNTRY_REGD("TW", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("TH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("VN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
- COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
- COUNTRY_REGD("PG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA),
+ COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA),
+ COUNTRY_REGD("PG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("CA", RTW89_IC, RTW89_IC, RTW89_IC),
- COUNTRY_REGD("JP", RTW89_MKK, RTW89_MKK, RTW89_NA),
- COUNTRY_REGD("JM", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("AN", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("JP", RTW89_MKK, RTW89_MKK, RTW89_MKK),
+ COUNTRY_REGD("JM", RTW89_FCC, RTW89_FCC, RTW89_FCC),
+ COUNTRY_REGD("AN", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("TT", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("TN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("AF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("DZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("DZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("AS", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("AD", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("AO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("AI", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("AI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("AQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("AG", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("AM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("AW", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("BS", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("BB", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("AG", RTW89_FCC, RTW89_FCC, RTW89_FCC),
+ COUNTRY_REGD("AM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("AW", RTW89_FCC, RTW89_FCC, RTW89_FCC),
+ COUNTRY_REGD("BS", RTW89_FCC, RTW89_FCC, RTW89_FCC),
+ COUNTRY_REGD("BB", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("BY", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("BZ", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("BJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("BM", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("BM", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("BT", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("BW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("BW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("BV", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("IO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("VG", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("VG", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("BN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("BF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("BI", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("BI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("CM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("CV", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("KY", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("KY", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("CF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("TD", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("TD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("CX", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
- COUNTRY_REGD("CC", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("KM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("CC", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
+ COUNTRY_REGD("KM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("CG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("CD", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("CK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("CI", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("DJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("DM", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("GQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("DJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("DM", RTW89_FCC, RTW89_FCC, RTW89_FCC),
+ COUNTRY_REGD("GQ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("ER", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("ET", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("FK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -173,17 +175,17 @@ static const struct rtw89_regulatory rtw89_regd_map[] = {
COUNTRY_REGD("PF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("TF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("GA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("GM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("GM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("GE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("GI", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("GL", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("GP", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("GU", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("GG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("GW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("GY", RTW89_NCC, RTW89_NCC, RTW89_NA),
+ COUNTRY_REGD("GY", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("HT", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("HM", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
COUNTRY_REGD("VA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -194,17 +196,17 @@ static const struct rtw89_regulatory rtw89_regd_map[] = {
COUNTRY_REGD("LR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("LY", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("MG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("MG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("MW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MV", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("ML", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MH", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("MQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("MU", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("MU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("YT", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("FM", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("MN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("NR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -218,26 +220,26 @@ static const struct rtw89_regulatory rtw89_regd_map[] = {
COUNTRY_REGD("RE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("RW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("SH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("KN", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("LC", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("KN", RTW89_FCC, RTW89_FCC, RTW89_FCC),
+ COUNTRY_REGD("LC", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("MF", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("SX", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("PM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("VC", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("WS", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("SM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("ST", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("ST", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("SC", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("SL", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("SL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("SB", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("SO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("GS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("SR", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("SR", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("SJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("SZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("TJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("TJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("TZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("TG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("TG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("TK", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
COUNTRY_REGD("TO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("TM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -245,7 +247,7 @@ static const struct rtw89_regulatory rtw89_regd_map[] = {
COUNTRY_REGD("TV", RTW89_ETSI, RTW89_NA, RTW89_NA),
COUNTRY_REGD("UG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("VI", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("UZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("UZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("VU", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("WF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("EH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -254,7 +256,7 @@ static const struct rtw89_regulatory rtw89_regd_map[] = {
COUNTRY_REGD("PS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
};
-static const struct rtw89_regulatory *rtw89_regd_find_reg_by_name(char *alpha2)
+static const struct rtw89_regd *rtw89_regd_find_reg_by_name(char *alpha2)
{
u32 i;
@@ -266,7 +268,7 @@ static const struct rtw89_regulatory *rtw89_regd_find_reg_by_name(char *alpha2)
return &rtw89_ww_regd;
}
-static bool rtw89_regd_is_ww(const struct rtw89_regulatory *regd)
+static bool rtw89_regd_is_ww(const struct rtw89_regd *regd)
{
return regd == &rtw89_ww_regd;
}
@@ -282,25 +284,139 @@ do { \
__r->txpwr_regd[RTW89_BAND_6G]); \
} while (0)
+static void rtw89_regd_setup_unii4(struct rtw89_dev *rtwdev,
+ struct wiphy *wiphy)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ bool regd_allow_unii_4 = chip->support_unii4;
+ struct ieee80211_supported_band *sband;
+ int ret;
+ u8 val;
+
+ if (!chip->support_unii4)
+ goto bottom;
+
+ ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_59G_EN, &val);
+ if (ret) {
+ rtw89_debug(rtwdev, RTW89_DBG_REGD,
+ "acpi: cannot eval unii 4: %d\n", ret);
+ goto bottom;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_REGD,
+ "acpi: eval if allow unii 4: %d\n", val);
+
+ switch (val) {
+ case 0:
+ regd_allow_unii_4 = false;
+ break;
+ case 1:
+ regd_allow_unii_4 = true;
+ break;
+ default:
+ break;
+ }
+
+bottom:
+ rtw89_debug(rtwdev, RTW89_DBG_REGD, "regd: allow unii 4: %d\n",
+ regd_allow_unii_4);
+
+ if (regd_allow_unii_4)
+ return;
+
+ sband = wiphy->bands[NL80211_BAND_5GHZ];
+ if (!sband)
+ return;
+
+ sband->n_channels -= 3;
+}
+
+static void rtw89_regd_setup_6ghz(struct rtw89_dev *rtwdev, struct wiphy *wiphy)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ bool chip_support_6ghz = chip->support_bands & BIT(NL80211_BAND_6GHZ);
+ bool regd_allow_6ghz = chip_support_6ghz;
+ struct ieee80211_supported_band *sband;
+ int ret;
+ u8 val;
+
+ if (!chip_support_6ghz)
+ goto bottom;
+
+ ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6G_DIS, &val);
+ if (ret) {
+ rtw89_debug(rtwdev, RTW89_DBG_REGD,
+ "acpi: cannot eval 6ghz: %d\n", ret);
+ goto bottom;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_REGD,
+ "acpi: eval if disallow 6ghz: %d\n", val);
+
+ switch (val) {
+ case 0:
+ regd_allow_6ghz = true;
+ break;
+ case 1:
+ regd_allow_6ghz = false;
+ break;
+ default:
+ break;
+ }
+
+bottom:
+ rtw89_debug(rtwdev, RTW89_DBG_REGD, "regd: allow 6ghz: %d\n",
+ regd_allow_6ghz);
+
+ if (regd_allow_6ghz)
+ return;
+
+ sband = wiphy->bands[NL80211_BAND_6GHZ];
+ if (!sband)
+ return;
+
+ wiphy->bands[NL80211_BAND_6GHZ] = NULL;
+ kfree(sband->iftype_data);
+ kfree(sband);
+}
+
+int rtw89_regd_setup(struct rtw89_dev *rtwdev)
+{
+ struct wiphy *wiphy = rtwdev->hw->wiphy;
+
+ if (!wiphy)
+ return -EINVAL;
+
+ rtw89_regd_setup_unii4(rtwdev, wiphy);
+ rtw89_regd_setup_6ghz(rtwdev, wiphy);
+
+ wiphy->reg_notifier = rtw89_regd_notifier;
+ return 0;
+}
+
int rtw89_regd_init(struct rtw89_dev *rtwdev,
void (*reg_notifier)(struct wiphy *wiphy,
struct regulatory_request *request))
{
- const struct rtw89_regulatory *chip_regd;
+ struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
+ const struct rtw89_regd *chip_regd;
struct wiphy *wiphy = rtwdev->hw->wiphy;
int ret;
+ regulatory->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
+
if (!wiphy)
return -EINVAL;
chip_regd = rtw89_regd_find_reg_by_name(rtwdev->efuse.country_code);
if (!rtw89_regd_is_ww(chip_regd)) {
- rtwdev->regd = chip_regd;
+ rtwdev->regulatory.regd = chip_regd;
/* Ignore country ie if there is a country domain programmed in chip */
wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
- ret = regulatory_hint(rtwdev->hw->wiphy, rtwdev->regd->alpha2);
+ ret = regulatory_hint(rtwdev->hw->wiphy,
+ rtwdev->regulatory.regd->alpha2);
if (ret)
rtw89_warn(rtwdev, "failed to hint regulatory:%d\n", ret);
@@ -308,7 +424,7 @@ int rtw89_regd_init(struct rtw89_dev *rtwdev,
return 0;
}
- rtw89_debug_regd(rtwdev, rtwdev->regd,
+ rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd,
"worldwide roaming chip, follow the setting of stack");
return 0;
}
@@ -317,13 +433,13 @@ static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev,
struct wiphy *wiphy,
struct regulatory_request *request)
{
- rtwdev->regd = rtw89_regd_find_reg_by_name(request->alpha2);
+ rtwdev->regulatory.regd = rtw89_regd_find_reg_by_name(request->alpha2);
/* This notification might be set from the system of distros,
* and it does not expect the regulatory will be modified by
* connecting to an AP (i.e. country ie).
*/
if (request->initiator == NL80211_REGDOM_SET_BY_USER &&
- !rtw89_regd_is_ww(rtwdev->regd))
+ !rtw89_regd_is_ww(rtwdev->regulatory.regd))
wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
else
wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE;
@@ -343,7 +459,8 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request
goto exit;
}
rtw89_regd_notifier_apply(rtwdev, wiphy, request);
- rtw89_debug_regd(rtwdev, rtwdev->regd, "get from initiator %d, alpha2",
+ rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd,
+ "get from initiator %d, alpha2",
request->initiator);
rtw89_core_set_chip_txpwr(rtwdev);
@@ -351,3 +468,66 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request
exit:
mutex_unlock(&rtwdev->mutex);
}
+
+static void __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
+ enum rtw89_reg_6ghz_power sel;
+ const struct rtw89_chan *chan;
+ struct rtw89_vif *rtwvif;
+ int count = 0;
+
+ rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+ chan = rtw89_chan_get(rtwdev, rtwvif->sub_entity_idx);
+ if (chan->band_type != RTW89_BAND_6G)
+ continue;
+
+ if (count != 0 && rtwvif->reg_6ghz_power == sel)
+ continue;
+
+ sel = rtwvif->reg_6ghz_power;
+ count++;
+ }
+
+ if (count != 1)
+ sel = RTW89_REG_6GHZ_POWER_DFLT;
+
+ if (regulatory->reg_6ghz_power == sel)
+ return;
+
+ rtw89_debug(rtwdev, RTW89_DBG_REGD,
+ "recalc 6 GHz reg power type to %d\n", sel);
+
+ regulatory->reg_6ghz_power = sel;
+
+ rtw89_core_set_chip_txpwr(rtwdev);
+}
+
+void rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev,
+ struct rtw89_vif *rtwvif, bool active)
+{
+ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+
+ lockdep_assert_held(&rtwdev->mutex);
+
+ if (active) {
+ switch (vif->bss_conf.power_type) {
+ case IEEE80211_REG_VLP_AP:
+ rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP;
+ break;
+ case IEEE80211_REG_LPI_AP:
+ rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI;
+ break;
+ case IEEE80211_REG_SP_AP:
+ rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD;
+ break;
+ default:
+ rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
+ break;
+ }
+ } else {
+ rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
+ }
+
+ __rtw89_reg_6ghz_power_recalc(rtwdev);
+}
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
new file mode 100644
index 000000000000..c3ffcb645ebf
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
@@ -0,0 +1,2442 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2022-2023 Realtek Corporation
+ */
+
+#include "coex.h"
+#include "efuse.h"
+#include "fw.h"
+#include "mac.h"
+#include "phy.h"
+#include "reg.h"
+#include "rtw8851b.h"
+#include "rtw8851b_rfk.h"
+#include "rtw8851b_rfk_table.h"
+#include "rtw8851b_table.h"
+#include "txrx.h"
+#include "util.h"
+
+#define RTW8851B_FW_FORMAT_MAX 0
+#define RTW8851B_FW_BASENAME "rtw89/rtw8851b_fw"
+#define RTW8851B_MODULE_FIRMWARE \
+ RTW8851B_FW_BASENAME ".bin"
+
+static const struct rtw89_hfc_ch_cfg rtw8851b_hfc_chcfg_pcie[] = {
+ {5, 343, grp_0}, /* ACH 0 */
+ {5, 343, grp_0}, /* ACH 1 */
+ {5, 343, grp_0}, /* ACH 2 */
+ {5, 343, grp_0}, /* ACH 3 */
+ {0, 0, grp_0}, /* ACH 4 */
+ {0, 0, grp_0}, /* ACH 5 */
+ {0, 0, grp_0}, /* ACH 6 */
+ {0, 0, grp_0}, /* ACH 7 */
+ {4, 344, grp_0}, /* B0MGQ */
+ {4, 344, grp_0}, /* B0HIQ */
+ {0, 0, grp_0}, /* B1MGQ */
+ {0, 0, grp_0}, /* B1HIQ */
+ {40, 0, 0} /* FWCMDQ */
+};
+
+static const struct rtw89_hfc_pub_cfg rtw8851b_hfc_pubcfg_pcie = {
+ 448, /* Group 0 */
+ 0, /* Group 1 */
+ 448, /* Public Max */
+ 0 /* WP threshold */
+};
+
+static const struct rtw89_hfc_param_ini rtw8851b_hfc_param_ini_pcie[] = {
+ [RTW89_QTA_SCC] = {rtw8851b_hfc_chcfg_pcie, &rtw8851b_hfc_pubcfg_pcie,
+ &rtw89_mac_size.hfc_preccfg_pcie, RTW89_HCIFC_POH},
+ [RTW89_QTA_DLFW] = {NULL, NULL, &rtw89_mac_size.hfc_preccfg_pcie,
+ RTW89_HCIFC_POH},
+ [RTW89_QTA_INVALID] = {NULL},
+};
+
+static const struct rtw89_dle_mem rtw8851b_dle_mem_pcie[] = {
+ [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size6,
+ &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt6,
+ &rtw89_mac_size.wde_qt6, &rtw89_mac_size.ple_qt18,
+ &rtw89_mac_size.ple_qt58},
+ [RTW89_QTA_WOW] = {RTW89_QTA_WOW, &rtw89_mac_size.wde_size6,
+ &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt6,
+ &rtw89_mac_size.wde_qt6, &rtw89_mac_size.ple_qt18,
+ &rtw89_mac_size.ple_qt_51b_wow},
+ [RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size9,
+ &rtw89_mac_size.ple_size8, &rtw89_mac_size.wde_qt4,
+ &rtw89_mac_size.wde_qt4, &rtw89_mac_size.ple_qt13,
+ &rtw89_mac_size.ple_qt13},
+ [RTW89_QTA_INVALID] = {RTW89_QTA_INVALID, NULL, NULL, NULL, NULL, NULL,
+ NULL},
+};
+
+static const struct rtw89_reg3_def rtw8851b_btc_preagc_en_defs[] = {
+ {0x46D0, GENMASK(1, 0), 0x3},
+ {0x4AD4, GENMASK(31, 0), 0xf},
+ {0x4688, GENMASK(23, 16), 0x80},
+ {0x4688, GENMASK(31, 24), 0x80},
+ {0x4694, GENMASK(7, 0), 0x80},
+ {0x4694, GENMASK(15, 8), 0x80},
+ {0x4AE4, GENMASK(11, 6), 0x34},
+ {0x4AE4, GENMASK(17, 12), 0x0},
+ {0x469C, GENMASK(31, 26), 0x34},
+};
+
+static DECLARE_PHY_REG3_TBL(rtw8851b_btc_preagc_en_defs);
+
+static const struct rtw89_reg3_def rtw8851b_btc_preagc_dis_defs[] = {
+ {0x46D0, GENMASK(1, 0), 0x0},
+ {0x4AD4, GENMASK(31, 0), 0x60},
+ {0x4688, GENMASK(23, 16), 0x10},
+ {0x4690, GENMASK(31, 24), 0x2a},
+ {0x4694, GENMASK(15, 8), 0x2a},
+ {0x4AE4, GENMASK(11, 6), 0x26},
+ {0x4AE4, GENMASK(17, 12), 0x1e},
+ {0x469C, GENMASK(31, 26), 0x26},
+};
+
+static DECLARE_PHY_REG3_TBL(rtw8851b_btc_preagc_dis_defs);
+
+static const u32 rtw8851b_h2c_regs[RTW89_H2CREG_MAX] = {
+ R_AX_H2CREG_DATA0, R_AX_H2CREG_DATA1, R_AX_H2CREG_DATA2,
+ R_AX_H2CREG_DATA3
+};
+
+static const u32 rtw8851b_c2h_regs[RTW89_C2HREG_MAX] = {
+ R_AX_C2HREG_DATA0, R_AX_C2HREG_DATA1, R_AX_C2HREG_DATA2,
+ R_AX_C2HREG_DATA3
+};
+
+static const struct rtw89_page_regs rtw8851b_page_regs = {
+ .hci_fc_ctrl = R_AX_HCI_FC_CTRL,
+ .ch_page_ctrl = R_AX_CH_PAGE_CTRL,
+ .ach_page_ctrl = R_AX_ACH0_PAGE_CTRL,
+ .ach_page_info = R_AX_ACH0_PAGE_INFO,
+ .pub_page_info3 = R_AX_PUB_PAGE_INFO3,
+ .pub_page_ctrl1 = R_AX_PUB_PAGE_CTRL1,
+ .pub_page_ctrl2 = R_AX_PUB_PAGE_CTRL2,
+ .pub_page_info1 = R_AX_PUB_PAGE_INFO1,
+ .pub_page_info2 = R_AX_PUB_PAGE_INFO2,
+ .wp_page_ctrl1 = R_AX_WP_PAGE_CTRL1,
+ .wp_page_ctrl2 = R_AX_WP_PAGE_CTRL2,
+ .wp_page_info1 = R_AX_WP_PAGE_INFO1,
+};
+
+static const struct rtw89_reg_def rtw8851b_dcfo_comp = {
+ R_DCFO_COMP_S0_V2, B_DCFO_COMP_S0_MSK_V2
+};
+
+static const struct rtw89_imr_info rtw8851b_imr_info = {
+ .wdrls_imr_set = B_AX_WDRLS_IMR_SET,
+ .wsec_imr_reg = R_AX_SEC_DEBUG,
+ .wsec_imr_set = B_AX_IMR_ERROR,
+ .mpdu_tx_imr_set = 0,
+ .mpdu_rx_imr_set = 0,
+ .sta_sch_imr_set = B_AX_STA_SCHEDULER_IMR_SET,
+ .txpktctl_imr_b0_reg = R_AX_TXPKTCTL_ERR_IMR_ISR,
+ .txpktctl_imr_b0_clr = B_AX_TXPKTCTL_IMR_B0_CLR,
+ .txpktctl_imr_b0_set = B_AX_TXPKTCTL_IMR_B0_SET,
+ .txpktctl_imr_b1_reg = R_AX_TXPKTCTL_ERR_IMR_ISR_B1,
+ .txpktctl_imr_b1_clr = B_AX_TXPKTCTL_IMR_B1_CLR,
+ .txpktctl_imr_b1_set = B_AX_TXPKTCTL_IMR_B1_SET,
+ .wde_imr_clr = B_AX_WDE_IMR_CLR,
+ .wde_imr_set = B_AX_WDE_IMR_SET,
+ .ple_imr_clr = B_AX_PLE_IMR_CLR,
+ .ple_imr_set = B_AX_PLE_IMR_SET,
+ .host_disp_imr_clr = B_AX_HOST_DISP_IMR_CLR,
+ .host_disp_imr_set = B_AX_HOST_DISP_IMR_SET,
+ .cpu_disp_imr_clr = B_AX_CPU_DISP_IMR_CLR,
+ .cpu_disp_imr_set = B_AX_CPU_DISP_IMR_SET,
+ .other_disp_imr_clr = B_AX_OTHER_DISP_IMR_CLR,
+ .other_disp_imr_set = 0,
+ .bbrpt_com_err_imr_reg = R_AX_BBRPT_COM_ERR_IMR_ISR,
+ .bbrpt_chinfo_err_imr_reg = R_AX_BBRPT_CHINFO_ERR_IMR_ISR,
+ .bbrpt_err_imr_set = 0,
+ .bbrpt_dfs_err_imr_reg = R_AX_BBRPT_DFS_ERR_IMR_ISR,
+ .ptcl_imr_clr = B_AX_PTCL_IMR_CLR_ALL,
+ .ptcl_imr_set = B_AX_PTCL_IMR_SET,
+ .cdma_imr_0_reg = R_AX_DLE_CTRL,
+ .cdma_imr_0_clr = B_AX_DLE_IMR_CLR,
+ .cdma_imr_0_set = B_AX_DLE_IMR_SET,
+ .cdma_imr_1_reg = 0,
+ .cdma_imr_1_clr = 0,
+ .cdma_imr_1_set = 0,
+ .phy_intf_imr_reg = R_AX_PHYINFO_ERR_IMR,
+ .phy_intf_imr_clr = 0,
+ .phy_intf_imr_set = 0,
+ .rmac_imr_reg = R_AX_RMAC_ERR_ISR,
+ .rmac_imr_clr = B_AX_RMAC_IMR_CLR,
+ .rmac_imr_set = B_AX_RMAC_IMR_SET,
+ .tmac_imr_reg = R_AX_TMAC_ERR_IMR_ISR,
+ .tmac_imr_clr = B_AX_TMAC_IMR_CLR,
+ .tmac_imr_set = B_AX_TMAC_IMR_SET,
+};
+
+static const struct rtw89_xtal_info rtw8851b_xtal_info = {
+ .xcap_reg = R_AX_XTAL_ON_CTRL3,
+ .sc_xo_mask = B_AX_XTAL_SC_XO_A_BLOCK_MASK,
+ .sc_xi_mask = B_AX_XTAL_SC_XI_A_BLOCK_MASK,
+};
+
+static const struct rtw89_rrsr_cfgs rtw8851b_rrsr_cfgs = {
+ .ref_rate = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_REF_RATE_SEL, 0},
+ .rsc = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_RSC_MASK, 2},
+};
+
+static const struct rtw89_dig_regs rtw8851b_dig_regs = {
+ .seg0_pd_reg = R_SEG0R_PD_V1,
+ .pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK,
+ .pd_spatial_reuse_en = B_SEG0R_PD_SPATIAL_REUSE_EN_MSK_V1,
+ .p0_lna_init = {R_PATH0_LNA_INIT_V1, B_PATH0_LNA_INIT_IDX_MSK},
+ .p1_lna_init = {R_PATH1_LNA_INIT_V1, B_PATH1_LNA_INIT_IDX_MSK},
+ .p0_tia_init = {R_PATH0_TIA_INIT_V1, B_PATH0_TIA_INIT_IDX_MSK_V1},
+ .p1_tia_init = {R_PATH1_TIA_INIT_V1, B_PATH1_TIA_INIT_IDX_MSK_V1},
+ .p0_rxb_init = {R_PATH0_RXB_INIT_V1, B_PATH0_RXB_INIT_IDX_MSK_V1},
+ .p1_rxb_init = {R_PATH1_RXB_INIT_V1, B_PATH1_RXB_INIT_IDX_MSK_V1},
+ .p0_p20_pagcugc_en = {R_PATH0_P20_FOLLOW_BY_PAGCUGC_V2,
+ B_PATH0_P20_FOLLOW_BY_PAGCUGC_EN_MSK},
+ .p0_s20_pagcugc_en = {R_PATH0_S20_FOLLOW_BY_PAGCUGC_V2,
+ B_PATH0_S20_FOLLOW_BY_PAGCUGC_EN_MSK},
+ .p1_p20_pagcugc_en = {R_PATH1_P20_FOLLOW_BY_PAGCUGC_V2,
+ B_PATH1_P20_FOLLOW_BY_PAGCUGC_EN_MSK},
+ .p1_s20_pagcugc_en = {R_PATH1_S20_FOLLOW_BY_PAGCUGC_V2,
+ B_PATH1_S20_FOLLOW_BY_PAGCUGC_EN_MSK},
+};
+
+static const struct rtw89_btc_rf_trx_para rtw89_btc_8851b_rf_ul[] = {
+ {255, 0, 0, 7}, /* 0 -> original */
+ {255, 2, 0, 7}, /* 1 -> for BT-connected ACI issue && BTG co-rx */
+ {255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 3- >reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */
+ {255, 1, 0, 7}, /* the below id is for non-shared-antenna free-run */
+ {6, 1, 0, 7},
+ {13, 1, 0, 7},
+ {13, 1, 0, 7}
+};
+
+static const struct rtw89_btc_rf_trx_para rtw89_btc_8851b_rf_dl[] = {
+ {255, 0, 0, 7}, /* 0 -> original */
+ {255, 2, 0, 7}, /* 1 -> reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 3- >reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */
+ {255, 1, 0, 7}, /* the below id is for non-shared-antenna free-run */
+ {255, 1, 0, 7},
+ {255, 1, 0, 7},
+ {255, 1, 0, 7}
+};
+
+static const struct rtw89_btc_fbtc_mreg rtw89_btc_8851b_mon_reg[] = {
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda24),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda28),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda2c),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda30),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda4c),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda10),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda20),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda34),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xcef4),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0x8424),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd200),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd220),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x980),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4738),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4688),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4694),
+};
+
+static const u8 rtw89_btc_8851b_wl_rssi_thres[BTC_WL_RSSI_THMAX] = {70, 60, 50, 40};
+static const u8 rtw89_btc_8851b_bt_rssi_thres[BTC_BT_RSSI_THMAX] = {50, 40, 30, 20};
+
+static int rtw8851b_pwr_on_func(struct rtw89_dev *rtwdev)
+{
+ u32 val32;
+ u8 val8;
+ u32 ret;
+
+ rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_AFSM_WLSUS_EN |
+ B_AX_AFSM_PCIE_SUS_EN);
+ rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_DIS_WLBT_PDNSUSEN_SOPC);
+ rtw89_write32_set(rtwdev, R_AX_WLLPS_CTRL, B_AX_DIS_WLBT_LPSEN_LOPC);
+ rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APDM_HPDN);
+ rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS);
+
+ ret = read_poll_timeout(rtw89_read32, val32, val32 & B_AX_RDY_SYSPWR,
+ 1000, 20000, false, rtwdev, R_AX_SYS_PW_CTRL);
+ if (ret)
+ return ret;
+
+ rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_EN_WLON);
+ rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFN_ONMAC);
+
+ ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_AX_APFN_ONMAC),
+ 1000, 20000, false, rtwdev, R_AX_SYS_PW_CTRL);
+ if (ret)
+ return ret;
+
+ rtw89_write8_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN);
+ rtw89_write8_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN);
+ rtw89_write8_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN);
+ rtw89_write8_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN);
+
+ rtw89_write8_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN);
+ rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL, B_AX_PCIE_CALIB_EN_V1);
+
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_OFF_WEI,
+ XTAL_SI_OFF_WEI);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_OFF_EI,
+ XTAL_SI_OFF_EI);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_RFC2RF);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_PON_WEI,
+ XTAL_SI_PON_WEI);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_PON_EI,
+ XTAL_SI_PON_EI);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_SRAM2RFC);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_SRAM_CTRL, 0, XTAL_SI_SRAM_DIS);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_XMD_2, 0, XTAL_SI_LDO_LPS);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_XMD_4, 0, XTAL_SI_LPS_CAP);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_DRV, 0, XTAL_SI_DRV_LATCH);
+ if (ret)
+ return ret;
+
+ rtw89_write32_set(rtwdev, R_AX_PMC_DBG_CTRL2, B_AX_SYSON_DIS_PMCR_AX_WRMSK);
+ rtw89_write32_set(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_ISO_EB2CORE);
+ rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B15);
+
+ fsleep(1000);
+
+ rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B14);
+ rtw89_write32_clr(rtwdev, R_AX_PMC_DBG_CTRL2, B_AX_SYSON_DIS_PMCR_AX_WRMSK);
+ rtw89_write32_set(rtwdev, R_AX_GPIO0_16_EECS_EESK_LED1_PULL_LOW_EN,
+ B_AX_GPIO10_PULL_LOW_EN | B_AX_GPIO16_PULL_LOW_EN_V1);
+
+ if (rtwdev->hal.cv == CHIP_CAV) {
+ ret = rtw89_read_efuse_ver(rtwdev, &val8);
+ if (!ret)
+ rtwdev->hal.cv = val8;
+ }
+
+ rtw89_write32_clr(rtwdev, R_AX_WLAN_XTAL_SI_CONFIG,
+ B_AX_XTAL_SI_ADDR_NOT_CHK);
+ if (rtwdev->hal.cv != CHIP_CAV) {
+ rtw89_write32_set(rtwdev, R_AX_SPSLDO_ON_CTRL1, B_AX_FPWMDELAY);
+ rtw89_write32_set(rtwdev, R_AX_SPSANA_ON_CTRL1, B_AX_FPWMDELAY);
+ }
+
+ rtw89_write32_set(rtwdev, R_AX_DMAC_FUNC_EN,
+ B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN | B_AX_MPDU_PROC_EN |
+ B_AX_WD_RLS_EN | B_AX_DLE_WDE_EN | B_AX_TXPKT_CTRL_EN |
+ B_AX_STA_SCH_EN | B_AX_DLE_PLE_EN | B_AX_PKT_BUF_EN |
+ B_AX_DMAC_TBL_EN | B_AX_PKT_IN_EN | B_AX_DLE_CPUIO_EN |
+ B_AX_DISPATCHER_EN | B_AX_BBRPT_EN | B_AX_MAC_SEC_EN |
+ B_AX_DMACREG_GCKEN);
+ rtw89_write32_set(rtwdev, R_AX_CMAC_FUNC_EN,
+ B_AX_CMAC_EN | B_AX_CMAC_TXEN | B_AX_CMAC_RXEN |
+ B_AX_FORCE_CMACREG_GCKEN | B_AX_PHYINTF_EN | B_AX_CMAC_DMA_EN |
+ B_AX_PTCLTOP_EN | B_AX_SCHEDULER_EN | B_AX_TMAC_EN |
+ B_AX_RMAC_EN);
+
+ rtw89_write32_mask(rtwdev, R_AX_EECS_EESK_FUNC_SEL, B_AX_PINMUX_EESK_FUNC_SEL_MASK,
+ PINMUX_EESK_FUNC_SEL_BT_LOG);
+
+ return 0;
+}
+
+static void rtw8851b_patch_swr_pfm2pwm(struct rtw89_dev *rtwdev)
+{
+ rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_SOP_PWMM_DSWR);
+ rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_SOP_ASWRM);
+ rtw89_write32_set(rtwdev, R_AX_WLLPS_CTRL, B_AX_LPSOP_DSWRM);
+ rtw89_write32_set(rtwdev, R_AX_WLLPS_CTRL, B_AX_LPSOP_ASWRM);
+}
+
+static int rtw8851b_pwr_off_func(struct rtw89_dev *rtwdev)
+{
+ u32 val32;
+ u32 ret;
+
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_RFC2RF,
+ XTAL_SI_RFC2RF);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_OFF_EI);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_OFF_WEI);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, 0, XTAL_SI_RF00);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_SRAM2RFC,
+ XTAL_SI_SRAM2RFC);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_PON_EI);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_PON_WEI);
+ if (ret)
+ return ret;
+
+ rtw89_write32_set(rtwdev, R_AX_WLAN_XTAL_SI_CONFIG,
+ B_AX_XTAL_SI_ADDR_NOT_CHK);
+ rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_EN_WLON);
+ rtw89_write32_clr(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG);
+ rtw89_write8_clr(rtwdev, R_AX_SYS_FUNC_EN, B_AX_FEN_BB_GLB_RSTN | B_AX_FEN_BBRSTB);
+
+ rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_OFFMAC);
+
+ ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_AX_APFM_OFFMAC),
+ 1000, 20000, false, rtwdev, R_AX_SYS_PW_CTRL);
+ if (ret)
+ return ret;
+
+ rtw89_write32(rtwdev, R_AX_WLLPS_CTRL, SW_LPS_OPTION);
+
+ if (rtwdev->hal.cv == CHIP_CAV) {
+ rtw8851b_patch_swr_pfm2pwm(rtwdev);
+ } else {
+ rtw89_write32_set(rtwdev, R_AX_SPSLDO_ON_CTRL1, B_AX_FPWMDELAY);
+ rtw89_write32_set(rtwdev, R_AX_SPSANA_ON_CTRL1, B_AX_FPWMDELAY);
+ }
+
+ rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS);
+
+ return 0;
+}
+
+static void rtw8851b_efuse_parsing(struct rtw89_efuse *efuse,
+ struct rtw8851b_efuse *map)
+{
+ ether_addr_copy(efuse->addr, map->e.mac_addr);
+ efuse->rfe_type = map->rfe_type;
+ efuse->xtal_cap = map->xtal_k;
+}
+
+static void rtw8851b_efuse_parsing_tssi(struct rtw89_dev *rtwdev,
+ struct rtw8851b_efuse *map)
+{
+ struct rtw89_tssi_info *tssi = &rtwdev->tssi;
+ struct rtw8851b_tssi_offset *ofst[] = {&map->path_a_tssi};
+ u8 i, j;
+
+ tssi->thermal[RF_PATH_A] = map->path_a_therm;
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++) {
+ memcpy(tssi->tssi_cck[i], ofst[i]->cck_tssi,
+ sizeof(ofst[i]->cck_tssi));
+
+ for (j = 0; j < TSSI_CCK_CH_GROUP_NUM; j++)
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][EFUSE] path=%d cck[%d]=0x%x\n",
+ i, j, tssi->tssi_cck[i][j]);
+
+ memcpy(tssi->tssi_mcs[i], ofst[i]->bw40_tssi,
+ sizeof(ofst[i]->bw40_tssi));
+ memcpy(tssi->tssi_mcs[i] + TSSI_MCS_2G_CH_GROUP_NUM,
+ ofst[i]->bw40_1s_tssi_5g, sizeof(ofst[i]->bw40_1s_tssi_5g));
+
+ for (j = 0; j < TSSI_MCS_CH_GROUP_NUM; j++)
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][EFUSE] path=%d mcs[%d]=0x%x\n",
+ i, j, tssi->tssi_mcs[i][j]);
+ }
+}
+
+static bool _decode_efuse_gain(u8 data, s8 *high, s8 *low)
+{
+ if (high)
+ *high = sign_extend32(u8_get_bits(data, GENMASK(7, 4)), 3);
+ if (low)
+ *low = sign_extend32(u8_get_bits(data, GENMASK(3, 0)), 3);
+
+ return data != 0xff;
+}
+
+static void rtw8851b_efuse_parsing_gain_offset(struct rtw89_dev *rtwdev,
+ struct rtw8851b_efuse *map)
+{
+ struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain;
+ bool valid = false;
+
+ valid |= _decode_efuse_gain(map->rx_gain_2g_cck,
+ &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_2G_CCK],
+ NULL);
+ valid |= _decode_efuse_gain(map->rx_gain_2g_ofdm,
+ &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_2G_OFDM],
+ NULL);
+ valid |= _decode_efuse_gain(map->rx_gain_5g_low,
+ &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_5G_LOW],
+ NULL);
+ valid |= _decode_efuse_gain(map->rx_gain_5g_mid,
+ &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_5G_MID],
+ NULL);
+ valid |= _decode_efuse_gain(map->rx_gain_5g_high,
+ &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_5G_HIGH],
+ NULL);
+
+ gain->offset_valid = valid;
+}
+
+static int rtw8851b_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map)
+{
+ struct rtw89_efuse *efuse = &rtwdev->efuse;
+ struct rtw8851b_efuse *map;
+
+ map = (struct rtw8851b_efuse *)log_map;
+
+ efuse->country_code[0] = map->country_code[0];
+ efuse->country_code[1] = map->country_code[1];
+ rtw8851b_efuse_parsing_tssi(rtwdev, map);
+ rtw8851b_efuse_parsing_gain_offset(rtwdev, map);
+
+ switch (rtwdev->hci.type) {
+ case RTW89_HCI_TYPE_PCIE:
+ rtw8851b_efuse_parsing(efuse, map);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type);
+
+ return 0;
+}
+
+static void rtw8851b_phycap_parsing_tssi(struct rtw89_dev *rtwdev, u8 *phycap_map)
+{
+ struct rtw89_tssi_info *tssi = &rtwdev->tssi;
+ static const u32 tssi_trim_addr[RF_PATH_NUM_8851B] = {0x5D6};
+ u32 addr = rtwdev->chip->phycap_addr;
+ bool pg = false;
+ u32 ofst;
+ u8 i, j;
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++) {
+ for (j = 0; j < TSSI_TRIM_CH_GROUP_NUM; j++) {
+ /* addrs are in decreasing order */
+ ofst = tssi_trim_addr[i] - addr - j;
+ tssi->tssi_trim[i][j] = phycap_map[ofst];
+
+ if (phycap_map[ofst] != 0xff)
+ pg = true;
+ }
+ }
+
+ if (!pg) {
+ memset(tssi->tssi_trim, 0, sizeof(tssi->tssi_trim));
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM] no PG, set all trim info to 0\n");
+ }
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++)
+ for (j = 0; j < TSSI_TRIM_CH_GROUP_NUM; j++)
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI] path=%d idx=%d trim=0x%x addr=0x%x\n",
+ i, j, tssi->tssi_trim[i][j],
+ tssi_trim_addr[i] - j);
+}
+
+static void rtw8851b_phycap_parsing_thermal_trim(struct rtw89_dev *rtwdev,
+ u8 *phycap_map)
+{
+ struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+ static const u32 thm_trim_addr[RF_PATH_NUM_8851B] = {0x5DF};
+ u32 addr = rtwdev->chip->phycap_addr;
+ u8 i;
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++) {
+ info->thermal_trim[i] = phycap_map[thm_trim_addr[i] - addr];
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[THERMAL][TRIM] path=%d thermal_trim=0x%x\n",
+ i, info->thermal_trim[i]);
+
+ if (info->thermal_trim[i] != 0xff)
+ info->pg_thermal_trim = true;
+ }
+}
+
+static void rtw8851b_thermal_trim(struct rtw89_dev *rtwdev)
+{
+#define __thm_setting(raw) \
+({ \
+ u8 __v = (raw); \
+ ((__v & 0x1) << 3) | ((__v & 0x1f) >> 1); \
+})
+ struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+ u8 i, val;
+
+ if (!info->pg_thermal_trim) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[THERMAL][TRIM] no PG, do nothing\n");
+
+ return;
+ }
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++) {
+ val = __thm_setting(info->thermal_trim[i]);
+ rtw89_write_rf(rtwdev, i, RR_TM2, RR_TM2_OFF, val);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[THERMAL][TRIM] path=%d thermal_setting=0x%x\n",
+ i, val);
+ }
+#undef __thm_setting
+}
+
+static void rtw8851b_phycap_parsing_pa_bias_trim(struct rtw89_dev *rtwdev,
+ u8 *phycap_map)
+{
+ struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+ static const u32 pabias_trim_addr[] = {0x5DE};
+ u32 addr = rtwdev->chip->phycap_addr;
+ u8 i;
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++) {
+ info->pa_bias_trim[i] = phycap_map[pabias_trim_addr[i] - addr];
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[PA_BIAS][TRIM] path=%d pa_bias_trim=0x%x\n",
+ i, info->pa_bias_trim[i]);
+
+ if (info->pa_bias_trim[i] != 0xff)
+ info->pg_pa_bias_trim = true;
+ }
+}
+
+static void rtw8851b_pa_bias_trim(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+ u8 pabias_2g, pabias_5g;
+ u8 i;
+
+ if (!info->pg_pa_bias_trim) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[PA_BIAS][TRIM] no PG, do nothing\n");
+
+ return;
+ }
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++) {
+ pabias_2g = u8_get_bits(info->pa_bias_trim[i], GENMASK(3, 0));
+ pabias_5g = u8_get_bits(info->pa_bias_trim[i], GENMASK(7, 4));
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[PA_BIAS][TRIM] path=%d 2G=0x%x 5G=0x%x\n",
+ i, pabias_2g, pabias_5g);
+
+ rtw89_write_rf(rtwdev, i, RR_BIASA, RR_BIASA_TXG, pabias_2g);
+ rtw89_write_rf(rtwdev, i, RR_BIASA, RR_BIASA_TXA, pabias_5g);
+ }
+}
+
+static void rtw8851b_phycap_parsing_gain_comp(struct rtw89_dev *rtwdev, u8 *phycap_map)
+{
+ static const u32 comp_addrs[][RTW89_SUBBAND_2GHZ_5GHZ_NR] = {
+ {0x5BB, 0x5BA, 0, 0x5B9, 0x5B8},
+ };
+ struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain;
+ u32 phycap_addr = rtwdev->chip->phycap_addr;
+ bool valid = false;
+ int path, i;
+ u8 data;
+
+ for (path = 0; path < BB_PATH_NUM_8851B; path++)
+ for (i = 0; i < RTW89_SUBBAND_2GHZ_5GHZ_NR; i++) {
+ if (comp_addrs[path][i] == 0)
+ continue;
+
+ data = phycap_map[comp_addrs[path][i] - phycap_addr];
+ valid |= _decode_efuse_gain(data, NULL,
+ &gain->comp[path][i]);
+ }
+
+ gain->comp_valid = valid;
+}
+
+static int rtw8851b_read_phycap(struct rtw89_dev *rtwdev, u8 *phycap_map)
+{
+ rtw8851b_phycap_parsing_tssi(rtwdev, phycap_map);
+ rtw8851b_phycap_parsing_thermal_trim(rtwdev, phycap_map);
+ rtw8851b_phycap_parsing_pa_bias_trim(rtwdev, phycap_map);
+ rtw8851b_phycap_parsing_gain_comp(rtwdev, phycap_map);
+
+ return 0;
+}
+
+static void rtw8851b_set_bb_gpio(struct rtw89_dev *rtwdev, u8 gpio_idx, bool inv,
+ u8 src_sel)
+{
+ u32 addr, mask;
+
+ if (gpio_idx >= 32)
+ return;
+
+ /* 2 continual 32-bit registers for 32 GPIOs, and each GPIO occupies 2 bits */
+ addr = R_RFE_SEL0_A2 + (gpio_idx / 16) * sizeof(u32);
+ mask = B_RFE_SEL0_MASK << (gpio_idx % 16) * 2;
+
+ rtw89_phy_write32_mask(rtwdev, addr, mask, RF_PATH_A);
+ rtw89_phy_write32_mask(rtwdev, R_RFE_INV0, BIT(gpio_idx), inv);
+
+ /* 4 continual 32-bit registers for 32 GPIOs, and each GPIO occupies 4 bits */
+ addr = R_RFE_SEL0_BASE + (gpio_idx / 8) * sizeof(u32);
+ mask = B_RFE_SEL0_SRC_MASK << (gpio_idx % 8) * 4;
+
+ rtw89_phy_write32_mask(rtwdev, addr, mask, src_sel);
+}
+
+static void rtw8851b_set_mac_gpio(struct rtw89_dev *rtwdev, u8 func)
+{
+ static const struct rtw89_reg3_def func16 = {
+ R_AX_GPIO16_23_FUNC_SEL, B_AX_PINMUX_GPIO16_FUNC_SEL_MASK, BIT(3)
+ };
+ static const struct rtw89_reg3_def func17 = {
+ R_AX_GPIO16_23_FUNC_SEL, B_AX_PINMUX_GPIO17_FUNC_SEL_MASK, BIT(7) >> 4,
+ };
+ const struct rtw89_reg3_def *def;
+
+ switch (func) {
+ case 16:
+ def = &func16;
+ break;
+ case 17:
+ def = &func17;
+ break;
+ default:
+ rtw89_warn(rtwdev, "undefined gpio func %d\n", func);
+ return;
+ }
+
+ rtw89_write8_mask(rtwdev, def->addr, def->mask, def->data);
+}
+
+static void rtw8851b_rfe_gpio(struct rtw89_dev *rtwdev)
+{
+ u8 rfe_type = rtwdev->efuse.rfe_type;
+
+ if (rfe_type > 50)
+ return;
+
+ if (rfe_type % 3 == 2) {
+ rtw8851b_set_bb_gpio(rtwdev, 16, true, RFE_SEL0_SRC_ANTSEL_0);
+ rtw8851b_set_bb_gpio(rtwdev, 17, false, RFE_SEL0_SRC_ANTSEL_0);
+
+ rtw8851b_set_mac_gpio(rtwdev, 16);
+ rtw8851b_set_mac_gpio(rtwdev, 17);
+ }
+}
+
+static void rtw8851b_power_trim(struct rtw89_dev *rtwdev)
+{
+ rtw8851b_thermal_trim(rtwdev);
+ rtw8851b_pa_bias_trim(rtwdev);
+}
+
+static void rtw8851b_set_channel_mac(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ u8 mac_idx)
+{
+ u32 sub_carr = rtw89_mac_reg_by_idx(R_AX_TX_SUB_CARRIER_VALUE, mac_idx);
+ u32 chk_rate = rtw89_mac_reg_by_idx(R_AX_TXRATE_CHK, mac_idx);
+ u32 rf_mod = rtw89_mac_reg_by_idx(R_AX_WMAC_RFMOD, mac_idx);
+ u8 txsc20 = 0, txsc40 = 0;
+
+ switch (chan->band_width) {
+ case RTW89_CHANNEL_WIDTH_80:
+ txsc40 = rtw89_phy_get_txsc(rtwdev, chan, RTW89_CHANNEL_WIDTH_40);
+ fallthrough;
+ case RTW89_CHANNEL_WIDTH_40:
+ txsc20 = rtw89_phy_get_txsc(rtwdev, chan, RTW89_CHANNEL_WIDTH_20);
+ break;
+ default:
+ break;
+ }
+
+ switch (chan->band_width) {
+ case RTW89_CHANNEL_WIDTH_80:
+ rtw89_write8_mask(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK, BIT(1));
+ rtw89_write32(rtwdev, sub_carr, txsc20 | (txsc40 << 4));
+ break;
+ case RTW89_CHANNEL_WIDTH_40:
+ rtw89_write8_mask(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK, BIT(0));
+ rtw89_write32(rtwdev, sub_carr, txsc20);
+ break;
+ case RTW89_CHANNEL_WIDTH_20:
+ rtw89_write8_clr(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK);
+ rtw89_write32(rtwdev, sub_carr, 0);
+ break;
+ default:
+ break;
+ }
+
+ if (chan->channel > 14) {
+ rtw89_write8_clr(rtwdev, chk_rate, B_AX_BAND_MODE);
+ rtw89_write8_set(rtwdev, chk_rate,
+ B_AX_CHECK_CCK_EN | B_AX_RTS_LIMIT_IN_OFDM6);
+ } else {
+ rtw89_write8_set(rtwdev, chk_rate, B_AX_BAND_MODE);
+ rtw89_write8_clr(rtwdev, chk_rate,
+ B_AX_CHECK_CCK_EN | B_AX_RTS_LIMIT_IN_OFDM6);
+ }
+}
+
+static const u32 rtw8851b_sco_barker_threshold[14] = {
+ 0x1cfea, 0x1d0e1, 0x1d1d7, 0x1d2cd, 0x1d3c3, 0x1d4b9, 0x1d5b0, 0x1d6a6,
+ 0x1d79c, 0x1d892, 0x1d988, 0x1da7f, 0x1db75, 0x1ddc4
+};
+
+static const u32 rtw8851b_sco_cck_threshold[14] = {
+ 0x27de3, 0x27f35, 0x28088, 0x281da, 0x2832d, 0x2847f, 0x285d2, 0x28724,
+ 0x28877, 0x289c9, 0x28b1c, 0x28c6e, 0x28dc1, 0x290ed
+};
+
+static void rtw8851b_ctrl_sco_cck(struct rtw89_dev *rtwdev, u8 primary_ch)
+{
+ u8 ch_element = primary_ch - 1;
+
+ rtw89_phy_write32_mask(rtwdev, R_RXSCOBC, B_RXSCOBC_TH,
+ rtw8851b_sco_barker_threshold[ch_element]);
+ rtw89_phy_write32_mask(rtwdev, R_RXSCOCCK, B_RXSCOCCK_TH,
+ rtw8851b_sco_cck_threshold[ch_element]);
+}
+
+static u8 rtw8851b_sco_mapping(u8 central_ch)
+{
+ if (central_ch == 1)
+ return 109;
+ else if (central_ch >= 2 && central_ch <= 6)
+ return 108;
+ else if (central_ch >= 7 && central_ch <= 10)
+ return 107;
+ else if (central_ch >= 11 && central_ch <= 14)
+ return 106;
+ else if (central_ch == 36 || central_ch == 38)
+ return 51;
+ else if (central_ch >= 40 && central_ch <= 58)
+ return 50;
+ else if (central_ch >= 60 && central_ch <= 64)
+ return 49;
+ else if (central_ch == 100 || central_ch == 102)
+ return 48;
+ else if (central_ch >= 104 && central_ch <= 126)
+ return 47;
+ else if (central_ch >= 128 && central_ch <= 151)
+ return 46;
+ else if (central_ch >= 153 && central_ch <= 177)
+ return 45;
+ else
+ return 0;
+}
+
+struct rtw8851b_bb_gain {
+ u32 gain_g[BB_PATH_NUM_8851B];
+ u32 gain_a[BB_PATH_NUM_8851B];
+ u32 gain_mask;
+};
+
+static const struct rtw8851b_bb_gain bb_gain_lna[LNA_GAIN_NUM] = {
+ { .gain_g = {0x4678}, .gain_a = {0x45DC},
+ .gain_mask = 0x00ff0000 },
+ { .gain_g = {0x4678}, .gain_a = {0x45DC},
+ .gain_mask = 0xff000000 },
+ { .gain_g = {0x467C}, .gain_a = {0x4660},
+ .gain_mask = 0x000000ff },
+ { .gain_g = {0x467C}, .gain_a = {0x4660},
+ .gain_mask = 0x0000ff00 },
+ { .gain_g = {0x467C}, .gain_a = {0x4660},
+ .gain_mask = 0x00ff0000 },
+ { .gain_g = {0x467C}, .gain_a = {0x4660},
+ .gain_mask = 0xff000000 },
+ { .gain_g = {0x4680}, .gain_a = {0x4664},
+ .gain_mask = 0x000000ff },
+};
+
+static const struct rtw8851b_bb_gain bb_gain_tia[TIA_GAIN_NUM] = {
+ { .gain_g = {0x4680}, .gain_a = {0x4664},
+ .gain_mask = 0x00ff0000 },
+ { .gain_g = {0x4680}, .gain_a = {0x4664},
+ .gain_mask = 0xff000000 },
+};
+
+static void rtw8851b_set_gain_error(struct rtw89_dev *rtwdev,
+ enum rtw89_subband subband,
+ enum rtw89_rf_path path)
+{
+ const struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain;
+ u8 gain_band = rtw89_subband_to_bb_gain_band(subband);
+ s32 val;
+ u32 reg;
+ u32 mask;
+ int i;
+
+ for (i = 0; i < LNA_GAIN_NUM; i++) {
+ if (subband == RTW89_CH_2G)
+ reg = bb_gain_lna[i].gain_g[path];
+ else
+ reg = bb_gain_lna[i].gain_a[path];
+
+ mask = bb_gain_lna[i].gain_mask;
+ val = gain->lna_gain[gain_band][path][i];
+ rtw89_phy_write32_mask(rtwdev, reg, mask, val);
+ }
+
+ for (i = 0; i < TIA_GAIN_NUM; i++) {
+ if (subband == RTW89_CH_2G)
+ reg = bb_gain_tia[i].gain_g[path];
+ else
+ reg = bb_gain_tia[i].gain_a[path];
+
+ mask = bb_gain_tia[i].gain_mask;
+ val = gain->tia_gain[gain_band][path][i];
+ rtw89_phy_write32_mask(rtwdev, reg, mask, val);
+ }
+}
+
+static void rtw8851b_set_gain_offset(struct rtw89_dev *rtwdev,
+ enum rtw89_subband subband,
+ enum rtw89_phy_idx phy_idx)
+{
+ static const u32 rssi_ofst_addr[] = {R_PATH0_G_TIA1_LNA6_OP1DB_V1};
+ static const u32 gain_err_addr[] = {R_P0_AGC_RSVD};
+ struct rtw89_phy_efuse_gain *efuse_gain = &rtwdev->efuse_gain;
+ enum rtw89_gain_offset gain_ofdm_band;
+ s32 offset_ofdm, offset_cck;
+ s32 offset_a;
+ s32 tmp;
+ u8 path;
+
+ if (!efuse_gain->comp_valid)
+ goto next;
+
+ for (path = RF_PATH_A; path < BB_PATH_NUM_8851B; path++) {
+ tmp = efuse_gain->comp[path][subband];
+ tmp = clamp_t(s32, tmp << 2, S8_MIN, S8_MAX);
+ rtw89_phy_write32_mask(rtwdev, gain_err_addr[path], MASKBYTE0, tmp);
+ }
+
+next:
+ if (!efuse_gain->offset_valid)
+ return;
+
+ gain_ofdm_band = rtw89_subband_to_gain_offset_band_of_ofdm(subband);
+
+ offset_a = -efuse_gain->offset[RF_PATH_A][gain_ofdm_band];
+
+ tmp = -((offset_a << 2) + (efuse_gain->offset_base[RTW89_PHY_0] >> 2));
+ tmp = clamp_t(s32, tmp, S8_MIN, S8_MAX);
+ rtw89_phy_write32_mask(rtwdev, rssi_ofst_addr[RF_PATH_A], B_PATH0_R_G_OFST_MASK, tmp);
+
+ offset_ofdm = -efuse_gain->offset[RF_PATH_A][gain_ofdm_band];
+ offset_cck = -efuse_gain->offset[RF_PATH_A][0];
+
+ tmp = (offset_ofdm << 4) + efuse_gain->offset_base[RTW89_PHY_0];
+ tmp = clamp_t(s32, tmp, S8_MIN, S8_MAX);
+ rtw89_phy_write32_idx(rtwdev, R_P0_RPL1, B_P0_RPL1_BIAS_MASK, tmp, phy_idx);
+
+ tmp = (offset_ofdm << 4) + efuse_gain->rssi_base[RTW89_PHY_0];
+ tmp = clamp_t(s32, tmp, S8_MIN, S8_MAX);
+ rtw89_phy_write32_idx(rtwdev, R_P1_RPL1, B_P0_RPL1_BIAS_MASK, tmp, phy_idx);
+
+ if (subband == RTW89_CH_2G) {
+ tmp = (offset_cck << 3) + (efuse_gain->offset_base[RTW89_PHY_0] >> 1);
+ tmp = clamp_t(s32, tmp, S8_MIN >> 1, S8_MAX >> 1);
+ rtw89_phy_write32_mask(rtwdev, R_RX_RPL_OFST,
+ B_RX_RPL_OFST_CCK_MASK, tmp);
+ }
+}
+
+static
+void rtw8851b_set_rxsc_rpl_comp(struct rtw89_dev *rtwdev, enum rtw89_subband subband)
+{
+ const struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain;
+ u8 band = rtw89_subband_to_bb_gain_band(subband);
+ u32 val;
+
+ val = u32_encode_bits(gain->rpl_ofst_20[band][RF_PATH_A], B_P0_RPL1_20_MASK) |
+ u32_encode_bits(gain->rpl_ofst_40[band][RF_PATH_A][0], B_P0_RPL1_40_MASK) |
+ u32_encode_bits(gain->rpl_ofst_40[band][RF_PATH_A][1], B_P0_RPL1_41_MASK);
+ val >>= B_P0_RPL1_SHIFT;
+ rtw89_phy_write32_mask(rtwdev, R_P0_RPL1, B_P0_RPL1_MASK, val);
+ rtw89_phy_write32_mask(rtwdev, R_P1_RPL1, B_P0_RPL1_MASK, val);
+
+ val = u32_encode_bits(gain->rpl_ofst_40[band][RF_PATH_A][2], B_P0_RTL2_42_MASK) |
+ u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][0], B_P0_RTL2_80_MASK) |
+ u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][1], B_P0_RTL2_81_MASK) |
+ u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][10], B_P0_RTL2_8A_MASK);
+ rtw89_phy_write32(rtwdev, R_P0_RPL2, val);
+ rtw89_phy_write32(rtwdev, R_P1_RPL2, val);
+
+ val = u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][2], B_P0_RTL3_82_MASK) |
+ u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][3], B_P0_RTL3_83_MASK) |
+ u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][4], B_P0_RTL3_84_MASK) |
+ u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][9], B_P0_RTL3_89_MASK);
+ rtw89_phy_write32(rtwdev, R_P0_RPL3, val);
+ rtw89_phy_write32(rtwdev, R_P1_RPL3, val);
+}
+
+static void rtw8851b_ctrl_ch(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ u8 subband = chan->subband_type;
+ u8 central_ch = chan->channel;
+ bool is_2g = central_ch <= 14;
+ u8 sco_comp;
+
+ if (is_2g)
+ rtw89_phy_write32_idx(rtwdev, R_PATH0_BAND_SEL_V1,
+ B_PATH0_BAND_SEL_MSK_V1, 1, phy_idx);
+ else
+ rtw89_phy_write32_idx(rtwdev, R_PATH0_BAND_SEL_V1,
+ B_PATH0_BAND_SEL_MSK_V1, 0, phy_idx);
+ /* SCO compensate FC setting */
+ sco_comp = rtw8851b_sco_mapping(central_ch);
+ rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_INV, sco_comp, phy_idx);
+
+ if (chan->band_type == RTW89_BAND_6G)
+ return;
+
+ /* CCK parameters */
+ if (central_ch == 14) {
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR0, B_TXFIR_C01, 0x3b13ff);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR2, B_TXFIR_C23, 0x1c42de);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR4, B_TXFIR_C45, 0xfdb0ad);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR6, B_TXFIR_C67, 0xf60f6e);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR8, B_TXFIR_C89, 0xfd8f92);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIRA, B_TXFIR_CAB, 0x2d011);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIRC, B_TXFIR_CCD, 0x1c02c);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIRE, B_TXFIR_CEF, 0xfff00a);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR0, B_TXFIR_C01, 0x3d23ff);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR2, B_TXFIR_C23, 0x29b354);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR4, B_TXFIR_C45, 0xfc1c8);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR6, B_TXFIR_C67, 0xfdb053);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR8, B_TXFIR_C89, 0xf86f9a);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIRA, B_TXFIR_CAB, 0xfaef92);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIRC, B_TXFIR_CCD, 0xfe5fcc);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIRE, B_TXFIR_CEF, 0xffdff5);
+ }
+
+ rtw8851b_set_gain_error(rtwdev, subband, RF_PATH_A);
+ rtw8851b_set_gain_offset(rtwdev, subband, phy_idx);
+ rtw8851b_set_rxsc_rpl_comp(rtwdev, subband);
+}
+
+static void rtw8851b_bw_setting(struct rtw89_dev *rtwdev, u8 bw)
+{
+ rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_CTL, 0x8);
+ rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_EN, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_BW0, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW1, B_P0_CFCH_BW1, 0x4);
+ rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_MUL, 0xf);
+ rtw89_phy_write32_mask(rtwdev, R_ADCMOD, B_ADCMOD_LP, 0xa);
+ rtw89_phy_write32_mask(rtwdev, R_P0_RXCK, B_P0_RXCK_ADJ, 0x92);
+
+ switch (bw) {
+ case RTW89_CHANNEL_WIDTH_5:
+ rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x1);
+ break;
+ case RTW89_CHANNEL_WIDTH_10:
+ rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0);
+ break;
+ case RTW89_CHANNEL_WIDTH_20:
+ rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0);
+ break;
+ case RTW89_CHANNEL_WIDTH_40:
+ rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0);
+ break;
+ case RTW89_CHANNEL_WIDTH_80:
+ rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0);
+ break;
+ default:
+ rtw89_warn(rtwdev, "Fail to set ADC\n");
+ }
+}
+
+static void rtw8851b_ctrl_bw(struct rtw89_dev *rtwdev, u8 pri_ch, u8 bw,
+ enum rtw89_phy_idx phy_idx)
+{
+ switch (bw) {
+ case RTW89_CHANNEL_WIDTH_5:
+ rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x1, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, 0x0, phy_idx);
+ break;
+ case RTW89_CHANNEL_WIDTH_10:
+ rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x2, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, 0x0, phy_idx);
+ break;
+ case RTW89_CHANNEL_WIDTH_20:
+ rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, 0x0, phy_idx);
+ break;
+ case RTW89_CHANNEL_WIDTH_40:
+ rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x1, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH,
+ pri_ch, phy_idx);
+ /* CCK primary channel */
+ if (pri_ch == RTW89_SC_20_UPPER)
+ rtw89_phy_write32_mask(rtwdev, R_RXSC, B_RXSC_EN, 1);
+ else
+ rtw89_phy_write32_mask(rtwdev, R_RXSC, B_RXSC_EN, 0);
+
+ break;
+ case RTW89_CHANNEL_WIDTH_80:
+ rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x2, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH,
+ pri_ch, phy_idx);
+ break;
+ default:
+ rtw89_warn(rtwdev, "Fail to switch bw (bw:%d, pri ch:%d)\n", bw,
+ pri_ch);
+ }
+
+ rtw8851b_bw_setting(rtwdev, bw);
+}
+
+static void rtw8851b_ctrl_cck_en(struct rtw89_dev *rtwdev, bool cck_en)
+{
+ if (cck_en) {
+ rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 0);
+ rtw89_phy_write32_mask(rtwdev, R_PD_ARBITER_OFF,
+ B_PD_ARBITER_OFF, 0);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK_ADC, B_ENABLE_CCK, 1);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 1);
+ rtw89_phy_write32_mask(rtwdev, R_PD_ARBITER_OFF,
+ B_PD_ARBITER_OFF, 1);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK_ADC, B_ENABLE_CCK, 0);
+ }
+}
+
+static u32 rtw8851b_spur_freq(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan)
+{
+ u8 center_chan = chan->channel;
+
+ switch (chan->band_type) {
+ case RTW89_BAND_5G:
+ if (center_chan == 151 || center_chan == 153 ||
+ center_chan == 155 || center_chan == 163)
+ return 5760;
+ else if (center_chan == 54 || center_chan == 58)
+ return 5280;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+#define CARRIER_SPACING_312_5 312500 /* 312.5 kHz */
+#define CARRIER_SPACING_78_125 78125 /* 78.125 kHz */
+#define MAX_TONE_NUM 2048
+
+static void rtw8851b_set_csi_tone_idx(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ u32 spur_freq;
+ s32 freq_diff, csi_idx, csi_tone_idx;
+
+ spur_freq = rtw8851b_spur_freq(rtwdev, chan);
+ if (spur_freq == 0) {
+ rtw89_phy_write32_idx(rtwdev, R_SEG0CSI_EN_V1, B_SEG0CSI_EN,
+ 0, phy_idx);
+ return;
+ }
+
+ freq_diff = (spur_freq - chan->freq) * 1000000;
+ csi_idx = s32_div_u32_round_closest(freq_diff, CARRIER_SPACING_78_125);
+ s32_div_u32_round_down(csi_idx, MAX_TONE_NUM, &csi_tone_idx);
+
+ rtw89_phy_write32_idx(rtwdev, R_SEG0CSI_V1, B_SEG0CSI_IDX,
+ csi_tone_idx, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_SEG0CSI_EN_V1, B_SEG0CSI_EN, 1, phy_idx);
+}
+
+static const struct rtw89_nbi_reg_def rtw8851b_nbi_reg_def = {
+ .notch1_idx = {0x46E4, 0xFF},
+ .notch1_frac_idx = {0x46E4, 0xC00},
+ .notch1_en = {0x46E4, 0x1000},
+ .notch2_idx = {0x47A4, 0xFF},
+ .notch2_frac_idx = {0x47A4, 0xC00},
+ .notch2_en = {0x47A4, 0x1000},
+};
+
+static void rtw8851b_set_nbi_tone_idx(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan)
+{
+ const struct rtw89_nbi_reg_def *nbi = &rtw8851b_nbi_reg_def;
+ s32 nbi_frac_idx, nbi_frac_tone_idx;
+ s32 nbi_idx, nbi_tone_idx;
+ bool notch2_chk = false;
+ u32 spur_freq, fc;
+ s32 freq_diff;
+
+ spur_freq = rtw8851b_spur_freq(rtwdev, chan);
+ if (spur_freq == 0) {
+ rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr,
+ nbi->notch1_en.mask, 0);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch2_en.addr,
+ nbi->notch2_en.mask, 0);
+ return;
+ }
+
+ fc = chan->freq;
+ if (chan->band_width == RTW89_CHANNEL_WIDTH_160) {
+ fc = (spur_freq > fc) ? fc + 40 : fc - 40;
+ if ((fc > spur_freq &&
+ chan->channel < chan->primary_channel) ||
+ (fc < spur_freq &&
+ chan->channel > chan->primary_channel))
+ notch2_chk = true;
+ }
+
+ freq_diff = (spur_freq - fc) * 1000000;
+ nbi_idx = s32_div_u32_round_down(freq_diff, CARRIER_SPACING_312_5,
+ &nbi_frac_idx);
+
+ if (chan->band_width == RTW89_CHANNEL_WIDTH_20) {
+ s32_div_u32_round_down(nbi_idx + 32, 64, &nbi_tone_idx);
+ } else {
+ u16 tone_para = (chan->band_width == RTW89_CHANNEL_WIDTH_40) ?
+ 128 : 256;
+
+ s32_div_u32_round_down(nbi_idx, tone_para, &nbi_tone_idx);
+ }
+ nbi_frac_tone_idx = s32_div_u32_round_closest(nbi_frac_idx,
+ CARRIER_SPACING_78_125);
+
+ if (chan->band_width == RTW89_CHANNEL_WIDTH_160 && notch2_chk) {
+ rtw89_phy_write32_mask(rtwdev, nbi->notch2_idx.addr,
+ nbi->notch2_idx.mask, nbi_tone_idx);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch2_frac_idx.addr,
+ nbi->notch2_frac_idx.mask, nbi_frac_tone_idx);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch2_en.addr,
+ nbi->notch2_en.mask, 0);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch2_en.addr,
+ nbi->notch2_en.mask, 1);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr,
+ nbi->notch1_en.mask, 0);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, nbi->notch1_idx.addr,
+ nbi->notch1_idx.mask, nbi_tone_idx);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch1_frac_idx.addr,
+ nbi->notch1_frac_idx.mask, nbi_frac_tone_idx);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr,
+ nbi->notch1_en.mask, 0);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr,
+ nbi->notch1_en.mask, 1);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch2_en.addr,
+ nbi->notch2_en.mask, 0);
+ }
+}
+
+static void rtw8851b_set_cfr(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan)
+{
+ if (chan->band_type == RTW89_BAND_2G &&
+ chan->band_width == RTW89_CHANNEL_WIDTH_20 &&
+ (chan->channel == 1 || chan->channel == 13)) {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_CFR,
+ B_PATH0_TX_CFR_LGC0, 0xf8);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_CFR,
+ B_PATH0_TX_CFR_LGC1, 0x120);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_POLAR_CLIPPING,
+ B_PATH0_TX_POLAR_CLIPPING_LGC0, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_POLAR_CLIPPING,
+ B_PATH0_TX_POLAR_CLIPPING_LGC1, 0x3);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_CFR,
+ B_PATH0_TX_CFR_LGC0, 0x120);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_CFR,
+ B_PATH0_TX_CFR_LGC1, 0x3ff);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_POLAR_CLIPPING,
+ B_PATH0_TX_POLAR_CLIPPING_LGC0, 0x3);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_POLAR_CLIPPING,
+ B_PATH0_TX_POLAR_CLIPPING_LGC1, 0x7);
+ }
+}
+
+static void rtw8851b_5m_mask(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ u8 pri_ch = chan->pri_ch_idx;
+ bool mask_5m_low;
+ bool mask_5m_en;
+
+ switch (chan->band_width) {
+ case RTW89_CHANNEL_WIDTH_40:
+ /* Prich=1: Mask 5M High, Prich=2: Mask 5M Low */
+ mask_5m_en = true;
+ mask_5m_low = pri_ch == RTW89_SC_20_LOWER;
+ break;
+ case RTW89_CHANNEL_WIDTH_80:
+ /* Prich=3: Mask 5M High, Prich=4: Mask 5M Low, Else: Disable */
+ mask_5m_en = pri_ch == RTW89_SC_20_UPMOST ||
+ pri_ch == RTW89_SC_20_LOWEST;
+ mask_5m_low = pri_ch == RTW89_SC_20_LOWEST;
+ break;
+ default:
+ mask_5m_en = false;
+ break;
+ }
+
+ if (!mask_5m_en) {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_EN, 0x0);
+ rtw89_phy_write32_idx(rtwdev, R_ASSIGN_SBD_OPT_V1,
+ B_ASSIGN_SBD_OPT_EN_V1, 0x0, phy_idx);
+ return;
+ }
+
+ if (mask_5m_low) {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_TH, 0x5);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_EN, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB2, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB0, 0x1);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_TH, 0x5);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_EN, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB2, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB0, 0x0);
+ }
+ rtw89_phy_write32_idx(rtwdev, R_ASSIGN_SBD_OPT_V1,
+ B_ASSIGN_SBD_OPT_EN_V1, 0x1, phy_idx);
+}
+
+static void rtw8851b_bb_reset_all(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS, B_S0_HW_SI_DIS_W_R_TRIG, 0x7, phy_idx);
+ fsleep(1);
+ rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 1, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS, B_S0_HW_SI_DIS_W_R_TRIG, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 1, phy_idx);
+}
+
+static void rtw8851b_bb_reset_en(struct rtw89_dev *rtwdev, enum rtw89_band band,
+ enum rtw89_phy_idx phy_idx, bool en)
+{
+ if (en) {
+ rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS,
+ B_S0_HW_SI_DIS_W_R_TRIG, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 1, phy_idx);
+ if (band == RTW89_BAND_2G)
+ rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_PD_CTRL, B_PD_HIT_DIS, 0x0);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_PD_CTRL, B_PD_HIT_DIS, 0x1);
+ rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS,
+ B_S0_HW_SI_DIS_W_R_TRIG, 0x7, phy_idx);
+ fsleep(1);
+ rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 0, phy_idx);
+ }
+}
+
+static void rtw8851b_bb_reset(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx)
+{
+ rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB,
+ B_P0_TXPW_RSTB_MANON | B_P0_TXPW_RSTB_TSSI, 0x1);
+ rtw89_phy_write32_set(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_TRK_EN);
+ rtw8851b_bb_reset_all(rtwdev, phy_idx);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB,
+ B_P0_TXPW_RSTB_MANON | B_P0_TXPW_RSTB_TSSI, 0x3);
+ rtw89_phy_write32_clr(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_TRK_EN);
+}
+
+static
+void rtw8851b_bb_gpio_trsw(struct rtw89_dev *rtwdev, enum rtw89_rf_path path,
+ u8 tx_path_en, u8 trsw_tx,
+ u8 trsw_rx, u8 trsw_a, u8 trsw_b)
+{
+ u32 mask_ofst = 16;
+ u32 val;
+
+ if (path != RF_PATH_A)
+ return;
+
+ mask_ofst += (tx_path_en * 4 + trsw_tx * 2 + trsw_rx) * 2;
+ val = u32_encode_bits(trsw_a, B_P0_TRSW_A) |
+ u32_encode_bits(trsw_b, B_P0_TRSW_B);
+
+ rtw89_phy_write32_mask(rtwdev, R_P0_TRSW,
+ (B_P0_TRSW_A | B_P0_TRSW_B) << mask_ofst, val);
+}
+
+static void rtw8851b_bb_gpio_init(struct rtw89_dev *rtwdev)
+{
+ rtw89_phy_write32_set(rtwdev, R_P0_TRSW, B_P0_TRSW_A);
+ rtw89_phy_write32_clr(rtwdev, R_P0_TRSW, B_P0_TRSW_X);
+ rtw89_phy_write32_clr(rtwdev, R_P0_TRSW, B_P0_TRSW_SO_A2);
+ rtw89_phy_write32(rtwdev, R_RFE_SEL0_BASE, 0x77777777);
+ rtw89_phy_write32(rtwdev, R_RFE_SEL32_BASE, 0x77777777);
+
+ rtw89_phy_write32(rtwdev, R_RFE_E_A2, 0xffffffff);
+ rtw89_phy_write32(rtwdev, R_RFE_O_SEL_A2, 0);
+ rtw89_phy_write32(rtwdev, R_RFE_SEL0_A2, 0);
+ rtw89_phy_write32(rtwdev, R_RFE_SEL32_A2, 0);
+
+ rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 0, 0, 0, 0, 1);
+ rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 0, 0, 1, 1, 0);
+ rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 0, 1, 0, 1, 0);
+ rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 0, 1, 1, 1, 0);
+ rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 1, 0, 0, 0, 1);
+ rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 1, 0, 1, 1, 0);
+ rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 1, 1, 0, 1, 0);
+ rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 1, 1, 1, 1, 0);
+}
+
+static void rtw8851b_bb_macid_ctrl_init(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx)
+{
+ u32 addr;
+
+ for (addr = R_AX_PWR_MACID_LMT_TABLE0;
+ addr <= R_AX_PWR_MACID_LMT_TABLE127; addr += 4)
+ rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, 0);
+}
+
+static void rtw8851b_bb_sethw(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain;
+
+ rtw89_phy_write32_clr(rtwdev, R_P0_EN_SOUND_WO_NDP, B_P0_EN_SOUND_WO_NDP);
+
+ rtw8851b_bb_macid_ctrl_init(rtwdev, RTW89_PHY_0);
+ rtw8851b_bb_gpio_init(rtwdev);
+
+ rtw89_write32_clr(rtwdev, R_AX_PWR_NORM_FORCE1, B_AX_FORCE_NTX_VALUE);
+ rtw89_write32_set(rtwdev, R_AX_PWR_NORM_FORCE1, B_AX_FORCE_NTX_EN);
+
+ /* read these registers after loading BB parameters */
+ gain->offset_base[RTW89_PHY_0] =
+ rtw89_phy_read32_mask(rtwdev, R_P0_RPL1, B_P0_RPL1_BIAS_MASK);
+ gain->rssi_base[RTW89_PHY_0] =
+ rtw89_phy_read32_mask(rtwdev, R_P1_RPL1, B_P0_RPL1_BIAS_MASK);
+}
+
+static void rtw8851b_set_channel_bb(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ u8 band = chan->band_type, chan_idx;
+ bool cck_en = chan->channel <= 14;
+ u8 pri_ch_idx = chan->pri_ch_idx;
+
+ if (cck_en)
+ rtw8851b_ctrl_sco_cck(rtwdev, chan->primary_channel);
+
+ rtw8851b_ctrl_ch(rtwdev, chan, phy_idx);
+ rtw8851b_ctrl_bw(rtwdev, pri_ch_idx, chan->band_width, phy_idx);
+ rtw8851b_ctrl_cck_en(rtwdev, cck_en);
+ rtw8851b_set_nbi_tone_idx(rtwdev, chan);
+ rtw8851b_set_csi_tone_idx(rtwdev, chan, phy_idx);
+
+ if (chan->band_type == RTW89_BAND_5G) {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_SHARE_V1,
+ B_PATH0_BT_SHARE_V1, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_BTG_PATH_V1,
+ B_PATH0_BTG_PATH_V1, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CHBW_MOD_V1, B_BT_SHARE, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_BT_SEG0, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_BT_DYN_DC_EST_EN_V1,
+ B_BT_DYN_DC_EST_EN_MSK, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_GNT_BT_WGT_EN, B_GNT_BT_WGT_EN, 0x0);
+ }
+
+ chan_idx = rtw89_encode_chan_idx(rtwdev, chan->primary_channel, band);
+ rtw89_phy_write32_mask(rtwdev, R_MAC_PIN_SEL, B_CH_IDX_SEG0, chan_idx);
+ rtw8851b_5m_mask(rtwdev, chan, phy_idx);
+ rtw8851b_set_cfr(rtwdev, chan);
+ rtw8851b_bb_reset_all(rtwdev, phy_idx);
+}
+
+static void rtw8851b_set_channel(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_mac_idx mac_idx,
+ enum rtw89_phy_idx phy_idx)
+{
+ rtw8851b_set_channel_mac(rtwdev, chan, mac_idx);
+ rtw8851b_set_channel_bb(rtwdev, chan, phy_idx);
+ rtw8851b_set_channel_rf(rtwdev, chan, phy_idx);
+}
+
+static void rtw8851b_tssi_cont_en(struct rtw89_dev *rtwdev, bool en,
+ enum rtw89_rf_path path)
+{
+ if (en) {
+ rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, B_P0_TXPW_RSTB_MANON, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_TRK_EN, 0x0);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, B_P0_TXPW_RSTB_MANON, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_TRK_EN, 0x1);
+ }
+}
+
+static void rtw8851b_tssi_cont_en_phyidx(struct rtw89_dev *rtwdev, bool en,
+ u8 phy_idx)
+{
+ rtw8851b_tssi_cont_en(rtwdev, en, RF_PATH_A);
+}
+
+static void rtw8851b_adc_en(struct rtw89_dev *rtwdev, bool en)
+{
+ if (en)
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0x0);
+ else
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0xf);
+}
+
+static void rtw8851b_set_channel_help(struct rtw89_dev *rtwdev, bool enter,
+ struct rtw89_channel_help_params *p,
+ const struct rtw89_chan *chan,
+ enum rtw89_mac_idx mac_idx,
+ enum rtw89_phy_idx phy_idx)
+{
+ if (enter) {
+ rtw89_chip_stop_sch_tx(rtwdev, RTW89_MAC_0, &p->tx_en, RTW89_SCH_TX_SEL_ALL);
+ rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, false);
+ rtw8851b_tssi_cont_en_phyidx(rtwdev, false, RTW89_PHY_0);
+ rtw8851b_adc_en(rtwdev, false);
+ fsleep(40);
+ rtw8851b_bb_reset_en(rtwdev, chan->band_type, phy_idx, false);
+ } else {
+ rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true);
+ rtw8851b_adc_en(rtwdev, true);
+ rtw8851b_tssi_cont_en_phyidx(rtwdev, true, RTW89_PHY_0);
+ rtw8851b_bb_reset_en(rtwdev, chan->band_type, phy_idx, true);
+ rtw89_chip_resume_sch_tx(rtwdev, RTW89_MAC_0, p->tx_en);
+ }
+}
+
+static void rtw8851b_rfk_init(struct rtw89_dev *rtwdev)
+{
+ rtwdev->is_tssi_mode[RF_PATH_A] = false;
+ rtwdev->is_tssi_mode[RF_PATH_B] = false;
+ rtw8851b_lck_init(rtwdev);
+
+ rtw8851b_dpk_init(rtwdev);
+ rtw8851b_aack(rtwdev);
+ rtw8851b_rck(rtwdev);
+ rtw8851b_dack(rtwdev);
+ rtw8851b_rx_dck(rtwdev, RTW89_PHY_0);
+}
+
+static void rtw8851b_rfk_channel(struct rtw89_dev *rtwdev)
+{
+ enum rtw89_phy_idx phy_idx = RTW89_PHY_0;
+
+ rtw8851b_rx_dck(rtwdev, phy_idx);
+ rtw8851b_iqk(rtwdev, phy_idx);
+ rtw8851b_tssi(rtwdev, phy_idx, true);
+ rtw8851b_dpk(rtwdev, phy_idx);
+}
+
+static void rtw8851b_rfk_band_changed(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx)
+{
+ rtw8851b_tssi_scan(rtwdev, phy_idx);
+}
+
+static void rtw8851b_rfk_scan(struct rtw89_dev *rtwdev, bool start)
+{
+ rtw8851b_wifi_scan_notify(rtwdev, start, RTW89_PHY_0);
+}
+
+static void rtw8851b_rfk_track(struct rtw89_dev *rtwdev)
+{
+ rtw8851b_dpk_track(rtwdev);
+ rtw8851b_lck_track(rtwdev);
+}
+
+static u32 rtw8851b_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx, s16 ref)
+{
+ const u16 tssi_16dbm_cw = 0x12c;
+ const u8 base_cw_0db = 0x27;
+ const s8 ofst_int = 0;
+ s16 pwr_s10_3;
+ s16 rf_pwr_cw;
+ u16 bb_pwr_cw;
+ u32 pwr_cw;
+ u32 tssi_ofst_cw;
+
+ pwr_s10_3 = (ref << 1) + (s16)(ofst_int) + (s16)(base_cw_0db << 3);
+ bb_pwr_cw = u16_get_bits(pwr_s10_3, GENMASK(2, 0));
+ rf_pwr_cw = u16_get_bits(pwr_s10_3, GENMASK(8, 3));
+ rf_pwr_cw = clamp_t(s16, rf_pwr_cw, 15, 63);
+ pwr_cw = (rf_pwr_cw << 3) | bb_pwr_cw;
+
+ tssi_ofst_cw = (u32)((s16)tssi_16dbm_cw + (ref << 1) - (16 << 3));
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
+ "[TXPWR] tssi_ofst_cw=%d rf_cw=0x%x bb_cw=0x%x\n",
+ tssi_ofst_cw, rf_pwr_cw, bb_pwr_cw);
+
+ return u32_encode_bits(tssi_ofst_cw, B_DPD_TSSI_CW) |
+ u32_encode_bits(pwr_cw, B_DPD_PWR_CW) |
+ u32_encode_bits(ref, B_DPD_REF);
+}
+
+static void rtw8851b_set_txpwr_ref(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx)
+{
+ static const u32 addr[RF_PATH_NUM_8851B] = {0x5800};
+ const u32 mask = B_DPD_TSSI_CW | B_DPD_PWR_CW | B_DPD_REF;
+ const u8 ofst_ofdm = 0x4;
+ const u8 ofst_cck = 0x8;
+ const s16 ref_ofdm = 0;
+ const s16 ref_cck = 0;
+ u32 val;
+ u8 i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set txpwr reference\n");
+
+ rtw89_mac_txpwr_write32_mask(rtwdev, phy_idx, R_AX_PWR_RATE_CTRL,
+ B_AX_PWR_REF, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb ofdm txpwr ref\n");
+ val = rtw8851b_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_ofdm);
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++)
+ rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_ofdm, mask, val,
+ phy_idx);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb cck txpwr ref\n");
+ val = rtw8851b_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_cck);
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++)
+ rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_cck, mask, val,
+ phy_idx);
+}
+
+static void rtw8851b_bb_set_tx_shape_dfir(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ u8 tx_shape_idx,
+ enum rtw89_phy_idx phy_idx)
+{
+#define __DFIR_CFG_ADDR(i) (R_TXFIR0 + ((i) << 2))
+#define __DFIR_CFG_MASK 0xffffffff
+#define __DFIR_CFG_NR 8
+#define __DECL_DFIR_PARAM(_name, _val...) \
+ static const u32 param_ ## _name[] = {_val}; \
+ static_assert(ARRAY_SIZE(param_ ## _name) == __DFIR_CFG_NR)
+
+ __DECL_DFIR_PARAM(flat,
+ 0x023D23FF, 0x0029B354, 0x000FC1C8, 0x00FDB053,
+ 0x00F86F9A, 0x06FAEF92, 0x00FE5FCC, 0x00FFDFF5);
+ __DECL_DFIR_PARAM(sharp,
+ 0x023D83FF, 0x002C636A, 0x0013F204, 0x00008090,
+ 0x00F87FB0, 0x06F99F83, 0x00FDBFBA, 0x00003FF5);
+ __DECL_DFIR_PARAM(sharp_14,
+ 0x023B13FF, 0x001C42DE, 0x00FDB0AD, 0x00F60F6E,
+ 0x00FD8F92, 0x0602D011, 0x0001C02C, 0x00FFF00A);
+ u8 ch = chan->channel;
+ const u32 *param;
+ u32 addr;
+ int i;
+
+ if (ch > 14) {
+ rtw89_warn(rtwdev,
+ "set tx shape dfir by unknown ch: %d on 2G\n", ch);
+ return;
+ }
+
+ if (ch == 14)
+ param = param_sharp_14;
+ else
+ param = tx_shape_idx == 0 ? param_flat : param_sharp;
+
+ for (i = 0; i < __DFIR_CFG_NR; i++) {
+ addr = __DFIR_CFG_ADDR(i);
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
+ "set tx shape dfir: 0x%x: 0x%x\n", addr, param[i]);
+ rtw89_phy_write32_idx(rtwdev, addr, __DFIR_CFG_MASK, param[i],
+ phy_idx);
+ }
+
+#undef __DECL_DFIR_PARAM
+#undef __DFIR_CFG_NR
+#undef __DFIR_CFG_MASK
+#undef __DECL_CFG_ADDR
+}
+
+static void rtw8851b_set_tx_shape(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ u8 band = chan->band_type;
+ u8 regd = rtw89_regd_get(rtwdev, band);
+ u8 tx_shape_cck = rtw89_8851b_tx_shape[band][RTW89_RS_CCK][regd];
+ u8 tx_shape_ofdm = rtw89_8851b_tx_shape[band][RTW89_RS_OFDM][regd];
+
+ if (band == RTW89_BAND_2G)
+ rtw8851b_bb_set_tx_shape_dfir(rtwdev, chan, tx_shape_cck, phy_idx);
+
+ rtw89_phy_write32_mask(rtwdev, R_DCFO_OPT, B_TXSHAPE_TRIANGULAR_CFG,
+ tx_shape_ofdm);
+}
+
+static void rtw8851b_set_txpwr(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ rtw89_phy_set_txpwr_byrate(rtwdev, chan, phy_idx);
+ rtw89_phy_set_txpwr_offset(rtwdev, chan, phy_idx);
+ rtw8851b_set_tx_shape(rtwdev, chan, phy_idx);
+ rtw89_phy_set_txpwr_limit(rtwdev, chan, phy_idx);
+ rtw89_phy_set_txpwr_limit_ru(rtwdev, chan, phy_idx);
+}
+
+static void rtw8851b_set_txpwr_ctrl(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx)
+{
+ rtw8851b_set_txpwr_ref(rtwdev, phy_idx);
+}
+
+static
+void rtw8851b_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
+ s8 pw_ofst, enum rtw89_mac_idx mac_idx)
+{
+ u32 reg;
+
+ if (pw_ofst < -16 || pw_ofst > 15) {
+ rtw89_warn(rtwdev, "[ULTB] Err pwr_offset=%d\n", pw_ofst);
+ return;
+ }
+
+ reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_CTRL, mac_idx);
+ rtw89_write32_set(rtwdev, reg, B_AX_PWR_UL_TB_CTRL_EN);
+
+ reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_1T, mac_idx);
+ rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_MASK, pw_ofst);
+
+ pw_ofst = max_t(s8, pw_ofst - 3, -16);
+ reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_2T, mac_idx);
+ rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_MASK, pw_ofst);
+}
+
+static int
+rtw8851b_init_txpwr_unit(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ int ret;
+
+ ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_UL_CTRL2, 0x07763333);
+ if (ret)
+ return ret;
+
+ ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_COEXT_CTRL, 0x01ebf000);
+ if (ret)
+ return ret;
+
+ ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_UL_CTRL0, 0x0002f8ff);
+ if (ret)
+ return ret;
+
+ rtw8851b_set_txpwr_ul_tb_offset(rtwdev, 0, phy_idx == RTW89_PHY_1 ?
+ RTW89_MAC_1 : RTW89_MAC_0);
+
+ return 0;
+}
+
+static void rtw8851b_bb_ctrl_btc_preagc(struct rtw89_dev *rtwdev, bool bt_en)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+
+ rtw89_phy_write_reg3_tbl(rtwdev, bt_en ? &rtw8851b_btc_preagc_en_defs_tbl :
+ &rtw8851b_btc_preagc_dis_defs_tbl);
+
+ if (!bt_en) {
+ if (chan->band_type == RTW89_BAND_2G) {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1,
+ B_PATH0_G_LNA6_OP1DB_V1, 0x20);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1,
+ B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x30);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1,
+ B_PATH0_G_LNA6_OP1DB_V1, 0x1a);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1,
+ B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x2a);
+ }
+ }
+}
+
+static void rtw8851b_ctrl_btg(struct rtw89_dev *rtwdev, bool btg)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+
+ if (btg) {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_SHARE_V1,
+ B_PATH0_BT_SHARE_V1, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_BTG_PATH_V1,
+ B_PATH0_BTG_PATH_V1, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1,
+ B_PATH0_G_LNA6_OP1DB_V1, 0x20);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1,
+ B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x30);
+ rtw89_phy_write32_mask(rtwdev, R_PMAC_GNT, B_PMAC_GNT_P1, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CHBW_MOD_V1, B_BT_SHARE, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_BT_SEG0, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_BT_DYN_DC_EST_EN_V1,
+ B_BT_DYN_DC_EST_EN_MSK, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_GNT_BT_WGT_EN, B_GNT_BT_WGT_EN, 0x1);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_SHARE_V1,
+ B_PATH0_BT_SHARE_V1, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_BTG_PATH_V1,
+ B_PATH0_BTG_PATH_V1, 0x0);
+ if (chan->band_type == RTW89_BAND_2G) {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1,
+ B_PATH0_G_LNA6_OP1DB_V1, 0x80);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1,
+ B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x80);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1,
+ B_PATH0_G_LNA6_OP1DB_V1, 0x1a);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1,
+ B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x2a);
+ }
+ rtw89_phy_write32_mask(rtwdev, R_PMAC_GNT, B_PMAC_GNT_P1, 0xc);
+ rtw89_phy_write32_mask(rtwdev, R_CHBW_MOD_V1, B_BT_SHARE, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_BT_SEG0, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_BT_DYN_DC_EST_EN_V1,
+ B_BT_DYN_DC_EST_EN_MSK, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_GNT_BT_WGT_EN, B_GNT_BT_WGT_EN, 0x0);
+ }
+}
+
+static void rtw8851b_bb_ctrl_rx_path(struct rtw89_dev *rtwdev,
+ enum rtw89_rf_path_bit rx_path)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ u32 rst_mask0;
+
+ if (rx_path == RF_A) {
+ rtw89_phy_write32_mask(rtwdev, R_CHBW_MOD_V1, B_ANT_RX_SEG0, 1);
+ rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_1RCCA_SEG0, 1);
+ rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_1RCCA_SEG1, 1);
+ rtw89_phy_write32_mask(rtwdev, R_RXHT_MCS_LIMIT, B_RXHT_MCS_LIMIT, 0);
+ rtw89_phy_write32_mask(rtwdev, R_RXVHT_MCS_LIMIT, B_RXVHT_MCS_LIMIT, 0);
+ rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_USER_MAX, 4);
+ rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_MAX_NSS, 0);
+ rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHETB_MAX_NSS, 0);
+ }
+
+ rtw8851b_set_gain_offset(rtwdev, chan->subband_type, RTW89_PHY_0);
+
+ rst_mask0 = B_P0_TXPW_RSTB_MANON | B_P0_TXPW_RSTB_TSSI;
+ if (rx_path == RF_A) {
+ rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, rst_mask0, 1);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, rst_mask0, 3);
+ }
+}
+
+static void rtw8851b_bb_cfg_txrx_path(struct rtw89_dev *rtwdev)
+{
+ rtw8851b_bb_ctrl_rx_path(rtwdev, RF_A);
+
+ if (rtwdev->hal.rx_nss == 1) {
+ rtw89_phy_write32_mask(rtwdev, R_RXHT_MCS_LIMIT, B_RXHT_MCS_LIMIT, 0);
+ rtw89_phy_write32_mask(rtwdev, R_RXVHT_MCS_LIMIT, B_RXVHT_MCS_LIMIT, 0);
+ rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_MAX_NSS, 0);
+ rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHETB_MAX_NSS, 0);
+ }
+
+ rtw89_phy_write32_idx(rtwdev, R_MAC_SEL, B_MAC_SEL_MOD, 0x0, RTW89_PHY_0);
+}
+
+static u8 rtw8851b_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path)
+{
+ if (rtwdev->is_tssi_mode[rf_path]) {
+ u32 addr = R_TSSI_THER + (rf_path << 13);
+
+ return rtw89_phy_read32_mask(rtwdev, addr, B_TSSI_THER);
+ }
+
+ rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x1);
+ rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x0);
+ rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x1);
+
+ fsleep(200);
+
+ return rtw89_read_rf(rtwdev, rf_path, RR_TM, RR_TM_VAL);
+}
+
+static void rtw8851b_btc_set_rfe(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_module *module = &btc->mdinfo;
+
+ module->rfe_type = rtwdev->efuse.rfe_type;
+ module->cv = rtwdev->hal.cv;
+ module->bt_solo = 0;
+ module->switch_type = BTC_SWITCH_INTERNAL;
+ module->ant.isolation = 10;
+ module->kt_ver_adie = rtwdev->hal.acv;
+
+ if (module->rfe_type == 0)
+ return;
+
+ /* rfe_type 3*n+1: 1-Ant(shared),
+ * 3*n+2: 2-Ant+Div(non-shared),
+ * 3*n+3: 2-Ant+no-Div(non-shared)
+ */
+ module->ant.num = (module->rfe_type % 3 == 1) ? 1 : 2;
+ /* WL-1ss at S0, btg at s0 (On 1 WL RF) */
+ module->ant.single_pos = RF_PATH_A;
+ module->ant.btg_pos = RF_PATH_A;
+ module->ant.stream_cnt = 1;
+
+ if (module->ant.num == 1) {
+ module->ant.type = BTC_ANT_SHARED;
+ module->bt_pos = BTC_BT_BTG;
+ module->wa_type = 1;
+ module->ant.diversity = 0;
+ } else { /* ant.num == 2 */
+ module->ant.type = BTC_ANT_DEDICATED;
+ module->bt_pos = BTC_BT_ALONE;
+ module->switch_type = BTC_SWITCH_EXTERNAL;
+ module->wa_type = 0;
+ if (module->rfe_type % 3 == 2)
+ module->ant.diversity = 1;
+ }
+}
+
+static
+void rtw8851b_set_trx_mask(struct rtw89_dev *rtwdev, u8 path, u8 group, u32 val)
+{
+ if (group > BTC_BT_SS_GROUP)
+ group--; /* Tx-group=1, Rx-group=2 */
+
+ if (rtwdev->btc.mdinfo.ant.type == BTC_ANT_SHARED) /* 1-Ant */
+ group += 3;
+
+ rtw89_write_rf(rtwdev, path, RR_LUTWA, RFREG_MASK, group);
+ rtw89_write_rf(rtwdev, path, RR_LUTWD0, RFREG_MASK, val);
+}
+
+static void rtw8851b_btc_init_cfg(struct rtw89_dev *rtwdev)
+{
+ static const struct rtw89_mac_ax_coex coex_params = {
+ .pta_mode = RTW89_MAC_AX_COEX_RTK_MODE,
+ .direction = RTW89_MAC_AX_COEX_INNER,
+ };
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_module *module = &btc->mdinfo;
+ struct rtw89_btc_ant_info *ant = &module->ant;
+ u8 path, path_min, path_max;
+
+ /* PTA init */
+ rtw89_mac_coex_init(rtwdev, &coex_params);
+
+ /* set WL Tx response = Hi-Pri */
+ chip->ops->btc_set_wl_pri(rtwdev, BTC_PRI_MASK_TX_RESP, true);
+ chip->ops->btc_set_wl_pri(rtwdev, BTC_PRI_MASK_BEACON, true);
+
+ /* for 1-Ant && 1-ss case: only 1-path */
+ if (ant->stream_cnt == 1) {
+ path_min = ant->single_pos;
+ path_max = path_min;
+ } else {
+ path_min = RF_PATH_A;
+ path_max = RF_PATH_B;
+ }
+
+ for (path = path_min; path <= path_max; path++) {
+ /* set rf gnt-debug off */
+ rtw89_write_rf(rtwdev, path, RR_WLSEL, RFREG_MASK, 0x0);
+
+ /* set DEBUG_LUT_RFMODE_MASK = 1 to start trx-mask-setup */
+ rtw89_write_rf(rtwdev, path, RR_LUTWE, RFREG_MASK, BIT(17));
+
+ /* if GNT_WL=0 && BT=SS_group --> WL Tx/Rx = THRU */
+ rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_SS_GROUP, 0x5ff);
+
+ /* if GNT_WL=0 && BT=Rx_group --> WL-Rx = THRU + WL-Tx = MASK */
+ rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_RX_GROUP, 0x5df);
+
+ /* if GNT_WL = 0 && BT = Tx_group -->
+ * Shared-Ant && BTG-path:WL mask(0x55f), others:WL THRU(0x5ff)
+ */
+ if (ant->type == BTC_ANT_SHARED && ant->btg_pos == path)
+ rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_TX_GROUP, 0x55f);
+ else
+ rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_TX_GROUP, 0x5ff);
+
+ /* set DEBUG_LUT_RFMODE_MASK = 0 to stop trx-mask-setup */
+ rtw89_write_rf(rtwdev, path, RR_LUTWE, RFREG_MASK, 0);
+ }
+
+ /* set PTA break table */
+ rtw89_write32(rtwdev, R_BTC_BREAK_TABLE, BTC_BREAK_PARAM);
+
+ /* enable BT counter 0xda40[16,2] = 2b'11 */
+ rtw89_write32_set(rtwdev, R_AX_CSR_MODE, B_AX_BT_CNT_RST | B_AX_STATIS_BT_EN);
+
+ btc->cx.wl.status.map.init_ok = true;
+}
+
+static
+void rtw8851b_btc_set_wl_pri(struct rtw89_dev *rtwdev, u8 map, bool state)
+{
+ u32 bitmap;
+ u32 reg;
+
+ switch (map) {
+ case BTC_PRI_MASK_TX_RESP:
+ reg = R_BTC_BT_COEX_MSK_TABLE;
+ bitmap = B_BTC_PRI_MASK_TX_RESP_V1;
+ break;
+ case BTC_PRI_MASK_BEACON:
+ reg = R_AX_WL_PRI_MSK;
+ bitmap = B_AX_PTA_WL_PRI_MASK_BCNQ;
+ break;
+ case BTC_PRI_MASK_RX_CCK:
+ reg = R_BTC_BT_COEX_MSK_TABLE;
+ bitmap = B_BTC_PRI_MASK_RXCCK_V1;
+ break;
+ default:
+ return;
+ }
+
+ if (state)
+ rtw89_write32_set(rtwdev, reg, bitmap);
+ else
+ rtw89_write32_clr(rtwdev, reg, bitmap);
+}
+
+union rtw8851b_btc_wl_txpwr_ctrl {
+ u32 txpwr_val;
+ struct {
+ union {
+ u16 ctrl_all_time;
+ struct {
+ s16 data:9;
+ u16 rsvd:6;
+ u16 flag:1;
+ } all_time;
+ };
+ union {
+ u16 ctrl_gnt_bt;
+ struct {
+ s16 data:9;
+ u16 rsvd:7;
+ } gnt_bt;
+ };
+ };
+} __packed;
+
+static void
+rtw8851b_btc_set_wl_txpwr_ctrl(struct rtw89_dev *rtwdev, u32 txpwr_val)
+{
+ union rtw8851b_btc_wl_txpwr_ctrl arg = { .txpwr_val = txpwr_val };
+ s32 val;
+
+#define __write_ctrl(_reg, _msk, _val, _en, _cond) \
+do { \
+ u32 _wrt = FIELD_PREP(_msk, _val); \
+ BUILD_BUG_ON(!!(_msk & _en)); \
+ if (_cond) \
+ _wrt |= _en; \
+ else \
+ _wrt &= ~_en; \
+ rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, _reg, \
+ _msk | _en, _wrt); \
+} while (0)
+
+ switch (arg.ctrl_all_time) {
+ case 0xffff:
+ val = 0;
+ break;
+ default:
+ val = arg.all_time.data;
+ break;
+ }
+
+ __write_ctrl(R_AX_PWR_RATE_CTRL, B_AX_FORCE_PWR_BY_RATE_VALUE_MASK,
+ val, B_AX_FORCE_PWR_BY_RATE_EN,
+ arg.ctrl_all_time != 0xffff);
+
+ switch (arg.ctrl_gnt_bt) {
+ case 0xffff:
+ val = 0;
+ break;
+ default:
+ val = arg.gnt_bt.data;
+ break;
+ }
+
+ __write_ctrl(R_AX_PWR_COEXT_CTRL, B_AX_TXAGC_BT_MASK, val,
+ B_AX_TXAGC_BT_EN, arg.ctrl_gnt_bt != 0xffff);
+
+#undef __write_ctrl
+}
+
+static
+s8 rtw8851b_btc_get_bt_rssi(struct rtw89_dev *rtwdev, s8 val)
+{
+ val = clamp_t(s8, val, -100, 0) + 100;
+ val = min(val + 6, 100); /* compensate offset */
+
+ return val;
+}
+
+static
+void rtw8851b_btc_update_bt_cnt(struct rtw89_dev *rtwdev)
+{
+ /* Feature move to firmware */
+}
+
+static void rtw8851b_btc_wl_s1_standby(struct rtw89_dev *rtwdev, bool state)
+{
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_ant_info *ant = &btc->mdinfo.ant;
+
+ rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWE, RFREG_MASK, 0x80000);
+ rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWA, RFREG_MASK, 0x1);
+ rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWD1, RFREG_MASK, 0x110);
+
+ /* set WL standby = Rx for GNT_BT_Tx = 1->0 settle issue */
+ if (state)
+ rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWD0, RFREG_MASK, 0x179c);
+ else
+ rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWD0, RFREG_MASK, 0x208);
+
+ rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWE, RFREG_MASK, 0x0);
+}
+
+#define LNA2_51B_MA 0x700
+
+static const struct rtw89_reg2_def btc_8851b_rf_0[] = {{0x2, 0x0}};
+static const struct rtw89_reg2_def btc_8851b_rf_1[] = {{0x2, 0x1}};
+
+static void rtw8851b_btc_set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
+{
+ /* To improve BT ACI in co-rx
+ * level=0 Default: TIA 1/0= (LNA2,TIAN6) = (7,1)/(5,1) = 21dB/12dB
+ * level=1 Fix LNA2=5: TIA 1/0= (LNA2,TIAN6) = (5,0)/(5,1) = 18dB/12dB
+ */
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_ant_info *ant = &btc->mdinfo.ant;
+ const struct rtw89_reg2_def *rf;
+ u32 n, i, val;
+
+ switch (level) {
+ case 0: /* original */
+ default:
+ btc->dm.wl_lna2 = 0;
+ break;
+ case 1: /* for FDD free-run */
+ btc->dm.wl_lna2 = 0;
+ break;
+ case 2: /* for BTG Co-Rx*/
+ btc->dm.wl_lna2 = 1;
+ break;
+ }
+
+ if (btc->dm.wl_lna2 == 0) {
+ rf = btc_8851b_rf_0;
+ n = ARRAY_SIZE(btc_8851b_rf_0);
+ } else {
+ rf = btc_8851b_rf_1;
+ n = ARRAY_SIZE(btc_8851b_rf_1);
+ }
+
+ for (i = 0; i < n; i++, rf++) {
+ val = rf->data;
+ /* bit[10] = 1 if non-shared-ant for 8851b */
+ if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED)
+ val |= 0x4;
+
+ rtw89_write_rf(rtwdev, ant->btg_pos, rf->addr, LNA2_51B_MA, val);
+ }
+}
+
+static void rtw8851b_fill_freq_with_ppdu(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_phy_ppdu *phy_ppdu,
+ struct ieee80211_rx_status *status)
+{
+ u16 chan = phy_ppdu->chan_idx;
+ enum nl80211_band band;
+ u8 ch;
+
+ if (chan == 0)
+ return;
+
+ rtw89_decode_chan_idx(rtwdev, chan, &ch, &band);
+ status->freq = ieee80211_channel_to_frequency(ch, band);
+ status->band = band;
+}
+
+static void rtw8851b_query_ppdu(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_phy_ppdu *phy_ppdu,
+ struct ieee80211_rx_status *status)
+{
+ u8 path;
+ u8 *rx_power = phy_ppdu->rssi;
+
+ status->signal = RTW89_RSSI_RAW_TO_DBM(rx_power[RF_PATH_A]);
+
+ for (path = 0; path < rtwdev->chip->rf_path_num; path++) {
+ status->chains |= BIT(path);
+ status->chain_signal[path] = RTW89_RSSI_RAW_TO_DBM(rx_power[path]);
+ }
+ if (phy_ppdu->valid)
+ rtw8851b_fill_freq_with_ppdu(rtwdev, phy_ppdu, status);
+}
+
+static int rtw8851b_mac_enable_bb_rf(struct rtw89_dev *rtwdev)
+{
+ int ret;
+
+ rtw89_write8_set(rtwdev, R_AX_SYS_FUNC_EN,
+ B_AX_FEN_BBRSTB | B_AX_FEN_BB_GLB_RSTN);
+ rtw89_write32_set(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG);
+ rtw89_write32_clr(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG);
+ rtw89_write32_set(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG);
+
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, 0xC7,
+ FULL_BIT_MASK);
+ if (ret)
+ return ret;
+
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, 0xC7,
+ FULL_BIT_MASK);
+ if (ret)
+ return ret;
+
+ rtw89_write8(rtwdev, R_AX_PHYREG_SET, PHYREG_SET_XYN_CYCLE);
+
+ return 0;
+}
+
+static int rtw8851b_mac_disable_bb_rf(struct rtw89_dev *rtwdev)
+{
+ u8 wl_rfc_s0;
+ u8 wl_rfc_s1;
+ int ret;
+
+ rtw89_write8_clr(rtwdev, R_AX_SYS_FUNC_EN,
+ B_AX_FEN_BBRSTB | B_AX_FEN_BB_GLB_RSTN);
+
+ ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, &wl_rfc_s0);
+ if (ret)
+ return ret;
+ wl_rfc_s0 &= ~XTAL_SI_RF00S_EN;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, wl_rfc_s0,
+ FULL_BIT_MASK);
+ if (ret)
+ return ret;
+
+ ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, &wl_rfc_s1);
+ if (ret)
+ return ret;
+ wl_rfc_s1 &= ~XTAL_SI_RF10S_EN;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, wl_rfc_s1,
+ FULL_BIT_MASK);
+ return ret;
+}
+
+static const struct rtw89_chip_ops rtw8851b_chip_ops = {
+ .enable_bb_rf = rtw8851b_mac_enable_bb_rf,
+ .disable_bb_rf = rtw8851b_mac_disable_bb_rf,
+ .bb_reset = rtw8851b_bb_reset,
+ .bb_sethw = rtw8851b_bb_sethw,
+ .read_rf = rtw89_phy_read_rf_v1,
+ .write_rf = rtw89_phy_write_rf_v1,
+ .set_channel = rtw8851b_set_channel,
+ .set_channel_help = rtw8851b_set_channel_help,
+ .read_efuse = rtw8851b_read_efuse,
+ .read_phycap = rtw8851b_read_phycap,
+ .fem_setup = NULL,
+ .rfe_gpio = rtw8851b_rfe_gpio,
+ .rfk_init = rtw8851b_rfk_init,
+ .rfk_channel = rtw8851b_rfk_channel,
+ .rfk_band_changed = rtw8851b_rfk_band_changed,
+ .rfk_scan = rtw8851b_rfk_scan,
+ .rfk_track = rtw8851b_rfk_track,
+ .power_trim = rtw8851b_power_trim,
+ .set_txpwr = rtw8851b_set_txpwr,
+ .set_txpwr_ctrl = rtw8851b_set_txpwr_ctrl,
+ .init_txpwr_unit = rtw8851b_init_txpwr_unit,
+ .get_thermal = rtw8851b_get_thermal,
+ .ctrl_btg = rtw8851b_ctrl_btg,
+ .query_ppdu = rtw8851b_query_ppdu,
+ .bb_ctrl_btc_preagc = rtw8851b_bb_ctrl_btc_preagc,
+ .cfg_txrx_path = rtw8851b_bb_cfg_txrx_path,
+ .set_txpwr_ul_tb_offset = rtw8851b_set_txpwr_ul_tb_offset,
+ .pwr_on_func = rtw8851b_pwr_on_func,
+ .pwr_off_func = rtw8851b_pwr_off_func,
+ .query_rxdesc = rtw89_core_query_rxdesc,
+ .fill_txdesc = rtw89_core_fill_txdesc,
+ .fill_txdesc_fwcmd = rtw89_core_fill_txdesc,
+ .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path,
+ .mac_cfg_gnt = rtw89_mac_cfg_gnt,
+ .stop_sch_tx = rtw89_mac_stop_sch_tx,
+ .resume_sch_tx = rtw89_mac_resume_sch_tx,
+ .h2c_dctl_sec_cam = NULL,
+
+ .btc_set_rfe = rtw8851b_btc_set_rfe,
+ .btc_init_cfg = rtw8851b_btc_init_cfg,
+ .btc_set_wl_pri = rtw8851b_btc_set_wl_pri,
+ .btc_set_wl_txpwr_ctrl = rtw8851b_btc_set_wl_txpwr_ctrl,
+ .btc_get_bt_rssi = rtw8851b_btc_get_bt_rssi,
+ .btc_update_bt_cnt = rtw8851b_btc_update_bt_cnt,
+ .btc_wl_s1_standby = rtw8851b_btc_wl_s1_standby,
+ .btc_set_wl_rx_gain = rtw8851b_btc_set_wl_rx_gain,
+ .btc_set_policy = rtw89_btc_set_policy_v1,
+};
+
+#ifdef CONFIG_PM
+static const struct wiphy_wowlan_support rtw_wowlan_stub_8851b = {
+ .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
+ .n_patterns = RTW89_MAX_PATTERN_NUM,
+ .pattern_max_len = RTW89_MAX_PATTERN_SIZE,
+ .pattern_min_len = 1,
+};
+#endif
+
+const struct rtw89_chip_info rtw8851b_chip_info = {
+ .chip_id = RTL8851B,
+ .ops = &rtw8851b_chip_ops,
+ .fw_basename = RTW8851B_FW_BASENAME,
+ .fw_format_max = RTW8851B_FW_FORMAT_MAX,
+ .try_ce_fw = true,
+ .fifo_size = 196608,
+ .small_fifo_size = true,
+ .dle_scc_rsvd_size = 98304,
+ .max_amsdu_limit = 3500,
+ .dis_2g_40m_ul_ofdma = true,
+ .rsvd_ple_ofst = 0x2f800,
+ .hfc_param_ini = rtw8851b_hfc_param_ini_pcie,
+ .dle_mem = rtw8851b_dle_mem_pcie,
+ .wde_qempty_acq_num = 4,
+ .wde_qempty_mgq_sel = 4,
+ .rf_base_addr = {0xe000},
+ .pwr_on_seq = NULL,
+ .pwr_off_seq = NULL,
+ .bb_table = &rtw89_8851b_phy_bb_table,
+ .bb_gain_table = &rtw89_8851b_phy_bb_gain_table,
+ .rf_table = {&rtw89_8851b_phy_radioa_table,},
+ .nctl_table = &rtw89_8851b_phy_nctl_table,
+ .nctl_post_table = &rtw8851b_nctl_post_defs_tbl,
+ .byr_table = &rtw89_8851b_byr_table,
+ .dflt_parms = &rtw89_8851b_dflt_parms,
+ .rfe_parms_conf = rtw89_8851b_rfe_parms_conf,
+ .txpwr_factor_rf = 2,
+ .txpwr_factor_mac = 1,
+ .dig_table = NULL,
+ .dig_regs = &rtw8851b_dig_regs,
+ .tssi_dbw_table = NULL,
+ .support_chanctx_num = 0,
+ .support_bands = BIT(NL80211_BAND_2GHZ) |
+ BIT(NL80211_BAND_5GHZ),
+ .support_bw160 = false,
+ .support_unii4 = true,
+ .support_ul_tb_ctrl = true,
+ .hw_sec_hdr = false,
+ .rf_path_num = 1,
+ .tx_nss = 1,
+ .rx_nss = 1,
+ .acam_num = 32,
+ .bcam_num = 20,
+ .scam_num = 128,
+ .bacam_num = 2,
+ .bacam_dynamic_num = 4,
+ .bacam_ver = RTW89_BACAM_V0,
+ .sec_ctrl_efuse_size = 4,
+ .physical_efuse_size = 1216,
+ .logical_efuse_size = 2048,
+ .limit_efuse_size = 1280,
+ .dav_phy_efuse_size = 0,
+ .dav_log_efuse_size = 0,
+ .phycap_addr = 0x580,
+ .phycap_size = 128,
+ .para_ver = 0,
+ .wlcx_desired = 0x06000000,
+ .btcx_desired = 0x7,
+ .scbd = 0x1,
+ .mailbox = 0x1,
+
+ .afh_guard_ch = 6,
+ .wl_rssi_thres = rtw89_btc_8851b_wl_rssi_thres,
+ .bt_rssi_thres = rtw89_btc_8851b_bt_rssi_thres,
+ .rssi_tol = 2,
+ .mon_reg_num = ARRAY_SIZE(rtw89_btc_8851b_mon_reg),
+ .mon_reg = rtw89_btc_8851b_mon_reg,
+ .rf_para_ulink_num = ARRAY_SIZE(rtw89_btc_8851b_rf_ul),
+ .rf_para_ulink = rtw89_btc_8851b_rf_ul,
+ .rf_para_dlink_num = ARRAY_SIZE(rtw89_btc_8851b_rf_dl),
+ .rf_para_dlink = rtw89_btc_8851b_rf_dl,
+ .ps_mode_supported = BIT(RTW89_PS_MODE_RFOFF) |
+ BIT(RTW89_PS_MODE_CLK_GATED),
+ .low_power_hci_modes = 0,
+ .h2c_cctl_func_id = H2C_FUNC_MAC_CCTLINFO_UD,
+ .hci_func_en_addr = R_AX_HCI_FUNC_EN,
+ .h2c_desc_size = sizeof(struct rtw89_txwd_body),
+ .txwd_body_size = sizeof(struct rtw89_txwd_body),
+ .h2c_ctrl_reg = R_AX_H2CREG_CTRL,
+ .h2c_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_H2C_DEQ_CNT_MASK >> 8},
+ .h2c_regs = rtw8851b_h2c_regs,
+ .c2h_ctrl_reg = R_AX_C2HREG_CTRL,
+ .c2h_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_C2H_ENQ_CNT_MASK >> 8},
+ .c2h_regs = rtw8851b_c2h_regs,
+ .page_regs = &rtw8851b_page_regs,
+ .cfo_src_fd = true,
+ .cfo_hw_comp = true,
+ .dcfo_comp = &rtw8851b_dcfo_comp,
+ .dcfo_comp_sft = 12,
+ .imr_info = &rtw8851b_imr_info,
+ .rrsr_cfgs = &rtw8851b_rrsr_cfgs,
+ .bss_clr_map_reg = R_BSS_CLR_MAP_V1,
+ .dma_ch_mask = BIT(RTW89_DMA_ACH4) | BIT(RTW89_DMA_ACH5) |
+ BIT(RTW89_DMA_ACH6) | BIT(RTW89_DMA_ACH7) |
+ BIT(RTW89_DMA_B1MG) | BIT(RTW89_DMA_B1HI),
+ .edcca_lvl_reg = R_SEG0R_EDCCA_LVL_V1,
+#ifdef CONFIG_PM
+ .wowlan_stub = &rtw_wowlan_stub_8851b,
+#endif
+ .xtal_info = &rtw8851b_xtal_info,
+};
+EXPORT_SYMBOL(rtw8851b_chip_info);
+
+MODULE_FIRMWARE(RTW8851B_MODULE_FIRMWARE);
+MODULE_AUTHOR("Realtek Corporation");
+MODULE_DESCRIPTION("Realtek 802.11ax wireless 8851B driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.h b/drivers/net/wireless/realtek/rtw89/rtw8851b.h
new file mode 100644
index 000000000000..1a5c52654d8a
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2022-2023 Realtek Corporation
+ */
+
+#ifndef __RTW89_8851B_H__
+#define __RTW89_8851B_H__
+
+#include "core.h"
+
+#define RF_PATH_NUM_8851B 1
+#define BB_PATH_NUM_8851B 1
+
+struct rtw8851bu_efuse {
+ u8 rsvd[0x88];
+ u8 mac_addr[ETH_ALEN];
+};
+
+struct rtw8851be_efuse {
+ u8 mac_addr[ETH_ALEN];
+};
+
+struct rtw8851b_tssi_offset {
+ u8 cck_tssi[TSSI_CCK_CH_GROUP_NUM];
+ u8 bw40_tssi[TSSI_MCS_2G_CH_GROUP_NUM];
+ u8 rsvd[7];
+ u8 bw40_1s_tssi_5g[TSSI_MCS_5G_CH_GROUP_NUM];
+} __packed;
+
+struct rtw8851b_efuse {
+ u8 rsvd[0x210];
+ struct rtw8851b_tssi_offset path_a_tssi;
+ u8 rsvd1[136];
+ u8 channel_plan;
+ u8 xtal_k;
+ u8 rsvd2;
+ u8 iqk_lck;
+ u8 rsvd3[8];
+ u8 eeprom_version;
+ u8 customer_id;
+ u8 tx_bb_swing_2g;
+ u8 tx_bb_swing_5g;
+ u8 tx_cali_pwr_trk_mode;
+ u8 trx_path_selection;
+ u8 rfe_type;
+ u8 country_code[2];
+ u8 rsvd4[3];
+ u8 path_a_therm;
+ u8 rsvd5[3];
+ u8 rx_gain_2g_ofdm;
+ u8 rsvd6;
+ u8 rx_gain_2g_cck;
+ u8 rsvd7;
+ u8 rx_gain_5g_low;
+ u8 rsvd8;
+ u8 rx_gain_5g_mid;
+ u8 rsvd9;
+ u8 rx_gain_5g_high;
+ u8 rsvd10[35];
+ u8 path_a_cck_pwr_idx[6];
+ u8 path_a_bw40_1tx_pwr_idx[5];
+ u8 path_a_ofdm_1tx_pwr_idx_diff:4;
+ u8 path_a_bw20_1tx_pwr_idx_diff:4;
+ u8 path_a_bw20_2tx_pwr_idx_diff:4;
+ u8 path_a_bw40_2tx_pwr_idx_diff:4;
+ u8 path_a_cck_2tx_pwr_idx_diff:4;
+ u8 path_a_ofdm_2tx_pwr_idx_diff:4;
+ u8 rsvd11[0xf2];
+ union {
+ struct rtw8851bu_efuse u;
+ struct rtw8851be_efuse e;
+ };
+} __packed;
+
+extern const struct rtw89_chip_info rtw8851b_chip_info;
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c
new file mode 100644
index 000000000000..a221f94627f5
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c
@@ -0,0 +1,3621 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2022-2023 Realtek Corporation
+ */
+
+#include "coex.h"
+#include "debug.h"
+#include "mac.h"
+#include "phy.h"
+#include "reg.h"
+#include "rtw8851b.h"
+#include "rtw8851b_rfk.h"
+#include "rtw8851b_rfk_table.h"
+#include "rtw8851b_table.h"
+
+#define DPK_VER_8851B 0x5
+#define DPK_KIP_REG_NUM_8851B 7
+#define DPK_RF_REG_NUM_8851B 4
+#define DPK_KSET_NUM 4
+#define RTW8851B_RXK_GROUP_NR 4
+#define RTW8851B_RXK_GROUP_IDX_NR 2
+#define RTW8851B_TXK_GROUP_NR 1
+#define RTW8851B_IQK_VER 0x2a
+#define RTW8851B_IQK_SS 1
+#define RTW8851B_LOK_GRAM 10
+#define RTW8851B_TSSI_PATH_NR 1
+
+#define _TSSI_DE_MASK GENMASK(21, 12)
+
+enum dpk_id {
+ LBK_RXIQK = 0x06,
+ SYNC = 0x10,
+ MDPK_IDL = 0x11,
+ MDPK_MPA = 0x12,
+ GAIN_LOSS = 0x13,
+ GAIN_CAL = 0x14,
+ DPK_RXAGC = 0x15,
+ KIP_PRESET = 0x16,
+ KIP_RESTORE = 0x17,
+ DPK_TXAGC = 0x19,
+ D_KIP_PRESET = 0x28,
+ D_TXAGC = 0x29,
+ D_RXAGC = 0x2a,
+ D_SYNC = 0x2b,
+ D_GAIN_LOSS = 0x2c,
+ D_MDPK_IDL = 0x2d,
+ D_MDPK_LDL = 0x2e,
+ D_GAIN_NORM = 0x2f,
+ D_KIP_THERMAL = 0x30,
+ D_KIP_RESTORE = 0x31
+};
+
+enum dpk_agc_step {
+ DPK_AGC_STEP_SYNC_DGAIN,
+ DPK_AGC_STEP_GAIN_LOSS_IDX,
+ DPK_AGC_STEP_GL_GT_CRITERION,
+ DPK_AGC_STEP_GL_LT_CRITERION,
+ DPK_AGC_STEP_SET_TX_GAIN,
+};
+
+enum rtw8851b_iqk_type {
+ ID_TXAGC = 0x0,
+ ID_FLOK_COARSE = 0x1,
+ ID_FLOK_FINE = 0x2,
+ ID_TXK = 0x3,
+ ID_RXAGC = 0x4,
+ ID_RXK = 0x5,
+ ID_NBTXK = 0x6,
+ ID_NBRXK = 0x7,
+ ID_FLOK_VBUFFER = 0x8,
+ ID_A_FLOK_COARSE = 0x9,
+ ID_G_FLOK_COARSE = 0xa,
+ ID_A_FLOK_FINE = 0xb,
+ ID_G_FLOK_FINE = 0xc,
+ ID_IQK_RESTORE = 0x10,
+};
+
+enum rf_mode {
+ RF_SHUT_DOWN = 0x0,
+ RF_STANDBY = 0x1,
+ RF_TX = 0x2,
+ RF_RX = 0x3,
+ RF_TXIQK = 0x4,
+ RF_DPK = 0x5,
+ RF_RXK1 = 0x6,
+ RF_RXK2 = 0x7,
+};
+
+static const u32 _tssi_de_cck_long[RF_PATH_NUM_8851B] = {0x5858};
+static const u32 _tssi_de_cck_short[RF_PATH_NUM_8851B] = {0x5860};
+static const u32 _tssi_de_mcs_20m[RF_PATH_NUM_8851B] = {0x5838};
+static const u32 _tssi_de_mcs_40m[RF_PATH_NUM_8851B] = {0x5840};
+static const u32 _tssi_de_mcs_80m[RF_PATH_NUM_8851B] = {0x5848};
+static const u32 _tssi_de_mcs_80m_80m[RF_PATH_NUM_8851B] = {0x5850};
+static const u32 _tssi_de_mcs_5m[RF_PATH_NUM_8851B] = {0x5828};
+static const u32 _tssi_de_mcs_10m[RF_PATH_NUM_8851B] = {0x5830};
+static const u32 g_idxrxgain[RTW8851B_RXK_GROUP_NR] = {0x10e, 0x116, 0x28e, 0x296};
+static const u32 g_idxattc2[RTW8851B_RXK_GROUP_NR] = {0x0, 0xf, 0x0, 0xf};
+static const u32 g_idxrxagc[RTW8851B_RXK_GROUP_NR] = {0x0, 0x1, 0x2, 0x3};
+static const u32 a_idxrxgain[RTW8851B_RXK_GROUP_IDX_NR] = {0x10C, 0x28c};
+static const u32 a_idxattc2[RTW8851B_RXK_GROUP_IDX_NR] = {0xf, 0xf};
+static const u32 a_idxrxagc[RTW8851B_RXK_GROUP_IDX_NR] = {0x4, 0x6};
+static const u32 a_power_range[RTW8851B_TXK_GROUP_NR] = {0x0};
+static const u32 a_track_range[RTW8851B_TXK_GROUP_NR] = {0x6};
+static const u32 a_gain_bb[RTW8851B_TXK_GROUP_NR] = {0x0a};
+static const u32 a_itqt[RTW8851B_TXK_GROUP_NR] = {0x12};
+static const u32 g_power_range[RTW8851B_TXK_GROUP_NR] = {0x0};
+static const u32 g_track_range[RTW8851B_TXK_GROUP_NR] = {0x6};
+static const u32 g_gain_bb[RTW8851B_TXK_GROUP_NR] = {0x10};
+static const u32 g_itqt[RTW8851B_TXK_GROUP_NR] = {0x12};
+
+static const u32 rtw8851b_backup_bb_regs[] = {0xc0d4, 0xc0d8, 0xc0c4, 0xc0ec, 0xc0e8};
+static const u32 rtw8851b_backup_rf_regs[] = {
+ 0xef, 0xde, 0x0, 0x1e, 0x2, 0x85, 0x90, 0x5};
+
+#define BACKUP_BB_REGS_NR ARRAY_SIZE(rtw8851b_backup_bb_regs)
+#define BACKUP_RF_REGS_NR ARRAY_SIZE(rtw8851b_backup_rf_regs)
+
+static const u32 dpk_kip_reg[DPK_KIP_REG_NUM_8851B] = {
+ 0x813c, 0x8124, 0xc0ec, 0xc0e8, 0xc0c4, 0xc0d4, 0xc0d8};
+static const u32 dpk_rf_reg[DPK_RF_REG_NUM_8851B] = {0xde, 0x8f, 0x5, 0x10005};
+
+static void _set_ch(struct rtw89_dev *rtwdev, u32 val);
+
+static u8 _rxk_5ghz_group_from_idx(u8 idx)
+{
+ /* There are four RXK groups (RTW8851B_RXK_GROUP_NR), but only group 0
+ * and 2 are used in 5 GHz band, so reduce elements to 2.
+ */
+ if (idx < RTW8851B_RXK_GROUP_IDX_NR)
+ return idx * 2;
+
+ return 0;
+}
+
+static u8 _kpath(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ return RF_A;
+}
+
+static void _adc_fifo_rst(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RXK, 0x0101);
+ fsleep(10);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RXK, 0x1111);
+}
+
+static void _rfk_rf_direct_cntrl(struct rtw89_dev *rtwdev,
+ enum rtw89_rf_path path, bool is_bybb)
+{
+ if (is_bybb)
+ rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x1);
+ else
+ rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0);
+}
+
+static void _rfk_drf_direct_cntrl(struct rtw89_dev *rtwdev,
+ enum rtw89_rf_path path, bool is_bybb)
+{
+ if (is_bybb)
+ rtw89_write_rf(rtwdev, path, RR_BBDC, RR_BBDC_SEL, 0x1);
+ else
+ rtw89_write_rf(rtwdev, path, RR_BBDC, RR_BBDC_SEL, 0x0);
+}
+
+static void _wait_rx_mode(struct rtw89_dev *rtwdev, u8 kpath)
+{
+ u32 rf_mode;
+ u8 path;
+ int ret;
+
+ for (path = 0; path < RF_PATH_MAX; path++) {
+ if (!(kpath & BIT(path)))
+ continue;
+
+ ret = read_poll_timeout_atomic(rtw89_read_rf, rf_mode,
+ rf_mode != 2, 2, 5000, false,
+ rtwdev, path, 0x00, RR_MOD_MASK);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RFK] Wait S%d to Rx mode!! (ret = %d)\n",
+ path, ret);
+ }
+}
+
+static void _dack_reset(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ rtw89_phy_write32_mask(rtwdev, R_DCOF0, B_DCOF0_RST, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_DCOF0, B_DCOF0_RST, 0x1);
+}
+
+static void _drck(struct rtw89_dev *rtwdev)
+{
+ u32 rck_d;
+ u32 val;
+ int ret;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]Ddie RCK start!!!\n");
+
+ rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_IDLE, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_EN, 0x1);
+
+ ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val,
+ 1, 10000, false,
+ rtwdev, R_DRCK_RES, B_DRCK_POL);
+ if (ret)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DRCK timeout\n");
+
+ rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_DRCK_FH, B_DRCK_LAT, 0x1);
+ udelay(1);
+ rtw89_phy_write32_mask(rtwdev, R_DRCK_FH, B_DRCK_LAT, 0x0);
+
+ rck_d = rtw89_phy_read32_mask(rtwdev, R_DRCK_RES, 0x7c00);
+ rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_IDLE, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_VAL, rck_d);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0xc0c4 = 0x%x\n",
+ rtw89_phy_read32_mask(rtwdev, R_DRCK, MASKDWORD));
+}
+
+static void _addck_backup(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0, 0x0);
+
+ dack->addck_d[0][0] = rtw89_phy_read32_mask(rtwdev, R_ADDCKR0, B_ADDCKR0_A0);
+ dack->addck_d[0][1] = rtw89_phy_read32_mask(rtwdev, R_ADDCKR0, B_ADDCKR0_A1);
+}
+
+static void _addck_reload(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0_RL, B_ADDCK0_RL1, dack->addck_d[0][0]);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0_RL, B_ADDCK0_RL0, dack->addck_d[0][1]);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0_RL, B_ADDCK0_RLS, 0x3);
+}
+
+static void _dack_backup_s0(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+ u8 i;
+
+ rtw89_phy_write32_mask(rtwdev, R_P0_NRBW, B_P0_NRBW_DBG, 0x1);
+
+ for (i = 0; i < RTW89_DACK_MSBK_NR; i++) {
+ rtw89_phy_write32_mask(rtwdev, R_DCOF0, B_DCOF0_V, i);
+ dack->msbk_d[0][0][i] =
+ rtw89_phy_read32_mask(rtwdev, R_DACK_S0P2, B_DACK_S0M0);
+
+ rtw89_phy_write32_mask(rtwdev, R_DCOF8, B_DCOF8_V, i);
+ dack->msbk_d[0][1][i] =
+ rtw89_phy_read32_mask(rtwdev, R_DACK_S0P3, B_DACK_S0M1);
+ }
+
+ dack->biask_d[0][0] =
+ rtw89_phy_read32_mask(rtwdev, R_DACK_BIAS00, B_DACK_BIAS00);
+ dack->biask_d[0][1] =
+ rtw89_phy_read32_mask(rtwdev, R_DACK_BIAS01, B_DACK_BIAS01);
+ dack->dadck_d[0][0] =
+ rtw89_phy_read32_mask(rtwdev, R_DACK_DADCK00, B_DACK_DADCK00) + 24;
+ dack->dadck_d[0][1] =
+ rtw89_phy_read32_mask(rtwdev, R_DACK_DADCK01, B_DACK_DADCK01) + 24;
+}
+
+static void _dack_reload_by_path(struct rtw89_dev *rtwdev,
+ enum rtw89_rf_path path, u8 index)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+ u32 idx_offset, path_offset;
+ u32 offset, reg;
+ u32 tmp;
+ u8 i;
+
+ if (index == 0)
+ idx_offset = 0;
+ else
+ idx_offset = 0x14;
+
+ if (path == RF_PATH_A)
+ path_offset = 0;
+ else
+ path_offset = 0x28;
+
+ offset = idx_offset + path_offset;
+
+ rtw89_phy_write32_mask(rtwdev, R_DCOF1, B_DCOF1_RST, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_DCOF9, B_DCOF9_RST, 0x1);
+
+ /* msbk_d: 15/14/13/12 */
+ tmp = 0x0;
+ for (i = 0; i < 4; i++)
+ tmp |= dack->msbk_d[path][index][i + 12] << (i * 8);
+ reg = 0xc200 + offset;
+ rtw89_phy_write32(rtwdev, reg, tmp);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", reg,
+ rtw89_phy_read32_mask(rtwdev, reg, MASKDWORD));
+
+ /* msbk_d: 11/10/9/8 */
+ tmp = 0x0;
+ for (i = 0; i < 4; i++)
+ tmp |= dack->msbk_d[path][index][i + 8] << (i * 8);
+ reg = 0xc204 + offset;
+ rtw89_phy_write32(rtwdev, reg, tmp);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", reg,
+ rtw89_phy_read32_mask(rtwdev, reg, MASKDWORD));
+
+ /* msbk_d: 7/6/5/4 */
+ tmp = 0x0;
+ for (i = 0; i < 4; i++)
+ tmp |= dack->msbk_d[path][index][i + 4] << (i * 8);
+ reg = 0xc208 + offset;
+ rtw89_phy_write32(rtwdev, reg, tmp);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", reg,
+ rtw89_phy_read32_mask(rtwdev, reg, MASKDWORD));
+
+ /* msbk_d: 3/2/1/0 */
+ tmp = 0x0;
+ for (i = 0; i < 4; i++)
+ tmp |= dack->msbk_d[path][index][i] << (i * 8);
+ reg = 0xc20c + offset;
+ rtw89_phy_write32(rtwdev, reg, tmp);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", reg,
+ rtw89_phy_read32_mask(rtwdev, reg, MASKDWORD));
+
+ /* dadak_d/biask_d */
+ tmp = 0x0;
+ tmp = (dack->biask_d[path][index] << 22) |
+ (dack->dadck_d[path][index] << 14);
+ reg = 0xc210 + offset;
+ rtw89_phy_write32(rtwdev, reg, tmp);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", reg,
+ rtw89_phy_read32_mask(rtwdev, reg, MASKDWORD));
+
+ rtw89_phy_write32_mask(rtwdev, R_DACKN0_CTL + offset, B_DACKN0_EN, 0x1);
+}
+
+static void _dack_reload(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ u8 index;
+
+ for (index = 0; index < 2; index++)
+ _dack_reload_by_path(rtwdev, path, index);
+}
+
+static void _addck(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+ u32 val;
+ int ret;
+
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_RST, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_EN, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_EN, 0x0);
+ udelay(1);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0, 0x1);
+
+ ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val,
+ 1, 10000, false,
+ rtwdev, R_ADDCKR0, BIT(0));
+ if (ret) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADDCK timeout\n");
+ dack->addck_timeout[0] = true;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]ADDCK ret = %d\n", ret);
+
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_RST, 0x0);
+}
+
+static void _new_dadck(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+ u32 i_dc, q_dc, ic, qc;
+ u32 val;
+ int ret;
+
+ rtw89_rfk_parser(rtwdev, &rtw8851b_dadck_setup_defs_tbl);
+
+ ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val,
+ 1, 10000, false,
+ rtwdev, R_ADDCKR0, BIT(0));
+ if (ret) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 DADCK timeout\n");
+ dack->addck_timeout[0] = true;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DADCK ret = %d\n", ret);
+
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_IQ, 0x0);
+ i_dc = rtw89_phy_read32_mask(rtwdev, R_ADDCKR0, B_ADDCKR0_DC);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_IQ, 0x1);
+ q_dc = rtw89_phy_read32_mask(rtwdev, R_ADDCKR0, B_ADDCKR0_DC);
+
+ ic = 0x80 - sign_extend32(i_dc, 11) * 6;
+ qc = 0x80 - sign_extend32(q_dc, 11) * 6;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DACK]before DADCK, i_dc=0x%x, q_dc=0x%x\n", i_dc, q_dc);
+
+ dack->dadck_d[0][0] = ic;
+ dack->dadck_d[0][1] = qc;
+
+ rtw89_phy_write32_mask(rtwdev, R_DACKN0_CTL, B_DACKN0_V, dack->dadck_d[0][0]);
+ rtw89_phy_write32_mask(rtwdev, R_DACKN1_CTL, B_DACKN1_V, dack->dadck_d[0][1]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DACK]after DADCK, 0xc210=0x%x, 0xc224=0x%x\n",
+ rtw89_phy_read32_mask(rtwdev, R_DACKN0_CTL, MASKDWORD),
+ rtw89_phy_read32_mask(rtwdev, R_DACKN1_CTL, MASKDWORD));
+
+ rtw89_rfk_parser(rtwdev, &rtw8851b_dadck_post_defs_tbl);
+}
+
+static bool _dack_s0_poll(struct rtw89_dev *rtwdev)
+{
+ if (rtw89_phy_read32_mask(rtwdev, R_DACK_S0P0, B_DACK_S0P0_OK) == 0 ||
+ rtw89_phy_read32_mask(rtwdev, R_DACK_S0P1, B_DACK_S0P1_OK) == 0 ||
+ rtw89_phy_read32_mask(rtwdev, R_DACK_S0P2, B_DACK_S0P2_OK) == 0 ||
+ rtw89_phy_read32_mask(rtwdev, R_DACK_S0P3, B_DACK_S0P3_OK) == 0)
+ return false;
+
+ return true;
+}
+
+static void _dack_s0(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+ bool done;
+ int ret;
+
+ rtw89_rfk_parser(rtwdev, &rtw8851b_dack_s0_1_defs_tbl);
+ _dack_reset(rtwdev, RF_PATH_A);
+ rtw89_phy_write32_mask(rtwdev, R_DCOF1, B_DCOF1_S, 0x1);
+
+ ret = read_poll_timeout_atomic(_dack_s0_poll, done, done,
+ 1, 10000, false, rtwdev);
+ if (ret) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 DACK timeout\n");
+ dack->msbk_timeout[0] = true;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK ret = %d\n", ret);
+
+ rtw89_rfk_parser(rtwdev, &rtw8851b_dack_s0_2_defs_tbl);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]after S0 DADCK\n");
+
+ _dack_backup_s0(rtwdev);
+ _dack_reload(rtwdev, RF_PATH_A);
+
+ rtw89_phy_write32_mask(rtwdev, R_P0_NRBW, B_P0_NRBW_DBG, 0x0);
+}
+
+static void _dack(struct rtw89_dev *rtwdev)
+{
+ _dack_s0(rtwdev);
+}
+
+static void _dack_dump(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+ u8 i;
+ u8 t;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_DCK ic = 0x%x, qc = 0x%x\n",
+ dack->addck_d[0][0], dack->addck_d[0][1]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 DAC_DCK ic = 0x%x, qc = 0x%x\n",
+ dack->dadck_d[0][0], dack->dadck_d[0][1]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 biask ic = 0x%x, qc = 0x%x\n",
+ dack->biask_d[0][0], dack->biask_d[0][1]);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK ic:\n");
+ for (i = 0; i < RTW89_DACK_MSBK_NR; i++) {
+ t = dack->msbk_d[0][0][i];
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", t);
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK qc:\n");
+ for (i = 0; i < RTW89_DACK_MSBK_NR; i++) {
+ t = dack->msbk_d[0][1][i];
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", t);
+ }
+}
+
+static void _dack_manual_off(struct rtw89_dev *rtwdev)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_dack_manual_off_defs_tbl);
+}
+
+static void _dac_cal(struct rtw89_dev *rtwdev, bool force)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+ u32 rf0_0;
+
+ dack->dack_done = false;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK 0x2\n");
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK start!!!\n");
+ rf0_0 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_MOD, RFREG_MASK);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]RF0=0x%x\n", rf0_0);
+
+ _drck(rtwdev);
+ _dack_manual_off(rtwdev);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RFREG_MASK, 0x337e1);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RR_RSV1_RST, 0x0);
+
+ _addck(rtwdev);
+ _addck_backup(rtwdev);
+ _addck_reload(rtwdev);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RFREG_MASK, 0x40001);
+
+ _dack(rtwdev);
+ _new_dadck(rtwdev);
+ _dack_dump(rtwdev);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RR_RSV1_RST, 0x1);
+
+ dack->dack_done = true;
+ dack->dack_cnt++;
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK finish!!!\n");
+}
+
+static void _rx_dck_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, bool is_afe)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RX_DCK] ==== S%d RX DCK (%s / CH%d / %s / by %s)====\n", path,
+ chan->band_type == RTW89_BAND_2G ? "2G" :
+ chan->band_type == RTW89_BAND_5G ? "5G" : "6G",
+ chan->channel,
+ chan->band_width == RTW89_CHANNEL_WIDTH_20 ? "20M" :
+ chan->band_width == RTW89_CHANNEL_WIDTH_40 ? "40M" : "80M",
+ is_afe ? "AFE" : "RFC");
+}
+
+static void _rxbb_ofst_swap(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 rf_mode)
+{
+ u32 val, val_i, val_q;
+
+ val_i = rtw89_read_rf(rtwdev, path, RR_DCK, RR_DCK_S1);
+ val_q = rtw89_read_rf(rtwdev, path, RR_DCK1, RR_DCK1_S1);
+
+ val = val_q << 4 | val_i;
+
+ rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_DIS, 0x1);
+ rtw89_write_rf(rtwdev, path, RR_LUTWA, RFREG_MASK, rf_mode);
+ rtw89_write_rf(rtwdev, path, RR_LUTWD0, RFREG_MASK, val);
+ rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_DIS, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RX_DCK] val_i = 0x%x, val_q = 0x%x, 0x3F = 0x%x\n",
+ val_i, val_q, val);
+}
+
+static void _set_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 rf_mode)
+{
+ u32 val;
+ int ret;
+
+ rtw89_write_rf(rtwdev, path, RR_DCK, RR_DCK_LV, 0x0);
+ rtw89_write_rf(rtwdev, path, RR_DCK, RR_DCK_LV, 0x1);
+
+ ret = read_poll_timeout_atomic(rtw89_read_rf, val, val,
+ 2, 2000, false,
+ rtwdev, path, RR_DCK, BIT(8));
+
+ rtw89_write_rf(rtwdev, path, RR_DCK, RR_DCK_LV, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RX_DCK] S%d RXDCK finish (ret = %d)\n",
+ path, ret);
+
+ _rxbb_ofst_swap(rtwdev, path, rf_mode);
+}
+
+static void _rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool is_afe)
+{
+ u32 rf_reg5;
+ u8 path;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RX_DCK] ****** RXDCK Start (Ver: 0x%x, Cv: %d) ******\n",
+ 0x2, rtwdev->hal.cv);
+
+ for (path = 0; path < RF_PATH_NUM_8851B; path++) {
+ _rx_dck_info(rtwdev, phy, path, is_afe);
+
+ rf_reg5 = rtw89_read_rf(rtwdev, path, RR_RSV1, RFREG_MASK);
+
+ if (rtwdev->is_tssi_mode[path])
+ rtw89_phy_write32_mask(rtwdev,
+ R_P0_TSSI_TRK + (path << 13),
+ B_P0_TSSI_TRK_EN, 0x1);
+
+ rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0);
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RF_RX);
+ _set_rx_dck(rtwdev, path, RF_RX);
+ rtw89_write_rf(rtwdev, path, RR_RSV1, RFREG_MASK, rf_reg5);
+
+ if (rtwdev->is_tssi_mode[path])
+ rtw89_phy_write32_mask(rtwdev,
+ R_P0_TSSI_TRK + (path << 13),
+ B_P0_TSSI_TRK_EN, 0x0);
+ }
+}
+
+static void _iqk_sram(struct rtw89_dev *rtwdev, u8 path)
+{
+ u32 i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, MASKDWORD, 0x00020000);
+ rtw89_phy_write32_mask(rtwdev, R_MDPK_RX_DCK, MASKDWORD, 0x80000000);
+ rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX2, MASKDWORD, 0x00000080);
+ rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX, MASKDWORD, 0x00010000);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x009);
+
+ for (i = 0; i <= 0x9f; i++) {
+ rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX, MASKDWORD,
+ 0x00010000 + i);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]0x%x\n",
+ rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCI));
+ }
+
+ for (i = 0; i <= 0x9f; i++) {
+ rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX, MASKDWORD,
+ 0x00010000 + i);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]0x%x\n",
+ rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCQ));
+ }
+
+ rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX2, MASKDWORD, 0x00000000);
+ rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX, MASKDWORD, 0x00000000);
+}
+
+static void _iqk_rxk_setting(struct rtw89_dev *rtwdev, u8 path)
+{
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, 0xc);
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_POW, 0x0);
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_POW, 0x1);
+}
+
+static bool _iqk_check_cal(struct rtw89_dev *rtwdev, u8 path)
+{
+ bool fail1 = false, fail2 = false;
+ u32 val;
+ int ret;
+
+ ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val == 0x55,
+ 10, 8200, false,
+ rtwdev, 0xbff8, MASKBYTE0);
+ if (ret) {
+ fail1 = true;
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]NCTL1 IQK timeout!!!\n");
+ }
+
+ fsleep(10);
+
+ ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val == 0x8000,
+ 10, 200, false,
+ rtwdev, R_RPT_COM, B_RPT_COM_RDY);
+ if (ret) {
+ fail2 = true;
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]NCTL2 IQK timeout!!!\n");
+ }
+
+ fsleep(10);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, MASKBYTE0, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, ret = %d, notready = %x fail=%d,%d\n",
+ path, ret, fail1 || fail2, fail1, fail2);
+
+ return fail1 || fail2;
+}
+
+static bool _iqk_one_shot(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path, u8 ktype)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool notready;
+ u32 iqk_cmd;
+
+ switch (ktype) {
+ case ID_A_FLOK_COARSE:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_A_FLOK_COARSE ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ iqk_cmd = 0x108 | (1 << (4 + path));
+ break;
+ case ID_G_FLOK_COARSE:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_G_FLOK_COARSE ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ iqk_cmd = 0x108 | (1 << (4 + path));
+ break;
+ case ID_A_FLOK_FINE:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_A_FLOK_FINE ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ iqk_cmd = 0x308 | (1 << (4 + path));
+ break;
+ case ID_G_FLOK_FINE:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_G_FLOK_FINE ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ iqk_cmd = 0x308 | (1 << (4 + path));
+ break;
+ case ID_TXK:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_TXK ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x0);
+ iqk_cmd = 0x008 | (1 << (path + 4)) |
+ (((0x8 + iqk_info->iqk_bw[path]) & 0xf) << 8);
+ break;
+ case ID_RXAGC:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_RXAGC ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ iqk_cmd = 0x708 | (1 << (4 + path)) | (path << 1);
+ break;
+ case ID_RXK:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_RXK ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ iqk_cmd = 0x008 | (1 << (path + 4)) |
+ (((0xc + iqk_info->iqk_bw[path]) & 0xf) << 8);
+ break;
+ case ID_NBTXK:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_NBTXK ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT,
+ 0x00b);
+ iqk_cmd = 0x408 | (1 << (4 + path));
+ break;
+ case ID_NBRXK:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_NBRXK ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT,
+ 0x011);
+ iqk_cmd = 0x608 | (1 << (4 + path));
+ break;
+ default:
+ return false;
+ }
+
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD, iqk_cmd + 1);
+ notready = _iqk_check_cal(rtwdev, path);
+ if (iqk_info->iqk_sram_en &&
+ (ktype == ID_NBRXK || ktype == ID_RXK))
+ _iqk_sram(rtwdev, path);
+
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x0);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, ktype= %x, id = %x, notready = %x\n",
+ path, ktype, iqk_cmd + 1, notready);
+
+ return notready;
+}
+
+static bool _rxk_2g_group_sel(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx, u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool kfail = false;
+ bool notready;
+ u32 rf_0;
+ u8 gp;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ for (gp = 0; gp < RTW8851B_RXK_GROUP_NR; gp++) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, gp = %x\n", path, gp);
+
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RGM, g_idxrxgain[gp]);
+ rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_C2, g_idxattc2[gp]);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP_V1, gp);
+
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RFREG_MASK, 0x80013);
+ fsleep(10);
+ rf_0 = rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF2, B_IQK_DIF2_RXPI, rf_0);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_RXA, B_IQK_RXAGC, g_idxrxagc[gp]);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x11);
+
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXAGC);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, RXAGC 0x8008 = 0x%x, rxbb = %x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD),
+ rtw89_read_rf(rtwdev, path, RR_MOD, 0x003e0));
+
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_OFF, 0x13);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x011);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBRXK);
+ iqk_info->nb_rxcfir[path] =
+ rtw89_phy_read32_mask(rtwdev, R_RXIQC, MASKDWORD) | 0x2;
+
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXK);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, WBRXK 0x8008 = 0x%x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD));
+ }
+
+ if (!notready)
+ kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG);
+
+ if (kfail)
+ _iqk_sram(rtwdev, path);
+
+ if (kfail) {
+ rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8),
+ MASKDWORD, iqk_info->nb_rxcfir[path] | 0x2);
+ iqk_info->is_wb_txiqk[path] = false;
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8),
+ MASKDWORD, 0x40000000);
+ iqk_info->is_wb_txiqk[path] = true;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, kfail = 0x%x, 0x8%x3c = 0x%x\n", path, kfail,
+ 1 << path, iqk_info->nb_rxcfir[path]);
+ return kfail;
+}
+
+static bool _rxk_5g_group_sel(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx, u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool kfail = false;
+ bool notready;
+ u32 rf_0;
+ u8 idx;
+ u8 gp;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ for (idx = 0; idx < RTW8851B_RXK_GROUP_IDX_NR; idx++) {
+ gp = _rxk_5ghz_group_from_idx(idx);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, gp = %x\n", path, gp);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_RGM, a_idxrxgain[idx]);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_RXA2, RR_RXA2_ATT, a_idxattc2[idx]);
+
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP_V1, gp);
+
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RFREG_MASK, 0x80013);
+ fsleep(100);
+ rf_0 = rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF2, B_IQK_DIF2_RXPI, rf_0);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_RXA, B_IQK_RXAGC, a_idxrxagc[idx]);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x11);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXAGC);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, RXAGC 0x8008 = 0x%x, rxbb = %x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD),
+ rtw89_read_rf(rtwdev, path, RR_MOD, RR_MOD_RXB));
+
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_OFF, 0x13);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x011);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBRXK);
+ iqk_info->nb_rxcfir[path] =
+ rtw89_phy_read32_mask(rtwdev, R_RXIQC, MASKDWORD) | 0x2;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, NBRXK 0x8008 = 0x%x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD));
+
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXK);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, WBRXK 0x8008 = 0x%x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD));
+ }
+
+ if (!notready)
+ kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG);
+
+ if (kfail)
+ _iqk_sram(rtwdev, path);
+
+ if (kfail) {
+ rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD,
+ iqk_info->nb_rxcfir[path] | 0x2);
+ iqk_info->is_wb_txiqk[path] = false;
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD,
+ 0x40000000);
+ iqk_info->is_wb_txiqk[path] = true;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, kfail = 0x%x, 0x8%x3c = 0x%x\n", path, kfail,
+ 1 << path, iqk_info->nb_rxcfir[path]);
+ return kfail;
+}
+
+static bool _iqk_5g_nbrxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool kfail = false;
+ bool notready;
+ u8 idx = 0x1;
+ u32 rf_0;
+ u8 gp;
+
+ gp = _rxk_5ghz_group_from_idx(idx);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, gp = %x\n", path, gp);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_RGM, a_idxrxgain[idx]);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_RXA2, RR_RXA2_ATT, a_idxattc2[idx]);
+
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP_V1, gp);
+
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RFREG_MASK, 0x80013);
+ fsleep(100);
+ rf_0 = rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF2, B_IQK_DIF2_RXPI, rf_0);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_RXA, B_IQK_RXAGC, a_idxrxagc[idx]);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x11);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXAGC);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, RXAGC 0x8008 = 0x%x, rxbb = %x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD),
+ rtw89_read_rf(rtwdev, path, RR_MOD, 0x003e0));
+
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_OFF, 0x13);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x011);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBRXK);
+ iqk_info->nb_rxcfir[path] =
+ rtw89_phy_read32_mask(rtwdev, R_RXIQC, MASKDWORD) | 0x2;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, NBRXK 0x8008 = 0x%x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD));
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, WBRXK 0x8008 = 0x%x\n",
+ path, rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD));
+
+ if (!notready)
+ kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG);
+
+ if (kfail) {
+ rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8),
+ MASKDWORD, 0x40000002);
+ iqk_info->is_wb_rxiqk[path] = false;
+ } else {
+ iqk_info->is_wb_rxiqk[path] = false;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, kfail = 0x%x, 0x8%x3c = 0x%x\n", path, kfail,
+ 1 << path, iqk_info->nb_rxcfir[path]);
+
+ return kfail;
+}
+
+static bool _iqk_2g_nbrxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool kfail = false;
+ bool notready;
+ u8 gp = 0x3;
+ u32 rf_0;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, gp = %x\n", path, gp);
+
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RGM, g_idxrxgain[gp]);
+ rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_C2, g_idxattc2[gp]);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP_V1, gp);
+
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RFREG_MASK, 0x80013);
+ fsleep(10);
+ rf_0 = rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF2, B_IQK_DIF2_RXPI, rf_0);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_RXA, B_IQK_RXAGC, g_idxrxagc[gp]);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x11);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXAGC);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, RXAGC 0x8008 = 0x%x, rxbb = %x\n",
+ path, rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD),
+ rtw89_read_rf(rtwdev, path, RR_MOD, 0x003e0));
+
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_OFF, 0x13);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x011);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBRXK);
+ iqk_info->nb_rxcfir[path] =
+ rtw89_phy_read32_mask(rtwdev, R_RXIQC, MASKDWORD) | 0x2;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, NBRXK 0x8008 = 0x%x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD));
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, WBRXK 0x8008 = 0x%x\n",
+ path, rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD));
+
+ if (!notready)
+ kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG);
+
+ if (kfail) {
+ rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8),
+ MASKDWORD, 0x40000002);
+ iqk_info->is_wb_rxiqk[path] = false;
+ } else {
+ iqk_info->is_wb_rxiqk[path] = false;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, kfail = 0x%x, 0x8%x3c = 0x%x\n", path, kfail,
+ 1 << path, iqk_info->nb_rxcfir[path]);
+ return kfail;
+}
+
+static void _iqk_rxclk_setting(struct rtw89_dev *rtwdev, u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+
+ rtw89_write_rf(rtwdev, path, RR_RXBB2, RR_RXBB2_CKT, 0x1);
+
+ if (iqk_info->iqk_bw[path] == RTW89_CHANNEL_WIDTH_80)
+ rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_rxclk_80_defs_tbl);
+ else
+ rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_rxclk_others_defs_tbl);
+}
+
+static bool _txk_5g_group_sel(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx, u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool kfail = false;
+ bool notready;
+ u8 gp;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ for (gp = 0x0; gp < RTW8851B_TXK_GROUP_NR; gp++) {
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, a_power_range[gp]);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, a_track_range[gp]);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, a_gain_bb[gp]);
+
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G2, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP, gp);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, MASKDWORD, a_itqt[gp]);
+
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBTXK);
+ iqk_info->nb_txcfir[path] =
+ rtw89_phy_read32_mask(rtwdev, R_TXIQC, MASKDWORD) | 0x2;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8),
+ MASKDWORD, a_itqt[gp]);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_TXK);
+ }
+
+ if (!notready)
+ kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG);
+
+ if (kfail) {
+ rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8),
+ MASKDWORD, iqk_info->nb_txcfir[path] | 0x2);
+ iqk_info->is_wb_txiqk[path] = false;
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8),
+ MASKDWORD, 0x40000000);
+ iqk_info->is_wb_txiqk[path] = true;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, kfail = 0x%x, 0x8%x38 = 0x%x\n", path, kfail,
+ 1 << path, iqk_info->nb_txcfir[path]);
+ return kfail;
+}
+
+static bool _txk_2g_group_sel(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx, u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool kfail = false;
+ bool notready;
+ u8 gp;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ for (gp = 0x0; gp < RTW8851B_TXK_GROUP_NR; gp++) {
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, g_power_range[gp]);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, g_track_range[gp]);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, g_gain_bb[gp]);
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, MASKDWORD, g_itqt[gp]);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G2, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP, gp);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBTXK);
+ iqk_info->nb_txcfir[path] =
+ rtw89_phy_read32_mask(rtwdev, R_TXIQC, MASKDWORD) | 0x2;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8),
+ MASKDWORD, g_itqt[gp]);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_TXK);
+ }
+
+ if (!notready)
+ kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG);
+
+ if (kfail) {
+ rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8),
+ MASKDWORD, iqk_info->nb_txcfir[path] | 0x2);
+ iqk_info->is_wb_txiqk[path] = false;
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8),
+ MASKDWORD, 0x40000000);
+ iqk_info->is_wb_txiqk[path] = true;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, kfail = 0x%x, 0x8%x38 = 0x%x\n", path, kfail,
+ 1 << path, iqk_info->nb_txcfir[path]);
+ return kfail;
+}
+
+static bool _iqk_5g_nbtxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool kfail = false;
+ bool notready;
+ u8 gp;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ for (gp = 0x0; gp < RTW8851B_TXK_GROUP_NR; gp++) {
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, a_power_range[gp]);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, a_track_range[gp]);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, a_gain_bb[gp]);
+
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G2, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP, gp);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, MASKDWORD, a_itqt[gp]);
+
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBTXK);
+ iqk_info->nb_txcfir[path] =
+ rtw89_phy_read32_mask(rtwdev, R_TXIQC, MASKDWORD) | 0x2;
+ }
+
+ if (!notready)
+ kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG);
+
+ if (kfail) {
+ rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8),
+ MASKDWORD, 0x40000002);
+ iqk_info->is_wb_rxiqk[path] = false;
+ } else {
+ iqk_info->is_wb_rxiqk[path] = false;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, kfail = 0x%x, 0x8%x38 = 0x%x\n", path, kfail,
+ 1 << path, iqk_info->nb_txcfir[path]);
+ return kfail;
+}
+
+static bool _iqk_2g_nbtxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool kfail = false;
+ bool notready;
+ u8 gp;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ for (gp = 0x0; gp < RTW8851B_TXK_GROUP_NR; gp++) {
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, g_power_range[gp]);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, g_track_range[gp]);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, g_gain_bb[gp]);
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, MASKDWORD, g_itqt[gp]);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G2, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP, gp);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBTXK);
+ iqk_info->nb_txcfir[path] =
+ rtw89_phy_read32_mask(rtwdev, R_TXIQC + (path << 8),
+ MASKDWORD) | 0x2;
+ }
+
+ if (!notready)
+ kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG);
+
+ if (kfail) {
+ rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8),
+ MASKDWORD, 0x40000002);
+ iqk_info->is_wb_rxiqk[path] = false;
+ } else {
+ iqk_info->is_wb_rxiqk[path] = false;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, kfail = 0x%x, 0x8%x38 = 0x%x\n", path, kfail,
+ 1 << path, iqk_info->nb_txcfir[path]);
+ return kfail;
+}
+
+static bool _iqk_2g_lok(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ static const u32 g_txbb[RTW8851B_LOK_GRAM] = {
+ 0x02, 0x06, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x17};
+ static const u32 g_itqt[RTW8851B_LOK_GRAM] = {
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x12, 0x12, 0x12, 0x1b};
+ static const u32 g_wa[RTW8851B_LOK_GRAM] = {
+ 0x00, 0x04, 0x08, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x17};
+ bool fail = false;
+ u8 i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTDBG, RR_LUTDBG_LOK, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_GR0, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_GR1, 0x6);
+
+ for (i = 0; i < RTW8851B_LOK_GRAM; i++) {
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_TG, g_txbb[i]);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RR_LUTWA_M1, g_wa[i]);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, B_KIP_IQP_IQSW, g_itqt[i]);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x021);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD,
+ 0x00000109 | (1 << (4 + path)));
+ fail |= _iqk_check_cal(rtwdev, path);
+
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, B_KIP_IQP_IQSW, g_itqt[i]);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD,
+ 0x00000309 | (1 << (4 + path)));
+ fail |= _iqk_check_cal(rtwdev, path);
+
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S0, i = %x, 0x8[19:15] = 0x%x,0x8[09:05] = 0x%x\n", i,
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_DTXLOK, 0xf8000),
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_DTXLOK, 0x003e0));
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S0, i = %x, 0x9[19:16] = 0x%x,0x9[09:06] = 0x%x\n", i,
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV2, 0xf0000),
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV2, 0x003c0));
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S0, i = %x, 0x58 = %x\n", i,
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_TXMO, RFREG_MASK));
+ }
+
+ return fail;
+}
+
+static bool _iqk_5g_lok(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ static const u32 a_txbb[RTW8851B_LOK_GRAM] = {
+ 0x02, 0x06, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x17};
+ static const u32 a_itqt[RTW8851B_LOK_GRAM] = {
+ 0x09, 0x09, 0x09, 0x12, 0x12, 0x12, 0x1b, 0x1b, 0x1b, 0x1b};
+ static const u32 a_wa[RTW8851B_LOK_GRAM] = {
+ 0x80, 0x84, 0x88, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x97};
+ bool fail = false;
+ u8 i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTDBG, RR_LUTDBG_LOK, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_GR0, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_GR1, 0x7);
+
+ for (i = 0; i < RTW8851B_LOK_GRAM; i++) {
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_TG, a_txbb[i]);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RR_LUTWA_M1, a_wa[i]);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, B_KIP_IQP_IQSW, a_itqt[i]);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x021);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD,
+ 0x00000109 | (1 << (4 + path)));
+ fail |= _iqk_check_cal(rtwdev, path);
+
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, B_KIP_IQP_IQSW, a_itqt[i]);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x021);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD,
+ 0x00000309 | (1 << (4 + path)));
+ fail |= _iqk_check_cal(rtwdev, path);
+
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S0, i = %x, 0x8[19:15] = 0x%x,0x8[09:05] = 0x%x\n", i,
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_DTXLOK, 0xf8000),
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_DTXLOK, 0x003e0));
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S0, i = %x, 0x9[19:16] = 0x%x,0x9[09:06] = 0x%x\n", i,
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV2, 0xf0000),
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV2, 0x003c0));
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S0, i = %x, 0x58 = %x\n", i,
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_TXMO, RFREG_MASK));
+ }
+
+ return fail;
+}
+
+static void _iqk_txk_setting(struct rtw89_dev *rtwdev, u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+
+ switch (iqk_info->iqk_band[path]) {
+ case RTW89_BAND_2G:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]RTW89_BAND_2G\n");
+ rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_txk_2ghz_defs_tbl);
+ break;
+ case RTW89_BAND_5G:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]RTW89_BAND_5G\n");
+ rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_txk_5ghz_defs_tbl);
+ break;
+ default:
+ break;
+ }
+}
+
+#define IQK_LOK_RETRY 1
+
+static void _iqk_by_path(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool lok_is_fail;
+ u8 i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ for (i = 0; i < IQK_LOK_RETRY; i++) {
+ _iqk_txk_setting(rtwdev, path);
+ if (iqk_info->iqk_band[path] == RTW89_BAND_2G)
+ lok_is_fail = _iqk_2g_lok(rtwdev, phy_idx, path);
+ else
+ lok_is_fail = _iqk_5g_lok(rtwdev, phy_idx, path);
+
+ if (!lok_is_fail)
+ break;
+ }
+
+ if (iqk_info->is_nbiqk) {
+ if (iqk_info->iqk_band[path] == RTW89_BAND_2G)
+ iqk_info->iqk_tx_fail[0][path] =
+ _iqk_2g_nbtxk(rtwdev, phy_idx, path);
+ else
+ iqk_info->iqk_tx_fail[0][path] =
+ _iqk_5g_nbtxk(rtwdev, phy_idx, path);
+ } else {
+ if (iqk_info->iqk_band[path] == RTW89_BAND_2G)
+ iqk_info->iqk_tx_fail[0][path] =
+ _txk_2g_group_sel(rtwdev, phy_idx, path);
+ else
+ iqk_info->iqk_tx_fail[0][path] =
+ _txk_5g_group_sel(rtwdev, phy_idx, path);
+ }
+
+ _iqk_rxclk_setting(rtwdev, path);
+ _iqk_rxk_setting(rtwdev, path);
+ _adc_fifo_rst(rtwdev, phy_idx, path);
+
+ if (iqk_info->is_nbiqk) {
+ if (iqk_info->iqk_band[path] == RTW89_BAND_2G)
+ iqk_info->iqk_rx_fail[0][path] =
+ _iqk_2g_nbrxk(rtwdev, phy_idx, path);
+ else
+ iqk_info->iqk_rx_fail[0][path] =
+ _iqk_5g_nbrxk(rtwdev, phy_idx, path);
+ } else {
+ if (iqk_info->iqk_band[path] == RTW89_BAND_2G)
+ iqk_info->iqk_rx_fail[0][path] =
+ _rxk_2g_group_sel(rtwdev, phy_idx, path);
+ else
+ iqk_info->iqk_rx_fail[0][path] =
+ _rxk_5g_group_sel(rtwdev, phy_idx, path);
+ }
+}
+
+static void _rfk_backup_bb_reg(struct rtw89_dev *rtwdev,
+ u32 backup_bb_reg_val[])
+{
+ u32 i;
+
+ for (i = 0; i < BACKUP_BB_REGS_NR; i++) {
+ backup_bb_reg_val[i] =
+ rtw89_phy_read32_mask(rtwdev, rtw8851b_backup_bb_regs[i],
+ MASKDWORD);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RFK]backup bb reg : %x, value =%x\n",
+ rtw8851b_backup_bb_regs[i], backup_bb_reg_val[i]);
+ }
+}
+
+static void _rfk_backup_rf_reg(struct rtw89_dev *rtwdev,
+ u32 backup_rf_reg_val[], u8 rf_path)
+{
+ u32 i;
+
+ for (i = 0; i < BACKUP_RF_REGS_NR; i++) {
+ backup_rf_reg_val[i] =
+ rtw89_read_rf(rtwdev, rf_path,
+ rtw8851b_backup_rf_regs[i], RFREG_MASK);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RFK]backup rf S%d reg : %x, value =%x\n", rf_path,
+ rtw8851b_backup_rf_regs[i], backup_rf_reg_val[i]);
+ }
+}
+
+static void _rfk_restore_bb_reg(struct rtw89_dev *rtwdev,
+ const u32 backup_bb_reg_val[])
+{
+ u32 i;
+
+ for (i = 0; i < BACKUP_BB_REGS_NR; i++) {
+ rtw89_phy_write32_mask(rtwdev, rtw8851b_backup_bb_regs[i],
+ MASKDWORD, backup_bb_reg_val[i]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RFK]restore bb reg : %x, value =%x\n",
+ rtw8851b_backup_bb_regs[i], backup_bb_reg_val[i]);
+ }
+}
+
+static void _rfk_restore_rf_reg(struct rtw89_dev *rtwdev,
+ const u32 backup_rf_reg_val[], u8 rf_path)
+{
+ u32 i;
+
+ for (i = 0; i < BACKUP_RF_REGS_NR; i++) {
+ rtw89_write_rf(rtwdev, rf_path, rtw8851b_backup_rf_regs[i],
+ RFREG_MASK, backup_rf_reg_val[i]);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RFK]restore rf S%d reg: %x, value =%x\n", rf_path,
+ rtw8851b_backup_rf_regs[i], backup_rf_reg_val[i]);
+ }
+}
+
+static void _iqk_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ u8 path)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ u8 idx = 0;
+
+ iqk_info->iqk_band[path] = chan->band_type;
+ iqk_info->iqk_bw[path] = chan->band_width;
+ iqk_info->iqk_ch[path] = chan->channel;
+ iqk_info->iqk_table_idx[path] = idx;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d (PHY%d): / DBCC %s/ %s/ CH%d/ %s\n",
+ path, phy, rtwdev->dbcc_en ? "on" : "off",
+ iqk_info->iqk_band[path] == 0 ? "2G" :
+ iqk_info->iqk_band[path] == 1 ? "5G" : "6G",
+ iqk_info->iqk_ch[path],
+ iqk_info->iqk_bw[path] == 0 ? "20M" :
+ iqk_info->iqk_bw[path] == 1 ? "40M" : "80M");
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]times = 0x%x, ch =%x\n",
+ iqk_info->iqk_times, idx);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, iqk_info->syn1to2= 0x%x\n",
+ path, iqk_info->syn1to2);
+}
+
+static void _iqk_start_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ _iqk_by_path(rtwdev, phy_idx, path);
+}
+
+static void _iqk_restore(struct rtw89_dev *rtwdev, u8 path)
+{
+ bool fail;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD, 0x00001219);
+ fsleep(10);
+ fail = _iqk_check_cal(rtwdev, path);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] restore fail=%d\n", fail);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RR_LUTWE_LOK, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTDBG, RR_LUTDBG_TIA, 0x0);
+
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_RPT, MASKDWORD, 0x00000000);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_SYSCFG, MASKDWORD, 0x80000000);
+}
+
+static void _iqk_afebb_restore(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx, u8 path)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_afebb_restore_defs_tbl);
+}
+
+static void _iqk_preset(struct rtw89_dev *rtwdev, u8 path)
+{
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_RPT, MASKDWORD, 0x00000080);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_SYSCFG, MASKDWORD, 0x81ff010a);
+}
+
+static void _iqk_macbb_setting(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx, u8 path)
+{
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_macbb_defs_tbl);
+}
+
+static void _iqk_init(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ u8 idx, path;
+
+ rtw89_phy_write32_mask(rtwdev, R_IQKINF, MASKDWORD, 0x0);
+
+ if (iqk_info->is_iqk_init)
+ return;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ iqk_info->is_iqk_init = true;
+ iqk_info->is_nbiqk = false;
+ iqk_info->iqk_fft_en = false;
+ iqk_info->iqk_sram_en = false;
+ iqk_info->iqk_cfir_en = false;
+ iqk_info->iqk_xym_en = false;
+ iqk_info->iqk_times = 0x0;
+
+ for (idx = 0; idx < RTW89_IQK_CHS_NR; idx++) {
+ iqk_info->iqk_channel[idx] = 0x0;
+ for (path = 0; path < RF_PATH_NUM_8851B; path++) {
+ iqk_info->lok_cor_fail[idx][path] = false;
+ iqk_info->lok_fin_fail[idx][path] = false;
+ iqk_info->iqk_tx_fail[idx][path] = false;
+ iqk_info->iqk_rx_fail[idx][path] = false;
+ iqk_info->iqk_table_idx[path] = 0x0;
+ }
+ }
+}
+
+static void _doiqk(struct rtw89_dev *rtwdev, bool force,
+ enum rtw89_phy_idx phy_idx, u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, RF_AB);
+ u32 backup_rf_val[RTW8851B_IQK_SS][BACKUP_RF_REGS_NR];
+ u32 backup_bb_val[BACKUP_BB_REGS_NR];
+
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK,
+ BTC_WRFK_ONESHOT_START);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]==========IQK start!!!!!==========\n");
+ iqk_info->iqk_times++;
+ iqk_info->version = RTW8851B_IQK_VER;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]Test Ver 0x%x\n", iqk_info->version);
+ _iqk_get_ch_info(rtwdev, phy_idx, path);
+
+ _rfk_backup_bb_reg(rtwdev, &backup_bb_val[0]);
+ _rfk_backup_rf_reg(rtwdev, &backup_rf_val[path][0], path);
+ _iqk_macbb_setting(rtwdev, phy_idx, path);
+ _iqk_preset(rtwdev, path);
+ _iqk_start_iqk(rtwdev, phy_idx, path);
+ _iqk_restore(rtwdev, path);
+ _iqk_afebb_restore(rtwdev, phy_idx, path);
+ _rfk_restore_bb_reg(rtwdev, &backup_bb_val[0]);
+ _rfk_restore_rf_reg(rtwdev, &backup_rf_val[path][0], path);
+
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK,
+ BTC_WRFK_ONESHOT_STOP);
+}
+
+static void _iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, bool force)
+{
+ _doiqk(rtwdev, force, phy_idx, RF_PATH_A);
+}
+
+static void _dpk_bkup_kip(struct rtw89_dev *rtwdev, const u32 *reg,
+ u32 reg_bkup[][DPK_KIP_REG_NUM_8851B], u8 path)
+{
+ u8 i;
+
+ for (i = 0; i < DPK_KIP_REG_NUM_8851B; i++) {
+ reg_bkup[path][i] =
+ rtw89_phy_read32_mask(rtwdev, reg[i] + (path << 8), MASKDWORD);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Backup 0x%x = %x\n",
+ reg[i] + (path << 8), reg_bkup[path][i]);
+ }
+}
+
+static void _dpk_bkup_rf(struct rtw89_dev *rtwdev, const u32 *rf_reg,
+ u32 rf_bkup[][DPK_RF_REG_NUM_8851B], u8 path)
+{
+ u8 i;
+
+ for (i = 0; i < DPK_RF_REG_NUM_8851B; i++) {
+ rf_bkup[path][i] = rtw89_read_rf(rtwdev, path, rf_reg[i], RFREG_MASK);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Backup RF S%d 0x%x = %x\n",
+ path, rf_reg[i], rf_bkup[path][i]);
+ }
+}
+
+static void _dpk_reload_kip(struct rtw89_dev *rtwdev, const u32 *reg,
+ u32 reg_bkup[][DPK_KIP_REG_NUM_8851B], u8 path)
+{
+ u8 i;
+
+ for (i = 0; i < DPK_KIP_REG_NUM_8851B; i++) {
+ rtw89_phy_write32_mask(rtwdev, reg[i] + (path << 8), MASKDWORD,
+ reg_bkup[path][i]);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] Reload 0x%x = %x\n",
+ reg[i] + (path << 8), reg_bkup[path][i]);
+ }
+}
+
+static void _dpk_reload_rf(struct rtw89_dev *rtwdev, const u32 *rf_reg,
+ u32 rf_bkup[][DPK_RF_REG_NUM_8851B], u8 path)
+{
+ u8 i;
+
+ for (i = 0; i < DPK_RF_REG_NUM_8851B; i++) {
+ rtw89_write_rf(rtwdev, path, rf_reg[i], RFREG_MASK, rf_bkup[path][i]);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] Reload RF S%d 0x%x = %x\n", path,
+ rf_reg[i], rf_bkup[path][i]);
+ }
+}
+
+static void _dpk_one_shot(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, enum dpk_id id)
+{
+ u16 dpk_cmd;
+ u32 val;
+ int ret;
+
+ dpk_cmd = ((id << 8) | (0x19 + path * 0x12));
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD, dpk_cmd);
+
+ ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val == 0x55,
+ 10, 20000, false,
+ rtwdev, 0xbff8, MASKBYTE0);
+ if (ret)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] one-shot 1 timeout\n");
+
+ udelay(1);
+
+ ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val == 0x8000,
+ 1, 2000, false,
+ rtwdev, R_RPT_COM, MASKLWORD);
+ if (ret)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] one-shot 2 timeout\n");
+
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, MASKBYTE0, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] one-shot for %s = 0x%04x\n",
+ id == 0x28 ? "KIP_PRESET" :
+ id == 0x29 ? "DPK_TXAGC" :
+ id == 0x2a ? "DPK_RXAGC" :
+ id == 0x2b ? "SYNC" :
+ id == 0x2c ? "GAIN_LOSS" :
+ id == 0x2d ? "MDPK_IDL" :
+ id == 0x2f ? "DPK_GAIN_NORM" :
+ id == 0x31 ? "KIP_RESTORE" :
+ id == 0x6 ? "LBK_RXIQK" : "Unknown id",
+ dpk_cmd);
+}
+
+static void _dpk_onoff(struct rtw89_dev *rtwdev, enum rtw89_rf_path path,
+ bool off)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+ u8 kidx = dpk->cur_idx[path];
+ u8 off_reverse = off ? 0 : 1;
+ u8 val;
+
+ val = dpk->is_dpk_enable * off_reverse * dpk->bp[path][kidx].path_ok;
+
+ rtw89_phy_write32_mask(rtwdev, R_DPD_CH0A + (path << 8) + (kidx << 2),
+ 0xf0000000, val);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] DPK %s !!!\n", path,
+ kidx, val == 0 ? "disable" : "enable");
+}
+
+static void _dpk_init(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+
+ u8 kidx = dpk->cur_idx[path];
+
+ dpk->bp[path][kidx].path_ok = 0;
+}
+
+static void _dpk_information(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+
+ u8 kidx = dpk->cur_idx[path];
+
+ dpk->bp[path][kidx].band = chan->band_type;
+ dpk->bp[path][kidx].ch = chan->band_width;
+ dpk->bp[path][kidx].bw = chan->channel;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] S%d[%d] (PHY%d): TSSI %s/ DBCC %s/ %s/ CH%d/ %s\n",
+ path, dpk->cur_idx[path], phy,
+ rtwdev->is_tssi_mode[path] ? "on" : "off",
+ rtwdev->dbcc_en ? "on" : "off",
+ dpk->bp[path][kidx].band == 0 ? "2G" :
+ dpk->bp[path][kidx].band == 1 ? "5G" : "6G",
+ dpk->bp[path][kidx].ch,
+ dpk->bp[path][kidx].bw == 0 ? "20M" :
+ dpk->bp[path][kidx].bw == 1 ? "40M" :
+ dpk->bp[path][kidx].bw == 2 ? "80M" : "160M");
+}
+
+static void _dpk_rxagc_onoff(struct rtw89_dev *rtwdev, enum rtw89_rf_path path,
+ bool turn_on)
+{
+ if (path == RF_PATH_A)
+ rtw89_phy_write32_mask(rtwdev, R_P0_AGC_CTL, B_P0_AGC_EN, turn_on);
+ else
+ rtw89_phy_write32_mask(rtwdev, R_P1_AGC_CTL, B_P1_AGC_EN, turn_on);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d RXAGC is %s\n", path,
+ turn_on ? "turn_on" : "turn_off");
+}
+
+static void _dpk_bb_afe_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(16 + path), 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(20 + path), 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(24 + path), 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(28 + path), 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK + (path << 13), MASKDWORD, 0xd801dffd);
+
+ rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_bb_afe_defs_tbl);
+
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(20 + path), 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(28 + path), 0x1);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d BB/AFE setting\n", path);
+}
+
+static void _dpk_bb_afe_restore(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ rtw89_phy_write32_mask(rtwdev, R_P0_NRBW + (path << 13), B_P0_NRBW_DBG, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(16 + path), 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(20 + path), 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(24 + path), 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(28 + path), 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK + (path << 13), MASKDWORD, 0x00000000);
+ rtw89_phy_write32_mask(rtwdev, R_P0_RXCK + (path << 13), B_P0_TXCK_ALL, 0x00);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(16 + path), 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(24 + path), 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d BB/AFE restore\n", path);
+}
+
+static void _dpk_tssi_pause(struct rtw89_dev *rtwdev, enum rtw89_rf_path path,
+ bool is_pause)
+{
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK + (path << 13),
+ B_P0_TSSI_TRK_EN, is_pause);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d TSSI %s\n", path,
+ is_pause ? "pause" : "resume");
+}
+
+static void _dpk_tpg_sel(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 kidx)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+
+ if (dpk->bp[path][kidx].bw == RTW89_CHANNEL_WIDTH_80) {
+ rtw89_phy_write32_mask(rtwdev, R_TPG_MOD, B_TPG_MOD_F, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_TPG_SEL, MASKDWORD, 0xffe0fa00);
+ } else if (dpk->bp[path][kidx].bw == RTW89_CHANNEL_WIDTH_40) {
+ rtw89_phy_write32_mask(rtwdev, R_TPG_MOD, B_TPG_MOD_F, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_TPG_SEL, MASKDWORD, 0xff4009e0);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_TPG_MOD, B_TPG_MOD_F, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_TPG_SEL, MASKDWORD, 0xf9f007d0);
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] TPG Select for %s\n",
+ dpk->bp[path][kidx].bw == RTW89_CHANNEL_WIDTH_80 ? "80M" :
+ dpk->bp[path][kidx].bw == RTW89_CHANNEL_WIDTH_40 ? "40M" : "20M");
+}
+
+static void _dpk_txpwr_bb_force(struct rtw89_dev *rtwdev,
+ enum rtw89_rf_path path, bool force)
+{
+ rtw89_phy_write32_mask(rtwdev, R_TXPWRB + (path << 13), B_TXPWRB_ON, force);
+ rtw89_phy_write32_mask(rtwdev, R_TXPWRB_H + (path << 13), B_TXPWRB_RDY, force);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d txpwr_bb_force %s\n",
+ path, force ? "on" : "off");
+}
+
+static void _dpk_kip_pwr_clk_onoff(struct rtw89_dev *rtwdev, bool turn_on)
+{
+ if (turn_on) {
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_RPT, MASKDWORD, 0x00000080);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_SYSCFG, MASKDWORD, 0x807f030a);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_RPT, MASKDWORD, 0x00000000);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_SYSCFG, MASKDWORD, 0x80000000);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_WR, BIT(18), 0x1);
+ }
+}
+
+static void _dpk_kip_control_rfc(struct rtw89_dev *rtwdev,
+ enum rtw89_rf_path path, bool ctrl_by_kip)
+{
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK + (path << 13),
+ B_IQK_RFC_ON, ctrl_by_kip);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] RFC is controlled by %s\n",
+ ctrl_by_kip ? "KIP" : "BB");
+}
+
+static void _dpk_kip_preset(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, u8 kidx)
+{
+ rtw89_phy_write32_mask(rtwdev, R_KIP_MOD, B_KIP_MOD,
+ rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK));
+ rtw89_phy_write32_mask(rtwdev, R_DPD_CH0A + (path << 8) + (kidx << 2),
+ B_DPD_SEL, 0x01);
+
+ _dpk_kip_control_rfc(rtwdev, path, true);
+ _dpk_one_shot(rtwdev, phy, path, D_KIP_PRESET);
+}
+
+static void _dpk_kip_restore(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ _dpk_one_shot(rtwdev, phy, path, D_KIP_RESTORE);
+ _dpk_kip_control_rfc(rtwdev, path, false);
+ _dpk_txpwr_bb_force(rtwdev, path, false);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d restore KIP\n", path);
+}
+
+static void _dpk_kset_query(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT + (path << 8), B_KIP_RPT_SEL, 0x10);
+
+ dpk->cur_k_set =
+ rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8), B_RPT_PER_KSET) - 1;
+}
+
+static void _dpk_para_query(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 kidx)
+{
+ static const u32 reg[RTW89_DPK_BKUP_NUM][DPK_KSET_NUM] = {
+ {0x8190, 0x8194, 0x8198, 0x81a4},
+ {0x81a8, 0x81c4, 0x81c8, 0x81e8}
+ };
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+ u8 cur_k_set = dpk->cur_k_set;
+ u32 para;
+
+ if (cur_k_set >= DPK_KSET_NUM) {
+ rtw89_warn(rtwdev, "DPK cur_k_set = %d\n", cur_k_set);
+ cur_k_set = 2;
+ }
+
+ para = rtw89_phy_read32_mask(rtwdev, reg[kidx][cur_k_set] + (path << 8),
+ MASKDWORD);
+
+ dpk->bp[path][kidx].txagc_dpk = (para >> 10) & 0x3f;
+ dpk->bp[path][kidx].ther_dpk = (para >> 26) & 0x3f;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] thermal/ txagc_RF (K%d) = 0x%x/ 0x%x\n",
+ dpk->cur_k_set, dpk->bp[path][kidx].ther_dpk,
+ dpk->bp[path][kidx].txagc_dpk);
+}
+
+static bool _dpk_sync_check(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 kidx)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+ u8 corr_val, corr_idx, rxbb;
+ u16 dc_i, dc_q;
+ u8 rxbb_ov;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x0);
+
+ corr_idx = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_CORI);
+ corr_val = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_CORV);
+ dpk->corr_idx[path][kidx] = corr_idx;
+ dpk->corr_val[path][kidx] = corr_val;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x9);
+
+ dc_i = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCI);
+ dc_q = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCQ);
+
+ dc_i = abs(sign_extend32(dc_i, 11));
+ dc_q = abs(sign_extend32(dc_q, 11));
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] S%d Corr_idx/ Corr_val /DC I/Q, = %d / %d / %d / %d\n",
+ path, corr_idx, corr_val, dc_i, dc_q);
+
+ dpk->dc_i[path][kidx] = dc_i;
+ dpk->dc_q[path][kidx] = dc_q;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x8);
+ rxbb = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_RXBB);
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x31);
+ rxbb_ov = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_RXOV);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] S%d RXBB/ RXAGC_done /RXBB_ovlmt = %d / %d / %d\n",
+ path, rxbb,
+ rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DONE),
+ rxbb_ov);
+
+ if (dc_i > 200 || dc_q > 200 || corr_val < 170)
+ return true;
+ else
+ return false;
+}
+
+static void _dpk_kip_set_txagc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, u8 dbm,
+ bool set_from_bb)
+{
+ if (set_from_bb) {
+ dbm = clamp_t(u8, dbm, 7, 24);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] set S%d txagc to %ddBm\n", path, dbm);
+ rtw89_phy_write32_mask(rtwdev, R_TXPWRB + (path << 13),
+ B_TXPWRB_VAL, dbm << 2);
+ }
+
+ _dpk_one_shot(rtwdev, phy, path, D_TXAGC);
+ _dpk_kset_query(rtwdev, path);
+}
+
+static bool _dpk_kip_set_rxagc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, u8 kidx)
+{
+ _dpk_kip_control_rfc(rtwdev, path, false);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_MOD, B_KIP_MOD,
+ rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK));
+ _dpk_kip_control_rfc(rtwdev, path, true);
+
+ _dpk_one_shot(rtwdev, phy, path, D_RXAGC);
+ return _dpk_sync_check(rtwdev, path, kidx);
+}
+
+static void _dpk_lbk_rxiqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ u32 rf_11, reg_81cc;
+ u8 cur_rxbb;
+
+ rtw89_phy_write32_mask(rtwdev, R_DPD_V1 + (path << 8), B_DPD_LBK, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_MDPK_RX_DCK, B_MDPK_RX_DCK_EN, 0x1);
+
+ _dpk_kip_control_rfc(rtwdev, path, false);
+
+ cur_rxbb = rtw89_read_rf(rtwdev, path, RR_MOD, RR_MOD_RXB);
+ rf_11 = rtw89_read_rf(rtwdev, path, RR_TXIG, RFREG_MASK);
+ reg_81cc = rtw89_phy_read32_mask(rtwdev, R_KIP_IQP + (path << 8),
+ B_KIP_IQP_SW);
+
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, 0x0);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, 0x3);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, 0xd);
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RXB, 0x1f);
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8), B_KIP_IQP_IQSW, 0x12);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8), B_KIP_IQP_SW, 0x3);
+
+ _dpk_kip_control_rfc(rtwdev, path, true);
+
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, MASKDWORD, 0x00250025);
+
+ _dpk_one_shot(rtwdev, phy, path, LBK_RXIQK);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d LBK RXIQC = 0x%x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD));
+
+ _dpk_kip_control_rfc(rtwdev, path, false);
+
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RFREG_MASK, rf_11);
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RXB, cur_rxbb);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8), B_KIP_IQP_SW, reg_81cc);
+
+ rtw89_phy_write32_mask(rtwdev, R_MDPK_RX_DCK, B_MDPK_RX_DCK_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_KPATH_CFG, B_KPATH_CFG_ED, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_LOAD_COEF + (path << 8), B_LOAD_COEF_DI, 0x1);
+
+ _dpk_kip_control_rfc(rtwdev, path, true);
+}
+
+static void _dpk_rf_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 kidx)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+
+ if (dpk->bp[path][kidx].band == RTW89_BAND_2G) {
+ rtw89_write_rf(rtwdev, path, RR_MOD, RFREG_MASK, 0x50521);
+ rtw89_write_rf(rtwdev, path, RR_MOD_V1, RR_MOD_MASK, RF_DPK);
+ rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_ATTC, 0x0);
+ rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_ATTR, 0x7);
+ } else {
+ rtw89_write_rf(rtwdev, path, RR_MOD, RFREG_MASK,
+ 0x50521 | BIT(rtwdev->dbcc_en));
+ rtw89_write_rf(rtwdev, path, RR_MOD_V1, RR_MOD_MASK, RF_DPK);
+ rtw89_write_rf(rtwdev, path, RR_RXA2, RR_RAA2_SATT, 0x3);
+ }
+
+ rtw89_write_rf(rtwdev, path, RR_RCKD, RR_RCKD_BW, 0x1);
+ rtw89_write_rf(rtwdev, path, RR_BTC, RR_BTC_TXBB, dpk->bp[path][kidx].bw + 1);
+ rtw89_write_rf(rtwdev, path, RR_BTC, RR_BTC_RXBB, 0x0);
+ rtw89_write_rf(rtwdev, path, RR_RXBB2, RR_RXBB2_EBW, 0x0);
+}
+
+static void _dpk_bypass_rxiqc(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ rtw89_phy_write32_mask(rtwdev, R_DPD_V1 + (path << 8), B_DPD_LBK, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD, 0x40000002);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Bypass RXIQC\n");
+}
+
+static u16 _dpk_dgain_read(struct rtw89_dev *rtwdev)
+{
+ u16 dgain;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x0);
+ dgain = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCI);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] DGain = 0x%x\n", dgain);
+
+ return dgain;
+}
+
+static u8 _dpk_gainloss_read(struct rtw89_dev *rtwdev)
+{
+ u8 result;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x6);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_CFG2, B_DPK_CFG2_ST, 0x1);
+ result = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_GL);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] tmp GL = %d\n", result);
+
+ return result;
+}
+
+static u8 _dpk_gainloss(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, u8 kidx)
+{
+ _dpk_one_shot(rtwdev, phy, path, D_GAIN_LOSS);
+ _dpk_kip_set_txagc(rtwdev, phy, path, 0xff, false);
+
+ rtw89_phy_write32_mask(rtwdev, R_DPK_GL + (path << 8), B_DPK_GL_A1, 0xf078);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_GL + (path << 8), B_DPK_GL_A0, 0x0);
+
+ return _dpk_gainloss_read(rtwdev);
+}
+
+static u8 _dpk_pas_read(struct rtw89_dev *rtwdev, u8 is_check)
+{
+ u32 val1_i = 0, val1_q = 0, val2_i = 0, val2_q = 0;
+ u32 val1_sqrt_sum, val2_sqrt_sum;
+ u8 i;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, MASKBYTE2, 0x06);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_CFG2, B_DPK_CFG2_ST, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_CFG3, MASKBYTE2, 0x08);
+
+ if (is_check) {
+ rtw89_phy_write32_mask(rtwdev, R_DPK_CFG3, MASKBYTE3, 0x00);
+ val1_i = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKHWORD);
+ val1_i = abs(sign_extend32(val1_i, 11));
+ val1_q = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKLWORD);
+ val1_q = abs(sign_extend32(val1_q, 11));
+
+ rtw89_phy_write32_mask(rtwdev, R_DPK_CFG3, MASKBYTE3, 0x1f);
+ val2_i = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKHWORD);
+ val2_i = abs(sign_extend32(val2_i, 11));
+ val2_q = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKLWORD);
+ val2_q = abs(sign_extend32(val2_q, 11));
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] PAS_delta = 0x%x\n",
+ phy_div(val1_i * val1_i + val1_q * val1_q,
+ val2_i * val2_i + val2_q * val2_q));
+ } else {
+ for (i = 0; i < 32; i++) {
+ rtw89_phy_write32_mask(rtwdev, R_DPK_CFG3, MASKBYTE3, i);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] PAS_Read[%02d]= 0x%08x\n", i,
+ rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKDWORD));
+ }
+ }
+
+ val1_sqrt_sum = val1_i * val1_i + val1_q * val1_q;
+ val2_sqrt_sum = val2_i * val2_i + val2_q * val2_q;
+
+ if (val1_sqrt_sum < val2_sqrt_sum)
+ return 2;
+ else if (val1_sqrt_sum >= val2_sqrt_sum * 8 / 5)
+ return 1;
+ else
+ return 0;
+}
+
+static u8 _dpk_agc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, u8 kidx, u8 init_xdbm, u8 loss_only)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+ u8 tmp_dbm = init_xdbm, tmp_gl_idx = 0;
+ u8 step = DPK_AGC_STEP_SYNC_DGAIN;
+ u8 goout = 0, agc_cnt = 0;
+ bool is_fail = false;
+ int limit = 200;
+ u8 tmp_rxbb;
+ u16 dgain;
+
+ do {
+ switch (step) {
+ case DPK_AGC_STEP_SYNC_DGAIN:
+ is_fail = _dpk_kip_set_rxagc(rtwdev, phy, path, kidx);
+
+ if (is_fail) {
+ goout = 1;
+ break;
+ }
+
+ dgain = _dpk_dgain_read(rtwdev);
+
+ if (dgain > 0x5fc || dgain < 0x556) {
+ _dpk_one_shot(rtwdev, phy, path, D_SYNC);
+ dgain = _dpk_dgain_read(rtwdev);
+ }
+
+ if (agc_cnt == 0) {
+ if (dpk->bp[path][kidx].band == RTW89_BAND_2G)
+ _dpk_bypass_rxiqc(rtwdev, path);
+ else
+ _dpk_lbk_rxiqk(rtwdev, phy, path);
+ }
+ step = DPK_AGC_STEP_GAIN_LOSS_IDX;
+ break;
+
+ case DPK_AGC_STEP_GAIN_LOSS_IDX:
+ tmp_gl_idx = _dpk_gainloss(rtwdev, phy, path, kidx);
+
+ if (_dpk_pas_read(rtwdev, true) == 2 && tmp_gl_idx > 0)
+ step = DPK_AGC_STEP_GL_LT_CRITERION;
+ else if ((tmp_gl_idx == 0 && _dpk_pas_read(rtwdev, true) == 1) ||
+ tmp_gl_idx >= 7)
+ step = DPK_AGC_STEP_GL_GT_CRITERION;
+ else if (tmp_gl_idx == 0)
+ step = DPK_AGC_STEP_GL_LT_CRITERION;
+ else
+ step = DPK_AGC_STEP_SET_TX_GAIN;
+ break;
+
+ case DPK_AGC_STEP_GL_GT_CRITERION:
+ if (tmp_dbm <= 7) {
+ goout = 1;
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] Txagc@lower bound!!\n");
+ } else {
+ tmp_dbm = max_t(u8, tmp_dbm - 3, 7);
+ _dpk_kip_set_txagc(rtwdev, phy, path, tmp_dbm, true);
+ }
+ step = DPK_AGC_STEP_SYNC_DGAIN;
+ agc_cnt++;
+ break;
+
+ case DPK_AGC_STEP_GL_LT_CRITERION:
+ if (tmp_dbm >= 24) {
+ goout = 1;
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] Txagc@upper bound!!\n");
+ } else {
+ tmp_dbm = min_t(u8, tmp_dbm + 2, 24);
+ _dpk_kip_set_txagc(rtwdev, phy, path, tmp_dbm, true);
+ }
+ step = DPK_AGC_STEP_SYNC_DGAIN;
+ agc_cnt++;
+ break;
+
+ case DPK_AGC_STEP_SET_TX_GAIN:
+ _dpk_kip_control_rfc(rtwdev, path, false);
+ tmp_rxbb = rtw89_read_rf(rtwdev, path, RR_MOD, RR_MOD_RXB);
+ tmp_rxbb = min_t(u8, tmp_rxbb + tmp_gl_idx, 0x1f);
+
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RXB, tmp_rxbb);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] Adjust RXBB (%+d) = 0x%x\n",
+ tmp_gl_idx, tmp_rxbb);
+ _dpk_kip_control_rfc(rtwdev, path, true);
+ goout = 1;
+ break;
+ default:
+ goout = 1;
+ break;
+ }
+ } while (!goout && agc_cnt < 6 && limit-- > 0);
+
+ return is_fail;
+}
+
+static void _dpk_set_mdpd_para(struct rtw89_dev *rtwdev, u8 order)
+{
+ switch (order) {
+ case 0: /* (5,3,1) */
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL_SEL, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x4);
+ rtw89_phy_write32_mask(rtwdev, R_MDPK_SYNC, B_MDPK_SYNC_DMAN, 0x1);
+ break;
+ case 1: /* (5,3,0) */
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_MDPK_SYNC, B_MDPK_SYNC_DMAN, 0x0);
+ break;
+ case 2: /* (5,0,0) */
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL_SEL, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_MDPK_SYNC, B_MDPK_SYNC_DMAN, 0x0);
+ break;
+ case 3: /* (7,3,1) */
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP, 0x3);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL_SEL, 0x3);
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x4);
+ rtw89_phy_write32_mask(rtwdev, R_MDPK_SYNC, B_MDPK_SYNC_DMAN, 0x1);
+ break;
+ default:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] Wrong MDPD order!!(0x%x)\n", order);
+ break;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Set %s for IDL\n",
+ order == 0x0 ? "(5,3,1)" :
+ order == 0x1 ? "(5,3,0)" :
+ order == 0x2 ? "(5,0,0)" : "(7,3,1)");
+}
+
+static void _dpk_idl_mpa(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, u8 kidx)
+{
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_MA, 0x1);
+
+ if (rtw89_phy_read32_mask(rtwdev, R_IDL_MPA, B_IDL_MD500) == 0x1)
+ _dpk_set_mdpd_para(rtwdev, 0x2);
+ else if (rtw89_phy_read32_mask(rtwdev, R_IDL_MPA, B_IDL_MD530) == 0x1)
+ _dpk_set_mdpd_para(rtwdev, 0x1);
+ else
+ _dpk_set_mdpd_para(rtwdev, 0x0);
+
+ rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL, 0x0);
+ fsleep(1000);
+
+ _dpk_one_shot(rtwdev, phy, path, D_MDPK_IDL);
+}
+
+static u8 _dpk_order_convert(struct rtw89_dev *rtwdev)
+{
+ u32 order;
+ u8 val;
+
+ order = rtw89_phy_read32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP);
+
+ switch (order) {
+ case 0: /* (5,3,1) */
+ val = 0x6;
+ break;
+ case 1: /* (5,3,0) */
+ val = 0x2;
+ break;
+ case 2: /* (5,0,0) */
+ val = 0x0;
+ break;
+ default:
+ val = 0xff;
+ break;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] convert MDPD order to 0x%x\n", val);
+
+ return val;
+}
+
+static void _dpk_gain_normalize(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, u8 kidx, bool is_execute)
+{
+ static const u32 reg[RTW89_DPK_BKUP_NUM][DPK_KSET_NUM] = {
+ {0x8190, 0x8194, 0x8198, 0x81a4},
+ {0x81a8, 0x81c4, 0x81c8, 0x81e8}
+ };
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+ u8 cur_k_set = dpk->cur_k_set;
+
+ if (cur_k_set >= DPK_KSET_NUM) {
+ rtw89_warn(rtwdev, "DPK cur_k_set = %d\n", cur_k_set);
+ cur_k_set = 2;
+ }
+
+ if (is_execute) {
+ rtw89_phy_write32_mask(rtwdev, R_DPK_GN + (path << 8),
+ B_DPK_GN_AG, 0x200);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_GN + (path << 8),
+ B_DPK_GN_EN, 0x3);
+
+ _dpk_one_shot(rtwdev, phy, path, D_GAIN_NORM);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, reg[kidx][cur_k_set] + (path << 8),
+ 0x0000007F, 0x5b);
+ }
+
+ dpk->bp[path][kidx].gs =
+ rtw89_phy_read32_mask(rtwdev, reg[kidx][cur_k_set] + (path << 8),
+ 0x0000007F);
+}
+
+static void _dpk_on(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, u8 kidx)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+
+ rtw89_phy_write32_mask(rtwdev, R_LOAD_COEF + (path << 8), B_LOAD_COEF_MDPD, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_LOAD_COEF + (path << 8), B_LOAD_COEF_MDPD, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_DPD_CH0A + (path << 8) + (kidx << 2),
+ B_DPD_ORDER, _dpk_order_convert(rtwdev));
+
+ dpk->bp[path][kidx].path_ok =
+ dpk->bp[path][kidx].path_ok | BIT(dpk->cur_k_set);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] path_ok = 0x%x\n",
+ path, kidx, dpk->bp[path][kidx].path_ok);
+
+ rtw89_phy_write32_mask(rtwdev, R_DPD_CH0A + (path << 8) + (kidx << 2),
+ B_DPD_MEN, dpk->bp[path][kidx].path_ok);
+
+ _dpk_gain_normalize(rtwdev, phy, path, kidx, false);
+}
+
+static bool _dpk_main(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+ u8 kidx = dpk->cur_idx[path];
+ u8 init_xdbm = 17;
+ bool is_fail;
+
+ if (dpk->bp[path][kidx].band != RTW89_BAND_2G)
+ init_xdbm = 15;
+
+ _dpk_kip_control_rfc(rtwdev, path, false);
+ _rfk_rf_direct_cntrl(rtwdev, path, false);
+ rtw89_write_rf(rtwdev, path, RR_BBDC, RFREG_MASK, 0x03ffd);
+
+ _dpk_rf_setting(rtwdev, path, kidx);
+ _set_rx_dck(rtwdev, path, RF_DPK);
+
+ _dpk_kip_pwr_clk_onoff(rtwdev, true);
+ _dpk_kip_preset(rtwdev, phy, path, kidx);
+ _dpk_txpwr_bb_force(rtwdev, path, true);
+ _dpk_kip_set_txagc(rtwdev, phy, path, init_xdbm, true);
+ _dpk_tpg_sel(rtwdev, path, kidx);
+ is_fail = _dpk_agc(rtwdev, phy, path, kidx, init_xdbm, false);
+ if (is_fail)
+ goto _error;
+
+ _dpk_idl_mpa(rtwdev, phy, path, kidx);
+ _dpk_para_query(rtwdev, path, kidx);
+
+ _dpk_on(rtwdev, phy, path, kidx);
+_error:
+ _dpk_kip_control_rfc(rtwdev, path, false);
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RF_RX);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d]_K%d %s\n", path, kidx,
+ dpk->cur_k_set, is_fail ? "need Check" : "is Success");
+
+ return is_fail;
+}
+
+static void _dpk_cal_select(struct rtw89_dev *rtwdev, bool force,
+ enum rtw89_phy_idx phy, u8 kpath)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+ u32 kip_bkup[RF_PATH_NUM_8851B][DPK_KIP_REG_NUM_8851B] = {};
+ u32 rf_bkup[RF_PATH_NUM_8851B][DPK_RF_REG_NUM_8851B] = {};
+ bool is_fail;
+ u8 path;
+
+ for (path = 0; path < RF_PATH_NUM_8851B; path++)
+ dpk->cur_idx[path] = 0;
+
+ for (path = 0; path < RF_PATH_NUM_8851B; path++) {
+ if (!(kpath & BIT(path)))
+ continue;
+ _dpk_bkup_kip(rtwdev, dpk_kip_reg, kip_bkup, path);
+ _dpk_bkup_rf(rtwdev, dpk_rf_reg, rf_bkup, path);
+ _dpk_information(rtwdev, phy, path);
+ _dpk_init(rtwdev, path);
+
+ if (rtwdev->is_tssi_mode[path])
+ _dpk_tssi_pause(rtwdev, path, true);
+ }
+
+ for (path = 0; path < RF_PATH_NUM_8851B; path++) {
+ if (!(kpath & BIT(path)))
+ continue;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] ========= S%d[%d] DPK Start =========\n",
+ path, dpk->cur_idx[path]);
+
+ _dpk_rxagc_onoff(rtwdev, path, false);
+ _rfk_drf_direct_cntrl(rtwdev, path, false);
+ _dpk_bb_afe_setting(rtwdev, path);
+
+ is_fail = _dpk_main(rtwdev, phy, path);
+ _dpk_onoff(rtwdev, path, is_fail);
+ }
+
+ for (path = 0; path < RF_PATH_NUM_8851B; path++) {
+ if (!(kpath & BIT(path)))
+ continue;
+
+ _dpk_kip_restore(rtwdev, phy, path);
+ _dpk_reload_kip(rtwdev, dpk_kip_reg, kip_bkup, path);
+ _dpk_reload_rf(rtwdev, dpk_rf_reg, rf_bkup, path);
+ _dpk_bb_afe_restore(rtwdev, path);
+ _dpk_rxagc_onoff(rtwdev, path, true);
+
+ if (rtwdev->is_tssi_mode[path])
+ _dpk_tssi_pause(rtwdev, path, false);
+ }
+
+ _dpk_kip_pwr_clk_onoff(rtwdev, false);
+}
+
+static void _dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool force)
+{
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] ****** 8851B DPK Start (Ver: 0x%x, Cv: %d) ******\n",
+ DPK_VER_8851B, rtwdev->hal.cv);
+
+ _dpk_cal_select(rtwdev, force, phy, _kpath(rtwdev, phy));
+}
+
+static void _dpk_track(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+ s8 txagc_bb, txagc_bb_tp, txagc_ofst;
+ s16 pwsf_tssi_ofst;
+ s8 delta_ther = 0;
+ u8 path, kidx;
+ u8 txagc_rf;
+ u8 cur_ther;
+
+ for (path = 0; path < RF_PATH_NUM_8851B; path++) {
+ kidx = dpk->cur_idx[path];
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+ "[DPK_TRK] ================[S%d[%d] (CH %d)]================\n",
+ path, kidx, dpk->bp[path][kidx].ch);
+
+ txagc_rf = rtw89_phy_read32_mask(rtwdev, R_TXAGC_BB + (path << 13),
+ B_TXAGC_RF);
+ txagc_bb = rtw89_phy_read32_mask(rtwdev, R_TXAGC_BB + (path << 13),
+ MASKBYTE2);
+ txagc_bb_tp = rtw89_phy_read32_mask(rtwdev, R_TXAGC_BTP + (path << 13),
+ B_TXAGC_BTP);
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT + (path << 8),
+ B_KIP_RPT_SEL, 0xf);
+ cur_ther = rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8),
+ B_RPT_PER_TH);
+ txagc_ofst = rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8),
+ B_RPT_PER_OF);
+ pwsf_tssi_ofst = rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8),
+ B_RPT_PER_TSSI);
+ pwsf_tssi_ofst = sign_extend32(pwsf_tssi_ofst, 12);
+
+ delta_ther = cur_ther - dpk->bp[path][kidx].ther_dpk;
+
+ delta_ther = delta_ther * 2 / 3;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+ "[DPK_TRK] extra delta_ther = %d (0x%x / 0x%x@k)\n",
+ delta_ther, cur_ther, dpk->bp[path][kidx].ther_dpk);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+ "[DPK_TRK] delta_txagc = %d (0x%x / 0x%x@k)\n",
+ txagc_rf - dpk->bp[path][kidx].txagc_dpk,
+ txagc_rf, dpk->bp[path][kidx].txagc_dpk);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+ "[DPK_TRK] txagc_offset / pwsf_tssi_ofst = 0x%x / %+d\n",
+ txagc_ofst, pwsf_tssi_ofst);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+ "[DPK_TRK] txagc_bb_tp / txagc_bb = 0x%x / 0x%x\n",
+ txagc_bb_tp, txagc_bb);
+
+ if (rtw89_phy_read32_mask(rtwdev, R_IDL_MPA, B_IDL_DN) == 0x0 &&
+ txagc_rf != 0) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+ "[DPK_TRK] New pwsf = 0x%x\n", 0x78 - delta_ther);
+
+ rtw89_phy_write32_mask(rtwdev,
+ R_DPD_BND + (path << 8) + (kidx << 2),
+ 0x07FC0000, 0x78 - delta_ther);
+ }
+ }
+}
+
+static void _rck(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ u32 rf_reg5;
+ u32 rck_val;
+ u32 val;
+ int ret;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] ====== S%d RCK ======\n", path);
+
+ rf_reg5 = rtw89_read_rf(rtwdev, path, RR_RSV1, RFREG_MASK);
+
+ rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0);
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RR_MOD_V_RX);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] RF0x00 = 0x%05x\n",
+ rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK));
+
+ /* RCK trigger */
+ rtw89_write_rf(rtwdev, path, RR_RCKC, RFREG_MASK, 0x00240);
+
+ ret = read_poll_timeout_atomic(rtw89_read_rf, val, val, 2, 30,
+ false, rtwdev, path, RR_RCKS, BIT(3));
+
+ rck_val = rtw89_read_rf(rtwdev, path, RR_RCKC, RR_RCKC_CA);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] rck_val = 0x%x, ret = %d\n",
+ rck_val, ret);
+
+ rtw89_write_rf(rtwdev, path, RR_RCKC, RFREG_MASK, rck_val);
+ rtw89_write_rf(rtwdev, path, RR_RSV1, RFREG_MASK, rf_reg5);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] RF 0x1b = 0x%x\n",
+ rtw89_read_rf(rtwdev, path, RR_RCKC, RFREG_MASK));
+}
+
+static void _tssi_set_sys(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ enum rtw89_band band = chan->band_type;
+
+ rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_sys_defs_tbl);
+
+ rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G,
+ &rtw8851b_tssi_sys_a_defs_2g_tbl,
+ &rtw8851b_tssi_sys_a_defs_5g_tbl);
+}
+
+static void _tssi_ini_txpwr_ctrl_bb(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_init_txpwr_defs_a_tbl);
+}
+
+static void _tssi_ini_txpwr_ctrl_bb_he_tb(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_init_txpwr_he_tb_defs_a_tbl);
+}
+
+static void _tssi_set_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_dck_defs_a_tbl);
+}
+
+static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+#define RTW8851B_TSSI_GET_VAL(ptr, idx) \
+({ \
+ s8 *__ptr = (ptr); \
+ u8 __idx = (idx), __i, __v; \
+ u32 __val = 0; \
+ for (__i = 0; __i < 4; __i++) { \
+ __v = (__ptr[__idx + __i]); \
+ __val |= (__v << (8 * __i)); \
+ } \
+ __val; \
+})
+ struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ u8 ch = chan->channel;
+ u8 subband = chan->subband_type;
+ const s8 *thm_up_a = NULL;
+ const s8 *thm_down_a = NULL;
+ u8 thermal = 0xff;
+ s8 thm_ofst[64] = {0};
+ u32 tmp = 0;
+ u8 i, j;
+
+ switch (subband) {
+ default:
+ case RTW89_CH_2G:
+ thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_2ga_p;
+ thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_2ga_n;
+ break;
+ case RTW89_CH_5G_BAND_1:
+ thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_p[0];
+ thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_n[0];
+ break;
+ case RTW89_CH_5G_BAND_3:
+ thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_p[1];
+ thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_n[1];
+ break;
+ case RTW89_CH_5G_BAND_4:
+ thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_p[2];
+ thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_n[2];
+ break;
+ }
+
+ if (path == RF_PATH_A) {
+ thermal = tssi_info->thermal[RF_PATH_A];
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI] ch=%d thermal_pathA=0x%x\n", ch, thermal);
+
+ rtw89_phy_write32_mask(rtwdev, R_P0_TMETER, B_P0_TMETER_DIS, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TMETER, B_P0_TMETER_TRK, 0x1);
+
+ if (thermal == 0xff) {
+ rtw89_phy_write32_mask(rtwdev, R_P0_TMETER, B_P0_TMETER, 32);
+ rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, B_P0_RFCTM_VAL, 32);
+
+ for (i = 0; i < 64; i += 4) {
+ rtw89_phy_write32(rtwdev, R_P0_TSSI_BASE + i, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI] write 0x%x val=0x%08x\n",
+ R_P0_TSSI_BASE + i, 0x0);
+ }
+
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_P0_TMETER, B_P0_TMETER,
+ thermal);
+ rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, B_P0_RFCTM_VAL,
+ thermal);
+
+ i = 0;
+ for (j = 0; j < 32; j++)
+ thm_ofst[j] = i < DELTA_SWINGIDX_SIZE ?
+ -thm_down_a[i++] :
+ -thm_down_a[DELTA_SWINGIDX_SIZE - 1];
+
+ i = 1;
+ for (j = 63; j >= 32; j--)
+ thm_ofst[j] = i < DELTA_SWINGIDX_SIZE ?
+ thm_up_a[i++] :
+ thm_up_a[DELTA_SWINGIDX_SIZE - 1];
+
+ for (i = 0; i < 64; i += 4) {
+ tmp = RTW8851B_TSSI_GET_VAL(thm_ofst, i);
+ rtw89_phy_write32(rtwdev, R_P0_TSSI_BASE + i, tmp);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI] write 0x%x val=0x%08x\n",
+ 0x5c00 + i, tmp);
+ }
+ }
+ rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, R_P0_RFCTM_RDY, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, R_P0_RFCTM_RDY, 0x0);
+ }
+#undef RTW8851B_TSSI_GET_VAL
+}
+
+static void _tssi_set_dac_gain_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_dac_gain_defs_a_tbl);
+}
+
+static void _tssi_slope_cal_org(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ enum rtw89_band band = chan->band_type;
+
+ rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G,
+ &rtw8851b_tssi_slope_a_defs_2g_tbl,
+ &rtw8851b_tssi_slope_a_defs_5g_tbl);
+}
+
+static void _tssi_alignment_default(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, bool all)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ enum rtw89_band band = chan->band_type;
+
+ rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G,
+ &rtw8851b_tssi_align_a_2g_defs_tbl,
+ &rtw8851b_tssi_align_a_5g_defs_tbl);
+}
+
+static void _tssi_set_tssi_slope(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_slope_defs_a_tbl);
+}
+
+static void _tssi_set_tssi_track(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_track_defs_a_tbl);
+}
+
+static void _tssi_set_txagc_offset_mv_avg(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_mv_avg_defs_a_tbl);
+}
+
+static void _tssi_enable(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
+{
+ _tssi_set_tssi_track(rtwdev, phy, RF_PATH_A);
+ _tssi_set_txagc_offset_mv_avg(rtwdev, phy, RF_PATH_A);
+
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_MV_AVG, B_P0_TSSI_MV_CLR, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_AVG, B_P0_TSSI_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_AVG, B_P0_TSSI_EN, 0x1);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXGA_V1, RR_TXGA_V1_TRK_EN, 0x1);
+
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_RFC, 0x3);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT, 0xc0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x1);
+
+ rtwdev->is_tssi_mode[RF_PATH_A] = true;
+}
+
+static void _tssi_disable(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
+{
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_AVG, B_P0_TSSI_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_MV_AVG, B_P0_TSSI_MV_CLR, 0x1);
+
+ rtwdev->is_tssi_mode[RF_PATH_A] = false;
+}
+
+static u32 _tssi_get_cck_group(struct rtw89_dev *rtwdev, u8 ch)
+{
+ switch (ch) {
+ case 1 ... 2:
+ return 0;
+ case 3 ... 5:
+ return 1;
+ case 6 ... 8:
+ return 2;
+ case 9 ... 11:
+ return 3;
+ case 12 ... 13:
+ return 4;
+ case 14:
+ return 5;
+ }
+
+ return 0;
+}
+
+#define TSSI_EXTRA_GROUP_BIT (BIT(31))
+#define TSSI_EXTRA_GROUP(idx) (TSSI_EXTRA_GROUP_BIT | (idx))
+#define IS_TSSI_EXTRA_GROUP(group) ((group) & TSSI_EXTRA_GROUP_BIT)
+#define TSSI_EXTRA_GET_GROUP_IDX1(group) ((group) & ~TSSI_EXTRA_GROUP_BIT)
+#define TSSI_EXTRA_GET_GROUP_IDX2(group) (TSSI_EXTRA_GET_GROUP_IDX1(group) + 1)
+
+static u32 _tssi_get_ofdm_group(struct rtw89_dev *rtwdev, u8 ch)
+{
+ switch (ch) {
+ case 1 ... 2:
+ return 0;
+ case 3 ... 5:
+ return 1;
+ case 6 ... 8:
+ return 2;
+ case 9 ... 11:
+ return 3;
+ case 12 ... 14:
+ return 4;
+ case 36 ... 40:
+ return 5;
+ case 41 ... 43:
+ return TSSI_EXTRA_GROUP(5);
+ case 44 ... 48:
+ return 6;
+ case 49 ... 51:
+ return TSSI_EXTRA_GROUP(6);
+ case 52 ... 56:
+ return 7;
+ case 57 ... 59:
+ return TSSI_EXTRA_GROUP(7);
+ case 60 ... 64:
+ return 8;
+ case 100 ... 104:
+ return 9;
+ case 105 ... 107:
+ return TSSI_EXTRA_GROUP(9);
+ case 108 ... 112:
+ return 10;
+ case 113 ... 115:
+ return TSSI_EXTRA_GROUP(10);
+ case 116 ... 120:
+ return 11;
+ case 121 ... 123:
+ return TSSI_EXTRA_GROUP(11);
+ case 124 ... 128:
+ return 12;
+ case 129 ... 131:
+ return TSSI_EXTRA_GROUP(12);
+ case 132 ... 136:
+ return 13;
+ case 137 ... 139:
+ return TSSI_EXTRA_GROUP(13);
+ case 140 ... 144:
+ return 14;
+ case 149 ... 153:
+ return 15;
+ case 154 ... 156:
+ return TSSI_EXTRA_GROUP(15);
+ case 157 ... 161:
+ return 16;
+ case 162 ... 164:
+ return TSSI_EXTRA_GROUP(16);
+ case 165 ... 169:
+ return 17;
+ case 170 ... 172:
+ return TSSI_EXTRA_GROUP(17);
+ case 173 ... 177:
+ return 18;
+ }
+
+ return 0;
+}
+
+static u32 _tssi_get_trim_group(struct rtw89_dev *rtwdev, u8 ch)
+{
+ switch (ch) {
+ case 1 ... 8:
+ return 0;
+ case 9 ... 14:
+ return 1;
+ case 36 ... 48:
+ return 2;
+ case 52 ... 64:
+ return 3;
+ case 100 ... 112:
+ return 4;
+ case 116 ... 128:
+ return 5;
+ case 132 ... 144:
+ return 6;
+ case 149 ... 177:
+ return 7;
+ }
+
+ return 0;
+}
+
+static s8 _tssi_get_ofdm_de(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ u32 gidx, gidx_1st, gidx_2nd;
+ u8 ch = chan->channel;
+ s8 de_1st;
+ s8 de_2nd;
+ s8 val;
+
+ gidx = _tssi_get_ofdm_group(rtwdev, ch);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM]: path=%d mcs group_idx=0x%x\n", path, gidx);
+
+ if (IS_TSSI_EXTRA_GROUP(gidx)) {
+ gidx_1st = TSSI_EXTRA_GET_GROUP_IDX1(gidx);
+ gidx_2nd = TSSI_EXTRA_GET_GROUP_IDX2(gidx);
+ de_1st = tssi_info->tssi_mcs[path][gidx_1st];
+ de_2nd = tssi_info->tssi_mcs[path][gidx_2nd];
+ val = (de_1st + de_2nd) / 2;
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM]: path=%d mcs de=%d 1st=%d 2nd=%d\n",
+ path, val, de_1st, de_2nd);
+ } else {
+ val = tssi_info->tssi_mcs[path][gidx];
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM]: path=%d mcs de=%d\n", path, val);
+ }
+
+ return val;
+}
+
+static s8 _tssi_get_ofdm_trim_de(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ u32 tgidx, tgidx_1st, tgidx_2nd;
+ u8 ch = chan->channel;
+ s8 tde_1st;
+ s8 tde_2nd;
+ s8 val;
+
+ tgidx = _tssi_get_trim_group(rtwdev, ch);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM]: path=%d mcs trim_group_idx=0x%x\n",
+ path, tgidx);
+
+ if (IS_TSSI_EXTRA_GROUP(tgidx)) {
+ tgidx_1st = TSSI_EXTRA_GET_GROUP_IDX1(tgidx);
+ tgidx_2nd = TSSI_EXTRA_GET_GROUP_IDX2(tgidx);
+ tde_1st = tssi_info->tssi_trim[path][tgidx_1st];
+ tde_2nd = tssi_info->tssi_trim[path][tgidx_2nd];
+ val = (tde_1st + tde_2nd) / 2;
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM]: path=%d mcs trim_de=%d 1st=%d 2nd=%d\n",
+ path, val, tde_1st, tde_2nd);
+ } else {
+ val = tssi_info->tssi_trim[path][tgidx];
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM]: path=%d mcs trim_de=%d\n",
+ path, val);
+ }
+
+ return val;
+}
+
+static void _tssi_set_efuse_to_de(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
+{
+ struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ u8 ch = chan->channel;
+ u8 gidx;
+ s8 ofdm_de;
+ s8 trim_de;
+ s32 val;
+ u32 i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI, "[TSSI][TRIM]: phy=%d ch=%d\n",
+ phy, ch);
+
+ for (i = RF_PATH_A; i < RTW8851B_TSSI_PATH_NR; i++) {
+ gidx = _tssi_get_cck_group(rtwdev, ch);
+ trim_de = _tssi_get_ofdm_trim_de(rtwdev, phy, i);
+ val = tssi_info->tssi_cck[i][gidx] + trim_de;
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM]: path=%d cck[%d]=0x%x trim=0x%x\n",
+ i, gidx, tssi_info->tssi_cck[i][gidx], trim_de);
+
+ rtw89_phy_write32_mask(rtwdev, _tssi_de_cck_long[i], _TSSI_DE_MASK, val);
+ rtw89_phy_write32_mask(rtwdev, _tssi_de_cck_short[i], _TSSI_DE_MASK, val);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI] Set TSSI CCK DE 0x%x[21:12]=0x%x\n",
+ _tssi_de_cck_long[i],
+ rtw89_phy_read32_mask(rtwdev, _tssi_de_cck_long[i],
+ _TSSI_DE_MASK));
+
+ ofdm_de = _tssi_get_ofdm_de(rtwdev, phy, i);
+ trim_de = _tssi_get_ofdm_trim_de(rtwdev, phy, i);
+ val = ofdm_de + trim_de;
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM]: path=%d mcs=0x%x trim=0x%x\n",
+ i, ofdm_de, trim_de);
+
+ rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_20m[i], _TSSI_DE_MASK, val);
+ rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_40m[i], _TSSI_DE_MASK, val);
+ rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_80m[i], _TSSI_DE_MASK, val);
+ rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_80m_80m[i], _TSSI_DE_MASK, val);
+ rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_5m[i], _TSSI_DE_MASK, val);
+ rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_10m[i], _TSSI_DE_MASK, val);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI] Set TSSI MCS DE 0x%x[21:12]=0x%x\n",
+ _tssi_de_mcs_20m[i],
+ rtw89_phy_read32_mask(rtwdev, _tssi_de_mcs_20m[i],
+ _TSSI_DE_MASK));
+ }
+}
+
+static void _tssi_alimentk_dump_result(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[TSSI PA K]\n0x%x = 0x%08x\n0x%x = 0x%08x\n0x%x = 0x%08x\n0x%x = 0x%08x\n"
+ "0x%x = 0x%08x\n0x%x = 0x%08x\n0x%x = 0x%08x\n0x%x = 0x%08x\n",
+ R_TSSI_PA_K1 + (path << 13),
+ rtw89_phy_read32_mask(rtwdev, R_TSSI_PA_K1 + (path << 13), MASKDWORD),
+ R_TSSI_PA_K2 + (path << 13),
+ rtw89_phy_read32_mask(rtwdev, R_TSSI_PA_K2 + (path << 13), MASKDWORD),
+ R_P0_TSSI_ALIM1 + (path << 13),
+ rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_ALIM1 + (path << 13), MASKDWORD),
+ R_P0_TSSI_ALIM3 + (path << 13),
+ rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_ALIM3 + (path << 13), MASKDWORD),
+ R_TSSI_PA_K5 + (path << 13),
+ rtw89_phy_read32_mask(rtwdev, R_TSSI_PA_K5 + (path << 13), MASKDWORD),
+ R_P0_TSSI_ALIM2 + (path << 13),
+ rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_ALIM2 + (path << 13), MASKDWORD),
+ R_P0_TSSI_ALIM4 + (path << 13),
+ rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_ALIM4 + (path << 13), MASKDWORD),
+ R_TSSI_PA_K8 + (path << 13),
+ rtw89_phy_read32_mask(rtwdev, R_TSSI_PA_K8 + (path << 13), MASKDWORD));
+}
+
+static void _tssi_alimentk_done(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy, enum rtw89_rf_path path)
+{
+ struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ u8 channel = chan->channel;
+ u8 band;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "======>%s phy=%d path=%d\n", __func__, phy, path);
+
+ if (channel >= 1 && channel <= 14)
+ band = TSSI_ALIMK_2G;
+ else if (channel >= 36 && channel <= 64)
+ band = TSSI_ALIMK_5GL;
+ else if (channel >= 100 && channel <= 144)
+ band = TSSI_ALIMK_5GM;
+ else if (channel >= 149 && channel <= 177)
+ band = TSSI_ALIMK_5GH;
+ else
+ band = TSSI_ALIMK_2G;
+
+ if (tssi_info->alignment_done[path][band]) {
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_ALIM1 + (path << 13), MASKDWORD,
+ tssi_info->alignment_value[path][band][0]);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_ALIM3 + (path << 13), MASKDWORD,
+ tssi_info->alignment_value[path][band][1]);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_ALIM2 + (path << 13), MASKDWORD,
+ tssi_info->alignment_value[path][band][2]);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_ALIM4 + (path << 13), MASKDWORD,
+ tssi_info->alignment_value[path][band][3]);
+ }
+
+ _tssi_alimentk_dump_result(rtwdev, path);
+}
+
+static void rtw8851b_by_rate_dpd(struct rtw89_dev *rtwdev)
+{
+ rtw89_write32_mask(rtwdev, R_AX_PWR_SWING_OTHER_CTRL0,
+ B_AX_CFIR_BY_RATE_OFF_MASK, 0x21861);
+}
+
+void rtw8851b_dpk_init(struct rtw89_dev *rtwdev)
+{
+ rtw8851b_by_rate_dpd(rtwdev);
+}
+
+void rtw8851b_aack(struct rtw89_dev *rtwdev)
+{
+ u32 tmp05, tmpd3, ib[4];
+ u32 tmp;
+ int ret;
+ int rek;
+ int i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]DO AACK\n");
+
+ tmp05 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK);
+ tmpd3 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RFREG_MASK);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_MASK, 0x3);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_ST, 0x0);
+
+ for (rek = 0; rek < 4; rek++) {
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_AACK, RFREG_MASK, 0x8201e);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_AACK, RFREG_MASK, 0x8201f);
+ fsleep(100);
+
+ ret = read_poll_timeout_atomic(rtw89_read_rf, tmp, tmp,
+ 1, 1000, false,
+ rtwdev, RF_PATH_A, 0xd0, BIT(16));
+ if (ret)
+ rtw89_warn(rtwdev, "[LCK]AACK timeout\n");
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_VCI, RR_VCI_ON, 0x1);
+ for (i = 0; i < 4; i++) {
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_VCO, RR_VCO_SEL, i);
+ ib[i] = rtw89_read_rf(rtwdev, RF_PATH_A, RR_IBD, RR_IBD_VAL);
+ }
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_VCI, RR_VCI_ON, 0x0);
+
+ if (ib[0] != 0 && ib[1] != 0 && ib[2] != 0 && ib[3] != 0)
+ break;
+ }
+
+ if (rek != 0)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]AACK rek = %d\n", rek);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK, tmp05);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RFREG_MASK, tmpd3);
+}
+
+static void _lck_keep_thermal(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_lck_info *lck = &rtwdev->lck;
+
+ lck->thermal[RF_PATH_A] =
+ ewma_thermal_read(&rtwdev->phystat.avg_thermal[RF_PATH_A]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+ "[LCK] path=%d thermal=0x%x", RF_PATH_A, lck->thermal[RF_PATH_A]);
+}
+
+static void rtw8851b_lck(struct rtw89_dev *rtwdev)
+{
+ u32 tmp05, tmp18, tmpd3;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]DO LCK\n");
+
+ tmp05 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK);
+ tmp18 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK);
+ tmpd3 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RFREG_MASK);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_MASK, 0x3);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x1);
+
+ _set_ch(rtwdev, tmp18);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RFREG_MASK, tmpd3);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK, tmp05);
+
+ _lck_keep_thermal(rtwdev);
+}
+
+#define RTW8851B_LCK_TH 8
+
+void rtw8851b_lck_track(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_lck_info *lck = &rtwdev->lck;
+ u8 cur_thermal;
+ int delta;
+
+ cur_thermal =
+ ewma_thermal_read(&rtwdev->phystat.avg_thermal[RF_PATH_A]);
+ delta = abs((int)cur_thermal - lck->thermal[RF_PATH_A]);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+ "[LCK] path=%d current thermal=0x%x delta=0x%x\n",
+ RF_PATH_A, cur_thermal, delta);
+
+ if (delta >= RTW8851B_LCK_TH) {
+ rtw8851b_aack(rtwdev);
+ rtw8851b_lck(rtwdev);
+ }
+}
+
+void rtw8851b_lck_init(struct rtw89_dev *rtwdev)
+{
+ _lck_keep_thermal(rtwdev);
+}
+
+void rtw8851b_rck(struct rtw89_dev *rtwdev)
+{
+ _rck(rtwdev, RF_PATH_A);
+}
+
+void rtw8851b_dack(struct rtw89_dev *rtwdev)
+{
+ _dac_cal(rtwdev, false);
+}
+
+void rtw8851b_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, 0);
+ u32 tx_en;
+
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_START);
+ rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL);
+ _wait_rx_mode(rtwdev, _kpath(rtwdev, phy_idx));
+
+ _iqk_init(rtwdev);
+ _iqk(rtwdev, phy_idx, false);
+
+ rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en);
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_STOP);
+}
+
+void rtw8851b_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, 0);
+ u32 tx_en;
+
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_RXDCK, BTC_WRFK_START);
+ rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL);
+ _wait_rx_mode(rtwdev, _kpath(rtwdev, phy_idx));
+
+ _rx_dck(rtwdev, phy_idx, false);
+
+ rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en);
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_RXDCK, BTC_WRFK_STOP);
+}
+
+void rtw8851b_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, 0);
+ u32 tx_en;
+
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DPK, BTC_WRFK_START);
+ rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL);
+ _wait_rx_mode(rtwdev, _kpath(rtwdev, phy_idx));
+
+ rtwdev->dpk.is_dpk_enable = true;
+ rtwdev->dpk.is_dpk_reload_en = false;
+ _dpk(rtwdev, phy_idx, false);
+
+ rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en);
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DPK, BTC_WRFK_STOP);
+}
+
+void rtw8851b_dpk_track(struct rtw89_dev *rtwdev)
+{
+ _dpk_track(rtwdev);
+}
+
+void rtw8851b_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool hwtx_en)
+{
+ u8 phy_map = rtw89_btc_phymap(rtwdev, phy, RF_A);
+ u8 i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI, "[TSSI] %s: phy=%d\n", __func__, phy);
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_START);
+
+ _tssi_disable(rtwdev, phy);
+
+ for (i = RF_PATH_A; i < RF_PATH_NUM_8851B; i++) {
+ _tssi_set_sys(rtwdev, phy, i);
+ _tssi_ini_txpwr_ctrl_bb(rtwdev, phy, i);
+ _tssi_ini_txpwr_ctrl_bb_he_tb(rtwdev, phy, i);
+ _tssi_set_dck(rtwdev, phy, i);
+ _tssi_set_tmeter_tbl(rtwdev, phy, i);
+ _tssi_set_dac_gain_tbl(rtwdev, phy, i);
+ _tssi_slope_cal_org(rtwdev, phy, i);
+ _tssi_alignment_default(rtwdev, phy, i, true);
+ _tssi_set_tssi_slope(rtwdev, phy, i);
+ }
+
+ _tssi_enable(rtwdev, phy);
+ _tssi_set_efuse_to_de(rtwdev, phy);
+
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_STOP);
+}
+
+void rtw8851b_tssi_scan(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ u8 channel = chan->channel;
+ u32 i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "======>%s phy=%d channel=%d\n", __func__, phy, channel);
+
+ _tssi_disable(rtwdev, phy);
+
+ for (i = RF_PATH_A; i < RF_PATH_NUM_8851B; i++) {
+ _tssi_set_sys(rtwdev, phy, i);
+ _tssi_set_tmeter_tbl(rtwdev, phy, i);
+ _tssi_slope_cal_org(rtwdev, phy, i);
+ _tssi_alignment_default(rtwdev, phy, i, true);
+ }
+
+ _tssi_enable(rtwdev, phy);
+ _tssi_set_efuse_to_de(rtwdev, phy);
+}
+
+static void rtw8851b_tssi_default_txagc(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy, bool enable)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ u8 channel = chan->channel;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "======> %s ch=%d\n",
+ __func__, channel);
+
+ if (enable)
+ return;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "======>%s 1 SCAN_END Set 0x5818[7:0]=0x%x\n",
+ __func__,
+ rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT));
+
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT, 0xc0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x1);
+
+ _tssi_alimentk_done(rtwdev, phy, RF_PATH_A);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "======>%s 2 SCAN_END Set 0x5818[7:0]=0x%x\n",
+ __func__,
+ rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT));
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "======> %s SCAN_END\n", __func__);
+}
+
+void rtw8851b_wifi_scan_notify(struct rtw89_dev *rtwdev, bool scan_start,
+ enum rtw89_phy_idx phy_idx)
+{
+ if (scan_start)
+ rtw8851b_tssi_default_txagc(rtwdev, phy_idx, true);
+ else
+ rtw8851b_tssi_default_txagc(rtwdev, phy_idx, false);
+}
+
+static void _bw_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path,
+ enum rtw89_bandwidth bw, bool dav)
+{
+ u32 reg18_addr = dav ? RR_CFGCH : RR_CFGCH_V1;
+ u32 rf_reg18;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK]===> %s\n", __func__);
+
+ rf_reg18 = rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK);
+ if (rf_reg18 == INV_RF_DATA) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RFK]Invalid RF_0x18 for Path-%d\n", path);
+ return;
+ }
+ rf_reg18 &= ~RR_CFGCH_BW;
+
+ switch (bw) {
+ case RTW89_CHANNEL_WIDTH_5:
+ case RTW89_CHANNEL_WIDTH_10:
+ case RTW89_CHANNEL_WIDTH_20:
+ rf_reg18 |= FIELD_PREP(RR_CFGCH_BW, CFGCH_BW_20M);
+ break;
+ case RTW89_CHANNEL_WIDTH_40:
+ rf_reg18 |= FIELD_PREP(RR_CFGCH_BW, CFGCH_BW_40M);
+ break;
+ case RTW89_CHANNEL_WIDTH_80:
+ rf_reg18 |= FIELD_PREP(RR_CFGCH_BW, CFGCH_BW_80M);
+ break;
+ default:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK]Fail to set CH\n");
+ }
+
+ rf_reg18 &= ~(RR_CFGCH_POW_LCK | RR_CFGCH_TRX_AH | RR_CFGCH_BCN |
+ RR_CFGCH_BW2) & RFREG_MASK;
+ rf_reg18 |= RR_CFGCH_BW2;
+ rtw89_write_rf(rtwdev, path, reg18_addr, RFREG_MASK, rf_reg18);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK] set %x at path%d, %x =0x%x\n",
+ bw, path, reg18_addr,
+ rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK));
+}
+
+static void _ctrl_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_bandwidth bw)
+{
+ _bw_setting(rtwdev, RF_PATH_A, bw, true);
+ _bw_setting(rtwdev, RF_PATH_A, bw, false);
+}
+
+static bool _set_s0_arfc18(struct rtw89_dev *rtwdev, u32 val)
+{
+ u32 bak;
+ u32 tmp;
+ int ret;
+
+ bak = rtw89_read_rf(rtwdev, RF_PATH_A, RR_LDO, RFREG_MASK);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LDO, RR_LDO_SEL, 0x1);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK, val);
+
+ ret = read_poll_timeout_atomic(rtw89_read_rf, tmp, tmp == 0, 1, 1000,
+ false, rtwdev, RF_PATH_A, RR_LPF, RR_LPF_BUSY);
+ if (ret)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]LCK timeout\n");
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LDO, RFREG_MASK, bak);
+
+ return !!ret;
+}
+
+static void _lck_check(struct rtw89_dev *rtwdev)
+{
+ u32 tmp;
+
+ if (rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RR_SYNFB_LK) == 0) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]SYN MMD reset\n");
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_EN, 0x1);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_SYN, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_SYN, 0x1);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_EN, 0x0);
+ }
+
+ udelay(10);
+
+ if (rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RR_SYNFB_LK) == 0) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]re-set RF 0x18\n");
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x1);
+ tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK);
+ _set_s0_arfc18(rtwdev, tmp);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x0);
+ }
+
+ if (rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RR_SYNFB_LK) == 0) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]SYN off/on\n");
+
+ tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_POW, RFREG_MASK);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RFREG_MASK, tmp);
+ tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_SX, RFREG_MASK);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_SX, RFREG_MASK, tmp);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_SYNLUT, RR_SYNLUT_MOD, 0x1);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x3);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_SYNLUT, RR_SYNLUT_MOD, 0x0);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x1);
+ tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK);
+ _set_s0_arfc18(rtwdev, tmp);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]0xb2=%x, 0xc5=%x\n",
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_VCO, RFREG_MASK),
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RFREG_MASK));
+ }
+}
+
+static void _set_ch(struct rtw89_dev *rtwdev, u32 val)
+{
+ bool timeout;
+
+ timeout = _set_s0_arfc18(rtwdev, val);
+ if (!timeout)
+ _lck_check(rtwdev);
+}
+
+static void _ch_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path,
+ u8 central_ch, bool dav)
+{
+ u32 reg18_addr = dav ? RR_CFGCH : RR_CFGCH_V1;
+ bool is_2g_ch = central_ch <= 14;
+ u32 rf_reg18;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK]===> %s\n", __func__);
+
+ rf_reg18 = rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK);
+ rf_reg18 &= ~(RR_CFGCH_BAND1 | RR_CFGCH_POW_LCK | RR_CFGCH_TRX_AH |
+ RR_CFGCH_BCN | RR_CFGCH_BAND0 | RR_CFGCH_CH);
+ rf_reg18 |= FIELD_PREP(RR_CFGCH_CH, central_ch);
+
+ if (!is_2g_ch)
+ rf_reg18 |= FIELD_PREP(RR_CFGCH_BAND1, CFGCH_BAND1_5G) |
+ FIELD_PREP(RR_CFGCH_BAND0, CFGCH_BAND0_5G);
+
+ rf_reg18 &= ~(RR_CFGCH_POW_LCK | RR_CFGCH_TRX_AH | RR_CFGCH_BCN |
+ RR_CFGCH_BW2) & RFREG_MASK;
+ rf_reg18 |= RR_CFGCH_BW2;
+
+ if (path == RF_PATH_A && dav)
+ _set_ch(rtwdev, rf_reg18);
+ else
+ rtw89_write_rf(rtwdev, path, reg18_addr, RFREG_MASK, rf_reg18);
+
+ rtw89_write_rf(rtwdev, path, RR_LCKST, RR_LCKST_BIN, 0);
+ rtw89_write_rf(rtwdev, path, RR_LCKST, RR_LCKST_BIN, 1);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RFK]CH: %d for Path-%d, reg0x%x = 0x%x\n",
+ central_ch, path, reg18_addr,
+ rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK));
+}
+
+static void _ctrl_ch(struct rtw89_dev *rtwdev, u8 central_ch)
+{
+ _ch_setting(rtwdev, RF_PATH_A, central_ch, true);
+ _ch_setting(rtwdev, RF_PATH_A, central_ch, false);
+}
+
+static void _set_rxbb_bw(struct rtw89_dev *rtwdev, enum rtw89_bandwidth bw,
+ enum rtw89_rf_path path)
+{
+ rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x1);
+ rtw89_write_rf(rtwdev, path, RR_LUTWA, RR_LUTWA_M2, 0x12);
+
+ if (bw == RTW89_CHANNEL_WIDTH_20)
+ rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0x1b);
+ else if (bw == RTW89_CHANNEL_WIDTH_40)
+ rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0x13);
+ else if (bw == RTW89_CHANNEL_WIDTH_80)
+ rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0xb);
+ else
+ rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0x3);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK] set S%d RXBB BW 0x3F = 0x%x\n", path,
+ rtw89_read_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB));
+
+ rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x0);
+}
+
+static void _rxbb_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_bandwidth bw)
+{
+ u8 kpath, path;
+
+ kpath = _kpath(rtwdev, phy);
+
+ for (path = 0; path < RF_PATH_NUM_8851B; path++) {
+ if (!(kpath & BIT(path)))
+ continue;
+
+ _set_rxbb_bw(rtwdev, bw, path);
+ }
+}
+
+static void rtw8851b_ctrl_bw_ch(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy, u8 central_ch,
+ enum rtw89_band band, enum rtw89_bandwidth bw)
+{
+ _ctrl_ch(rtwdev, central_ch);
+ _ctrl_bw(rtwdev, phy, bw);
+ _rxbb_bw(rtwdev, phy, bw);
+}
+
+void rtw8851b_set_channel_rf(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ rtw8851b_ctrl_bw_ch(rtwdev, phy_idx, chan->channel, chan->band_type,
+ chan->band_width);
+}
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.h b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.h
new file mode 100644
index 000000000000..b66a23d6d367
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2022-2023 Realtek Corporation
+ */
+
+#ifndef __RTW89_8851B_RFK_H__
+#define __RTW89_8851B_RFK_H__
+
+#include "core.h"
+
+void rtw8851b_aack(struct rtw89_dev *rtwdev);
+void rtw8851b_lck_init(struct rtw89_dev *rtwdev);
+void rtw8851b_lck_track(struct rtw89_dev *rtwdev);
+void rtw8851b_rck(struct rtw89_dev *rtwdev);
+void rtw8851b_dack(struct rtw89_dev *rtwdev);
+void rtw8851b_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
+void rtw8851b_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
+void rtw8851b_dpk_init(struct rtw89_dev *rtwdev);
+void rtw8851b_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy);
+void rtw8851b_dpk_track(struct rtw89_dev *rtwdev);
+void rtw8851b_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool hwtx_en);
+void rtw8851b_tssi_scan(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy);
+void rtw8851b_wifi_scan_notify(struct rtw89_dev *rtwdev, bool scan_start,
+ enum rtw89_phy_idx phy_idx);
+void rtw8851b_set_channel_rf(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx);
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c
index bb724140df4f..c447f91a4bd0 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c
@@ -1273,6 +1273,25 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_radioa_regs[] = {
{0xF0010000, 0x00000000},
{0xF0020000, 0x00000001},
{0xF0030000, 0x00000002},
+ {0xF0010001, 0x00000003},
+ {0xF0020001, 0x00000004},
+ {0xF0030001, 0x00000005},
+ {0xF0040001, 0x00000006},
+ {0xF0050001, 0x00000007},
+ {0xF0060001, 0x00000008},
+ {0x000, 0x00000000},
+ {0x0EF, 0x00080000},
+ {0x033, 0x00000003},
+ {0x03E, 0x00000150},
+ {0x03F, 0x0000D79C},
+ {0x0EF, 0x00000000},
+ {0x052, 0x000C3338},
+ {0x053, 0x000608AF},
+ {0x054, 0x00006C04},
+ {0x063, 0x000FC082},
+ {0x065, 0x00018122},
+ {0x000, 0x00010000},
+ {0x0FE, 0x0000005A},
{0x000, 0x00030000},
{0x018, 0x00013124},
{0x0EF, 0x00080000},
@@ -1834,8 +1853,6 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_radioa_regs[] = {
{0x059, 0x00050033},
{0x061, 0x0005F48A},
{0x062, 0x00077435},
- {0x063, 0x000F80A2},
- {0x065, 0x00018F22},
{0x067, 0x00008060},
{0x07E, 0x0009780B},
{0x0EE, 0x00000004},
@@ -2074,9 +2091,6 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_radioa_regs[] = {
{0x03F, 0x0001C3C3},
{0x0EF, 0x00000000},
{0x051, 0x0003D368},
- {0x052, 0x000A3338},
- {0x053, 0x000688AF},
- {0x054, 0x00012C04},
{0x058, 0x00084221},
{0x05B, 0x000EB000},
{0x100EE, 0x00002000},
@@ -2229,9 +2243,11 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_radioa_regs[] = {
{0x033, 0x00000000},
{0x03F, 0x00000004},
{0x0EF, 0x00000000},
+ {0x000, 0x00010000},
+ {0x0FE, 0x0000005A},
{0x005, 0x00000001},
{0x10005, 0x00000001},
- {0x0FE, 0x00000022},
+ {0x0FE, 0x00000028},
};
static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = {
@@ -2306,7 +2322,7 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = {
{0x8144, 0x0b040b03},
{0x8148, 0x07020b04},
{0x814c, 0x07020b04},
- {0x8150, 0xe4e40000},
+ {0x8150, 0xa0a00000},
{0x8158, 0xffffffff},
{0x815c, 0xffffffff},
{0x8160, 0xffffffff},
@@ -3305,7 +3321,7 @@ static const s8 _txpwr_track_delta_swingidx_2g_cck_a_p[] = {
0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4
};
-const u8 rtw89_8851b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
+const u8 rtw89_8851b_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM]
[RTW89_REGD_NUM] = {
[0][0][RTW89_ACMA] = 0,
[0][0][RTW89_CN] = 0,
@@ -3326,8 +3342,8 @@ const u8 rtw89_8851b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
[1][1][RTW89_ACMA] = 0,
[1][1][RTW89_CN] = 0,
[1][1][RTW89_ETSI] = 0,
- [1][1][RTW89_FCC] = 3,
- [1][1][RTW89_IC] = 3,
+ [1][1][RTW89_FCC] = 1,
+ [1][1][RTW89_IC] = 1,
[1][1][RTW89_KCC] = 0,
[1][1][RTW89_MKK] = 0,
[1][1][RTW89_UK] = 0,
@@ -4880,9 +4896,9 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_WW][42] = 30,
[0][0][1][0][RTW89_WW][44] = 30,
[0][0][1][0][RTW89_WW][46] = 30,
- [0][0][1][0][RTW89_WW][48] = 72,
- [0][0][1][0][RTW89_WW][50] = 72,
- [0][0][1][0][RTW89_WW][52] = 72,
+ [0][0][1][0][RTW89_WW][48] = 68,
+ [0][0][1][0][RTW89_WW][50] = 68,
+ [0][0][1][0][RTW89_WW][52] = 68,
[0][1][1][0][RTW89_WW][0] = 0,
[0][1][1][0][RTW89_WW][2] = 0,
[0][1][1][0][RTW89_WW][4] = 0,
@@ -4936,9 +4952,9 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_WW][42] = 30,
[0][0][2][0][RTW89_WW][44] = 30,
[0][0][2][0][RTW89_WW][46] = 30,
- [0][0][2][0][RTW89_WW][48] = 74,
- [0][0][2][0][RTW89_WW][50] = 76,
- [0][0][2][0][RTW89_WW][52] = 76,
+ [0][0][2][0][RTW89_WW][48] = 70,
+ [0][0][2][0][RTW89_WW][50] = 72,
+ [0][0][2][0][RTW89_WW][52] = 72,
[0][1][2][0][RTW89_WW][0] = 0,
[0][1][2][0][RTW89_WW][2] = 0,
[0][1][2][0][RTW89_WW][4] = 0,
@@ -4995,11 +5011,11 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_WW][48] = 0,
[0][1][2][1][RTW89_WW][50] = 0,
[0][1][2][1][RTW89_WW][52] = 0,
- [1][0][2][0][RTW89_WW][1] = 64,
+ [1][0][2][0][RTW89_WW][1] = 60,
[1][0][2][0][RTW89_WW][5] = 62,
[1][0][2][0][RTW89_WW][9] = 64,
- [1][0][2][0][RTW89_WW][13] = 64,
- [1][0][2][0][RTW89_WW][16] = 66,
+ [1][0][2][0][RTW89_WW][13] = 60,
+ [1][0][2][0][RTW89_WW][16] = 62,
[1][0][2][0][RTW89_WW][20] = 66,
[1][0][2][0][RTW89_WW][24] = 66,
[1][0][2][0][RTW89_WW][28] = 66,
@@ -5007,8 +5023,8 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_WW][36] = 76,
[1][0][2][0][RTW89_WW][39] = 30,
[1][0][2][0][RTW89_WW][43] = 30,
- [1][0][2][0][RTW89_WW][47] = 84,
- [1][0][2][0][RTW89_WW][51] = 84,
+ [1][0][2][0][RTW89_WW][47] = 80,
+ [1][0][2][0][RTW89_WW][51] = 80,
[1][1][2][0][RTW89_WW][1] = 0,
[1][1][2][0][RTW89_WW][5] = 0,
[1][1][2][0][RTW89_WW][9] = 0,
@@ -5037,13 +5053,13 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_WW][43] = 0,
[1][1][2][1][RTW89_WW][47] = 0,
[1][1][2][1][RTW89_WW][51] = 0,
- [2][0][2][0][RTW89_WW][3] = 62,
- [2][0][2][0][RTW89_WW][11] = 62,
- [2][0][2][0][RTW89_WW][18] = 64,
+ [2][0][2][0][RTW89_WW][3] = 60,
+ [2][0][2][0][RTW89_WW][11] = 58,
+ [2][0][2][0][RTW89_WW][18] = 62,
[2][0][2][0][RTW89_WW][26] = 64,
[2][0][2][0][RTW89_WW][34] = 72,
[2][0][2][0][RTW89_WW][41] = 30,
- [2][0][2][0][RTW89_WW][49] = 74,
+ [2][0][2][0][RTW89_WW][49] = 70,
[2][1][2][0][RTW89_WW][3] = 0,
[2][1][2][0][RTW89_WW][11] = 0,
[2][1][2][0][RTW89_WW][18] = 0,
@@ -5067,7 +5083,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][1][RTW89_WW][7] = 0,
[3][1][2][1][RTW89_WW][22] = 0,
[3][1][2][1][RTW89_WW][45] = 0,
- [0][0][1][0][RTW89_FCC][0] = 80,
+ [0][0][1][0][RTW89_FCC][0] = 76,
[0][0][1][0][RTW89_ETSI][0] = 58,
[0][0][1][0][RTW89_MKK][0] = 60,
[0][0][1][0][RTW89_IC][0] = 62,
@@ -5123,7 +5139,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][12] = 58,
[0][0][1][0][RTW89_CN][12] = 60,
[0][0][1][0][RTW89_UK][12] = 58,
- [0][0][1][0][RTW89_FCC][14] = 78,
+ [0][0][1][0][RTW89_FCC][14] = 74,
[0][0][1][0][RTW89_ETSI][14] = 58,
[0][0][1][0][RTW89_MKK][14] = 60,
[0][0][1][0][RTW89_IC][14] = 64,
@@ -5131,10 +5147,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][14] = 58,
[0][0][1][0][RTW89_CN][14] = 60,
[0][0][1][0][RTW89_UK][14] = 58,
- [0][0][1][0][RTW89_FCC][15] = 78,
+ [0][0][1][0][RTW89_FCC][15] = 74,
[0][0][1][0][RTW89_ETSI][15] = 58,
[0][0][1][0][RTW89_MKK][15] = 78,
- [0][0][1][0][RTW89_IC][15] = 78,
+ [0][0][1][0][RTW89_IC][15] = 74,
[0][0][1][0][RTW89_KCC][15] = 78,
[0][0][1][0][RTW89_ACMA][15] = 58,
[0][0][1][0][RTW89_CN][15] = 127,
@@ -5211,10 +5227,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][33] = 60,
[0][0][1][0][RTW89_CN][33] = 127,
[0][0][1][0][RTW89_UK][33] = 60,
- [0][0][1][0][RTW89_FCC][35] = 72,
+ [0][0][1][0][RTW89_FCC][35] = 68,
[0][0][1][0][RTW89_ETSI][35] = 60,
[0][0][1][0][RTW89_MKK][35] = 78,
- [0][0][1][0][RTW89_IC][35] = 72,
+ [0][0][1][0][RTW89_IC][35] = 68,
[0][0][1][0][RTW89_KCC][35] = 74,
[0][0][1][0][RTW89_ACMA][35] = 60,
[0][0][1][0][RTW89_CN][35] = 127,
@@ -5267,7 +5283,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][46] = 78,
[0][0][1][0][RTW89_CN][46] = 78,
[0][0][1][0][RTW89_UK][46] = 58,
- [0][0][1][0][RTW89_FCC][48] = 72,
+ [0][0][1][0][RTW89_FCC][48] = 68,
[0][0][1][0][RTW89_ETSI][48] = 127,
[0][0][1][0][RTW89_MKK][48] = 127,
[0][0][1][0][RTW89_IC][48] = 127,
@@ -5275,7 +5291,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][48] = 127,
[0][0][1][0][RTW89_CN][48] = 127,
[0][0][1][0][RTW89_UK][48] = 127,
- [0][0][1][0][RTW89_FCC][50] = 72,
+ [0][0][1][0][RTW89_FCC][50] = 68,
[0][0][1][0][RTW89_ETSI][50] = 127,
[0][0][1][0][RTW89_MKK][50] = 127,
[0][0][1][0][RTW89_IC][50] = 127,
@@ -5283,7 +5299,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][50] = 127,
[0][0][1][0][RTW89_CN][50] = 127,
[0][0][1][0][RTW89_UK][50] = 127,
- [0][0][1][0][RTW89_FCC][52] = 72,
+ [0][0][1][0][RTW89_FCC][52] = 68,
[0][0][1][0][RTW89_ETSI][52] = 127,
[0][0][1][0][RTW89_MKK][52] = 127,
[0][0][1][0][RTW89_IC][52] = 127,
@@ -5515,7 +5531,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][52] = 127,
[0][1][1][0][RTW89_CN][52] = 127,
[0][1][1][0][RTW89_UK][52] = 127,
- [0][0][2][0][RTW89_FCC][0] = 78,
+ [0][0][2][0][RTW89_FCC][0] = 74,
[0][0][2][0][RTW89_ETSI][0] = 62,
[0][0][2][0][RTW89_MKK][0] = 62,
[0][0][2][0][RTW89_IC][0] = 64,
@@ -5571,7 +5587,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][12] = 62,
[0][0][2][0][RTW89_CN][12] = 62,
[0][0][2][0][RTW89_UK][12] = 62,
- [0][0][2][0][RTW89_FCC][14] = 76,
+ [0][0][2][0][RTW89_FCC][14] = 72,
[0][0][2][0][RTW89_ETSI][14] = 62,
[0][0][2][0][RTW89_MKK][14] = 62,
[0][0][2][0][RTW89_IC][14] = 64,
@@ -5579,10 +5595,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][14] = 62,
[0][0][2][0][RTW89_CN][14] = 62,
[0][0][2][0][RTW89_UK][14] = 62,
- [0][0][2][0][RTW89_FCC][15] = 76,
+ [0][0][2][0][RTW89_FCC][15] = 72,
[0][0][2][0][RTW89_ETSI][15] = 60,
[0][0][2][0][RTW89_MKK][15] = 78,
- [0][0][2][0][RTW89_IC][15] = 76,
+ [0][0][2][0][RTW89_IC][15] = 72,
[0][0][2][0][RTW89_KCC][15] = 78,
[0][0][2][0][RTW89_ACMA][15] = 60,
[0][0][2][0][RTW89_CN][15] = 127,
@@ -5659,10 +5675,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][33] = 62,
[0][0][2][0][RTW89_CN][33] = 127,
[0][0][2][0][RTW89_UK][33] = 62,
- [0][0][2][0][RTW89_FCC][35] = 72,
+ [0][0][2][0][RTW89_FCC][35] = 68,
[0][0][2][0][RTW89_ETSI][35] = 62,
[0][0][2][0][RTW89_MKK][35] = 78,
- [0][0][2][0][RTW89_IC][35] = 72,
+ [0][0][2][0][RTW89_IC][35] = 68,
[0][0][2][0][RTW89_KCC][35] = 74,
[0][0][2][0][RTW89_ACMA][35] = 62,
[0][0][2][0][RTW89_CN][35] = 127,
@@ -5715,7 +5731,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][46] = 78,
[0][0][2][0][RTW89_CN][46] = 78,
[0][0][2][0][RTW89_UK][46] = 60,
- [0][0][2][0][RTW89_FCC][48] = 74,
+ [0][0][2][0][RTW89_FCC][48] = 70,
[0][0][2][0][RTW89_ETSI][48] = 127,
[0][0][2][0][RTW89_MKK][48] = 127,
[0][0][2][0][RTW89_IC][48] = 127,
@@ -5723,7 +5739,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][48] = 127,
[0][0][2][0][RTW89_CN][48] = 127,
[0][0][2][0][RTW89_UK][48] = 127,
- [0][0][2][0][RTW89_FCC][50] = 76,
+ [0][0][2][0][RTW89_FCC][50] = 72,
[0][0][2][0][RTW89_ETSI][50] = 127,
[0][0][2][0][RTW89_MKK][50] = 127,
[0][0][2][0][RTW89_IC][50] = 127,
@@ -5731,7 +5747,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][50] = 127,
[0][0][2][0][RTW89_CN][50] = 127,
[0][0][2][0][RTW89_UK][50] = 127,
- [0][0][2][0][RTW89_FCC][52] = 76,
+ [0][0][2][0][RTW89_FCC][52] = 72,
[0][0][2][0][RTW89_ETSI][52] = 127,
[0][0][2][0][RTW89_MKK][52] = 127,
[0][0][2][0][RTW89_IC][52] = 127,
@@ -6187,10 +6203,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][52] = 127,
[0][1][2][1][RTW89_CN][52] = 127,
[0][1][2][1][RTW89_UK][52] = 127,
- [1][0][2][0][RTW89_FCC][1] = 68,
+ [1][0][2][0][RTW89_FCC][1] = 64,
[1][0][2][0][RTW89_ETSI][1] = 64,
[1][0][2][0][RTW89_MKK][1] = 64,
- [1][0][2][0][RTW89_IC][1] = 64,
+ [1][0][2][0][RTW89_IC][1] = 60,
[1][0][2][0][RTW89_KCC][1] = 74,
[1][0][2][0][RTW89_ACMA][1] = 64,
[1][0][2][0][RTW89_CN][1] = 64,
@@ -6211,18 +6227,18 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][9] = 64,
[1][0][2][0][RTW89_CN][9] = 64,
[1][0][2][0][RTW89_UK][9] = 64,
- [1][0][2][0][RTW89_FCC][13] = 66,
+ [1][0][2][0][RTW89_FCC][13] = 62,
[1][0][2][0][RTW89_ETSI][13] = 64,
[1][0][2][0][RTW89_MKK][13] = 64,
- [1][0][2][0][RTW89_IC][13] = 64,
+ [1][0][2][0][RTW89_IC][13] = 60,
[1][0][2][0][RTW89_KCC][13] = 72,
[1][0][2][0][RTW89_ACMA][13] = 64,
[1][0][2][0][RTW89_CN][13] = 64,
[1][0][2][0][RTW89_UK][13] = 64,
- [1][0][2][0][RTW89_FCC][16] = 66,
+ [1][0][2][0][RTW89_FCC][16] = 62,
[1][0][2][0][RTW89_ETSI][16] = 66,
[1][0][2][0][RTW89_MKK][16] = 80,
- [1][0][2][0][RTW89_IC][16] = 66,
+ [1][0][2][0][RTW89_IC][16] = 62,
[1][0][2][0][RTW89_KCC][16] = 74,
[1][0][2][0][RTW89_ACMA][16] = 66,
[1][0][2][0][RTW89_CN][16] = 127,
@@ -6230,7 +6246,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_FCC][20] = 80,
[1][0][2][0][RTW89_ETSI][20] = 66,
[1][0][2][0][RTW89_MKK][20] = 80,
- [1][0][2][0][RTW89_IC][20] = 80,
+ [1][0][2][0][RTW89_IC][20] = 76,
[1][0][2][0][RTW89_KCC][20] = 74,
[1][0][2][0][RTW89_ACMA][20] = 66,
[1][0][2][0][RTW89_CN][20] = 127,
@@ -6251,10 +6267,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][28] = 127,
[1][0][2][0][RTW89_CN][28] = 127,
[1][0][2][0][RTW89_UK][28] = 66,
- [1][0][2][0][RTW89_FCC][32] = 76,
+ [1][0][2][0][RTW89_FCC][32] = 72,
[1][0][2][0][RTW89_ETSI][32] = 66,
[1][0][2][0][RTW89_MKK][32] = 80,
- [1][0][2][0][RTW89_IC][32] = 76,
+ [1][0][2][0][RTW89_IC][32] = 72,
[1][0][2][0][RTW89_KCC][32] = 78,
[1][0][2][0][RTW89_ACMA][32] = 66,
[1][0][2][0][RTW89_CN][32] = 127,
@@ -6270,7 +6286,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_FCC][39] = 84,
[1][0][2][0][RTW89_ETSI][39] = 30,
[1][0][2][0][RTW89_MKK][39] = 127,
- [1][0][2][0][RTW89_IC][39] = 84,
+ [1][0][2][0][RTW89_IC][39] = 80,
[1][0][2][0][RTW89_KCC][39] = 68,
[1][0][2][0][RTW89_ACMA][39] = 80,
[1][0][2][0][RTW89_CN][39] = 70,
@@ -6283,7 +6299,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][43] = 80,
[1][0][2][0][RTW89_CN][43] = 80,
[1][0][2][0][RTW89_UK][43] = 64,
- [1][0][2][0][RTW89_FCC][47] = 84,
+ [1][0][2][0][RTW89_FCC][47] = 80,
[1][0][2][0][RTW89_ETSI][47] = 127,
[1][0][2][0][RTW89_MKK][47] = 127,
[1][0][2][0][RTW89_IC][47] = 127,
@@ -6291,7 +6307,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][47] = 127,
[1][0][2][0][RTW89_CN][47] = 127,
[1][0][2][0][RTW89_UK][47] = 127,
- [1][0][2][0][RTW89_FCC][51] = 84,
+ [1][0][2][0][RTW89_FCC][51] = 80,
[1][0][2][0][RTW89_ETSI][51] = 127,
[1][0][2][0][RTW89_MKK][51] = 127,
[1][0][2][0][RTW89_IC][51] = 127,
@@ -6523,26 +6539,26 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][51] = 127,
[1][1][2][1][RTW89_CN][51] = 127,
[1][1][2][1][RTW89_UK][51] = 127,
- [2][0][2][0][RTW89_FCC][3] = 76,
+ [2][0][2][0][RTW89_FCC][3] = 72,
[2][0][2][0][RTW89_ETSI][3] = 64,
[2][0][2][0][RTW89_MKK][3] = 62,
- [2][0][2][0][RTW89_IC][3] = 64,
+ [2][0][2][0][RTW89_IC][3] = 60,
[2][0][2][0][RTW89_KCC][3] = 72,
[2][0][2][0][RTW89_ACMA][3] = 64,
[2][0][2][0][RTW89_CN][3] = 64,
[2][0][2][0][RTW89_UK][3] = 64,
- [2][0][2][0][RTW89_FCC][11] = 64,
+ [2][0][2][0][RTW89_FCC][11] = 60,
[2][0][2][0][RTW89_ETSI][11] = 64,
[2][0][2][0][RTW89_MKK][11] = 64,
- [2][0][2][0][RTW89_IC][11] = 62,
+ [2][0][2][0][RTW89_IC][11] = 58,
[2][0][2][0][RTW89_KCC][11] = 72,
[2][0][2][0][RTW89_ACMA][11] = 64,
[2][0][2][0][RTW89_CN][11] = 64,
[2][0][2][0][RTW89_UK][11] = 64,
- [2][0][2][0][RTW89_FCC][18] = 66,
+ [2][0][2][0][RTW89_FCC][18] = 62,
[2][0][2][0][RTW89_ETSI][18] = 64,
[2][0][2][0][RTW89_MKK][18] = 72,
- [2][0][2][0][RTW89_IC][18] = 66,
+ [2][0][2][0][RTW89_IC][18] = 62,
[2][0][2][0][RTW89_KCC][18] = 72,
[2][0][2][0][RTW89_ACMA][18] = 64,
[2][0][2][0][RTW89_CN][18] = 127,
@@ -6558,7 +6574,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_FCC][34] = 76,
[2][0][2][0][RTW89_ETSI][34] = 127,
[2][0][2][0][RTW89_MKK][34] = 72,
- [2][0][2][0][RTW89_IC][34] = 76,
+ [2][0][2][0][RTW89_IC][34] = 72,
[2][0][2][0][RTW89_KCC][34] = 72,
[2][0][2][0][RTW89_ACMA][34] = 72,
[2][0][2][0][RTW89_CN][34] = 127,
@@ -6566,12 +6582,12 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_FCC][41] = 76,
[2][0][2][0][RTW89_ETSI][41] = 30,
[2][0][2][0][RTW89_MKK][41] = 127,
- [2][0][2][0][RTW89_IC][41] = 76,
+ [2][0][2][0][RTW89_IC][41] = 72,
[2][0][2][0][RTW89_KCC][41] = 64,
[2][0][2][0][RTW89_ACMA][41] = 72,
[2][0][2][0][RTW89_CN][41] = 72,
[2][0][2][0][RTW89_UK][41] = 64,
- [2][0][2][0][RTW89_FCC][49] = 74,
+ [2][0][2][0][RTW89_FCC][49] = 70,
[2][0][2][0][RTW89_ETSI][49] = 127,
[2][0][2][0][RTW89_MKK][49] = 127,
[2][0][2][0][RTW89_IC][49] = 127,
@@ -10590,9 +10606,9 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_WW][42] = 30,
[0][0][1][0][RTW89_WW][44] = 30,
[0][0][1][0][RTW89_WW][46] = 30,
- [0][0][1][0][RTW89_WW][48] = 72,
- [0][0][1][0][RTW89_WW][50] = 72,
- [0][0][1][0][RTW89_WW][52] = 72,
+ [0][0][1][0][RTW89_WW][48] = 68,
+ [0][0][1][0][RTW89_WW][50] = 68,
+ [0][0][1][0][RTW89_WW][52] = 68,
[0][1][1][0][RTW89_WW][0] = 0,
[0][1][1][0][RTW89_WW][2] = 0,
[0][1][1][0][RTW89_WW][4] = 0,
@@ -10646,9 +10662,9 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_WW][42] = 30,
[0][0][2][0][RTW89_WW][44] = 30,
[0][0][2][0][RTW89_WW][46] = 30,
- [0][0][2][0][RTW89_WW][48] = 74,
- [0][0][2][0][RTW89_WW][50] = 74,
- [0][0][2][0][RTW89_WW][52] = 74,
+ [0][0][2][0][RTW89_WW][48] = 70,
+ [0][0][2][0][RTW89_WW][50] = 70,
+ [0][0][2][0][RTW89_WW][52] = 70,
[0][1][2][0][RTW89_WW][0] = 0,
[0][1][2][0][RTW89_WW][2] = 0,
[0][1][2][0][RTW89_WW][4] = 0,
@@ -10705,11 +10721,11 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_WW][48] = 0,
[0][1][2][1][RTW89_WW][50] = 0,
[0][1][2][1][RTW89_WW][52] = 0,
- [1][0][2][0][RTW89_WW][1] = 64,
+ [1][0][2][0][RTW89_WW][1] = 60,
[1][0][2][0][RTW89_WW][5] = 62,
[1][0][2][0][RTW89_WW][9] = 64,
- [1][0][2][0][RTW89_WW][13] = 64,
- [1][0][2][0][RTW89_WW][16] = 66,
+ [1][0][2][0][RTW89_WW][13] = 60,
+ [1][0][2][0][RTW89_WW][16] = 62,
[1][0][2][0][RTW89_WW][20] = 66,
[1][0][2][0][RTW89_WW][24] = 66,
[1][0][2][0][RTW89_WW][28] = 66,
@@ -10717,8 +10733,8 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_WW][36] = 76,
[1][0][2][0][RTW89_WW][39] = 30,
[1][0][2][0][RTW89_WW][43] = 30,
- [1][0][2][0][RTW89_WW][47] = 80,
- [1][0][2][0][RTW89_WW][51] = 80,
+ [1][0][2][0][RTW89_WW][47] = 76,
+ [1][0][2][0][RTW89_WW][51] = 76,
[1][1][2][0][RTW89_WW][1] = 0,
[1][1][2][0][RTW89_WW][5] = 0,
[1][1][2][0][RTW89_WW][9] = 0,
@@ -10747,13 +10763,13 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_WW][43] = 0,
[1][1][2][1][RTW89_WW][47] = 0,
[1][1][2][1][RTW89_WW][51] = 0,
- [2][0][2][0][RTW89_WW][3] = 62,
- [2][0][2][0][RTW89_WW][11] = 62,
- [2][0][2][0][RTW89_WW][18] = 64,
+ [2][0][2][0][RTW89_WW][3] = 60,
+ [2][0][2][0][RTW89_WW][11] = 58,
+ [2][0][2][0][RTW89_WW][18] = 62,
[2][0][2][0][RTW89_WW][26] = 64,
[2][0][2][0][RTW89_WW][34] = 68,
[2][0][2][0][RTW89_WW][41] = 30,
- [2][0][2][0][RTW89_WW][49] = 72,
+ [2][0][2][0][RTW89_WW][49] = 68,
[2][1][2][0][RTW89_WW][3] = 0,
[2][1][2][0][RTW89_WW][11] = 0,
[2][1][2][0][RTW89_WW][18] = 0,
@@ -10777,7 +10793,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][1][RTW89_WW][7] = 0,
[3][1][2][1][RTW89_WW][22] = 0,
[3][1][2][1][RTW89_WW][45] = 0,
- [0][0][1][0][RTW89_FCC][0] = 78,
+ [0][0][1][0][RTW89_FCC][0] = 74,
[0][0][1][0][RTW89_ETSI][0] = 58,
[0][0][1][0][RTW89_MKK][0] = 60,
[0][0][1][0][RTW89_IC][0] = 62,
@@ -10833,7 +10849,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][12] = 58,
[0][0][1][0][RTW89_CN][12] = 60,
[0][0][1][0][RTW89_UK][12] = 58,
- [0][0][1][0][RTW89_FCC][14] = 76,
+ [0][0][1][0][RTW89_FCC][14] = 72,
[0][0][1][0][RTW89_ETSI][14] = 58,
[0][0][1][0][RTW89_MKK][14] = 60,
[0][0][1][0][RTW89_IC][14] = 62,
@@ -10841,10 +10857,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][14] = 58,
[0][0][1][0][RTW89_CN][14] = 60,
[0][0][1][0][RTW89_UK][14] = 58,
- [0][0][1][0][RTW89_FCC][15] = 76,
+ [0][0][1][0][RTW89_FCC][15] = 72,
[0][0][1][0][RTW89_ETSI][15] = 58,
[0][0][1][0][RTW89_MKK][15] = 74,
- [0][0][1][0][RTW89_IC][15] = 76,
+ [0][0][1][0][RTW89_IC][15] = 72,
[0][0][1][0][RTW89_KCC][15] = 74,
[0][0][1][0][RTW89_ACMA][15] = 58,
[0][0][1][0][RTW89_CN][15] = 127,
@@ -10921,10 +10937,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][33] = 60,
[0][0][1][0][RTW89_CN][33] = 127,
[0][0][1][0][RTW89_UK][33] = 60,
- [0][0][1][0][RTW89_FCC][35] = 70,
+ [0][0][1][0][RTW89_FCC][35] = 66,
[0][0][1][0][RTW89_ETSI][35] = 60,
[0][0][1][0][RTW89_MKK][35] = 74,
- [0][0][1][0][RTW89_IC][35] = 70,
+ [0][0][1][0][RTW89_IC][35] = 66,
[0][0][1][0][RTW89_KCC][35] = 74,
[0][0][1][0][RTW89_ACMA][35] = 60,
[0][0][1][0][RTW89_CN][35] = 127,
@@ -10977,7 +10993,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][46] = 74,
[0][0][1][0][RTW89_CN][46] = 74,
[0][0][1][0][RTW89_UK][46] = 58,
- [0][0][1][0][RTW89_FCC][48] = 72,
+ [0][0][1][0][RTW89_FCC][48] = 68,
[0][0][1][0][RTW89_ETSI][48] = 127,
[0][0][1][0][RTW89_MKK][48] = 127,
[0][0][1][0][RTW89_IC][48] = 127,
@@ -10985,7 +11001,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][48] = 127,
[0][0][1][0][RTW89_CN][48] = 127,
[0][0][1][0][RTW89_UK][48] = 127,
- [0][0][1][0][RTW89_FCC][50] = 72,
+ [0][0][1][0][RTW89_FCC][50] = 68,
[0][0][1][0][RTW89_ETSI][50] = 127,
[0][0][1][0][RTW89_MKK][50] = 127,
[0][0][1][0][RTW89_IC][50] = 127,
@@ -10993,7 +11009,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][50] = 127,
[0][0][1][0][RTW89_CN][50] = 127,
[0][0][1][0][RTW89_UK][50] = 127,
- [0][0][1][0][RTW89_FCC][52] = 72,
+ [0][0][1][0][RTW89_FCC][52] = 68,
[0][0][1][0][RTW89_ETSI][52] = 127,
[0][0][1][0][RTW89_MKK][52] = 127,
[0][0][1][0][RTW89_IC][52] = 127,
@@ -11225,7 +11241,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][52] = 127,
[0][1][1][0][RTW89_CN][52] = 127,
[0][1][1][0][RTW89_UK][52] = 127,
- [0][0][2][0][RTW89_FCC][0] = 76,
+ [0][0][2][0][RTW89_FCC][0] = 72,
[0][0][2][0][RTW89_ETSI][0] = 62,
[0][0][2][0][RTW89_MKK][0] = 62,
[0][0][2][0][RTW89_IC][0] = 64,
@@ -11281,7 +11297,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][12] = 62,
[0][0][2][0][RTW89_CN][12] = 62,
[0][0][2][0][RTW89_UK][12] = 62,
- [0][0][2][0][RTW89_FCC][14] = 74,
+ [0][0][2][0][RTW89_FCC][14] = 70,
[0][0][2][0][RTW89_ETSI][14] = 62,
[0][0][2][0][RTW89_MKK][14] = 62,
[0][0][2][0][RTW89_IC][14] = 64,
@@ -11289,10 +11305,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][14] = 62,
[0][0][2][0][RTW89_CN][14] = 62,
[0][0][2][0][RTW89_UK][14] = 62,
- [0][0][2][0][RTW89_FCC][15] = 74,
+ [0][0][2][0][RTW89_FCC][15] = 70,
[0][0][2][0][RTW89_ETSI][15] = 60,
[0][0][2][0][RTW89_MKK][15] = 74,
- [0][0][2][0][RTW89_IC][15] = 74,
+ [0][0][2][0][RTW89_IC][15] = 70,
[0][0][2][0][RTW89_KCC][15] = 74,
[0][0][2][0][RTW89_ACMA][15] = 60,
[0][0][2][0][RTW89_CN][15] = 127,
@@ -11369,10 +11385,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][33] = 62,
[0][0][2][0][RTW89_CN][33] = 127,
[0][0][2][0][RTW89_UK][33] = 62,
- [0][0][2][0][RTW89_FCC][35] = 72,
+ [0][0][2][0][RTW89_FCC][35] = 68,
[0][0][2][0][RTW89_ETSI][35] = 62,
[0][0][2][0][RTW89_MKK][35] = 74,
- [0][0][2][0][RTW89_IC][35] = 72,
+ [0][0][2][0][RTW89_IC][35] = 68,
[0][0][2][0][RTW89_KCC][35] = 74,
[0][0][2][0][RTW89_ACMA][35] = 62,
[0][0][2][0][RTW89_CN][35] = 127,
@@ -11425,7 +11441,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][46] = 74,
[0][0][2][0][RTW89_CN][46] = 74,
[0][0][2][0][RTW89_UK][46] = 60,
- [0][0][2][0][RTW89_FCC][48] = 74,
+ [0][0][2][0][RTW89_FCC][48] = 70,
[0][0][2][0][RTW89_ETSI][48] = 127,
[0][0][2][0][RTW89_MKK][48] = 127,
[0][0][2][0][RTW89_IC][48] = 127,
@@ -11433,7 +11449,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][48] = 127,
[0][0][2][0][RTW89_CN][48] = 127,
[0][0][2][0][RTW89_UK][48] = 127,
- [0][0][2][0][RTW89_FCC][50] = 74,
+ [0][0][2][0][RTW89_FCC][50] = 70,
[0][0][2][0][RTW89_ETSI][50] = 127,
[0][0][2][0][RTW89_MKK][50] = 127,
[0][0][2][0][RTW89_IC][50] = 127,
@@ -11441,7 +11457,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][50] = 127,
[0][0][2][0][RTW89_CN][50] = 127,
[0][0][2][0][RTW89_UK][50] = 127,
- [0][0][2][0][RTW89_FCC][52] = 74,
+ [0][0][2][0][RTW89_FCC][52] = 70,
[0][0][2][0][RTW89_ETSI][52] = 127,
[0][0][2][0][RTW89_MKK][52] = 127,
[0][0][2][0][RTW89_IC][52] = 127,
@@ -11897,10 +11913,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][52] = 127,
[0][1][2][1][RTW89_CN][52] = 127,
[0][1][2][1][RTW89_UK][52] = 127,
- [1][0][2][0][RTW89_FCC][1] = 66,
+ [1][0][2][0][RTW89_FCC][1] = 62,
[1][0][2][0][RTW89_ETSI][1] = 64,
[1][0][2][0][RTW89_MKK][1] = 64,
- [1][0][2][0][RTW89_IC][1] = 64,
+ [1][0][2][0][RTW89_IC][1] = 60,
[1][0][2][0][RTW89_KCC][1] = 74,
[1][0][2][0][RTW89_ACMA][1] = 64,
[1][0][2][0][RTW89_CN][1] = 64,
@@ -11921,18 +11937,18 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][9] = 64,
[1][0][2][0][RTW89_CN][9] = 64,
[1][0][2][0][RTW89_UK][9] = 64,
- [1][0][2][0][RTW89_FCC][13] = 64,
+ [1][0][2][0][RTW89_FCC][13] = 60,
[1][0][2][0][RTW89_ETSI][13] = 64,
[1][0][2][0][RTW89_MKK][13] = 64,
- [1][0][2][0][RTW89_IC][13] = 64,
+ [1][0][2][0][RTW89_IC][13] = 60,
[1][0][2][0][RTW89_KCC][13] = 72,
[1][0][2][0][RTW89_ACMA][13] = 64,
[1][0][2][0][RTW89_CN][13] = 64,
[1][0][2][0][RTW89_UK][13] = 64,
- [1][0][2][0][RTW89_FCC][16] = 66,
+ [1][0][2][0][RTW89_FCC][16] = 62,
[1][0][2][0][RTW89_ETSI][16] = 66,
[1][0][2][0][RTW89_MKK][16] = 76,
- [1][0][2][0][RTW89_IC][16] = 66,
+ [1][0][2][0][RTW89_IC][16] = 62,
[1][0][2][0][RTW89_KCC][16] = 74,
[1][0][2][0][RTW89_ACMA][16] = 66,
[1][0][2][0][RTW89_CN][16] = 127,
@@ -11940,7 +11956,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_FCC][20] = 80,
[1][0][2][0][RTW89_ETSI][20] = 66,
[1][0][2][0][RTW89_MKK][20] = 76,
- [1][0][2][0][RTW89_IC][20] = 80,
+ [1][0][2][0][RTW89_IC][20] = 76,
[1][0][2][0][RTW89_KCC][20] = 74,
[1][0][2][0][RTW89_ACMA][20] = 66,
[1][0][2][0][RTW89_CN][20] = 127,
@@ -11961,10 +11977,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][28] = 127,
[1][0][2][0][RTW89_CN][28] = 127,
[1][0][2][0][RTW89_UK][28] = 66,
- [1][0][2][0][RTW89_FCC][32] = 74,
+ [1][0][2][0][RTW89_FCC][32] = 70,
[1][0][2][0][RTW89_ETSI][32] = 66,
[1][0][2][0][RTW89_MKK][32] = 76,
- [1][0][2][0][RTW89_IC][32] = 74,
+ [1][0][2][0][RTW89_IC][32] = 70,
[1][0][2][0][RTW89_KCC][32] = 76,
[1][0][2][0][RTW89_ACMA][32] = 66,
[1][0][2][0][RTW89_CN][32] = 127,
@@ -11980,7 +11996,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_FCC][39] = 80,
[1][0][2][0][RTW89_ETSI][39] = 30,
[1][0][2][0][RTW89_MKK][39] = 127,
- [1][0][2][0][RTW89_IC][39] = 80,
+ [1][0][2][0][RTW89_IC][39] = 76,
[1][0][2][0][RTW89_KCC][39] = 68,
[1][0][2][0][RTW89_ACMA][39] = 76,
[1][0][2][0][RTW89_CN][39] = 70,
@@ -11993,7 +12009,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][43] = 76,
[1][0][2][0][RTW89_CN][43] = 76,
[1][0][2][0][RTW89_UK][43] = 64,
- [1][0][2][0][RTW89_FCC][47] = 80,
+ [1][0][2][0][RTW89_FCC][47] = 76,
[1][0][2][0][RTW89_ETSI][47] = 127,
[1][0][2][0][RTW89_MKK][47] = 127,
[1][0][2][0][RTW89_IC][47] = 127,
@@ -12001,7 +12017,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][47] = 127,
[1][0][2][0][RTW89_CN][47] = 127,
[1][0][2][0][RTW89_UK][47] = 127,
- [1][0][2][0][RTW89_FCC][51] = 80,
+ [1][0][2][0][RTW89_FCC][51] = 76,
[1][0][2][0][RTW89_ETSI][51] = 127,
[1][0][2][0][RTW89_MKK][51] = 127,
[1][0][2][0][RTW89_IC][51] = 127,
@@ -12233,26 +12249,26 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][51] = 127,
[1][1][2][1][RTW89_CN][51] = 127,
[1][1][2][1][RTW89_UK][51] = 127,
- [2][0][2][0][RTW89_FCC][3] = 72,
+ [2][0][2][0][RTW89_FCC][3] = 68,
[2][0][2][0][RTW89_ETSI][3] = 64,
[2][0][2][0][RTW89_MKK][3] = 62,
- [2][0][2][0][RTW89_IC][3] = 64,
+ [2][0][2][0][RTW89_IC][3] = 60,
[2][0][2][0][RTW89_KCC][3] = 68,
[2][0][2][0][RTW89_ACMA][3] = 64,
[2][0][2][0][RTW89_CN][3] = 64,
[2][0][2][0][RTW89_UK][3] = 64,
- [2][0][2][0][RTW89_FCC][11] = 62,
+ [2][0][2][0][RTW89_FCC][11] = 58,
[2][0][2][0][RTW89_ETSI][11] = 64,
[2][0][2][0][RTW89_MKK][11] = 64,
- [2][0][2][0][RTW89_IC][11] = 62,
+ [2][0][2][0][RTW89_IC][11] = 58,
[2][0][2][0][RTW89_KCC][11] = 68,
[2][0][2][0][RTW89_ACMA][11] = 64,
[2][0][2][0][RTW89_CN][11] = 64,
[2][0][2][0][RTW89_UK][11] = 64,
- [2][0][2][0][RTW89_FCC][18] = 66,
+ [2][0][2][0][RTW89_FCC][18] = 62,
[2][0][2][0][RTW89_ETSI][18] = 64,
[2][0][2][0][RTW89_MKK][18] = 68,
- [2][0][2][0][RTW89_IC][18] = 66,
+ [2][0][2][0][RTW89_IC][18] = 62,
[2][0][2][0][RTW89_KCC][18] = 68,
[2][0][2][0][RTW89_ACMA][18] = 64,
[2][0][2][0][RTW89_CN][18] = 127,
@@ -12268,7 +12284,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_FCC][34] = 72,
[2][0][2][0][RTW89_ETSI][34] = 127,
[2][0][2][0][RTW89_MKK][34] = 68,
- [2][0][2][0][RTW89_IC][34] = 72,
+ [2][0][2][0][RTW89_IC][34] = 68,
[2][0][2][0][RTW89_KCC][34] = 68,
[2][0][2][0][RTW89_ACMA][34] = 68,
[2][0][2][0][RTW89_CN][34] = 127,
@@ -12276,12 +12292,12 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_FCC][41] = 72,
[2][0][2][0][RTW89_ETSI][41] = 30,
[2][0][2][0][RTW89_MKK][41] = 127,
- [2][0][2][0][RTW89_IC][41] = 72,
+ [2][0][2][0][RTW89_IC][41] = 68,
[2][0][2][0][RTW89_KCC][41] = 64,
[2][0][2][0][RTW89_ACMA][41] = 68,
[2][0][2][0][RTW89_CN][41] = 68,
[2][0][2][0][RTW89_UK][41] = 64,
- [2][0][2][0][RTW89_FCC][49] = 72,
+ [2][0][2][0][RTW89_FCC][49] = 68,
[2][0][2][0][RTW89_ETSI][49] = 127,
[2][0][2][0][RTW89_MKK][49] = 127,
[2][0][2][0][RTW89_IC][49] = 127,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h
index f2e673ba39c8..a8737de02f66 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h
@@ -13,7 +13,7 @@ extern const struct rtw89_phy_table rtw89_8851b_phy_radioa_table;
extern const struct rtw89_phy_table rtw89_8851b_phy_nctl_table;
extern const struct rtw89_txpwr_table rtw89_8851b_byr_table;
extern const struct rtw89_txpwr_track_cfg rtw89_8851b_trk_cfg;
-extern const u8 rtw89_8851b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
+extern const u8 rtw89_8851b_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM]
[RTW89_REGD_NUM];
extern const struct rtw89_rfe_parms rtw89_8851b_dflt_parms;
extern const struct rtw89_rfe_parms_conf rtw89_8851b_rfe_parms_conf[];
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851be.c b/drivers/net/wireless/realtek/rtw89/rtw8851be.c
new file mode 100644
index 000000000000..0f7711c50bd1
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851be.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2022-2023 Realtek Corporation
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "pci.h"
+#include "reg.h"
+#include "rtw8851b.h"
+
+static const struct rtw89_pci_info rtw8851b_pci_info = {
+ .txbd_trunc_mode = MAC_AX_BD_TRUNC,
+ .rxbd_trunc_mode = MAC_AX_BD_TRUNC,
+ .rxbd_mode = MAC_AX_RXBD_PKT,
+ .tag_mode = MAC_AX_TAG_MULTI,
+ .tx_burst = MAC_AX_TX_BURST_2048B,
+ .rx_burst = MAC_AX_RX_BURST_128B,
+ .wd_dma_idle_intvl = MAC_AX_WD_DMA_INTVL_256NS,
+ .wd_dma_act_intvl = MAC_AX_WD_DMA_INTVL_256NS,
+ .multi_tag_num = MAC_AX_TAG_NUM_8,
+ .lbc_en = MAC_AX_PCIE_ENABLE,
+ .lbc_tmr = MAC_AX_LBC_TMR_2MS,
+ .autok_en = MAC_AX_PCIE_DISABLE,
+ .io_rcy_en = MAC_AX_PCIE_DISABLE,
+ .io_rcy_tmr = MAC_AX_IO_RCY_ANA_TMR_6MS,
+
+ .init_cfg_reg = R_AX_PCIE_INIT_CFG1,
+ .txhci_en_bit = B_AX_TXHCI_EN,
+ .rxhci_en_bit = B_AX_RXHCI_EN,
+ .rxbd_mode_bit = B_AX_RXBD_MODE,
+ .exp_ctrl_reg = R_AX_PCIE_EXP_CTRL,
+ .max_tag_num_mask = B_AX_MAX_TAG_NUM,
+ .rxbd_rwptr_clr_reg = R_AX_RXBD_RWPTR_CLR,
+ .txbd_rwptr_clr2_reg = 0,
+ .dma_stop1 = {R_AX_PCIE_DMA_STOP1, B_AX_TX_STOP1_MASK_V1},
+ .dma_stop2 = {0},
+ .dma_busy1 = {R_AX_PCIE_DMA_BUSY1, DMA_BUSY1_CHECK_V1},
+ .dma_busy2_reg = 0,
+ .dma_busy3_reg = R_AX_PCIE_DMA_BUSY1,
+
+ .rpwm_addr = R_AX_PCIE_HRPWM,
+ .cpwm_addr = R_AX_CPWM,
+ .tx_dma_ch_mask = BIT(RTW89_TXCH_ACH4) | BIT(RTW89_TXCH_ACH5) |
+ BIT(RTW89_TXCH_ACH6) | BIT(RTW89_TXCH_ACH7) |
+ BIT(RTW89_TXCH_CH10) | BIT(RTW89_TXCH_CH11),
+ .bd_idx_addr_low_power = NULL,
+ .dma_addr_set = &rtw89_pci_ch_dma_addr_set,
+ .bd_ram_table = &rtw89_bd_ram_table_single,
+
+ .ltr_set = rtw89_pci_ltr_set,
+ .fill_txaddr_info = rtw89_pci_fill_txaddr_info,
+ .config_intr_mask = rtw89_pci_config_intr_mask,
+ .enable_intr = rtw89_pci_enable_intr,
+ .disable_intr = rtw89_pci_disable_intr,
+ .recognize_intrs = rtw89_pci_recognize_intrs,
+};
+
+static const struct rtw89_driver_info rtw89_8851be_info = {
+ .chip = &rtw8851b_chip_info,
+ .bus = {
+ .pci = &rtw8851b_pci_info,
+ },
+};
+
+static const struct pci_device_id rtw89_8851be_id_table[] = {
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xb851),
+ .driver_data = (kernel_ulong_t)&rtw89_8851be_info,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(pci, rtw89_8851be_id_table);
+
+static struct pci_driver rtw89_8851be_driver = {
+ .name = "rtw89_8851be",
+ .id_table = rtw89_8851be_id_table,
+ .probe = rtw89_pci_probe,
+ .remove = rtw89_pci_remove,
+ .driver.pm = &rtw89_pm_ops,
+};
+module_pci_driver(rtw89_8851be_driver);
+
+MODULE_AUTHOR("Realtek Corporation");
+MODULE_DESCRIPTION("Realtek 802.11ax wireless 8851BE driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index d7930efd89b7..6257414a3b4b 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -463,6 +463,12 @@ static const struct rtw89_imr_info rtw8852a_imr_info = {
.tmac_imr_set = B_AX_TMAC_IMR_SET,
};
+static const struct rtw89_xtal_info rtw8852a_xtal_info = {
+ .xcap_reg = R_AX_XTAL_ON_CTRL0,
+ .sc_xo_mask = B_AX_XTAL_SC_XO_MASK,
+ .sc_xi_mask = B_AX_XTAL_SC_XI_MASK,
+};
+
static const struct rtw89_rrsr_cfgs rtw8852a_rrsr_cfgs = {
.ref_rate = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_REF_RATE_SEL, 0},
.rsc = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_RSC_MASK, 2},
@@ -1332,7 +1338,6 @@ static void rtw8852a_rfk_scan(struct rtw89_dev *rtwdev, bool start)
static void rtw8852a_rfk_track(struct rtw89_dev *rtwdev)
{
rtw8852a_dpk_track(rtwdev);
- rtw8852a_iqk_track(rtwdev);
rtw8852a_tssi_track(rtwdev);
}
@@ -2026,6 +2031,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
.read_efuse = rtw8852a_read_efuse,
.read_phycap = rtw8852a_read_phycap,
.fem_setup = rtw8852a_fem_setup,
+ .rfe_gpio = NULL,
.rfk_init = rtw8852a_rfk_init,
.rfk_channel = rtw8852a_rfk_channel,
.rfk_band_changed = rtw8852a_rfk_band_changed,
@@ -2043,6 +2049,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
.set_txpwr_ul_tb_offset = rtw8852a_set_txpwr_ul_tb_offset,
.pwr_on_func = NULL,
.pwr_off_func = NULL,
+ .query_rxdesc = rtw89_core_query_rxdesc,
.fill_txdesc = rtw89_core_fill_txdesc,
.fill_txdesc_fwcmd = rtw89_core_fill_txdesc,
.cfg_ctrl_path = rtw89_mac_cfg_ctrl_path,
@@ -2069,6 +2076,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.fw_format_max = RTW8852A_FW_FORMAT_MAX,
.try_ce_fw = false,
.fifo_size = 458752,
+ .small_fifo_size = false,
.dle_scc_rsvd_size = 0,
.max_amsdu_limit = 3500,
.dis_2g_40m_ul_ofdma = true,
@@ -2085,6 +2093,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.rf_table = {&rtw89_8852a_phy_radioa_table,
&rtw89_8852a_phy_radiob_table,},
.nctl_table = &rtw89_8852a_phy_nctl_table,
+ .nctl_post_table = NULL,
.byr_table = &rtw89_8852a_byr_table,
.dflt_parms = &rtw89_8852a_dflt_parms,
.rfe_parms_conf = NULL,
@@ -2097,6 +2106,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.support_bands = BIT(NL80211_BAND_2GHZ) |
BIT(NL80211_BAND_5GHZ),
.support_bw160 = false,
+ .support_unii4 = false,
.support_ul_tb_ctrl = false,
.hw_sec_hdr = false,
.rf_path_num = 2,
@@ -2107,7 +2117,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.scam_num = 128,
.bacam_num = 2,
.bacam_dynamic_num = 4,
- .bacam_v1 = false,
+ .bacam_ver = RTW89_BACAM_V0,
.sec_ctrl_efuse_size = 4,
.physical_efuse_size = 1216,
.logical_efuse_size = 1536,
@@ -2159,6 +2169,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
#ifdef CONFIG_PM
.wowlan_stub = &rtw_wowlan_stub_8852a,
#endif
+ .xtal_info = &rtw8852a_xtal_info,
};
EXPORT_SYMBOL(rtw8852a_chip_info);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c
index cd6c39b7f802..d86429e4a35f 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c
@@ -1284,11 +1284,8 @@ static void _iqk_info_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
u32 tmp = 0x0;
bool flag = 0x0;
- iqk_info->thermal[path] =
- ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]);
- iqk_info->thermal_rek_en = false;
- rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_thermal = %d\n", path,
- iqk_info->thermal[path]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_thermal = %lu\n", path,
+ ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]));
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_LOK_COR_fail= %d\n", path,
iqk_info->lok_cor_fail[0][path]);
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_LOK_FIN_fail= %d\n", path,
@@ -1536,28 +1533,6 @@ static void _iqk_dbcc(struct rtw89_dev *rtwdev, u8 path)
_iqk_afebb_restore(rtwdev, phy_idx, path);
}
-static void _iqk_track(struct rtw89_dev *rtwdev)
-{
- struct rtw89_iqk_info *iqk = &rtwdev->iqk;
- u8 path = 0x0;
- u8 cur_ther;
-
- if (iqk->iqk_band[0] == RTW89_BAND_2G)
- return;
- if (iqk->iqk_bw[0] < RTW89_CHANNEL_WIDTH_80)
- return;
-
- /* only check path 0 */
- for (path = 0; path < 1; path++) {
- cur_ther = ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]);
-
- if (abs(cur_ther - iqk->thermal[path]) > RTW8852A_IQK_THR_REK)
- iqk->thermal_rek_en = true;
- else
- iqk->thermal_rek_en = false;
- }
-}
-
static void _rck(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
{
u32 rf_reg5, rck_val = 0;
@@ -1616,7 +1591,6 @@ static void _iqk_init(struct rtw89_dev *rtwdev)
iqk_info->iqk_sram_en = false;
iqk_info->iqk_cfir_en = false;
iqk_info->iqk_xym_en = false;
- iqk_info->thermal_rek_en = false;
iqk_info->iqk_times = 0x0;
for (ch = 0; ch < RTW89_IQK_CHS_NR; ch++) {
@@ -1645,7 +1619,6 @@ static void _doiqk(struct rtw89_dev *rtwdev, bool force,
rtw89_debug(rtwdev, RTW89_DBG_RFK,
"[IQK]==========IQK start!!!!!==========\n");
iqk_info->iqk_times++;
- iqk_info->kcount = 0;
iqk_info->version = RTW8852A_IQK_VER;
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]Test Ver 0x%x\n", iqk_info->version);
@@ -3655,11 +3628,6 @@ void rtw8852a_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_STOP);
}
-void rtw8852a_iqk_track(struct rtw89_dev *rtwdev)
-{
- _iqk_track(rtwdev);
-}
-
void rtw8852a_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
bool is_afe)
{
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.h b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.h
index ea36553a76b7..fa058ccc8616 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.h
@@ -10,7 +10,6 @@
void rtw8852a_rck(struct rtw89_dev *rtwdev);
void rtw8852a_dack(struct rtw89_dev *rtwdev);
void rtw8852a_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
-void rtw8852a_iqk_track(struct rtw89_dev *rtwdev);
void rtw8852a_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
bool is_afe);
void rtw8852a_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
index 6da1b603a9a9..718f993da62a 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
@@ -2454,6 +2454,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = {
.read_efuse = rtw8852b_read_efuse,
.read_phycap = rtw8852b_read_phycap,
.fem_setup = NULL,
+ .rfe_gpio = NULL,
.rfk_init = rtw8852b_rfk_init,
.rfk_channel = rtw8852b_rfk_channel,
.rfk_band_changed = rtw8852b_rfk_band_changed,
@@ -2471,6 +2472,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = {
.set_txpwr_ul_tb_offset = rtw8852b_set_txpwr_ul_tb_offset,
.pwr_on_func = rtw8852b_pwr_on_func,
.pwr_off_func = rtw8852b_pwr_off_func,
+ .query_rxdesc = rtw89_core_query_rxdesc,
.fill_txdesc = rtw89_core_fill_txdesc,
.fill_txdesc_fwcmd = rtw89_core_fill_txdesc,
.cfg_ctrl_path = rtw89_mac_cfg_ctrl_path,
@@ -2506,6 +2508,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
.fw_format_max = RTW8852B_FW_FORMAT_MAX,
.try_ce_fw = true,
.fifo_size = 196608,
+ .small_fifo_size = true,
.dle_scc_rsvd_size = 98304,
.max_amsdu_limit = 3500,
.dis_2g_40m_ul_ofdma = true,
@@ -2522,6 +2525,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
.rf_table = {&rtw89_8852b_phy_radioa_table,
&rtw89_8852b_phy_radiob_table,},
.nctl_table = &rtw89_8852b_phy_nctl_table,
+ .nctl_post_table = NULL,
.byr_table = &rtw89_8852b_byr_table,
.dflt_parms = &rtw89_8852b_dflt_parms,
.rfe_parms_conf = NULL,
@@ -2534,6 +2538,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
.support_bands = BIT(NL80211_BAND_2GHZ) |
BIT(NL80211_BAND_5GHZ),
.support_bw160 = false,
+ .support_unii4 = true,
.support_ul_tb_ctrl = true,
.hw_sec_hdr = false,
.rf_path_num = 2,
@@ -2544,7 +2549,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
.scam_num = 128,
.bacam_num = 2,
.bacam_dynamic_num = 4,
- .bacam_v1 = false,
+ .bacam_ver = RTW89_BACAM_V0,
.sec_ctrl_efuse_size = 4,
.physical_efuse_size = 1216,
.logical_efuse_size = 2048,
@@ -2598,6 +2603,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
#ifdef CONFIG_PM
.wowlan_stub = &rtw_wowlan_stub_8852b,
#endif
+ .xtal_info = NULL,
};
EXPORT_SYMBOL(rtw8852b_chip_info);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c
index 722ae34b09c1..fa018e1f499b 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c
@@ -1317,10 +1317,6 @@ static void _iqk_info_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
u32 tmp;
bool flag;
- iqk_info->thermal[path] =
- ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]);
- iqk_info->thermal_rek_en = false;
-
flag = iqk_info->lok_cor_fail[0][path];
rtw89_phy_write32_mask(rtwdev, R_IQKINF, B_IQKINF_FCOR << (path * 4), flag);
flag = iqk_info->lok_fin_fail[0][path];
@@ -1568,7 +1564,6 @@ static void _iqk_init(struct rtw89_dev *rtwdev)
iqk_info->iqk_sram_en = false;
iqk_info->iqk_cfir_en = false;
iqk_info->iqk_xym_en = false;
- iqk_info->thermal_rek_en = false;
iqk_info->iqk_times = 0x0;
for (idx = 0; idx < RTW89_IQK_CHS_NR; idx++) {
@@ -1622,9 +1617,8 @@ static void _doiqk(struct rtw89_dev *rtwdev, bool force,
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_START);
rtw89_debug(rtwdev, RTW89_DBG_RFK,
- "[IQK]==========IQK strat!!!!!==========\n");
+ "[IQK]==========IQK start!!!!!==========\n");
iqk_info->iqk_times++;
- iqk_info->kcount = 0;
iqk_info->version = RTW8852B_IQK_VER;
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]Test Ver 0x%x\n", iqk_info->version);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c
index 904cdb9e56fa..17124d851a22 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c
@@ -14666,7 +14666,7 @@ static const s8 _txpwr_track_delta_swingidx_2g_cck_a_p[] = {
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
-const u8 rtw89_8852b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
+const u8 rtw89_8852b_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM]
[RTW89_REGD_NUM] = {
[0][0][RTW89_ACMA] = 0,
[0][0][RTW89_CHILE] = 0,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h
index 5f4161496a58..7ef217629f46 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h
@@ -14,7 +14,7 @@ extern const struct rtw89_phy_table rtw89_8852b_phy_radiob_table;
extern const struct rtw89_phy_table rtw89_8852b_phy_nctl_table;
extern const struct rtw89_txpwr_table rtw89_8852b_byr_table;
extern const struct rtw89_txpwr_track_cfg rtw89_8852b_trk_cfg;
-extern const u8 rtw89_8852b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
+extern const u8 rtw89_8852b_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM]
[RTW89_REGD_NUM];
extern const struct rtw89_rfe_parms rtw89_8852b_dflt_parms;
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index ceb819a62efc..9c7c9812d4f4 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -2762,6 +2762,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
.read_efuse = rtw8852c_read_efuse,
.read_phycap = rtw8852c_read_phycap,
.fem_setup = NULL,
+ .rfe_gpio = NULL,
.rfk_init = rtw8852c_rfk_init,
.rfk_channel = rtw8852c_rfk_channel,
.rfk_band_changed = rtw8852c_rfk_band_changed,
@@ -2779,6 +2780,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
.set_txpwr_ul_tb_offset = rtw8852c_set_txpwr_ul_tb_offset,
.pwr_on_func = rtw8852c_pwr_on_func,
.pwr_off_func = rtw8852c_pwr_off_func,
+ .query_rxdesc = rtw89_core_query_rxdesc,
.fill_txdesc = rtw89_core_fill_txdesc_v1,
.fill_txdesc_fwcmd = rtw89_core_fill_txdesc_fwcmd_v1,
.cfg_ctrl_path = rtw89_mac_cfg_ctrl_path_v1,
@@ -2805,6 +2807,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.fw_format_max = RTW8852C_FW_FORMAT_MAX,
.try_ce_fw = false,
.fifo_size = 458752,
+ .small_fifo_size = false,
.dle_scc_rsvd_size = 0,
.max_amsdu_limit = 8000,
.dis_2g_40m_ul_ofdma = false,
@@ -2821,6 +2824,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.rf_table = {&rtw89_8852c_phy_radiob_table,
&rtw89_8852c_phy_radioa_table,},
.nctl_table = &rtw89_8852c_phy_nctl_table,
+ .nctl_post_table = NULL,
.byr_table = &rtw89_8852c_byr_table,
.dflt_parms = &rtw89_8852c_dflt_parms,
.rfe_parms_conf = NULL,
@@ -2834,6 +2838,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
BIT(NL80211_BAND_5GHZ) |
BIT(NL80211_BAND_6GHZ),
.support_bw160 = true,
+ .support_unii4 = true,
.support_ul_tb_ctrl = false,
.hw_sec_hdr = true,
.rf_path_num = 2,
@@ -2844,7 +2849,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.scam_num = 128,
.bacam_num = 8,
.bacam_dynamic_num = 8,
- .bacam_v1 = true,
+ .bacam_ver = RTW89_BACAM_V0_EXT,
.sec_ctrl_efuse_size = 4,
.physical_efuse_size = 1216,
.logical_efuse_size = 2048,
@@ -2897,6 +2902,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
#ifdef CONFIG_PM
.wowlan_stub = &rtw_wowlan_stub_8852c,
#endif
+ .xtal_info = NULL,
};
EXPORT_SYMBOL(rtw8852c_chip_info);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
index 2c0bc3a4ab3b..de7714f871d5 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
@@ -1261,11 +1261,8 @@ static void _iqk_info_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
u32 tmp;
bool flag;
- iqk_info->thermal[path] =
- ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]);
- iqk_info->thermal_rek_en = false;
- rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_thermal = %d\n", path,
- iqk_info->thermal[path]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_thermal = %lu\n", path,
+ ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]));
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_LOK_COR_fail= %d\n", path,
iqk_info->lok_cor_fail[0][path]);
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_LOK_FIN_fail= %d\n", path,
@@ -1502,7 +1499,6 @@ static void _iqk_init(struct rtw89_dev *rtwdev)
iqk_info->iqk_sram_en = false;
iqk_info->iqk_cfir_en = false;
iqk_info->iqk_xym_en = false;
- iqk_info->thermal_rek_en = false;
iqk_info->iqk_times = 0x0;
for (ch = 0; ch < RTW89_IQK_CHS_NR; ch++) {
@@ -1529,9 +1525,8 @@ static void _doiqk(struct rtw89_dev *rtwdev, bool force,
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_START);
rtw89_debug(rtwdev, RTW89_DBG_RFK,
- "[IQK]==========IQK strat!!!!!==========\n");
+ "[IQK]==========IQK start!!!!!==========\n");
iqk_info->iqk_times++;
- iqk_info->kcount = 0;
iqk_info->version = RTW8852C_IQK_VER;
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]Test Ver 0x%x\n", iqk_info->version);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c
index 7011e5a6f8fd..4b272fdf1fd7 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c
@@ -2551,19 +2551,27 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0xF0040001, 0x0000000A},
{0xF0050001, 0x0000000B},
{0xF0070001, 0x0000000C},
- {0xF0320001, 0x0000000D},
- {0xF0330001, 0x0000000E},
- {0xF0340001, 0x0000000F},
- {0xF0350001, 0x00000010},
- {0xF0360001, 0x00000011},
- {0xF03F0001, 0x00000012},
- {0xF0400001, 0x00000013},
+ {0xF0150001, 0x0000000D},
+ {0xF0160001, 0x0000000E},
+ {0xF0320001, 0x0000000F},
+ {0xF0330001, 0x00000010},
+ {0xF0340001, 0x00000011},
+ {0xF0350001, 0x00000012},
+ {0xF0360001, 0x00000013},
+ {0xF03F0001, 0x00000014},
+ {0xF0400001, 0x00000015},
{0x005, 0x00000000},
{0x10005, 0x00000000},
{0x000, 0x00030001},
{0x10000, 0x00030000},
{0x018, 0x00011124},
{0x10018, 0x00011124},
+ {0x0A3, 0x000B9204},
+ {0x0AD, 0x00091E0F},
+ {0x05D, 0x00001012},
+ {0x05C, 0x00061C5C},
+ {0x062, 0x00055220},
+ {0x0D3, 0x00000103},
{0x0EF, 0x00080000},
{0x033, 0x00000001},
{0x03E, 0x00000620},
@@ -2636,6 +2644,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x067, 0x0000D300},
{0x0DA, 0x000D4000},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x067, 0x0000D300},
+ {0x0DA, 0x000D4000},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x067, 0x0000D300},
+ {0x0DA, 0x000D4000},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x067, 0x0000D300},
{0x0DA, 0x000D4000},
@@ -2716,6 +2730,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000CC},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000CC},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000CC},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000CC},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000CC},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2760,6 +2778,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000C4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000C4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000C4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000C4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000C4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2804,6 +2826,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000BC},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000BC},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000BC},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000BC},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000BC},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2848,6 +2874,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000B4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000B4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000B4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000B4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000B4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2892,6 +2922,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000AC},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000AC},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000AC},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000AC},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000AC},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2936,6 +2970,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2980,6 +3018,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000009C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000009C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000009C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000009C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000009C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3024,6 +3066,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000094},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000094},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000094},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000094},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000094},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3068,6 +3114,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000008C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000008C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000008C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000008C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000008C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3112,6 +3162,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000084},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000084},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000084},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000084},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000084},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3156,6 +3210,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000BC},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000BC},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000BC},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000BC},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000BC},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3200,6 +3258,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000B4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000B4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000B4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000B4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000B4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3244,6 +3306,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000AC},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000AC},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000AC},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000AC},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000AC},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3288,6 +3354,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3332,6 +3402,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000009C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000009C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000009C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000009C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000009C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3376,6 +3450,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000094},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000094},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000094},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000094},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000094},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3420,6 +3498,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000008C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000008C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000008C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000008C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000008C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3464,6 +3546,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000084},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000084},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000084},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000084},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000084},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3508,6 +3594,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000003C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000003C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000003C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000003C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000003C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3552,6 +3642,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000034},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000034},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000034},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000034},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000034},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3596,6 +3690,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000002C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000002C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000002C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000002C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000002C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3640,6 +3738,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000024},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000024},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000024},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000024},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000024},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3684,6 +3786,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000001C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000001C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000001C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000001C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000001C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3728,6 +3834,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000014},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000014},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000014},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000014},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000014},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3772,6 +3882,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000000C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000000C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000000C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000000C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000000C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3816,6 +3930,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000004},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000004},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000004},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000004},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000004},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3873,6 +3991,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x08F, 0x000D1352},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x08F, 0x000D1352},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x08F, 0x000D1352},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x08F, 0x000D1352},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x08F, 0x000D1352},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3936,6 +4058,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000007},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000007},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000017},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000017},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000007},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -4472,6 +4598,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000EFFF},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000EFFF},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000EFFF},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000EFFF},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000EFFF},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -4810,6 +4940,32 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x030, 0x00050112},
{0x030, 0x00058101},
{0x030, 0x00060001},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x000085ED},
+ {0x030, 0x000105CC},
+ {0x030, 0x000184AA},
+ {0x030, 0x00020388},
+ {0x030, 0x00028377},
+ {0x030, 0x00030377},
+ {0x030, 0x00038255},
+ {0x030, 0x00040244},
+ {0x030, 0x00048133},
+ {0x030, 0x00050112},
+ {0x030, 0x00058101},
+ {0x030, 0x00060001},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x000085ED},
+ {0x030, 0x000105CC},
+ {0x030, 0x000184AA},
+ {0x030, 0x00020388},
+ {0x030, 0x00028377},
+ {0x030, 0x00030377},
+ {0x030, 0x00038255},
+ {0x030, 0x00040244},
+ {0x030, 0x00048133},
+ {0x030, 0x00050112},
+ {0x030, 0x00058101},
+ {0x030, 0x00060001},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x030, 0x000085ED},
{0x030, 0x000105CC},
@@ -5157,6 +5313,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x030, 0x000300FF},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x030, 0x000300FF},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x000300FF},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x000300FF},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x030, 0x000300FF},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5178,11 +5338,268 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x0EF, 0x00000000},
{0x06E, 0x00077A18},
{0x06D, 0x00000C31},
+ {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
{0x06A, 0x000E0F8A},
{0x06B, 0x000018A0},
{0x06F, 0x000F81FC},
{0x05E, 0x0000001F},
+ {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0380},
+ {0x06B, 0x00003CA0},
+ {0x06F, 0x000C01FC},
+ {0x05E, 0x0000001F},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0380},
+ {0x06B, 0x00003CA0},
+ {0x06F, 0x000C01FC},
+ {0x05E, 0x0000001F},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0xA0000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0xB0000000, 0x00000000},
{0x0EF, 0x00000200},
+ {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
{0x030, 0x0003D407},
{0x030, 0x00035A87},
{0x030, 0x0002CF07},
@@ -5191,14 +5608,225 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x030, 0x00014F07},
{0x030, 0x0000CF07},
{0x030, 0x00004F07},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0xA0000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0xB0000000, 0x00000000},
{0x0EF, 0x00000000},
{0x0EB, 0x00080000},
+ {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
{0x030, 0x00008038},
{0x030, 0x00010038},
{0x030, 0x00018038},
{0x030, 0x00020038},
{0x030, 0x00028038},
{0x030, 0x00030038},
+ {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0000803C},
+ {0x030, 0x0001003C},
+ {0x030, 0x0001803C},
+ {0x030, 0x0002003C},
+ {0x030, 0x0002803C},
+ {0x030, 0x0003003C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0000803C},
+ {0x030, 0x0001003C},
+ {0x030, 0x0001803C},
+ {0x030, 0x0002003C},
+ {0x030, 0x0002803C},
+ {0x030, 0x0003003C},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0xA0000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0xB0000000, 0x00000000},
{0x030, 0x0003803C},
{0x030, 0x0004003C},
{0x030, 0x0004803C},
@@ -5235,6 +5863,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x095, 0x00000008},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x095, 0x00000008},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x095, 0x00000008},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x095, 0x00000008},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x095, 0x00000008},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5280,6 +5912,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5324,6 +5960,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5368,6 +6008,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5412,6 +6056,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5456,6 +6104,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5500,6 +6152,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5548,6 +6204,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5592,6 +6252,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5636,6 +6300,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5680,6 +6348,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5724,6 +6396,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5768,6 +6444,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5812,6 +6492,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5856,6 +6540,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5900,6 +6588,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5944,6 +6636,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5988,6 +6684,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -6032,6 +6732,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -6076,6 +6780,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -6120,6 +6828,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -6164,6 +6876,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -6208,6 +6924,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -6252,20 +6972,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0xA0000000, 0x00000000},
{0x03F, 0x00000052},
{0xB0000000, 0x00000000},
@@ -6296,20 +7020,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0xA0000000, 0x00000000},
{0x03F, 0x0000005A},
{0xB0000000, 0x00000000},
@@ -6340,20 +7068,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0xA0000000, 0x00000000},
{0x03F, 0x0000009C},
{0xB0000000, 0x00000000},
@@ -6384,20 +7116,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0xA0000000, 0x00000000},
{0x03F, 0x0000019C},
{0xB0000000, 0x00000000},
@@ -6428,20 +7164,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001A4},
{0xB0000000, 0x00000000},
@@ -6472,20 +7212,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001E6},
{0xB0000000, 0x00000000},
@@ -6516,20 +7260,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000002E6},
{0xB0000000, 0x00000000},
@@ -6560,20 +7308,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000003E6},
{0xB0000000, 0x00000000},
@@ -6604,20 +7356,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0xA0000000, 0x00000000},
{0x03F, 0x00000052},
{0xB0000000, 0x00000000},
@@ -6648,20 +7404,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0xA0000000, 0x00000000},
{0x03F, 0x0000005A},
{0xB0000000, 0x00000000},
@@ -6692,20 +7452,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0xA0000000, 0x00000000},
{0x03F, 0x0000009C},
{0xB0000000, 0x00000000},
@@ -6736,20 +7500,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0xA0000000, 0x00000000},
{0x03F, 0x0000019C},
{0xB0000000, 0x00000000},
@@ -6780,20 +7548,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001A4},
{0xB0000000, 0x00000000},
@@ -6824,20 +7596,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001E6},
{0xB0000000, 0x00000000},
@@ -6868,20 +7644,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000002E6},
{0xB0000000, 0x00000000},
@@ -6912,20 +7692,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000003E6},
{0xB0000000, 0x00000000},
@@ -6956,20 +7740,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0xA0000000, 0x00000000},
{0x03F, 0x00000052},
{0xB0000000, 0x00000000},
@@ -7000,20 +7788,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0xA0000000, 0x00000000},
{0x03F, 0x0000005A},
{0xB0000000, 0x00000000},
@@ -7044,20 +7836,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0xA0000000, 0x00000000},
{0x03F, 0x0000009C},
{0xB0000000, 0x00000000},
@@ -7088,20 +7884,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0xA0000000, 0x00000000},
{0x03F, 0x0000019C},
{0xB0000000, 0x00000000},
@@ -7132,20 +7932,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001A4},
{0xB0000000, 0x00000000},
@@ -7176,20 +7980,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001E6},
{0xB0000000, 0x00000000},
@@ -7220,20 +8028,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000002E6},
{0xB0000000, 0x00000000},
@@ -7264,20 +8076,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000003E6},
{0xB0000000, 0x00000000},
@@ -7308,20 +8124,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0xA0000000, 0x00000000},
{0x03F, 0x00000052},
{0xB0000000, 0x00000000},
@@ -7352,20 +8172,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0xA0000000, 0x00000000},
{0x03F, 0x0000005A},
{0xB0000000, 0x00000000},
@@ -7396,20 +8220,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0xA0000000, 0x00000000},
{0x03F, 0x0000009C},
{0xB0000000, 0x00000000},
@@ -7440,20 +8268,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0xA0000000, 0x00000000},
{0x03F, 0x0000019C},
{0xB0000000, 0x00000000},
@@ -7484,20 +8316,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001A4},
{0xB0000000, 0x00000000},
@@ -7528,20 +8364,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001E6},
{0xB0000000, 0x00000000},
@@ -9436,7 +10276,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x0007BC1D},
{0x10030, 0x0007C017},
{0x10030, 0x0007C40F},
- {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
{0x10030, 0x000009E3},
@@ -9581,7 +10421,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x0007BC1D},
{0x10030, 0x0007C017},
{0x10030, 0x0007C40F},
- {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
{0x10030, 0x000009E3},
@@ -9600,60 +10440,60 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x00003C5F},
{0x10030, 0x00004059},
{0x10030, 0x00004453},
- {0x10030, 0x000201A7},
- {0x10030, 0x000205A1},
- {0x10030, 0x0002099B},
- {0x10030, 0x00020D95},
- {0x10030, 0x0002115B},
- {0x10030, 0x00021555},
- {0x10030, 0x00021921},
- {0x10030, 0x00021D1B},
- {0x10030, 0x000220E3},
- {0x10030, 0x000224DD},
+ {0x10030, 0x000201EF},
+ {0x10030, 0x000205E9},
+ {0x10030, 0x000209E3},
+ {0x10030, 0x00020DA3},
+ {0x10030, 0x00021161},
+ {0x10030, 0x0002155B},
+ {0x10030, 0x0002191F},
+ {0x10030, 0x00021D19},
+ {0x10030, 0x000220E1},
+ {0x10030, 0x000224DB},
{0x10030, 0x000228A3},
{0x10030, 0x00022C9D},
{0x10030, 0x00023063},
{0x10030, 0x0002345D},
{0x10030, 0x00023823},
- {0x10030, 0x00023C1D},
- {0x10030, 0x00024017},
- {0x10030, 0x00024411},
- {0x10030, 0x000281A9},
- {0x10030, 0x000285A3},
- {0x10030, 0x0002899D},
- {0x10030, 0x00028D97},
- {0x10030, 0x0002915D},
- {0x10030, 0x00029557},
- {0x10030, 0x0002991F},
- {0x10030, 0x00029D19},
- {0x10030, 0x0002A0E1},
- {0x10030, 0x0002A4DB},
+ {0x10030, 0x00023C1B},
+ {0x10030, 0x00024015},
+ {0x10030, 0x0002440F},
+ {0x10030, 0x000281EF},
+ {0x10030, 0x000285E7},
+ {0x10030, 0x000289A7},
+ {0x10030, 0x00028D65},
+ {0x10030, 0x0002915F},
+ {0x10030, 0x00029523},
+ {0x10030, 0x0002991D},
+ {0x10030, 0x00029CE5},
+ {0x10030, 0x0002A0DF},
+ {0x10030, 0x0002A4A7},
{0x10030, 0x0002A8A1},
- {0x10030, 0x0002AC9B},
+ {0x10030, 0x0002AC67},
{0x10030, 0x0002B061},
- {0x10030, 0x0002B45B},
+ {0x10030, 0x0002B427},
{0x10030, 0x0002B821},
- {0x10030, 0x0002BC1B},
- {0x10030, 0x0002C015},
- {0x10030, 0x0002C40F},
- {0x10030, 0x000301A9},
- {0x10030, 0x000305A3},
- {0x10030, 0x0003099D},
- {0x10030, 0x00030D97},
- {0x10030, 0x0003115D},
- {0x10030, 0x00031557},
+ {0x10030, 0x0002BC19},
+ {0x10030, 0x0002C013},
+ {0x10030, 0x0002C40D},
+ {0x10030, 0x000301EF},
+ {0x10030, 0x000305E7},
+ {0x10030, 0x000309A7},
+ {0x10030, 0x00030D65},
+ {0x10030, 0x0003115F},
+ {0x10030, 0x00031525},
{0x10030, 0x0003191F},
- {0x10030, 0x00031D19},
+ {0x10030, 0x00031CE7},
{0x10030, 0x000320E1},
- {0x10030, 0x000324DB},
- {0x10030, 0x000328A1},
- {0x10030, 0x00032C9B},
- {0x10030, 0x00033061},
- {0x10030, 0x0003345B},
- {0x10030, 0x00033821},
- {0x10030, 0x00033C1B},
- {0x10030, 0x00034015},
- {0x10030, 0x0003440F},
+ {0x10030, 0x000324A9},
+ {0x10030, 0x000328A3},
+ {0x10030, 0x00032C69},
+ {0x10030, 0x00033063},
+ {0x10030, 0x00033429},
+ {0x10030, 0x00033823},
+ {0x10030, 0x00033C1D},
+ {0x10030, 0x00034013},
+ {0x10030, 0x0003440D},
{0x10030, 0x000601F1},
{0x10030, 0x000605E9},
{0x10030, 0x000609A9},
@@ -9697,7 +10537,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x0007115B},
{0x10030, 0x00071523},
{0x10030, 0x0007191D},
- {0x10030, 0x00071CE5},
+ {0x10030, 0x00071D17},
{0x10030, 0x000720DF},
{0x10030, 0x000724D9},
{0x10030, 0x000728A1},
@@ -9726,7 +10566,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x0007BC1D},
{0x10030, 0x0007C017},
{0x10030, 0x0007C40F},
- {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
{0x10030, 0x000009E3},
@@ -9745,60 +10585,60 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x00003C5F},
{0x10030, 0x00004059},
{0x10030, 0x00004453},
- {0x10030, 0x000201A7},
- {0x10030, 0x000205A1},
- {0x10030, 0x0002099B},
- {0x10030, 0x00020D95},
- {0x10030, 0x0002115B},
- {0x10030, 0x00021555},
- {0x10030, 0x00021921},
- {0x10030, 0x00021D1B},
- {0x10030, 0x000220E3},
- {0x10030, 0x000224DD},
+ {0x10030, 0x000201EF},
+ {0x10030, 0x000205E9},
+ {0x10030, 0x000209E3},
+ {0x10030, 0x00020DA3},
+ {0x10030, 0x00021161},
+ {0x10030, 0x0002155B},
+ {0x10030, 0x0002191F},
+ {0x10030, 0x00021D19},
+ {0x10030, 0x000220E1},
+ {0x10030, 0x000224DB},
{0x10030, 0x000228A3},
{0x10030, 0x00022C9D},
{0x10030, 0x00023063},
{0x10030, 0x0002345D},
{0x10030, 0x00023823},
- {0x10030, 0x00023C1D},
- {0x10030, 0x00024017},
- {0x10030, 0x00024411},
- {0x10030, 0x000281A9},
- {0x10030, 0x000285A3},
- {0x10030, 0x0002899D},
- {0x10030, 0x00028D97},
- {0x10030, 0x0002915D},
- {0x10030, 0x00029557},
- {0x10030, 0x0002991F},
- {0x10030, 0x00029D19},
- {0x10030, 0x0002A0E1},
- {0x10030, 0x0002A4DB},
+ {0x10030, 0x00023C1B},
+ {0x10030, 0x00024015},
+ {0x10030, 0x0002440F},
+ {0x10030, 0x000281EF},
+ {0x10030, 0x000285E7},
+ {0x10030, 0x000289A7},
+ {0x10030, 0x00028D65},
+ {0x10030, 0x0002915F},
+ {0x10030, 0x00029523},
+ {0x10030, 0x0002991D},
+ {0x10030, 0x00029CE5},
+ {0x10030, 0x0002A0DF},
+ {0x10030, 0x0002A4A7},
{0x10030, 0x0002A8A1},
- {0x10030, 0x0002AC9B},
+ {0x10030, 0x0002AC67},
{0x10030, 0x0002B061},
- {0x10030, 0x0002B45B},
+ {0x10030, 0x0002B427},
{0x10030, 0x0002B821},
- {0x10030, 0x0002BC1B},
- {0x10030, 0x0002C015},
- {0x10030, 0x0002C40F},
- {0x10030, 0x000301A9},
- {0x10030, 0x000305A3},
- {0x10030, 0x0003099D},
- {0x10030, 0x00030D97},
- {0x10030, 0x0003115D},
- {0x10030, 0x00031557},
+ {0x10030, 0x0002BC19},
+ {0x10030, 0x0002C013},
+ {0x10030, 0x0002C40D},
+ {0x10030, 0x000301EF},
+ {0x10030, 0x000305E7},
+ {0x10030, 0x000309A7},
+ {0x10030, 0x00030D65},
+ {0x10030, 0x0003115F},
+ {0x10030, 0x00031525},
{0x10030, 0x0003191F},
- {0x10030, 0x00031D19},
+ {0x10030, 0x00031CE7},
{0x10030, 0x000320E1},
- {0x10030, 0x000324DB},
- {0x10030, 0x000328A1},
- {0x10030, 0x00032C9B},
- {0x10030, 0x00033061},
- {0x10030, 0x0003345B},
- {0x10030, 0x00033821},
- {0x10030, 0x00033C1B},
- {0x10030, 0x00034015},
- {0x10030, 0x0003440F},
+ {0x10030, 0x000324A9},
+ {0x10030, 0x000328A3},
+ {0x10030, 0x00032C69},
+ {0x10030, 0x00033063},
+ {0x10030, 0x00033429},
+ {0x10030, 0x00033823},
+ {0x10030, 0x00033C1D},
+ {0x10030, 0x00034013},
+ {0x10030, 0x0003440D},
{0x10030, 0x000601F1},
{0x10030, 0x000605E9},
{0x10030, 0x000609A9},
@@ -9842,7 +10682,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x0007115B},
{0x10030, 0x00071523},
{0x10030, 0x0007191D},
- {0x10030, 0x00071CE5},
+ {0x10030, 0x00071D17},
{0x10030, 0x000720DF},
{0x10030, 0x000724D9},
{0x10030, 0x000728A1},
@@ -9871,6 +10711,296 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x0007BC1D},
{0x10030, 0x0007C017},
{0x10030, 0x0007C40F},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x000001EF},
+ {0x10030, 0x000005E9},
+ {0x10030, 0x000009E3},
+ {0x10030, 0x00000DDD},
+ {0x10030, 0x000011D7},
+ {0x10030, 0x0000159F},
+ {0x10030, 0x00001999},
+ {0x10030, 0x00001D5F},
+ {0x10030, 0x00002159},
+ {0x10030, 0x0000251F},
+ {0x10030, 0x00002919},
+ {0x10030, 0x00002CDF},
+ {0x10030, 0x000030D9},
+ {0x10030, 0x0000349F},
+ {0x10030, 0x00003899},
+ {0x10030, 0x00003C5F},
+ {0x10030, 0x00004059},
+ {0x10030, 0x00004453},
+ {0x10030, 0x000201A7},
+ {0x10030, 0x000205A1},
+ {0x10030, 0x0002099B},
+ {0x10030, 0x00020D95},
+ {0x10030, 0x0002115B},
+ {0x10030, 0x00021555},
+ {0x10030, 0x00021921},
+ {0x10030, 0x00021D1B},
+ {0x10030, 0x000220E3},
+ {0x10030, 0x000224DD},
+ {0x10030, 0x000228A3},
+ {0x10030, 0x00022C9D},
+ {0x10030, 0x00023063},
+ {0x10030, 0x0002345D},
+ {0x10030, 0x00023823},
+ {0x10030, 0x00023C1D},
+ {0x10030, 0x00024017},
+ {0x10030, 0x00024411},
+ {0x10030, 0x000281A9},
+ {0x10030, 0x000285A3},
+ {0x10030, 0x0002899D},
+ {0x10030, 0x00028D97},
+ {0x10030, 0x0002915D},
+ {0x10030, 0x00029557},
+ {0x10030, 0x0002991F},
+ {0x10030, 0x00029D19},
+ {0x10030, 0x0002A0E1},
+ {0x10030, 0x0002A4DB},
+ {0x10030, 0x0002A8A1},
+ {0x10030, 0x0002AC9B},
+ {0x10030, 0x0002B061},
+ {0x10030, 0x0002B45B},
+ {0x10030, 0x0002B821},
+ {0x10030, 0x0002BC1B},
+ {0x10030, 0x0002C015},
+ {0x10030, 0x0002C40F},
+ {0x10030, 0x000301A9},
+ {0x10030, 0x000305A3},
+ {0x10030, 0x0003099D},
+ {0x10030, 0x00030D97},
+ {0x10030, 0x0003115D},
+ {0x10030, 0x00031557},
+ {0x10030, 0x0003191F},
+ {0x10030, 0x00031D19},
+ {0x10030, 0x000320E1},
+ {0x10030, 0x000324DB},
+ {0x10030, 0x000328A1},
+ {0x10030, 0x00032C9B},
+ {0x10030, 0x00033061},
+ {0x10030, 0x0003345B},
+ {0x10030, 0x00033821},
+ {0x10030, 0x00033C1B},
+ {0x10030, 0x00034015},
+ {0x10030, 0x0003440F},
+ {0x10030, 0x000601F1},
+ {0x10030, 0x000605E9},
+ {0x10030, 0x000609A9},
+ {0x10030, 0x00060D65},
+ {0x10030, 0x0006115F},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
+ {0x10030, 0x000681EF},
+ {0x10030, 0x000685E7},
+ {0x10030, 0x000689A7},
+ {0x10030, 0x00068D61},
+ {0x10030, 0x0006915B},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
+ {0x10030, 0x0006B429},
+ {0x10030, 0x0006B823},
+ {0x10030, 0x0006BC1D},
+ {0x10030, 0x0006C017},
+ {0x10030, 0x0006C411},
+ {0x10030, 0x000701EF},
+ {0x10030, 0x000705E9},
+ {0x10030, 0x000709A9},
+ {0x10030, 0x00070D63},
+ {0x10030, 0x0007115D},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
+ {0x10030, 0x000781EF},
+ {0x10030, 0x000785E9},
+ {0x10030, 0x000789E3},
+ {0x10030, 0x00078DA1},
+ {0x10030, 0x0007915F},
+ {0x10030, 0x00079559},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x000001EF},
+ {0x10030, 0x000005E9},
+ {0x10030, 0x000009E3},
+ {0x10030, 0x00000DDD},
+ {0x10030, 0x000011D7},
+ {0x10030, 0x0000159F},
+ {0x10030, 0x00001999},
+ {0x10030, 0x00001D5F},
+ {0x10030, 0x00002159},
+ {0x10030, 0x0000251F},
+ {0x10030, 0x00002919},
+ {0x10030, 0x00002CDF},
+ {0x10030, 0x000030D9},
+ {0x10030, 0x0000349F},
+ {0x10030, 0x00003899},
+ {0x10030, 0x00003C5F},
+ {0x10030, 0x00004059},
+ {0x10030, 0x00004453},
+ {0x10030, 0x000201A7},
+ {0x10030, 0x000205A1},
+ {0x10030, 0x0002099B},
+ {0x10030, 0x00020D95},
+ {0x10030, 0x0002115B},
+ {0x10030, 0x00021555},
+ {0x10030, 0x00021921},
+ {0x10030, 0x00021D1B},
+ {0x10030, 0x000220E3},
+ {0x10030, 0x000224DD},
+ {0x10030, 0x000228A3},
+ {0x10030, 0x00022C9D},
+ {0x10030, 0x00023063},
+ {0x10030, 0x0002345D},
+ {0x10030, 0x00023823},
+ {0x10030, 0x00023C1D},
+ {0x10030, 0x00024017},
+ {0x10030, 0x00024411},
+ {0x10030, 0x000281A9},
+ {0x10030, 0x000285A3},
+ {0x10030, 0x0002899D},
+ {0x10030, 0x00028D97},
+ {0x10030, 0x0002915D},
+ {0x10030, 0x00029557},
+ {0x10030, 0x0002991F},
+ {0x10030, 0x00029D19},
+ {0x10030, 0x0002A0E1},
+ {0x10030, 0x0002A4DB},
+ {0x10030, 0x0002A8A1},
+ {0x10030, 0x0002AC9B},
+ {0x10030, 0x0002B061},
+ {0x10030, 0x0002B45B},
+ {0x10030, 0x0002B821},
+ {0x10030, 0x0002BC1B},
+ {0x10030, 0x0002C015},
+ {0x10030, 0x0002C40F},
+ {0x10030, 0x000301A9},
+ {0x10030, 0x000305A3},
+ {0x10030, 0x0003099D},
+ {0x10030, 0x00030D97},
+ {0x10030, 0x0003115D},
+ {0x10030, 0x00031557},
+ {0x10030, 0x0003191F},
+ {0x10030, 0x00031D19},
+ {0x10030, 0x000320E1},
+ {0x10030, 0x000324DB},
+ {0x10030, 0x000328A1},
+ {0x10030, 0x00032C9B},
+ {0x10030, 0x00033061},
+ {0x10030, 0x0003345B},
+ {0x10030, 0x00033821},
+ {0x10030, 0x00033C1B},
+ {0x10030, 0x00034015},
+ {0x10030, 0x0003440F},
+ {0x10030, 0x000601F1},
+ {0x10030, 0x000605E9},
+ {0x10030, 0x000609A9},
+ {0x10030, 0x00060D65},
+ {0x10030, 0x0006115F},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
+ {0x10030, 0x000681EF},
+ {0x10030, 0x000685E7},
+ {0x10030, 0x000689A7},
+ {0x10030, 0x00068D61},
+ {0x10030, 0x0006915B},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
+ {0x10030, 0x0006B429},
+ {0x10030, 0x0006B823},
+ {0x10030, 0x0006BC1D},
+ {0x10030, 0x0006C017},
+ {0x10030, 0x0006C411},
+ {0x10030, 0x000701EF},
+ {0x10030, 0x000705E9},
+ {0x10030, 0x000709A9},
+ {0x10030, 0x00070D63},
+ {0x10030, 0x0007115D},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
+ {0x10030, 0x000781EF},
+ {0x10030, 0x000785E9},
+ {0x10030, 0x000789E3},
+ {0x10030, 0x00078DA1},
+ {0x10030, 0x0007915F},
+ {0x10030, 0x00079559},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -9949,73 +11079,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x000609A9},
{0x10030, 0x00060D65},
{0x10030, 0x0006115F},
- {0x10030, 0x00061525},
- {0x10030, 0x0006191F},
- {0x10030, 0x00061CE7},
- {0x10030, 0x000620E1},
- {0x10030, 0x000624DB},
- {0x10030, 0x000628A3},
- {0x10030, 0x00062C69},
- {0x10030, 0x00063063},
- {0x10030, 0x00063429},
- {0x10030, 0x00063823},
- {0x10030, 0x00063C1D},
- {0x10030, 0x00064013},
- {0x10030, 0x0006440D},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
{0x10030, 0x000681EF},
{0x10030, 0x000685E7},
{0x10030, 0x000689A7},
{0x10030, 0x00068D61},
{0x10030, 0x0006915B},
- {0x10030, 0x00069523},
- {0x10030, 0x0006991D},
- {0x10030, 0x00069CE5},
- {0x10030, 0x0006A0DF},
- {0x10030, 0x0006A4A7},
- {0x10030, 0x0006A8A1},
- {0x10030, 0x0006AC67},
- {0x10030, 0x0006B061},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
{0x10030, 0x0006B429},
{0x10030, 0x0006B823},
{0x10030, 0x0006BC1D},
{0x10030, 0x0006C017},
- {0x10030, 0x0006C40D},
+ {0x10030, 0x0006C411},
{0x10030, 0x000701EF},
- {0x10030, 0x000705E7},
- {0x10030, 0x000709A7},
- {0x10030, 0x00070D61},
- {0x10030, 0x0007115B},
- {0x10030, 0x00071523},
- {0x10030, 0x0007191D},
- {0x10030, 0x00071CE5},
- {0x10030, 0x000720DF},
- {0x10030, 0x000724D9},
- {0x10030, 0x000728A1},
- {0x10030, 0x00072C67},
- {0x10030, 0x00073061},
- {0x10030, 0x00073427},
- {0x10030, 0x00073821},
- {0x10030, 0x00073C1B},
- {0x10030, 0x00074015},
- {0x10030, 0x0007440D},
+ {0x10030, 0x000705E9},
+ {0x10030, 0x000709A9},
+ {0x10030, 0x00070D63},
+ {0x10030, 0x0007115D},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
{0x10030, 0x000781EF},
{0x10030, 0x000785E9},
{0x10030, 0x000789E3},
{0x10030, 0x00078DA1},
{0x10030, 0x0007915F},
{0x10030, 0x00079559},
- {0x10030, 0x00079921},
- {0x10030, 0x00079D1B},
- {0x10030, 0x0007A0E3},
- {0x10030, 0x0007A4DD},
- {0x10030, 0x0007A8D7},
- {0x10030, 0x0007AC9D},
- {0x10030, 0x0007B063},
- {0x10030, 0x0007B45D},
- {0x10030, 0x0007B823},
- {0x10030, 0x0007BC1D},
- {0x10030, 0x0007C017},
- {0x10030, 0x0007C40F},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -10094,73 +11224,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x000609A9},
{0x10030, 0x00060D65},
{0x10030, 0x0006115F},
- {0x10030, 0x00061525},
- {0x10030, 0x0006191F},
- {0x10030, 0x00061CE7},
- {0x10030, 0x000620E1},
- {0x10030, 0x000624DB},
- {0x10030, 0x000628A3},
- {0x10030, 0x00062C69},
- {0x10030, 0x00063063},
- {0x10030, 0x00063429},
- {0x10030, 0x00063823},
- {0x10030, 0x00063C1D},
- {0x10030, 0x00064013},
- {0x10030, 0x0006440D},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
{0x10030, 0x000681EF},
{0x10030, 0x000685E7},
{0x10030, 0x000689A7},
{0x10030, 0x00068D61},
{0x10030, 0x0006915B},
- {0x10030, 0x00069523},
- {0x10030, 0x0006991D},
- {0x10030, 0x00069CE5},
- {0x10030, 0x0006A0DF},
- {0x10030, 0x0006A4A7},
- {0x10030, 0x0006A8A1},
- {0x10030, 0x0006AC67},
- {0x10030, 0x0006B061},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
{0x10030, 0x0006B429},
{0x10030, 0x0006B823},
{0x10030, 0x0006BC1D},
{0x10030, 0x0006C017},
- {0x10030, 0x0006C40D},
+ {0x10030, 0x0006C411},
{0x10030, 0x000701EF},
- {0x10030, 0x000705E7},
- {0x10030, 0x000709A7},
- {0x10030, 0x00070D61},
- {0x10030, 0x0007115B},
- {0x10030, 0x00071523},
- {0x10030, 0x0007191D},
- {0x10030, 0x00071CE5},
- {0x10030, 0x000720DF},
- {0x10030, 0x000724D9},
- {0x10030, 0x000728A1},
- {0x10030, 0x00072C67},
- {0x10030, 0x00073061},
- {0x10030, 0x00073427},
- {0x10030, 0x00073821},
- {0x10030, 0x00073C1B},
- {0x10030, 0x00074015},
- {0x10030, 0x0007440D},
+ {0x10030, 0x000705E9},
+ {0x10030, 0x000709A9},
+ {0x10030, 0x00070D63},
+ {0x10030, 0x0007115D},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
{0x10030, 0x000781EF},
{0x10030, 0x000785E9},
{0x10030, 0x000789E3},
{0x10030, 0x00078DA1},
{0x10030, 0x0007915F},
{0x10030, 0x00079559},
- {0x10030, 0x00079921},
- {0x10030, 0x00079D1B},
- {0x10030, 0x0007A0E3},
- {0x10030, 0x0007A4DD},
- {0x10030, 0x0007A8D7},
- {0x10030, 0x0007AC9D},
- {0x10030, 0x0007B063},
- {0x10030, 0x0007B45D},
- {0x10030, 0x0007B823},
- {0x10030, 0x0007BC1D},
- {0x10030, 0x0007C017},
- {0x10030, 0x0007C40F},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -10239,73 +11369,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x000609A9},
{0x10030, 0x00060D65},
{0x10030, 0x0006115F},
- {0x10030, 0x00061525},
- {0x10030, 0x0006191F},
- {0x10030, 0x00061CE7},
- {0x10030, 0x000620E1},
- {0x10030, 0x000624DB},
- {0x10030, 0x000628A3},
- {0x10030, 0x00062C69},
- {0x10030, 0x00063063},
- {0x10030, 0x00063429},
- {0x10030, 0x00063823},
- {0x10030, 0x00063C1D},
- {0x10030, 0x00064013},
- {0x10030, 0x0006440D},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
{0x10030, 0x000681EF},
{0x10030, 0x000685E7},
{0x10030, 0x000689A7},
{0x10030, 0x00068D61},
{0x10030, 0x0006915B},
- {0x10030, 0x00069523},
- {0x10030, 0x0006991D},
- {0x10030, 0x00069CE5},
- {0x10030, 0x0006A0DF},
- {0x10030, 0x0006A4A7},
- {0x10030, 0x0006A8A1},
- {0x10030, 0x0006AC67},
- {0x10030, 0x0006B061},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
{0x10030, 0x0006B429},
{0x10030, 0x0006B823},
{0x10030, 0x0006BC1D},
{0x10030, 0x0006C017},
- {0x10030, 0x0006C40D},
+ {0x10030, 0x0006C411},
{0x10030, 0x000701EF},
- {0x10030, 0x000705E7},
- {0x10030, 0x000709A7},
- {0x10030, 0x00070D61},
- {0x10030, 0x0007115B},
- {0x10030, 0x00071523},
- {0x10030, 0x0007191D},
- {0x10030, 0x00071CE5},
- {0x10030, 0x000720DF},
- {0x10030, 0x000724D9},
- {0x10030, 0x000728A1},
- {0x10030, 0x00072C67},
- {0x10030, 0x00073061},
- {0x10030, 0x00073427},
- {0x10030, 0x00073821},
- {0x10030, 0x00073C1B},
- {0x10030, 0x00074015},
- {0x10030, 0x0007440D},
+ {0x10030, 0x000705E9},
+ {0x10030, 0x000709A9},
+ {0x10030, 0x00070D63},
+ {0x10030, 0x0007115D},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
{0x10030, 0x000781EF},
{0x10030, 0x000785E9},
{0x10030, 0x000789E3},
{0x10030, 0x00078DA1},
{0x10030, 0x0007915F},
{0x10030, 0x00079559},
- {0x10030, 0x00079921},
- {0x10030, 0x00079D1B},
- {0x10030, 0x0007A0E3},
- {0x10030, 0x0007A4DD},
- {0x10030, 0x0007A8D7},
- {0x10030, 0x0007AC9D},
- {0x10030, 0x0007B063},
- {0x10030, 0x0007B45D},
- {0x10030, 0x0007B823},
- {0x10030, 0x0007BC1D},
- {0x10030, 0x0007C017},
- {0x10030, 0x0007C40F},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -10384,73 +11514,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x000609A9},
{0x10030, 0x00060D65},
{0x10030, 0x0006115F},
- {0x10030, 0x00061525},
- {0x10030, 0x0006191F},
- {0x10030, 0x00061CE7},
- {0x10030, 0x000620E1},
- {0x10030, 0x000624DB},
- {0x10030, 0x000628A3},
- {0x10030, 0x00062C69},
- {0x10030, 0x00063063},
- {0x10030, 0x00063429},
- {0x10030, 0x00063823},
- {0x10030, 0x00063C1D},
- {0x10030, 0x00064013},
- {0x10030, 0x0006440D},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
{0x10030, 0x000681EF},
{0x10030, 0x000685E7},
{0x10030, 0x000689A7},
{0x10030, 0x00068D61},
{0x10030, 0x0006915B},
- {0x10030, 0x00069523},
- {0x10030, 0x0006991D},
- {0x10030, 0x00069CE5},
- {0x10030, 0x0006A0DF},
- {0x10030, 0x0006A4A7},
- {0x10030, 0x0006A8A1},
- {0x10030, 0x0006AC67},
- {0x10030, 0x0006B061},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
{0x10030, 0x0006B429},
{0x10030, 0x0006B823},
{0x10030, 0x0006BC1D},
{0x10030, 0x0006C017},
- {0x10030, 0x0006C40D},
+ {0x10030, 0x0006C411},
{0x10030, 0x000701EF},
- {0x10030, 0x000705E7},
- {0x10030, 0x000709A7},
- {0x10030, 0x00070D61},
- {0x10030, 0x0007115B},
- {0x10030, 0x00071523},
- {0x10030, 0x0007191D},
- {0x10030, 0x00071CE5},
- {0x10030, 0x000720DF},
- {0x10030, 0x000724D9},
- {0x10030, 0x000728A1},
- {0x10030, 0x00072C67},
- {0x10030, 0x00073061},
- {0x10030, 0x00073427},
- {0x10030, 0x00073821},
- {0x10030, 0x00073C1B},
- {0x10030, 0x00074015},
- {0x10030, 0x0007440D},
+ {0x10030, 0x000705E9},
+ {0x10030, 0x000709A9},
+ {0x10030, 0x00070D63},
+ {0x10030, 0x0007115D},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
{0x10030, 0x000781EF},
{0x10030, 0x000785E9},
{0x10030, 0x000789E3},
{0x10030, 0x00078DA1},
{0x10030, 0x0007915F},
{0x10030, 0x00079559},
- {0x10030, 0x00079921},
- {0x10030, 0x00079D1B},
- {0x10030, 0x0007A0E3},
- {0x10030, 0x0007A4DD},
- {0x10030, 0x0007A8D7},
- {0x10030, 0x0007AC9D},
- {0x10030, 0x0007B063},
- {0x10030, 0x0007B45D},
- {0x10030, 0x0007B823},
- {0x10030, 0x0007BC1D},
- {0x10030, 0x0007C017},
- {0x10030, 0x0007C40F},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0xA0000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -11294,6 +12424,110 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x000338CC},
{0x10030, 0x00033C09},
{0x10030, 0x00034006},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x000200E8},
+ {0x10030, 0x000204E5},
+ {0x10030, 0x000208E2},
+ {0x10030, 0x00020CDF},
+ {0x10030, 0x000210DC},
+ {0x10030, 0x000214D9},
+ {0x10030, 0x000218D6},
+ {0x10030, 0x00021CD3},
+ {0x10030, 0x000220D0},
+ {0x10030, 0x0002240D},
+ {0x10030, 0x0002280A},
+ {0x10030, 0x00022C07},
+ {0x10030, 0x00023004},
+ {0x10030, 0x00023401},
+ {0x10030, 0x00023800},
+ {0x10030, 0x00023C00},
+ {0x10030, 0x00024000},
+ {0x10030, 0x000280ED},
+ {0x10030, 0x000284EA},
+ {0x10030, 0x000288E7},
+ {0x10030, 0x00028CE4},
+ {0x10030, 0x000290E1},
+ {0x10030, 0x000294DE},
+ {0x10030, 0x000298DB},
+ {0x10030, 0x00029CD8},
+ {0x10030, 0x0002A0D5},
+ {0x10030, 0x0002A4D2},
+ {0x10030, 0x0002A8CF},
+ {0x10030, 0x0002AC0C},
+ {0x10030, 0x0002B009},
+ {0x10030, 0x0002B406},
+ {0x10030, 0x0002B803},
+ {0x10030, 0x0002BC00},
+ {0x10030, 0x0002C000},
+ {0x10030, 0x000300EE},
+ {0x10030, 0x000304EB},
+ {0x10030, 0x000308E8},
+ {0x10030, 0x00030CE5},
+ {0x10030, 0x000310E2},
+ {0x10030, 0x000314DF},
+ {0x10030, 0x000318DC},
+ {0x10030, 0x00031CD9},
+ {0x10030, 0x000320D6},
+ {0x10030, 0x000324D3},
+ {0x10030, 0x000328D0},
+ {0x10030, 0x00032CCD},
+ {0x10030, 0x0003300A},
+ {0x10030, 0x00033407},
+ {0x10030, 0x00033804},
+ {0x10030, 0x00033C01},
+ {0x10030, 0x00034000},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x000200E8},
+ {0x10030, 0x000204E5},
+ {0x10030, 0x000208E2},
+ {0x10030, 0x00020CDF},
+ {0x10030, 0x000210DC},
+ {0x10030, 0x000214D9},
+ {0x10030, 0x000218D6},
+ {0x10030, 0x00021CD3},
+ {0x10030, 0x000220D0},
+ {0x10030, 0x0002240D},
+ {0x10030, 0x0002280A},
+ {0x10030, 0x00022C07},
+ {0x10030, 0x00023004},
+ {0x10030, 0x00023401},
+ {0x10030, 0x00023800},
+ {0x10030, 0x00023C00},
+ {0x10030, 0x00024000},
+ {0x10030, 0x000280ED},
+ {0x10030, 0x000284EA},
+ {0x10030, 0x000288E7},
+ {0x10030, 0x00028CE4},
+ {0x10030, 0x000290E1},
+ {0x10030, 0x000294DE},
+ {0x10030, 0x000298DB},
+ {0x10030, 0x00029CD8},
+ {0x10030, 0x0002A0D5},
+ {0x10030, 0x0002A4D2},
+ {0x10030, 0x0002A8CF},
+ {0x10030, 0x0002AC0C},
+ {0x10030, 0x0002B009},
+ {0x10030, 0x0002B406},
+ {0x10030, 0x0002B803},
+ {0x10030, 0x0002BC00},
+ {0x10030, 0x0002C000},
+ {0x10030, 0x000300EE},
+ {0x10030, 0x000304EB},
+ {0x10030, 0x000308E8},
+ {0x10030, 0x00030CE5},
+ {0x10030, 0x000310E2},
+ {0x10030, 0x000314DF},
+ {0x10030, 0x000318DC},
+ {0x10030, 0x00031CD9},
+ {0x10030, 0x000320D6},
+ {0x10030, 0x000324D3},
+ {0x10030, 0x000328D0},
+ {0x10030, 0x00032CCD},
+ {0x10030, 0x0003300A},
+ {0x10030, 0x00033407},
+ {0x10030, 0x00033804},
+ {0x10030, 0x00033C01},
+ {0x10030, 0x00034000},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000200FA},
{0x10030, 0x000204F7},
@@ -11841,6 +13075,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -11885,6 +13123,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -11941,6 +13183,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -11985,6 +13231,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12041,6 +13291,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12085,6 +13339,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12141,6 +13399,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12185,6 +13447,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12241,6 +13507,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12285,6 +13555,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12305,7 +13579,53 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x033, 0x00000070},
{0x03F, 0x00050002},
{0x033, 0x00000071},
+ {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00060032},
+ {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0xA0000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0xB0000000, 0x00000000},
{0x033, 0x00000072},
{0x03F, 0x00050042},
{0x033, 0x00000073},
@@ -12341,6 +13661,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12385,6 +13709,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12405,7 +13733,53 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x033, 0x00000078},
{0x03F, 0x00050002},
{0x033, 0x00000079},
+ {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00060032},
+ {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0xA0000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0xB0000000, 0x00000000},
{0x033, 0x0000007A},
{0x03F, 0x00050042},
{0x033, 0x0000007B},
@@ -12441,6 +13815,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12485,6 +13863,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12541,6 +13923,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12585,6 +13971,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12641,6 +14031,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12685,6 +14079,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12741,6 +14139,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12785,6 +14187,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12841,6 +14247,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12885,6 +14295,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12941,6 +14355,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12985,6 +14403,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13041,6 +14463,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13085,6 +14511,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13141,6 +14571,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13185,6 +14619,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13241,6 +14679,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13285,6 +14727,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13341,6 +14787,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13385,6 +14835,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13441,6 +14895,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13485,6 +14943,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13541,6 +15003,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13585,6 +15051,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13641,6 +15111,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13685,6 +15159,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13741,6 +15219,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13785,6 +15267,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13841,6 +15327,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13885,6 +15375,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13941,6 +15435,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13985,6 +15483,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14041,6 +15543,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14085,6 +15591,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14141,6 +15651,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14185,6 +15699,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14241,6 +15759,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14285,6 +15807,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14341,6 +15867,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14385,6 +15915,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14441,6 +15975,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14485,6 +16023,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14541,6 +16083,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14585,6 +16131,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14669,6 +16219,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x00025003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00025003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00025003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00025003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00025003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14719,6 +16273,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x0002D003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0002D003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0002D003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0002D003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0002D003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14769,6 +16327,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x00035003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00035003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00035003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00035003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00035003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14819,6 +16381,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x0003D003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0003D003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0003D003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0003D003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0003D003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14882,6 +16448,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00065003},
{0x10030, 0x00066003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00065003},
+ {0x10030, 0x00066003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00065003},
+ {0x10030, 0x00066003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00065003},
{0x10030, 0x00066003},
@@ -14952,6 +16524,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0006D003},
{0x10030, 0x0006E003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0006D003},
+ {0x10030, 0x0006E003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0006D003},
+ {0x10030, 0x0006E003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0006D003},
{0x10030, 0x0006E003},
@@ -15022,6 +16600,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00075003},
{0x10030, 0x00076003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00075003},
+ {0x10030, 0x00076003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00075003},
+ {0x10030, 0x00076003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00075003},
{0x10030, 0x00076003},
@@ -15092,6 +16676,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0007D003},
{0x10030, 0x0007E003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0007D003},
+ {0x10030, 0x0007E003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0007D003},
+ {0x10030, 0x0007E003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0007D003},
{0x10030, 0x0007E003},
@@ -15119,7 +16709,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0xB0000000, 0x00000000},
{0x10030, 0x0007F003},
{0x100EE, 0x00000000},
- {0x0FE, 0x00000048},
+ {0x0FE, 0x00000063},
};
static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
@@ -15136,13 +16726,15 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0xF0040001, 0x0000000A},
{0xF0050001, 0x0000000B},
{0xF0070001, 0x0000000C},
- {0xF0320001, 0x0000000D},
- {0xF0330001, 0x0000000E},
- {0xF0340001, 0x0000000F},
- {0xF0350001, 0x00000010},
- {0xF0360001, 0x00000011},
- {0xF03F0001, 0x00000012},
- {0xF0400001, 0x00000013},
+ {0xF0150001, 0x0000000D},
+ {0xF0160001, 0x0000000E},
+ {0xF0320001, 0x0000000F},
+ {0xF0330001, 0x00000010},
+ {0xF0340001, 0x00000011},
+ {0xF0350001, 0x00000012},
+ {0xF0360001, 0x00000013},
+ {0xF03F0001, 0x00000014},
+ {0xF0400001, 0x00000015},
{0x005, 0x00000000},
{0x10005, 0x00000000},
{0x0B9, 0x00020440},
@@ -15150,6 +16742,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10000, 0x00030000},
{0x018, 0x00011124},
{0x10018, 0x00011124},
+ {0x0A3, 0x000B9204},
+ {0x0AD, 0x00091E0F},
+ {0x05D, 0x00001012},
+ {0x05C, 0x00079C5C},
+ {0x062, 0x00055220},
+ {0x0D3, 0x00000103},
{0x05F, 0x00000038},
{0x097, 0x00043200},
{0x0A6, 0x00066DB7},
@@ -15253,6 +16851,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x067, 0x0000D300},
{0x0DA, 0x000D4000},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x067, 0x0000D300},
+ {0x0DA, 0x000D4000},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x067, 0x0000D300},
+ {0x0DA, 0x000D4000},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x067, 0x0000D300},
{0x0DA, 0x000D4000},
@@ -15319,6 +16923,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x08F, 0x000D1352},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x08F, 0x000D1352},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x08F, 0x000D1352},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x08F, 0x000D1352},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x08F, 0x000D1352},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -15382,6 +16990,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000007},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000007},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000017},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000017},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000007},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -15918,6 +17530,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000EFFF},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000EFFF},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000EFFF},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000EFFF},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000EFFF},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16256,6 +17872,32 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x030, 0x00050112},
{0x030, 0x00058101},
{0x030, 0x00060001},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x000085ED},
+ {0x030, 0x000105CC},
+ {0x030, 0x000184AA},
+ {0x030, 0x00020388},
+ {0x030, 0x00028377},
+ {0x030, 0x00030377},
+ {0x030, 0x00038255},
+ {0x030, 0x00040244},
+ {0x030, 0x00048133},
+ {0x030, 0x00050112},
+ {0x030, 0x00058101},
+ {0x030, 0x00060001},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x000085ED},
+ {0x030, 0x000105CC},
+ {0x030, 0x000184AA},
+ {0x030, 0x00020388},
+ {0x030, 0x00028377},
+ {0x030, 0x00030377},
+ {0x030, 0x00038255},
+ {0x030, 0x00040244},
+ {0x030, 0x00048133},
+ {0x030, 0x00050112},
+ {0x030, 0x00058101},
+ {0x030, 0x00060001},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x030, 0x000085ED},
{0x030, 0x000105CC},
@@ -16582,11 +18224,291 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x0EF, 0x00000000},
{0x06E, 0x00077A18},
{0x06D, 0x00000C31},
+ {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x06A, 0x000E0F8A},
{0x06B, 0x000018A0},
{0x06F, 0x000F81FC},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0380},
+ {0x06B, 0x00003CA0},
+ {0x06F, 0x000C01FC},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0380},
+ {0x06B, 0x00003CA0},
+ {0x06F, 0x000C01FC},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0xA0000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0xB0000000, 0x00000000},
{0x05E, 0x0000001F},
{0x0EF, 0x00000200},
+ {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
{0x030, 0x0003D407},
{0x030, 0x00035A87},
{0x030, 0x0002CF07},
@@ -16595,14 +18517,180 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x030, 0x00014F07},
{0x030, 0x0000CF07},
{0x030, 0x00004F07},
+ {0xA0000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0xB0000000, 0x00000000},
{0x0EF, 0x00000000},
{0x0EB, 0x00080000},
+ {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
{0x030, 0x00008038},
{0x030, 0x00010038},
{0x030, 0x00018038},
{0x030, 0x00020038},
{0x030, 0x00028038},
{0x030, 0x00030038},
+ {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0000803C},
+ {0x030, 0x0001003C},
+ {0x030, 0x0001803C},
+ {0x030, 0x0002003C},
+ {0x030, 0x0002803C},
+ {0x030, 0x0003003C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0000803C},
+ {0x030, 0x0001003C},
+ {0x030, 0x0001803C},
+ {0x030, 0x0002003C},
+ {0x030, 0x0002803C},
+ {0x030, 0x0003003C},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0xA0000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0xB0000000, 0x00000000},
{0x030, 0x0003803C},
{0x030, 0x0004003C},
{0x030, 0x0004803C},
@@ -16639,6 +18727,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x095, 0x00000008},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x095, 0x00000008},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x095, 0x00000008},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x095, 0x00000008},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x095, 0x00000008},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16684,6 +18776,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16728,6 +18824,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16772,6 +18872,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16816,6 +18920,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16860,6 +18968,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16904,6 +19016,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16948,6 +19064,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16992,6 +19112,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17036,6 +19160,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17080,6 +19208,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17124,6 +19256,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17168,6 +19304,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17212,6 +19352,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17256,6 +19400,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17300,6 +19448,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17344,6 +19496,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17388,6 +19544,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17432,6 +19592,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17476,6 +19640,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17520,6 +19688,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17564,6 +19736,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17608,6 +19784,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17652,6 +19832,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17696,6 +19880,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17740,20 +19928,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0xA0000000, 0x00000000},
{0x03F, 0x00000052},
{0xB0000000, 0x00000000},
@@ -17784,20 +19976,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0xA0000000, 0x00000000},
{0x03F, 0x0000005A},
{0xB0000000, 0x00000000},
@@ -17828,20 +20024,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0xA0000000, 0x00000000},
{0x03F, 0x0000009C},
{0xB0000000, 0x00000000},
@@ -17872,20 +20072,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0xA0000000, 0x00000000},
{0x03F, 0x0000019C},
{0xB0000000, 0x00000000},
@@ -17916,20 +20120,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001A4},
{0xB0000000, 0x00000000},
@@ -17960,20 +20168,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001E6},
{0xB0000000, 0x00000000},
@@ -18004,20 +20216,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000002E6},
{0xB0000000, 0x00000000},
@@ -18048,20 +20264,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000003E6},
{0xB0000000, 0x00000000},
@@ -18092,20 +20312,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0xA0000000, 0x00000000},
{0x03F, 0x00000052},
{0xB0000000, 0x00000000},
@@ -18136,20 +20360,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0xA0000000, 0x00000000},
{0x03F, 0x0000005A},
{0xB0000000, 0x00000000},
@@ -18180,20 +20408,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0xA0000000, 0x00000000},
{0x03F, 0x0000009C},
{0xB0000000, 0x00000000},
@@ -18224,20 +20456,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0xA0000000, 0x00000000},
{0x03F, 0x0000019C},
{0xB0000000, 0x00000000},
@@ -18268,20 +20504,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001A4},
{0xB0000000, 0x00000000},
@@ -18312,20 +20552,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001E6},
{0xB0000000, 0x00000000},
@@ -18356,20 +20600,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000002E6},
{0xB0000000, 0x00000000},
@@ -18400,20 +20648,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000003E6},
{0xB0000000, 0x00000000},
@@ -18444,20 +20696,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0xA0000000, 0x00000000},
{0x03F, 0x00000052},
{0xB0000000, 0x00000000},
@@ -18488,20 +20744,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0xA0000000, 0x00000000},
{0x03F, 0x0000005A},
{0xB0000000, 0x00000000},
@@ -18532,20 +20792,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0xA0000000, 0x00000000},
{0x03F, 0x0000009C},
{0xB0000000, 0x00000000},
@@ -18576,20 +20840,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0xA0000000, 0x00000000},
{0x03F, 0x0000019C},
{0xB0000000, 0x00000000},
@@ -18620,20 +20888,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001A4},
{0xB0000000, 0x00000000},
@@ -18664,20 +20936,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001E6},
{0xB0000000, 0x00000000},
@@ -18708,20 +20984,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000002E6},
{0xB0000000, 0x00000000},
@@ -18752,20 +21032,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000003E6},
{0xB0000000, 0x00000000},
@@ -18796,20 +21080,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0xA0000000, 0x00000000},
{0x03F, 0x00000052},
{0xB0000000, 0x00000000},
@@ -18840,20 +21128,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0xA0000000, 0x00000000},
{0x03F, 0x0000005A},
{0xB0000000, 0x00000000},
@@ -18884,20 +21176,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0xA0000000, 0x00000000},
{0x03F, 0x0000009C},
{0xB0000000, 0x00000000},
@@ -18928,20 +21224,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0xA0000000, 0x00000000},
{0x03F, 0x0000019C},
{0xB0000000, 0x00000000},
@@ -18972,20 +21272,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001A4},
{0xB0000000, 0x00000000},
@@ -19016,20 +21320,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001E6},
{0xB0000000, 0x00000000},
@@ -20924,7 +23232,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x0007BC1D},
{0x10030, 0x0007C017},
{0x10030, 0x0007C40F},
- {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
{0x10030, 0x000009E3},
@@ -21069,7 +23377,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x0007BC1D},
{0x10030, 0x0007C017},
{0x10030, 0x0007C40F},
- {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
{0x10030, 0x000009E3},
@@ -21088,60 +23396,60 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x00003C5F},
{0x10030, 0x00004059},
{0x10030, 0x00004453},
- {0x10030, 0x000201A7},
- {0x10030, 0x000205A1},
- {0x10030, 0x0002099B},
- {0x10030, 0x00020D95},
- {0x10030, 0x0002115B},
- {0x10030, 0x00021555},
- {0x10030, 0x00021921},
- {0x10030, 0x00021D1B},
- {0x10030, 0x000220E3},
- {0x10030, 0x000224DD},
+ {0x10030, 0x000201EF},
+ {0x10030, 0x000205E9},
+ {0x10030, 0x000209E3},
+ {0x10030, 0x00020DA3},
+ {0x10030, 0x00021161},
+ {0x10030, 0x0002155B},
+ {0x10030, 0x0002191F},
+ {0x10030, 0x00021D19},
+ {0x10030, 0x000220E1},
+ {0x10030, 0x000224DB},
{0x10030, 0x000228A3},
{0x10030, 0x00022C9D},
{0x10030, 0x00023063},
{0x10030, 0x0002345D},
{0x10030, 0x00023823},
- {0x10030, 0x00023C1D},
- {0x10030, 0x00024017},
- {0x10030, 0x00024411},
- {0x10030, 0x000281A9},
- {0x10030, 0x000285A3},
- {0x10030, 0x0002899D},
- {0x10030, 0x00028D97},
- {0x10030, 0x0002915D},
- {0x10030, 0x00029557},
- {0x10030, 0x0002991F},
- {0x10030, 0x00029D19},
- {0x10030, 0x0002A0E1},
- {0x10030, 0x0002A4DB},
+ {0x10030, 0x00023C1B},
+ {0x10030, 0x00024015},
+ {0x10030, 0x0002440F},
+ {0x10030, 0x000281EF},
+ {0x10030, 0x000285E7},
+ {0x10030, 0x000289A7},
+ {0x10030, 0x00028D65},
+ {0x10030, 0x0002915F},
+ {0x10030, 0x00029523},
+ {0x10030, 0x0002991D},
+ {0x10030, 0x00029CE5},
+ {0x10030, 0x0002A0DF},
+ {0x10030, 0x0002A4A7},
{0x10030, 0x0002A8A1},
- {0x10030, 0x0002AC9B},
+ {0x10030, 0x0002AC67},
{0x10030, 0x0002B061},
- {0x10030, 0x0002B45B},
+ {0x10030, 0x0002B427},
{0x10030, 0x0002B821},
- {0x10030, 0x0002BC1B},
- {0x10030, 0x0002C015},
- {0x10030, 0x0002C40F},
- {0x10030, 0x000301A9},
- {0x10030, 0x000305A3},
- {0x10030, 0x0003099D},
- {0x10030, 0x00030D97},
- {0x10030, 0x0003115D},
- {0x10030, 0x00031557},
+ {0x10030, 0x0002BC19},
+ {0x10030, 0x0002C013},
+ {0x10030, 0x0002C40D},
+ {0x10030, 0x000301EF},
+ {0x10030, 0x000305E7},
+ {0x10030, 0x000309A7},
+ {0x10030, 0x00030D65},
+ {0x10030, 0x0003115F},
+ {0x10030, 0x00031525},
{0x10030, 0x0003191F},
- {0x10030, 0x00031D19},
+ {0x10030, 0x00031CE7},
{0x10030, 0x000320E1},
- {0x10030, 0x000324DB},
- {0x10030, 0x000328A1},
- {0x10030, 0x00032C9B},
- {0x10030, 0x00033061},
- {0x10030, 0x0003345B},
- {0x10030, 0x00033821},
- {0x10030, 0x00033C1B},
- {0x10030, 0x00034015},
- {0x10030, 0x0003440F},
+ {0x10030, 0x000324A9},
+ {0x10030, 0x000328A3},
+ {0x10030, 0x00032C69},
+ {0x10030, 0x00033063},
+ {0x10030, 0x00033429},
+ {0x10030, 0x00033823},
+ {0x10030, 0x00033C1D},
+ {0x10030, 0x00034013},
+ {0x10030, 0x0003440D},
{0x10030, 0x000601F1},
{0x10030, 0x000605E9},
{0x10030, 0x000609A9},
@@ -21186,7 +23494,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x00071523},
{0x10030, 0x0007191D},
{0x10030, 0x00071D17},
- {0x10030, 0x000720DF},
+ {0x10030, 0x00072111},
{0x10030, 0x000724D9},
{0x10030, 0x000728D3},
{0x10030, 0x00072C67},
@@ -21214,7 +23522,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x0007BC1D},
{0x10030, 0x0007C017},
{0x10030, 0x0007C40F},
- {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
{0x10030, 0x000009E3},
@@ -21233,60 +23541,60 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x00003C5F},
{0x10030, 0x00004059},
{0x10030, 0x00004453},
- {0x10030, 0x000201A7},
- {0x10030, 0x000205A1},
- {0x10030, 0x0002099B},
- {0x10030, 0x00020D95},
- {0x10030, 0x0002115B},
- {0x10030, 0x00021555},
- {0x10030, 0x00021921},
- {0x10030, 0x00021D1B},
- {0x10030, 0x000220E3},
- {0x10030, 0x000224DD},
+ {0x10030, 0x000201EF},
+ {0x10030, 0x000205E9},
+ {0x10030, 0x000209E3},
+ {0x10030, 0x00020DA3},
+ {0x10030, 0x00021161},
+ {0x10030, 0x0002155B},
+ {0x10030, 0x0002191F},
+ {0x10030, 0x00021D19},
+ {0x10030, 0x000220E1},
+ {0x10030, 0x000224DB},
{0x10030, 0x000228A3},
{0x10030, 0x00022C9D},
{0x10030, 0x00023063},
{0x10030, 0x0002345D},
{0x10030, 0x00023823},
- {0x10030, 0x00023C1D},
- {0x10030, 0x00024017},
- {0x10030, 0x00024411},
- {0x10030, 0x000281A9},
- {0x10030, 0x000285A3},
- {0x10030, 0x0002899D},
- {0x10030, 0x00028D97},
- {0x10030, 0x0002915D},
- {0x10030, 0x00029557},
- {0x10030, 0x0002991F},
- {0x10030, 0x00029D19},
- {0x10030, 0x0002A0E1},
- {0x10030, 0x0002A4DB},
+ {0x10030, 0x00023C1B},
+ {0x10030, 0x00024015},
+ {0x10030, 0x0002440F},
+ {0x10030, 0x000281EF},
+ {0x10030, 0x000285E7},
+ {0x10030, 0x000289A7},
+ {0x10030, 0x00028D65},
+ {0x10030, 0x0002915F},
+ {0x10030, 0x00029523},
+ {0x10030, 0x0002991D},
+ {0x10030, 0x00029CE5},
+ {0x10030, 0x0002A0DF},
+ {0x10030, 0x0002A4A7},
{0x10030, 0x0002A8A1},
- {0x10030, 0x0002AC9B},
+ {0x10030, 0x0002AC67},
{0x10030, 0x0002B061},
- {0x10030, 0x0002B45B},
+ {0x10030, 0x0002B427},
{0x10030, 0x0002B821},
- {0x10030, 0x0002BC1B},
- {0x10030, 0x0002C015},
- {0x10030, 0x0002C40F},
- {0x10030, 0x000301A9},
- {0x10030, 0x000305A3},
- {0x10030, 0x0003099D},
- {0x10030, 0x00030D97},
- {0x10030, 0x0003115D},
- {0x10030, 0x00031557},
+ {0x10030, 0x0002BC19},
+ {0x10030, 0x0002C013},
+ {0x10030, 0x0002C40D},
+ {0x10030, 0x000301EF},
+ {0x10030, 0x000305E7},
+ {0x10030, 0x000309A7},
+ {0x10030, 0x00030D65},
+ {0x10030, 0x0003115F},
+ {0x10030, 0x00031525},
{0x10030, 0x0003191F},
- {0x10030, 0x00031D19},
+ {0x10030, 0x00031CE7},
{0x10030, 0x000320E1},
- {0x10030, 0x000324DB},
- {0x10030, 0x000328A1},
- {0x10030, 0x00032C9B},
- {0x10030, 0x00033061},
- {0x10030, 0x0003345B},
- {0x10030, 0x00033821},
- {0x10030, 0x00033C1B},
- {0x10030, 0x00034015},
- {0x10030, 0x0003440F},
+ {0x10030, 0x000324A9},
+ {0x10030, 0x000328A3},
+ {0x10030, 0x00032C69},
+ {0x10030, 0x00033063},
+ {0x10030, 0x00033429},
+ {0x10030, 0x00033823},
+ {0x10030, 0x00033C1D},
+ {0x10030, 0x00034013},
+ {0x10030, 0x0003440D},
{0x10030, 0x000601F1},
{0x10030, 0x000605E9},
{0x10030, 0x000609A9},
@@ -21331,7 +23639,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x00071523},
{0x10030, 0x0007191D},
{0x10030, 0x00071D17},
- {0x10030, 0x000720DF},
+ {0x10030, 0x00072111},
{0x10030, 0x000724D9},
{0x10030, 0x000728D3},
{0x10030, 0x00072C67},
@@ -21359,6 +23667,296 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x0007BC1D},
{0x10030, 0x0007C017},
{0x10030, 0x0007C40F},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x000001EF},
+ {0x10030, 0x000005E9},
+ {0x10030, 0x000009E3},
+ {0x10030, 0x00000DDD},
+ {0x10030, 0x000011D7},
+ {0x10030, 0x0000159F},
+ {0x10030, 0x00001999},
+ {0x10030, 0x00001D5F},
+ {0x10030, 0x00002159},
+ {0x10030, 0x0000251F},
+ {0x10030, 0x00002919},
+ {0x10030, 0x00002CDF},
+ {0x10030, 0x000030D9},
+ {0x10030, 0x0000349F},
+ {0x10030, 0x00003899},
+ {0x10030, 0x00003C5F},
+ {0x10030, 0x00004059},
+ {0x10030, 0x00004453},
+ {0x10030, 0x000201A7},
+ {0x10030, 0x000205A1},
+ {0x10030, 0x0002099B},
+ {0x10030, 0x00020D95},
+ {0x10030, 0x0002115B},
+ {0x10030, 0x00021555},
+ {0x10030, 0x00021921},
+ {0x10030, 0x00021D1B},
+ {0x10030, 0x000220E3},
+ {0x10030, 0x000224DD},
+ {0x10030, 0x000228A3},
+ {0x10030, 0x00022C9D},
+ {0x10030, 0x00023063},
+ {0x10030, 0x0002345D},
+ {0x10030, 0x00023823},
+ {0x10030, 0x00023C1D},
+ {0x10030, 0x00024017},
+ {0x10030, 0x00024411},
+ {0x10030, 0x000281A9},
+ {0x10030, 0x000285A3},
+ {0x10030, 0x0002899D},
+ {0x10030, 0x00028D97},
+ {0x10030, 0x0002915D},
+ {0x10030, 0x00029557},
+ {0x10030, 0x0002991F},
+ {0x10030, 0x00029D19},
+ {0x10030, 0x0002A0E1},
+ {0x10030, 0x0002A4DB},
+ {0x10030, 0x0002A8A1},
+ {0x10030, 0x0002AC9B},
+ {0x10030, 0x0002B061},
+ {0x10030, 0x0002B45B},
+ {0x10030, 0x0002B821},
+ {0x10030, 0x0002BC1B},
+ {0x10030, 0x0002C015},
+ {0x10030, 0x0002C40F},
+ {0x10030, 0x000301A9},
+ {0x10030, 0x000305A3},
+ {0x10030, 0x0003099D},
+ {0x10030, 0x00030D97},
+ {0x10030, 0x0003115D},
+ {0x10030, 0x00031557},
+ {0x10030, 0x0003191F},
+ {0x10030, 0x00031D19},
+ {0x10030, 0x000320E1},
+ {0x10030, 0x000324DB},
+ {0x10030, 0x000328A1},
+ {0x10030, 0x00032C9B},
+ {0x10030, 0x00033061},
+ {0x10030, 0x0003345B},
+ {0x10030, 0x00033821},
+ {0x10030, 0x00033C1B},
+ {0x10030, 0x00034015},
+ {0x10030, 0x0003440F},
+ {0x10030, 0x000601F1},
+ {0x10030, 0x000605E9},
+ {0x10030, 0x000609A9},
+ {0x10030, 0x00060D65},
+ {0x10030, 0x0006115F},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
+ {0x10030, 0x000681EF},
+ {0x10030, 0x000685E7},
+ {0x10030, 0x000689A7},
+ {0x10030, 0x00068D61},
+ {0x10030, 0x0006915B},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
+ {0x10030, 0x0006B429},
+ {0x10030, 0x0006B823},
+ {0x10030, 0x0006BC1D},
+ {0x10030, 0x0006C017},
+ {0x10030, 0x0006C411},
+ {0x10030, 0x000701EF},
+ {0x10030, 0x000705E9},
+ {0x10030, 0x000709A9},
+ {0x10030, 0x00070D63},
+ {0x10030, 0x0007115D},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
+ {0x10030, 0x000781EF},
+ {0x10030, 0x000785E9},
+ {0x10030, 0x000789E3},
+ {0x10030, 0x00078DA1},
+ {0x10030, 0x0007915F},
+ {0x10030, 0x00079559},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x000001EF},
+ {0x10030, 0x000005E9},
+ {0x10030, 0x000009E3},
+ {0x10030, 0x00000DDD},
+ {0x10030, 0x000011D7},
+ {0x10030, 0x0000159F},
+ {0x10030, 0x00001999},
+ {0x10030, 0x00001D5F},
+ {0x10030, 0x00002159},
+ {0x10030, 0x0000251F},
+ {0x10030, 0x00002919},
+ {0x10030, 0x00002CDF},
+ {0x10030, 0x000030D9},
+ {0x10030, 0x0000349F},
+ {0x10030, 0x00003899},
+ {0x10030, 0x00003C5F},
+ {0x10030, 0x00004059},
+ {0x10030, 0x00004453},
+ {0x10030, 0x000201A7},
+ {0x10030, 0x000205A1},
+ {0x10030, 0x0002099B},
+ {0x10030, 0x00020D95},
+ {0x10030, 0x0002115B},
+ {0x10030, 0x00021555},
+ {0x10030, 0x00021921},
+ {0x10030, 0x00021D1B},
+ {0x10030, 0x000220E3},
+ {0x10030, 0x000224DD},
+ {0x10030, 0x000228A3},
+ {0x10030, 0x00022C9D},
+ {0x10030, 0x00023063},
+ {0x10030, 0x0002345D},
+ {0x10030, 0x00023823},
+ {0x10030, 0x00023C1D},
+ {0x10030, 0x00024017},
+ {0x10030, 0x00024411},
+ {0x10030, 0x000281A9},
+ {0x10030, 0x000285A3},
+ {0x10030, 0x0002899D},
+ {0x10030, 0x00028D97},
+ {0x10030, 0x0002915D},
+ {0x10030, 0x00029557},
+ {0x10030, 0x0002991F},
+ {0x10030, 0x00029D19},
+ {0x10030, 0x0002A0E1},
+ {0x10030, 0x0002A4DB},
+ {0x10030, 0x0002A8A1},
+ {0x10030, 0x0002AC9B},
+ {0x10030, 0x0002B061},
+ {0x10030, 0x0002B45B},
+ {0x10030, 0x0002B821},
+ {0x10030, 0x0002BC1B},
+ {0x10030, 0x0002C015},
+ {0x10030, 0x0002C40F},
+ {0x10030, 0x000301A9},
+ {0x10030, 0x000305A3},
+ {0x10030, 0x0003099D},
+ {0x10030, 0x00030D97},
+ {0x10030, 0x0003115D},
+ {0x10030, 0x00031557},
+ {0x10030, 0x0003191F},
+ {0x10030, 0x00031D19},
+ {0x10030, 0x000320E1},
+ {0x10030, 0x000324DB},
+ {0x10030, 0x000328A1},
+ {0x10030, 0x00032C9B},
+ {0x10030, 0x00033061},
+ {0x10030, 0x0003345B},
+ {0x10030, 0x00033821},
+ {0x10030, 0x00033C1B},
+ {0x10030, 0x00034015},
+ {0x10030, 0x0003440F},
+ {0x10030, 0x000601F1},
+ {0x10030, 0x000605E9},
+ {0x10030, 0x000609A9},
+ {0x10030, 0x00060D65},
+ {0x10030, 0x0006115F},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
+ {0x10030, 0x000681EF},
+ {0x10030, 0x000685E7},
+ {0x10030, 0x000689A7},
+ {0x10030, 0x00068D61},
+ {0x10030, 0x0006915B},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
+ {0x10030, 0x0006B429},
+ {0x10030, 0x0006B823},
+ {0x10030, 0x0006BC1D},
+ {0x10030, 0x0006C017},
+ {0x10030, 0x0006C411},
+ {0x10030, 0x000701EF},
+ {0x10030, 0x000705E9},
+ {0x10030, 0x000709A9},
+ {0x10030, 0x00070D63},
+ {0x10030, 0x0007115D},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
+ {0x10030, 0x000781EF},
+ {0x10030, 0x000785E9},
+ {0x10030, 0x000789E3},
+ {0x10030, 0x00078DA1},
+ {0x10030, 0x0007915F},
+ {0x10030, 0x00079559},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -21437,73 +24035,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x000609A9},
{0x10030, 0x00060D65},
{0x10030, 0x0006115F},
- {0x10030, 0x00061525},
- {0x10030, 0x0006191F},
- {0x10030, 0x00061CE7},
- {0x10030, 0x000620E1},
- {0x10030, 0x000624DB},
- {0x10030, 0x000628A3},
- {0x10030, 0x00062C69},
- {0x10030, 0x00063063},
- {0x10030, 0x00063429},
- {0x10030, 0x00063823},
- {0x10030, 0x00063C1D},
- {0x10030, 0x00064013},
- {0x10030, 0x0006440D},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
{0x10030, 0x000681EF},
{0x10030, 0x000685E7},
{0x10030, 0x000689A7},
{0x10030, 0x00068D61},
{0x10030, 0x0006915B},
- {0x10030, 0x00069523},
- {0x10030, 0x0006991D},
- {0x10030, 0x00069CE5},
- {0x10030, 0x0006A0DF},
- {0x10030, 0x0006A4A7},
- {0x10030, 0x0006A8A1},
- {0x10030, 0x0006AC67},
- {0x10030, 0x0006B061},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
{0x10030, 0x0006B429},
{0x10030, 0x0006B823},
{0x10030, 0x0006BC1D},
{0x10030, 0x0006C017},
- {0x10030, 0x0006C40D},
- {0x10030, 0x000701F1},
+ {0x10030, 0x0006C411},
+ {0x10030, 0x000701EF},
{0x10030, 0x000705E9},
{0x10030, 0x000709A9},
{0x10030, 0x00070D63},
{0x10030, 0x0007115D},
- {0x10030, 0x00071523},
- {0x10030, 0x0007191D},
- {0x10030, 0x00071D17},
- {0x10030, 0x000720DF},
- {0x10030, 0x000724D9},
- {0x10030, 0x000728D3},
- {0x10030, 0x00072C67},
- {0x10030, 0x00073061},
- {0x10030, 0x00073427},
- {0x10030, 0x00073821},
- {0x10030, 0x00073C1B},
- {0x10030, 0x00074015},
- {0x10030, 0x0007440D},
- {0x10030, 0x000781F1},
- {0x10030, 0x000785EB},
- {0x10030, 0x000789E5},
- {0x10030, 0x00078DA3},
- {0x10030, 0x00079161},
- {0x10030, 0x0007955B},
- {0x10030, 0x00079923},
- {0x10030, 0x00079D1D},
- {0x10030, 0x0007A117},
- {0x10030, 0x0007A4DD},
- {0x10030, 0x0007A8D7},
- {0x10030, 0x0007AC9D},
- {0x10030, 0x0007B063},
- {0x10030, 0x0007B45D},
- {0x10030, 0x0007B857},
- {0x10030, 0x0007BC1D},
- {0x10030, 0x0007C017},
- {0x10030, 0x0007C40F},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
+ {0x10030, 0x000781EF},
+ {0x10030, 0x000785E9},
+ {0x10030, 0x000789E3},
+ {0x10030, 0x00078DA1},
+ {0x10030, 0x0007915F},
+ {0x10030, 0x00079559},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -21582,73 +24180,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x000609A9},
{0x10030, 0x00060D65},
{0x10030, 0x0006115F},
- {0x10030, 0x00061525},
- {0x10030, 0x0006191F},
- {0x10030, 0x00061CE7},
- {0x10030, 0x000620E1},
- {0x10030, 0x000624DB},
- {0x10030, 0x000628A3},
- {0x10030, 0x00062C69},
- {0x10030, 0x00063063},
- {0x10030, 0x00063429},
- {0x10030, 0x00063823},
- {0x10030, 0x00063C1D},
- {0x10030, 0x00064013},
- {0x10030, 0x0006440D},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
{0x10030, 0x000681EF},
{0x10030, 0x000685E7},
{0x10030, 0x000689A7},
{0x10030, 0x00068D61},
{0x10030, 0x0006915B},
- {0x10030, 0x00069523},
- {0x10030, 0x0006991D},
- {0x10030, 0x00069CE5},
- {0x10030, 0x0006A0DF},
- {0x10030, 0x0006A4A7},
- {0x10030, 0x0006A8A1},
- {0x10030, 0x0006AC67},
- {0x10030, 0x0006B061},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
{0x10030, 0x0006B429},
{0x10030, 0x0006B823},
{0x10030, 0x0006BC1D},
{0x10030, 0x0006C017},
- {0x10030, 0x0006C40D},
- {0x10030, 0x000701F1},
+ {0x10030, 0x0006C411},
+ {0x10030, 0x000701EF},
{0x10030, 0x000705E9},
{0x10030, 0x000709A9},
{0x10030, 0x00070D63},
{0x10030, 0x0007115D},
- {0x10030, 0x00071523},
- {0x10030, 0x0007191D},
- {0x10030, 0x00071D17},
- {0x10030, 0x000720DF},
- {0x10030, 0x000724D9},
- {0x10030, 0x000728D3},
- {0x10030, 0x00072C67},
- {0x10030, 0x00073061},
- {0x10030, 0x00073427},
- {0x10030, 0x00073821},
- {0x10030, 0x00073C1B},
- {0x10030, 0x00074015},
- {0x10030, 0x0007440D},
- {0x10030, 0x000781F1},
- {0x10030, 0x000785EB},
- {0x10030, 0x000789E5},
- {0x10030, 0x00078DA3},
- {0x10030, 0x00079161},
- {0x10030, 0x0007955B},
- {0x10030, 0x00079923},
- {0x10030, 0x00079D1D},
- {0x10030, 0x0007A117},
- {0x10030, 0x0007A4DD},
- {0x10030, 0x0007A8D7},
- {0x10030, 0x0007AC9D},
- {0x10030, 0x0007B063},
- {0x10030, 0x0007B45D},
- {0x10030, 0x0007B857},
- {0x10030, 0x0007BC1D},
- {0x10030, 0x0007C017},
- {0x10030, 0x0007C40F},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
+ {0x10030, 0x000781EF},
+ {0x10030, 0x000785E9},
+ {0x10030, 0x000789E3},
+ {0x10030, 0x00078DA1},
+ {0x10030, 0x0007915F},
+ {0x10030, 0x00079559},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -21727,73 +24325,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x000609A9},
{0x10030, 0x00060D65},
{0x10030, 0x0006115F},
- {0x10030, 0x00061525},
- {0x10030, 0x0006191F},
- {0x10030, 0x00061CE7},
- {0x10030, 0x000620E1},
- {0x10030, 0x000624DB},
- {0x10030, 0x000628A3},
- {0x10030, 0x00062C69},
- {0x10030, 0x00063063},
- {0x10030, 0x00063429},
- {0x10030, 0x00063823},
- {0x10030, 0x00063C1D},
- {0x10030, 0x00064013},
- {0x10030, 0x0006440D},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
{0x10030, 0x000681EF},
{0x10030, 0x000685E7},
{0x10030, 0x000689A7},
{0x10030, 0x00068D61},
{0x10030, 0x0006915B},
- {0x10030, 0x00069523},
- {0x10030, 0x0006991D},
- {0x10030, 0x00069CE5},
- {0x10030, 0x0006A0DF},
- {0x10030, 0x0006A4A7},
- {0x10030, 0x0006A8A1},
- {0x10030, 0x0006AC67},
- {0x10030, 0x0006B061},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
{0x10030, 0x0006B429},
{0x10030, 0x0006B823},
{0x10030, 0x0006BC1D},
{0x10030, 0x0006C017},
- {0x10030, 0x0006C40D},
- {0x10030, 0x000701F1},
+ {0x10030, 0x0006C411},
+ {0x10030, 0x000701EF},
{0x10030, 0x000705E9},
{0x10030, 0x000709A9},
{0x10030, 0x00070D63},
{0x10030, 0x0007115D},
- {0x10030, 0x00071523},
- {0x10030, 0x0007191D},
- {0x10030, 0x00071D17},
- {0x10030, 0x000720DF},
- {0x10030, 0x000724D9},
- {0x10030, 0x000728D3},
- {0x10030, 0x00072C67},
- {0x10030, 0x00073061},
- {0x10030, 0x00073427},
- {0x10030, 0x00073821},
- {0x10030, 0x00073C1B},
- {0x10030, 0x00074015},
- {0x10030, 0x0007440D},
- {0x10030, 0x000781F1},
- {0x10030, 0x000785EB},
- {0x10030, 0x000789E5},
- {0x10030, 0x00078DA3},
- {0x10030, 0x00079161},
- {0x10030, 0x0007955B},
- {0x10030, 0x00079923},
- {0x10030, 0x00079D1D},
- {0x10030, 0x0007A117},
- {0x10030, 0x0007A4DD},
- {0x10030, 0x0007A8D7},
- {0x10030, 0x0007AC9D},
- {0x10030, 0x0007B063},
- {0x10030, 0x0007B45D},
- {0x10030, 0x0007B857},
- {0x10030, 0x0007BC1D},
- {0x10030, 0x0007C017},
- {0x10030, 0x0007C40F},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
+ {0x10030, 0x000781EF},
+ {0x10030, 0x000785E9},
+ {0x10030, 0x000789E3},
+ {0x10030, 0x00078DA1},
+ {0x10030, 0x0007915F},
+ {0x10030, 0x00079559},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -21872,73 +24470,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x000609A9},
{0x10030, 0x00060D65},
{0x10030, 0x0006115F},
- {0x10030, 0x00061525},
- {0x10030, 0x0006191F},
- {0x10030, 0x00061CE7},
- {0x10030, 0x000620E1},
- {0x10030, 0x000624DB},
- {0x10030, 0x000628A3},
- {0x10030, 0x00062C69},
- {0x10030, 0x00063063},
- {0x10030, 0x00063429},
- {0x10030, 0x00063823},
- {0x10030, 0x00063C1D},
- {0x10030, 0x00064013},
- {0x10030, 0x0006440D},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
{0x10030, 0x000681EF},
{0x10030, 0x000685E7},
{0x10030, 0x000689A7},
{0x10030, 0x00068D61},
{0x10030, 0x0006915B},
- {0x10030, 0x00069523},
- {0x10030, 0x0006991D},
- {0x10030, 0x00069CE5},
- {0x10030, 0x0006A0DF},
- {0x10030, 0x0006A4A7},
- {0x10030, 0x0006A8A1},
- {0x10030, 0x0006AC67},
- {0x10030, 0x0006B061},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
{0x10030, 0x0006B429},
{0x10030, 0x0006B823},
{0x10030, 0x0006BC1D},
{0x10030, 0x0006C017},
- {0x10030, 0x0006C40D},
- {0x10030, 0x000701F1},
+ {0x10030, 0x0006C411},
+ {0x10030, 0x000701EF},
{0x10030, 0x000705E9},
{0x10030, 0x000709A9},
{0x10030, 0x00070D63},
{0x10030, 0x0007115D},
- {0x10030, 0x00071523},
- {0x10030, 0x0007191D},
- {0x10030, 0x00071D17},
- {0x10030, 0x000720DF},
- {0x10030, 0x000724D9},
- {0x10030, 0x000728D3},
- {0x10030, 0x00072C67},
- {0x10030, 0x00073061},
- {0x10030, 0x00073427},
- {0x10030, 0x00073821},
- {0x10030, 0x00073C1B},
- {0x10030, 0x00074015},
- {0x10030, 0x0007440D},
- {0x10030, 0x000781F1},
- {0x10030, 0x000785EB},
- {0x10030, 0x000789E5},
- {0x10030, 0x00078DA3},
- {0x10030, 0x00079161},
- {0x10030, 0x0007955B},
- {0x10030, 0x00079923},
- {0x10030, 0x00079D1D},
- {0x10030, 0x0007A117},
- {0x10030, 0x0007A4DD},
- {0x10030, 0x0007A8D7},
- {0x10030, 0x0007AC9D},
- {0x10030, 0x0007B063},
- {0x10030, 0x0007B45D},
- {0x10030, 0x0007B857},
- {0x10030, 0x0007BC1D},
- {0x10030, 0x0007C017},
- {0x10030, 0x0007C40F},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
+ {0x10030, 0x000781EF},
+ {0x10030, 0x000785E9},
+ {0x10030, 0x000789E3},
+ {0x10030, 0x00078DA1},
+ {0x10030, 0x0007915F},
+ {0x10030, 0x00079559},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0xA0000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -22782,6 +25380,110 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x000338CC},
{0x10030, 0x00033C09},
{0x10030, 0x00034006},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x000200E8},
+ {0x10030, 0x000204E5},
+ {0x10030, 0x000208E2},
+ {0x10030, 0x00020CDF},
+ {0x10030, 0x000210DC},
+ {0x10030, 0x000214D9},
+ {0x10030, 0x000218D6},
+ {0x10030, 0x00021CD3},
+ {0x10030, 0x000220D0},
+ {0x10030, 0x0002240D},
+ {0x10030, 0x0002280A},
+ {0x10030, 0x00022C07},
+ {0x10030, 0x00023004},
+ {0x10030, 0x00023401},
+ {0x10030, 0x00023800},
+ {0x10030, 0x00023C00},
+ {0x10030, 0x00024000},
+ {0x10030, 0x000280E7},
+ {0x10030, 0x000284E4},
+ {0x10030, 0x000288E1},
+ {0x10030, 0x00028CDE},
+ {0x10030, 0x000290DB},
+ {0x10030, 0x000294D8},
+ {0x10030, 0x000298D5},
+ {0x10030, 0x00029CD2},
+ {0x10030, 0x0002A0CF},
+ {0x10030, 0x0002A40C},
+ {0x10030, 0x0002A809},
+ {0x10030, 0x0002AC06},
+ {0x10030, 0x0002B003},
+ {0x10030, 0x0002B400},
+ {0x10030, 0x0002B800},
+ {0x10030, 0x0002BC00},
+ {0x10030, 0x0002C000},
+ {0x10030, 0x000300E7},
+ {0x10030, 0x000304E4},
+ {0x10030, 0x000308E1},
+ {0x10030, 0x00030CDE},
+ {0x10030, 0x000310DB},
+ {0x10030, 0x000314D8},
+ {0x10030, 0x000318D5},
+ {0x10030, 0x00031CD2},
+ {0x10030, 0x000320CF},
+ {0x10030, 0x000324CC},
+ {0x10030, 0x00032809},
+ {0x10030, 0x00032C06},
+ {0x10030, 0x00033003},
+ {0x10030, 0x00033400},
+ {0x10030, 0x00033800},
+ {0x10030, 0x00033C00},
+ {0x10030, 0x00034000},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x000200E8},
+ {0x10030, 0x000204E5},
+ {0x10030, 0x000208E2},
+ {0x10030, 0x00020CDF},
+ {0x10030, 0x000210DC},
+ {0x10030, 0x000214D9},
+ {0x10030, 0x000218D6},
+ {0x10030, 0x00021CD3},
+ {0x10030, 0x000220D0},
+ {0x10030, 0x0002240D},
+ {0x10030, 0x0002280A},
+ {0x10030, 0x00022C07},
+ {0x10030, 0x00023004},
+ {0x10030, 0x00023401},
+ {0x10030, 0x00023800},
+ {0x10030, 0x00023C00},
+ {0x10030, 0x00024000},
+ {0x10030, 0x000280E7},
+ {0x10030, 0x000284E4},
+ {0x10030, 0x000288E1},
+ {0x10030, 0x00028CDE},
+ {0x10030, 0x000290DB},
+ {0x10030, 0x000294D8},
+ {0x10030, 0x000298D5},
+ {0x10030, 0x00029CD2},
+ {0x10030, 0x0002A0CF},
+ {0x10030, 0x0002A40C},
+ {0x10030, 0x0002A809},
+ {0x10030, 0x0002AC06},
+ {0x10030, 0x0002B003},
+ {0x10030, 0x0002B400},
+ {0x10030, 0x0002B800},
+ {0x10030, 0x0002BC00},
+ {0x10030, 0x0002C000},
+ {0x10030, 0x000300E7},
+ {0x10030, 0x000304E4},
+ {0x10030, 0x000308E1},
+ {0x10030, 0x00030CDE},
+ {0x10030, 0x000310DB},
+ {0x10030, 0x000314D8},
+ {0x10030, 0x000318D5},
+ {0x10030, 0x00031CD2},
+ {0x10030, 0x000320CF},
+ {0x10030, 0x000324CC},
+ {0x10030, 0x00032809},
+ {0x10030, 0x00032C06},
+ {0x10030, 0x00033003},
+ {0x10030, 0x00033400},
+ {0x10030, 0x00033800},
+ {0x10030, 0x00033C00},
+ {0x10030, 0x00034000},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000200FA},
{0x10030, 0x000204F7},
@@ -23329,6 +26031,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23373,6 +26079,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23429,6 +26139,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23473,6 +26187,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23529,6 +26247,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23573,6 +26295,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23629,6 +26355,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23673,6 +26403,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23729,6 +26463,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23773,6 +26511,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23829,6 +26571,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23873,6 +26619,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23929,6 +26679,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23973,6 +26727,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24029,6 +26787,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24073,6 +26835,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24129,6 +26895,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24173,6 +26943,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24229,6 +27003,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24273,6 +27051,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24329,6 +27111,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24373,6 +27159,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24429,6 +27219,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24473,6 +27267,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24529,6 +27327,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24573,6 +27375,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24629,6 +27435,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24673,6 +27483,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24729,6 +27543,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24773,6 +27591,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24829,6 +27651,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24873,6 +27699,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24929,6 +27759,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24973,6 +27807,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25029,6 +27867,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25073,6 +27915,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25129,6 +27975,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25173,6 +28023,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25229,6 +28083,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25273,6 +28131,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25329,6 +28191,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25373,6 +28239,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25429,6 +28299,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25473,6 +28347,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25529,6 +28407,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25573,6 +28455,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25629,6 +28515,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25673,6 +28563,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25729,6 +28623,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25773,6 +28671,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25829,6 +28731,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25873,6 +28779,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25929,6 +28839,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25973,6 +28887,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -26029,6 +28947,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -26073,6 +28995,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -26157,6 +29083,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x00025003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00025003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00025003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00025003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00025003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -26207,6 +29137,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x0002D003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0002D003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0002D003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0002D003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0002D003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -26257,6 +29191,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x00035003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00035003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00035003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00035003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00035003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -26307,6 +29245,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x0003D003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0003D003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0003D003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0003D003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0003D003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -26370,6 +29312,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00065003},
{0x10030, 0x00066003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00065003},
+ {0x10030, 0x00066003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00065003},
+ {0x10030, 0x00066003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00065003},
{0x10030, 0x00066003},
@@ -26440,6 +29388,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0006D003},
{0x10030, 0x0006E003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0006D003},
+ {0x10030, 0x0006E003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0006D003},
+ {0x10030, 0x0006E003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0006D003},
{0x10030, 0x0006E003},
@@ -26510,6 +29464,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00075003},
{0x10030, 0x00076003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00075003},
+ {0x10030, 0x00076003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00075003},
+ {0x10030, 0x00076003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00075003},
{0x10030, 0x00076003},
@@ -26580,6 +29540,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0007D003},
{0x10030, 0x0007E003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0007D003},
+ {0x10030, 0x0007E003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0007D003},
+ {0x10030, 0x0007E003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0007D003},
{0x10030, 0x0007E003},
@@ -26621,7 +29587,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000000A},
{0x0ED, 0x00000000},
{0x100EE, 0x00000000},
- {0x0FE, 0x00000048},
+ {0x0FE, 0x00000063},
};
static const struct rtw89_reg2_def rtw89_8852c_phy_nctl_regs[] = {
@@ -28430,11 +31396,11 @@ static const struct rtw89_txpwr_byrate_cfg rtw89_8852c_txpwr_byrate[] = {
{ 2, 0, 1, 4, 4, 0x383c4040, },
{ 2, 0, 2, 0, 4, 0x40404040, },
{ 2, 0, 2, 4, 4, 0x34383c40, },
- { 2, 0, 2, 8, 4, 0x24282c30, },
+ { 2, 0, 2, 8, 4, 0x20282c30, },
{ 2, 0, 3, 0, 4, 0x40404040, },
{ 2, 1, 2, 0, 4, 0x40404040, },
{ 2, 1, 2, 4, 4, 0x34383c40, },
- { 2, 1, 2, 8, 4, 0x24282c30, },
+ { 2, 1, 2, 8, 4, 0x20282c30, },
{ 2, 1, 3, 0, 4, 0x40404040, },
{ 2, 0, 4, 0, 4, 0x00000000, },
};
@@ -28559,35 +31525,53 @@ static const s8 _txpwr_track_delta_swingidx_2g_cck_a_p[] = {
3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5
};
-const u8 rtw89_8852c_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
+const u8 rtw89_8852c_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM]
[RTW89_REGD_NUM] = {
[0][0][RTW89_ACMA] = 0,
+ [0][0][RTW89_CHILE] = 0,
[0][0][RTW89_CN] = 0,
[0][0][RTW89_ETSI] = 0,
[0][0][RTW89_FCC] = 1,
[0][0][RTW89_IC] = 1,
[0][0][RTW89_KCC] = 0,
+ [0][0][RTW89_MEXICO] = 1,
[0][0][RTW89_MKK] = 0,
+ [0][0][RTW89_QATAR] = 0,
[0][0][RTW89_UK] = 0,
+ [0][0][RTW89_UKRAINE] = 0,
[0][1][RTW89_ACMA] = 0,
+ [0][1][RTW89_CHILE] = 0,
[0][1][RTW89_CN] = 0,
[0][1][RTW89_ETSI] = 0,
[0][1][RTW89_FCC] = 3,
[0][1][RTW89_IC] = 3,
[0][1][RTW89_KCC] = 0,
+ [0][1][RTW89_MEXICO] = 3,
[0][1][RTW89_MKK] = 0,
+ [0][1][RTW89_QATAR] = 0,
[0][1][RTW89_UK] = 0,
+ [0][1][RTW89_UKRAINE] = 0,
[1][1][RTW89_ACMA] = 0,
+ [1][1][RTW89_CHILE] = 0,
[1][1][RTW89_CN] = 0,
[1][1][RTW89_ETSI] = 0,
[1][1][RTW89_FCC] = 3,
[1][1][RTW89_IC] = 3,
[1][1][RTW89_KCC] = 0,
+ [1][1][RTW89_MEXICO] = 3,
[1][1][RTW89_MKK] = 0,
+ [1][1][RTW89_QATAR] = 0,
[1][1][RTW89_UK] = 0,
+ [1][1][RTW89_UKRAINE] = 0,
+ [2][1][RTW89_ACMA] = 0,
+ [2][1][RTW89_CHILE] = 0,
[2][1][RTW89_ETSI] = 0,
[2][1][RTW89_FCC] = 0,
+ [2][1][RTW89_IC] = 0,
[2][1][RTW89_KCC] = 0,
+ [2][1][RTW89_MKK] = 0,
+ [2][1][RTW89_QATAR] = 0,
+ [2][1][RTW89_UK] = 0,
};
static
@@ -28770,6 +31754,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][0] = 60,
[0][0][0][0][RTW89_CN][0] = 58,
[0][0][0][0][RTW89_UK][0] = 60,
+ [0][0][0][0][RTW89_MEXICO][0] = 76,
+ [0][0][0][0][RTW89_UKRAINE][0] = 60,
+ [0][0][0][0][RTW89_CHILE][0] = 76,
+ [0][0][0][0][RTW89_QATAR][0] = 60,
[0][0][0][0][RTW89_FCC][1] = 76,
[0][0][0][0][RTW89_ETSI][1] = 60,
[0][0][0][0][RTW89_MKK][1] = 68,
@@ -28778,6 +31766,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][1] = 60,
[0][0][0][0][RTW89_CN][1] = 58,
[0][0][0][0][RTW89_UK][1] = 60,
+ [0][0][0][0][RTW89_MEXICO][1] = 76,
+ [0][0][0][0][RTW89_UKRAINE][1] = 60,
+ [0][0][0][0][RTW89_CHILE][1] = 68,
+ [0][0][0][0][RTW89_QATAR][1] = 60,
[0][0][0][0][RTW89_FCC][2] = 76,
[0][0][0][0][RTW89_ETSI][2] = 60,
[0][0][0][0][RTW89_MKK][2] = 68,
@@ -28786,6 +31778,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][2] = 60,
[0][0][0][0][RTW89_CN][2] = 58,
[0][0][0][0][RTW89_UK][2] = 60,
+ [0][0][0][0][RTW89_MEXICO][2] = 76,
+ [0][0][0][0][RTW89_UKRAINE][2] = 60,
+ [0][0][0][0][RTW89_CHILE][2] = 68,
+ [0][0][0][0][RTW89_QATAR][2] = 60,
[0][0][0][0][RTW89_FCC][3] = 76,
[0][0][0][0][RTW89_ETSI][3] = 60,
[0][0][0][0][RTW89_MKK][3] = 68,
@@ -28794,6 +31790,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][3] = 60,
[0][0][0][0][RTW89_CN][3] = 58,
[0][0][0][0][RTW89_UK][3] = 60,
+ [0][0][0][0][RTW89_MEXICO][3] = 76,
+ [0][0][0][0][RTW89_UKRAINE][3] = 60,
+ [0][0][0][0][RTW89_CHILE][3] = 68,
+ [0][0][0][0][RTW89_QATAR][3] = 60,
[0][0][0][0][RTW89_FCC][4] = 76,
[0][0][0][0][RTW89_ETSI][4] = 60,
[0][0][0][0][RTW89_MKK][4] = 68,
@@ -28802,6 +31802,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][4] = 60,
[0][0][0][0][RTW89_CN][4] = 58,
[0][0][0][0][RTW89_UK][4] = 60,
+ [0][0][0][0][RTW89_MEXICO][4] = 76,
+ [0][0][0][0][RTW89_UKRAINE][4] = 60,
+ [0][0][0][0][RTW89_CHILE][4] = 68,
+ [0][0][0][0][RTW89_QATAR][4] = 60,
[0][0][0][0][RTW89_FCC][5] = 76,
[0][0][0][0][RTW89_ETSI][5] = 60,
[0][0][0][0][RTW89_MKK][5] = 68,
@@ -28810,6 +31814,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][5] = 60,
[0][0][0][0][RTW89_CN][5] = 58,
[0][0][0][0][RTW89_UK][5] = 60,
+ [0][0][0][0][RTW89_MEXICO][5] = 76,
+ [0][0][0][0][RTW89_UKRAINE][5] = 60,
+ [0][0][0][0][RTW89_CHILE][5] = 76,
+ [0][0][0][0][RTW89_QATAR][5] = 60,
[0][0][0][0][RTW89_FCC][6] = 76,
[0][0][0][0][RTW89_ETSI][6] = 60,
[0][0][0][0][RTW89_MKK][6] = 68,
@@ -28818,6 +31826,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][6] = 60,
[0][0][0][0][RTW89_CN][6] = 58,
[0][0][0][0][RTW89_UK][6] = 60,
+ [0][0][0][0][RTW89_MEXICO][6] = 76,
+ [0][0][0][0][RTW89_UKRAINE][6] = 60,
+ [0][0][0][0][RTW89_CHILE][6] = 76,
+ [0][0][0][0][RTW89_QATAR][6] = 60,
[0][0][0][0][RTW89_FCC][7] = 76,
[0][0][0][0][RTW89_ETSI][7] = 60,
[0][0][0][0][RTW89_MKK][7] = 68,
@@ -28826,6 +31838,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][7] = 60,
[0][0][0][0][RTW89_CN][7] = 58,
[0][0][0][0][RTW89_UK][7] = 60,
+ [0][0][0][0][RTW89_MEXICO][7] = 76,
+ [0][0][0][0][RTW89_UKRAINE][7] = 60,
+ [0][0][0][0][RTW89_CHILE][7] = 76,
+ [0][0][0][0][RTW89_QATAR][7] = 60,
[0][0][0][0][RTW89_FCC][8] = 76,
[0][0][0][0][RTW89_ETSI][8] = 60,
[0][0][0][0][RTW89_MKK][8] = 68,
@@ -28834,6 +31850,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][8] = 60,
[0][0][0][0][RTW89_CN][8] = 58,
[0][0][0][0][RTW89_UK][8] = 60,
+ [0][0][0][0][RTW89_MEXICO][8] = 76,
+ [0][0][0][0][RTW89_UKRAINE][8] = 60,
+ [0][0][0][0][RTW89_CHILE][8] = 76,
+ [0][0][0][0][RTW89_QATAR][8] = 60,
[0][0][0][0][RTW89_FCC][9] = 76,
[0][0][0][0][RTW89_ETSI][9] = 60,
[0][0][0][0][RTW89_MKK][9] = 68,
@@ -28842,6 +31862,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][9] = 60,
[0][0][0][0][RTW89_CN][9] = 58,
[0][0][0][0][RTW89_UK][9] = 60,
+ [0][0][0][0][RTW89_MEXICO][9] = 76,
+ [0][0][0][0][RTW89_UKRAINE][9] = 60,
+ [0][0][0][0][RTW89_CHILE][9] = 76,
+ [0][0][0][0][RTW89_QATAR][9] = 60,
[0][0][0][0][RTW89_FCC][10] = 76,
[0][0][0][0][RTW89_ETSI][10] = 60,
[0][0][0][0][RTW89_MKK][10] = 68,
@@ -28850,6 +31874,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][10] = 60,
[0][0][0][0][RTW89_CN][10] = 58,
[0][0][0][0][RTW89_UK][10] = 60,
+ [0][0][0][0][RTW89_MEXICO][10] = 76,
+ [0][0][0][0][RTW89_UKRAINE][10] = 60,
+ [0][0][0][0][RTW89_CHILE][10] = 76,
+ [0][0][0][0][RTW89_QATAR][10] = 60,
[0][0][0][0][RTW89_FCC][11] = 58,
[0][0][0][0][RTW89_ETSI][11] = 60,
[0][0][0][0][RTW89_MKK][11] = 68,
@@ -28858,6 +31886,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][11] = 60,
[0][0][0][0][RTW89_CN][11] = 58,
[0][0][0][0][RTW89_UK][11] = 60,
+ [0][0][0][0][RTW89_MEXICO][11] = 58,
+ [0][0][0][0][RTW89_UKRAINE][11] = 60,
+ [0][0][0][0][RTW89_CHILE][11] = 58,
+ [0][0][0][0][RTW89_QATAR][11] = 60,
[0][0][0][0][RTW89_FCC][12] = 46,
[0][0][0][0][RTW89_ETSI][12] = 60,
[0][0][0][0][RTW89_MKK][12] = 68,
@@ -28866,6 +31898,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][12] = 60,
[0][0][0][0][RTW89_CN][12] = 58,
[0][0][0][0][RTW89_UK][12] = 60,
+ [0][0][0][0][RTW89_MEXICO][12] = 46,
+ [0][0][0][0][RTW89_UKRAINE][12] = 60,
+ [0][0][0][0][RTW89_CHILE][12] = 46,
+ [0][0][0][0][RTW89_QATAR][12] = 60,
[0][0][0][0][RTW89_FCC][13] = 127,
[0][0][0][0][RTW89_ETSI][13] = 127,
[0][0][0][0][RTW89_MKK][13] = 72,
@@ -28874,6 +31910,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][13] = 127,
[0][0][0][0][RTW89_CN][13] = 127,
[0][0][0][0][RTW89_UK][13] = 127,
+ [0][0][0][0][RTW89_MEXICO][13] = 127,
+ [0][0][0][0][RTW89_UKRAINE][13] = 127,
+ [0][0][0][0][RTW89_CHILE][13] = 127,
+ [0][0][0][0][RTW89_QATAR][13] = 127,
[0][1][0][0][RTW89_FCC][0] = 76,
[0][1][0][0][RTW89_ETSI][0] = 48,
[0][1][0][0][RTW89_MKK][0] = 58,
@@ -28882,6 +31922,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][0] = 48,
[0][1][0][0][RTW89_CN][0] = 42,
[0][1][0][0][RTW89_UK][0] = 48,
+ [0][1][0][0][RTW89_MEXICO][0] = 76,
+ [0][1][0][0][RTW89_UKRAINE][0] = 48,
+ [0][1][0][0][RTW89_CHILE][0] = 76,
+ [0][1][0][0][RTW89_QATAR][0] = 48,
[0][1][0][0][RTW89_FCC][1] = 76,
[0][1][0][0][RTW89_ETSI][1] = 48,
[0][1][0][0][RTW89_MKK][1] = 58,
@@ -28890,6 +31934,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][1] = 48,
[0][1][0][0][RTW89_CN][1] = 42,
[0][1][0][0][RTW89_UK][1] = 48,
+ [0][1][0][0][RTW89_MEXICO][1] = 76,
+ [0][1][0][0][RTW89_UKRAINE][1] = 48,
+ [0][1][0][0][RTW89_CHILE][1] = 54,
+ [0][1][0][0][RTW89_QATAR][1] = 48,
[0][1][0][0][RTW89_FCC][2] = 76,
[0][1][0][0][RTW89_ETSI][2] = 48,
[0][1][0][0][RTW89_MKK][2] = 58,
@@ -28898,6 +31946,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][2] = 48,
[0][1][0][0][RTW89_CN][2] = 42,
[0][1][0][0][RTW89_UK][2] = 48,
+ [0][1][0][0][RTW89_MEXICO][2] = 76,
+ [0][1][0][0][RTW89_UKRAINE][2] = 48,
+ [0][1][0][0][RTW89_CHILE][2] = 54,
+ [0][1][0][0][RTW89_QATAR][2] = 48,
[0][1][0][0][RTW89_FCC][3] = 76,
[0][1][0][0][RTW89_ETSI][3] = 48,
[0][1][0][0][RTW89_MKK][3] = 58,
@@ -28906,6 +31958,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][3] = 48,
[0][1][0][0][RTW89_CN][3] = 42,
[0][1][0][0][RTW89_UK][3] = 48,
+ [0][1][0][0][RTW89_MEXICO][3] = 76,
+ [0][1][0][0][RTW89_UKRAINE][3] = 48,
+ [0][1][0][0][RTW89_CHILE][3] = 54,
+ [0][1][0][0][RTW89_QATAR][3] = 48,
[0][1][0][0][RTW89_FCC][4] = 76,
[0][1][0][0][RTW89_ETSI][4] = 48,
[0][1][0][0][RTW89_MKK][4] = 58,
@@ -28914,6 +31970,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][4] = 48,
[0][1][0][0][RTW89_CN][4] = 42,
[0][1][0][0][RTW89_UK][4] = 48,
+ [0][1][0][0][RTW89_MEXICO][4] = 76,
+ [0][1][0][0][RTW89_UKRAINE][4] = 48,
+ [0][1][0][0][RTW89_CHILE][4] = 54,
+ [0][1][0][0][RTW89_QATAR][4] = 48,
[0][1][0][0][RTW89_FCC][5] = 76,
[0][1][0][0][RTW89_ETSI][5] = 48,
[0][1][0][0][RTW89_MKK][5] = 58,
@@ -28922,6 +31982,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][5] = 48,
[0][1][0][0][RTW89_CN][5] = 42,
[0][1][0][0][RTW89_UK][5] = 48,
+ [0][1][0][0][RTW89_MEXICO][5] = 76,
+ [0][1][0][0][RTW89_UKRAINE][5] = 48,
+ [0][1][0][0][RTW89_CHILE][5] = 76,
+ [0][1][0][0][RTW89_QATAR][5] = 48,
[0][1][0][0][RTW89_FCC][6] = 76,
[0][1][0][0][RTW89_ETSI][6] = 48,
[0][1][0][0][RTW89_MKK][6] = 58,
@@ -28930,6 +31994,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][6] = 48,
[0][1][0][0][RTW89_CN][6] = 42,
[0][1][0][0][RTW89_UK][6] = 48,
+ [0][1][0][0][RTW89_MEXICO][6] = 76,
+ [0][1][0][0][RTW89_UKRAINE][6] = 48,
+ [0][1][0][0][RTW89_CHILE][6] = 76,
+ [0][1][0][0][RTW89_QATAR][6] = 48,
[0][1][0][0][RTW89_FCC][7] = 76,
[0][1][0][0][RTW89_ETSI][7] = 48,
[0][1][0][0][RTW89_MKK][7] = 58,
@@ -28938,6 +32006,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][7] = 48,
[0][1][0][0][RTW89_CN][7] = 42,
[0][1][0][0][RTW89_UK][7] = 48,
+ [0][1][0][0][RTW89_MEXICO][7] = 76,
+ [0][1][0][0][RTW89_UKRAINE][7] = 48,
+ [0][1][0][0][RTW89_CHILE][7] = 76,
+ [0][1][0][0][RTW89_QATAR][7] = 48,
[0][1][0][0][RTW89_FCC][8] = 76,
[0][1][0][0][RTW89_ETSI][8] = 48,
[0][1][0][0][RTW89_MKK][8] = 58,
@@ -28946,6 +32018,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][8] = 48,
[0][1][0][0][RTW89_CN][8] = 42,
[0][1][0][0][RTW89_UK][8] = 48,
+ [0][1][0][0][RTW89_MEXICO][8] = 76,
+ [0][1][0][0][RTW89_UKRAINE][8] = 48,
+ [0][1][0][0][RTW89_CHILE][8] = 76,
+ [0][1][0][0][RTW89_QATAR][8] = 48,
[0][1][0][0][RTW89_FCC][9] = 70,
[0][1][0][0][RTW89_ETSI][9] = 48,
[0][1][0][0][RTW89_MKK][9] = 58,
@@ -28954,6 +32030,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][9] = 48,
[0][1][0][0][RTW89_CN][9] = 42,
[0][1][0][0][RTW89_UK][9] = 48,
+ [0][1][0][0][RTW89_MEXICO][9] = 70,
+ [0][1][0][0][RTW89_UKRAINE][9] = 48,
+ [0][1][0][0][RTW89_CHILE][9] = 70,
+ [0][1][0][0][RTW89_QATAR][9] = 48,
[0][1][0][0][RTW89_FCC][10] = 72,
[0][1][0][0][RTW89_ETSI][10] = 48,
[0][1][0][0][RTW89_MKK][10] = 58,
@@ -28962,6 +32042,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][10] = 48,
[0][1][0][0][RTW89_CN][10] = 42,
[0][1][0][0][RTW89_UK][10] = 48,
+ [0][1][0][0][RTW89_MEXICO][10] = 72,
+ [0][1][0][0][RTW89_UKRAINE][10] = 48,
+ [0][1][0][0][RTW89_CHILE][10] = 72,
+ [0][1][0][0][RTW89_QATAR][10] = 48,
[0][1][0][0][RTW89_FCC][11] = 44,
[0][1][0][0][RTW89_ETSI][11] = 48,
[0][1][0][0][RTW89_MKK][11] = 58,
@@ -28970,6 +32054,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][11] = 48,
[0][1][0][0][RTW89_CN][11] = 42,
[0][1][0][0][RTW89_UK][11] = 48,
+ [0][1][0][0][RTW89_MEXICO][11] = 44,
+ [0][1][0][0][RTW89_UKRAINE][11] = 48,
+ [0][1][0][0][RTW89_CHILE][11] = 44,
+ [0][1][0][0][RTW89_QATAR][11] = 48,
[0][1][0][0][RTW89_FCC][12] = 18,
[0][1][0][0][RTW89_ETSI][12] = 48,
[0][1][0][0][RTW89_MKK][12] = 58,
@@ -28978,6 +32066,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][12] = 48,
[0][1][0][0][RTW89_CN][12] = 42,
[0][1][0][0][RTW89_UK][12] = 48,
+ [0][1][0][0][RTW89_MEXICO][12] = 18,
+ [0][1][0][0][RTW89_UKRAINE][12] = 48,
+ [0][1][0][0][RTW89_CHILE][12] = 18,
+ [0][1][0][0][RTW89_QATAR][12] = 48,
[0][1][0][0][RTW89_FCC][13] = 127,
[0][1][0][0][RTW89_ETSI][13] = 127,
[0][1][0][0][RTW89_MKK][13] = 60,
@@ -28986,6 +32078,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][13] = 127,
[0][1][0][0][RTW89_CN][13] = 127,
[0][1][0][0][RTW89_UK][13] = 127,
+ [0][1][0][0][RTW89_MEXICO][13] = 127,
+ [0][1][0][0][RTW89_UKRAINE][13] = 127,
+ [0][1][0][0][RTW89_CHILE][13] = 127,
+ [0][1][0][0][RTW89_QATAR][13] = 127,
[1][0][0][0][RTW89_FCC][0] = 127,
[1][0][0][0][RTW89_ETSI][0] = 127,
[1][0][0][0][RTW89_MKK][0] = 127,
@@ -28994,6 +32090,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][0] = 127,
[1][0][0][0][RTW89_CN][0] = 127,
[1][0][0][0][RTW89_UK][0] = 127,
+ [1][0][0][0][RTW89_MEXICO][0] = 127,
+ [1][0][0][0][RTW89_UKRAINE][0] = 127,
+ [1][0][0][0][RTW89_CHILE][0] = 127,
+ [1][0][0][0][RTW89_QATAR][0] = 127,
[1][0][0][0][RTW89_FCC][1] = 127,
[1][0][0][0][RTW89_ETSI][1] = 127,
[1][0][0][0][RTW89_MKK][1] = 127,
@@ -29002,6 +32102,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][1] = 127,
[1][0][0][0][RTW89_CN][1] = 127,
[1][0][0][0][RTW89_UK][1] = 127,
+ [1][0][0][0][RTW89_MEXICO][1] = 127,
+ [1][0][0][0][RTW89_UKRAINE][1] = 127,
+ [1][0][0][0][RTW89_CHILE][1] = 127,
+ [1][0][0][0][RTW89_QATAR][1] = 127,
[1][0][0][0][RTW89_FCC][2] = 44,
[1][0][0][0][RTW89_ETSI][2] = 60,
[1][0][0][0][RTW89_MKK][2] = 66,
@@ -29010,6 +32114,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][2] = 60,
[1][0][0][0][RTW89_CN][2] = 58,
[1][0][0][0][RTW89_UK][2] = 60,
+ [1][0][0][0][RTW89_MEXICO][2] = 44,
+ [1][0][0][0][RTW89_UKRAINE][2] = 60,
+ [1][0][0][0][RTW89_CHILE][2] = 44,
+ [1][0][0][0][RTW89_QATAR][2] = 60,
[1][0][0][0][RTW89_FCC][3] = 60,
[1][0][0][0][RTW89_ETSI][3] = 60,
[1][0][0][0][RTW89_MKK][3] = 66,
@@ -29018,6 +32126,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][3] = 60,
[1][0][0][0][RTW89_CN][3] = 58,
[1][0][0][0][RTW89_UK][3] = 60,
+ [1][0][0][0][RTW89_MEXICO][3] = 60,
+ [1][0][0][0][RTW89_UKRAINE][3] = 60,
+ [1][0][0][0][RTW89_CHILE][3] = 60,
+ [1][0][0][0][RTW89_QATAR][3] = 60,
[1][0][0][0][RTW89_FCC][4] = 60,
[1][0][0][0][RTW89_ETSI][4] = 60,
[1][0][0][0][RTW89_MKK][4] = 66,
@@ -29026,6 +32138,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][4] = 60,
[1][0][0][0][RTW89_CN][4] = 58,
[1][0][0][0][RTW89_UK][4] = 60,
+ [1][0][0][0][RTW89_MEXICO][4] = 60,
+ [1][0][0][0][RTW89_UKRAINE][4] = 60,
+ [1][0][0][0][RTW89_CHILE][4] = 60,
+ [1][0][0][0][RTW89_QATAR][4] = 60,
[1][0][0][0][RTW89_FCC][5] = 62,
[1][0][0][0][RTW89_ETSI][5] = 60,
[1][0][0][0][RTW89_MKK][5] = 66,
@@ -29034,6 +32150,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][5] = 60,
[1][0][0][0][RTW89_CN][5] = 58,
[1][0][0][0][RTW89_UK][5] = 60,
+ [1][0][0][0][RTW89_MEXICO][5] = 62,
+ [1][0][0][0][RTW89_UKRAINE][5] = 60,
+ [1][0][0][0][RTW89_CHILE][5] = 62,
+ [1][0][0][0][RTW89_QATAR][5] = 60,
[1][0][0][0][RTW89_FCC][6] = 46,
[1][0][0][0][RTW89_ETSI][6] = 60,
[1][0][0][0][RTW89_MKK][6] = 66,
@@ -29042,6 +32162,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][6] = 60,
[1][0][0][0][RTW89_CN][6] = 58,
[1][0][0][0][RTW89_UK][6] = 60,
+ [1][0][0][0][RTW89_MEXICO][6] = 46,
+ [1][0][0][0][RTW89_UKRAINE][6] = 60,
+ [1][0][0][0][RTW89_CHILE][6] = 46,
+ [1][0][0][0][RTW89_QATAR][6] = 60,
[1][0][0][0][RTW89_FCC][7] = 46,
[1][0][0][0][RTW89_ETSI][7] = 60,
[1][0][0][0][RTW89_MKK][7] = 66,
@@ -29050,6 +32174,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][7] = 60,
[1][0][0][0][RTW89_CN][7] = 58,
[1][0][0][0][RTW89_UK][7] = 60,
+ [1][0][0][0][RTW89_MEXICO][7] = 46,
+ [1][0][0][0][RTW89_UKRAINE][7] = 60,
+ [1][0][0][0][RTW89_CHILE][7] = 46,
+ [1][0][0][0][RTW89_QATAR][7] = 60,
[1][0][0][0][RTW89_FCC][8] = 28,
[1][0][0][0][RTW89_ETSI][8] = 60,
[1][0][0][0][RTW89_MKK][8] = 66,
@@ -29058,6 +32186,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][8] = 60,
[1][0][0][0][RTW89_CN][8] = 58,
[1][0][0][0][RTW89_UK][8] = 60,
+ [1][0][0][0][RTW89_MEXICO][8] = 28,
+ [1][0][0][0][RTW89_UKRAINE][8] = 60,
+ [1][0][0][0][RTW89_CHILE][8] = 28,
+ [1][0][0][0][RTW89_QATAR][8] = 60,
[1][0][0][0][RTW89_FCC][9] = 26,
[1][0][0][0][RTW89_ETSI][9] = 60,
[1][0][0][0][RTW89_MKK][9] = 66,
@@ -29066,6 +32198,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][9] = 60,
[1][0][0][0][RTW89_CN][9] = 58,
[1][0][0][0][RTW89_UK][9] = 60,
+ [1][0][0][0][RTW89_MEXICO][9] = 26,
+ [1][0][0][0][RTW89_UKRAINE][9] = 60,
+ [1][0][0][0][RTW89_CHILE][9] = 26,
+ [1][0][0][0][RTW89_QATAR][9] = 60,
[1][0][0][0][RTW89_FCC][10] = 26,
[1][0][0][0][RTW89_ETSI][10] = 60,
[1][0][0][0][RTW89_MKK][10] = 66,
@@ -29074,6 +32210,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][10] = 60,
[1][0][0][0][RTW89_CN][10] = 58,
[1][0][0][0][RTW89_UK][10] = 60,
+ [1][0][0][0][RTW89_MEXICO][10] = 26,
+ [1][0][0][0][RTW89_UKRAINE][10] = 60,
+ [1][0][0][0][RTW89_CHILE][10] = 26,
+ [1][0][0][0][RTW89_QATAR][10] = 60,
[1][0][0][0][RTW89_FCC][11] = 127,
[1][0][0][0][RTW89_ETSI][11] = 127,
[1][0][0][0][RTW89_MKK][11] = 127,
@@ -29082,6 +32222,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][11] = 127,
[1][0][0][0][RTW89_CN][11] = 127,
[1][0][0][0][RTW89_UK][11] = 127,
+ [1][0][0][0][RTW89_MEXICO][11] = 127,
+ [1][0][0][0][RTW89_UKRAINE][11] = 127,
+ [1][0][0][0][RTW89_CHILE][11] = 127,
+ [1][0][0][0][RTW89_QATAR][11] = 127,
[1][0][0][0][RTW89_FCC][12] = 127,
[1][0][0][0][RTW89_ETSI][12] = 127,
[1][0][0][0][RTW89_MKK][12] = 127,
@@ -29090,6 +32234,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][12] = 127,
[1][0][0][0][RTW89_CN][12] = 127,
[1][0][0][0][RTW89_UK][12] = 127,
+ [1][0][0][0][RTW89_MEXICO][12] = 127,
+ [1][0][0][0][RTW89_UKRAINE][12] = 127,
+ [1][0][0][0][RTW89_CHILE][12] = 127,
+ [1][0][0][0][RTW89_QATAR][12] = 127,
[1][0][0][0][RTW89_FCC][13] = 127,
[1][0][0][0][RTW89_ETSI][13] = 127,
[1][0][0][0][RTW89_MKK][13] = 127,
@@ -29098,6 +32246,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][13] = 127,
[1][0][0][0][RTW89_CN][13] = 127,
[1][0][0][0][RTW89_UK][13] = 127,
+ [1][0][0][0][RTW89_MEXICO][13] = 127,
+ [1][0][0][0][RTW89_UKRAINE][13] = 127,
+ [1][0][0][0][RTW89_CHILE][13] = 127,
+ [1][0][0][0][RTW89_QATAR][13] = 127,
[1][1][0][0][RTW89_FCC][0] = 127,
[1][1][0][0][RTW89_ETSI][0] = 127,
[1][1][0][0][RTW89_MKK][0] = 127,
@@ -29106,6 +32258,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][0] = 127,
[1][1][0][0][RTW89_CN][0] = 127,
[1][1][0][0][RTW89_UK][0] = 127,
+ [1][1][0][0][RTW89_MEXICO][0] = 127,
+ [1][1][0][0][RTW89_UKRAINE][0] = 127,
+ [1][1][0][0][RTW89_CHILE][0] = 127,
+ [1][1][0][0][RTW89_QATAR][0] = 127,
[1][1][0][0][RTW89_FCC][1] = 127,
[1][1][0][0][RTW89_ETSI][1] = 127,
[1][1][0][0][RTW89_MKK][1] = 127,
@@ -29114,6 +32270,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][1] = 127,
[1][1][0][0][RTW89_CN][1] = 127,
[1][1][0][0][RTW89_UK][1] = 127,
+ [1][1][0][0][RTW89_MEXICO][1] = 127,
+ [1][1][0][0][RTW89_UKRAINE][1] = 127,
+ [1][1][0][0][RTW89_CHILE][1] = 127,
+ [1][1][0][0][RTW89_QATAR][1] = 127,
[1][1][0][0][RTW89_FCC][2] = 46,
[1][1][0][0][RTW89_ETSI][2] = 48,
[1][1][0][0][RTW89_MKK][2] = 58,
@@ -29122,6 +32282,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][2] = 48,
[1][1][0][0][RTW89_CN][2] = 46,
[1][1][0][0][RTW89_UK][2] = 48,
+ [1][1][0][0][RTW89_MEXICO][2] = 46,
+ [1][1][0][0][RTW89_UKRAINE][2] = 48,
+ [1][1][0][0][RTW89_CHILE][2] = 46,
+ [1][1][0][0][RTW89_QATAR][2] = 48,
[1][1][0][0][RTW89_FCC][3] = 46,
[1][1][0][0][RTW89_ETSI][3] = 48,
[1][1][0][0][RTW89_MKK][3] = 58,
@@ -29130,6 +32294,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][3] = 48,
[1][1][0][0][RTW89_CN][3] = 46,
[1][1][0][0][RTW89_UK][3] = 48,
+ [1][1][0][0][RTW89_MEXICO][3] = 46,
+ [1][1][0][0][RTW89_UKRAINE][3] = 48,
+ [1][1][0][0][RTW89_CHILE][3] = 46,
+ [1][1][0][0][RTW89_QATAR][3] = 48,
[1][1][0][0][RTW89_FCC][4] = 46,
[1][1][0][0][RTW89_ETSI][4] = 48,
[1][1][0][0][RTW89_MKK][4] = 58,
@@ -29138,6 +32306,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][4] = 48,
[1][1][0][0][RTW89_CN][4] = 46,
[1][1][0][0][RTW89_UK][4] = 48,
+ [1][1][0][0][RTW89_MEXICO][4] = 46,
+ [1][1][0][0][RTW89_UKRAINE][4] = 48,
+ [1][1][0][0][RTW89_CHILE][4] = 46,
+ [1][1][0][0][RTW89_QATAR][4] = 48,
[1][1][0][0][RTW89_FCC][5] = 48,
[1][1][0][0][RTW89_ETSI][5] = 48,
[1][1][0][0][RTW89_MKK][5] = 58,
@@ -29146,6 +32318,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][5] = 48,
[1][1][0][0][RTW89_CN][5] = 46,
[1][1][0][0][RTW89_UK][5] = 48,
+ [1][1][0][0][RTW89_MEXICO][5] = 48,
+ [1][1][0][0][RTW89_UKRAINE][5] = 48,
+ [1][1][0][0][RTW89_CHILE][5] = 48,
+ [1][1][0][0][RTW89_QATAR][5] = 48,
[1][1][0][0][RTW89_FCC][6] = 40,
[1][1][0][0][RTW89_ETSI][6] = 48,
[1][1][0][0][RTW89_MKK][6] = 58,
@@ -29154,6 +32330,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][6] = 48,
[1][1][0][0][RTW89_CN][6] = 46,
[1][1][0][0][RTW89_UK][6] = 48,
+ [1][1][0][0][RTW89_MEXICO][6] = 40,
+ [1][1][0][0][RTW89_UKRAINE][6] = 48,
+ [1][1][0][0][RTW89_CHILE][6] = 40,
+ [1][1][0][0][RTW89_QATAR][6] = 48,
[1][1][0][0][RTW89_FCC][7] = 40,
[1][1][0][0][RTW89_ETSI][7] = 48,
[1][1][0][0][RTW89_MKK][7] = 58,
@@ -29162,6 +32342,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][7] = 48,
[1][1][0][0][RTW89_CN][7] = 46,
[1][1][0][0][RTW89_UK][7] = 48,
+ [1][1][0][0][RTW89_MEXICO][7] = 40,
+ [1][1][0][0][RTW89_UKRAINE][7] = 48,
+ [1][1][0][0][RTW89_CHILE][7] = 40,
+ [1][1][0][0][RTW89_QATAR][7] = 48,
[1][1][0][0][RTW89_FCC][8] = 14,
[1][1][0][0][RTW89_ETSI][8] = 48,
[1][1][0][0][RTW89_MKK][8] = 58,
@@ -29170,6 +32354,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][8] = 48,
[1][1][0][0][RTW89_CN][8] = 46,
[1][1][0][0][RTW89_UK][8] = 48,
+ [1][1][0][0][RTW89_MEXICO][8] = 14,
+ [1][1][0][0][RTW89_UKRAINE][8] = 48,
+ [1][1][0][0][RTW89_CHILE][8] = 14,
+ [1][1][0][0][RTW89_QATAR][8] = 48,
[1][1][0][0][RTW89_FCC][9] = 14,
[1][1][0][0][RTW89_ETSI][9] = 48,
[1][1][0][0][RTW89_MKK][9] = 58,
@@ -29178,6 +32366,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][9] = 48,
[1][1][0][0][RTW89_CN][9] = 46,
[1][1][0][0][RTW89_UK][9] = 48,
+ [1][1][0][0][RTW89_MEXICO][9] = 14,
+ [1][1][0][0][RTW89_UKRAINE][9] = 48,
+ [1][1][0][0][RTW89_CHILE][9] = 14,
+ [1][1][0][0][RTW89_QATAR][9] = 48,
[1][1][0][0][RTW89_FCC][10] = 12,
[1][1][0][0][RTW89_ETSI][10] = 48,
[1][1][0][0][RTW89_MKK][10] = 56,
@@ -29186,6 +32378,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][10] = 48,
[1][1][0][0][RTW89_CN][10] = 46,
[1][1][0][0][RTW89_UK][10] = 48,
+ [1][1][0][0][RTW89_MEXICO][10] = 12,
+ [1][1][0][0][RTW89_UKRAINE][10] = 48,
+ [1][1][0][0][RTW89_CHILE][10] = 12,
+ [1][1][0][0][RTW89_QATAR][10] = 48,
[1][1][0][0][RTW89_FCC][11] = 127,
[1][1][0][0][RTW89_ETSI][11] = 127,
[1][1][0][0][RTW89_MKK][11] = 127,
@@ -29194,6 +32390,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][11] = 127,
[1][1][0][0][RTW89_CN][11] = 127,
[1][1][0][0][RTW89_UK][11] = 127,
+ [1][1][0][0][RTW89_MEXICO][11] = 127,
+ [1][1][0][0][RTW89_UKRAINE][11] = 127,
+ [1][1][0][0][RTW89_CHILE][11] = 127,
+ [1][1][0][0][RTW89_QATAR][11] = 127,
[1][1][0][0][RTW89_FCC][12] = 127,
[1][1][0][0][RTW89_ETSI][12] = 127,
[1][1][0][0][RTW89_MKK][12] = 127,
@@ -29202,6 +32402,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][12] = 127,
[1][1][0][0][RTW89_CN][12] = 127,
[1][1][0][0][RTW89_UK][12] = 127,
+ [1][1][0][0][RTW89_MEXICO][12] = 127,
+ [1][1][0][0][RTW89_UKRAINE][12] = 127,
+ [1][1][0][0][RTW89_CHILE][12] = 127,
+ [1][1][0][0][RTW89_QATAR][12] = 127,
[1][1][0][0][RTW89_FCC][13] = 127,
[1][1][0][0][RTW89_ETSI][13] = 127,
[1][1][0][0][RTW89_MKK][13] = 127,
@@ -29210,6 +32414,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][13] = 127,
[1][1][0][0][RTW89_CN][13] = 127,
[1][1][0][0][RTW89_UK][13] = 127,
+ [1][1][0][0][RTW89_MEXICO][13] = 127,
+ [1][1][0][0][RTW89_UKRAINE][13] = 127,
+ [1][1][0][0][RTW89_CHILE][13] = 127,
+ [1][1][0][0][RTW89_QATAR][13] = 127,
[0][0][1][0][RTW89_FCC][0] = 66,
[0][0][1][0][RTW89_ETSI][0] = 60,
[0][0][1][0][RTW89_MKK][0] = 76,
@@ -29218,6 +32426,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][0] = 60,
[0][0][1][0][RTW89_CN][0] = 58,
[0][0][1][0][RTW89_UK][0] = 60,
+ [0][0][1][0][RTW89_MEXICO][0] = 66,
+ [0][0][1][0][RTW89_UKRAINE][0] = 60,
+ [0][0][1][0][RTW89_CHILE][0] = 66,
+ [0][0][1][0][RTW89_QATAR][0] = 60,
[0][0][1][0][RTW89_FCC][1] = 68,
[0][0][1][0][RTW89_ETSI][1] = 60,
[0][0][1][0][RTW89_MKK][1] = 78,
@@ -29226,6 +32438,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][1] = 60,
[0][0][1][0][RTW89_CN][1] = 58,
[0][0][1][0][RTW89_UK][1] = 60,
+ [0][0][1][0][RTW89_MEXICO][1] = 68,
+ [0][0][1][0][RTW89_UKRAINE][1] = 60,
+ [0][0][1][0][RTW89_CHILE][1] = 68,
+ [0][0][1][0][RTW89_QATAR][1] = 60,
[0][0][1][0][RTW89_FCC][2] = 72,
[0][0][1][0][RTW89_ETSI][2] = 60,
[0][0][1][0][RTW89_MKK][2] = 78,
@@ -29234,6 +32450,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][2] = 60,
[0][0][1][0][RTW89_CN][2] = 58,
[0][0][1][0][RTW89_UK][2] = 60,
+ [0][0][1][0][RTW89_MEXICO][2] = 72,
+ [0][0][1][0][RTW89_UKRAINE][2] = 60,
+ [0][0][1][0][RTW89_CHILE][2] = 62,
+ [0][0][1][0][RTW89_QATAR][2] = 60,
[0][0][1][0][RTW89_FCC][3] = 76,
[0][0][1][0][RTW89_ETSI][3] = 60,
[0][0][1][0][RTW89_MKK][3] = 78,
@@ -29242,6 +32462,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][3] = 60,
[0][0][1][0][RTW89_CN][3] = 58,
[0][0][1][0][RTW89_UK][3] = 60,
+ [0][0][1][0][RTW89_MEXICO][3] = 76,
+ [0][0][1][0][RTW89_UKRAINE][3] = 60,
+ [0][0][1][0][RTW89_CHILE][3] = 62,
+ [0][0][1][0][RTW89_QATAR][3] = 60,
[0][0][1][0][RTW89_FCC][4] = 80,
[0][0][1][0][RTW89_ETSI][4] = 60,
[0][0][1][0][RTW89_MKK][4] = 78,
@@ -29250,6 +32474,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][4] = 60,
[0][0][1][0][RTW89_CN][4] = 58,
[0][0][1][0][RTW89_UK][4] = 60,
+ [0][0][1][0][RTW89_MEXICO][4] = 80,
+ [0][0][1][0][RTW89_UKRAINE][4] = 60,
+ [0][0][1][0][RTW89_CHILE][4] = 62,
+ [0][0][1][0][RTW89_QATAR][4] = 60,
[0][0][1][0][RTW89_FCC][5] = 80,
[0][0][1][0][RTW89_ETSI][5] = 60,
[0][0][1][0][RTW89_MKK][5] = 78,
@@ -29258,6 +32486,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][5] = 60,
[0][0][1][0][RTW89_CN][5] = 58,
[0][0][1][0][RTW89_UK][5] = 60,
+ [0][0][1][0][RTW89_MEXICO][5] = 80,
+ [0][0][1][0][RTW89_UKRAINE][5] = 60,
+ [0][0][1][0][RTW89_CHILE][5] = 80,
+ [0][0][1][0][RTW89_QATAR][5] = 60,
[0][0][1][0][RTW89_FCC][6] = 80,
[0][0][1][0][RTW89_ETSI][6] = 60,
[0][0][1][0][RTW89_MKK][6] = 76,
@@ -29266,6 +32498,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][6] = 60,
[0][0][1][0][RTW89_CN][6] = 58,
[0][0][1][0][RTW89_UK][6] = 60,
+ [0][0][1][0][RTW89_MEXICO][6] = 80,
+ [0][0][1][0][RTW89_UKRAINE][6] = 60,
+ [0][0][1][0][RTW89_CHILE][6] = 70,
+ [0][0][1][0][RTW89_QATAR][6] = 60,
[0][0][1][0][RTW89_FCC][7] = 80,
[0][0][1][0][RTW89_ETSI][7] = 60,
[0][0][1][0][RTW89_MKK][7] = 78,
@@ -29274,6 +32510,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][7] = 60,
[0][0][1][0][RTW89_CN][7] = 58,
[0][0][1][0][RTW89_UK][7] = 60,
+ [0][0][1][0][RTW89_MEXICO][7] = 80,
+ [0][0][1][0][RTW89_UKRAINE][7] = 60,
+ [0][0][1][0][RTW89_CHILE][7] = 70,
+ [0][0][1][0][RTW89_QATAR][7] = 60,
[0][0][1][0][RTW89_FCC][8] = 80,
[0][0][1][0][RTW89_ETSI][8] = 60,
[0][0][1][0][RTW89_MKK][8] = 78,
@@ -29282,6 +32522,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][8] = 60,
[0][0][1][0][RTW89_CN][8] = 58,
[0][0][1][0][RTW89_UK][8] = 60,
+ [0][0][1][0][RTW89_MEXICO][8] = 80,
+ [0][0][1][0][RTW89_UKRAINE][8] = 60,
+ [0][0][1][0][RTW89_CHILE][8] = 70,
+ [0][0][1][0][RTW89_QATAR][8] = 60,
[0][0][1][0][RTW89_FCC][9] = 76,
[0][0][1][0][RTW89_ETSI][9] = 60,
[0][0][1][0][RTW89_MKK][9] = 78,
@@ -29290,6 +32534,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][9] = 60,
[0][0][1][0][RTW89_CN][9] = 58,
[0][0][1][0][RTW89_UK][9] = 60,
+ [0][0][1][0][RTW89_MEXICO][9] = 76,
+ [0][0][1][0][RTW89_UKRAINE][9] = 60,
+ [0][0][1][0][RTW89_CHILE][9] = 76,
+ [0][0][1][0][RTW89_QATAR][9] = 60,
[0][0][1][0][RTW89_FCC][10] = 66,
[0][0][1][0][RTW89_ETSI][10] = 60,
[0][0][1][0][RTW89_MKK][10] = 78,
@@ -29298,6 +32546,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][10] = 60,
[0][0][1][0][RTW89_CN][10] = 58,
[0][0][1][0][RTW89_UK][10] = 60,
+ [0][0][1][0][RTW89_MEXICO][10] = 66,
+ [0][0][1][0][RTW89_UKRAINE][10] = 60,
+ [0][0][1][0][RTW89_CHILE][10] = 66,
+ [0][0][1][0][RTW89_QATAR][10] = 60,
[0][0][1][0][RTW89_FCC][11] = 62,
[0][0][1][0][RTW89_ETSI][11] = 60,
[0][0][1][0][RTW89_MKK][11] = 78,
@@ -29306,6 +32558,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][11] = 60,
[0][0][1][0][RTW89_CN][11] = 58,
[0][0][1][0][RTW89_UK][11] = 60,
+ [0][0][1][0][RTW89_MEXICO][11] = 62,
+ [0][0][1][0][RTW89_UKRAINE][11] = 60,
+ [0][0][1][0][RTW89_CHILE][11] = 62,
+ [0][0][1][0][RTW89_QATAR][11] = 60,
[0][0][1][0][RTW89_FCC][12] = 60,
[0][0][1][0][RTW89_ETSI][12] = 60,
[0][0][1][0][RTW89_MKK][12] = 78,
@@ -29314,6 +32570,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][12] = 60,
[0][0][1][0][RTW89_CN][12] = 58,
[0][0][1][0][RTW89_UK][12] = 60,
+ [0][0][1][0][RTW89_MEXICO][12] = 60,
+ [0][0][1][0][RTW89_UKRAINE][12] = 60,
+ [0][0][1][0][RTW89_CHILE][12] = 60,
+ [0][0][1][0][RTW89_QATAR][12] = 60,
[0][0][1][0][RTW89_FCC][13] = 127,
[0][0][1][0][RTW89_ETSI][13] = 127,
[0][0][1][0][RTW89_MKK][13] = 127,
@@ -29322,6 +32582,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][13] = 127,
[0][0][1][0][RTW89_CN][13] = 127,
[0][0][1][0][RTW89_UK][13] = 127,
+ [0][0][1][0][RTW89_MEXICO][13] = 127,
+ [0][0][1][0][RTW89_UKRAINE][13] = 127,
+ [0][0][1][0][RTW89_CHILE][13] = 127,
+ [0][0][1][0][RTW89_QATAR][13] = 127,
[0][1][1][0][RTW89_FCC][0] = 66,
[0][1][1][0][RTW89_ETSI][0] = 48,
[0][1][1][0][RTW89_MKK][0] = 66,
@@ -29330,6 +32594,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][0] = 48,
[0][1][1][0][RTW89_CN][0] = 46,
[0][1][1][0][RTW89_UK][0] = 48,
+ [0][1][1][0][RTW89_MEXICO][0] = 66,
+ [0][1][1][0][RTW89_UKRAINE][0] = 48,
+ [0][1][1][0][RTW89_CHILE][0] = 66,
+ [0][1][1][0][RTW89_QATAR][0] = 48,
[0][1][1][0][RTW89_FCC][1] = 68,
[0][1][1][0][RTW89_ETSI][1] = 48,
[0][1][1][0][RTW89_MKK][1] = 66,
@@ -29338,6 +32606,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][1] = 48,
[0][1][1][0][RTW89_CN][1] = 46,
[0][1][1][0][RTW89_UK][1] = 48,
+ [0][1][1][0][RTW89_MEXICO][1] = 68,
+ [0][1][1][0][RTW89_UKRAINE][1] = 48,
+ [0][1][1][0][RTW89_CHILE][1] = 68,
+ [0][1][1][0][RTW89_QATAR][1] = 48,
[0][1][1][0][RTW89_FCC][2] = 72,
[0][1][1][0][RTW89_ETSI][2] = 48,
[0][1][1][0][RTW89_MKK][2] = 66,
@@ -29346,6 +32618,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][2] = 48,
[0][1][1][0][RTW89_CN][2] = 46,
[0][1][1][0][RTW89_UK][2] = 48,
+ [0][1][1][0][RTW89_MEXICO][2] = 72,
+ [0][1][1][0][RTW89_UKRAINE][2] = 48,
+ [0][1][1][0][RTW89_CHILE][2] = 54,
+ [0][1][1][0][RTW89_QATAR][2] = 48,
[0][1][1][0][RTW89_FCC][3] = 76,
[0][1][1][0][RTW89_ETSI][3] = 48,
[0][1][1][0][RTW89_MKK][3] = 66,
@@ -29354,6 +32630,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][3] = 48,
[0][1][1][0][RTW89_CN][3] = 46,
[0][1][1][0][RTW89_UK][3] = 48,
+ [0][1][1][0][RTW89_MEXICO][3] = 76,
+ [0][1][1][0][RTW89_UKRAINE][3] = 48,
+ [0][1][1][0][RTW89_CHILE][3] = 54,
+ [0][1][1][0][RTW89_QATAR][3] = 48,
[0][1][1][0][RTW89_FCC][4] = 80,
[0][1][1][0][RTW89_ETSI][4] = 48,
[0][1][1][0][RTW89_MKK][4] = 66,
@@ -29362,6 +32642,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][4] = 48,
[0][1][1][0][RTW89_CN][4] = 46,
[0][1][1][0][RTW89_UK][4] = 48,
+ [0][1][1][0][RTW89_MEXICO][4] = 80,
+ [0][1][1][0][RTW89_UKRAINE][4] = 48,
+ [0][1][1][0][RTW89_CHILE][4] = 54,
+ [0][1][1][0][RTW89_QATAR][4] = 48,
[0][1][1][0][RTW89_FCC][5] = 80,
[0][1][1][0][RTW89_ETSI][5] = 48,
[0][1][1][0][RTW89_MKK][5] = 66,
@@ -29370,6 +32654,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][5] = 48,
[0][1][1][0][RTW89_CN][5] = 46,
[0][1][1][0][RTW89_UK][5] = 48,
+ [0][1][1][0][RTW89_MEXICO][5] = 80,
+ [0][1][1][0][RTW89_UKRAINE][5] = 48,
+ [0][1][1][0][RTW89_CHILE][5] = 80,
+ [0][1][1][0][RTW89_QATAR][5] = 48,
[0][1][1][0][RTW89_FCC][6] = 80,
[0][1][1][0][RTW89_ETSI][6] = 48,
[0][1][1][0][RTW89_MKK][6] = 66,
@@ -29378,6 +32666,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][6] = 48,
[0][1][1][0][RTW89_CN][6] = 46,
[0][1][1][0][RTW89_UK][6] = 48,
+ [0][1][1][0][RTW89_MEXICO][6] = 80,
+ [0][1][1][0][RTW89_UKRAINE][6] = 48,
+ [0][1][1][0][RTW89_CHILE][6] = 56,
+ [0][1][1][0][RTW89_QATAR][6] = 48,
[0][1][1][0][RTW89_FCC][7] = 78,
[0][1][1][0][RTW89_ETSI][7] = 48,
[0][1][1][0][RTW89_MKK][7] = 66,
@@ -29386,6 +32678,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][7] = 48,
[0][1][1][0][RTW89_CN][7] = 46,
[0][1][1][0][RTW89_UK][7] = 48,
+ [0][1][1][0][RTW89_MEXICO][7] = 78,
+ [0][1][1][0][RTW89_UKRAINE][7] = 48,
+ [0][1][1][0][RTW89_CHILE][7] = 56,
+ [0][1][1][0][RTW89_QATAR][7] = 48,
[0][1][1][0][RTW89_FCC][8] = 74,
[0][1][1][0][RTW89_ETSI][8] = 48,
[0][1][1][0][RTW89_MKK][8] = 66,
@@ -29394,6 +32690,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][8] = 48,
[0][1][1][0][RTW89_CN][8] = 46,
[0][1][1][0][RTW89_UK][8] = 48,
+ [0][1][1][0][RTW89_MEXICO][8] = 74,
+ [0][1][1][0][RTW89_UKRAINE][8] = 48,
+ [0][1][1][0][RTW89_CHILE][8] = 56,
+ [0][1][1][0][RTW89_QATAR][8] = 48,
[0][1][1][0][RTW89_FCC][9] = 70,
[0][1][1][0][RTW89_ETSI][9] = 48,
[0][1][1][0][RTW89_MKK][9] = 66,
@@ -29402,6 +32702,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][9] = 48,
[0][1][1][0][RTW89_CN][9] = 46,
[0][1][1][0][RTW89_UK][9] = 48,
+ [0][1][1][0][RTW89_MEXICO][9] = 70,
+ [0][1][1][0][RTW89_UKRAINE][9] = 48,
+ [0][1][1][0][RTW89_CHILE][9] = 70,
+ [0][1][1][0][RTW89_QATAR][9] = 48,
[0][1][1][0][RTW89_FCC][10] = 62,
[0][1][1][0][RTW89_ETSI][10] = 48,
[0][1][1][0][RTW89_MKK][10] = 66,
@@ -29410,6 +32714,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][10] = 48,
[0][1][1][0][RTW89_CN][10] = 46,
[0][1][1][0][RTW89_UK][10] = 48,
+ [0][1][1][0][RTW89_MEXICO][10] = 62,
+ [0][1][1][0][RTW89_UKRAINE][10] = 48,
+ [0][1][1][0][RTW89_CHILE][10] = 62,
+ [0][1][1][0][RTW89_QATAR][10] = 48,
[0][1][1][0][RTW89_FCC][11] = 60,
[0][1][1][0][RTW89_ETSI][11] = 48,
[0][1][1][0][RTW89_MKK][11] = 66,
@@ -29418,6 +32726,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][11] = 48,
[0][1][1][0][RTW89_CN][11] = 46,
[0][1][1][0][RTW89_UK][11] = 48,
+ [0][1][1][0][RTW89_MEXICO][11] = 60,
+ [0][1][1][0][RTW89_UKRAINE][11] = 48,
+ [0][1][1][0][RTW89_CHILE][11] = 60,
+ [0][1][1][0][RTW89_QATAR][11] = 48,
[0][1][1][0][RTW89_FCC][12] = 36,
[0][1][1][0][RTW89_ETSI][12] = 48,
[0][1][1][0][RTW89_MKK][12] = 66,
@@ -29426,6 +32738,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][12] = 48,
[0][1][1][0][RTW89_CN][12] = 46,
[0][1][1][0][RTW89_UK][12] = 48,
+ [0][1][1][0][RTW89_MEXICO][12] = 36,
+ [0][1][1][0][RTW89_UKRAINE][12] = 48,
+ [0][1][1][0][RTW89_CHILE][12] = 36,
+ [0][1][1][0][RTW89_QATAR][12] = 48,
[0][1][1][0][RTW89_FCC][13] = 127,
[0][1][1][0][RTW89_ETSI][13] = 127,
[0][1][1][0][RTW89_MKK][13] = 127,
@@ -29434,6 +32750,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][13] = 127,
[0][1][1][0][RTW89_CN][13] = 127,
[0][1][1][0][RTW89_UK][13] = 127,
+ [0][1][1][0][RTW89_MEXICO][13] = 127,
+ [0][1][1][0][RTW89_UKRAINE][13] = 127,
+ [0][1][1][0][RTW89_CHILE][13] = 127,
+ [0][1][1][0][RTW89_QATAR][13] = 127,
[0][0][2][0][RTW89_FCC][0] = 66,
[0][0][2][0][RTW89_ETSI][0] = 60,
[0][0][2][0][RTW89_MKK][0] = 78,
@@ -29442,6 +32762,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][0] = 60,
[0][0][2][0][RTW89_CN][0] = 58,
[0][0][2][0][RTW89_UK][0] = 60,
+ [0][0][2][0][RTW89_MEXICO][0] = 66,
+ [0][0][2][0][RTW89_UKRAINE][0] = 60,
+ [0][0][2][0][RTW89_CHILE][0] = 66,
+ [0][0][2][0][RTW89_QATAR][0] = 60,
[0][0][2][0][RTW89_FCC][1] = 70,
[0][0][2][0][RTW89_ETSI][1] = 60,
[0][0][2][0][RTW89_MKK][1] = 78,
@@ -29450,6 +32774,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][1] = 60,
[0][0][2][0][RTW89_CN][1] = 58,
[0][0][2][0][RTW89_UK][1] = 60,
+ [0][0][2][0][RTW89_MEXICO][1] = 70,
+ [0][0][2][0][RTW89_UKRAINE][1] = 60,
+ [0][0][2][0][RTW89_CHILE][1] = 70,
+ [0][0][2][0][RTW89_QATAR][1] = 60,
[0][0][2][0][RTW89_FCC][2] = 74,
[0][0][2][0][RTW89_ETSI][2] = 60,
[0][0][2][0][RTW89_MKK][2] = 78,
@@ -29458,6 +32786,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][2] = 60,
[0][0][2][0][RTW89_CN][2] = 58,
[0][0][2][0][RTW89_UK][2] = 60,
+ [0][0][2][0][RTW89_MEXICO][2] = 74,
+ [0][0][2][0][RTW89_UKRAINE][2] = 60,
+ [0][0][2][0][RTW89_CHILE][2] = 64,
+ [0][0][2][0][RTW89_QATAR][2] = 60,
[0][0][2][0][RTW89_FCC][3] = 78,
[0][0][2][0][RTW89_ETSI][3] = 60,
[0][0][2][0][RTW89_MKK][3] = 78,
@@ -29466,6 +32798,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][3] = 60,
[0][0][2][0][RTW89_CN][3] = 58,
[0][0][2][0][RTW89_UK][3] = 60,
+ [0][0][2][0][RTW89_MEXICO][3] = 78,
+ [0][0][2][0][RTW89_UKRAINE][3] = 60,
+ [0][0][2][0][RTW89_CHILE][3] = 64,
+ [0][0][2][0][RTW89_QATAR][3] = 60,
[0][0][2][0][RTW89_FCC][4] = 80,
[0][0][2][0][RTW89_ETSI][4] = 60,
[0][0][2][0][RTW89_MKK][4] = 78,
@@ -29474,6 +32810,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][4] = 60,
[0][0][2][0][RTW89_CN][4] = 58,
[0][0][2][0][RTW89_UK][4] = 60,
+ [0][0][2][0][RTW89_MEXICO][4] = 80,
+ [0][0][2][0][RTW89_UKRAINE][4] = 60,
+ [0][0][2][0][RTW89_CHILE][4] = 64,
+ [0][0][2][0][RTW89_QATAR][4] = 60,
[0][0][2][0][RTW89_FCC][5] = 80,
[0][0][2][0][RTW89_ETSI][5] = 60,
[0][0][2][0][RTW89_MKK][5] = 78,
@@ -29482,6 +32822,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][5] = 60,
[0][0][2][0][RTW89_CN][5] = 58,
[0][0][2][0][RTW89_UK][5] = 60,
+ [0][0][2][0][RTW89_MEXICO][5] = 80,
+ [0][0][2][0][RTW89_UKRAINE][5] = 60,
+ [0][0][2][0][RTW89_CHILE][5] = 80,
+ [0][0][2][0][RTW89_QATAR][5] = 60,
[0][0][2][0][RTW89_FCC][6] = 80,
[0][0][2][0][RTW89_ETSI][6] = 60,
[0][0][2][0][RTW89_MKK][6] = 78,
@@ -29490,6 +32834,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][6] = 60,
[0][0][2][0][RTW89_CN][6] = 58,
[0][0][2][0][RTW89_UK][6] = 60,
+ [0][0][2][0][RTW89_MEXICO][6] = 80,
+ [0][0][2][0][RTW89_UKRAINE][6] = 60,
+ [0][0][2][0][RTW89_CHILE][6] = 68,
+ [0][0][2][0][RTW89_QATAR][6] = 60,
[0][0][2][0][RTW89_FCC][7] = 80,
[0][0][2][0][RTW89_ETSI][7] = 60,
[0][0][2][0][RTW89_MKK][7] = 78,
@@ -29498,6 +32846,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][7] = 60,
[0][0][2][0][RTW89_CN][7] = 58,
[0][0][2][0][RTW89_UK][7] = 60,
+ [0][0][2][0][RTW89_MEXICO][7] = 80,
+ [0][0][2][0][RTW89_UKRAINE][7] = 60,
+ [0][0][2][0][RTW89_CHILE][7] = 68,
+ [0][0][2][0][RTW89_QATAR][7] = 60,
[0][0][2][0][RTW89_FCC][8] = 78,
[0][0][2][0][RTW89_ETSI][8] = 60,
[0][0][2][0][RTW89_MKK][8] = 78,
@@ -29506,6 +32858,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][8] = 60,
[0][0][2][0][RTW89_CN][8] = 58,
[0][0][2][0][RTW89_UK][8] = 60,
+ [0][0][2][0][RTW89_MEXICO][8] = 78,
+ [0][0][2][0][RTW89_UKRAINE][8] = 60,
+ [0][0][2][0][RTW89_CHILE][8] = 68,
+ [0][0][2][0][RTW89_QATAR][8] = 60,
[0][0][2][0][RTW89_FCC][9] = 74,
[0][0][2][0][RTW89_ETSI][9] = 60,
[0][0][2][0][RTW89_MKK][9] = 78,
@@ -29514,6 +32870,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][9] = 60,
[0][0][2][0][RTW89_CN][9] = 58,
[0][0][2][0][RTW89_UK][9] = 60,
+ [0][0][2][0][RTW89_MEXICO][9] = 74,
+ [0][0][2][0][RTW89_UKRAINE][9] = 60,
+ [0][0][2][0][RTW89_CHILE][9] = 74,
+ [0][0][2][0][RTW89_QATAR][9] = 60,
[0][0][2][0][RTW89_FCC][10] = 62,
[0][0][2][0][RTW89_ETSI][10] = 60,
[0][0][2][0][RTW89_MKK][10] = 78,
@@ -29522,6 +32882,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][10] = 60,
[0][0][2][0][RTW89_CN][10] = 58,
[0][0][2][0][RTW89_UK][10] = 60,
+ [0][0][2][0][RTW89_MEXICO][10] = 62,
+ [0][0][2][0][RTW89_UKRAINE][10] = 60,
+ [0][0][2][0][RTW89_CHILE][10] = 62,
+ [0][0][2][0][RTW89_QATAR][10] = 60,
[0][0][2][0][RTW89_FCC][11] = 60,
[0][0][2][0][RTW89_ETSI][11] = 60,
[0][0][2][0][RTW89_MKK][11] = 78,
@@ -29530,6 +32894,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][11] = 60,
[0][0][2][0][RTW89_CN][11] = 58,
[0][0][2][0][RTW89_UK][11] = 60,
+ [0][0][2][0][RTW89_MEXICO][11] = 60,
+ [0][0][2][0][RTW89_UKRAINE][11] = 60,
+ [0][0][2][0][RTW89_CHILE][11] = 60,
+ [0][0][2][0][RTW89_QATAR][11] = 60,
[0][0][2][0][RTW89_FCC][12] = 38,
[0][0][2][0][RTW89_ETSI][12] = 60,
[0][0][2][0][RTW89_MKK][12] = 78,
@@ -29538,6 +32906,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][12] = 60,
[0][0][2][0][RTW89_CN][12] = 58,
[0][0][2][0][RTW89_UK][12] = 60,
+ [0][0][2][0][RTW89_MEXICO][12] = 38,
+ [0][0][2][0][RTW89_UKRAINE][12] = 60,
+ [0][0][2][0][RTW89_CHILE][12] = 38,
+ [0][0][2][0][RTW89_QATAR][12] = 60,
[0][0][2][0][RTW89_FCC][13] = 127,
[0][0][2][0][RTW89_ETSI][13] = 127,
[0][0][2][0][RTW89_MKK][13] = 127,
@@ -29546,6 +32918,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][13] = 127,
[0][0][2][0][RTW89_CN][13] = 127,
[0][0][2][0][RTW89_UK][13] = 127,
+ [0][0][2][0][RTW89_MEXICO][13] = 127,
+ [0][0][2][0][RTW89_UKRAINE][13] = 127,
+ [0][0][2][0][RTW89_CHILE][13] = 127,
+ [0][0][2][0][RTW89_QATAR][13] = 127,
[0][1][2][0][RTW89_FCC][0] = 64,
[0][1][2][0][RTW89_ETSI][0] = 48,
[0][1][2][0][RTW89_MKK][0] = 68,
@@ -29554,6 +32930,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][0] = 48,
[0][1][2][0][RTW89_CN][0] = 46,
[0][1][2][0][RTW89_UK][0] = 48,
+ [0][1][2][0][RTW89_MEXICO][0] = 64,
+ [0][1][2][0][RTW89_UKRAINE][0] = 48,
+ [0][1][2][0][RTW89_CHILE][0] = 64,
+ [0][1][2][0][RTW89_QATAR][0] = 48,
[0][1][2][0][RTW89_FCC][1] = 70,
[0][1][2][0][RTW89_ETSI][1] = 48,
[0][1][2][0][RTW89_MKK][1] = 68,
@@ -29562,6 +32942,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][1] = 48,
[0][1][2][0][RTW89_CN][1] = 46,
[0][1][2][0][RTW89_UK][1] = 48,
+ [0][1][2][0][RTW89_MEXICO][1] = 70,
+ [0][1][2][0][RTW89_UKRAINE][1] = 48,
+ [0][1][2][0][RTW89_CHILE][1] = 70,
+ [0][1][2][0][RTW89_QATAR][1] = 48,
[0][1][2][0][RTW89_FCC][2] = 74,
[0][1][2][0][RTW89_ETSI][2] = 48,
[0][1][2][0][RTW89_MKK][2] = 68,
@@ -29570,6 +32954,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][2] = 48,
[0][1][2][0][RTW89_CN][2] = 46,
[0][1][2][0][RTW89_UK][2] = 48,
+ [0][1][2][0][RTW89_MEXICO][2] = 74,
+ [0][1][2][0][RTW89_UKRAINE][2] = 48,
+ [0][1][2][0][RTW89_CHILE][2] = 56,
+ [0][1][2][0][RTW89_QATAR][2] = 48,
[0][1][2][0][RTW89_FCC][3] = 78,
[0][1][2][0][RTW89_ETSI][3] = 48,
[0][1][2][0][RTW89_MKK][3] = 68,
@@ -29578,6 +32966,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][3] = 48,
[0][1][2][0][RTW89_CN][3] = 46,
[0][1][2][0][RTW89_UK][3] = 48,
+ [0][1][2][0][RTW89_MEXICO][3] = 78,
+ [0][1][2][0][RTW89_UKRAINE][3] = 48,
+ [0][1][2][0][RTW89_CHILE][3] = 56,
+ [0][1][2][0][RTW89_QATAR][3] = 48,
[0][1][2][0][RTW89_FCC][4] = 80,
[0][1][2][0][RTW89_ETSI][4] = 48,
[0][1][2][0][RTW89_MKK][4] = 68,
@@ -29586,6 +32978,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][4] = 48,
[0][1][2][0][RTW89_CN][4] = 46,
[0][1][2][0][RTW89_UK][4] = 48,
+ [0][1][2][0][RTW89_MEXICO][4] = 80,
+ [0][1][2][0][RTW89_UKRAINE][4] = 48,
+ [0][1][2][0][RTW89_CHILE][4] = 56,
+ [0][1][2][0][RTW89_QATAR][4] = 48,
[0][1][2][0][RTW89_FCC][5] = 80,
[0][1][2][0][RTW89_ETSI][5] = 48,
[0][1][2][0][RTW89_MKK][5] = 68,
@@ -29594,6 +32990,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][5] = 48,
[0][1][2][0][RTW89_CN][5] = 46,
[0][1][2][0][RTW89_UK][5] = 48,
+ [0][1][2][0][RTW89_MEXICO][5] = 80,
+ [0][1][2][0][RTW89_UKRAINE][5] = 48,
+ [0][1][2][0][RTW89_CHILE][5] = 78,
+ [0][1][2][0][RTW89_QATAR][5] = 48,
[0][1][2][0][RTW89_FCC][6] = 80,
[0][1][2][0][RTW89_ETSI][6] = 48,
[0][1][2][0][RTW89_MKK][6] = 68,
@@ -29602,6 +33002,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][6] = 48,
[0][1][2][0][RTW89_CN][6] = 46,
[0][1][2][0][RTW89_UK][6] = 48,
+ [0][1][2][0][RTW89_MEXICO][6] = 80,
+ [0][1][2][0][RTW89_UKRAINE][6] = 48,
+ [0][1][2][0][RTW89_CHILE][6] = 54,
+ [0][1][2][0][RTW89_QATAR][6] = 48,
[0][1][2][0][RTW89_FCC][7] = 74,
[0][1][2][0][RTW89_ETSI][7] = 48,
[0][1][2][0][RTW89_MKK][7] = 68,
@@ -29610,6 +33014,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][7] = 48,
[0][1][2][0][RTW89_CN][7] = 46,
[0][1][2][0][RTW89_UK][7] = 48,
+ [0][1][2][0][RTW89_MEXICO][7] = 74,
+ [0][1][2][0][RTW89_UKRAINE][7] = 48,
+ [0][1][2][0][RTW89_CHILE][7] = 54,
+ [0][1][2][0][RTW89_QATAR][7] = 48,
[0][1][2][0][RTW89_FCC][8] = 70,
[0][1][2][0][RTW89_ETSI][8] = 48,
[0][1][2][0][RTW89_MKK][8] = 68,
@@ -29618,6 +33026,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][8] = 48,
[0][1][2][0][RTW89_CN][8] = 46,
[0][1][2][0][RTW89_UK][8] = 48,
+ [0][1][2][0][RTW89_MEXICO][8] = 70,
+ [0][1][2][0][RTW89_UKRAINE][8] = 48,
+ [0][1][2][0][RTW89_CHILE][8] = 54,
+ [0][1][2][0][RTW89_QATAR][8] = 48,
[0][1][2][0][RTW89_FCC][9] = 66,
[0][1][2][0][RTW89_ETSI][9] = 48,
[0][1][2][0][RTW89_MKK][9] = 68,
@@ -29626,6 +33038,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][9] = 48,
[0][1][2][0][RTW89_CN][9] = 46,
[0][1][2][0][RTW89_UK][9] = 48,
+ [0][1][2][0][RTW89_MEXICO][9] = 66,
+ [0][1][2][0][RTW89_UKRAINE][9] = 48,
+ [0][1][2][0][RTW89_CHILE][9] = 66,
+ [0][1][2][0][RTW89_QATAR][9] = 48,
[0][1][2][0][RTW89_FCC][10] = 58,
[0][1][2][0][RTW89_ETSI][10] = 48,
[0][1][2][0][RTW89_MKK][10] = 68,
@@ -29634,6 +33050,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][10] = 48,
[0][1][2][0][RTW89_CN][10] = 46,
[0][1][2][0][RTW89_UK][10] = 48,
+ [0][1][2][0][RTW89_MEXICO][10] = 58,
+ [0][1][2][0][RTW89_UKRAINE][10] = 48,
+ [0][1][2][0][RTW89_CHILE][10] = 58,
+ [0][1][2][0][RTW89_QATAR][10] = 48,
[0][1][2][0][RTW89_FCC][11] = 58,
[0][1][2][0][RTW89_ETSI][11] = 48,
[0][1][2][0][RTW89_MKK][11] = 68,
@@ -29642,6 +33062,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][11] = 48,
[0][1][2][0][RTW89_CN][11] = 46,
[0][1][2][0][RTW89_UK][11] = 48,
+ [0][1][2][0][RTW89_MEXICO][11] = 58,
+ [0][1][2][0][RTW89_UKRAINE][11] = 48,
+ [0][1][2][0][RTW89_CHILE][11] = 58,
+ [0][1][2][0][RTW89_QATAR][11] = 48,
[0][1][2][0][RTW89_FCC][12] = 16,
[0][1][2][0][RTW89_ETSI][12] = 48,
[0][1][2][0][RTW89_MKK][12] = 68,
@@ -29650,6 +33074,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][12] = 48,
[0][1][2][0][RTW89_CN][12] = 46,
[0][1][2][0][RTW89_UK][12] = 48,
+ [0][1][2][0][RTW89_MEXICO][12] = 16,
+ [0][1][2][0][RTW89_UKRAINE][12] = 48,
+ [0][1][2][0][RTW89_CHILE][12] = 16,
+ [0][1][2][0][RTW89_QATAR][12] = 48,
[0][1][2][0][RTW89_FCC][13] = 127,
[0][1][2][0][RTW89_ETSI][13] = 127,
[0][1][2][0][RTW89_MKK][13] = 127,
@@ -29658,6 +33086,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][13] = 127,
[0][1][2][0][RTW89_CN][13] = 127,
[0][1][2][0][RTW89_UK][13] = 127,
+ [0][1][2][0][RTW89_MEXICO][13] = 127,
+ [0][1][2][0][RTW89_UKRAINE][13] = 127,
+ [0][1][2][0][RTW89_CHILE][13] = 127,
+ [0][1][2][0][RTW89_QATAR][13] = 127,
[0][1][2][1][RTW89_FCC][0] = 64,
[0][1][2][1][RTW89_ETSI][0] = 36,
[0][1][2][1][RTW89_MKK][0] = 68,
@@ -29666,6 +33098,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][0] = 36,
[0][1][2][1][RTW89_CN][0] = 36,
[0][1][2][1][RTW89_UK][0] = 36,
+ [0][1][2][1][RTW89_MEXICO][0] = 64,
+ [0][1][2][1][RTW89_UKRAINE][0] = 36,
+ [0][1][2][1][RTW89_CHILE][0] = 64,
+ [0][1][2][1][RTW89_QATAR][0] = 36,
[0][1][2][1][RTW89_FCC][1] = 70,
[0][1][2][1][RTW89_ETSI][1] = 36,
[0][1][2][1][RTW89_MKK][1] = 68,
@@ -29674,6 +33110,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][1] = 36,
[0][1][2][1][RTW89_CN][1] = 34,
[0][1][2][1][RTW89_UK][1] = 36,
+ [0][1][2][1][RTW89_MEXICO][1] = 70,
+ [0][1][2][1][RTW89_UKRAINE][1] = 36,
+ [0][1][2][1][RTW89_CHILE][1] = 70,
+ [0][1][2][1][RTW89_QATAR][1] = 36,
[0][1][2][1][RTW89_FCC][2] = 74,
[0][1][2][1][RTW89_ETSI][2] = 36,
[0][1][2][1][RTW89_MKK][2] = 68,
@@ -29682,6 +33122,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][2] = 36,
[0][1][2][1][RTW89_CN][2] = 34,
[0][1][2][1][RTW89_UK][2] = 36,
+ [0][1][2][1][RTW89_MEXICO][2] = 74,
+ [0][1][2][1][RTW89_UKRAINE][2] = 36,
+ [0][1][2][1][RTW89_CHILE][2] = 44,
+ [0][1][2][1][RTW89_QATAR][2] = 36,
[0][1][2][1][RTW89_FCC][3] = 78,
[0][1][2][1][RTW89_ETSI][3] = 36,
[0][1][2][1][RTW89_MKK][3] = 68,
@@ -29690,6 +33134,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][3] = 36,
[0][1][2][1][RTW89_CN][3] = 34,
[0][1][2][1][RTW89_UK][3] = 36,
+ [0][1][2][1][RTW89_MEXICO][3] = 78,
+ [0][1][2][1][RTW89_UKRAINE][3] = 36,
+ [0][1][2][1][RTW89_CHILE][3] = 44,
+ [0][1][2][1][RTW89_QATAR][3] = 36,
[0][1][2][1][RTW89_FCC][4] = 80,
[0][1][2][1][RTW89_ETSI][4] = 36,
[0][1][2][1][RTW89_MKK][4] = 68,
@@ -29698,6 +33146,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][4] = 36,
[0][1][2][1][RTW89_CN][4] = 34,
[0][1][2][1][RTW89_UK][4] = 36,
+ [0][1][2][1][RTW89_MEXICO][4] = 80,
+ [0][1][2][1][RTW89_UKRAINE][4] = 36,
+ [0][1][2][1][RTW89_CHILE][4] = 44,
+ [0][1][2][1][RTW89_QATAR][4] = 36,
[0][1][2][1][RTW89_FCC][5] = 80,
[0][1][2][1][RTW89_ETSI][5] = 36,
[0][1][2][1][RTW89_MKK][5] = 68,
@@ -29706,6 +33158,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][5] = 36,
[0][1][2][1][RTW89_CN][5] = 34,
[0][1][2][1][RTW89_UK][5] = 36,
+ [0][1][2][1][RTW89_MEXICO][5] = 80,
+ [0][1][2][1][RTW89_UKRAINE][5] = 36,
+ [0][1][2][1][RTW89_CHILE][5] = 74,
+ [0][1][2][1][RTW89_QATAR][5] = 36,
[0][1][2][1][RTW89_FCC][6] = 80,
[0][1][2][1][RTW89_ETSI][6] = 36,
[0][1][2][1][RTW89_MKK][6] = 68,
@@ -29714,6 +33170,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][6] = 36,
[0][1][2][1][RTW89_CN][6] = 34,
[0][1][2][1][RTW89_UK][6] = 36,
+ [0][1][2][1][RTW89_MEXICO][6] = 80,
+ [0][1][2][1][RTW89_UKRAINE][6] = 36,
+ [0][1][2][1][RTW89_CHILE][6] = 42,
+ [0][1][2][1][RTW89_QATAR][6] = 36,
[0][1][2][1][RTW89_FCC][7] = 74,
[0][1][2][1][RTW89_ETSI][7] = 36,
[0][1][2][1][RTW89_MKK][7] = 68,
@@ -29722,6 +33182,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][7] = 36,
[0][1][2][1][RTW89_CN][7] = 34,
[0][1][2][1][RTW89_UK][7] = 36,
+ [0][1][2][1][RTW89_MEXICO][7] = 74,
+ [0][1][2][1][RTW89_UKRAINE][7] = 36,
+ [0][1][2][1][RTW89_CHILE][7] = 42,
+ [0][1][2][1][RTW89_QATAR][7] = 36,
[0][1][2][1][RTW89_FCC][8] = 70,
[0][1][2][1][RTW89_ETSI][8] = 36,
[0][1][2][1][RTW89_MKK][8] = 68,
@@ -29730,6 +33194,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][8] = 36,
[0][1][2][1][RTW89_CN][8] = 34,
[0][1][2][1][RTW89_UK][8] = 36,
+ [0][1][2][1][RTW89_MEXICO][8] = 70,
+ [0][1][2][1][RTW89_UKRAINE][8] = 36,
+ [0][1][2][1][RTW89_CHILE][8] = 42,
+ [0][1][2][1][RTW89_QATAR][8] = 36,
[0][1][2][1][RTW89_FCC][9] = 66,
[0][1][2][1][RTW89_ETSI][9] = 36,
[0][1][2][1][RTW89_MKK][9] = 68,
@@ -29738,6 +33206,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][9] = 36,
[0][1][2][1][RTW89_CN][9] = 34,
[0][1][2][1][RTW89_UK][9] = 36,
+ [0][1][2][1][RTW89_MEXICO][9] = 66,
+ [0][1][2][1][RTW89_UKRAINE][9] = 36,
+ [0][1][2][1][RTW89_CHILE][9] = 66,
+ [0][1][2][1][RTW89_QATAR][9] = 36,
[0][1][2][1][RTW89_FCC][10] = 58,
[0][1][2][1][RTW89_ETSI][10] = 36,
[0][1][2][1][RTW89_MKK][10] = 68,
@@ -29746,6 +33218,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][10] = 36,
[0][1][2][1][RTW89_CN][10] = 34,
[0][1][2][1][RTW89_UK][10] = 36,
+ [0][1][2][1][RTW89_MEXICO][10] = 58,
+ [0][1][2][1][RTW89_UKRAINE][10] = 36,
+ [0][1][2][1][RTW89_CHILE][10] = 58,
+ [0][1][2][1][RTW89_QATAR][10] = 36,
[0][1][2][1][RTW89_FCC][11] = 58,
[0][1][2][1][RTW89_ETSI][11] = 36,
[0][1][2][1][RTW89_MKK][11] = 68,
@@ -29754,6 +33230,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][11] = 36,
[0][1][2][1][RTW89_CN][11] = 34,
[0][1][2][1][RTW89_UK][11] = 36,
+ [0][1][2][1][RTW89_MEXICO][11] = 58,
+ [0][1][2][1][RTW89_UKRAINE][11] = 36,
+ [0][1][2][1][RTW89_CHILE][11] = 58,
+ [0][1][2][1][RTW89_QATAR][11] = 36,
[0][1][2][1][RTW89_FCC][12] = 16,
[0][1][2][1][RTW89_ETSI][12] = 36,
[0][1][2][1][RTW89_MKK][12] = 68,
@@ -29762,6 +33242,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][12] = 36,
[0][1][2][1][RTW89_CN][12] = 34,
[0][1][2][1][RTW89_UK][12] = 36,
+ [0][1][2][1][RTW89_MEXICO][12] = 16,
+ [0][1][2][1][RTW89_UKRAINE][12] = 36,
+ [0][1][2][1][RTW89_CHILE][12] = 16,
+ [0][1][2][1][RTW89_QATAR][12] = 36,
[0][1][2][1][RTW89_FCC][13] = 127,
[0][1][2][1][RTW89_ETSI][13] = 127,
[0][1][2][1][RTW89_MKK][13] = 127,
@@ -29770,6 +33254,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][13] = 127,
[0][1][2][1][RTW89_CN][13] = 127,
[0][1][2][1][RTW89_UK][13] = 127,
+ [0][1][2][1][RTW89_MEXICO][13] = 127,
+ [0][1][2][1][RTW89_UKRAINE][13] = 127,
+ [0][1][2][1][RTW89_CHILE][13] = 127,
+ [0][1][2][1][RTW89_QATAR][13] = 127,
[1][0][2][0][RTW89_FCC][0] = 127,
[1][0][2][0][RTW89_ETSI][0] = 127,
[1][0][2][0][RTW89_MKK][0] = 127,
@@ -29778,6 +33266,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][0] = 127,
[1][0][2][0][RTW89_CN][0] = 127,
[1][0][2][0][RTW89_UK][0] = 127,
+ [1][0][2][0][RTW89_MEXICO][0] = 127,
+ [1][0][2][0][RTW89_UKRAINE][0] = 127,
+ [1][0][2][0][RTW89_CHILE][0] = 127,
+ [1][0][2][0][RTW89_QATAR][0] = 127,
[1][0][2][0][RTW89_FCC][1] = 127,
[1][0][2][0][RTW89_ETSI][1] = 127,
[1][0][2][0][RTW89_MKK][1] = 127,
@@ -29786,6 +33278,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][1] = 127,
[1][0][2][0][RTW89_CN][1] = 127,
[1][0][2][0][RTW89_UK][1] = 127,
+ [1][0][2][0][RTW89_MEXICO][1] = 127,
+ [1][0][2][0][RTW89_UKRAINE][1] = 127,
+ [1][0][2][0][RTW89_CHILE][1] = 127,
+ [1][0][2][0][RTW89_QATAR][1] = 127,
[1][0][2][0][RTW89_FCC][2] = 64,
[1][0][2][0][RTW89_ETSI][2] = 60,
[1][0][2][0][RTW89_MKK][2] = 74,
@@ -29794,6 +33290,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][2] = 60,
[1][0][2][0][RTW89_CN][2] = 58,
[1][0][2][0][RTW89_UK][2] = 60,
+ [1][0][2][0][RTW89_MEXICO][2] = 64,
+ [1][0][2][0][RTW89_UKRAINE][2] = 60,
+ [1][0][2][0][RTW89_CHILE][2] = 64,
+ [1][0][2][0][RTW89_QATAR][2] = 60,
[1][0][2][0][RTW89_FCC][3] = 64,
[1][0][2][0][RTW89_ETSI][3] = 60,
[1][0][2][0][RTW89_MKK][3] = 74,
@@ -29802,6 +33302,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][3] = 60,
[1][0][2][0][RTW89_CN][3] = 58,
[1][0][2][0][RTW89_UK][3] = 60,
+ [1][0][2][0][RTW89_MEXICO][3] = 64,
+ [1][0][2][0][RTW89_UKRAINE][3] = 60,
+ [1][0][2][0][RTW89_CHILE][3] = 64,
+ [1][0][2][0][RTW89_QATAR][3] = 60,
[1][0][2][0][RTW89_FCC][4] = 68,
[1][0][2][0][RTW89_ETSI][4] = 60,
[1][0][2][0][RTW89_MKK][4] = 74,
@@ -29810,6 +33314,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][4] = 60,
[1][0][2][0][RTW89_CN][4] = 58,
[1][0][2][0][RTW89_UK][4] = 60,
+ [1][0][2][0][RTW89_MEXICO][4] = 68,
+ [1][0][2][0][RTW89_UKRAINE][4] = 60,
+ [1][0][2][0][RTW89_CHILE][4] = 68,
+ [1][0][2][0][RTW89_QATAR][4] = 60,
[1][0][2][0][RTW89_FCC][5] = 68,
[1][0][2][0][RTW89_ETSI][5] = 60,
[1][0][2][0][RTW89_MKK][5] = 74,
@@ -29818,6 +33326,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][5] = 60,
[1][0][2][0][RTW89_CN][5] = 58,
[1][0][2][0][RTW89_UK][5] = 60,
+ [1][0][2][0][RTW89_MEXICO][5] = 68,
+ [1][0][2][0][RTW89_UKRAINE][5] = 60,
+ [1][0][2][0][RTW89_CHILE][5] = 68,
+ [1][0][2][0][RTW89_QATAR][5] = 60,
[1][0][2][0][RTW89_FCC][6] = 66,
[1][0][2][0][RTW89_ETSI][6] = 60,
[1][0][2][0][RTW89_MKK][6] = 74,
@@ -29826,6 +33338,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][6] = 60,
[1][0][2][0][RTW89_CN][6] = 58,
[1][0][2][0][RTW89_UK][6] = 60,
+ [1][0][2][0][RTW89_MEXICO][6] = 66,
+ [1][0][2][0][RTW89_UKRAINE][6] = 60,
+ [1][0][2][0][RTW89_CHILE][6] = 66,
+ [1][0][2][0][RTW89_QATAR][6] = 60,
[1][0][2][0][RTW89_FCC][7] = 62,
[1][0][2][0][RTW89_ETSI][7] = 60,
[1][0][2][0][RTW89_MKK][7] = 74,
@@ -29834,6 +33350,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][7] = 60,
[1][0][2][0][RTW89_CN][7] = 58,
[1][0][2][0][RTW89_UK][7] = 60,
+ [1][0][2][0][RTW89_MEXICO][7] = 62,
+ [1][0][2][0][RTW89_UKRAINE][7] = 60,
+ [1][0][2][0][RTW89_CHILE][7] = 62,
+ [1][0][2][0][RTW89_QATAR][7] = 60,
[1][0][2][0][RTW89_FCC][8] = 62,
[1][0][2][0][RTW89_ETSI][8] = 60,
[1][0][2][0][RTW89_MKK][8] = 74,
@@ -29842,6 +33362,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][8] = 60,
[1][0][2][0][RTW89_CN][8] = 58,
[1][0][2][0][RTW89_UK][8] = 60,
+ [1][0][2][0][RTW89_MEXICO][8] = 62,
+ [1][0][2][0][RTW89_UKRAINE][8] = 60,
+ [1][0][2][0][RTW89_CHILE][8] = 62,
+ [1][0][2][0][RTW89_QATAR][8] = 60,
[1][0][2][0][RTW89_FCC][9] = 60,
[1][0][2][0][RTW89_ETSI][9] = 60,
[1][0][2][0][RTW89_MKK][9] = 74,
@@ -29850,6 +33374,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][9] = 60,
[1][0][2][0][RTW89_CN][9] = 58,
[1][0][2][0][RTW89_UK][9] = 60,
+ [1][0][2][0][RTW89_MEXICO][9] = 60,
+ [1][0][2][0][RTW89_UKRAINE][9] = 60,
+ [1][0][2][0][RTW89_CHILE][9] = 60,
+ [1][0][2][0][RTW89_QATAR][9] = 60,
[1][0][2][0][RTW89_FCC][10] = 56,
[1][0][2][0][RTW89_ETSI][10] = 60,
[1][0][2][0][RTW89_MKK][10] = 74,
@@ -29858,6 +33386,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][10] = 60,
[1][0][2][0][RTW89_CN][10] = 58,
[1][0][2][0][RTW89_UK][10] = 60,
+ [1][0][2][0][RTW89_MEXICO][10] = 56,
+ [1][0][2][0][RTW89_UKRAINE][10] = 60,
+ [1][0][2][0][RTW89_CHILE][10] = 56,
+ [1][0][2][0][RTW89_QATAR][10] = 60,
[1][0][2][0][RTW89_FCC][11] = 127,
[1][0][2][0][RTW89_ETSI][11] = 127,
[1][0][2][0][RTW89_MKK][11] = 127,
@@ -29866,6 +33398,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][11] = 127,
[1][0][2][0][RTW89_CN][11] = 127,
[1][0][2][0][RTW89_UK][11] = 127,
+ [1][0][2][0][RTW89_MEXICO][11] = 127,
+ [1][0][2][0][RTW89_UKRAINE][11] = 127,
+ [1][0][2][0][RTW89_CHILE][11] = 127,
+ [1][0][2][0][RTW89_QATAR][11] = 127,
[1][0][2][0][RTW89_FCC][12] = 127,
[1][0][2][0][RTW89_ETSI][12] = 127,
[1][0][2][0][RTW89_MKK][12] = 127,
@@ -29874,6 +33410,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][12] = 127,
[1][0][2][0][RTW89_CN][12] = 127,
[1][0][2][0][RTW89_UK][12] = 127,
+ [1][0][2][0][RTW89_MEXICO][12] = 127,
+ [1][0][2][0][RTW89_UKRAINE][12] = 127,
+ [1][0][2][0][RTW89_CHILE][12] = 127,
+ [1][0][2][0][RTW89_QATAR][12] = 127,
[1][0][2][0][RTW89_FCC][13] = 127,
[1][0][2][0][RTW89_ETSI][13] = 127,
[1][0][2][0][RTW89_MKK][13] = 127,
@@ -29882,6 +33422,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][13] = 127,
[1][0][2][0][RTW89_CN][13] = 127,
[1][0][2][0][RTW89_UK][13] = 127,
+ [1][0][2][0][RTW89_MEXICO][13] = 127,
+ [1][0][2][0][RTW89_UKRAINE][13] = 127,
+ [1][0][2][0][RTW89_CHILE][13] = 127,
+ [1][0][2][0][RTW89_QATAR][13] = 127,
[1][1][2][0][RTW89_FCC][0] = 127,
[1][1][2][0][RTW89_ETSI][0] = 127,
[1][1][2][0][RTW89_MKK][0] = 127,
@@ -29890,6 +33434,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][0] = 127,
[1][1][2][0][RTW89_CN][0] = 127,
[1][1][2][0][RTW89_UK][0] = 127,
+ [1][1][2][0][RTW89_MEXICO][0] = 127,
+ [1][1][2][0][RTW89_UKRAINE][0] = 127,
+ [1][1][2][0][RTW89_CHILE][0] = 127,
+ [1][1][2][0][RTW89_QATAR][0] = 127,
[1][1][2][0][RTW89_FCC][1] = 127,
[1][1][2][0][RTW89_ETSI][1] = 127,
[1][1][2][0][RTW89_MKK][1] = 127,
@@ -29898,6 +33446,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][1] = 127,
[1][1][2][0][RTW89_CN][1] = 127,
[1][1][2][0][RTW89_UK][1] = 127,
+ [1][1][2][0][RTW89_MEXICO][1] = 127,
+ [1][1][2][0][RTW89_UKRAINE][1] = 127,
+ [1][1][2][0][RTW89_CHILE][1] = 127,
+ [1][1][2][0][RTW89_QATAR][1] = 127,
[1][1][2][0][RTW89_FCC][2] = 60,
[1][1][2][0][RTW89_ETSI][2] = 48,
[1][1][2][0][RTW89_MKK][2] = 68,
@@ -29906,6 +33458,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][2] = 48,
[1][1][2][0][RTW89_CN][2] = 34,
[1][1][2][0][RTW89_UK][2] = 48,
+ [1][1][2][0][RTW89_MEXICO][2] = 60,
+ [1][1][2][0][RTW89_UKRAINE][2] = 48,
+ [1][1][2][0][RTW89_CHILE][2] = 60,
+ [1][1][2][0][RTW89_QATAR][2] = 48,
[1][1][2][0][RTW89_FCC][3] = 60,
[1][1][2][0][RTW89_ETSI][3] = 48,
[1][1][2][0][RTW89_MKK][3] = 68,
@@ -29914,6 +33470,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][3] = 48,
[1][1][2][0][RTW89_CN][3] = 34,
[1][1][2][0][RTW89_UK][3] = 48,
+ [1][1][2][0][RTW89_MEXICO][3] = 60,
+ [1][1][2][0][RTW89_UKRAINE][3] = 48,
+ [1][1][2][0][RTW89_CHILE][3] = 56,
+ [1][1][2][0][RTW89_QATAR][3] = 48,
[1][1][2][0][RTW89_FCC][4] = 60,
[1][1][2][0][RTW89_ETSI][4] = 48,
[1][1][2][0][RTW89_MKK][4] = 68,
@@ -29922,6 +33482,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][4] = 48,
[1][1][2][0][RTW89_CN][4] = 34,
[1][1][2][0][RTW89_UK][4] = 48,
+ [1][1][2][0][RTW89_MEXICO][4] = 60,
+ [1][1][2][0][RTW89_UKRAINE][4] = 48,
+ [1][1][2][0][RTW89_CHILE][4] = 56,
+ [1][1][2][0][RTW89_QATAR][4] = 48,
[1][1][2][0][RTW89_FCC][5] = 60,
[1][1][2][0][RTW89_ETSI][5] = 48,
[1][1][2][0][RTW89_MKK][5] = 68,
@@ -29930,6 +33494,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][5] = 48,
[1][1][2][0][RTW89_CN][5] = 34,
[1][1][2][0][RTW89_UK][5] = 48,
+ [1][1][2][0][RTW89_MEXICO][5] = 60,
+ [1][1][2][0][RTW89_UKRAINE][5] = 48,
+ [1][1][2][0][RTW89_CHILE][5] = 60,
+ [1][1][2][0][RTW89_QATAR][5] = 48,
[1][1][2][0][RTW89_FCC][6] = 58,
[1][1][2][0][RTW89_ETSI][6] = 48,
[1][1][2][0][RTW89_MKK][6] = 68,
@@ -29938,6 +33506,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][6] = 48,
[1][1][2][0][RTW89_CN][6] = 34,
[1][1][2][0][RTW89_UK][6] = 48,
+ [1][1][2][0][RTW89_MEXICO][6] = 58,
+ [1][1][2][0][RTW89_UKRAINE][6] = 48,
+ [1][1][2][0][RTW89_CHILE][6] = 52,
+ [1][1][2][0][RTW89_QATAR][6] = 48,
[1][1][2][0][RTW89_FCC][7] = 54,
[1][1][2][0][RTW89_ETSI][7] = 48,
[1][1][2][0][RTW89_MKK][7] = 68,
@@ -29946,6 +33518,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][7] = 48,
[1][1][2][0][RTW89_CN][7] = 34,
[1][1][2][0][RTW89_UK][7] = 48,
+ [1][1][2][0][RTW89_MEXICO][7] = 54,
+ [1][1][2][0][RTW89_UKRAINE][7] = 48,
+ [1][1][2][0][RTW89_CHILE][7] = 52,
+ [1][1][2][0][RTW89_QATAR][7] = 48,
[1][1][2][0][RTW89_FCC][8] = 54,
[1][1][2][0][RTW89_ETSI][8] = 48,
[1][1][2][0][RTW89_MKK][8] = 68,
@@ -29954,6 +33530,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][8] = 48,
[1][1][2][0][RTW89_CN][8] = 34,
[1][1][2][0][RTW89_UK][8] = 48,
+ [1][1][2][0][RTW89_MEXICO][8] = 54,
+ [1][1][2][0][RTW89_UKRAINE][8] = 48,
+ [1][1][2][0][RTW89_CHILE][8] = 54,
+ [1][1][2][0][RTW89_QATAR][8] = 48,
[1][1][2][0][RTW89_FCC][9] = 54,
[1][1][2][0][RTW89_ETSI][9] = 48,
[1][1][2][0][RTW89_MKK][9] = 68,
@@ -29962,6 +33542,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][9] = 48,
[1][1][2][0][RTW89_CN][9] = 34,
[1][1][2][0][RTW89_UK][9] = 48,
+ [1][1][2][0][RTW89_MEXICO][9] = 54,
+ [1][1][2][0][RTW89_UKRAINE][9] = 48,
+ [1][1][2][0][RTW89_CHILE][9] = 54,
+ [1][1][2][0][RTW89_QATAR][9] = 48,
[1][1][2][0][RTW89_FCC][10] = 46,
[1][1][2][0][RTW89_ETSI][10] = 48,
[1][1][2][0][RTW89_MKK][10] = 68,
@@ -29970,6 +33554,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][10] = 48,
[1][1][2][0][RTW89_CN][10] = 34,
[1][1][2][0][RTW89_UK][10] = 48,
+ [1][1][2][0][RTW89_MEXICO][10] = 46,
+ [1][1][2][0][RTW89_UKRAINE][10] = 48,
+ [1][1][2][0][RTW89_CHILE][10] = 46,
+ [1][1][2][0][RTW89_QATAR][10] = 48,
[1][1][2][0][RTW89_FCC][11] = 127,
[1][1][2][0][RTW89_ETSI][11] = 127,
[1][1][2][0][RTW89_MKK][11] = 127,
@@ -29978,6 +33566,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][11] = 127,
[1][1][2][0][RTW89_CN][11] = 127,
[1][1][2][0][RTW89_UK][11] = 127,
+ [1][1][2][0][RTW89_MEXICO][11] = 127,
+ [1][1][2][0][RTW89_UKRAINE][11] = 127,
+ [1][1][2][0][RTW89_CHILE][11] = 127,
+ [1][1][2][0][RTW89_QATAR][11] = 127,
[1][1][2][0][RTW89_FCC][12] = 127,
[1][1][2][0][RTW89_ETSI][12] = 127,
[1][1][2][0][RTW89_MKK][12] = 127,
@@ -29986,6 +33578,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][12] = 127,
[1][1][2][0][RTW89_CN][12] = 127,
[1][1][2][0][RTW89_UK][12] = 127,
+ [1][1][2][0][RTW89_MEXICO][12] = 127,
+ [1][1][2][0][RTW89_UKRAINE][12] = 127,
+ [1][1][2][0][RTW89_CHILE][12] = 127,
+ [1][1][2][0][RTW89_QATAR][12] = 127,
[1][1][2][0][RTW89_FCC][13] = 127,
[1][1][2][0][RTW89_ETSI][13] = 127,
[1][1][2][0][RTW89_MKK][13] = 127,
@@ -29994,6 +33590,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][13] = 127,
[1][1][2][0][RTW89_CN][13] = 127,
[1][1][2][0][RTW89_UK][13] = 127,
+ [1][1][2][0][RTW89_MEXICO][13] = 127,
+ [1][1][2][0][RTW89_UKRAINE][13] = 127,
+ [1][1][2][0][RTW89_CHILE][13] = 127,
+ [1][1][2][0][RTW89_QATAR][13] = 127,
[1][1][2][1][RTW89_FCC][0] = 127,
[1][1][2][1][RTW89_ETSI][0] = 127,
[1][1][2][1][RTW89_MKK][0] = 127,
@@ -30002,6 +33602,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][0] = 127,
[1][1][2][1][RTW89_CN][0] = 127,
[1][1][2][1][RTW89_UK][0] = 127,
+ [1][1][2][1][RTW89_MEXICO][0] = 127,
+ [1][1][2][1][RTW89_UKRAINE][0] = 127,
+ [1][1][2][1][RTW89_CHILE][0] = 127,
+ [1][1][2][1][RTW89_QATAR][0] = 127,
[1][1][2][1][RTW89_FCC][1] = 127,
[1][1][2][1][RTW89_ETSI][1] = 127,
[1][1][2][1][RTW89_MKK][1] = 127,
@@ -30010,6 +33614,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][1] = 127,
[1][1][2][1][RTW89_CN][1] = 127,
[1][1][2][1][RTW89_UK][1] = 127,
+ [1][1][2][1][RTW89_MEXICO][1] = 127,
+ [1][1][2][1][RTW89_UKRAINE][1] = 127,
+ [1][1][2][1][RTW89_CHILE][1] = 127,
+ [1][1][2][1][RTW89_QATAR][1] = 127,
[1][1][2][1][RTW89_FCC][2] = 60,
[1][1][2][1][RTW89_ETSI][2] = 36,
[1][1][2][1][RTW89_MKK][2] = 68,
@@ -30018,6 +33626,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][2] = 36,
[1][1][2][1][RTW89_CN][2] = 34,
[1][1][2][1][RTW89_UK][2] = 36,
+ [1][1][2][1][RTW89_MEXICO][2] = 60,
+ [1][1][2][1][RTW89_UKRAINE][2] = 36,
+ [1][1][2][1][RTW89_CHILE][2] = 60,
+ [1][1][2][1][RTW89_QATAR][2] = 36,
[1][1][2][1][RTW89_FCC][3] = 60,
[1][1][2][1][RTW89_ETSI][3] = 36,
[1][1][2][1][RTW89_MKK][3] = 68,
@@ -30026,6 +33638,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][3] = 36,
[1][1][2][1][RTW89_CN][3] = 34,
[1][1][2][1][RTW89_UK][3] = 36,
+ [1][1][2][1][RTW89_MEXICO][3] = 60,
+ [1][1][2][1][RTW89_UKRAINE][3] = 36,
+ [1][1][2][1][RTW89_CHILE][3] = 44,
+ [1][1][2][1][RTW89_QATAR][3] = 36,
[1][1][2][1][RTW89_FCC][4] = 60,
[1][1][2][1][RTW89_ETSI][4] = 36,
[1][1][2][1][RTW89_MKK][4] = 68,
@@ -30034,6 +33650,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][4] = 36,
[1][1][2][1][RTW89_CN][4] = 34,
[1][1][2][1][RTW89_UK][4] = 36,
+ [1][1][2][1][RTW89_MEXICO][4] = 60,
+ [1][1][2][1][RTW89_UKRAINE][4] = 36,
+ [1][1][2][1][RTW89_CHILE][4] = 44,
+ [1][1][2][1][RTW89_QATAR][4] = 36,
[1][1][2][1][RTW89_FCC][5] = 60,
[1][1][2][1][RTW89_ETSI][5] = 36,
[1][1][2][1][RTW89_MKK][5] = 68,
@@ -30042,6 +33662,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][5] = 36,
[1][1][2][1][RTW89_CN][5] = 34,
[1][1][2][1][RTW89_UK][5] = 36,
+ [1][1][2][1][RTW89_MEXICO][5] = 60,
+ [1][1][2][1][RTW89_UKRAINE][5] = 36,
+ [1][1][2][1][RTW89_CHILE][5] = 60,
+ [1][1][2][1][RTW89_QATAR][5] = 36,
[1][1][2][1][RTW89_FCC][6] = 58,
[1][1][2][1][RTW89_ETSI][6] = 36,
[1][1][2][1][RTW89_MKK][6] = 68,
@@ -30050,6 +33674,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][6] = 36,
[1][1][2][1][RTW89_CN][6] = 34,
[1][1][2][1][RTW89_UK][6] = 36,
+ [1][1][2][1][RTW89_MEXICO][6] = 58,
+ [1][1][2][1][RTW89_UKRAINE][6] = 36,
+ [1][1][2][1][RTW89_CHILE][6] = 40,
+ [1][1][2][1][RTW89_QATAR][6] = 36,
[1][1][2][1][RTW89_FCC][7] = 54,
[1][1][2][1][RTW89_ETSI][7] = 36,
[1][1][2][1][RTW89_MKK][7] = 68,
@@ -30058,6 +33686,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][7] = 36,
[1][1][2][1][RTW89_CN][7] = 34,
[1][1][2][1][RTW89_UK][7] = 36,
+ [1][1][2][1][RTW89_MEXICO][7] = 54,
+ [1][1][2][1][RTW89_UKRAINE][7] = 36,
+ [1][1][2][1][RTW89_CHILE][7] = 40,
+ [1][1][2][1][RTW89_QATAR][7] = 36,
[1][1][2][1][RTW89_FCC][8] = 54,
[1][1][2][1][RTW89_ETSI][8] = 36,
[1][1][2][1][RTW89_MKK][8] = 68,
@@ -30066,6 +33698,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][8] = 36,
[1][1][2][1][RTW89_CN][8] = 34,
[1][1][2][1][RTW89_UK][8] = 36,
+ [1][1][2][1][RTW89_MEXICO][8] = 54,
+ [1][1][2][1][RTW89_UKRAINE][8] = 36,
+ [1][1][2][1][RTW89_CHILE][8] = 54,
+ [1][1][2][1][RTW89_QATAR][8] = 36,
[1][1][2][1][RTW89_FCC][9] = 54,
[1][1][2][1][RTW89_ETSI][9] = 36,
[1][1][2][1][RTW89_MKK][9] = 68,
@@ -30074,6 +33710,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][9] = 36,
[1][1][2][1][RTW89_CN][9] = 34,
[1][1][2][1][RTW89_UK][9] = 36,
+ [1][1][2][1][RTW89_MEXICO][9] = 54,
+ [1][1][2][1][RTW89_UKRAINE][9] = 36,
+ [1][1][2][1][RTW89_CHILE][9] = 54,
+ [1][1][2][1][RTW89_QATAR][9] = 36,
[1][1][2][1][RTW89_FCC][10] = 46,
[1][1][2][1][RTW89_ETSI][10] = 36,
[1][1][2][1][RTW89_MKK][10] = 68,
@@ -30082,6 +33722,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][10] = 36,
[1][1][2][1][RTW89_CN][10] = 36,
[1][1][2][1][RTW89_UK][10] = 36,
+ [1][1][2][1][RTW89_MEXICO][10] = 46,
+ [1][1][2][1][RTW89_UKRAINE][10] = 36,
+ [1][1][2][1][RTW89_CHILE][10] = 46,
+ [1][1][2][1][RTW89_QATAR][10] = 36,
[1][1][2][1][RTW89_FCC][11] = 127,
[1][1][2][1][RTW89_ETSI][11] = 127,
[1][1][2][1][RTW89_MKK][11] = 127,
@@ -30090,6 +33734,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][11] = 127,
[1][1][2][1][RTW89_CN][11] = 127,
[1][1][2][1][RTW89_UK][11] = 127,
+ [1][1][2][1][RTW89_MEXICO][11] = 127,
+ [1][1][2][1][RTW89_UKRAINE][11] = 127,
+ [1][1][2][1][RTW89_CHILE][11] = 127,
+ [1][1][2][1][RTW89_QATAR][11] = 127,
[1][1][2][1][RTW89_FCC][12] = 127,
[1][1][2][1][RTW89_ETSI][12] = 127,
[1][1][2][1][RTW89_MKK][12] = 127,
@@ -30098,6 +33746,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][12] = 127,
[1][1][2][1][RTW89_CN][12] = 127,
[1][1][2][1][RTW89_UK][12] = 127,
+ [1][1][2][1][RTW89_MEXICO][12] = 127,
+ [1][1][2][1][RTW89_UKRAINE][12] = 127,
+ [1][1][2][1][RTW89_CHILE][12] = 127,
+ [1][1][2][1][RTW89_QATAR][12] = 127,
[1][1][2][1][RTW89_FCC][13] = 127,
[1][1][2][1][RTW89_ETSI][13] = 127,
[1][1][2][1][RTW89_MKK][13] = 127,
@@ -30106,6 +33758,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][13] = 127,
[1][1][2][1][RTW89_CN][13] = 127,
[1][1][2][1][RTW89_UK][13] = 127,
+ [1][1][2][1][RTW89_MEXICO][13] = 127,
+ [1][1][2][1][RTW89_UKRAINE][13] = 127,
+ [1][1][2][1][RTW89_CHILE][13] = 127,
+ [1][1][2][1][RTW89_QATAR][13] = 127,
};
static
@@ -30120,17 +33776,17 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_WW][10] = 50,
[0][0][1][0][RTW89_WW][12] = 50,
[0][0][1][0][RTW89_WW][14] = 50,
- [0][0][1][0][RTW89_WW][15] = 66,
- [0][0][1][0][RTW89_WW][17] = 66,
- [0][0][1][0][RTW89_WW][19] = 66,
- [0][0][1][0][RTW89_WW][21] = 66,
- [0][0][1][0][RTW89_WW][23] = 66,
- [0][0][1][0][RTW89_WW][25] = 66,
- [0][0][1][0][RTW89_WW][27] = 66,
- [0][0][1][0][RTW89_WW][29] = 66,
- [0][0][1][0][RTW89_WW][31] = 66,
- [0][0][1][0][RTW89_WW][33] = 66,
- [0][0][1][0][RTW89_WW][35] = 60,
+ [0][0][1][0][RTW89_WW][15] = 54,
+ [0][0][1][0][RTW89_WW][17] = 54,
+ [0][0][1][0][RTW89_WW][19] = 54,
+ [0][0][1][0][RTW89_WW][21] = 54,
+ [0][0][1][0][RTW89_WW][23] = 54,
+ [0][0][1][0][RTW89_WW][25] = 54,
+ [0][0][1][0][RTW89_WW][27] = 54,
+ [0][0][1][0][RTW89_WW][29] = 54,
+ [0][0][1][0][RTW89_WW][31] = 54,
+ [0][0][1][0][RTW89_WW][33] = 54,
+ [0][0][1][0][RTW89_WW][35] = 54,
[0][0][1][0][RTW89_WW][37] = 64,
[0][0][1][0][RTW89_WW][38] = 30,
[0][0][1][0][RTW89_WW][40] = 30,
@@ -30144,21 +33800,21 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_WW][2] = 34,
[0][1][1][0][RTW89_WW][4] = 34,
[0][1][1][0][RTW89_WW][6] = 36,
- [0][1][1][0][RTW89_WW][8] = 46,
- [0][1][1][0][RTW89_WW][10] = 46,
- [0][1][1][0][RTW89_WW][12] = 46,
- [0][1][1][0][RTW89_WW][14] = 46,
- [0][1][1][0][RTW89_WW][15] = 54,
- [0][1][1][0][RTW89_WW][17] = 54,
- [0][1][1][0][RTW89_WW][19] = 54,
- [0][1][1][0][RTW89_WW][21] = 54,
- [0][1][1][0][RTW89_WW][23] = 54,
- [0][1][1][0][RTW89_WW][25] = 54,
- [0][1][1][0][RTW89_WW][27] = 54,
- [0][1][1][0][RTW89_WW][29] = 54,
- [0][1][1][0][RTW89_WW][31] = 54,
- [0][1][1][0][RTW89_WW][33] = 54,
- [0][1][1][0][RTW89_WW][35] = 52,
+ [0][1][1][0][RTW89_WW][8] = 42,
+ [0][1][1][0][RTW89_WW][10] = 42,
+ [0][1][1][0][RTW89_WW][12] = 42,
+ [0][1][1][0][RTW89_WW][14] = 42,
+ [0][1][1][0][RTW89_WW][15] = 42,
+ [0][1][1][0][RTW89_WW][17] = 42,
+ [0][1][1][0][RTW89_WW][19] = 42,
+ [0][1][1][0][RTW89_WW][21] = 42,
+ [0][1][1][0][RTW89_WW][23] = 42,
+ [0][1][1][0][RTW89_WW][25] = 42,
+ [0][1][1][0][RTW89_WW][27] = 42,
+ [0][1][1][0][RTW89_WW][29] = 42,
+ [0][1][1][0][RTW89_WW][31] = 42,
+ [0][1][1][0][RTW89_WW][33] = 42,
+ [0][1][1][0][RTW89_WW][35] = 42,
[0][1][1][0][RTW89_WW][37] = 52,
[0][1][1][0][RTW89_WW][38] = 18,
[0][1][1][0][RTW89_WW][40] = 18,
@@ -30176,17 +33832,17 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_WW][10] = 52,
[0][0][2][0][RTW89_WW][12] = 52,
[0][0][2][0][RTW89_WW][14] = 52,
- [0][0][2][0][RTW89_WW][15] = 66,
- [0][0][2][0][RTW89_WW][17] = 66,
- [0][0][2][0][RTW89_WW][19] = 66,
- [0][0][2][0][RTW89_WW][21] = 66,
- [0][0][2][0][RTW89_WW][23] = 66,
- [0][0][2][0][RTW89_WW][25] = 66,
- [0][0][2][0][RTW89_WW][27] = 66,
- [0][0][2][0][RTW89_WW][29] = 66,
- [0][0][2][0][RTW89_WW][31] = 66,
- [0][0][2][0][RTW89_WW][33] = 66,
- [0][0][2][0][RTW89_WW][35] = 56,
+ [0][0][2][0][RTW89_WW][15] = 54,
+ [0][0][2][0][RTW89_WW][17] = 54,
+ [0][0][2][0][RTW89_WW][19] = 54,
+ [0][0][2][0][RTW89_WW][21] = 54,
+ [0][0][2][0][RTW89_WW][23] = 54,
+ [0][0][2][0][RTW89_WW][25] = 54,
+ [0][0][2][0][RTW89_WW][27] = 54,
+ [0][0][2][0][RTW89_WW][29] = 54,
+ [0][0][2][0][RTW89_WW][31] = 54,
+ [0][0][2][0][RTW89_WW][33] = 54,
+ [0][0][2][0][RTW89_WW][35] = 54,
[0][0][2][0][RTW89_WW][37] = 64,
[0][0][2][0][RTW89_WW][38] = 30,
[0][0][2][0][RTW89_WW][40] = 30,
@@ -30204,17 +33860,17 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_WW][10] = 40,
[0][1][2][0][RTW89_WW][12] = 40,
[0][1][2][0][RTW89_WW][14] = 40,
- [0][1][2][0][RTW89_WW][15] = 54,
- [0][1][2][0][RTW89_WW][17] = 54,
- [0][1][2][0][RTW89_WW][19] = 54,
- [0][1][2][0][RTW89_WW][21] = 54,
- [0][1][2][0][RTW89_WW][23] = 54,
- [0][1][2][0][RTW89_WW][25] = 54,
- [0][1][2][0][RTW89_WW][27] = 54,
- [0][1][2][0][RTW89_WW][29] = 54,
- [0][1][2][0][RTW89_WW][31] = 54,
- [0][1][2][0][RTW89_WW][33] = 54,
- [0][1][2][0][RTW89_WW][35] = 46,
+ [0][1][2][0][RTW89_WW][15] = 42,
+ [0][1][2][0][RTW89_WW][17] = 42,
+ [0][1][2][0][RTW89_WW][19] = 42,
+ [0][1][2][0][RTW89_WW][21] = 42,
+ [0][1][2][0][RTW89_WW][23] = 42,
+ [0][1][2][0][RTW89_WW][25] = 42,
+ [0][1][2][0][RTW89_WW][27] = 42,
+ [0][1][2][0][RTW89_WW][29] = 42,
+ [0][1][2][0][RTW89_WW][31] = 42,
+ [0][1][2][0][RTW89_WW][33] = 42,
+ [0][1][2][0][RTW89_WW][35] = 42,
[0][1][2][0][RTW89_WW][37] = 52,
[0][1][2][0][RTW89_WW][38] = 18,
[0][1][2][0][RTW89_WW][40] = 18,
@@ -30224,25 +33880,25 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_WW][48] = 48,
[0][1][2][0][RTW89_WW][50] = 50,
[0][1][2][0][RTW89_WW][52] = 48,
- [0][1][2][1][RTW89_WW][0] = 36,
- [0][1][2][1][RTW89_WW][2] = 36,
- [0][1][2][1][RTW89_WW][4] = 36,
- [0][1][2][1][RTW89_WW][6] = 36,
- [0][1][2][1][RTW89_WW][8] = 36,
- [0][1][2][1][RTW89_WW][10] = 36,
- [0][1][2][1][RTW89_WW][12] = 36,
- [0][1][2][1][RTW89_WW][14] = 36,
- [0][1][2][1][RTW89_WW][15] = 40,
- [0][1][2][1][RTW89_WW][17] = 40,
- [0][1][2][1][RTW89_WW][19] = 40,
- [0][1][2][1][RTW89_WW][21] = 40,
- [0][1][2][1][RTW89_WW][23] = 40,
- [0][1][2][1][RTW89_WW][25] = 40,
- [0][1][2][1][RTW89_WW][27] = 40,
- [0][1][2][1][RTW89_WW][29] = 40,
- [0][1][2][1][RTW89_WW][31] = 40,
- [0][1][2][1][RTW89_WW][33] = 40,
- [0][1][2][1][RTW89_WW][35] = 40,
+ [0][1][2][1][RTW89_WW][0] = 30,
+ [0][1][2][1][RTW89_WW][2] = 30,
+ [0][1][2][1][RTW89_WW][4] = 30,
+ [0][1][2][1][RTW89_WW][6] = 30,
+ [0][1][2][1][RTW89_WW][8] = 30,
+ [0][1][2][1][RTW89_WW][10] = 30,
+ [0][1][2][1][RTW89_WW][12] = 30,
+ [0][1][2][1][RTW89_WW][14] = 30,
+ [0][1][2][1][RTW89_WW][15] = 30,
+ [0][1][2][1][RTW89_WW][17] = 30,
+ [0][1][2][1][RTW89_WW][19] = 30,
+ [0][1][2][1][RTW89_WW][21] = 30,
+ [0][1][2][1][RTW89_WW][23] = 30,
+ [0][1][2][1][RTW89_WW][25] = 30,
+ [0][1][2][1][RTW89_WW][27] = 30,
+ [0][1][2][1][RTW89_WW][29] = 30,
+ [0][1][2][1][RTW89_WW][31] = 30,
+ [0][1][2][1][RTW89_WW][33] = 30,
+ [0][1][2][1][RTW89_WW][35] = 30,
[0][1][2][1][RTW89_WW][37] = 40,
[0][1][2][1][RTW89_WW][38] = 6,
[0][1][2][1][RTW89_WW][40] = 6,
@@ -30256,11 +33912,11 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_WW][5] = 54,
[1][0][2][0][RTW89_WW][9] = 54,
[1][0][2][0][RTW89_WW][13] = 52,
- [1][0][2][0][RTW89_WW][16] = 56,
- [1][0][2][0][RTW89_WW][20] = 56,
- [1][0][2][0][RTW89_WW][24] = 56,
- [1][0][2][0][RTW89_WW][28] = 66,
- [1][0][2][0][RTW89_WW][32] = 62,
+ [1][0][2][0][RTW89_WW][16] = 54,
+ [1][0][2][0][RTW89_WW][20] = 54,
+ [1][0][2][0][RTW89_WW][24] = 54,
+ [1][0][2][0][RTW89_WW][28] = 54,
+ [1][0][2][0][RTW89_WW][32] = 54,
[1][0][2][0][RTW89_WW][36] = 64,
[1][0][2][0][RTW89_WW][39] = 30,
[1][0][2][0][RTW89_WW][43] = 30,
@@ -30270,25 +33926,25 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_WW][5] = 42,
[1][1][2][0][RTW89_WW][9] = 42,
[1][1][2][0][RTW89_WW][13] = 42,
- [1][1][2][0][RTW89_WW][16] = 54,
- [1][1][2][0][RTW89_WW][20] = 54,
- [1][1][2][0][RTW89_WW][24] = 54,
- [1][1][2][0][RTW89_WW][28] = 54,
- [1][1][2][0][RTW89_WW][32] = 54,
+ [1][1][2][0][RTW89_WW][16] = 42,
+ [1][1][2][0][RTW89_WW][20] = 42,
+ [1][1][2][0][RTW89_WW][24] = 42,
+ [1][1][2][0][RTW89_WW][28] = 42,
+ [1][1][2][0][RTW89_WW][32] = 42,
[1][1][2][0][RTW89_WW][36] = 52,
[1][1][2][0][RTW89_WW][39] = 18,
[1][1][2][0][RTW89_WW][43] = 18,
[1][1][2][0][RTW89_WW][47] = 62,
[1][1][2][0][RTW89_WW][51] = 60,
- [1][1][2][1][RTW89_WW][1] = 40,
- [1][1][2][1][RTW89_WW][5] = 40,
- [1][1][2][1][RTW89_WW][9] = 40,
- [1][1][2][1][RTW89_WW][13] = 40,
- [1][1][2][1][RTW89_WW][16] = 40,
- [1][1][2][1][RTW89_WW][20] = 40,
- [1][1][2][1][RTW89_WW][24] = 40,
- [1][1][2][1][RTW89_WW][28] = 40,
- [1][1][2][1][RTW89_WW][32] = 40,
+ [1][1][2][1][RTW89_WW][1] = 30,
+ [1][1][2][1][RTW89_WW][5] = 30,
+ [1][1][2][1][RTW89_WW][9] = 30,
+ [1][1][2][1][RTW89_WW][13] = 30,
+ [1][1][2][1][RTW89_WW][16] = 30,
+ [1][1][2][1][RTW89_WW][20] = 30,
+ [1][1][2][1][RTW89_WW][24] = 30,
+ [1][1][2][1][RTW89_WW][28] = 30,
+ [1][1][2][1][RTW89_WW][32] = 30,
[1][1][2][1][RTW89_WW][36] = 40,
[1][1][2][1][RTW89_WW][39] = 6,
[1][1][2][1][RTW89_WW][43] = 6,
@@ -30296,22 +33952,22 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_WW][51] = 60,
[2][0][2][0][RTW89_WW][3] = 54,
[2][0][2][0][RTW89_WW][11] = 50,
- [2][0][2][0][RTW89_WW][18] = 56,
- [2][0][2][0][RTW89_WW][26] = 60,
+ [2][0][2][0][RTW89_WW][18] = 54,
+ [2][0][2][0][RTW89_WW][26] = 54,
[2][0][2][0][RTW89_WW][34] = 60,
[2][0][2][0][RTW89_WW][41] = 30,
[2][0][2][0][RTW89_WW][49] = 62,
- [2][1][2][0][RTW89_WW][3] = 46,
+ [2][1][2][0][RTW89_WW][3] = 42,
[2][1][2][0][RTW89_WW][11] = 38,
- [2][1][2][0][RTW89_WW][18] = 50,
- [2][1][2][0][RTW89_WW][26] = 52,
+ [2][1][2][0][RTW89_WW][18] = 42,
+ [2][1][2][0][RTW89_WW][26] = 42,
[2][1][2][0][RTW89_WW][34] = 52,
[2][1][2][0][RTW89_WW][41] = 18,
[2][1][2][0][RTW89_WW][49] = 62,
- [2][1][2][1][RTW89_WW][3] = 40,
- [2][1][2][1][RTW89_WW][11] = 38,
- [2][1][2][1][RTW89_WW][18] = 40,
- [2][1][2][1][RTW89_WW][26] = 42,
+ [2][1][2][1][RTW89_WW][3] = 30,
+ [2][1][2][1][RTW89_WW][11] = 30,
+ [2][1][2][1][RTW89_WW][18] = 30,
+ [2][1][2][1][RTW89_WW][26] = 30,
[2][1][2][1][RTW89_WW][34] = 40,
[2][1][2][1][RTW89_WW][41] = 6,
[2][1][2][1][RTW89_WW][49] = 62,
@@ -30328,34 +33984,50 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ETSI][0] = 66,
[0][0][1][0][RTW89_MKK][0] = 66,
[0][0][1][0][RTW89_IC][0] = 60,
- [0][0][1][0][RTW89_KCC][0] = 52,
+ [0][0][1][0][RTW89_KCC][0] = 62,
[0][0][1][0][RTW89_ACMA][0] = 66,
[0][0][1][0][RTW89_CN][0] = 50,
[0][0][1][0][RTW89_UK][0] = 66,
+ [0][0][1][0][RTW89_MEXICO][0] = 62,
+ [0][0][1][0][RTW89_UKRAINE][0] = 54,
+ [0][0][1][0][RTW89_CHILE][0] = 70,
+ [0][0][1][0][RTW89_QATAR][0] = 66,
[0][0][1][0][RTW89_FCC][2] = 72,
[0][0][1][0][RTW89_ETSI][2] = 66,
[0][0][1][0][RTW89_MKK][2] = 66,
[0][0][1][0][RTW89_IC][2] = 60,
- [0][0][1][0][RTW89_KCC][2] = 52,
+ [0][0][1][0][RTW89_KCC][2] = 62,
[0][0][1][0][RTW89_ACMA][2] = 66,
[0][0][1][0][RTW89_CN][2] = 50,
[0][0][1][0][RTW89_UK][2] = 66,
+ [0][0][1][0][RTW89_MEXICO][2] = 62,
+ [0][0][1][0][RTW89_UKRAINE][2] = 54,
+ [0][0][1][0][RTW89_CHILE][2] = 70,
+ [0][0][1][0][RTW89_QATAR][2] = 66,
[0][0][1][0][RTW89_FCC][4] = 72,
[0][0][1][0][RTW89_ETSI][4] = 66,
[0][0][1][0][RTW89_MKK][4] = 66,
[0][0][1][0][RTW89_IC][4] = 60,
- [0][0][1][0][RTW89_KCC][4] = 52,
+ [0][0][1][0][RTW89_KCC][4] = 62,
[0][0][1][0][RTW89_ACMA][4] = 66,
[0][0][1][0][RTW89_CN][4] = 50,
[0][0][1][0][RTW89_UK][4] = 66,
+ [0][0][1][0][RTW89_MEXICO][4] = 62,
+ [0][0][1][0][RTW89_UKRAINE][4] = 54,
+ [0][0][1][0][RTW89_CHILE][4] = 70,
+ [0][0][1][0][RTW89_QATAR][4] = 66,
[0][0][1][0][RTW89_FCC][6] = 72,
[0][0][1][0][RTW89_ETSI][6] = 66,
[0][0][1][0][RTW89_MKK][6] = 66,
[0][0][1][0][RTW89_IC][6] = 58,
- [0][0][1][0][RTW89_KCC][6] = 62,
+ [0][0][1][0][RTW89_KCC][6] = 52,
[0][0][1][0][RTW89_ACMA][6] = 66,
[0][0][1][0][RTW89_CN][6] = 50,
[0][0][1][0][RTW89_UK][6] = 66,
+ [0][0][1][0][RTW89_MEXICO][6] = 62,
+ [0][0][1][0][RTW89_UKRAINE][6] = 54,
+ [0][0][1][0][RTW89_CHILE][6] = 70,
+ [0][0][1][0][RTW89_QATAR][6] = 66,
[0][0][1][0][RTW89_FCC][8] = 72,
[0][0][1][0][RTW89_ETSI][8] = 66,
[0][0][1][0][RTW89_MKK][8] = 66,
@@ -30364,6 +34036,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][8] = 66,
[0][0][1][0][RTW89_CN][8] = 50,
[0][0][1][0][RTW89_UK][8] = 66,
+ [0][0][1][0][RTW89_MEXICO][8] = 72,
+ [0][0][1][0][RTW89_UKRAINE][8] = 54,
+ [0][0][1][0][RTW89_CHILE][8] = 70,
+ [0][0][1][0][RTW89_QATAR][8] = 66,
[0][0][1][0][RTW89_FCC][10] = 72,
[0][0][1][0][RTW89_ETSI][10] = 66,
[0][0][1][0][RTW89_MKK][10] = 66,
@@ -30372,6 +34048,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][10] = 66,
[0][0][1][0][RTW89_CN][10] = 50,
[0][0][1][0][RTW89_UK][10] = 66,
+ [0][0][1][0][RTW89_MEXICO][10] = 72,
+ [0][0][1][0][RTW89_UKRAINE][10] = 54,
+ [0][0][1][0][RTW89_CHILE][10] = 70,
+ [0][0][1][0][RTW89_QATAR][10] = 66,
[0][0][1][0][RTW89_FCC][12] = 72,
[0][0][1][0][RTW89_ETSI][12] = 66,
[0][0][1][0][RTW89_MKK][12] = 66,
@@ -30380,6 +34060,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][12] = 66,
[0][0][1][0][RTW89_CN][12] = 50,
[0][0][1][0][RTW89_UK][12] = 66,
+ [0][0][1][0][RTW89_MEXICO][12] = 72,
+ [0][0][1][0][RTW89_UKRAINE][12] = 54,
+ [0][0][1][0][RTW89_CHILE][12] = 70,
+ [0][0][1][0][RTW89_QATAR][12] = 66,
[0][0][1][0][RTW89_FCC][14] = 70,
[0][0][1][0][RTW89_ETSI][14] = 66,
[0][0][1][0][RTW89_MKK][14] = 66,
@@ -30388,6 +34072,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][14] = 66,
[0][0][1][0][RTW89_CN][14] = 50,
[0][0][1][0][RTW89_UK][14] = 66,
+ [0][0][1][0][RTW89_MEXICO][14] = 70,
+ [0][0][1][0][RTW89_UKRAINE][14] = 54,
+ [0][0][1][0][RTW89_CHILE][14] = 68,
+ [0][0][1][0][RTW89_QATAR][14] = 66,
[0][0][1][0][RTW89_FCC][15] = 72,
[0][0][1][0][RTW89_ETSI][15] = 66,
[0][0][1][0][RTW89_MKK][15] = 70,
@@ -30396,6 +34084,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][15] = 66,
[0][0][1][0][RTW89_CN][15] = 127,
[0][0][1][0][RTW89_UK][15] = 66,
+ [0][0][1][0][RTW89_MEXICO][15] = 72,
+ [0][0][1][0][RTW89_UKRAINE][15] = 54,
+ [0][0][1][0][RTW89_CHILE][15] = 70,
+ [0][0][1][0][RTW89_QATAR][15] = 66,
[0][0][1][0][RTW89_FCC][17] = 72,
[0][0][1][0][RTW89_ETSI][17] = 66,
[0][0][1][0][RTW89_MKK][17] = 70,
@@ -30404,6 +34096,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][17] = 66,
[0][0][1][0][RTW89_CN][17] = 127,
[0][0][1][0][RTW89_UK][17] = 66,
+ [0][0][1][0][RTW89_MEXICO][17] = 72,
+ [0][0][1][0][RTW89_UKRAINE][17] = 54,
+ [0][0][1][0][RTW89_CHILE][17] = 70,
+ [0][0][1][0][RTW89_QATAR][17] = 66,
[0][0][1][0][RTW89_FCC][19] = 72,
[0][0][1][0][RTW89_ETSI][19] = 66,
[0][0][1][0][RTW89_MKK][19] = 70,
@@ -30412,6 +34108,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][19] = 66,
[0][0][1][0][RTW89_CN][19] = 127,
[0][0][1][0][RTW89_UK][19] = 66,
+ [0][0][1][0][RTW89_MEXICO][19] = 72,
+ [0][0][1][0][RTW89_UKRAINE][19] = 54,
+ [0][0][1][0][RTW89_CHILE][19] = 70,
+ [0][0][1][0][RTW89_QATAR][19] = 66,
[0][0][1][0][RTW89_FCC][21] = 72,
[0][0][1][0][RTW89_ETSI][21] = 66,
[0][0][1][0][RTW89_MKK][21] = 70,
@@ -30420,6 +34120,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][21] = 66,
[0][0][1][0][RTW89_CN][21] = 127,
[0][0][1][0][RTW89_UK][21] = 66,
+ [0][0][1][0][RTW89_MEXICO][21] = 72,
+ [0][0][1][0][RTW89_UKRAINE][21] = 54,
+ [0][0][1][0][RTW89_CHILE][21] = 70,
+ [0][0][1][0][RTW89_QATAR][21] = 66,
[0][0][1][0][RTW89_FCC][23] = 72,
[0][0][1][0][RTW89_ETSI][23] = 66,
[0][0][1][0][RTW89_MKK][23] = 70,
@@ -30428,6 +34132,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][23] = 66,
[0][0][1][0][RTW89_CN][23] = 127,
[0][0][1][0][RTW89_UK][23] = 66,
+ [0][0][1][0][RTW89_MEXICO][23] = 72,
+ [0][0][1][0][RTW89_UKRAINE][23] = 54,
+ [0][0][1][0][RTW89_CHILE][23] = 70,
+ [0][0][1][0][RTW89_QATAR][23] = 66,
[0][0][1][0][RTW89_FCC][25] = 72,
[0][0][1][0][RTW89_ETSI][25] = 66,
[0][0][1][0][RTW89_MKK][25] = 70,
@@ -30436,6 +34144,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][25] = 127,
[0][0][1][0][RTW89_CN][25] = 127,
[0][0][1][0][RTW89_UK][25] = 66,
+ [0][0][1][0][RTW89_MEXICO][25] = 72,
+ [0][0][1][0][RTW89_UKRAINE][25] = 54,
+ [0][0][1][0][RTW89_CHILE][25] = 70,
+ [0][0][1][0][RTW89_QATAR][25] = 66,
[0][0][1][0][RTW89_FCC][27] = 72,
[0][0][1][0][RTW89_ETSI][27] = 66,
[0][0][1][0][RTW89_MKK][27] = 70,
@@ -30444,6 +34156,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][27] = 127,
[0][0][1][0][RTW89_CN][27] = 127,
[0][0][1][0][RTW89_UK][27] = 66,
+ [0][0][1][0][RTW89_MEXICO][27] = 72,
+ [0][0][1][0][RTW89_UKRAINE][27] = 54,
+ [0][0][1][0][RTW89_CHILE][27] = 58,
+ [0][0][1][0][RTW89_QATAR][27] = 66,
[0][0][1][0][RTW89_FCC][29] = 72,
[0][0][1][0][RTW89_ETSI][29] = 66,
[0][0][1][0][RTW89_MKK][29] = 70,
@@ -30452,6 +34168,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][29] = 127,
[0][0][1][0][RTW89_CN][29] = 127,
[0][0][1][0][RTW89_UK][29] = 66,
+ [0][0][1][0][RTW89_MEXICO][29] = 72,
+ [0][0][1][0][RTW89_UKRAINE][29] = 54,
+ [0][0][1][0][RTW89_CHILE][29] = 58,
+ [0][0][1][0][RTW89_QATAR][29] = 66,
[0][0][1][0][RTW89_FCC][31] = 72,
[0][0][1][0][RTW89_ETSI][31] = 66,
[0][0][1][0][RTW89_MKK][31] = 70,
@@ -30460,6 +34180,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][31] = 66,
[0][0][1][0][RTW89_CN][31] = 127,
[0][0][1][0][RTW89_UK][31] = 66,
+ [0][0][1][0][RTW89_MEXICO][31] = 72,
+ [0][0][1][0][RTW89_UKRAINE][31] = 54,
+ [0][0][1][0][RTW89_CHILE][31] = 58,
+ [0][0][1][0][RTW89_QATAR][31] = 66,
[0][0][1][0][RTW89_FCC][33] = 72,
[0][0][1][0][RTW89_ETSI][33] = 66,
[0][0][1][0][RTW89_MKK][33] = 70,
@@ -30468,6 +34192,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][33] = 66,
[0][0][1][0][RTW89_CN][33] = 127,
[0][0][1][0][RTW89_UK][33] = 66,
+ [0][0][1][0][RTW89_MEXICO][33] = 72,
+ [0][0][1][0][RTW89_UKRAINE][33] = 54,
+ [0][0][1][0][RTW89_CHILE][33] = 58,
+ [0][0][1][0][RTW89_QATAR][33] = 66,
[0][0][1][0][RTW89_FCC][35] = 60,
[0][0][1][0][RTW89_ETSI][35] = 66,
[0][0][1][0][RTW89_MKK][35] = 70,
@@ -30476,6 +34204,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][35] = 66,
[0][0][1][0][RTW89_CN][35] = 127,
[0][0][1][0][RTW89_UK][35] = 66,
+ [0][0][1][0][RTW89_MEXICO][35] = 60,
+ [0][0][1][0][RTW89_UKRAINE][35] = 54,
+ [0][0][1][0][RTW89_CHILE][35] = 58,
+ [0][0][1][0][RTW89_QATAR][35] = 66,
[0][0][1][0][RTW89_FCC][37] = 72,
[0][0][1][0][RTW89_ETSI][37] = 127,
[0][0][1][0][RTW89_MKK][37] = 70,
@@ -30484,6 +34216,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][37] = 70,
[0][0][1][0][RTW89_CN][37] = 127,
[0][0][1][0][RTW89_UK][37] = 64,
+ [0][0][1][0][RTW89_MEXICO][37] = 72,
+ [0][0][1][0][RTW89_UKRAINE][37] = 127,
+ [0][0][1][0][RTW89_CHILE][37] = 70,
+ [0][0][1][0][RTW89_QATAR][37] = 127,
[0][0][1][0][RTW89_FCC][38] = 72,
[0][0][1][0][RTW89_ETSI][38] = 30,
[0][0][1][0][RTW89_MKK][38] = 127,
@@ -30492,6 +34228,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][38] = 70,
[0][0][1][0][RTW89_CN][38] = 68,
[0][0][1][0][RTW89_UK][38] = 64,
+ [0][0][1][0][RTW89_MEXICO][38] = 72,
+ [0][0][1][0][RTW89_UKRAINE][38] = 30,
+ [0][0][1][0][RTW89_CHILE][38] = 70,
+ [0][0][1][0][RTW89_QATAR][38] = 30,
[0][0][1][0][RTW89_FCC][40] = 72,
[0][0][1][0][RTW89_ETSI][40] = 30,
[0][0][1][0][RTW89_MKK][40] = 127,
@@ -30500,6 +34240,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][40] = 70,
[0][0][1][0][RTW89_CN][40] = 68,
[0][0][1][0][RTW89_UK][40] = 64,
+ [0][0][1][0][RTW89_MEXICO][40] = 72,
+ [0][0][1][0][RTW89_UKRAINE][40] = 30,
+ [0][0][1][0][RTW89_CHILE][40] = 70,
+ [0][0][1][0][RTW89_QATAR][40] = 30,
[0][0][1][0][RTW89_FCC][42] = 72,
[0][0][1][0][RTW89_ETSI][42] = 30,
[0][0][1][0][RTW89_MKK][42] = 127,
@@ -30508,6 +34252,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][42] = 70,
[0][0][1][0][RTW89_CN][42] = 68,
[0][0][1][0][RTW89_UK][42] = 64,
+ [0][0][1][0][RTW89_MEXICO][42] = 72,
+ [0][0][1][0][RTW89_UKRAINE][42] = 30,
+ [0][0][1][0][RTW89_CHILE][42] = 70,
+ [0][0][1][0][RTW89_QATAR][42] = 30,
[0][0][1][0][RTW89_FCC][44] = 72,
[0][0][1][0][RTW89_ETSI][44] = 30,
[0][0][1][0][RTW89_MKK][44] = 127,
@@ -30516,6 +34264,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][44] = 70,
[0][0][1][0][RTW89_CN][44] = 68,
[0][0][1][0][RTW89_UK][44] = 64,
+ [0][0][1][0][RTW89_MEXICO][44] = 72,
+ [0][0][1][0][RTW89_UKRAINE][44] = 30,
+ [0][0][1][0][RTW89_CHILE][44] = 70,
+ [0][0][1][0][RTW89_QATAR][44] = 30,
[0][0][1][0][RTW89_FCC][46] = 72,
[0][0][1][0][RTW89_ETSI][46] = 30,
[0][0][1][0][RTW89_MKK][46] = 127,
@@ -30524,6 +34276,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][46] = 70,
[0][0][1][0][RTW89_CN][46] = 68,
[0][0][1][0][RTW89_UK][46] = 64,
+ [0][0][1][0][RTW89_MEXICO][46] = 72,
+ [0][0][1][0][RTW89_UKRAINE][46] = 30,
+ [0][0][1][0][RTW89_CHILE][46] = 70,
+ [0][0][1][0][RTW89_QATAR][46] = 30,
[0][0][1][0][RTW89_FCC][48] = 72,
[0][0][1][0][RTW89_ETSI][48] = 127,
[0][0][1][0][RTW89_MKK][48] = 127,
@@ -30532,6 +34288,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][48] = 127,
[0][0][1][0][RTW89_CN][48] = 127,
[0][0][1][0][RTW89_UK][48] = 127,
+ [0][0][1][0][RTW89_MEXICO][48] = 127,
+ [0][0][1][0][RTW89_UKRAINE][48] = 127,
+ [0][0][1][0][RTW89_CHILE][48] = 127,
+ [0][0][1][0][RTW89_QATAR][48] = 127,
[0][0][1][0][RTW89_FCC][50] = 72,
[0][0][1][0][RTW89_ETSI][50] = 127,
[0][0][1][0][RTW89_MKK][50] = 127,
@@ -30540,6 +34300,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][50] = 127,
[0][0][1][0][RTW89_CN][50] = 127,
[0][0][1][0][RTW89_UK][50] = 127,
+ [0][0][1][0][RTW89_MEXICO][50] = 127,
+ [0][0][1][0][RTW89_UKRAINE][50] = 127,
+ [0][0][1][0][RTW89_CHILE][50] = 127,
+ [0][0][1][0][RTW89_QATAR][50] = 127,
[0][0][1][0][RTW89_FCC][52] = 72,
[0][0][1][0][RTW89_ETSI][52] = 127,
[0][0][1][0][RTW89_MKK][52] = 127,
@@ -30548,38 +34312,58 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][52] = 127,
[0][0][1][0][RTW89_CN][52] = 127,
[0][0][1][0][RTW89_UK][52] = 127,
+ [0][0][1][0][RTW89_MEXICO][52] = 127,
+ [0][0][1][0][RTW89_UKRAINE][52] = 127,
+ [0][0][1][0][RTW89_CHILE][52] = 127,
+ [0][0][1][0][RTW89_QATAR][52] = 127,
[0][1][1][0][RTW89_FCC][0] = 60,
[0][1][1][0][RTW89_ETSI][0] = 54,
[0][1][1][0][RTW89_MKK][0] = 54,
[0][1][1][0][RTW89_IC][0] = 34,
- [0][1][1][0][RTW89_KCC][0] = 40,
+ [0][1][1][0][RTW89_KCC][0] = 60,
[0][1][1][0][RTW89_ACMA][0] = 54,
[0][1][1][0][RTW89_CN][0] = 46,
[0][1][1][0][RTW89_UK][0] = 54,
+ [0][1][1][0][RTW89_MEXICO][0] = 50,
+ [0][1][1][0][RTW89_UKRAINE][0] = 42,
+ [0][1][1][0][RTW89_CHILE][0] = 60,
+ [0][1][1][0][RTW89_QATAR][0] = 54,
[0][1][1][0][RTW89_FCC][2] = 60,
[0][1][1][0][RTW89_ETSI][2] = 54,
[0][1][1][0][RTW89_MKK][2] = 54,
[0][1][1][0][RTW89_IC][2] = 34,
- [0][1][1][0][RTW89_KCC][2] = 40,
+ [0][1][1][0][RTW89_KCC][2] = 60,
[0][1][1][0][RTW89_ACMA][2] = 54,
[0][1][1][0][RTW89_CN][2] = 46,
[0][1][1][0][RTW89_UK][2] = 54,
+ [0][1][1][0][RTW89_MEXICO][2] = 50,
+ [0][1][1][0][RTW89_UKRAINE][2] = 42,
+ [0][1][1][0][RTW89_CHILE][2] = 60,
+ [0][1][1][0][RTW89_QATAR][2] = 54,
[0][1][1][0][RTW89_FCC][4] = 60,
[0][1][1][0][RTW89_ETSI][4] = 54,
[0][1][1][0][RTW89_MKK][4] = 54,
[0][1][1][0][RTW89_IC][4] = 34,
- [0][1][1][0][RTW89_KCC][4] = 40,
+ [0][1][1][0][RTW89_KCC][4] = 60,
[0][1][1][0][RTW89_ACMA][4] = 54,
[0][1][1][0][RTW89_CN][4] = 46,
[0][1][1][0][RTW89_UK][4] = 54,
+ [0][1][1][0][RTW89_MEXICO][4] = 50,
+ [0][1][1][0][RTW89_UKRAINE][4] = 42,
+ [0][1][1][0][RTW89_CHILE][4] = 60,
+ [0][1][1][0][RTW89_QATAR][4] = 54,
[0][1][1][0][RTW89_FCC][6] = 60,
[0][1][1][0][RTW89_ETSI][6] = 54,
[0][1][1][0][RTW89_MKK][6] = 54,
[0][1][1][0][RTW89_IC][6] = 36,
- [0][1][1][0][RTW89_KCC][6] = 60,
+ [0][1][1][0][RTW89_KCC][6] = 40,
[0][1][1][0][RTW89_ACMA][6] = 54,
[0][1][1][0][RTW89_CN][6] = 46,
[0][1][1][0][RTW89_UK][6] = 54,
+ [0][1][1][0][RTW89_MEXICO][6] = 50,
+ [0][1][1][0][RTW89_UKRAINE][6] = 42,
+ [0][1][1][0][RTW89_CHILE][6] = 60,
+ [0][1][1][0][RTW89_QATAR][6] = 54,
[0][1][1][0][RTW89_FCC][8] = 62,
[0][1][1][0][RTW89_ETSI][8] = 54,
[0][1][1][0][RTW89_MKK][8] = 52,
@@ -30588,6 +34372,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][8] = 54,
[0][1][1][0][RTW89_CN][8] = 46,
[0][1][1][0][RTW89_UK][8] = 54,
+ [0][1][1][0][RTW89_MEXICO][8] = 62,
+ [0][1][1][0][RTW89_UKRAINE][8] = 42,
+ [0][1][1][0][RTW89_CHILE][8] = 62,
+ [0][1][1][0][RTW89_QATAR][8] = 54,
[0][1][1][0][RTW89_FCC][10] = 62,
[0][1][1][0][RTW89_ETSI][10] = 54,
[0][1][1][0][RTW89_MKK][10] = 54,
@@ -30596,6 +34384,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][10] = 54,
[0][1][1][0][RTW89_CN][10] = 46,
[0][1][1][0][RTW89_UK][10] = 54,
+ [0][1][1][0][RTW89_MEXICO][10] = 62,
+ [0][1][1][0][RTW89_UKRAINE][10] = 42,
+ [0][1][1][0][RTW89_CHILE][10] = 62,
+ [0][1][1][0][RTW89_QATAR][10] = 54,
[0][1][1][0][RTW89_FCC][12] = 62,
[0][1][1][0][RTW89_ETSI][12] = 54,
[0][1][1][0][RTW89_MKK][12] = 54,
@@ -30604,6 +34396,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][12] = 54,
[0][1][1][0][RTW89_CN][12] = 46,
[0][1][1][0][RTW89_UK][12] = 54,
+ [0][1][1][0][RTW89_MEXICO][12] = 62,
+ [0][1][1][0][RTW89_UKRAINE][12] = 42,
+ [0][1][1][0][RTW89_CHILE][12] = 62,
+ [0][1][1][0][RTW89_QATAR][12] = 54,
[0][1][1][0][RTW89_FCC][14] = 60,
[0][1][1][0][RTW89_ETSI][14] = 54,
[0][1][1][0][RTW89_MKK][14] = 54,
@@ -30612,6 +34408,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][14] = 54,
[0][1][1][0][RTW89_CN][14] = 46,
[0][1][1][0][RTW89_UK][14] = 54,
+ [0][1][1][0][RTW89_MEXICO][14] = 60,
+ [0][1][1][0][RTW89_UKRAINE][14] = 42,
+ [0][1][1][0][RTW89_CHILE][14] = 60,
+ [0][1][1][0][RTW89_QATAR][14] = 54,
[0][1][1][0][RTW89_FCC][15] = 60,
[0][1][1][0][RTW89_ETSI][15] = 54,
[0][1][1][0][RTW89_MKK][15] = 70,
@@ -30620,6 +34420,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][15] = 54,
[0][1][1][0][RTW89_CN][15] = 127,
[0][1][1][0][RTW89_UK][15] = 54,
+ [0][1][1][0][RTW89_MEXICO][15] = 60,
+ [0][1][1][0][RTW89_UKRAINE][15] = 42,
+ [0][1][1][0][RTW89_CHILE][15] = 60,
+ [0][1][1][0][RTW89_QATAR][15] = 54,
[0][1][1][0][RTW89_FCC][17] = 60,
[0][1][1][0][RTW89_ETSI][17] = 54,
[0][1][1][0][RTW89_MKK][17] = 70,
@@ -30628,6 +34432,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][17] = 54,
[0][1][1][0][RTW89_CN][17] = 127,
[0][1][1][0][RTW89_UK][17] = 54,
+ [0][1][1][0][RTW89_MEXICO][17] = 60,
+ [0][1][1][0][RTW89_UKRAINE][17] = 42,
+ [0][1][1][0][RTW89_CHILE][17] = 60,
+ [0][1][1][0][RTW89_QATAR][17] = 54,
[0][1][1][0][RTW89_FCC][19] = 60,
[0][1][1][0][RTW89_ETSI][19] = 54,
[0][1][1][0][RTW89_MKK][19] = 70,
@@ -30636,6 +34444,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][19] = 54,
[0][1][1][0][RTW89_CN][19] = 127,
[0][1][1][0][RTW89_UK][19] = 54,
+ [0][1][1][0][RTW89_MEXICO][19] = 60,
+ [0][1][1][0][RTW89_UKRAINE][19] = 42,
+ [0][1][1][0][RTW89_CHILE][19] = 60,
+ [0][1][1][0][RTW89_QATAR][19] = 54,
[0][1][1][0][RTW89_FCC][21] = 60,
[0][1][1][0][RTW89_ETSI][21] = 54,
[0][1][1][0][RTW89_MKK][21] = 70,
@@ -30644,6 +34456,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][21] = 54,
[0][1][1][0][RTW89_CN][21] = 127,
[0][1][1][0][RTW89_UK][21] = 54,
+ [0][1][1][0][RTW89_MEXICO][21] = 60,
+ [0][1][1][0][RTW89_UKRAINE][21] = 42,
+ [0][1][1][0][RTW89_CHILE][21] = 60,
+ [0][1][1][0][RTW89_QATAR][21] = 54,
[0][1][1][0][RTW89_FCC][23] = 60,
[0][1][1][0][RTW89_ETSI][23] = 54,
[0][1][1][0][RTW89_MKK][23] = 70,
@@ -30652,6 +34468,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][23] = 54,
[0][1][1][0][RTW89_CN][23] = 127,
[0][1][1][0][RTW89_UK][23] = 54,
+ [0][1][1][0][RTW89_MEXICO][23] = 60,
+ [0][1][1][0][RTW89_UKRAINE][23] = 42,
+ [0][1][1][0][RTW89_CHILE][23] = 60,
+ [0][1][1][0][RTW89_QATAR][23] = 54,
[0][1][1][0][RTW89_FCC][25] = 60,
[0][1][1][0][RTW89_ETSI][25] = 54,
[0][1][1][0][RTW89_MKK][25] = 70,
@@ -30660,6 +34480,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][25] = 127,
[0][1][1][0][RTW89_CN][25] = 127,
[0][1][1][0][RTW89_UK][25] = 54,
+ [0][1][1][0][RTW89_MEXICO][25] = 60,
+ [0][1][1][0][RTW89_UKRAINE][25] = 42,
+ [0][1][1][0][RTW89_CHILE][25] = 60,
+ [0][1][1][0][RTW89_QATAR][25] = 54,
[0][1][1][0][RTW89_FCC][27] = 60,
[0][1][1][0][RTW89_ETSI][27] = 54,
[0][1][1][0][RTW89_MKK][27] = 70,
@@ -30668,6 +34492,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][27] = 127,
[0][1][1][0][RTW89_CN][27] = 127,
[0][1][1][0][RTW89_UK][27] = 54,
+ [0][1][1][0][RTW89_MEXICO][27] = 60,
+ [0][1][1][0][RTW89_UKRAINE][27] = 42,
+ [0][1][1][0][RTW89_CHILE][27] = 52,
+ [0][1][1][0][RTW89_QATAR][27] = 54,
[0][1][1][0][RTW89_FCC][29] = 60,
[0][1][1][0][RTW89_ETSI][29] = 54,
[0][1][1][0][RTW89_MKK][29] = 70,
@@ -30676,6 +34504,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][29] = 127,
[0][1][1][0][RTW89_CN][29] = 127,
[0][1][1][0][RTW89_UK][29] = 54,
+ [0][1][1][0][RTW89_MEXICO][29] = 60,
+ [0][1][1][0][RTW89_UKRAINE][29] = 42,
+ [0][1][1][0][RTW89_CHILE][29] = 52,
+ [0][1][1][0][RTW89_QATAR][29] = 54,
[0][1][1][0][RTW89_FCC][31] = 60,
[0][1][1][0][RTW89_ETSI][31] = 54,
[0][1][1][0][RTW89_MKK][31] = 70,
@@ -30684,6 +34516,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][31] = 54,
[0][1][1][0][RTW89_CN][31] = 127,
[0][1][1][0][RTW89_UK][31] = 54,
+ [0][1][1][0][RTW89_MEXICO][31] = 60,
+ [0][1][1][0][RTW89_UKRAINE][31] = 42,
+ [0][1][1][0][RTW89_CHILE][31] = 52,
+ [0][1][1][0][RTW89_QATAR][31] = 54,
[0][1][1][0][RTW89_FCC][33] = 60,
[0][1][1][0][RTW89_ETSI][33] = 54,
[0][1][1][0][RTW89_MKK][33] = 70,
@@ -30692,6 +34528,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][33] = 54,
[0][1][1][0][RTW89_CN][33] = 127,
[0][1][1][0][RTW89_UK][33] = 54,
+ [0][1][1][0][RTW89_MEXICO][33] = 60,
+ [0][1][1][0][RTW89_UKRAINE][33] = 42,
+ [0][1][1][0][RTW89_CHILE][33] = 52,
+ [0][1][1][0][RTW89_QATAR][33] = 54,
[0][1][1][0][RTW89_FCC][35] = 52,
[0][1][1][0][RTW89_ETSI][35] = 54,
[0][1][1][0][RTW89_MKK][35] = 70,
@@ -30700,6 +34540,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][35] = 54,
[0][1][1][0][RTW89_CN][35] = 127,
[0][1][1][0][RTW89_UK][35] = 54,
+ [0][1][1][0][RTW89_MEXICO][35] = 52,
+ [0][1][1][0][RTW89_UKRAINE][35] = 42,
+ [0][1][1][0][RTW89_CHILE][35] = 52,
+ [0][1][1][0][RTW89_QATAR][35] = 54,
[0][1][1][0][RTW89_FCC][37] = 62,
[0][1][1][0][RTW89_ETSI][37] = 127,
[0][1][1][0][RTW89_MKK][37] = 70,
@@ -30708,6 +34552,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][37] = 64,
[0][1][1][0][RTW89_CN][37] = 127,
[0][1][1][0][RTW89_UK][37] = 52,
+ [0][1][1][0][RTW89_MEXICO][37] = 62,
+ [0][1][1][0][RTW89_UKRAINE][37] = 127,
+ [0][1][1][0][RTW89_CHILE][37] = 62,
+ [0][1][1][0][RTW89_QATAR][37] = 127,
[0][1][1][0][RTW89_FCC][38] = 72,
[0][1][1][0][RTW89_ETSI][38] = 18,
[0][1][1][0][RTW89_MKK][38] = 127,
@@ -30716,6 +34564,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][38] = 70,
[0][1][1][0][RTW89_CN][38] = 64,
[0][1][1][0][RTW89_UK][38] = 52,
+ [0][1][1][0][RTW89_MEXICO][38] = 72,
+ [0][1][1][0][RTW89_UKRAINE][38] = 18,
+ [0][1][1][0][RTW89_CHILE][38] = 70,
+ [0][1][1][0][RTW89_QATAR][38] = 18,
[0][1][1][0][RTW89_FCC][40] = 72,
[0][1][1][0][RTW89_ETSI][40] = 18,
[0][1][1][0][RTW89_MKK][40] = 127,
@@ -30724,6 +34576,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][40] = 70,
[0][1][1][0][RTW89_CN][40] = 64,
[0][1][1][0][RTW89_UK][40] = 52,
+ [0][1][1][0][RTW89_MEXICO][40] = 72,
+ [0][1][1][0][RTW89_UKRAINE][40] = 18,
+ [0][1][1][0][RTW89_CHILE][40] = 70,
+ [0][1][1][0][RTW89_QATAR][40] = 18,
[0][1][1][0][RTW89_FCC][42] = 72,
[0][1][1][0][RTW89_ETSI][42] = 18,
[0][1][1][0][RTW89_MKK][42] = 127,
@@ -30732,6 +34588,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][42] = 70,
[0][1][1][0][RTW89_CN][42] = 64,
[0][1][1][0][RTW89_UK][42] = 52,
+ [0][1][1][0][RTW89_MEXICO][42] = 72,
+ [0][1][1][0][RTW89_UKRAINE][42] = 18,
+ [0][1][1][0][RTW89_CHILE][42] = 70,
+ [0][1][1][0][RTW89_QATAR][42] = 18,
[0][1][1][0][RTW89_FCC][44] = 72,
[0][1][1][0][RTW89_ETSI][44] = 18,
[0][1][1][0][RTW89_MKK][44] = 127,
@@ -30740,6 +34600,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][44] = 70,
[0][1][1][0][RTW89_CN][44] = 60,
[0][1][1][0][RTW89_UK][44] = 52,
+ [0][1][1][0][RTW89_MEXICO][44] = 72,
+ [0][1][1][0][RTW89_UKRAINE][44] = 18,
+ [0][1][1][0][RTW89_CHILE][44] = 70,
+ [0][1][1][0][RTW89_QATAR][44] = 18,
[0][1][1][0][RTW89_FCC][46] = 72,
[0][1][1][0][RTW89_ETSI][46] = 18,
[0][1][1][0][RTW89_MKK][46] = 127,
@@ -30748,6 +34612,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][46] = 70,
[0][1][1][0][RTW89_CN][46] = 60,
[0][1][1][0][RTW89_UK][46] = 52,
+ [0][1][1][0][RTW89_MEXICO][46] = 72,
+ [0][1][1][0][RTW89_UKRAINE][46] = 18,
+ [0][1][1][0][RTW89_CHILE][46] = 70,
+ [0][1][1][0][RTW89_QATAR][46] = 18,
[0][1][1][0][RTW89_FCC][48] = 48,
[0][1][1][0][RTW89_ETSI][48] = 127,
[0][1][1][0][RTW89_MKK][48] = 127,
@@ -30756,6 +34624,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][48] = 127,
[0][1][1][0][RTW89_CN][48] = 127,
[0][1][1][0][RTW89_UK][48] = 127,
+ [0][1][1][0][RTW89_MEXICO][48] = 127,
+ [0][1][1][0][RTW89_UKRAINE][48] = 127,
+ [0][1][1][0][RTW89_CHILE][48] = 127,
+ [0][1][1][0][RTW89_QATAR][48] = 127,
[0][1][1][0][RTW89_FCC][50] = 48,
[0][1][1][0][RTW89_ETSI][50] = 127,
[0][1][1][0][RTW89_MKK][50] = 127,
@@ -30764,6 +34636,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][50] = 127,
[0][1][1][0][RTW89_CN][50] = 127,
[0][1][1][0][RTW89_UK][50] = 127,
+ [0][1][1][0][RTW89_MEXICO][50] = 127,
+ [0][1][1][0][RTW89_UKRAINE][50] = 127,
+ [0][1][1][0][RTW89_CHILE][50] = 127,
+ [0][1][1][0][RTW89_QATAR][50] = 127,
[0][1][1][0][RTW89_FCC][52] = 48,
[0][1][1][0][RTW89_ETSI][52] = 127,
[0][1][1][0][RTW89_MKK][52] = 127,
@@ -30772,38 +34648,58 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][52] = 127,
[0][1][1][0][RTW89_CN][52] = 127,
[0][1][1][0][RTW89_UK][52] = 127,
+ [0][1][1][0][RTW89_MEXICO][52] = 127,
+ [0][1][1][0][RTW89_UKRAINE][52] = 127,
+ [0][1][1][0][RTW89_CHILE][52] = 127,
+ [0][1][1][0][RTW89_QATAR][52] = 127,
[0][0][2][0][RTW89_FCC][0] = 70,
[0][0][2][0][RTW89_ETSI][0] = 66,
[0][0][2][0][RTW89_MKK][0] = 68,
[0][0][2][0][RTW89_IC][0] = 60,
- [0][0][2][0][RTW89_KCC][0] = 54,
+ [0][0][2][0][RTW89_KCC][0] = 68,
[0][0][2][0][RTW89_ACMA][0] = 66,
[0][0][2][0][RTW89_CN][0] = 52,
[0][0][2][0][RTW89_UK][0] = 66,
+ [0][0][2][0][RTW89_MEXICO][0] = 62,
+ [0][0][2][0][RTW89_UKRAINE][0] = 54,
+ [0][0][2][0][RTW89_CHILE][0] = 68,
+ [0][0][2][0][RTW89_QATAR][0] = 66,
[0][0][2][0][RTW89_FCC][2] = 72,
[0][0][2][0][RTW89_ETSI][2] = 66,
[0][0][2][0][RTW89_MKK][2] = 68,
[0][0][2][0][RTW89_IC][2] = 60,
- [0][0][2][0][RTW89_KCC][2] = 54,
+ [0][0][2][0][RTW89_KCC][2] = 68,
[0][0][2][0][RTW89_ACMA][2] = 66,
[0][0][2][0][RTW89_CN][2] = 52,
[0][0][2][0][RTW89_UK][2] = 66,
+ [0][0][2][0][RTW89_MEXICO][2] = 62,
+ [0][0][2][0][RTW89_UKRAINE][2] = 54,
+ [0][0][2][0][RTW89_CHILE][2] = 70,
+ [0][0][2][0][RTW89_QATAR][2] = 66,
[0][0][2][0][RTW89_FCC][4] = 72,
[0][0][2][0][RTW89_ETSI][4] = 66,
[0][0][2][0][RTW89_MKK][4] = 68,
[0][0][2][0][RTW89_IC][4] = 60,
- [0][0][2][0][RTW89_KCC][4] = 54,
+ [0][0][2][0][RTW89_KCC][4] = 68,
[0][0][2][0][RTW89_ACMA][4] = 66,
[0][0][2][0][RTW89_CN][4] = 52,
[0][0][2][0][RTW89_UK][4] = 66,
+ [0][0][2][0][RTW89_MEXICO][4] = 62,
+ [0][0][2][0][RTW89_UKRAINE][4] = 54,
+ [0][0][2][0][RTW89_CHILE][4] = 70,
+ [0][0][2][0][RTW89_QATAR][4] = 66,
[0][0][2][0][RTW89_FCC][6] = 72,
[0][0][2][0][RTW89_ETSI][6] = 66,
[0][0][2][0][RTW89_MKK][6] = 60,
[0][0][2][0][RTW89_IC][6] = 60,
- [0][0][2][0][RTW89_KCC][6] = 68,
+ [0][0][2][0][RTW89_KCC][6] = 54,
[0][0][2][0][RTW89_ACMA][6] = 66,
[0][0][2][0][RTW89_CN][6] = 52,
[0][0][2][0][RTW89_UK][6] = 66,
+ [0][0][2][0][RTW89_MEXICO][6] = 62,
+ [0][0][2][0][RTW89_UKRAINE][6] = 54,
+ [0][0][2][0][RTW89_CHILE][6] = 70,
+ [0][0][2][0][RTW89_QATAR][6] = 66,
[0][0][2][0][RTW89_FCC][8] = 72,
[0][0][2][0][RTW89_ETSI][8] = 66,
[0][0][2][0][RTW89_MKK][8] = 58,
@@ -30812,6 +34708,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][8] = 66,
[0][0][2][0][RTW89_CN][8] = 52,
[0][0][2][0][RTW89_UK][8] = 66,
+ [0][0][2][0][RTW89_MEXICO][8] = 72,
+ [0][0][2][0][RTW89_UKRAINE][8] = 54,
+ [0][0][2][0][RTW89_CHILE][8] = 70,
+ [0][0][2][0][RTW89_QATAR][8] = 66,
[0][0][2][0][RTW89_FCC][10] = 72,
[0][0][2][0][RTW89_ETSI][10] = 66,
[0][0][2][0][RTW89_MKK][10] = 70,
@@ -30820,6 +34720,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][10] = 66,
[0][0][2][0][RTW89_CN][10] = 52,
[0][0][2][0][RTW89_UK][10] = 66,
+ [0][0][2][0][RTW89_MEXICO][10] = 72,
+ [0][0][2][0][RTW89_UKRAINE][10] = 54,
+ [0][0][2][0][RTW89_CHILE][10] = 70,
+ [0][0][2][0][RTW89_QATAR][10] = 66,
[0][0][2][0][RTW89_FCC][12] = 72,
[0][0][2][0][RTW89_ETSI][12] = 66,
[0][0][2][0][RTW89_MKK][12] = 70,
@@ -30828,6 +34732,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][12] = 66,
[0][0][2][0][RTW89_CN][12] = 52,
[0][0][2][0][RTW89_UK][12] = 66,
+ [0][0][2][0][RTW89_MEXICO][12] = 72,
+ [0][0][2][0][RTW89_UKRAINE][12] = 54,
+ [0][0][2][0][RTW89_CHILE][12] = 70,
+ [0][0][2][0][RTW89_QATAR][12] = 66,
[0][0][2][0][RTW89_FCC][14] = 68,
[0][0][2][0][RTW89_ETSI][14] = 66,
[0][0][2][0][RTW89_MKK][14] = 70,
@@ -30836,6 +34744,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][14] = 66,
[0][0][2][0][RTW89_CN][14] = 52,
[0][0][2][0][RTW89_UK][14] = 66,
+ [0][0][2][0][RTW89_MEXICO][14] = 68,
+ [0][0][2][0][RTW89_UKRAINE][14] = 54,
+ [0][0][2][0][RTW89_CHILE][14] = 66,
+ [0][0][2][0][RTW89_QATAR][14] = 66,
[0][0][2][0][RTW89_FCC][15] = 70,
[0][0][2][0][RTW89_ETSI][15] = 66,
[0][0][2][0][RTW89_MKK][15] = 70,
@@ -30844,6 +34756,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][15] = 66,
[0][0][2][0][RTW89_CN][15] = 127,
[0][0][2][0][RTW89_UK][15] = 66,
+ [0][0][2][0][RTW89_MEXICO][15] = 70,
+ [0][0][2][0][RTW89_UKRAINE][15] = 54,
+ [0][0][2][0][RTW89_CHILE][15] = 68,
+ [0][0][2][0][RTW89_QATAR][15] = 66,
[0][0][2][0][RTW89_FCC][17] = 72,
[0][0][2][0][RTW89_ETSI][17] = 66,
[0][0][2][0][RTW89_MKK][17] = 70,
@@ -30852,6 +34768,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][17] = 66,
[0][0][2][0][RTW89_CN][17] = 127,
[0][0][2][0][RTW89_UK][17] = 66,
+ [0][0][2][0][RTW89_MEXICO][17] = 72,
+ [0][0][2][0][RTW89_UKRAINE][17] = 54,
+ [0][0][2][0][RTW89_CHILE][17] = 68,
+ [0][0][2][0][RTW89_QATAR][17] = 66,
[0][0][2][0][RTW89_FCC][19] = 72,
[0][0][2][0][RTW89_ETSI][19] = 66,
[0][0][2][0][RTW89_MKK][19] = 70,
@@ -30860,6 +34780,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][19] = 66,
[0][0][2][0][RTW89_CN][19] = 127,
[0][0][2][0][RTW89_UK][19] = 66,
+ [0][0][2][0][RTW89_MEXICO][19] = 72,
+ [0][0][2][0][RTW89_UKRAINE][19] = 54,
+ [0][0][2][0][RTW89_CHILE][19] = 68,
+ [0][0][2][0][RTW89_QATAR][19] = 66,
[0][0][2][0][RTW89_FCC][21] = 72,
[0][0][2][0][RTW89_ETSI][21] = 66,
[0][0][2][0][RTW89_MKK][21] = 70,
@@ -30868,6 +34792,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][21] = 66,
[0][0][2][0][RTW89_CN][21] = 127,
[0][0][2][0][RTW89_UK][21] = 66,
+ [0][0][2][0][RTW89_MEXICO][21] = 72,
+ [0][0][2][0][RTW89_UKRAINE][21] = 54,
+ [0][0][2][0][RTW89_CHILE][21] = 70,
+ [0][0][2][0][RTW89_QATAR][21] = 66,
[0][0][2][0][RTW89_FCC][23] = 72,
[0][0][2][0][RTW89_ETSI][23] = 66,
[0][0][2][0][RTW89_MKK][23] = 70,
@@ -30876,6 +34804,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][23] = 66,
[0][0][2][0][RTW89_CN][23] = 127,
[0][0][2][0][RTW89_UK][23] = 66,
+ [0][0][2][0][RTW89_MEXICO][23] = 72,
+ [0][0][2][0][RTW89_UKRAINE][23] = 54,
+ [0][0][2][0][RTW89_CHILE][23] = 70,
+ [0][0][2][0][RTW89_QATAR][23] = 66,
[0][0][2][0][RTW89_FCC][25] = 72,
[0][0][2][0][RTW89_ETSI][25] = 66,
[0][0][2][0][RTW89_MKK][25] = 70,
@@ -30884,6 +34816,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][25] = 127,
[0][0][2][0][RTW89_CN][25] = 127,
[0][0][2][0][RTW89_UK][25] = 66,
+ [0][0][2][0][RTW89_MEXICO][25] = 72,
+ [0][0][2][0][RTW89_UKRAINE][25] = 54,
+ [0][0][2][0][RTW89_CHILE][25] = 70,
+ [0][0][2][0][RTW89_QATAR][25] = 66,
[0][0][2][0][RTW89_FCC][27] = 72,
[0][0][2][0][RTW89_ETSI][27] = 66,
[0][0][2][0][RTW89_MKK][27] = 70,
@@ -30892,6 +34828,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][27] = 127,
[0][0][2][0][RTW89_CN][27] = 127,
[0][0][2][0][RTW89_UK][27] = 66,
+ [0][0][2][0][RTW89_MEXICO][27] = 72,
+ [0][0][2][0][RTW89_UKRAINE][27] = 54,
+ [0][0][2][0][RTW89_CHILE][27] = 56,
+ [0][0][2][0][RTW89_QATAR][27] = 66,
[0][0][2][0][RTW89_FCC][29] = 72,
[0][0][2][0][RTW89_ETSI][29] = 66,
[0][0][2][0][RTW89_MKK][29] = 70,
@@ -30900,6 +34840,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][29] = 127,
[0][0][2][0][RTW89_CN][29] = 127,
[0][0][2][0][RTW89_UK][29] = 66,
+ [0][0][2][0][RTW89_MEXICO][29] = 72,
+ [0][0][2][0][RTW89_UKRAINE][29] = 54,
+ [0][0][2][0][RTW89_CHILE][29] = 56,
+ [0][0][2][0][RTW89_QATAR][29] = 66,
[0][0][2][0][RTW89_FCC][31] = 72,
[0][0][2][0][RTW89_ETSI][31] = 66,
[0][0][2][0][RTW89_MKK][31] = 70,
@@ -30908,6 +34852,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][31] = 66,
[0][0][2][0][RTW89_CN][31] = 127,
[0][0][2][0][RTW89_UK][31] = 66,
+ [0][0][2][0][RTW89_MEXICO][31] = 72,
+ [0][0][2][0][RTW89_UKRAINE][31] = 54,
+ [0][0][2][0][RTW89_CHILE][31] = 56,
+ [0][0][2][0][RTW89_QATAR][31] = 66,
[0][0][2][0][RTW89_FCC][33] = 72,
[0][0][2][0][RTW89_ETSI][33] = 66,
[0][0][2][0][RTW89_MKK][33] = 70,
@@ -30916,6 +34864,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][33] = 66,
[0][0][2][0][RTW89_CN][33] = 127,
[0][0][2][0][RTW89_UK][33] = 66,
+ [0][0][2][0][RTW89_MEXICO][33] = 72,
+ [0][0][2][0][RTW89_UKRAINE][33] = 54,
+ [0][0][2][0][RTW89_CHILE][33] = 56,
+ [0][0][2][0][RTW89_QATAR][33] = 66,
[0][0][2][0][RTW89_FCC][35] = 56,
[0][0][2][0][RTW89_ETSI][35] = 66,
[0][0][2][0][RTW89_MKK][35] = 70,
@@ -30924,6 +34876,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][35] = 66,
[0][0][2][0][RTW89_CN][35] = 127,
[0][0][2][0][RTW89_UK][35] = 66,
+ [0][0][2][0][RTW89_MEXICO][35] = 56,
+ [0][0][2][0][RTW89_UKRAINE][35] = 54,
+ [0][0][2][0][RTW89_CHILE][35] = 56,
+ [0][0][2][0][RTW89_QATAR][35] = 66,
[0][0][2][0][RTW89_FCC][37] = 72,
[0][0][2][0][RTW89_ETSI][37] = 127,
[0][0][2][0][RTW89_MKK][37] = 70,
@@ -30932,6 +34888,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][37] = 70,
[0][0][2][0][RTW89_CN][37] = 127,
[0][0][2][0][RTW89_UK][37] = 64,
+ [0][0][2][0][RTW89_MEXICO][37] = 72,
+ [0][0][2][0][RTW89_UKRAINE][37] = 127,
+ [0][0][2][0][RTW89_CHILE][37] = 70,
+ [0][0][2][0][RTW89_QATAR][37] = 127,
[0][0][2][0][RTW89_FCC][38] = 72,
[0][0][2][0][RTW89_ETSI][38] = 30,
[0][0][2][0][RTW89_MKK][38] = 127,
@@ -30940,6 +34900,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][38] = 70,
[0][0][2][0][RTW89_CN][38] = 68,
[0][0][2][0][RTW89_UK][38] = 64,
+ [0][0][2][0][RTW89_MEXICO][38] = 72,
+ [0][0][2][0][RTW89_UKRAINE][38] = 30,
+ [0][0][2][0][RTW89_CHILE][38] = 70,
+ [0][0][2][0][RTW89_QATAR][38] = 30,
[0][0][2][0][RTW89_FCC][40] = 72,
[0][0][2][0][RTW89_ETSI][40] = 30,
[0][0][2][0][RTW89_MKK][40] = 127,
@@ -30948,6 +34912,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][40] = 70,
[0][0][2][0][RTW89_CN][40] = 68,
[0][0][2][0][RTW89_UK][40] = 64,
+ [0][0][2][0][RTW89_MEXICO][40] = 72,
+ [0][0][2][0][RTW89_UKRAINE][40] = 30,
+ [0][0][2][0][RTW89_CHILE][40] = 70,
+ [0][0][2][0][RTW89_QATAR][40] = 30,
[0][0][2][0][RTW89_FCC][42] = 72,
[0][0][2][0][RTW89_ETSI][42] = 30,
[0][0][2][0][RTW89_MKK][42] = 127,
@@ -30956,6 +34924,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][42] = 70,
[0][0][2][0][RTW89_CN][42] = 68,
[0][0][2][0][RTW89_UK][42] = 64,
+ [0][0][2][0][RTW89_MEXICO][42] = 72,
+ [0][0][2][0][RTW89_UKRAINE][42] = 30,
+ [0][0][2][0][RTW89_CHILE][42] = 70,
+ [0][0][2][0][RTW89_QATAR][42] = 30,
[0][0][2][0][RTW89_FCC][44] = 72,
[0][0][2][0][RTW89_ETSI][44] = 30,
[0][0][2][0][RTW89_MKK][44] = 127,
@@ -30964,6 +34936,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][44] = 70,
[0][0][2][0][RTW89_CN][44] = 68,
[0][0][2][0][RTW89_UK][44] = 64,
+ [0][0][2][0][RTW89_MEXICO][44] = 72,
+ [0][0][2][0][RTW89_UKRAINE][44] = 30,
+ [0][0][2][0][RTW89_CHILE][44] = 70,
+ [0][0][2][0][RTW89_QATAR][44] = 30,
[0][0][2][0][RTW89_FCC][46] = 72,
[0][0][2][0][RTW89_ETSI][46] = 30,
[0][0][2][0][RTW89_MKK][46] = 127,
@@ -30972,6 +34948,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][46] = 70,
[0][0][2][0][RTW89_CN][46] = 68,
[0][0][2][0][RTW89_UK][46] = 64,
+ [0][0][2][0][RTW89_MEXICO][46] = 72,
+ [0][0][2][0][RTW89_UKRAINE][46] = 30,
+ [0][0][2][0][RTW89_CHILE][46] = 70,
+ [0][0][2][0][RTW89_QATAR][46] = 30,
[0][0][2][0][RTW89_FCC][48] = 72,
[0][0][2][0][RTW89_ETSI][48] = 127,
[0][0][2][0][RTW89_MKK][48] = 127,
@@ -30980,6 +34960,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][48] = 127,
[0][0][2][0][RTW89_CN][48] = 127,
[0][0][2][0][RTW89_UK][48] = 127,
+ [0][0][2][0][RTW89_MEXICO][48] = 127,
+ [0][0][2][0][RTW89_UKRAINE][48] = 127,
+ [0][0][2][0][RTW89_CHILE][48] = 127,
+ [0][0][2][0][RTW89_QATAR][48] = 127,
[0][0][2][0][RTW89_FCC][50] = 72,
[0][0][2][0][RTW89_ETSI][50] = 127,
[0][0][2][0][RTW89_MKK][50] = 127,
@@ -30988,6 +34972,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][50] = 127,
[0][0][2][0][RTW89_CN][50] = 127,
[0][0][2][0][RTW89_UK][50] = 127,
+ [0][0][2][0][RTW89_MEXICO][50] = 127,
+ [0][0][2][0][RTW89_UKRAINE][50] = 127,
+ [0][0][2][0][RTW89_CHILE][50] = 127,
+ [0][0][2][0][RTW89_QATAR][50] = 127,
[0][0][2][0][RTW89_FCC][52] = 72,
[0][0][2][0][RTW89_ETSI][52] = 127,
[0][0][2][0][RTW89_MKK][52] = 127,
@@ -30996,38 +34984,58 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][52] = 127,
[0][0][2][0][RTW89_CN][52] = 127,
[0][0][2][0][RTW89_UK][52] = 127,
+ [0][0][2][0][RTW89_MEXICO][52] = 127,
+ [0][0][2][0][RTW89_UKRAINE][52] = 127,
+ [0][0][2][0][RTW89_CHILE][52] = 127,
+ [0][0][2][0][RTW89_QATAR][52] = 127,
[0][1][2][0][RTW89_FCC][0] = 60,
[0][1][2][0][RTW89_ETSI][0] = 54,
[0][1][2][0][RTW89_MKK][0] = 54,
[0][1][2][0][RTW89_IC][0] = 36,
- [0][1][2][0][RTW89_KCC][0] = 40,
+ [0][1][2][0][RTW89_KCC][0] = 64,
[0][1][2][0][RTW89_ACMA][0] = 54,
[0][1][2][0][RTW89_CN][0] = 40,
[0][1][2][0][RTW89_UK][0] = 54,
+ [0][1][2][0][RTW89_MEXICO][0] = 50,
+ [0][1][2][0][RTW89_UKRAINE][0] = 42,
+ [0][1][2][0][RTW89_CHILE][0] = 60,
+ [0][1][2][0][RTW89_QATAR][0] = 54,
[0][1][2][0][RTW89_FCC][2] = 62,
[0][1][2][0][RTW89_ETSI][2] = 54,
[0][1][2][0][RTW89_MKK][2] = 54,
[0][1][2][0][RTW89_IC][2] = 36,
- [0][1][2][0][RTW89_KCC][2] = 40,
+ [0][1][2][0][RTW89_KCC][2] = 64,
[0][1][2][0][RTW89_ACMA][2] = 54,
[0][1][2][0][RTW89_CN][2] = 40,
[0][1][2][0][RTW89_UK][2] = 54,
+ [0][1][2][0][RTW89_MEXICO][2] = 50,
+ [0][1][2][0][RTW89_UKRAINE][2] = 42,
+ [0][1][2][0][RTW89_CHILE][2] = 62,
+ [0][1][2][0][RTW89_QATAR][2] = 54,
[0][1][2][0][RTW89_FCC][4] = 62,
[0][1][2][0][RTW89_ETSI][4] = 54,
[0][1][2][0][RTW89_MKK][4] = 54,
[0][1][2][0][RTW89_IC][4] = 36,
- [0][1][2][0][RTW89_KCC][4] = 40,
+ [0][1][2][0][RTW89_KCC][4] = 64,
[0][1][2][0][RTW89_ACMA][4] = 54,
[0][1][2][0][RTW89_CN][4] = 40,
[0][1][2][0][RTW89_UK][4] = 54,
+ [0][1][2][0][RTW89_MEXICO][4] = 50,
+ [0][1][2][0][RTW89_UKRAINE][4] = 42,
+ [0][1][2][0][RTW89_CHILE][4] = 62,
+ [0][1][2][0][RTW89_QATAR][4] = 54,
[0][1][2][0][RTW89_FCC][6] = 62,
[0][1][2][0][RTW89_ETSI][6] = 54,
[0][1][2][0][RTW89_MKK][6] = 50,
[0][1][2][0][RTW89_IC][6] = 38,
- [0][1][2][0][RTW89_KCC][6] = 64,
+ [0][1][2][0][RTW89_KCC][6] = 40,
[0][1][2][0][RTW89_ACMA][6] = 54,
[0][1][2][0][RTW89_CN][6] = 40,
[0][1][2][0][RTW89_UK][6] = 54,
+ [0][1][2][0][RTW89_MEXICO][6] = 50,
+ [0][1][2][0][RTW89_UKRAINE][6] = 42,
+ [0][1][2][0][RTW89_CHILE][6] = 62,
+ [0][1][2][0][RTW89_QATAR][6] = 54,
[0][1][2][0][RTW89_FCC][8] = 62,
[0][1][2][0][RTW89_ETSI][8] = 54,
[0][1][2][0][RTW89_MKK][8] = 42,
@@ -31036,6 +35044,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][8] = 54,
[0][1][2][0][RTW89_CN][8] = 40,
[0][1][2][0][RTW89_UK][8] = 54,
+ [0][1][2][0][RTW89_MEXICO][8] = 62,
+ [0][1][2][0][RTW89_UKRAINE][8] = 42,
+ [0][1][2][0][RTW89_CHILE][8] = 62,
+ [0][1][2][0][RTW89_QATAR][8] = 54,
[0][1][2][0][RTW89_FCC][10] = 62,
[0][1][2][0][RTW89_ETSI][10] = 54,
[0][1][2][0][RTW89_MKK][10] = 54,
@@ -31044,6 +35056,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][10] = 54,
[0][1][2][0][RTW89_CN][10] = 40,
[0][1][2][0][RTW89_UK][10] = 54,
+ [0][1][2][0][RTW89_MEXICO][10] = 62,
+ [0][1][2][0][RTW89_UKRAINE][10] = 42,
+ [0][1][2][0][RTW89_CHILE][10] = 62,
+ [0][1][2][0][RTW89_QATAR][10] = 54,
[0][1][2][0][RTW89_FCC][12] = 62,
[0][1][2][0][RTW89_ETSI][12] = 54,
[0][1][2][0][RTW89_MKK][12] = 54,
@@ -31052,6 +35068,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][12] = 54,
[0][1][2][0][RTW89_CN][12] = 40,
[0][1][2][0][RTW89_UK][12] = 54,
+ [0][1][2][0][RTW89_MEXICO][12] = 62,
+ [0][1][2][0][RTW89_UKRAINE][12] = 42,
+ [0][1][2][0][RTW89_CHILE][12] = 62,
+ [0][1][2][0][RTW89_QATAR][12] = 54,
[0][1][2][0][RTW89_FCC][14] = 62,
[0][1][2][0][RTW89_ETSI][14] = 54,
[0][1][2][0][RTW89_MKK][14] = 54,
@@ -31060,6 +35080,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][14] = 54,
[0][1][2][0][RTW89_CN][14] = 40,
[0][1][2][0][RTW89_UK][14] = 54,
+ [0][1][2][0][RTW89_MEXICO][14] = 62,
+ [0][1][2][0][RTW89_UKRAINE][14] = 42,
+ [0][1][2][0][RTW89_CHILE][14] = 62,
+ [0][1][2][0][RTW89_QATAR][14] = 54,
[0][1][2][0][RTW89_FCC][15] = 60,
[0][1][2][0][RTW89_ETSI][15] = 54,
[0][1][2][0][RTW89_MKK][15] = 68,
@@ -31068,6 +35092,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][15] = 54,
[0][1][2][0][RTW89_CN][15] = 127,
[0][1][2][0][RTW89_UK][15] = 54,
+ [0][1][2][0][RTW89_MEXICO][15] = 60,
+ [0][1][2][0][RTW89_UKRAINE][15] = 42,
+ [0][1][2][0][RTW89_CHILE][15] = 60,
+ [0][1][2][0][RTW89_QATAR][15] = 54,
[0][1][2][0][RTW89_FCC][17] = 62,
[0][1][2][0][RTW89_ETSI][17] = 54,
[0][1][2][0][RTW89_MKK][17] = 68,
@@ -31076,6 +35104,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][17] = 54,
[0][1][2][0][RTW89_CN][17] = 127,
[0][1][2][0][RTW89_UK][17] = 54,
+ [0][1][2][0][RTW89_MEXICO][17] = 62,
+ [0][1][2][0][RTW89_UKRAINE][17] = 42,
+ [0][1][2][0][RTW89_CHILE][17] = 60,
+ [0][1][2][0][RTW89_QATAR][17] = 54,
[0][1][2][0][RTW89_FCC][19] = 62,
[0][1][2][0][RTW89_ETSI][19] = 54,
[0][1][2][0][RTW89_MKK][19] = 68,
@@ -31084,6 +35116,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][19] = 54,
[0][1][2][0][RTW89_CN][19] = 127,
[0][1][2][0][RTW89_UK][19] = 54,
+ [0][1][2][0][RTW89_MEXICO][19] = 62,
+ [0][1][2][0][RTW89_UKRAINE][19] = 42,
+ [0][1][2][0][RTW89_CHILE][19] = 62,
+ [0][1][2][0][RTW89_QATAR][19] = 54,
[0][1][2][0][RTW89_FCC][21] = 62,
[0][1][2][0][RTW89_ETSI][21] = 54,
[0][1][2][0][RTW89_MKK][21] = 68,
@@ -31092,6 +35128,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][21] = 54,
[0][1][2][0][RTW89_CN][21] = 127,
[0][1][2][0][RTW89_UK][21] = 54,
+ [0][1][2][0][RTW89_MEXICO][21] = 62,
+ [0][1][2][0][RTW89_UKRAINE][21] = 42,
+ [0][1][2][0][RTW89_CHILE][21] = 62,
+ [0][1][2][0][RTW89_QATAR][21] = 54,
[0][1][2][0][RTW89_FCC][23] = 62,
[0][1][2][0][RTW89_ETSI][23] = 54,
[0][1][2][0][RTW89_MKK][23] = 68,
@@ -31100,6 +35140,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][23] = 54,
[0][1][2][0][RTW89_CN][23] = 127,
[0][1][2][0][RTW89_UK][23] = 54,
+ [0][1][2][0][RTW89_MEXICO][23] = 62,
+ [0][1][2][0][RTW89_UKRAINE][23] = 42,
+ [0][1][2][0][RTW89_CHILE][23] = 62,
+ [0][1][2][0][RTW89_QATAR][23] = 54,
[0][1][2][0][RTW89_FCC][25] = 62,
[0][1][2][0][RTW89_ETSI][25] = 54,
[0][1][2][0][RTW89_MKK][25] = 68,
@@ -31108,6 +35152,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][25] = 127,
[0][1][2][0][RTW89_CN][25] = 127,
[0][1][2][0][RTW89_UK][25] = 54,
+ [0][1][2][0][RTW89_MEXICO][25] = 62,
+ [0][1][2][0][RTW89_UKRAINE][25] = 42,
+ [0][1][2][0][RTW89_CHILE][25] = 62,
+ [0][1][2][0][RTW89_QATAR][25] = 54,
[0][1][2][0][RTW89_FCC][27] = 62,
[0][1][2][0][RTW89_ETSI][27] = 54,
[0][1][2][0][RTW89_MKK][27] = 68,
@@ -31116,6 +35164,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][27] = 127,
[0][1][2][0][RTW89_CN][27] = 127,
[0][1][2][0][RTW89_UK][27] = 54,
+ [0][1][2][0][RTW89_MEXICO][27] = 62,
+ [0][1][2][0][RTW89_UKRAINE][27] = 42,
+ [0][1][2][0][RTW89_CHILE][27] = 46,
+ [0][1][2][0][RTW89_QATAR][27] = 54,
[0][1][2][0][RTW89_FCC][29] = 62,
[0][1][2][0][RTW89_ETSI][29] = 54,
[0][1][2][0][RTW89_MKK][29] = 68,
@@ -31124,6 +35176,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][29] = 127,
[0][1][2][0][RTW89_CN][29] = 127,
[0][1][2][0][RTW89_UK][29] = 54,
+ [0][1][2][0][RTW89_MEXICO][29] = 62,
+ [0][1][2][0][RTW89_UKRAINE][29] = 42,
+ [0][1][2][0][RTW89_CHILE][29] = 46,
+ [0][1][2][0][RTW89_QATAR][29] = 54,
[0][1][2][0][RTW89_FCC][31] = 62,
[0][1][2][0][RTW89_ETSI][31] = 54,
[0][1][2][0][RTW89_MKK][31] = 68,
@@ -31132,6 +35188,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][31] = 54,
[0][1][2][0][RTW89_CN][31] = 127,
[0][1][2][0][RTW89_UK][31] = 54,
+ [0][1][2][0][RTW89_MEXICO][31] = 62,
+ [0][1][2][0][RTW89_UKRAINE][31] = 42,
+ [0][1][2][0][RTW89_CHILE][31] = 46,
+ [0][1][2][0][RTW89_QATAR][31] = 54,
[0][1][2][0][RTW89_FCC][33] = 62,
[0][1][2][0][RTW89_ETSI][33] = 54,
[0][1][2][0][RTW89_MKK][33] = 68,
@@ -31140,6 +35200,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][33] = 54,
[0][1][2][0][RTW89_CN][33] = 127,
[0][1][2][0][RTW89_UK][33] = 54,
+ [0][1][2][0][RTW89_MEXICO][33] = 62,
+ [0][1][2][0][RTW89_UKRAINE][33] = 42,
+ [0][1][2][0][RTW89_CHILE][33] = 46,
+ [0][1][2][0][RTW89_QATAR][33] = 54,
[0][1][2][0][RTW89_FCC][35] = 46,
[0][1][2][0][RTW89_ETSI][35] = 54,
[0][1][2][0][RTW89_MKK][35] = 68,
@@ -31148,6 +35212,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][35] = 54,
[0][1][2][0][RTW89_CN][35] = 127,
[0][1][2][0][RTW89_UK][35] = 54,
+ [0][1][2][0][RTW89_MEXICO][35] = 46,
+ [0][1][2][0][RTW89_UKRAINE][35] = 42,
+ [0][1][2][0][RTW89_CHILE][35] = 46,
+ [0][1][2][0][RTW89_QATAR][35] = 54,
[0][1][2][0][RTW89_FCC][37] = 64,
[0][1][2][0][RTW89_ETSI][37] = 127,
[0][1][2][0][RTW89_MKK][37] = 68,
@@ -31156,6 +35224,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][37] = 64,
[0][1][2][0][RTW89_CN][37] = 127,
[0][1][2][0][RTW89_UK][37] = 52,
+ [0][1][2][0][RTW89_MEXICO][37] = 64,
+ [0][1][2][0][RTW89_UKRAINE][37] = 127,
+ [0][1][2][0][RTW89_CHILE][37] = 64,
+ [0][1][2][0][RTW89_QATAR][37] = 127,
[0][1][2][0][RTW89_FCC][38] = 72,
[0][1][2][0][RTW89_ETSI][38] = 18,
[0][1][2][0][RTW89_MKK][38] = 127,
@@ -31164,6 +35236,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][38] = 70,
[0][1][2][0][RTW89_CN][38] = 68,
[0][1][2][0][RTW89_UK][38] = 52,
+ [0][1][2][0][RTW89_MEXICO][38] = 72,
+ [0][1][2][0][RTW89_UKRAINE][38] = 18,
+ [0][1][2][0][RTW89_CHILE][38] = 70,
+ [0][1][2][0][RTW89_QATAR][38] = 18,
[0][1][2][0][RTW89_FCC][40] = 72,
[0][1][2][0][RTW89_ETSI][40] = 18,
[0][1][2][0][RTW89_MKK][40] = 127,
@@ -31172,6 +35248,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][40] = 70,
[0][1][2][0][RTW89_CN][40] = 68,
[0][1][2][0][RTW89_UK][40] = 52,
+ [0][1][2][0][RTW89_MEXICO][40] = 72,
+ [0][1][2][0][RTW89_UKRAINE][40] = 18,
+ [0][1][2][0][RTW89_CHILE][40] = 70,
+ [0][1][2][0][RTW89_QATAR][40] = 18,
[0][1][2][0][RTW89_FCC][42] = 72,
[0][1][2][0][RTW89_ETSI][42] = 18,
[0][1][2][0][RTW89_MKK][42] = 127,
@@ -31180,6 +35260,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][42] = 70,
[0][1][2][0][RTW89_CN][42] = 68,
[0][1][2][0][RTW89_UK][42] = 52,
+ [0][1][2][0][RTW89_MEXICO][42] = 72,
+ [0][1][2][0][RTW89_UKRAINE][42] = 18,
+ [0][1][2][0][RTW89_CHILE][42] = 70,
+ [0][1][2][0][RTW89_QATAR][42] = 18,
[0][1][2][0][RTW89_FCC][44] = 72,
[0][1][2][0][RTW89_ETSI][44] = 18,
[0][1][2][0][RTW89_MKK][44] = 127,
@@ -31188,6 +35272,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][44] = 70,
[0][1][2][0][RTW89_CN][44] = 68,
[0][1][2][0][RTW89_UK][44] = 52,
+ [0][1][2][0][RTW89_MEXICO][44] = 72,
+ [0][1][2][0][RTW89_UKRAINE][44] = 18,
+ [0][1][2][0][RTW89_CHILE][44] = 70,
+ [0][1][2][0][RTW89_QATAR][44] = 18,
[0][1][2][0][RTW89_FCC][46] = 72,
[0][1][2][0][RTW89_ETSI][46] = 18,
[0][1][2][0][RTW89_MKK][46] = 127,
@@ -31196,6 +35284,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][46] = 70,
[0][1][2][0][RTW89_CN][46] = 68,
[0][1][2][0][RTW89_UK][46] = 52,
+ [0][1][2][0][RTW89_MEXICO][46] = 72,
+ [0][1][2][0][RTW89_UKRAINE][46] = 18,
+ [0][1][2][0][RTW89_CHILE][46] = 70,
+ [0][1][2][0][RTW89_QATAR][46] = 18,
[0][1][2][0][RTW89_FCC][48] = 48,
[0][1][2][0][RTW89_ETSI][48] = 127,
[0][1][2][0][RTW89_MKK][48] = 127,
@@ -31204,6 +35296,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][48] = 127,
[0][1][2][0][RTW89_CN][48] = 127,
[0][1][2][0][RTW89_UK][48] = 127,
+ [0][1][2][0][RTW89_MEXICO][48] = 127,
+ [0][1][2][0][RTW89_UKRAINE][48] = 127,
+ [0][1][2][0][RTW89_CHILE][48] = 127,
+ [0][1][2][0][RTW89_QATAR][48] = 127,
[0][1][2][0][RTW89_FCC][50] = 50,
[0][1][2][0][RTW89_ETSI][50] = 127,
[0][1][2][0][RTW89_MKK][50] = 127,
@@ -31212,6 +35308,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][50] = 127,
[0][1][2][0][RTW89_CN][50] = 127,
[0][1][2][0][RTW89_UK][50] = 127,
+ [0][1][2][0][RTW89_MEXICO][50] = 127,
+ [0][1][2][0][RTW89_UKRAINE][50] = 127,
+ [0][1][2][0][RTW89_CHILE][50] = 127,
+ [0][1][2][0][RTW89_QATAR][50] = 127,
[0][1][2][0][RTW89_FCC][52] = 48,
[0][1][2][0][RTW89_ETSI][52] = 127,
[0][1][2][0][RTW89_MKK][52] = 127,
@@ -31220,38 +35320,58 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][52] = 127,
[0][1][2][0][RTW89_CN][52] = 127,
[0][1][2][0][RTW89_UK][52] = 127,
+ [0][1][2][0][RTW89_MEXICO][52] = 127,
+ [0][1][2][0][RTW89_UKRAINE][52] = 127,
+ [0][1][2][0][RTW89_CHILE][52] = 127,
+ [0][1][2][0][RTW89_QATAR][52] = 127,
[0][1][2][1][RTW89_FCC][0] = 60,
[0][1][2][1][RTW89_ETSI][0] = 40,
[0][1][2][1][RTW89_MKK][0] = 54,
[0][1][2][1][RTW89_IC][0] = 40,
- [0][1][2][1][RTW89_KCC][0] = 40,
+ [0][1][2][1][RTW89_KCC][0] = 64,
[0][1][2][1][RTW89_ACMA][0] = 40,
[0][1][2][1][RTW89_CN][0] = 36,
[0][1][2][1][RTW89_UK][0] = 40,
+ [0][1][2][1][RTW89_MEXICO][0] = 50,
+ [0][1][2][1][RTW89_UKRAINE][0] = 30,
+ [0][1][2][1][RTW89_CHILE][0] = 60,
+ [0][1][2][1][RTW89_QATAR][0] = 40,
[0][1][2][1][RTW89_FCC][2] = 62,
[0][1][2][1][RTW89_ETSI][2] = 40,
[0][1][2][1][RTW89_MKK][2] = 54,
[0][1][2][1][RTW89_IC][2] = 40,
- [0][1][2][1][RTW89_KCC][2] = 40,
+ [0][1][2][1][RTW89_KCC][2] = 64,
[0][1][2][1][RTW89_ACMA][2] = 40,
[0][1][2][1][RTW89_CN][2] = 36,
[0][1][2][1][RTW89_UK][2] = 40,
+ [0][1][2][1][RTW89_MEXICO][2] = 50,
+ [0][1][2][1][RTW89_UKRAINE][2] = 30,
+ [0][1][2][1][RTW89_CHILE][2] = 60,
+ [0][1][2][1][RTW89_QATAR][2] = 40,
[0][1][2][1][RTW89_FCC][4] = 62,
[0][1][2][1][RTW89_ETSI][4] = 40,
[0][1][2][1][RTW89_MKK][4] = 54,
[0][1][2][1][RTW89_IC][4] = 40,
- [0][1][2][1][RTW89_KCC][4] = 40,
+ [0][1][2][1][RTW89_KCC][4] = 64,
[0][1][2][1][RTW89_ACMA][4] = 40,
[0][1][2][1][RTW89_CN][4] = 36,
[0][1][2][1][RTW89_UK][4] = 40,
+ [0][1][2][1][RTW89_MEXICO][4] = 50,
+ [0][1][2][1][RTW89_UKRAINE][4] = 30,
+ [0][1][2][1][RTW89_CHILE][4] = 60,
+ [0][1][2][1][RTW89_QATAR][4] = 40,
[0][1][2][1][RTW89_FCC][6] = 62,
[0][1][2][1][RTW89_ETSI][6] = 40,
[0][1][2][1][RTW89_MKK][6] = 50,
[0][1][2][1][RTW89_IC][6] = 40,
- [0][1][2][1][RTW89_KCC][6] = 64,
+ [0][1][2][1][RTW89_KCC][6] = 40,
[0][1][2][1][RTW89_ACMA][6] = 40,
[0][1][2][1][RTW89_CN][6] = 36,
[0][1][2][1][RTW89_UK][6] = 40,
+ [0][1][2][1][RTW89_MEXICO][6] = 50,
+ [0][1][2][1][RTW89_UKRAINE][6] = 30,
+ [0][1][2][1][RTW89_CHILE][6] = 60,
+ [0][1][2][1][RTW89_QATAR][6] = 40,
[0][1][2][1][RTW89_FCC][8] = 62,
[0][1][2][1][RTW89_ETSI][8] = 40,
[0][1][2][1][RTW89_MKK][8] = 42,
@@ -31260,6 +35380,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][8] = 40,
[0][1][2][1][RTW89_CN][8] = 36,
[0][1][2][1][RTW89_UK][8] = 40,
+ [0][1][2][1][RTW89_MEXICO][8] = 62,
+ [0][1][2][1][RTW89_UKRAINE][8] = 30,
+ [0][1][2][1][RTW89_CHILE][8] = 60,
+ [0][1][2][1][RTW89_QATAR][8] = 40,
[0][1][2][1][RTW89_FCC][10] = 62,
[0][1][2][1][RTW89_ETSI][10] = 40,
[0][1][2][1][RTW89_MKK][10] = 54,
@@ -31268,6 +35392,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][10] = 40,
[0][1][2][1][RTW89_CN][10] = 36,
[0][1][2][1][RTW89_UK][10] = 40,
+ [0][1][2][1][RTW89_MEXICO][10] = 62,
+ [0][1][2][1][RTW89_UKRAINE][10] = 30,
+ [0][1][2][1][RTW89_CHILE][10] = 60,
+ [0][1][2][1][RTW89_QATAR][10] = 40,
[0][1][2][1][RTW89_FCC][12] = 62,
[0][1][2][1][RTW89_ETSI][12] = 40,
[0][1][2][1][RTW89_MKK][12] = 54,
@@ -31276,6 +35404,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][12] = 40,
[0][1][2][1][RTW89_CN][12] = 36,
[0][1][2][1][RTW89_UK][12] = 40,
+ [0][1][2][1][RTW89_MEXICO][12] = 62,
+ [0][1][2][1][RTW89_UKRAINE][12] = 30,
+ [0][1][2][1][RTW89_CHILE][12] = 60,
+ [0][1][2][1][RTW89_QATAR][12] = 40,
[0][1][2][1][RTW89_FCC][14] = 62,
[0][1][2][1][RTW89_ETSI][14] = 40,
[0][1][2][1][RTW89_MKK][14] = 54,
@@ -31284,6 +35416,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][14] = 40,
[0][1][2][1][RTW89_CN][14] = 36,
[0][1][2][1][RTW89_UK][14] = 40,
+ [0][1][2][1][RTW89_MEXICO][14] = 62,
+ [0][1][2][1][RTW89_UKRAINE][14] = 30,
+ [0][1][2][1][RTW89_CHILE][14] = 60,
+ [0][1][2][1][RTW89_QATAR][14] = 40,
[0][1][2][1][RTW89_FCC][15] = 60,
[0][1][2][1][RTW89_ETSI][15] = 40,
[0][1][2][1][RTW89_MKK][15] = 68,
@@ -31292,6 +35428,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][15] = 40,
[0][1][2][1][RTW89_CN][15] = 127,
[0][1][2][1][RTW89_UK][15] = 40,
+ [0][1][2][1][RTW89_MEXICO][15] = 60,
+ [0][1][2][1][RTW89_UKRAINE][15] = 30,
+ [0][1][2][1][RTW89_CHILE][15] = 60,
+ [0][1][2][1][RTW89_QATAR][15] = 40,
[0][1][2][1][RTW89_FCC][17] = 62,
[0][1][2][1][RTW89_ETSI][17] = 40,
[0][1][2][1][RTW89_MKK][17] = 68,
@@ -31300,6 +35440,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][17] = 40,
[0][1][2][1][RTW89_CN][17] = 127,
[0][1][2][1][RTW89_UK][17] = 40,
+ [0][1][2][1][RTW89_MEXICO][17] = 62,
+ [0][1][2][1][RTW89_UKRAINE][17] = 30,
+ [0][1][2][1][RTW89_CHILE][17] = 60,
+ [0][1][2][1][RTW89_QATAR][17] = 40,
[0][1][2][1][RTW89_FCC][19] = 62,
[0][1][2][1][RTW89_ETSI][19] = 40,
[0][1][2][1][RTW89_MKK][19] = 68,
@@ -31308,6 +35452,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][19] = 40,
[0][1][2][1][RTW89_CN][19] = 127,
[0][1][2][1][RTW89_UK][19] = 40,
+ [0][1][2][1][RTW89_MEXICO][19] = 62,
+ [0][1][2][1][RTW89_UKRAINE][19] = 30,
+ [0][1][2][1][RTW89_CHILE][19] = 60,
+ [0][1][2][1][RTW89_QATAR][19] = 40,
[0][1][2][1][RTW89_FCC][21] = 62,
[0][1][2][1][RTW89_ETSI][21] = 40,
[0][1][2][1][RTW89_MKK][21] = 68,
@@ -31316,6 +35464,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][21] = 40,
[0][1][2][1][RTW89_CN][21] = 127,
[0][1][2][1][RTW89_UK][21] = 40,
+ [0][1][2][1][RTW89_MEXICO][21] = 62,
+ [0][1][2][1][RTW89_UKRAINE][21] = 30,
+ [0][1][2][1][RTW89_CHILE][21] = 60,
+ [0][1][2][1][RTW89_QATAR][21] = 40,
[0][1][2][1][RTW89_FCC][23] = 62,
[0][1][2][1][RTW89_ETSI][23] = 40,
[0][1][2][1][RTW89_MKK][23] = 68,
@@ -31324,6 +35476,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][23] = 40,
[0][1][2][1][RTW89_CN][23] = 127,
[0][1][2][1][RTW89_UK][23] = 40,
+ [0][1][2][1][RTW89_MEXICO][23] = 62,
+ [0][1][2][1][RTW89_UKRAINE][23] = 30,
+ [0][1][2][1][RTW89_CHILE][23] = 60,
+ [0][1][2][1][RTW89_QATAR][23] = 40,
[0][1][2][1][RTW89_FCC][25] = 46,
[0][1][2][1][RTW89_ETSI][25] = 40,
[0][1][2][1][RTW89_MKK][25] = 68,
@@ -31332,6 +35488,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][25] = 127,
[0][1][2][1][RTW89_CN][25] = 127,
[0][1][2][1][RTW89_UK][25] = 40,
+ [0][1][2][1][RTW89_MEXICO][25] = 46,
+ [0][1][2][1][RTW89_UKRAINE][25] = 30,
+ [0][1][2][1][RTW89_CHILE][25] = 60,
+ [0][1][2][1][RTW89_QATAR][25] = 40,
[0][1][2][1][RTW89_FCC][27] = 46,
[0][1][2][1][RTW89_ETSI][27] = 40,
[0][1][2][1][RTW89_MKK][27] = 68,
@@ -31340,6 +35500,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][27] = 127,
[0][1][2][1][RTW89_CN][27] = 127,
[0][1][2][1][RTW89_UK][27] = 40,
+ [0][1][2][1][RTW89_MEXICO][27] = 46,
+ [0][1][2][1][RTW89_UKRAINE][27] = 30,
+ [0][1][2][1][RTW89_CHILE][27] = 46,
+ [0][1][2][1][RTW89_QATAR][27] = 40,
[0][1][2][1][RTW89_FCC][29] = 46,
[0][1][2][1][RTW89_ETSI][29] = 40,
[0][1][2][1][RTW89_MKK][29] = 68,
@@ -31348,6 +35512,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][29] = 127,
[0][1][2][1][RTW89_CN][29] = 127,
[0][1][2][1][RTW89_UK][29] = 40,
+ [0][1][2][1][RTW89_MEXICO][29] = 46,
+ [0][1][2][1][RTW89_UKRAINE][29] = 30,
+ [0][1][2][1][RTW89_CHILE][29] = 46,
+ [0][1][2][1][RTW89_QATAR][29] = 40,
[0][1][2][1][RTW89_FCC][31] = 46,
[0][1][2][1][RTW89_ETSI][31] = 40,
[0][1][2][1][RTW89_MKK][31] = 68,
@@ -31356,6 +35524,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][31] = 40,
[0][1][2][1][RTW89_CN][31] = 127,
[0][1][2][1][RTW89_UK][31] = 40,
+ [0][1][2][1][RTW89_MEXICO][31] = 46,
+ [0][1][2][1][RTW89_UKRAINE][31] = 30,
+ [0][1][2][1][RTW89_CHILE][31] = 46,
+ [0][1][2][1][RTW89_QATAR][31] = 40,
[0][1][2][1][RTW89_FCC][33] = 46,
[0][1][2][1][RTW89_ETSI][33] = 40,
[0][1][2][1][RTW89_MKK][33] = 68,
@@ -31364,6 +35536,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][33] = 40,
[0][1][2][1][RTW89_CN][33] = 127,
[0][1][2][1][RTW89_UK][33] = 40,
+ [0][1][2][1][RTW89_MEXICO][33] = 46,
+ [0][1][2][1][RTW89_UKRAINE][33] = 30,
+ [0][1][2][1][RTW89_CHILE][33] = 46,
+ [0][1][2][1][RTW89_QATAR][33] = 40,
[0][1][2][1][RTW89_FCC][35] = 46,
[0][1][2][1][RTW89_ETSI][35] = 40,
[0][1][2][1][RTW89_MKK][35] = 68,
@@ -31372,6 +35548,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][35] = 40,
[0][1][2][1][RTW89_CN][35] = 127,
[0][1][2][1][RTW89_UK][35] = 40,
+ [0][1][2][1][RTW89_MEXICO][35] = 46,
+ [0][1][2][1][RTW89_UKRAINE][35] = 30,
+ [0][1][2][1][RTW89_CHILE][35] = 46,
+ [0][1][2][1][RTW89_QATAR][35] = 40,
[0][1][2][1][RTW89_FCC][37] = 64,
[0][1][2][1][RTW89_ETSI][37] = 127,
[0][1][2][1][RTW89_MKK][37] = 68,
@@ -31380,6 +35560,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][37] = 64,
[0][1][2][1][RTW89_CN][37] = 127,
[0][1][2][1][RTW89_UK][37] = 40,
+ [0][1][2][1][RTW89_MEXICO][37] = 64,
+ [0][1][2][1][RTW89_UKRAINE][37] = 127,
+ [0][1][2][1][RTW89_CHILE][37] = 64,
+ [0][1][2][1][RTW89_QATAR][37] = 127,
[0][1][2][1][RTW89_FCC][38] = 72,
[0][1][2][1][RTW89_ETSI][38] = 6,
[0][1][2][1][RTW89_MKK][38] = 127,
@@ -31388,6 +35572,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][38] = 70,
[0][1][2][1][RTW89_CN][38] = 60,
[0][1][2][1][RTW89_UK][38] = 40,
+ [0][1][2][1][RTW89_MEXICO][38] = 72,
+ [0][1][2][1][RTW89_UKRAINE][38] = 6,
+ [0][1][2][1][RTW89_CHILE][38] = 60,
+ [0][1][2][1][RTW89_QATAR][38] = 6,
[0][1][2][1][RTW89_FCC][40] = 72,
[0][1][2][1][RTW89_ETSI][40] = 6,
[0][1][2][1][RTW89_MKK][40] = 127,
@@ -31396,6 +35584,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][40] = 70,
[0][1][2][1][RTW89_CN][40] = 60,
[0][1][2][1][RTW89_UK][40] = 40,
+ [0][1][2][1][RTW89_MEXICO][40] = 72,
+ [0][1][2][1][RTW89_UKRAINE][40] = 6,
+ [0][1][2][1][RTW89_CHILE][40] = 60,
+ [0][1][2][1][RTW89_QATAR][40] = 6,
[0][1][2][1][RTW89_FCC][42] = 72,
[0][1][2][1][RTW89_ETSI][42] = 6,
[0][1][2][1][RTW89_MKK][42] = 127,
@@ -31404,6 +35596,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][42] = 70,
[0][1][2][1][RTW89_CN][42] = 60,
[0][1][2][1][RTW89_UK][42] = 40,
+ [0][1][2][1][RTW89_MEXICO][42] = 72,
+ [0][1][2][1][RTW89_UKRAINE][42] = 6,
+ [0][1][2][1][RTW89_CHILE][42] = 60,
+ [0][1][2][1][RTW89_QATAR][42] = 6,
[0][1][2][1][RTW89_FCC][44] = 72,
[0][1][2][1][RTW89_ETSI][44] = 6,
[0][1][2][1][RTW89_MKK][44] = 127,
@@ -31412,6 +35608,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][44] = 70,
[0][1][2][1][RTW89_CN][44] = 54,
[0][1][2][1][RTW89_UK][44] = 40,
+ [0][1][2][1][RTW89_MEXICO][44] = 72,
+ [0][1][2][1][RTW89_UKRAINE][44] = 6,
+ [0][1][2][1][RTW89_CHILE][44] = 60,
+ [0][1][2][1][RTW89_QATAR][44] = 6,
[0][1][2][1][RTW89_FCC][46] = 72,
[0][1][2][1][RTW89_ETSI][46] = 6,
[0][1][2][1][RTW89_MKK][46] = 127,
@@ -31420,6 +35620,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][46] = 70,
[0][1][2][1][RTW89_CN][46] = 54,
[0][1][2][1][RTW89_UK][46] = 40,
+ [0][1][2][1][RTW89_MEXICO][46] = 72,
+ [0][1][2][1][RTW89_UKRAINE][46] = 6,
+ [0][1][2][1][RTW89_CHILE][46] = 60,
+ [0][1][2][1][RTW89_QATAR][46] = 6,
[0][1][2][1][RTW89_FCC][48] = 48,
[0][1][2][1][RTW89_ETSI][48] = 127,
[0][1][2][1][RTW89_MKK][48] = 127,
@@ -31428,6 +35632,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][48] = 127,
[0][1][2][1][RTW89_CN][48] = 127,
[0][1][2][1][RTW89_UK][48] = 127,
+ [0][1][2][1][RTW89_MEXICO][48] = 127,
+ [0][1][2][1][RTW89_UKRAINE][48] = 127,
+ [0][1][2][1][RTW89_CHILE][48] = 127,
+ [0][1][2][1][RTW89_QATAR][48] = 127,
[0][1][2][1][RTW89_FCC][50] = 50,
[0][1][2][1][RTW89_ETSI][50] = 127,
[0][1][2][1][RTW89_MKK][50] = 127,
@@ -31436,6 +35644,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][50] = 127,
[0][1][2][1][RTW89_CN][50] = 127,
[0][1][2][1][RTW89_UK][50] = 127,
+ [0][1][2][1][RTW89_MEXICO][50] = 127,
+ [0][1][2][1][RTW89_UKRAINE][50] = 127,
+ [0][1][2][1][RTW89_CHILE][50] = 127,
+ [0][1][2][1][RTW89_QATAR][50] = 127,
[0][1][2][1][RTW89_FCC][52] = 48,
[0][1][2][1][RTW89_ETSI][52] = 127,
[0][1][2][1][RTW89_MKK][52] = 127,
@@ -31444,22 +35656,34 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][52] = 127,
[0][1][2][1][RTW89_CN][52] = 127,
[0][1][2][1][RTW89_UK][52] = 127,
+ [0][1][2][1][RTW89_MEXICO][52] = 127,
+ [0][1][2][1][RTW89_UKRAINE][52] = 127,
+ [0][1][2][1][RTW89_CHILE][52] = 127,
+ [0][1][2][1][RTW89_QATAR][52] = 127,
[1][0][2][0][RTW89_FCC][1] = 64,
[1][0][2][0][RTW89_ETSI][1] = 66,
[1][0][2][0][RTW89_MKK][1] = 66,
[1][0][2][0][RTW89_IC][1] = 62,
- [1][0][2][0][RTW89_KCC][1] = 66,
+ [1][0][2][0][RTW89_KCC][1] = 54,
[1][0][2][0][RTW89_ACMA][1] = 66,
[1][0][2][0][RTW89_CN][1] = 54,
[1][0][2][0][RTW89_UK][1] = 66,
+ [1][0][2][0][RTW89_MEXICO][1] = 62,
+ [1][0][2][0][RTW89_UKRAINE][1] = 54,
+ [1][0][2][0][RTW89_CHILE][1] = 62,
+ [1][0][2][0][RTW89_QATAR][1] = 66,
[1][0][2][0][RTW89_FCC][5] = 68,
[1][0][2][0][RTW89_ETSI][5] = 66,
[1][0][2][0][RTW89_MKK][5] = 66,
[1][0][2][0][RTW89_IC][5] = 64,
- [1][0][2][0][RTW89_KCC][5] = 54,
+ [1][0][2][0][RTW89_KCC][5] = 66,
[1][0][2][0][RTW89_ACMA][5] = 66,
[1][0][2][0][RTW89_CN][5] = 54,
[1][0][2][0][RTW89_UK][5] = 66,
+ [1][0][2][0][RTW89_MEXICO][5] = 62,
+ [1][0][2][0][RTW89_UKRAINE][5] = 54,
+ [1][0][2][0][RTW89_CHILE][5] = 66,
+ [1][0][2][0][RTW89_QATAR][5] = 66,
[1][0][2][0][RTW89_FCC][9] = 68,
[1][0][2][0][RTW89_ETSI][9] = 66,
[1][0][2][0][RTW89_MKK][9] = 66,
@@ -31468,6 +35692,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][9] = 66,
[1][0][2][0][RTW89_CN][9] = 54,
[1][0][2][0][RTW89_UK][9] = 66,
+ [1][0][2][0][RTW89_MEXICO][9] = 68,
+ [1][0][2][0][RTW89_UKRAINE][9] = 54,
+ [1][0][2][0][RTW89_CHILE][9] = 66,
+ [1][0][2][0][RTW89_QATAR][9] = 66,
[1][0][2][0][RTW89_FCC][13] = 60,
[1][0][2][0][RTW89_ETSI][13] = 66,
[1][0][2][0][RTW89_MKK][13] = 66,
@@ -31476,6 +35704,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][13] = 66,
[1][0][2][0][RTW89_CN][13] = 54,
[1][0][2][0][RTW89_UK][13] = 66,
+ [1][0][2][0][RTW89_MEXICO][13] = 60,
+ [1][0][2][0][RTW89_UKRAINE][13] = 54,
+ [1][0][2][0][RTW89_CHILE][13] = 60,
+ [1][0][2][0][RTW89_QATAR][13] = 66,
[1][0][2][0][RTW89_FCC][16] = 64,
[1][0][2][0][RTW89_ETSI][16] = 66,
[1][0][2][0][RTW89_MKK][16] = 66,
@@ -31484,6 +35716,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][16] = 66,
[1][0][2][0][RTW89_CN][16] = 127,
[1][0][2][0][RTW89_UK][16] = 66,
+ [1][0][2][0][RTW89_MEXICO][16] = 64,
+ [1][0][2][0][RTW89_UKRAINE][16] = 54,
+ [1][0][2][0][RTW89_CHILE][16] = 64,
+ [1][0][2][0][RTW89_QATAR][16] = 66,
[1][0][2][0][RTW89_FCC][20] = 68,
[1][0][2][0][RTW89_ETSI][20] = 66,
[1][0][2][0][RTW89_MKK][20] = 66,
@@ -31492,6 +35728,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][20] = 66,
[1][0][2][0][RTW89_CN][20] = 127,
[1][0][2][0][RTW89_UK][20] = 66,
+ [1][0][2][0][RTW89_MEXICO][20] = 68,
+ [1][0][2][0][RTW89_UKRAINE][20] = 54,
+ [1][0][2][0][RTW89_CHILE][20] = 66,
+ [1][0][2][0][RTW89_QATAR][20] = 66,
[1][0][2][0][RTW89_FCC][24] = 68,
[1][0][2][0][RTW89_ETSI][24] = 66,
[1][0][2][0][RTW89_MKK][24] = 66,
@@ -31500,6 +35740,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][24] = 127,
[1][0][2][0][RTW89_CN][24] = 127,
[1][0][2][0][RTW89_UK][24] = 66,
+ [1][0][2][0][RTW89_MEXICO][24] = 68,
+ [1][0][2][0][RTW89_UKRAINE][24] = 54,
+ [1][0][2][0][RTW89_CHILE][24] = 66,
+ [1][0][2][0][RTW89_QATAR][24] = 66,
[1][0][2][0][RTW89_FCC][28] = 68,
[1][0][2][0][RTW89_ETSI][28] = 66,
[1][0][2][0][RTW89_MKK][28] = 66,
@@ -31508,6 +35752,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][28] = 127,
[1][0][2][0][RTW89_CN][28] = 127,
[1][0][2][0][RTW89_UK][28] = 66,
+ [1][0][2][0][RTW89_MEXICO][28] = 68,
+ [1][0][2][0][RTW89_UKRAINE][28] = 54,
+ [1][0][2][0][RTW89_CHILE][28] = 62,
+ [1][0][2][0][RTW89_QATAR][28] = 66,
[1][0][2][0][RTW89_FCC][32] = 62,
[1][0][2][0][RTW89_ETSI][32] = 66,
[1][0][2][0][RTW89_MKK][32] = 66,
@@ -31516,6 +35764,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][32] = 66,
[1][0][2][0][RTW89_CN][32] = 127,
[1][0][2][0][RTW89_UK][32] = 66,
+ [1][0][2][0][RTW89_MEXICO][32] = 62,
+ [1][0][2][0][RTW89_UKRAINE][32] = 54,
+ [1][0][2][0][RTW89_CHILE][32] = 62,
+ [1][0][2][0][RTW89_QATAR][32] = 66,
[1][0][2][0][RTW89_FCC][36] = 68,
[1][0][2][0][RTW89_ETSI][36] = 127,
[1][0][2][0][RTW89_MKK][36] = 66,
@@ -31524,6 +35776,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][36] = 66,
[1][0][2][0][RTW89_CN][36] = 127,
[1][0][2][0][RTW89_UK][36] = 64,
+ [1][0][2][0][RTW89_MEXICO][36] = 68,
+ [1][0][2][0][RTW89_UKRAINE][36] = 127,
+ [1][0][2][0][RTW89_CHILE][36] = 66,
+ [1][0][2][0][RTW89_QATAR][36] = 127,
[1][0][2][0][RTW89_FCC][39] = 68,
[1][0][2][0][RTW89_ETSI][39] = 30,
[1][0][2][0][RTW89_MKK][39] = 127,
@@ -31532,6 +35788,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][39] = 66,
[1][0][2][0][RTW89_CN][39] = 62,
[1][0][2][0][RTW89_UK][39] = 64,
+ [1][0][2][0][RTW89_MEXICO][39] = 68,
+ [1][0][2][0][RTW89_UKRAINE][39] = 30,
+ [1][0][2][0][RTW89_CHILE][39] = 66,
+ [1][0][2][0][RTW89_QATAR][39] = 30,
[1][0][2][0][RTW89_FCC][43] = 68,
[1][0][2][0][RTW89_ETSI][43] = 30,
[1][0][2][0][RTW89_MKK][43] = 127,
@@ -31540,6 +35800,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][43] = 66,
[1][0][2][0][RTW89_CN][43] = 66,
[1][0][2][0][RTW89_UK][43] = 64,
+ [1][0][2][0][RTW89_MEXICO][43] = 68,
+ [1][0][2][0][RTW89_UKRAINE][43] = 30,
+ [1][0][2][0][RTW89_CHILE][43] = 66,
+ [1][0][2][0][RTW89_QATAR][43] = 30,
[1][0][2][0][RTW89_FCC][47] = 68,
[1][0][2][0][RTW89_ETSI][47] = 127,
[1][0][2][0][RTW89_MKK][47] = 127,
@@ -31548,6 +35812,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][47] = 127,
[1][0][2][0][RTW89_CN][47] = 127,
[1][0][2][0][RTW89_UK][47] = 127,
+ [1][0][2][0][RTW89_MEXICO][47] = 127,
+ [1][0][2][0][RTW89_UKRAINE][47] = 127,
+ [1][0][2][0][RTW89_CHILE][47] = 127,
+ [1][0][2][0][RTW89_QATAR][47] = 127,
[1][0][2][0][RTW89_FCC][51] = 68,
[1][0][2][0][RTW89_ETSI][51] = 127,
[1][0][2][0][RTW89_MKK][51] = 127,
@@ -31556,6 +35824,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][51] = 127,
[1][0][2][0][RTW89_CN][51] = 127,
[1][0][2][0][RTW89_UK][51] = 127,
+ [1][0][2][0][RTW89_MEXICO][51] = 127,
+ [1][0][2][0][RTW89_UKRAINE][51] = 127,
+ [1][0][2][0][RTW89_CHILE][51] = 127,
+ [1][0][2][0][RTW89_QATAR][51] = 127,
[1][1][2][0][RTW89_FCC][1] = 54,
[1][1][2][0][RTW89_ETSI][1] = 54,
[1][1][2][0][RTW89_MKK][1] = 48,
@@ -31564,6 +35836,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][1] = 54,
[1][1][2][0][RTW89_CN][1] = 42,
[1][1][2][0][RTW89_UK][1] = 54,
+ [1][1][2][0][RTW89_MEXICO][1] = 50,
+ [1][1][2][0][RTW89_UKRAINE][1] = 42,
+ [1][1][2][0][RTW89_CHILE][1] = 54,
+ [1][1][2][0][RTW89_QATAR][1] = 54,
[1][1][2][0][RTW89_FCC][5] = 68,
[1][1][2][0][RTW89_ETSI][5] = 54,
[1][1][2][0][RTW89_MKK][5] = 52,
@@ -31572,6 +35848,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][5] = 54,
[1][1][2][0][RTW89_CN][5] = 42,
[1][1][2][0][RTW89_UK][5] = 54,
+ [1][1][2][0][RTW89_MEXICO][5] = 50,
+ [1][1][2][0][RTW89_UKRAINE][5] = 42,
+ [1][1][2][0][RTW89_CHILE][5] = 66,
+ [1][1][2][0][RTW89_QATAR][5] = 54,
[1][1][2][0][RTW89_FCC][9] = 68,
[1][1][2][0][RTW89_ETSI][9] = 54,
[1][1][2][0][RTW89_MKK][9] = 52,
@@ -31580,6 +35860,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][9] = 54,
[1][1][2][0][RTW89_CN][9] = 42,
[1][1][2][0][RTW89_UK][9] = 54,
+ [1][1][2][0][RTW89_MEXICO][9] = 68,
+ [1][1][2][0][RTW89_UKRAINE][9] = 42,
+ [1][1][2][0][RTW89_CHILE][9] = 66,
+ [1][1][2][0][RTW89_QATAR][9] = 54,
[1][1][2][0][RTW89_FCC][13] = 54,
[1][1][2][0][RTW89_ETSI][13] = 54,
[1][1][2][0][RTW89_MKK][13] = 52,
@@ -31588,6 +35872,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][13] = 54,
[1][1][2][0][RTW89_CN][13] = 42,
[1][1][2][0][RTW89_UK][13] = 54,
+ [1][1][2][0][RTW89_MEXICO][13] = 54,
+ [1][1][2][0][RTW89_UKRAINE][13] = 42,
+ [1][1][2][0][RTW89_CHILE][13] = 54,
+ [1][1][2][0][RTW89_QATAR][13] = 54,
[1][1][2][0][RTW89_FCC][16] = 56,
[1][1][2][0][RTW89_ETSI][16] = 54,
[1][1][2][0][RTW89_MKK][16] = 66,
@@ -31596,6 +35884,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][16] = 54,
[1][1][2][0][RTW89_CN][16] = 127,
[1][1][2][0][RTW89_UK][16] = 54,
+ [1][1][2][0][RTW89_MEXICO][16] = 56,
+ [1][1][2][0][RTW89_UKRAINE][16] = 42,
+ [1][1][2][0][RTW89_CHILE][16] = 54,
+ [1][1][2][0][RTW89_QATAR][16] = 54,
[1][1][2][0][RTW89_FCC][20] = 68,
[1][1][2][0][RTW89_ETSI][20] = 54,
[1][1][2][0][RTW89_MKK][20] = 66,
@@ -31604,6 +35896,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][20] = 54,
[1][1][2][0][RTW89_CN][20] = 127,
[1][1][2][0][RTW89_UK][20] = 54,
+ [1][1][2][0][RTW89_MEXICO][20] = 68,
+ [1][1][2][0][RTW89_UKRAINE][20] = 42,
+ [1][1][2][0][RTW89_CHILE][20] = 66,
+ [1][1][2][0][RTW89_QATAR][20] = 54,
[1][1][2][0][RTW89_FCC][24] = 68,
[1][1][2][0][RTW89_ETSI][24] = 54,
[1][1][2][0][RTW89_MKK][24] = 66,
@@ -31612,6 +35908,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][24] = 127,
[1][1][2][0][RTW89_CN][24] = 127,
[1][1][2][0][RTW89_UK][24] = 54,
+ [1][1][2][0][RTW89_MEXICO][24] = 68,
+ [1][1][2][0][RTW89_UKRAINE][24] = 42,
+ [1][1][2][0][RTW89_CHILE][24] = 66,
+ [1][1][2][0][RTW89_QATAR][24] = 54,
[1][1][2][0][RTW89_FCC][28] = 68,
[1][1][2][0][RTW89_ETSI][28] = 54,
[1][1][2][0][RTW89_MKK][28] = 66,
@@ -31620,6 +35920,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][28] = 127,
[1][1][2][0][RTW89_CN][28] = 127,
[1][1][2][0][RTW89_UK][28] = 54,
+ [1][1][2][0][RTW89_MEXICO][28] = 68,
+ [1][1][2][0][RTW89_UKRAINE][28] = 42,
+ [1][1][2][0][RTW89_CHILE][28] = 54,
+ [1][1][2][0][RTW89_QATAR][28] = 54,
[1][1][2][0][RTW89_FCC][32] = 56,
[1][1][2][0][RTW89_ETSI][32] = 54,
[1][1][2][0][RTW89_MKK][32] = 66,
@@ -31628,6 +35932,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][32] = 54,
[1][1][2][0][RTW89_CN][32] = 127,
[1][1][2][0][RTW89_UK][32] = 54,
+ [1][1][2][0][RTW89_MEXICO][32] = 56,
+ [1][1][2][0][RTW89_UKRAINE][32] = 42,
+ [1][1][2][0][RTW89_CHILE][32] = 54,
+ [1][1][2][0][RTW89_QATAR][32] = 54,
[1][1][2][0][RTW89_FCC][36] = 68,
[1][1][2][0][RTW89_ETSI][36] = 127,
[1][1][2][0][RTW89_MKK][36] = 66,
@@ -31636,6 +35944,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][36] = 66,
[1][1][2][0][RTW89_CN][36] = 127,
[1][1][2][0][RTW89_UK][36] = 52,
+ [1][1][2][0][RTW89_MEXICO][36] = 68,
+ [1][1][2][0][RTW89_UKRAINE][36] = 127,
+ [1][1][2][0][RTW89_CHILE][36] = 66,
+ [1][1][2][0][RTW89_QATAR][36] = 127,
[1][1][2][0][RTW89_FCC][39] = 68,
[1][1][2][0][RTW89_ETSI][39] = 18,
[1][1][2][0][RTW89_MKK][39] = 127,
@@ -31644,6 +35956,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][39] = 66,
[1][1][2][0][RTW89_CN][39] = 62,
[1][1][2][0][RTW89_UK][39] = 52,
+ [1][1][2][0][RTW89_MEXICO][39] = 68,
+ [1][1][2][0][RTW89_UKRAINE][39] = 18,
+ [1][1][2][0][RTW89_CHILE][39] = 66,
+ [1][1][2][0][RTW89_QATAR][39] = 18,
[1][1][2][0][RTW89_FCC][43] = 68,
[1][1][2][0][RTW89_ETSI][43] = 18,
[1][1][2][0][RTW89_MKK][43] = 127,
@@ -31652,6 +35968,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][43] = 66,
[1][1][2][0][RTW89_CN][43] = 66,
[1][1][2][0][RTW89_UK][43] = 52,
+ [1][1][2][0][RTW89_MEXICO][43] = 68,
+ [1][1][2][0][RTW89_UKRAINE][43] = 18,
+ [1][1][2][0][RTW89_CHILE][43] = 66,
+ [1][1][2][0][RTW89_QATAR][43] = 18,
[1][1][2][0][RTW89_FCC][47] = 62,
[1][1][2][0][RTW89_ETSI][47] = 127,
[1][1][2][0][RTW89_MKK][47] = 127,
@@ -31660,6 +35980,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][47] = 127,
[1][1][2][0][RTW89_CN][47] = 127,
[1][1][2][0][RTW89_UK][47] = 127,
+ [1][1][2][0][RTW89_MEXICO][47] = 127,
+ [1][1][2][0][RTW89_UKRAINE][47] = 127,
+ [1][1][2][0][RTW89_CHILE][47] = 127,
+ [1][1][2][0][RTW89_QATAR][47] = 127,
[1][1][2][0][RTW89_FCC][51] = 60,
[1][1][2][0][RTW89_ETSI][51] = 127,
[1][1][2][0][RTW89_MKK][51] = 127,
@@ -31668,6 +35992,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][51] = 127,
[1][1][2][0][RTW89_CN][51] = 127,
[1][1][2][0][RTW89_UK][51] = 127,
+ [1][1][2][0][RTW89_MEXICO][51] = 127,
+ [1][1][2][0][RTW89_UKRAINE][51] = 127,
+ [1][1][2][0][RTW89_CHILE][51] = 127,
+ [1][1][2][0][RTW89_QATAR][51] = 127,
[1][1][2][1][RTW89_FCC][1] = 54,
[1][1][2][1][RTW89_ETSI][1] = 40,
[1][1][2][1][RTW89_MKK][1] = 48,
@@ -31676,6 +36004,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][1] = 40,
[1][1][2][1][RTW89_CN][1] = 42,
[1][1][2][1][RTW89_UK][1] = 40,
+ [1][1][2][1][RTW89_MEXICO][1] = 50,
+ [1][1][2][1][RTW89_UKRAINE][1] = 30,
+ [1][1][2][1][RTW89_CHILE][1] = 54,
+ [1][1][2][1][RTW89_QATAR][1] = 40,
[1][1][2][1][RTW89_FCC][5] = 68,
[1][1][2][1][RTW89_ETSI][5] = 40,
[1][1][2][1][RTW89_MKK][5] = 52,
@@ -31684,6 +36016,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][5] = 40,
[1][1][2][1][RTW89_CN][5] = 42,
[1][1][2][1][RTW89_UK][5] = 40,
+ [1][1][2][1][RTW89_MEXICO][5] = 50,
+ [1][1][2][1][RTW89_UKRAINE][5] = 30,
+ [1][1][2][1][RTW89_CHILE][5] = 60,
+ [1][1][2][1][RTW89_QATAR][5] = 40,
[1][1][2][1][RTW89_FCC][9] = 68,
[1][1][2][1][RTW89_ETSI][9] = 40,
[1][1][2][1][RTW89_MKK][9] = 52,
@@ -31692,6 +36028,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][9] = 40,
[1][1][2][1][RTW89_CN][9] = 42,
[1][1][2][1][RTW89_UK][9] = 40,
+ [1][1][2][1][RTW89_MEXICO][9] = 68,
+ [1][1][2][1][RTW89_UKRAINE][9] = 30,
+ [1][1][2][1][RTW89_CHILE][9] = 60,
+ [1][1][2][1][RTW89_QATAR][9] = 40,
[1][1][2][1][RTW89_FCC][13] = 54,
[1][1][2][1][RTW89_ETSI][13] = 40,
[1][1][2][1][RTW89_MKK][13] = 52,
@@ -31700,6 +36040,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][13] = 40,
[1][1][2][1][RTW89_CN][13] = 42,
[1][1][2][1][RTW89_UK][13] = 40,
+ [1][1][2][1][RTW89_MEXICO][13] = 54,
+ [1][1][2][1][RTW89_UKRAINE][13] = 30,
+ [1][1][2][1][RTW89_CHILE][13] = 54,
+ [1][1][2][1][RTW89_QATAR][13] = 40,
[1][1][2][1][RTW89_FCC][16] = 56,
[1][1][2][1][RTW89_ETSI][16] = 40,
[1][1][2][1][RTW89_MKK][16] = 66,
@@ -31708,6 +36052,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][16] = 40,
[1][1][2][1][RTW89_CN][16] = 127,
[1][1][2][1][RTW89_UK][16] = 40,
+ [1][1][2][1][RTW89_MEXICO][16] = 56,
+ [1][1][2][1][RTW89_UKRAINE][16] = 30,
+ [1][1][2][1][RTW89_CHILE][16] = 54,
+ [1][1][2][1][RTW89_QATAR][16] = 40,
[1][1][2][1][RTW89_FCC][20] = 68,
[1][1][2][1][RTW89_ETSI][20] = 40,
[1][1][2][1][RTW89_MKK][20] = 66,
@@ -31716,6 +36064,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][20] = 40,
[1][1][2][1][RTW89_CN][20] = 127,
[1][1][2][1][RTW89_UK][20] = 40,
+ [1][1][2][1][RTW89_MEXICO][20] = 68,
+ [1][1][2][1][RTW89_UKRAINE][20] = 30,
+ [1][1][2][1][RTW89_CHILE][20] = 60,
+ [1][1][2][1][RTW89_QATAR][20] = 40,
[1][1][2][1][RTW89_FCC][24] = 68,
[1][1][2][1][RTW89_ETSI][24] = 40,
[1][1][2][1][RTW89_MKK][24] = 66,
@@ -31724,6 +36076,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][24] = 127,
[1][1][2][1][RTW89_CN][24] = 127,
[1][1][2][1][RTW89_UK][24] = 40,
+ [1][1][2][1][RTW89_MEXICO][24] = 68,
+ [1][1][2][1][RTW89_UKRAINE][24] = 30,
+ [1][1][2][1][RTW89_CHILE][24] = 60,
+ [1][1][2][1][RTW89_QATAR][24] = 40,
[1][1][2][1][RTW89_FCC][28] = 68,
[1][1][2][1][RTW89_ETSI][28] = 40,
[1][1][2][1][RTW89_MKK][28] = 66,
@@ -31732,6 +36088,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][28] = 127,
[1][1][2][1][RTW89_CN][28] = 127,
[1][1][2][1][RTW89_UK][28] = 40,
+ [1][1][2][1][RTW89_MEXICO][28] = 68,
+ [1][1][2][1][RTW89_UKRAINE][28] = 30,
+ [1][1][2][1][RTW89_CHILE][28] = 54,
+ [1][1][2][1][RTW89_QATAR][28] = 40,
[1][1][2][1][RTW89_FCC][32] = 56,
[1][1][2][1][RTW89_ETSI][32] = 40,
[1][1][2][1][RTW89_MKK][32] = 66,
@@ -31740,6 +36100,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][32] = 40,
[1][1][2][1][RTW89_CN][32] = 127,
[1][1][2][1][RTW89_UK][32] = 40,
+ [1][1][2][1][RTW89_MEXICO][32] = 56,
+ [1][1][2][1][RTW89_UKRAINE][32] = 30,
+ [1][1][2][1][RTW89_CHILE][32] = 54,
+ [1][1][2][1][RTW89_QATAR][32] = 40,
[1][1][2][1][RTW89_FCC][36] = 68,
[1][1][2][1][RTW89_ETSI][36] = 127,
[1][1][2][1][RTW89_MKK][36] = 66,
@@ -31748,6 +36112,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][36] = 66,
[1][1][2][1][RTW89_CN][36] = 127,
[1][1][2][1][RTW89_UK][36] = 40,
+ [1][1][2][1][RTW89_MEXICO][36] = 68,
+ [1][1][2][1][RTW89_UKRAINE][36] = 127,
+ [1][1][2][1][RTW89_CHILE][36] = 66,
+ [1][1][2][1][RTW89_QATAR][36] = 127,
[1][1][2][1][RTW89_FCC][39] = 68,
[1][1][2][1][RTW89_ETSI][39] = 6,
[1][1][2][1][RTW89_MKK][39] = 127,
@@ -31756,6 +36124,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][39] = 66,
[1][1][2][1][RTW89_CN][39] = 60,
[1][1][2][1][RTW89_UK][39] = 40,
+ [1][1][2][1][RTW89_MEXICO][39] = 68,
+ [1][1][2][1][RTW89_UKRAINE][39] = 6,
+ [1][1][2][1][RTW89_CHILE][39] = 60,
+ [1][1][2][1][RTW89_QATAR][39] = 6,
[1][1][2][1][RTW89_FCC][43] = 68,
[1][1][2][1][RTW89_ETSI][43] = 6,
[1][1][2][1][RTW89_MKK][43] = 127,
@@ -31764,6 +36136,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][43] = 66,
[1][1][2][1][RTW89_CN][43] = 52,
[1][1][2][1][RTW89_UK][43] = 40,
+ [1][1][2][1][RTW89_MEXICO][43] = 68,
+ [1][1][2][1][RTW89_UKRAINE][43] = 6,
+ [1][1][2][1][RTW89_CHILE][43] = 60,
+ [1][1][2][1][RTW89_QATAR][43] = 6,
[1][1][2][1][RTW89_FCC][47] = 62,
[1][1][2][1][RTW89_ETSI][47] = 127,
[1][1][2][1][RTW89_MKK][47] = 127,
@@ -31772,6 +36148,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][47] = 127,
[1][1][2][1][RTW89_CN][47] = 127,
[1][1][2][1][RTW89_UK][47] = 127,
+ [1][1][2][1][RTW89_MEXICO][47] = 127,
+ [1][1][2][1][RTW89_UKRAINE][47] = 127,
+ [1][1][2][1][RTW89_CHILE][47] = 127,
+ [1][1][2][1][RTW89_QATAR][47] = 127,
[1][1][2][1][RTW89_FCC][51] = 60,
[1][1][2][1][RTW89_ETSI][51] = 127,
[1][1][2][1][RTW89_MKK][51] = 127,
@@ -31780,6 +36160,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][51] = 127,
[1][1][2][1][RTW89_CN][51] = 127,
[1][1][2][1][RTW89_UK][51] = 127,
+ [1][1][2][1][RTW89_MEXICO][51] = 127,
+ [1][1][2][1][RTW89_UKRAINE][51] = 127,
+ [1][1][2][1][RTW89_CHILE][51] = 127,
+ [1][1][2][1][RTW89_QATAR][51] = 127,
[2][0][2][0][RTW89_FCC][3] = 58,
[2][0][2][0][RTW89_ETSI][3] = 60,
[2][0][2][0][RTW89_MKK][3] = 60,
@@ -31788,6 +36172,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_ACMA][3] = 60,
[2][0][2][0][RTW89_CN][3] = 54,
[2][0][2][0][RTW89_UK][3] = 60,
+ [2][0][2][0][RTW89_MEXICO][3] = 58,
+ [2][0][2][0][RTW89_UKRAINE][3] = 54,
+ [2][0][2][0][RTW89_CHILE][3] = 58,
+ [2][0][2][0][RTW89_QATAR][3] = 60,
[2][0][2][0][RTW89_FCC][11] = 50,
[2][0][2][0][RTW89_ETSI][11] = 60,
[2][0][2][0][RTW89_MKK][11] = 60,
@@ -31796,6 +36184,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_ACMA][11] = 60,
[2][0][2][0][RTW89_CN][11] = 54,
[2][0][2][0][RTW89_UK][11] = 60,
+ [2][0][2][0][RTW89_MEXICO][11] = 50,
+ [2][0][2][0][RTW89_UKRAINE][11] = 54,
+ [2][0][2][0][RTW89_CHILE][11] = 50,
+ [2][0][2][0][RTW89_QATAR][11] = 60,
[2][0][2][0][RTW89_FCC][18] = 60,
[2][0][2][0][RTW89_ETSI][18] = 60,
[2][0][2][0][RTW89_MKK][18] = 60,
@@ -31804,6 +36196,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_ACMA][18] = 60,
[2][0][2][0][RTW89_CN][18] = 127,
[2][0][2][0][RTW89_UK][18] = 60,
+ [2][0][2][0][RTW89_MEXICO][18] = 60,
+ [2][0][2][0][RTW89_UKRAINE][18] = 54,
+ [2][0][2][0][RTW89_CHILE][18] = 60,
+ [2][0][2][0][RTW89_QATAR][18] = 60,
[2][0][2][0][RTW89_FCC][26] = 62,
[2][0][2][0][RTW89_ETSI][26] = 60,
[2][0][2][0][RTW89_MKK][26] = 60,
@@ -31812,6 +36208,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_ACMA][26] = 127,
[2][0][2][0][RTW89_CN][26] = 127,
[2][0][2][0][RTW89_UK][26] = 60,
+ [2][0][2][0][RTW89_MEXICO][26] = 62,
+ [2][0][2][0][RTW89_UKRAINE][26] = 54,
+ [2][0][2][0][RTW89_CHILE][26] = 60,
+ [2][0][2][0][RTW89_QATAR][26] = 60,
[2][0][2][0][RTW89_FCC][34] = 62,
[2][0][2][0][RTW89_ETSI][34] = 127,
[2][0][2][0][RTW89_MKK][34] = 60,
@@ -31820,6 +36220,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_ACMA][34] = 60,
[2][0][2][0][RTW89_CN][34] = 127,
[2][0][2][0][RTW89_UK][34] = 60,
+ [2][0][2][0][RTW89_MEXICO][34] = 62,
+ [2][0][2][0][RTW89_UKRAINE][34] = 127,
+ [2][0][2][0][RTW89_CHILE][34] = 60,
+ [2][0][2][0][RTW89_QATAR][34] = 127,
[2][0][2][0][RTW89_FCC][41] = 62,
[2][0][2][0][RTW89_ETSI][41] = 30,
[2][0][2][0][RTW89_MKK][41] = 127,
@@ -31828,6 +36232,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_ACMA][41] = 60,
[2][0][2][0][RTW89_CN][41] = 62,
[2][0][2][0][RTW89_UK][41] = 60,
+ [2][0][2][0][RTW89_MEXICO][41] = 62,
+ [2][0][2][0][RTW89_UKRAINE][41] = 30,
+ [2][0][2][0][RTW89_CHILE][41] = 60,
+ [2][0][2][0][RTW89_QATAR][41] = 30,
[2][0][2][0][RTW89_FCC][49] = 62,
[2][0][2][0][RTW89_ETSI][49] = 127,
[2][0][2][0][RTW89_MKK][49] = 127,
@@ -31836,6 +36244,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_ACMA][49] = 127,
[2][0][2][0][RTW89_CN][49] = 127,
[2][0][2][0][RTW89_UK][49] = 127,
+ [2][0][2][0][RTW89_MEXICO][49] = 127,
+ [2][0][2][0][RTW89_UKRAINE][49] = 127,
+ [2][0][2][0][RTW89_CHILE][49] = 127,
+ [2][0][2][0][RTW89_QATAR][49] = 127,
[2][1][2][0][RTW89_FCC][3] = 48,
[2][1][2][0][RTW89_ETSI][3] = 54,
[2][1][2][0][RTW89_MKK][3] = 56,
@@ -31844,6 +36256,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][0][RTW89_ACMA][3] = 54,
[2][1][2][0][RTW89_CN][3] = 52,
[2][1][2][0][RTW89_UK][3] = 54,
+ [2][1][2][0][RTW89_MEXICO][3] = 48,
+ [2][1][2][0][RTW89_UKRAINE][3] = 42,
+ [2][1][2][0][RTW89_CHILE][3] = 46,
+ [2][1][2][0][RTW89_QATAR][3] = 54,
[2][1][2][0][RTW89_FCC][11] = 38,
[2][1][2][0][RTW89_ETSI][11] = 54,
[2][1][2][0][RTW89_MKK][11] = 54,
@@ -31852,6 +36268,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][0][RTW89_ACMA][11] = 54,
[2][1][2][0][RTW89_CN][11] = 52,
[2][1][2][0][RTW89_UK][11] = 54,
+ [2][1][2][0][RTW89_MEXICO][11] = 38,
+ [2][1][2][0][RTW89_UKRAINE][11] = 42,
+ [2][1][2][0][RTW89_CHILE][11] = 38,
+ [2][1][2][0][RTW89_QATAR][11] = 54,
[2][1][2][0][RTW89_FCC][18] = 50,
[2][1][2][0][RTW89_ETSI][18] = 54,
[2][1][2][0][RTW89_MKK][18] = 60,
@@ -31860,6 +36280,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][0][RTW89_ACMA][18] = 54,
[2][1][2][0][RTW89_CN][18] = 127,
[2][1][2][0][RTW89_UK][18] = 54,
+ [2][1][2][0][RTW89_MEXICO][18] = 50,
+ [2][1][2][0][RTW89_UKRAINE][18] = 42,
+ [2][1][2][0][RTW89_CHILE][18] = 50,
+ [2][1][2][0][RTW89_QATAR][18] = 54,
[2][1][2][0][RTW89_FCC][26] = 52,
[2][1][2][0][RTW89_ETSI][26] = 54,
[2][1][2][0][RTW89_MKK][26] = 56,
@@ -31868,6 +36292,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][0][RTW89_ACMA][26] = 127,
[2][1][2][0][RTW89_CN][26] = 127,
[2][1][2][0][RTW89_UK][26] = 54,
+ [2][1][2][0][RTW89_MEXICO][26] = 52,
+ [2][1][2][0][RTW89_UKRAINE][26] = 42,
+ [2][1][2][0][RTW89_CHILE][26] = 52,
+ [2][1][2][0][RTW89_QATAR][26] = 54,
[2][1][2][0][RTW89_FCC][34] = 62,
[2][1][2][0][RTW89_ETSI][34] = 127,
[2][1][2][0][RTW89_MKK][34] = 60,
@@ -31876,6 +36304,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][0][RTW89_ACMA][34] = 60,
[2][1][2][0][RTW89_CN][34] = 127,
[2][1][2][0][RTW89_UK][34] = 52,
+ [2][1][2][0][RTW89_MEXICO][34] = 62,
+ [2][1][2][0][RTW89_UKRAINE][34] = 127,
+ [2][1][2][0][RTW89_CHILE][34] = 60,
+ [2][1][2][0][RTW89_QATAR][34] = 127,
[2][1][2][0][RTW89_FCC][41] = 60,
[2][1][2][0][RTW89_ETSI][41] = 18,
[2][1][2][0][RTW89_MKK][41] = 127,
@@ -31884,6 +36316,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][0][RTW89_ACMA][41] = 58,
[2][1][2][0][RTW89_CN][41] = 62,
[2][1][2][0][RTW89_UK][41] = 52,
+ [2][1][2][0][RTW89_MEXICO][41] = 60,
+ [2][1][2][0][RTW89_UKRAINE][41] = 18,
+ [2][1][2][0][RTW89_CHILE][41] = 58,
+ [2][1][2][0][RTW89_QATAR][41] = 18,
[2][1][2][0][RTW89_FCC][49] = 62,
[2][1][2][0][RTW89_ETSI][49] = 127,
[2][1][2][0][RTW89_MKK][49] = 127,
@@ -31892,6 +36328,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][0][RTW89_ACMA][49] = 127,
[2][1][2][0][RTW89_CN][49] = 127,
[2][1][2][0][RTW89_UK][49] = 127,
+ [2][1][2][0][RTW89_MEXICO][49] = 127,
+ [2][1][2][0][RTW89_UKRAINE][49] = 127,
+ [2][1][2][0][RTW89_CHILE][49] = 127,
+ [2][1][2][0][RTW89_QATAR][49] = 127,
[2][1][2][1][RTW89_FCC][3] = 48,
[2][1][2][1][RTW89_ETSI][3] = 40,
[2][1][2][1][RTW89_MKK][3] = 56,
@@ -31900,6 +36340,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][1][RTW89_ACMA][3] = 40,
[2][1][2][1][RTW89_CN][3] = 42,
[2][1][2][1][RTW89_UK][3] = 40,
+ [2][1][2][1][RTW89_MEXICO][3] = 48,
+ [2][1][2][1][RTW89_UKRAINE][3] = 30,
+ [2][1][2][1][RTW89_CHILE][3] = 46,
+ [2][1][2][1][RTW89_QATAR][3] = 40,
[2][1][2][1][RTW89_FCC][11] = 38,
[2][1][2][1][RTW89_ETSI][11] = 40,
[2][1][2][1][RTW89_MKK][11] = 54,
@@ -31908,6 +36352,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][1][RTW89_ACMA][11] = 40,
[2][1][2][1][RTW89_CN][11] = 42,
[2][1][2][1][RTW89_UK][11] = 40,
+ [2][1][2][1][RTW89_MEXICO][11] = 38,
+ [2][1][2][1][RTW89_UKRAINE][11] = 30,
+ [2][1][2][1][RTW89_CHILE][11] = 38,
+ [2][1][2][1][RTW89_QATAR][11] = 40,
[2][1][2][1][RTW89_FCC][18] = 50,
[2][1][2][1][RTW89_ETSI][18] = 40,
[2][1][2][1][RTW89_MKK][18] = 60,
@@ -31916,6 +36364,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][1][RTW89_ACMA][18] = 40,
[2][1][2][1][RTW89_CN][18] = 127,
[2][1][2][1][RTW89_UK][18] = 40,
+ [2][1][2][1][RTW89_MEXICO][18] = 50,
+ [2][1][2][1][RTW89_UKRAINE][18] = 30,
+ [2][1][2][1][RTW89_CHILE][18] = 50,
+ [2][1][2][1][RTW89_QATAR][18] = 40,
[2][1][2][1][RTW89_FCC][26] = 52,
[2][1][2][1][RTW89_ETSI][26] = 42,
[2][1][2][1][RTW89_MKK][26] = 56,
@@ -31924,6 +36376,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][1][RTW89_ACMA][26] = 127,
[2][1][2][1][RTW89_CN][26] = 127,
[2][1][2][1][RTW89_UK][26] = 42,
+ [2][1][2][1][RTW89_MEXICO][26] = 52,
+ [2][1][2][1][RTW89_UKRAINE][26] = 30,
+ [2][1][2][1][RTW89_CHILE][26] = 52,
+ [2][1][2][1][RTW89_QATAR][26] = 42,
[2][1][2][1][RTW89_FCC][34] = 62,
[2][1][2][1][RTW89_ETSI][34] = 127,
[2][1][2][1][RTW89_MKK][34] = 60,
@@ -31932,6 +36388,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][1][RTW89_ACMA][34] = 60,
[2][1][2][1][RTW89_CN][34] = 127,
[2][1][2][1][RTW89_UK][34] = 40,
+ [2][1][2][1][RTW89_MEXICO][34] = 62,
+ [2][1][2][1][RTW89_UKRAINE][34] = 127,
+ [2][1][2][1][RTW89_CHILE][34] = 60,
+ [2][1][2][1][RTW89_QATAR][34] = 127,
[2][1][2][1][RTW89_FCC][41] = 60,
[2][1][2][1][RTW89_ETSI][41] = 6,
[2][1][2][1][RTW89_MKK][41] = 127,
@@ -31940,6 +36400,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][1][RTW89_ACMA][41] = 58,
[2][1][2][1][RTW89_CN][41] = 40,
[2][1][2][1][RTW89_UK][41] = 40,
+ [2][1][2][1][RTW89_MEXICO][41] = 60,
+ [2][1][2][1][RTW89_UKRAINE][41] = 6,
+ [2][1][2][1][RTW89_CHILE][41] = 58,
+ [2][1][2][1][RTW89_QATAR][41] = 6,
[2][1][2][1][RTW89_FCC][49] = 62,
[2][1][2][1][RTW89_ETSI][49] = 127,
[2][1][2][1][RTW89_MKK][49] = 127,
@@ -31948,6 +36412,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][1][RTW89_ACMA][49] = 127,
[2][1][2][1][RTW89_CN][49] = 127,
[2][1][2][1][RTW89_UK][49] = 127,
+ [2][1][2][1][RTW89_MEXICO][49] = 127,
+ [2][1][2][1][RTW89_UKRAINE][49] = 127,
+ [2][1][2][1][RTW89_CHILE][49] = 127,
+ [2][1][2][1][RTW89_QATAR][49] = 127,
[3][0][2][0][RTW89_FCC][7] = 40,
[3][0][2][0][RTW89_ETSI][7] = 50,
[3][0][2][0][RTW89_MKK][7] = 50,
@@ -31956,6 +36424,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][0][2][0][RTW89_ACMA][7] = 127,
[3][0][2][0][RTW89_CN][7] = 66,
[3][0][2][0][RTW89_UK][7] = 127,
+ [3][0][2][0][RTW89_MEXICO][7] = 127,
+ [3][0][2][0][RTW89_UKRAINE][7] = 50,
+ [3][0][2][0][RTW89_CHILE][7] = 40,
+ [3][0][2][0][RTW89_QATAR][7] = 50,
[3][0][2][0][RTW89_FCC][22] = 42,
[3][0][2][0][RTW89_ETSI][22] = 50,
[3][0][2][0][RTW89_MKK][22] = 50,
@@ -31964,6 +36436,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][0][2][0][RTW89_ACMA][22] = 127,
[3][0][2][0][RTW89_CN][22] = 66,
[3][0][2][0][RTW89_UK][22] = 127,
+ [3][0][2][0][RTW89_MEXICO][22] = 127,
+ [3][0][2][0][RTW89_UKRAINE][22] = 50,
+ [3][0][2][0][RTW89_CHILE][22] = 42,
+ [3][0][2][0][RTW89_QATAR][22] = 50,
[3][0][2][0][RTW89_FCC][45] = 52,
[3][0][2][0][RTW89_ETSI][45] = 127,
[3][0][2][0][RTW89_MKK][45] = 127,
@@ -31972,6 +36448,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][0][2][0][RTW89_ACMA][45] = 127,
[3][0][2][0][RTW89_CN][45] = 127,
[3][0][2][0][RTW89_UK][45] = 127,
+ [3][0][2][0][RTW89_MEXICO][45] = 127,
+ [3][0][2][0][RTW89_UKRAINE][45] = 127,
+ [3][0][2][0][RTW89_CHILE][45] = 127,
+ [3][0][2][0][RTW89_QATAR][45] = 127,
[3][1][2][0][RTW89_FCC][7] = 32,
[3][1][2][0][RTW89_ETSI][7] = 50,
[3][1][2][0][RTW89_MKK][7] = 36,
@@ -31980,6 +36460,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][0][RTW89_ACMA][7] = 127,
[3][1][2][0][RTW89_CN][7] = 54,
[3][1][2][0][RTW89_UK][7] = 127,
+ [3][1][2][0][RTW89_MEXICO][7] = 127,
+ [3][1][2][0][RTW89_UKRAINE][7] = 50,
+ [3][1][2][0][RTW89_CHILE][7] = 32,
+ [3][1][2][0][RTW89_QATAR][7] = 50,
[3][1][2][0][RTW89_FCC][22] = 36,
[3][1][2][0][RTW89_ETSI][22] = 50,
[3][1][2][0][RTW89_MKK][22] = 48,
@@ -31988,6 +36472,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][0][RTW89_ACMA][22] = 127,
[3][1][2][0][RTW89_CN][22] = 54,
[3][1][2][0][RTW89_UK][22] = 127,
+ [3][1][2][0][RTW89_MEXICO][22] = 127,
+ [3][1][2][0][RTW89_UKRAINE][22] = 50,
+ [3][1][2][0][RTW89_CHILE][22] = 36,
+ [3][1][2][0][RTW89_QATAR][22] = 50,
[3][1][2][0][RTW89_FCC][45] = 46,
[3][1][2][0][RTW89_ETSI][45] = 127,
[3][1][2][0][RTW89_MKK][45] = 127,
@@ -31996,6 +36484,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][0][RTW89_ACMA][45] = 127,
[3][1][2][0][RTW89_CN][45] = 127,
[3][1][2][0][RTW89_UK][45] = 127,
+ [3][1][2][0][RTW89_MEXICO][45] = 127,
+ [3][1][2][0][RTW89_UKRAINE][45] = 127,
+ [3][1][2][0][RTW89_CHILE][45] = 127,
+ [3][1][2][0][RTW89_QATAR][45] = 127,
[3][1][2][1][RTW89_FCC][7] = 32,
[3][1][2][1][RTW89_ETSI][7] = 42,
[3][1][2][1][RTW89_MKK][7] = 36,
@@ -32004,6 +36496,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][1][RTW89_ACMA][7] = 127,
[3][1][2][1][RTW89_CN][7] = 42,
[3][1][2][1][RTW89_UK][7] = 127,
+ [3][1][2][1][RTW89_MEXICO][7] = 127,
+ [3][1][2][1][RTW89_UKRAINE][7] = 42,
+ [3][1][2][1][RTW89_CHILE][7] = 32,
+ [3][1][2][1][RTW89_QATAR][7] = 42,
[3][1][2][1][RTW89_FCC][22] = 36,
[3][1][2][1][RTW89_ETSI][22] = 42,
[3][1][2][1][RTW89_MKK][22] = 48,
@@ -32012,6 +36508,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][1][RTW89_ACMA][22] = 127,
[3][1][2][1][RTW89_CN][22] = 42,
[3][1][2][1][RTW89_UK][22] = 127,
+ [3][1][2][1][RTW89_MEXICO][22] = 127,
+ [3][1][2][1][RTW89_UKRAINE][22] = 42,
+ [3][1][2][1][RTW89_CHILE][22] = 36,
+ [3][1][2][1][RTW89_QATAR][22] = 42,
[3][1][2][1][RTW89_FCC][45] = 46,
[3][1][2][1][RTW89_ETSI][45] = 127,
[3][1][2][1][RTW89_MKK][45] = 127,
@@ -32020,1964 +36520,9289 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][1][RTW89_ACMA][45] = 127,
[3][1][2][1][RTW89_CN][45] = 127,
[3][1][2][1][RTW89_UK][45] = 127,
+ [3][1][2][1][RTW89_MEXICO][45] = 127,
+ [3][1][2][1][RTW89_UKRAINE][45] = 127,
+ [3][1][2][1][RTW89_CHILE][45] = 127,
+ [3][1][2][1][RTW89_QATAR][45] = 127,
};
static
const s8 rtw89_8852c_txpwr_lmt_6g[RTW89_6G_BW_NUM][RTW89_NTX_NUM]
[RTW89_RS_LMT_NUM][RTW89_BF_NUM]
- [RTW89_REGD_NUM][RTW89_6G_CH_NUM] = {
- [0][0][1][0][RTW89_WW][0] = 24,
- [0][0][1][0][RTW89_WW][2] = 22,
- [0][0][1][0][RTW89_WW][4] = 22,
- [0][0][1][0][RTW89_WW][6] = 22,
- [0][0][1][0][RTW89_WW][8] = 22,
- [0][0][1][0][RTW89_WW][10] = 22,
- [0][0][1][0][RTW89_WW][12] = 22,
- [0][0][1][0][RTW89_WW][14] = 22,
- [0][0][1][0][RTW89_WW][15] = 22,
- [0][0][1][0][RTW89_WW][17] = 22,
- [0][0][1][0][RTW89_WW][19] = 22,
- [0][0][1][0][RTW89_WW][21] = 22,
- [0][0][1][0][RTW89_WW][23] = 22,
- [0][0][1][0][RTW89_WW][25] = 22,
- [0][0][1][0][RTW89_WW][27] = 22,
- [0][0][1][0][RTW89_WW][29] = 22,
- [0][0][1][0][RTW89_WW][30] = 22,
- [0][0][1][0][RTW89_WW][32] = 22,
- [0][0][1][0][RTW89_WW][34] = 22,
- [0][0][1][0][RTW89_WW][36] = 22,
- [0][0][1][0][RTW89_WW][38] = 22,
- [0][0][1][0][RTW89_WW][40] = 22,
- [0][0][1][0][RTW89_WW][42] = 22,
- [0][0][1][0][RTW89_WW][44] = 22,
- [0][0][1][0][RTW89_WW][45] = 22,
- [0][0][1][0][RTW89_WW][47] = 22,
- [0][0][1][0][RTW89_WW][49] = 24,
- [0][0][1][0][RTW89_WW][51] = 22,
- [0][0][1][0][RTW89_WW][53] = 22,
- [0][0][1][0][RTW89_WW][55] = 22,
- [0][0][1][0][RTW89_WW][57] = 22,
- [0][0][1][0][RTW89_WW][59] = 22,
- [0][0][1][0][RTW89_WW][60] = 22,
- [0][0][1][0][RTW89_WW][62] = 22,
- [0][0][1][0][RTW89_WW][64] = 22,
- [0][0][1][0][RTW89_WW][66] = 22,
- [0][0][1][0][RTW89_WW][68] = 22,
- [0][0][1][0][RTW89_WW][70] = 24,
- [0][0][1][0][RTW89_WW][72] = 22,
- [0][0][1][0][RTW89_WW][74] = 22,
- [0][0][1][0][RTW89_WW][75] = 22,
- [0][0][1][0][RTW89_WW][77] = 22,
- [0][0][1][0][RTW89_WW][79] = 22,
- [0][0][1][0][RTW89_WW][81] = 22,
- [0][0][1][0][RTW89_WW][83] = 22,
- [0][0][1][0][RTW89_WW][85] = 22,
- [0][0][1][0][RTW89_WW][87] = 22,
- [0][0][1][0][RTW89_WW][89] = 22,
- [0][0][1][0][RTW89_WW][90] = 22,
- [0][0][1][0][RTW89_WW][92] = 22,
- [0][0][1][0][RTW89_WW][94] = 22,
- [0][0][1][0][RTW89_WW][96] = 22,
- [0][0][1][0][RTW89_WW][98] = 22,
- [0][0][1][0][RTW89_WW][100] = 22,
- [0][0][1][0][RTW89_WW][102] = 22,
- [0][0][1][0][RTW89_WW][104] = 22,
- [0][0][1][0][RTW89_WW][105] = 22,
- [0][0][1][0][RTW89_WW][107] = 24,
- [0][0][1][0][RTW89_WW][109] = 24,
- [0][0][1][0][RTW89_WW][111] = 0,
- [0][0][1][0][RTW89_WW][113] = 0,
- [0][0][1][0][RTW89_WW][115] = 0,
- [0][0][1][0][RTW89_WW][117] = 0,
- [0][0][1][0][RTW89_WW][119] = 0,
- [0][1][1][0][RTW89_WW][0] = -2,
- [0][1][1][0][RTW89_WW][2] = -4,
- [0][1][1][0][RTW89_WW][4] = -4,
- [0][1][1][0][RTW89_WW][6] = -4,
- [0][1][1][0][RTW89_WW][8] = -4,
- [0][1][1][0][RTW89_WW][10] = -4,
- [0][1][1][0][RTW89_WW][12] = -4,
- [0][1][1][0][RTW89_WW][14] = -4,
- [0][1][1][0][RTW89_WW][15] = -4,
- [0][1][1][0][RTW89_WW][17] = -4,
- [0][1][1][0][RTW89_WW][19] = -4,
- [0][1][1][0][RTW89_WW][21] = -4,
- [0][1][1][0][RTW89_WW][23] = -4,
- [0][1][1][0][RTW89_WW][25] = -4,
- [0][1][1][0][RTW89_WW][27] = -4,
- [0][1][1][0][RTW89_WW][29] = -4,
- [0][1][1][0][RTW89_WW][30] = -4,
- [0][1][1][0][RTW89_WW][32] = -4,
- [0][1][1][0][RTW89_WW][34] = -4,
- [0][1][1][0][RTW89_WW][36] = -4,
- [0][1][1][0][RTW89_WW][38] = -4,
- [0][1][1][0][RTW89_WW][40] = -4,
- [0][1][1][0][RTW89_WW][42] = -4,
- [0][1][1][0][RTW89_WW][44] = -2,
- [0][1][1][0][RTW89_WW][45] = -2,
- [0][1][1][0][RTW89_WW][47] = -2,
- [0][1][1][0][RTW89_WW][49] = -2,
- [0][1][1][0][RTW89_WW][51] = -2,
- [0][1][1][0][RTW89_WW][53] = -2,
- [0][1][1][0][RTW89_WW][55] = -2,
- [0][1][1][0][RTW89_WW][57] = -2,
- [0][1][1][0][RTW89_WW][59] = -2,
- [0][1][1][0][RTW89_WW][60] = -2,
- [0][1][1][0][RTW89_WW][62] = -2,
- [0][1][1][0][RTW89_WW][64] = -2,
- [0][1][1][0][RTW89_WW][66] = -2,
- [0][1][1][0][RTW89_WW][68] = -2,
- [0][1][1][0][RTW89_WW][70] = -2,
- [0][1][1][0][RTW89_WW][72] = -2,
- [0][1][1][0][RTW89_WW][74] = -2,
- [0][1][1][0][RTW89_WW][75] = -2,
- [0][1][1][0][RTW89_WW][77] = -2,
- [0][1][1][0][RTW89_WW][79] = -2,
- [0][1][1][0][RTW89_WW][81] = -2,
- [0][1][1][0][RTW89_WW][83] = -2,
- [0][1][1][0][RTW89_WW][85] = -2,
- [0][1][1][0][RTW89_WW][87] = -2,
- [0][1][1][0][RTW89_WW][89] = -2,
- [0][1][1][0][RTW89_WW][90] = -2,
- [0][1][1][0][RTW89_WW][92] = -2,
- [0][1][1][0][RTW89_WW][94] = -2,
- [0][1][1][0][RTW89_WW][96] = -2,
- [0][1][1][0][RTW89_WW][98] = -2,
- [0][1][1][0][RTW89_WW][100] = -2,
- [0][1][1][0][RTW89_WW][102] = -2,
- [0][1][1][0][RTW89_WW][104] = -2,
- [0][1][1][0][RTW89_WW][105] = -2,
- [0][1][1][0][RTW89_WW][107] = 1,
- [0][1][1][0][RTW89_WW][109] = 1,
- [0][1][1][0][RTW89_WW][111] = 0,
- [0][1][1][0][RTW89_WW][113] = 0,
- [0][1][1][0][RTW89_WW][115] = 0,
- [0][1][1][0][RTW89_WW][117] = 0,
- [0][1][1][0][RTW89_WW][119] = 0,
- [0][0][2][0][RTW89_WW][0] = 24,
- [0][0][2][0][RTW89_WW][2] = 22,
- [0][0][2][0][RTW89_WW][4] = 22,
- [0][0][2][0][RTW89_WW][6] = 22,
- [0][0][2][0][RTW89_WW][8] = 22,
- [0][0][2][0][RTW89_WW][10] = 22,
- [0][0][2][0][RTW89_WW][12] = 22,
- [0][0][2][0][RTW89_WW][14] = 22,
- [0][0][2][0][RTW89_WW][15] = 22,
- [0][0][2][0][RTW89_WW][17] = 22,
- [0][0][2][0][RTW89_WW][19] = 22,
- [0][0][2][0][RTW89_WW][21] = 22,
- [0][0][2][0][RTW89_WW][23] = 22,
- [0][0][2][0][RTW89_WW][25] = 22,
- [0][0][2][0][RTW89_WW][27] = 22,
- [0][0][2][0][RTW89_WW][29] = 22,
- [0][0][2][0][RTW89_WW][30] = 22,
- [0][0][2][0][RTW89_WW][32] = 22,
- [0][0][2][0][RTW89_WW][34] = 22,
- [0][0][2][0][RTW89_WW][36] = 22,
- [0][0][2][0][RTW89_WW][38] = 22,
- [0][0][2][0][RTW89_WW][40] = 22,
- [0][0][2][0][RTW89_WW][42] = 22,
- [0][0][2][0][RTW89_WW][44] = 22,
- [0][0][2][0][RTW89_WW][45] = 22,
- [0][0][2][0][RTW89_WW][47] = 22,
- [0][0][2][0][RTW89_WW][49] = 24,
- [0][0][2][0][RTW89_WW][51] = 22,
- [0][0][2][0][RTW89_WW][53] = 22,
- [0][0][2][0][RTW89_WW][55] = 22,
- [0][0][2][0][RTW89_WW][57] = 22,
- [0][0][2][0][RTW89_WW][59] = 22,
- [0][0][2][0][RTW89_WW][60] = 22,
- [0][0][2][0][RTW89_WW][62] = 22,
- [0][0][2][0][RTW89_WW][64] = 22,
- [0][0][2][0][RTW89_WW][66] = 22,
- [0][0][2][0][RTW89_WW][68] = 22,
- [0][0][2][0][RTW89_WW][70] = 24,
- [0][0][2][0][RTW89_WW][72] = 22,
- [0][0][2][0][RTW89_WW][74] = 22,
- [0][0][2][0][RTW89_WW][75] = 22,
- [0][0][2][0][RTW89_WW][77] = 22,
- [0][0][2][0][RTW89_WW][79] = 22,
- [0][0][2][0][RTW89_WW][81] = 22,
- [0][0][2][0][RTW89_WW][83] = 22,
- [0][0][2][0][RTW89_WW][85] = 22,
- [0][0][2][0][RTW89_WW][87] = 22,
- [0][0][2][0][RTW89_WW][89] = 22,
- [0][0][2][0][RTW89_WW][90] = 22,
- [0][0][2][0][RTW89_WW][92] = 22,
- [0][0][2][0][RTW89_WW][94] = 22,
- [0][0][2][0][RTW89_WW][96] = 22,
- [0][0][2][0][RTW89_WW][98] = 22,
- [0][0][2][0][RTW89_WW][100] = 22,
- [0][0][2][0][RTW89_WW][102] = 22,
- [0][0][2][0][RTW89_WW][104] = 22,
- [0][0][2][0][RTW89_WW][105] = 22,
- [0][0][2][0][RTW89_WW][107] = 24,
- [0][0][2][0][RTW89_WW][109] = 24,
- [0][0][2][0][RTW89_WW][111] = 0,
- [0][0][2][0][RTW89_WW][113] = 0,
- [0][0][2][0][RTW89_WW][115] = 0,
- [0][0][2][0][RTW89_WW][117] = 0,
- [0][0][2][0][RTW89_WW][119] = 0,
- [0][1][2][0][RTW89_WW][0] = -2,
- [0][1][2][0][RTW89_WW][2] = -4,
- [0][1][2][0][RTW89_WW][4] = -4,
- [0][1][2][0][RTW89_WW][6] = -4,
- [0][1][2][0][RTW89_WW][8] = -4,
- [0][1][2][0][RTW89_WW][10] = -4,
- [0][1][2][0][RTW89_WW][12] = -4,
- [0][1][2][0][RTW89_WW][14] = -4,
- [0][1][2][0][RTW89_WW][15] = -4,
- [0][1][2][0][RTW89_WW][17] = -4,
- [0][1][2][0][RTW89_WW][19] = -4,
- [0][1][2][0][RTW89_WW][21] = -4,
- [0][1][2][0][RTW89_WW][23] = -4,
- [0][1][2][0][RTW89_WW][25] = -4,
- [0][1][2][0][RTW89_WW][27] = -4,
- [0][1][2][0][RTW89_WW][29] = -4,
- [0][1][2][0][RTW89_WW][30] = -4,
- [0][1][2][0][RTW89_WW][32] = -4,
- [0][1][2][0][RTW89_WW][34] = -4,
- [0][1][2][0][RTW89_WW][36] = -4,
- [0][1][2][0][RTW89_WW][38] = -4,
- [0][1][2][0][RTW89_WW][40] = -4,
- [0][1][2][0][RTW89_WW][42] = -4,
- [0][1][2][0][RTW89_WW][44] = -2,
- [0][1][2][0][RTW89_WW][45] = -2,
- [0][1][2][0][RTW89_WW][47] = -2,
- [0][1][2][0][RTW89_WW][49] = -2,
- [0][1][2][0][RTW89_WW][51] = -2,
- [0][1][2][0][RTW89_WW][53] = -2,
- [0][1][2][0][RTW89_WW][55] = -2,
- [0][1][2][0][RTW89_WW][57] = -2,
- [0][1][2][0][RTW89_WW][59] = -2,
- [0][1][2][0][RTW89_WW][60] = -2,
- [0][1][2][0][RTW89_WW][62] = -2,
- [0][1][2][0][RTW89_WW][64] = -2,
- [0][1][2][0][RTW89_WW][66] = -2,
- [0][1][2][0][RTW89_WW][68] = -2,
- [0][1][2][0][RTW89_WW][70] = -2,
- [0][1][2][0][RTW89_WW][72] = -2,
- [0][1][2][0][RTW89_WW][74] = -2,
- [0][1][2][0][RTW89_WW][75] = -2,
- [0][1][2][0][RTW89_WW][77] = -2,
- [0][1][2][0][RTW89_WW][79] = -2,
- [0][1][2][0][RTW89_WW][81] = -2,
- [0][1][2][0][RTW89_WW][83] = -2,
- [0][1][2][0][RTW89_WW][85] = -2,
- [0][1][2][0][RTW89_WW][87] = -2,
- [0][1][2][0][RTW89_WW][89] = -2,
- [0][1][2][0][RTW89_WW][90] = -2,
- [0][1][2][0][RTW89_WW][92] = -2,
- [0][1][2][0][RTW89_WW][94] = -2,
- [0][1][2][0][RTW89_WW][96] = -2,
- [0][1][2][0][RTW89_WW][98] = -2,
- [0][1][2][0][RTW89_WW][100] = -2,
- [0][1][2][0][RTW89_WW][102] = -2,
- [0][1][2][0][RTW89_WW][104] = -2,
- [0][1][2][0][RTW89_WW][105] = -2,
- [0][1][2][0][RTW89_WW][107] = 1,
- [0][1][2][0][RTW89_WW][109] = 1,
- [0][1][2][0][RTW89_WW][111] = 0,
- [0][1][2][0][RTW89_WW][113] = 0,
- [0][1][2][0][RTW89_WW][115] = 0,
- [0][1][2][0][RTW89_WW][117] = 0,
- [0][1][2][0][RTW89_WW][119] = 0,
- [0][1][2][1][RTW89_WW][0] = -2,
- [0][1][2][1][RTW89_WW][2] = -4,
- [0][1][2][1][RTW89_WW][4] = -4,
- [0][1][2][1][RTW89_WW][6] = -4,
- [0][1][2][1][RTW89_WW][8] = -4,
- [0][1][2][1][RTW89_WW][10] = -4,
- [0][1][2][1][RTW89_WW][12] = -4,
- [0][1][2][1][RTW89_WW][14] = -4,
- [0][1][2][1][RTW89_WW][15] = -4,
- [0][1][2][1][RTW89_WW][17] = -4,
- [0][1][2][1][RTW89_WW][19] = -4,
- [0][1][2][1][RTW89_WW][21] = -4,
- [0][1][2][1][RTW89_WW][23] = -4,
- [0][1][2][1][RTW89_WW][25] = -4,
- [0][1][2][1][RTW89_WW][27] = -4,
- [0][1][2][1][RTW89_WW][29] = -4,
- [0][1][2][1][RTW89_WW][30] = -4,
- [0][1][2][1][RTW89_WW][32] = -4,
- [0][1][2][1][RTW89_WW][34] = -4,
- [0][1][2][1][RTW89_WW][36] = -4,
- [0][1][2][1][RTW89_WW][38] = -4,
- [0][1][2][1][RTW89_WW][40] = -4,
- [0][1][2][1][RTW89_WW][42] = -4,
- [0][1][2][1][RTW89_WW][44] = -2,
- [0][1][2][1][RTW89_WW][45] = -2,
- [0][1][2][1][RTW89_WW][47] = -2,
- [0][1][2][1][RTW89_WW][49] = -2,
- [0][1][2][1][RTW89_WW][51] = -2,
- [0][1][2][1][RTW89_WW][53] = -2,
- [0][1][2][1][RTW89_WW][55] = -2,
- [0][1][2][1][RTW89_WW][57] = -2,
- [0][1][2][1][RTW89_WW][59] = -2,
- [0][1][2][1][RTW89_WW][60] = -2,
- [0][1][2][1][RTW89_WW][62] = -2,
- [0][1][2][1][RTW89_WW][64] = -2,
- [0][1][2][1][RTW89_WW][66] = -2,
- [0][1][2][1][RTW89_WW][68] = -2,
- [0][1][2][1][RTW89_WW][70] = -2,
- [0][1][2][1][RTW89_WW][72] = -2,
- [0][1][2][1][RTW89_WW][74] = -2,
- [0][1][2][1][RTW89_WW][75] = -2,
- [0][1][2][1][RTW89_WW][77] = -2,
- [0][1][2][1][RTW89_WW][79] = -2,
- [0][1][2][1][RTW89_WW][81] = -2,
- [0][1][2][1][RTW89_WW][83] = -2,
- [0][1][2][1][RTW89_WW][85] = -2,
- [0][1][2][1][RTW89_WW][87] = -2,
- [0][1][2][1][RTW89_WW][89] = -2,
- [0][1][2][1][RTW89_WW][90] = -2,
- [0][1][2][1][RTW89_WW][92] = -2,
- [0][1][2][1][RTW89_WW][94] = -2,
- [0][1][2][1][RTW89_WW][96] = -2,
- [0][1][2][1][RTW89_WW][98] = -2,
- [0][1][2][1][RTW89_WW][100] = -2,
- [0][1][2][1][RTW89_WW][102] = -2,
- [0][1][2][1][RTW89_WW][104] = -2,
- [0][1][2][1][RTW89_WW][105] = -2,
- [0][1][2][1][RTW89_WW][107] = 1,
- [0][1][2][1][RTW89_WW][109] = 1,
- [0][1][2][1][RTW89_WW][111] = 0,
- [0][1][2][1][RTW89_WW][113] = 0,
- [0][1][2][1][RTW89_WW][115] = 0,
- [0][1][2][1][RTW89_WW][117] = 0,
- [0][1][2][1][RTW89_WW][119] = 0,
- [1][0][2][0][RTW89_WW][1] = 34,
- [1][0][2][0][RTW89_WW][5] = 34,
- [1][0][2][0][RTW89_WW][9] = 34,
- [1][0][2][0][RTW89_WW][13] = 34,
- [1][0][2][0][RTW89_WW][16] = 34,
- [1][0][2][0][RTW89_WW][20] = 34,
- [1][0][2][0][RTW89_WW][24] = 36,
- [1][0][2][0][RTW89_WW][28] = 34,
- [1][0][2][0][RTW89_WW][31] = 34,
- [1][0][2][0][RTW89_WW][35] = 34,
- [1][0][2][0][RTW89_WW][39] = 34,
- [1][0][2][0][RTW89_WW][43] = 34,
- [1][0][2][0][RTW89_WW][46] = 34,
- [1][0][2][0][RTW89_WW][50] = 34,
- [1][0][2][0][RTW89_WW][54] = 36,
- [1][0][2][0][RTW89_WW][58] = 36,
- [1][0][2][0][RTW89_WW][61] = 34,
- [1][0][2][0][RTW89_WW][65] = 34,
- [1][0][2][0][RTW89_WW][69] = 34,
- [1][0][2][0][RTW89_WW][73] = 34,
- [1][0][2][0][RTW89_WW][76] = 34,
- [1][0][2][0][RTW89_WW][80] = 34,
- [1][0][2][0][RTW89_WW][84] = 34,
- [1][0][2][0][RTW89_WW][88] = 34,
- [1][0][2][0][RTW89_WW][91] = 36,
- [1][0][2][0][RTW89_WW][95] = 34,
- [1][0][2][0][RTW89_WW][99] = 34,
- [1][0][2][0][RTW89_WW][103] = 34,
- [1][0][2][0][RTW89_WW][106] = 36,
- [1][0][2][0][RTW89_WW][110] = 0,
- [1][0][2][0][RTW89_WW][114] = 0,
- [1][0][2][0][RTW89_WW][118] = 0,
- [1][1][2][0][RTW89_WW][1] = 10,
- [1][1][2][0][RTW89_WW][5] = 10,
- [1][1][2][0][RTW89_WW][9] = 10,
- [1][1][2][0][RTW89_WW][13] = 10,
- [1][1][2][0][RTW89_WW][16] = 10,
- [1][1][2][0][RTW89_WW][20] = 10,
- [1][1][2][0][RTW89_WW][24] = 10,
- [1][1][2][0][RTW89_WW][28] = 10,
- [1][1][2][0][RTW89_WW][31] = 10,
- [1][1][2][0][RTW89_WW][35] = 10,
- [1][1][2][0][RTW89_WW][39] = 10,
- [1][1][2][0][RTW89_WW][43] = 10,
- [1][1][2][0][RTW89_WW][46] = 12,
- [1][1][2][0][RTW89_WW][50] = 12,
- [1][1][2][0][RTW89_WW][54] = 10,
- [1][1][2][0][RTW89_WW][58] = 10,
- [1][1][2][0][RTW89_WW][61] = 10,
- [1][1][2][0][RTW89_WW][65] = 10,
- [1][1][2][0][RTW89_WW][69] = 10,
- [1][1][2][0][RTW89_WW][73] = 10,
- [1][1][2][0][RTW89_WW][76] = 10,
- [1][1][2][0][RTW89_WW][80] = 10,
- [1][1][2][0][RTW89_WW][84] = 10,
- [1][1][2][0][RTW89_WW][88] = 10,
- [1][1][2][0][RTW89_WW][91] = 12,
- [1][1][2][0][RTW89_WW][95] = 10,
- [1][1][2][0][RTW89_WW][99] = 10,
- [1][1][2][0][RTW89_WW][103] = 10,
- [1][1][2][0][RTW89_WW][106] = 12,
- [1][1][2][0][RTW89_WW][110] = 0,
- [1][1][2][0][RTW89_WW][114] = 0,
- [1][1][2][0][RTW89_WW][118] = 0,
- [1][1][2][1][RTW89_WW][1] = 10,
- [1][1][2][1][RTW89_WW][5] = 10,
- [1][1][2][1][RTW89_WW][9] = 10,
- [1][1][2][1][RTW89_WW][13] = 10,
- [1][1][2][1][RTW89_WW][16] = 10,
- [1][1][2][1][RTW89_WW][20] = 10,
- [1][1][2][1][RTW89_WW][24] = 10,
- [1][1][2][1][RTW89_WW][28] = 10,
- [1][1][2][1][RTW89_WW][31] = 10,
- [1][1][2][1][RTW89_WW][35] = 10,
- [1][1][2][1][RTW89_WW][39] = 10,
- [1][1][2][1][RTW89_WW][43] = 10,
- [1][1][2][1][RTW89_WW][46] = 12,
- [1][1][2][1][RTW89_WW][50] = 12,
- [1][1][2][1][RTW89_WW][54] = 10,
- [1][1][2][1][RTW89_WW][58] = 10,
- [1][1][2][1][RTW89_WW][61] = 10,
- [1][1][2][1][RTW89_WW][65] = 10,
- [1][1][2][1][RTW89_WW][69] = 10,
- [1][1][2][1][RTW89_WW][73] = 10,
- [1][1][2][1][RTW89_WW][76] = 10,
- [1][1][2][1][RTW89_WW][80] = 10,
- [1][1][2][1][RTW89_WW][84] = 10,
- [1][1][2][1][RTW89_WW][88] = 10,
- [1][1][2][1][RTW89_WW][91] = 12,
- [1][1][2][1][RTW89_WW][95] = 10,
- [1][1][2][1][RTW89_WW][99] = 10,
- [1][1][2][1][RTW89_WW][103] = 10,
- [1][1][2][1][RTW89_WW][106] = 12,
- [1][1][2][1][RTW89_WW][110] = 0,
- [1][1][2][1][RTW89_WW][114] = 0,
- [1][1][2][1][RTW89_WW][118] = 0,
- [2][0][2][0][RTW89_WW][3] = 46,
- [2][0][2][0][RTW89_WW][11] = 46,
- [2][0][2][0][RTW89_WW][18] = 46,
- [2][0][2][0][RTW89_WW][26] = 46,
- [2][0][2][0][RTW89_WW][33] = 46,
- [2][0][2][0][RTW89_WW][41] = 46,
- [2][0][2][0][RTW89_WW][48] = 46,
- [2][0][2][0][RTW89_WW][56] = 46,
- [2][0][2][0][RTW89_WW][63] = 46,
- [2][0][2][0][RTW89_WW][71] = 46,
- [2][0][2][0][RTW89_WW][78] = 46,
- [2][0][2][0][RTW89_WW][86] = 46,
- [2][0][2][0][RTW89_WW][93] = 46,
- [2][0][2][0][RTW89_WW][101] = 44,
- [2][0][2][0][RTW89_WW][108] = 0,
- [2][0][2][0][RTW89_WW][116] = 0,
- [2][1][2][0][RTW89_WW][3] = 22,
- [2][1][2][0][RTW89_WW][11] = 20,
- [2][1][2][0][RTW89_WW][18] = 20,
- [2][1][2][0][RTW89_WW][26] = 20,
- [2][1][2][0][RTW89_WW][33] = 20,
- [2][1][2][0][RTW89_WW][41] = 22,
- [2][1][2][0][RTW89_WW][48] = 22,
- [2][1][2][0][RTW89_WW][56] = 20,
- [2][1][2][0][RTW89_WW][63] = 22,
- [2][1][2][0][RTW89_WW][71] = 20,
- [2][1][2][0][RTW89_WW][78] = 20,
- [2][1][2][0][RTW89_WW][86] = 20,
- [2][1][2][0][RTW89_WW][93] = 22,
- [2][1][2][0][RTW89_WW][101] = 22,
- [2][1][2][0][RTW89_WW][108] = 0,
- [2][1][2][0][RTW89_WW][116] = 0,
- [2][1][2][1][RTW89_WW][3] = 22,
- [2][1][2][1][RTW89_WW][11] = 20,
- [2][1][2][1][RTW89_WW][18] = 20,
- [2][1][2][1][RTW89_WW][26] = 20,
- [2][1][2][1][RTW89_WW][33] = 20,
- [2][1][2][1][RTW89_WW][41] = 22,
- [2][1][2][1][RTW89_WW][48] = 22,
- [2][1][2][1][RTW89_WW][56] = 20,
- [2][1][2][1][RTW89_WW][63] = 22,
- [2][1][2][1][RTW89_WW][71] = 20,
- [2][1][2][1][RTW89_WW][78] = 20,
- [2][1][2][1][RTW89_WW][86] = 20,
- [2][1][2][1][RTW89_WW][93] = 22,
- [2][1][2][1][RTW89_WW][101] = 22,
- [2][1][2][1][RTW89_WW][108] = 0,
- [2][1][2][1][RTW89_WW][116] = 0,
- [3][0][2][0][RTW89_WW][7] = 38,
- [3][0][2][0][RTW89_WW][22] = 38,
- [3][0][2][0][RTW89_WW][37] = 38,
- [3][0][2][0][RTW89_WW][52] = 54,
- [3][0][2][0][RTW89_WW][67] = 54,
- [3][0][2][0][RTW89_WW][82] = 26,
- [3][0][2][0][RTW89_WW][97] = 26,
- [3][0][2][0][RTW89_WW][112] = 0,
- [3][1][2][0][RTW89_WW][7] = 32,
- [3][1][2][0][RTW89_WW][22] = 30,
- [3][1][2][0][RTW89_WW][37] = 30,
- [3][1][2][0][RTW89_WW][52] = 30,
- [3][1][2][0][RTW89_WW][67] = 32,
- [3][1][2][0][RTW89_WW][82] = 24,
- [3][1][2][0][RTW89_WW][97] = 14,
- [3][1][2][0][RTW89_WW][112] = 0,
- [3][1][2][1][RTW89_WW][7] = 32,
- [3][1][2][1][RTW89_WW][22] = 30,
- [3][1][2][1][RTW89_WW][37] = 30,
- [3][1][2][1][RTW89_WW][52] = 30,
- [3][1][2][1][RTW89_WW][67] = 32,
- [3][1][2][1][RTW89_WW][82] = 24,
- [3][1][2][1][RTW89_WW][97] = 14,
- [3][1][2][1][RTW89_WW][112] = 0,
- [0][0][1][0][RTW89_FCC][0] = 24,
- [0][0][1][0][RTW89_ETSI][0] = 66,
- [0][0][1][0][RTW89_KCC][0] = 24,
- [0][0][1][0][RTW89_FCC][2] = 22,
- [0][0][1][0][RTW89_ETSI][2] = 66,
- [0][0][1][0][RTW89_KCC][2] = 24,
- [0][0][1][0][RTW89_FCC][4] = 22,
- [0][0][1][0][RTW89_ETSI][4] = 66,
- [0][0][1][0][RTW89_KCC][4] = 24,
- [0][0][1][0][RTW89_FCC][6] = 22,
- [0][0][1][0][RTW89_ETSI][6] = 66,
- [0][0][1][0][RTW89_KCC][6] = 24,
- [0][0][1][0][RTW89_FCC][8] = 22,
- [0][0][1][0][RTW89_ETSI][8] = 66,
- [0][0][1][0][RTW89_KCC][8] = 24,
- [0][0][1][0][RTW89_FCC][10] = 22,
- [0][0][1][0][RTW89_ETSI][10] = 66,
- [0][0][1][0][RTW89_KCC][10] = 24,
- [0][0][1][0][RTW89_FCC][12] = 22,
- [0][0][1][0][RTW89_ETSI][12] = 66,
- [0][0][1][0][RTW89_KCC][12] = 24,
- [0][0][1][0][RTW89_FCC][14] = 22,
- [0][0][1][0][RTW89_ETSI][14] = 66,
- [0][0][1][0][RTW89_KCC][14] = 24,
- [0][0][1][0][RTW89_FCC][15] = 22,
- [0][0][1][0][RTW89_ETSI][15] = 66,
- [0][0][1][0][RTW89_KCC][15] = 24,
- [0][0][1][0][RTW89_FCC][17] = 22,
- [0][0][1][0][RTW89_ETSI][17] = 66,
- [0][0][1][0][RTW89_KCC][17] = 24,
- [0][0][1][0][RTW89_FCC][19] = 22,
- [0][0][1][0][RTW89_ETSI][19] = 66,
- [0][0][1][0][RTW89_KCC][19] = 24,
- [0][0][1][0][RTW89_FCC][21] = 22,
- [0][0][1][0][RTW89_ETSI][21] = 66,
- [0][0][1][0][RTW89_KCC][21] = 24,
- [0][0][1][0][RTW89_FCC][23] = 22,
- [0][0][1][0][RTW89_ETSI][23] = 66,
- [0][0][1][0][RTW89_KCC][23] = 24,
- [0][0][1][0][RTW89_FCC][25] = 22,
- [0][0][1][0][RTW89_ETSI][25] = 66,
- [0][0][1][0][RTW89_KCC][25] = 24,
- [0][0][1][0][RTW89_FCC][27] = 22,
- [0][0][1][0][RTW89_ETSI][27] = 66,
- [0][0][1][0][RTW89_KCC][27] = 24,
- [0][0][1][0][RTW89_FCC][29] = 22,
- [0][0][1][0][RTW89_ETSI][29] = 66,
- [0][0][1][0][RTW89_KCC][29] = 24,
- [0][0][1][0][RTW89_FCC][30] = 22,
- [0][0][1][0][RTW89_ETSI][30] = 66,
- [0][0][1][0][RTW89_KCC][30] = 24,
- [0][0][1][0][RTW89_FCC][32] = 22,
- [0][0][1][0][RTW89_ETSI][32] = 66,
- [0][0][1][0][RTW89_KCC][32] = 24,
- [0][0][1][0][RTW89_FCC][34] = 22,
- [0][0][1][0][RTW89_ETSI][34] = 66,
- [0][0][1][0][RTW89_KCC][34] = 24,
- [0][0][1][0][RTW89_FCC][36] = 22,
- [0][0][1][0][RTW89_ETSI][36] = 66,
- [0][0][1][0][RTW89_KCC][36] = 24,
- [0][0][1][0][RTW89_FCC][38] = 22,
- [0][0][1][0][RTW89_ETSI][38] = 66,
- [0][0][1][0][RTW89_KCC][38] = 24,
- [0][0][1][0][RTW89_FCC][40] = 22,
- [0][0][1][0][RTW89_ETSI][40] = 66,
- [0][0][1][0][RTW89_KCC][40] = 24,
- [0][0][1][0][RTW89_FCC][42] = 22,
- [0][0][1][0][RTW89_ETSI][42] = 66,
- [0][0][1][0][RTW89_KCC][42] = 24,
- [0][0][1][0][RTW89_FCC][44] = 22,
- [0][0][1][0][RTW89_ETSI][44] = 66,
- [0][0][1][0][RTW89_KCC][44] = 24,
- [0][0][1][0][RTW89_FCC][45] = 22,
- [0][0][1][0][RTW89_ETSI][45] = 127,
- [0][0][1][0][RTW89_KCC][45] = 24,
- [0][0][1][0][RTW89_FCC][47] = 22,
- [0][0][1][0][RTW89_ETSI][47] = 127,
- [0][0][1][0][RTW89_KCC][47] = 24,
- [0][0][1][0][RTW89_FCC][49] = 24,
- [0][0][1][0][RTW89_ETSI][49] = 127,
- [0][0][1][0][RTW89_KCC][49] = 24,
- [0][0][1][0][RTW89_FCC][51] = 22,
- [0][0][1][0][RTW89_ETSI][51] = 127,
- [0][0][1][0][RTW89_KCC][51] = 24,
- [0][0][1][0][RTW89_FCC][53] = 22,
- [0][0][1][0][RTW89_ETSI][53] = 127,
- [0][0][1][0][RTW89_KCC][53] = 24,
- [0][0][1][0][RTW89_FCC][55] = 22,
- [0][0][1][0][RTW89_ETSI][55] = 127,
- [0][0][1][0][RTW89_KCC][55] = 26,
- [0][0][1][0][RTW89_FCC][57] = 22,
- [0][0][1][0][RTW89_ETSI][57] = 127,
- [0][0][1][0][RTW89_KCC][57] = 26,
- [0][0][1][0][RTW89_FCC][59] = 22,
- [0][0][1][0][RTW89_ETSI][59] = 127,
- [0][0][1][0][RTW89_KCC][59] = 26,
- [0][0][1][0][RTW89_FCC][60] = 22,
- [0][0][1][0][RTW89_ETSI][60] = 127,
- [0][0][1][0][RTW89_KCC][60] = 26,
- [0][0][1][0][RTW89_FCC][62] = 22,
- [0][0][1][0][RTW89_ETSI][62] = 127,
- [0][0][1][0][RTW89_KCC][62] = 26,
- [0][0][1][0][RTW89_FCC][64] = 22,
- [0][0][1][0][RTW89_ETSI][64] = 127,
- [0][0][1][0][RTW89_KCC][64] = 26,
- [0][0][1][0][RTW89_FCC][66] = 22,
- [0][0][1][0][RTW89_ETSI][66] = 127,
- [0][0][1][0][RTW89_KCC][66] = 26,
- [0][0][1][0][RTW89_FCC][68] = 22,
- [0][0][1][0][RTW89_ETSI][68] = 127,
- [0][0][1][0][RTW89_KCC][68] = 26,
- [0][0][1][0][RTW89_FCC][70] = 24,
- [0][0][1][0][RTW89_ETSI][70] = 127,
- [0][0][1][0][RTW89_KCC][70] = 26,
- [0][0][1][0][RTW89_FCC][72] = 22,
- [0][0][1][0][RTW89_ETSI][72] = 127,
- [0][0][1][0][RTW89_KCC][72] = 26,
- [0][0][1][0][RTW89_FCC][74] = 22,
- [0][0][1][0][RTW89_ETSI][74] = 127,
- [0][0][1][0][RTW89_KCC][74] = 26,
- [0][0][1][0][RTW89_FCC][75] = 22,
- [0][0][1][0][RTW89_ETSI][75] = 127,
- [0][0][1][0][RTW89_KCC][75] = 26,
- [0][0][1][0][RTW89_FCC][77] = 22,
- [0][0][1][0][RTW89_ETSI][77] = 127,
- [0][0][1][0][RTW89_KCC][77] = 26,
- [0][0][1][0][RTW89_FCC][79] = 22,
- [0][0][1][0][RTW89_ETSI][79] = 127,
- [0][0][1][0][RTW89_KCC][79] = 26,
- [0][0][1][0][RTW89_FCC][81] = 22,
- [0][0][1][0][RTW89_ETSI][81] = 127,
- [0][0][1][0][RTW89_KCC][81] = 26,
- [0][0][1][0][RTW89_FCC][83] = 22,
- [0][0][1][0][RTW89_ETSI][83] = 127,
- [0][0][1][0][RTW89_KCC][83] = 32,
- [0][0][1][0][RTW89_FCC][85] = 22,
- [0][0][1][0][RTW89_ETSI][85] = 127,
- [0][0][1][0][RTW89_KCC][85] = 32,
- [0][0][1][0][RTW89_FCC][87] = 22,
- [0][0][1][0][RTW89_ETSI][87] = 127,
- [0][0][1][0][RTW89_KCC][87] = 32,
- [0][0][1][0][RTW89_FCC][89] = 22,
- [0][0][1][0][RTW89_ETSI][89] = 127,
- [0][0][1][0][RTW89_KCC][89] = 32,
- [0][0][1][0][RTW89_FCC][90] = 22,
- [0][0][1][0][RTW89_ETSI][90] = 127,
- [0][0][1][0][RTW89_KCC][90] = 32,
- [0][0][1][0][RTW89_FCC][92] = 22,
- [0][0][1][0][RTW89_ETSI][92] = 127,
- [0][0][1][0][RTW89_KCC][92] = 32,
- [0][0][1][0][RTW89_FCC][94] = 22,
- [0][0][1][0][RTW89_ETSI][94] = 127,
- [0][0][1][0][RTW89_KCC][94] = 32,
- [0][0][1][0][RTW89_FCC][96] = 22,
- [0][0][1][0][RTW89_ETSI][96] = 127,
- [0][0][1][0][RTW89_KCC][96] = 32,
- [0][0][1][0][RTW89_FCC][98] = 22,
- [0][0][1][0][RTW89_ETSI][98] = 127,
- [0][0][1][0][RTW89_KCC][98] = 32,
- [0][0][1][0][RTW89_FCC][100] = 22,
- [0][0][1][0][RTW89_ETSI][100] = 127,
- [0][0][1][0][RTW89_KCC][100] = 32,
- [0][0][1][0][RTW89_FCC][102] = 22,
- [0][0][1][0][RTW89_ETSI][102] = 127,
- [0][0][1][0][RTW89_KCC][102] = 32,
- [0][0][1][0][RTW89_FCC][104] = 22,
- [0][0][1][0][RTW89_ETSI][104] = 127,
- [0][0][1][0][RTW89_KCC][104] = 32,
- [0][0][1][0][RTW89_FCC][105] = 22,
- [0][0][1][0][RTW89_ETSI][105] = 127,
- [0][0][1][0][RTW89_KCC][105] = 32,
- [0][0][1][0][RTW89_FCC][107] = 24,
- [0][0][1][0][RTW89_ETSI][107] = 127,
- [0][0][1][0][RTW89_KCC][107] = 32,
- [0][0][1][0][RTW89_FCC][109] = 24,
- [0][0][1][0][RTW89_ETSI][109] = 127,
- [0][0][1][0][RTW89_KCC][109] = 32,
- [0][0][1][0][RTW89_FCC][111] = 127,
- [0][0][1][0][RTW89_ETSI][111] = 127,
- [0][0][1][0][RTW89_KCC][111] = 127,
- [0][0][1][0][RTW89_FCC][113] = 127,
- [0][0][1][0][RTW89_ETSI][113] = 127,
- [0][0][1][0][RTW89_KCC][113] = 127,
- [0][0][1][0][RTW89_FCC][115] = 127,
- [0][0][1][0][RTW89_ETSI][115] = 127,
- [0][0][1][0][RTW89_KCC][115] = 127,
- [0][0][1][0][RTW89_FCC][117] = 127,
- [0][0][1][0][RTW89_ETSI][117] = 127,
- [0][0][1][0][RTW89_KCC][117] = 127,
- [0][0][1][0][RTW89_FCC][119] = 127,
- [0][0][1][0][RTW89_ETSI][119] = 127,
- [0][0][1][0][RTW89_KCC][119] = 127,
- [0][1][1][0][RTW89_FCC][0] = -2,
- [0][1][1][0][RTW89_ETSI][0] = 54,
- [0][1][1][0][RTW89_KCC][0] = 12,
- [0][1][1][0][RTW89_FCC][2] = -4,
- [0][1][1][0][RTW89_ETSI][2] = 54,
- [0][1][1][0][RTW89_KCC][2] = 12,
- [0][1][1][0][RTW89_FCC][4] = -4,
- [0][1][1][0][RTW89_ETSI][4] = 54,
- [0][1][1][0][RTW89_KCC][4] = 12,
- [0][1][1][0][RTW89_FCC][6] = -4,
- [0][1][1][0][RTW89_ETSI][6] = 54,
- [0][1][1][0][RTW89_KCC][6] = 12,
- [0][1][1][0][RTW89_FCC][8] = -4,
- [0][1][1][0][RTW89_ETSI][8] = 54,
- [0][1][1][0][RTW89_KCC][8] = 12,
- [0][1][1][0][RTW89_FCC][10] = -4,
- [0][1][1][0][RTW89_ETSI][10] = 54,
- [0][1][1][0][RTW89_KCC][10] = 12,
- [0][1][1][0][RTW89_FCC][12] = -4,
- [0][1][1][0][RTW89_ETSI][12] = 54,
- [0][1][1][0][RTW89_KCC][12] = 12,
- [0][1][1][0][RTW89_FCC][14] = -4,
- [0][1][1][0][RTW89_ETSI][14] = 54,
- [0][1][1][0][RTW89_KCC][14] = 12,
- [0][1][1][0][RTW89_FCC][15] = -4,
- [0][1][1][0][RTW89_ETSI][15] = 54,
- [0][1][1][0][RTW89_KCC][15] = 12,
- [0][1][1][0][RTW89_FCC][17] = -4,
- [0][1][1][0][RTW89_ETSI][17] = 54,
- [0][1][1][0][RTW89_KCC][17] = 12,
- [0][1][1][0][RTW89_FCC][19] = -4,
- [0][1][1][0][RTW89_ETSI][19] = 54,
- [0][1][1][0][RTW89_KCC][19] = 12,
- [0][1][1][0][RTW89_FCC][21] = -4,
- [0][1][1][0][RTW89_ETSI][21] = 54,
- [0][1][1][0][RTW89_KCC][21] = 12,
- [0][1][1][0][RTW89_FCC][23] = -4,
- [0][1][1][0][RTW89_ETSI][23] = 54,
- [0][1][1][0][RTW89_KCC][23] = 12,
- [0][1][1][0][RTW89_FCC][25] = -4,
- [0][1][1][0][RTW89_ETSI][25] = 54,
- [0][1][1][0][RTW89_KCC][25] = 12,
- [0][1][1][0][RTW89_FCC][27] = -4,
- [0][1][1][0][RTW89_ETSI][27] = 54,
- [0][1][1][0][RTW89_KCC][27] = 12,
- [0][1][1][0][RTW89_FCC][29] = -4,
- [0][1][1][0][RTW89_ETSI][29] = 54,
- [0][1][1][0][RTW89_KCC][29] = 12,
- [0][1][1][0][RTW89_FCC][30] = -4,
- [0][1][1][0][RTW89_ETSI][30] = 54,
- [0][1][1][0][RTW89_KCC][30] = 12,
- [0][1][1][0][RTW89_FCC][32] = -4,
- [0][1][1][0][RTW89_ETSI][32] = 54,
- [0][1][1][0][RTW89_KCC][32] = 12,
- [0][1][1][0][RTW89_FCC][34] = -4,
- [0][1][1][0][RTW89_ETSI][34] = 54,
- [0][1][1][0][RTW89_KCC][34] = 12,
- [0][1][1][0][RTW89_FCC][36] = -4,
- [0][1][1][0][RTW89_ETSI][36] = 54,
- [0][1][1][0][RTW89_KCC][36] = 12,
- [0][1][1][0][RTW89_FCC][38] = -4,
- [0][1][1][0][RTW89_ETSI][38] = 54,
- [0][1][1][0][RTW89_KCC][38] = 12,
- [0][1][1][0][RTW89_FCC][40] = -4,
- [0][1][1][0][RTW89_ETSI][40] = 54,
- [0][1][1][0][RTW89_KCC][40] = 12,
- [0][1][1][0][RTW89_FCC][42] = -4,
- [0][1][1][0][RTW89_ETSI][42] = 54,
- [0][1][1][0][RTW89_KCC][42] = 12,
- [0][1][1][0][RTW89_FCC][44] = -2,
- [0][1][1][0][RTW89_ETSI][44] = 54,
- [0][1][1][0][RTW89_KCC][44] = 12,
- [0][1][1][0][RTW89_FCC][45] = -2,
- [0][1][1][0][RTW89_ETSI][45] = 127,
- [0][1][1][0][RTW89_KCC][45] = 12,
- [0][1][1][0][RTW89_FCC][47] = -2,
- [0][1][1][0][RTW89_ETSI][47] = 127,
- [0][1][1][0][RTW89_KCC][47] = 12,
- [0][1][1][0][RTW89_FCC][49] = -2,
- [0][1][1][0][RTW89_ETSI][49] = 127,
- [0][1][1][0][RTW89_KCC][49] = 12,
- [0][1][1][0][RTW89_FCC][51] = -2,
- [0][1][1][0][RTW89_ETSI][51] = 127,
- [0][1][1][0][RTW89_KCC][51] = 12,
- [0][1][1][0][RTW89_FCC][53] = -2,
- [0][1][1][0][RTW89_ETSI][53] = 127,
- [0][1][1][0][RTW89_KCC][53] = 12,
- [0][1][1][0][RTW89_FCC][55] = -2,
- [0][1][1][0][RTW89_ETSI][55] = 127,
- [0][1][1][0][RTW89_KCC][55] = 12,
- [0][1][1][0][RTW89_FCC][57] = -2,
- [0][1][1][0][RTW89_ETSI][57] = 127,
- [0][1][1][0][RTW89_KCC][57] = 12,
- [0][1][1][0][RTW89_FCC][59] = -2,
- [0][1][1][0][RTW89_ETSI][59] = 127,
- [0][1][1][0][RTW89_KCC][59] = 12,
- [0][1][1][0][RTW89_FCC][60] = -2,
- [0][1][1][0][RTW89_ETSI][60] = 127,
- [0][1][1][0][RTW89_KCC][60] = 12,
- [0][1][1][0][RTW89_FCC][62] = -2,
- [0][1][1][0][RTW89_ETSI][62] = 127,
- [0][1][1][0][RTW89_KCC][62] = 12,
- [0][1][1][0][RTW89_FCC][64] = -2,
- [0][1][1][0][RTW89_ETSI][64] = 127,
- [0][1][1][0][RTW89_KCC][64] = 12,
- [0][1][1][0][RTW89_FCC][66] = -2,
- [0][1][1][0][RTW89_ETSI][66] = 127,
- [0][1][1][0][RTW89_KCC][66] = 12,
- [0][1][1][0][RTW89_FCC][68] = -2,
- [0][1][1][0][RTW89_ETSI][68] = 127,
- [0][1][1][0][RTW89_KCC][68] = 12,
- [0][1][1][0][RTW89_FCC][70] = -2,
- [0][1][1][0][RTW89_ETSI][70] = 127,
- [0][1][1][0][RTW89_KCC][70] = 12,
- [0][1][1][0][RTW89_FCC][72] = -2,
- [0][1][1][0][RTW89_ETSI][72] = 127,
- [0][1][1][0][RTW89_KCC][72] = 12,
- [0][1][1][0][RTW89_FCC][74] = -2,
- [0][1][1][0][RTW89_ETSI][74] = 127,
- [0][1][1][0][RTW89_KCC][74] = 12,
- [0][1][1][0][RTW89_FCC][75] = -2,
- [0][1][1][0][RTW89_ETSI][75] = 127,
- [0][1][1][0][RTW89_KCC][75] = 12,
- [0][1][1][0][RTW89_FCC][77] = -2,
- [0][1][1][0][RTW89_ETSI][77] = 127,
- [0][1][1][0][RTW89_KCC][77] = 12,
- [0][1][1][0][RTW89_FCC][79] = -2,
- [0][1][1][0][RTW89_ETSI][79] = 127,
- [0][1][1][0][RTW89_KCC][79] = 12,
- [0][1][1][0][RTW89_FCC][81] = -2,
- [0][1][1][0][RTW89_ETSI][81] = 127,
- [0][1][1][0][RTW89_KCC][81] = 12,
- [0][1][1][0][RTW89_FCC][83] = -2,
- [0][1][1][0][RTW89_ETSI][83] = 127,
- [0][1][1][0][RTW89_KCC][83] = 20,
- [0][1][1][0][RTW89_FCC][85] = -2,
- [0][1][1][0][RTW89_ETSI][85] = 127,
- [0][1][1][0][RTW89_KCC][85] = 20,
- [0][1][1][0][RTW89_FCC][87] = -2,
- [0][1][1][0][RTW89_ETSI][87] = 127,
- [0][1][1][0][RTW89_KCC][87] = 20,
- [0][1][1][0][RTW89_FCC][89] = -2,
- [0][1][1][0][RTW89_ETSI][89] = 127,
- [0][1][1][0][RTW89_KCC][89] = 20,
- [0][1][1][0][RTW89_FCC][90] = -2,
- [0][1][1][0][RTW89_ETSI][90] = 127,
- [0][1][1][0][RTW89_KCC][90] = 20,
- [0][1][1][0][RTW89_FCC][92] = -2,
- [0][1][1][0][RTW89_ETSI][92] = 127,
- [0][1][1][0][RTW89_KCC][92] = 20,
- [0][1][1][0][RTW89_FCC][94] = -2,
- [0][1][1][0][RTW89_ETSI][94] = 127,
- [0][1][1][0][RTW89_KCC][94] = 20,
- [0][1][1][0][RTW89_FCC][96] = -2,
- [0][1][1][0][RTW89_ETSI][96] = 127,
- [0][1][1][0][RTW89_KCC][96] = 20,
- [0][1][1][0][RTW89_FCC][98] = -2,
- [0][1][1][0][RTW89_ETSI][98] = 127,
- [0][1][1][0][RTW89_KCC][98] = 20,
- [0][1][1][0][RTW89_FCC][100] = -2,
- [0][1][1][0][RTW89_ETSI][100] = 127,
- [0][1][1][0][RTW89_KCC][100] = 20,
- [0][1][1][0][RTW89_FCC][102] = -2,
- [0][1][1][0][RTW89_ETSI][102] = 127,
- [0][1][1][0][RTW89_KCC][102] = 20,
- [0][1][1][0][RTW89_FCC][104] = -2,
- [0][1][1][0][RTW89_ETSI][104] = 127,
- [0][1][1][0][RTW89_KCC][104] = 20,
- [0][1][1][0][RTW89_FCC][105] = -2,
- [0][1][1][0][RTW89_ETSI][105] = 127,
- [0][1][1][0][RTW89_KCC][105] = 20,
- [0][1][1][0][RTW89_FCC][107] = 0,
- [0][1][1][0][RTW89_ETSI][107] = 127,
- [0][1][1][0][RTW89_KCC][107] = 20,
- [0][1][1][0][RTW89_FCC][109] = 0,
- [0][1][1][0][RTW89_ETSI][109] = 127,
- [0][1][1][0][RTW89_KCC][109] = 20,
- [0][1][1][0][RTW89_FCC][111] = 127,
- [0][1][1][0][RTW89_ETSI][111] = 127,
- [0][1][1][0][RTW89_KCC][111] = 127,
- [0][1][1][0][RTW89_FCC][113] = 127,
- [0][1][1][0][RTW89_ETSI][113] = 127,
- [0][1][1][0][RTW89_KCC][113] = 127,
- [0][1][1][0][RTW89_FCC][115] = 127,
- [0][1][1][0][RTW89_ETSI][115] = 127,
- [0][1][1][0][RTW89_KCC][115] = 127,
- [0][1][1][0][RTW89_FCC][117] = 127,
- [0][1][1][0][RTW89_ETSI][117] = 127,
- [0][1][1][0][RTW89_KCC][117] = 127,
- [0][1][1][0][RTW89_FCC][119] = 127,
- [0][1][1][0][RTW89_ETSI][119] = 127,
- [0][1][1][0][RTW89_KCC][119] = 127,
- [0][0][2][0][RTW89_FCC][0] = 24,
- [0][0][2][0][RTW89_ETSI][0] = 66,
- [0][0][2][0][RTW89_KCC][0] = 24,
- [0][0][2][0][RTW89_FCC][2] = 22,
- [0][0][2][0][RTW89_ETSI][2] = 66,
- [0][0][2][0][RTW89_KCC][2] = 24,
- [0][0][2][0][RTW89_FCC][4] = 22,
- [0][0][2][0][RTW89_ETSI][4] = 66,
- [0][0][2][0][RTW89_KCC][4] = 24,
- [0][0][2][0][RTW89_FCC][6] = 22,
- [0][0][2][0][RTW89_ETSI][6] = 66,
- [0][0][2][0][RTW89_KCC][6] = 24,
- [0][0][2][0][RTW89_FCC][8] = 22,
- [0][0][2][0][RTW89_ETSI][8] = 66,
- [0][0][2][0][RTW89_KCC][8] = 24,
- [0][0][2][0][RTW89_FCC][10] = 22,
- [0][0][2][0][RTW89_ETSI][10] = 66,
- [0][0][2][0][RTW89_KCC][10] = 24,
- [0][0][2][0][RTW89_FCC][12] = 22,
- [0][0][2][0][RTW89_ETSI][12] = 66,
- [0][0][2][0][RTW89_KCC][12] = 24,
- [0][0][2][0][RTW89_FCC][14] = 22,
- [0][0][2][0][RTW89_ETSI][14] = 66,
- [0][0][2][0][RTW89_KCC][14] = 24,
- [0][0][2][0][RTW89_FCC][15] = 22,
- [0][0][2][0][RTW89_ETSI][15] = 66,
- [0][0][2][0][RTW89_KCC][15] = 24,
- [0][0][2][0][RTW89_FCC][17] = 22,
- [0][0][2][0][RTW89_ETSI][17] = 66,
- [0][0][2][0][RTW89_KCC][17] = 24,
- [0][0][2][0][RTW89_FCC][19] = 22,
- [0][0][2][0][RTW89_ETSI][19] = 66,
- [0][0][2][0][RTW89_KCC][19] = 24,
- [0][0][2][0][RTW89_FCC][21] = 22,
- [0][0][2][0][RTW89_ETSI][21] = 66,
- [0][0][2][0][RTW89_KCC][21] = 24,
- [0][0][2][0][RTW89_FCC][23] = 22,
- [0][0][2][0][RTW89_ETSI][23] = 66,
- [0][0][2][0][RTW89_KCC][23] = 24,
- [0][0][2][0][RTW89_FCC][25] = 22,
- [0][0][2][0][RTW89_ETSI][25] = 66,
- [0][0][2][0][RTW89_KCC][25] = 24,
- [0][0][2][0][RTW89_FCC][27] = 22,
- [0][0][2][0][RTW89_ETSI][27] = 66,
- [0][0][2][0][RTW89_KCC][27] = 24,
- [0][0][2][0][RTW89_FCC][29] = 22,
- [0][0][2][0][RTW89_ETSI][29] = 66,
- [0][0][2][0][RTW89_KCC][29] = 24,
- [0][0][2][0][RTW89_FCC][30] = 22,
- [0][0][2][0][RTW89_ETSI][30] = 66,
- [0][0][2][0][RTW89_KCC][30] = 24,
- [0][0][2][0][RTW89_FCC][32] = 22,
- [0][0][2][0][RTW89_ETSI][32] = 66,
- [0][0][2][0][RTW89_KCC][32] = 24,
- [0][0][2][0][RTW89_FCC][34] = 22,
- [0][0][2][0][RTW89_ETSI][34] = 66,
- [0][0][2][0][RTW89_KCC][34] = 24,
- [0][0][2][0][RTW89_FCC][36] = 22,
- [0][0][2][0][RTW89_ETSI][36] = 66,
- [0][0][2][0][RTW89_KCC][36] = 24,
- [0][0][2][0][RTW89_FCC][38] = 22,
- [0][0][2][0][RTW89_ETSI][38] = 66,
- [0][0][2][0][RTW89_KCC][38] = 24,
- [0][0][2][0][RTW89_FCC][40] = 22,
- [0][0][2][0][RTW89_ETSI][40] = 66,
- [0][0][2][0][RTW89_KCC][40] = 24,
- [0][0][2][0][RTW89_FCC][42] = 22,
- [0][0][2][0][RTW89_ETSI][42] = 66,
- [0][0][2][0][RTW89_KCC][42] = 24,
- [0][0][2][0][RTW89_FCC][44] = 22,
- [0][0][2][0][RTW89_ETSI][44] = 66,
- [0][0][2][0][RTW89_KCC][44] = 24,
- [0][0][2][0][RTW89_FCC][45] = 22,
- [0][0][2][0][RTW89_ETSI][45] = 127,
- [0][0][2][0][RTW89_KCC][45] = 24,
- [0][0][2][0][RTW89_FCC][47] = 22,
- [0][0][2][0][RTW89_ETSI][47] = 127,
- [0][0][2][0][RTW89_KCC][47] = 24,
- [0][0][2][0][RTW89_FCC][49] = 24,
- [0][0][2][0][RTW89_ETSI][49] = 127,
- [0][0][2][0][RTW89_KCC][49] = 24,
- [0][0][2][0][RTW89_FCC][51] = 22,
- [0][0][2][0][RTW89_ETSI][51] = 127,
- [0][0][2][0][RTW89_KCC][51] = 24,
- [0][0][2][0][RTW89_FCC][53] = 22,
- [0][0][2][0][RTW89_ETSI][53] = 127,
- [0][0][2][0][RTW89_KCC][53] = 24,
- [0][0][2][0][RTW89_FCC][55] = 22,
- [0][0][2][0][RTW89_ETSI][55] = 127,
- [0][0][2][0][RTW89_KCC][55] = 26,
- [0][0][2][0][RTW89_FCC][57] = 22,
- [0][0][2][0][RTW89_ETSI][57] = 127,
- [0][0][2][0][RTW89_KCC][57] = 26,
- [0][0][2][0][RTW89_FCC][59] = 22,
- [0][0][2][0][RTW89_ETSI][59] = 127,
- [0][0][2][0][RTW89_KCC][59] = 26,
- [0][0][2][0][RTW89_FCC][60] = 22,
- [0][0][2][0][RTW89_ETSI][60] = 127,
- [0][0][2][0][RTW89_KCC][60] = 26,
- [0][0][2][0][RTW89_FCC][62] = 22,
- [0][0][2][0][RTW89_ETSI][62] = 127,
- [0][0][2][0][RTW89_KCC][62] = 26,
- [0][0][2][0][RTW89_FCC][64] = 22,
- [0][0][2][0][RTW89_ETSI][64] = 127,
- [0][0][2][0][RTW89_KCC][64] = 26,
- [0][0][2][0][RTW89_FCC][66] = 22,
- [0][0][2][0][RTW89_ETSI][66] = 127,
- [0][0][2][0][RTW89_KCC][66] = 26,
- [0][0][2][0][RTW89_FCC][68] = 22,
- [0][0][2][0][RTW89_ETSI][68] = 127,
- [0][0][2][0][RTW89_KCC][68] = 26,
- [0][0][2][0][RTW89_FCC][70] = 24,
- [0][0][2][0][RTW89_ETSI][70] = 127,
- [0][0][2][0][RTW89_KCC][70] = 26,
- [0][0][2][0][RTW89_FCC][72] = 22,
- [0][0][2][0][RTW89_ETSI][72] = 127,
- [0][0][2][0][RTW89_KCC][72] = 26,
- [0][0][2][0][RTW89_FCC][74] = 22,
- [0][0][2][0][RTW89_ETSI][74] = 127,
- [0][0][2][0][RTW89_KCC][74] = 26,
- [0][0][2][0][RTW89_FCC][75] = 22,
- [0][0][2][0][RTW89_ETSI][75] = 127,
- [0][0][2][0][RTW89_KCC][75] = 26,
- [0][0][2][0][RTW89_FCC][77] = 22,
- [0][0][2][0][RTW89_ETSI][77] = 127,
- [0][0][2][0][RTW89_KCC][77] = 26,
- [0][0][2][0][RTW89_FCC][79] = 22,
- [0][0][2][0][RTW89_ETSI][79] = 127,
- [0][0][2][0][RTW89_KCC][79] = 26,
- [0][0][2][0][RTW89_FCC][81] = 22,
- [0][0][2][0][RTW89_ETSI][81] = 127,
- [0][0][2][0][RTW89_KCC][81] = 26,
- [0][0][2][0][RTW89_FCC][83] = 22,
- [0][0][2][0][RTW89_ETSI][83] = 127,
- [0][0][2][0][RTW89_KCC][83] = 32,
- [0][0][2][0][RTW89_FCC][85] = 22,
- [0][0][2][0][RTW89_ETSI][85] = 127,
- [0][0][2][0][RTW89_KCC][85] = 32,
- [0][0][2][0][RTW89_FCC][87] = 22,
- [0][0][2][0][RTW89_ETSI][87] = 127,
- [0][0][2][0][RTW89_KCC][87] = 32,
- [0][0][2][0][RTW89_FCC][89] = 22,
- [0][0][2][0][RTW89_ETSI][89] = 127,
- [0][0][2][0][RTW89_KCC][89] = 32,
- [0][0][2][0][RTW89_FCC][90] = 22,
- [0][0][2][0][RTW89_ETSI][90] = 127,
- [0][0][2][0][RTW89_KCC][90] = 32,
- [0][0][2][0][RTW89_FCC][92] = 22,
- [0][0][2][0][RTW89_ETSI][92] = 127,
- [0][0][2][0][RTW89_KCC][92] = 32,
- [0][0][2][0][RTW89_FCC][94] = 22,
- [0][0][2][0][RTW89_ETSI][94] = 127,
- [0][0][2][0][RTW89_KCC][94] = 32,
- [0][0][2][0][RTW89_FCC][96] = 22,
- [0][0][2][0][RTW89_ETSI][96] = 127,
- [0][0][2][0][RTW89_KCC][96] = 32,
- [0][0][2][0][RTW89_FCC][98] = 22,
- [0][0][2][0][RTW89_ETSI][98] = 127,
- [0][0][2][0][RTW89_KCC][98] = 32,
- [0][0][2][0][RTW89_FCC][100] = 22,
- [0][0][2][0][RTW89_ETSI][100] = 127,
- [0][0][2][0][RTW89_KCC][100] = 32,
- [0][0][2][0][RTW89_FCC][102] = 22,
- [0][0][2][0][RTW89_ETSI][102] = 127,
- [0][0][2][0][RTW89_KCC][102] = 32,
- [0][0][2][0][RTW89_FCC][104] = 22,
- [0][0][2][0][RTW89_ETSI][104] = 127,
- [0][0][2][0][RTW89_KCC][104] = 32,
- [0][0][2][0][RTW89_FCC][105] = 22,
- [0][0][2][0][RTW89_ETSI][105] = 127,
- [0][0][2][0][RTW89_KCC][105] = 32,
- [0][0][2][0][RTW89_FCC][107] = 24,
- [0][0][2][0][RTW89_ETSI][107] = 127,
- [0][0][2][0][RTW89_KCC][107] = 32,
- [0][0][2][0][RTW89_FCC][109] = 24,
- [0][0][2][0][RTW89_ETSI][109] = 127,
- [0][0][2][0][RTW89_KCC][109] = 32,
- [0][0][2][0][RTW89_FCC][111] = 127,
- [0][0][2][0][RTW89_ETSI][111] = 127,
- [0][0][2][0][RTW89_KCC][111] = 127,
- [0][0][2][0][RTW89_FCC][113] = 127,
- [0][0][2][0][RTW89_ETSI][113] = 127,
- [0][0][2][0][RTW89_KCC][113] = 127,
- [0][0][2][0][RTW89_FCC][115] = 127,
- [0][0][2][0][RTW89_ETSI][115] = 127,
- [0][0][2][0][RTW89_KCC][115] = 127,
- [0][0][2][0][RTW89_FCC][117] = 127,
- [0][0][2][0][RTW89_ETSI][117] = 127,
- [0][0][2][0][RTW89_KCC][117] = 127,
- [0][0][2][0][RTW89_FCC][119] = 127,
- [0][0][2][0][RTW89_ETSI][119] = 127,
- [0][0][2][0][RTW89_KCC][119] = 127,
- [0][1][2][0][RTW89_FCC][0] = -2,
- [0][1][2][0][RTW89_ETSI][0] = 54,
- [0][1][2][0][RTW89_KCC][0] = 12,
- [0][1][2][0][RTW89_FCC][2] = -4,
- [0][1][2][0][RTW89_ETSI][2] = 54,
- [0][1][2][0][RTW89_KCC][2] = 12,
- [0][1][2][0][RTW89_FCC][4] = -4,
- [0][1][2][0][RTW89_ETSI][4] = 54,
- [0][1][2][0][RTW89_KCC][4] = 12,
- [0][1][2][0][RTW89_FCC][6] = -4,
- [0][1][2][0][RTW89_ETSI][6] = 54,
- [0][1][2][0][RTW89_KCC][6] = 12,
- [0][1][2][0][RTW89_FCC][8] = -4,
- [0][1][2][0][RTW89_ETSI][8] = 54,
- [0][1][2][0][RTW89_KCC][8] = 12,
- [0][1][2][0][RTW89_FCC][10] = -4,
- [0][1][2][0][RTW89_ETSI][10] = 54,
- [0][1][2][0][RTW89_KCC][10] = 12,
- [0][1][2][0][RTW89_FCC][12] = -4,
- [0][1][2][0][RTW89_ETSI][12] = 54,
- [0][1][2][0][RTW89_KCC][12] = 12,
- [0][1][2][0][RTW89_FCC][14] = -4,
- [0][1][2][0][RTW89_ETSI][14] = 54,
- [0][1][2][0][RTW89_KCC][14] = 12,
- [0][1][2][0][RTW89_FCC][15] = -4,
- [0][1][2][0][RTW89_ETSI][15] = 54,
- [0][1][2][0][RTW89_KCC][15] = 12,
- [0][1][2][0][RTW89_FCC][17] = -4,
- [0][1][2][0][RTW89_ETSI][17] = 54,
- [0][1][2][0][RTW89_KCC][17] = 12,
- [0][1][2][0][RTW89_FCC][19] = -4,
- [0][1][2][0][RTW89_ETSI][19] = 54,
- [0][1][2][0][RTW89_KCC][19] = 12,
- [0][1][2][0][RTW89_FCC][21] = -4,
- [0][1][2][0][RTW89_ETSI][21] = 54,
- [0][1][2][0][RTW89_KCC][21] = 12,
- [0][1][2][0][RTW89_FCC][23] = -4,
- [0][1][2][0][RTW89_ETSI][23] = 54,
- [0][1][2][0][RTW89_KCC][23] = 12,
- [0][1][2][0][RTW89_FCC][25] = -4,
- [0][1][2][0][RTW89_ETSI][25] = 54,
- [0][1][2][0][RTW89_KCC][25] = 12,
- [0][1][2][0][RTW89_FCC][27] = -4,
- [0][1][2][0][RTW89_ETSI][27] = 54,
- [0][1][2][0][RTW89_KCC][27] = 12,
- [0][1][2][0][RTW89_FCC][29] = -4,
- [0][1][2][0][RTW89_ETSI][29] = 54,
- [0][1][2][0][RTW89_KCC][29] = 12,
- [0][1][2][0][RTW89_FCC][30] = -4,
- [0][1][2][0][RTW89_ETSI][30] = 54,
- [0][1][2][0][RTW89_KCC][30] = 12,
- [0][1][2][0][RTW89_FCC][32] = -4,
- [0][1][2][0][RTW89_ETSI][32] = 54,
- [0][1][2][0][RTW89_KCC][32] = 12,
- [0][1][2][0][RTW89_FCC][34] = -4,
- [0][1][2][0][RTW89_ETSI][34] = 54,
- [0][1][2][0][RTW89_KCC][34] = 12,
- [0][1][2][0][RTW89_FCC][36] = -4,
- [0][1][2][0][RTW89_ETSI][36] = 54,
- [0][1][2][0][RTW89_KCC][36] = 12,
- [0][1][2][0][RTW89_FCC][38] = -4,
- [0][1][2][0][RTW89_ETSI][38] = 54,
- [0][1][2][0][RTW89_KCC][38] = 12,
- [0][1][2][0][RTW89_FCC][40] = -4,
- [0][1][2][0][RTW89_ETSI][40] = 54,
- [0][1][2][0][RTW89_KCC][40] = 12,
- [0][1][2][0][RTW89_FCC][42] = -4,
- [0][1][2][0][RTW89_ETSI][42] = 54,
- [0][1][2][0][RTW89_KCC][42] = 12,
- [0][1][2][0][RTW89_FCC][44] = -2,
- [0][1][2][0][RTW89_ETSI][44] = 54,
- [0][1][2][0][RTW89_KCC][44] = 12,
- [0][1][2][0][RTW89_FCC][45] = -2,
- [0][1][2][0][RTW89_ETSI][45] = 127,
- [0][1][2][0][RTW89_KCC][45] = 12,
- [0][1][2][0][RTW89_FCC][47] = -2,
- [0][1][2][0][RTW89_ETSI][47] = 127,
- [0][1][2][0][RTW89_KCC][47] = 12,
- [0][1][2][0][RTW89_FCC][49] = -2,
- [0][1][2][0][RTW89_ETSI][49] = 127,
- [0][1][2][0][RTW89_KCC][49] = 12,
- [0][1][2][0][RTW89_FCC][51] = -2,
- [0][1][2][0][RTW89_ETSI][51] = 127,
- [0][1][2][0][RTW89_KCC][51] = 12,
- [0][1][2][0][RTW89_FCC][53] = -2,
- [0][1][2][0][RTW89_ETSI][53] = 127,
- [0][1][2][0][RTW89_KCC][53] = 12,
- [0][1][2][0][RTW89_FCC][55] = -2,
- [0][1][2][0][RTW89_ETSI][55] = 127,
- [0][1][2][0][RTW89_KCC][55] = 12,
- [0][1][2][0][RTW89_FCC][57] = -2,
- [0][1][2][0][RTW89_ETSI][57] = 127,
- [0][1][2][0][RTW89_KCC][57] = 12,
- [0][1][2][0][RTW89_FCC][59] = -2,
- [0][1][2][0][RTW89_ETSI][59] = 127,
- [0][1][2][0][RTW89_KCC][59] = 12,
- [0][1][2][0][RTW89_FCC][60] = -2,
- [0][1][2][0][RTW89_ETSI][60] = 127,
- [0][1][2][0][RTW89_KCC][60] = 12,
- [0][1][2][0][RTW89_FCC][62] = -2,
- [0][1][2][0][RTW89_ETSI][62] = 127,
- [0][1][2][0][RTW89_KCC][62] = 12,
- [0][1][2][0][RTW89_FCC][64] = -2,
- [0][1][2][0][RTW89_ETSI][64] = 127,
- [0][1][2][0][RTW89_KCC][64] = 12,
- [0][1][2][0][RTW89_FCC][66] = -2,
- [0][1][2][0][RTW89_ETSI][66] = 127,
- [0][1][2][0][RTW89_KCC][66] = 12,
- [0][1][2][0][RTW89_FCC][68] = -2,
- [0][1][2][0][RTW89_ETSI][68] = 127,
- [0][1][2][0][RTW89_KCC][68] = 12,
- [0][1][2][0][RTW89_FCC][70] = -2,
- [0][1][2][0][RTW89_ETSI][70] = 127,
- [0][1][2][0][RTW89_KCC][70] = 12,
- [0][1][2][0][RTW89_FCC][72] = -2,
- [0][1][2][0][RTW89_ETSI][72] = 127,
- [0][1][2][0][RTW89_KCC][72] = 12,
- [0][1][2][0][RTW89_FCC][74] = -2,
- [0][1][2][0][RTW89_ETSI][74] = 127,
- [0][1][2][0][RTW89_KCC][74] = 12,
- [0][1][2][0][RTW89_FCC][75] = -2,
- [0][1][2][0][RTW89_ETSI][75] = 127,
- [0][1][2][0][RTW89_KCC][75] = 12,
- [0][1][2][0][RTW89_FCC][77] = -2,
- [0][1][2][0][RTW89_ETSI][77] = 127,
- [0][1][2][0][RTW89_KCC][77] = 12,
- [0][1][2][0][RTW89_FCC][79] = -2,
- [0][1][2][0][RTW89_ETSI][79] = 127,
- [0][1][2][0][RTW89_KCC][79] = 12,
- [0][1][2][0][RTW89_FCC][81] = -2,
- [0][1][2][0][RTW89_ETSI][81] = 127,
- [0][1][2][0][RTW89_KCC][81] = 12,
- [0][1][2][0][RTW89_FCC][83] = -2,
- [0][1][2][0][RTW89_ETSI][83] = 127,
- [0][1][2][0][RTW89_KCC][83] = 20,
- [0][1][2][0][RTW89_FCC][85] = -2,
- [0][1][2][0][RTW89_ETSI][85] = 127,
- [0][1][2][0][RTW89_KCC][85] = 20,
- [0][1][2][0][RTW89_FCC][87] = -2,
- [0][1][2][0][RTW89_ETSI][87] = 127,
- [0][1][2][0][RTW89_KCC][87] = 20,
- [0][1][2][0][RTW89_FCC][89] = -2,
- [0][1][2][0][RTW89_ETSI][89] = 127,
- [0][1][2][0][RTW89_KCC][89] = 20,
- [0][1][2][0][RTW89_FCC][90] = -2,
- [0][1][2][0][RTW89_ETSI][90] = 127,
- [0][1][2][0][RTW89_KCC][90] = 20,
- [0][1][2][0][RTW89_FCC][92] = -2,
- [0][1][2][0][RTW89_ETSI][92] = 127,
- [0][1][2][0][RTW89_KCC][92] = 20,
- [0][1][2][0][RTW89_FCC][94] = -2,
- [0][1][2][0][RTW89_ETSI][94] = 127,
- [0][1][2][0][RTW89_KCC][94] = 20,
- [0][1][2][0][RTW89_FCC][96] = -2,
- [0][1][2][0][RTW89_ETSI][96] = 127,
- [0][1][2][0][RTW89_KCC][96] = 20,
- [0][1][2][0][RTW89_FCC][98] = -2,
- [0][1][2][0][RTW89_ETSI][98] = 127,
- [0][1][2][0][RTW89_KCC][98] = 20,
- [0][1][2][0][RTW89_FCC][100] = -2,
- [0][1][2][0][RTW89_ETSI][100] = 127,
- [0][1][2][0][RTW89_KCC][100] = 20,
- [0][1][2][0][RTW89_FCC][102] = -2,
- [0][1][2][0][RTW89_ETSI][102] = 127,
- [0][1][2][0][RTW89_KCC][102] = 20,
- [0][1][2][0][RTW89_FCC][104] = -2,
- [0][1][2][0][RTW89_ETSI][104] = 127,
- [0][1][2][0][RTW89_KCC][104] = 20,
- [0][1][2][0][RTW89_FCC][105] = -2,
- [0][1][2][0][RTW89_ETSI][105] = 127,
- [0][1][2][0][RTW89_KCC][105] = 20,
- [0][1][2][0][RTW89_FCC][107] = 0,
- [0][1][2][0][RTW89_ETSI][107] = 127,
- [0][1][2][0][RTW89_KCC][107] = 20,
- [0][1][2][0][RTW89_FCC][109] = 0,
- [0][1][2][0][RTW89_ETSI][109] = 127,
- [0][1][2][0][RTW89_KCC][109] = 20,
- [0][1][2][0][RTW89_FCC][111] = 127,
- [0][1][2][0][RTW89_ETSI][111] = 127,
- [0][1][2][0][RTW89_KCC][111] = 127,
- [0][1][2][0][RTW89_FCC][113] = 127,
- [0][1][2][0][RTW89_ETSI][113] = 127,
- [0][1][2][0][RTW89_KCC][113] = 127,
- [0][1][2][0][RTW89_FCC][115] = 127,
- [0][1][2][0][RTW89_ETSI][115] = 127,
- [0][1][2][0][RTW89_KCC][115] = 127,
- [0][1][2][0][RTW89_FCC][117] = 127,
- [0][1][2][0][RTW89_ETSI][117] = 127,
- [0][1][2][0][RTW89_KCC][117] = 127,
- [0][1][2][0][RTW89_FCC][119] = 127,
- [0][1][2][0][RTW89_ETSI][119] = 127,
- [0][1][2][0][RTW89_KCC][119] = 127,
- [0][1][2][1][RTW89_FCC][0] = -2,
- [0][1][2][1][RTW89_ETSI][0] = 42,
- [0][1][2][1][RTW89_KCC][0] = 12,
- [0][1][2][1][RTW89_FCC][2] = -4,
- [0][1][2][1][RTW89_ETSI][2] = 42,
- [0][1][2][1][RTW89_KCC][2] = 12,
- [0][1][2][1][RTW89_FCC][4] = -4,
- [0][1][2][1][RTW89_ETSI][4] = 42,
- [0][1][2][1][RTW89_KCC][4] = 12,
- [0][1][2][1][RTW89_FCC][6] = -4,
- [0][1][2][1][RTW89_ETSI][6] = 42,
- [0][1][2][1][RTW89_KCC][6] = 12,
- [0][1][2][1][RTW89_FCC][8] = -4,
- [0][1][2][1][RTW89_ETSI][8] = 42,
- [0][1][2][1][RTW89_KCC][8] = 12,
- [0][1][2][1][RTW89_FCC][10] = -4,
- [0][1][2][1][RTW89_ETSI][10] = 42,
- [0][1][2][1][RTW89_KCC][10] = 12,
- [0][1][2][1][RTW89_FCC][12] = -4,
- [0][1][2][1][RTW89_ETSI][12] = 42,
- [0][1][2][1][RTW89_KCC][12] = 12,
- [0][1][2][1][RTW89_FCC][14] = -4,
- [0][1][2][1][RTW89_ETSI][14] = 42,
- [0][1][2][1][RTW89_KCC][14] = 12,
- [0][1][2][1][RTW89_FCC][15] = -4,
- [0][1][2][1][RTW89_ETSI][15] = 42,
- [0][1][2][1][RTW89_KCC][15] = 12,
- [0][1][2][1][RTW89_FCC][17] = -4,
- [0][1][2][1][RTW89_ETSI][17] = 42,
- [0][1][2][1][RTW89_KCC][17] = 12,
- [0][1][2][1][RTW89_FCC][19] = -4,
- [0][1][2][1][RTW89_ETSI][19] = 42,
- [0][1][2][1][RTW89_KCC][19] = 12,
- [0][1][2][1][RTW89_FCC][21] = -4,
- [0][1][2][1][RTW89_ETSI][21] = 42,
- [0][1][2][1][RTW89_KCC][21] = 12,
- [0][1][2][1][RTW89_FCC][23] = -4,
- [0][1][2][1][RTW89_ETSI][23] = 42,
- [0][1][2][1][RTW89_KCC][23] = 12,
- [0][1][2][1][RTW89_FCC][25] = -4,
- [0][1][2][1][RTW89_ETSI][25] = 42,
- [0][1][2][1][RTW89_KCC][25] = 12,
- [0][1][2][1][RTW89_FCC][27] = -4,
- [0][1][2][1][RTW89_ETSI][27] = 42,
- [0][1][2][1][RTW89_KCC][27] = 12,
- [0][1][2][1][RTW89_FCC][29] = -4,
- [0][1][2][1][RTW89_ETSI][29] = 42,
- [0][1][2][1][RTW89_KCC][29] = 12,
- [0][1][2][1][RTW89_FCC][30] = -4,
- [0][1][2][1][RTW89_ETSI][30] = 42,
- [0][1][2][1][RTW89_KCC][30] = 12,
- [0][1][2][1][RTW89_FCC][32] = -4,
- [0][1][2][1][RTW89_ETSI][32] = 42,
- [0][1][2][1][RTW89_KCC][32] = 12,
- [0][1][2][1][RTW89_FCC][34] = -4,
- [0][1][2][1][RTW89_ETSI][34] = 42,
- [0][1][2][1][RTW89_KCC][34] = 12,
- [0][1][2][1][RTW89_FCC][36] = -4,
- [0][1][2][1][RTW89_ETSI][36] = 42,
- [0][1][2][1][RTW89_KCC][36] = 12,
- [0][1][2][1][RTW89_FCC][38] = -4,
- [0][1][2][1][RTW89_ETSI][38] = 42,
- [0][1][2][1][RTW89_KCC][38] = 12,
- [0][1][2][1][RTW89_FCC][40] = -4,
- [0][1][2][1][RTW89_ETSI][40] = 42,
- [0][1][2][1][RTW89_KCC][40] = 12,
- [0][1][2][1][RTW89_FCC][42] = -4,
- [0][1][2][1][RTW89_ETSI][42] = 42,
- [0][1][2][1][RTW89_KCC][42] = 12,
- [0][1][2][1][RTW89_FCC][44] = -2,
- [0][1][2][1][RTW89_ETSI][44] = 42,
- [0][1][2][1][RTW89_KCC][44] = 12,
- [0][1][2][1][RTW89_FCC][45] = -2,
- [0][1][2][1][RTW89_ETSI][45] = 127,
- [0][1][2][1][RTW89_KCC][45] = 12,
- [0][1][2][1][RTW89_FCC][47] = -2,
- [0][1][2][1][RTW89_ETSI][47] = 127,
- [0][1][2][1][RTW89_KCC][47] = 12,
- [0][1][2][1][RTW89_FCC][49] = -2,
- [0][1][2][1][RTW89_ETSI][49] = 127,
- [0][1][2][1][RTW89_KCC][49] = 12,
- [0][1][2][1][RTW89_FCC][51] = -2,
- [0][1][2][1][RTW89_ETSI][51] = 127,
- [0][1][2][1][RTW89_KCC][51] = 12,
- [0][1][2][1][RTW89_FCC][53] = -2,
- [0][1][2][1][RTW89_ETSI][53] = 127,
- [0][1][2][1][RTW89_KCC][53] = 12,
- [0][1][2][1][RTW89_FCC][55] = -2,
- [0][1][2][1][RTW89_ETSI][55] = 127,
- [0][1][2][1][RTW89_KCC][55] = 12,
- [0][1][2][1][RTW89_FCC][57] = -2,
- [0][1][2][1][RTW89_ETSI][57] = 127,
- [0][1][2][1][RTW89_KCC][57] = 12,
- [0][1][2][1][RTW89_FCC][59] = -2,
- [0][1][2][1][RTW89_ETSI][59] = 127,
- [0][1][2][1][RTW89_KCC][59] = 12,
- [0][1][2][1][RTW89_FCC][60] = -2,
- [0][1][2][1][RTW89_ETSI][60] = 127,
- [0][1][2][1][RTW89_KCC][60] = 12,
- [0][1][2][1][RTW89_FCC][62] = -2,
- [0][1][2][1][RTW89_ETSI][62] = 127,
- [0][1][2][1][RTW89_KCC][62] = 12,
- [0][1][2][1][RTW89_FCC][64] = -2,
- [0][1][2][1][RTW89_ETSI][64] = 127,
- [0][1][2][1][RTW89_KCC][64] = 12,
- [0][1][2][1][RTW89_FCC][66] = -2,
- [0][1][2][1][RTW89_ETSI][66] = 127,
- [0][1][2][1][RTW89_KCC][66] = 12,
- [0][1][2][1][RTW89_FCC][68] = -2,
- [0][1][2][1][RTW89_ETSI][68] = 127,
- [0][1][2][1][RTW89_KCC][68] = 12,
- [0][1][2][1][RTW89_FCC][70] = -2,
- [0][1][2][1][RTW89_ETSI][70] = 127,
- [0][1][2][1][RTW89_KCC][70] = 12,
- [0][1][2][1][RTW89_FCC][72] = -2,
- [0][1][2][1][RTW89_ETSI][72] = 127,
- [0][1][2][1][RTW89_KCC][72] = 12,
- [0][1][2][1][RTW89_FCC][74] = -2,
- [0][1][2][1][RTW89_ETSI][74] = 127,
- [0][1][2][1][RTW89_KCC][74] = 12,
- [0][1][2][1][RTW89_FCC][75] = -2,
- [0][1][2][1][RTW89_ETSI][75] = 127,
- [0][1][2][1][RTW89_KCC][75] = 12,
- [0][1][2][1][RTW89_FCC][77] = -2,
- [0][1][2][1][RTW89_ETSI][77] = 127,
- [0][1][2][1][RTW89_KCC][77] = 12,
- [0][1][2][1][RTW89_FCC][79] = -2,
- [0][1][2][1][RTW89_ETSI][79] = 127,
- [0][1][2][1][RTW89_KCC][79] = 12,
- [0][1][2][1][RTW89_FCC][81] = -2,
- [0][1][2][1][RTW89_ETSI][81] = 127,
- [0][1][2][1][RTW89_KCC][81] = 12,
- [0][1][2][1][RTW89_FCC][83] = -2,
- [0][1][2][1][RTW89_ETSI][83] = 127,
- [0][1][2][1][RTW89_KCC][83] = 20,
- [0][1][2][1][RTW89_FCC][85] = -2,
- [0][1][2][1][RTW89_ETSI][85] = 127,
- [0][1][2][1][RTW89_KCC][85] = 20,
- [0][1][2][1][RTW89_FCC][87] = -2,
- [0][1][2][1][RTW89_ETSI][87] = 127,
- [0][1][2][1][RTW89_KCC][87] = 20,
- [0][1][2][1][RTW89_FCC][89] = -2,
- [0][1][2][1][RTW89_ETSI][89] = 127,
- [0][1][2][1][RTW89_KCC][89] = 20,
- [0][1][2][1][RTW89_FCC][90] = -2,
- [0][1][2][1][RTW89_ETSI][90] = 127,
- [0][1][2][1][RTW89_KCC][90] = 20,
- [0][1][2][1][RTW89_FCC][92] = -2,
- [0][1][2][1][RTW89_ETSI][92] = 127,
- [0][1][2][1][RTW89_KCC][92] = 20,
- [0][1][2][1][RTW89_FCC][94] = -2,
- [0][1][2][1][RTW89_ETSI][94] = 127,
- [0][1][2][1][RTW89_KCC][94] = 20,
- [0][1][2][1][RTW89_FCC][96] = -2,
- [0][1][2][1][RTW89_ETSI][96] = 127,
- [0][1][2][1][RTW89_KCC][96] = 20,
- [0][1][2][1][RTW89_FCC][98] = -2,
- [0][1][2][1][RTW89_ETSI][98] = 127,
- [0][1][2][1][RTW89_KCC][98] = 20,
- [0][1][2][1][RTW89_FCC][100] = -2,
- [0][1][2][1][RTW89_ETSI][100] = 127,
- [0][1][2][1][RTW89_KCC][100] = 20,
- [0][1][2][1][RTW89_FCC][102] = -2,
- [0][1][2][1][RTW89_ETSI][102] = 127,
- [0][1][2][1][RTW89_KCC][102] = 20,
- [0][1][2][1][RTW89_FCC][104] = -2,
- [0][1][2][1][RTW89_ETSI][104] = 127,
- [0][1][2][1][RTW89_KCC][104] = 20,
- [0][1][2][1][RTW89_FCC][105] = -2,
- [0][1][2][1][RTW89_ETSI][105] = 127,
- [0][1][2][1][RTW89_KCC][105] = 20,
- [0][1][2][1][RTW89_FCC][107] = 0,
- [0][1][2][1][RTW89_ETSI][107] = 127,
- [0][1][2][1][RTW89_KCC][107] = 20,
- [0][1][2][1][RTW89_FCC][109] = 0,
- [0][1][2][1][RTW89_ETSI][109] = 127,
- [0][1][2][1][RTW89_KCC][109] = 20,
- [0][1][2][1][RTW89_FCC][111] = 127,
- [0][1][2][1][RTW89_ETSI][111] = 127,
- [0][1][2][1][RTW89_KCC][111] = 127,
- [0][1][2][1][RTW89_FCC][113] = 127,
- [0][1][2][1][RTW89_ETSI][113] = 127,
- [0][1][2][1][RTW89_KCC][113] = 127,
- [0][1][2][1][RTW89_FCC][115] = 127,
- [0][1][2][1][RTW89_ETSI][115] = 127,
- [0][1][2][1][RTW89_KCC][115] = 127,
- [0][1][2][1][RTW89_FCC][117] = 127,
- [0][1][2][1][RTW89_ETSI][117] = 127,
- [0][1][2][1][RTW89_KCC][117] = 127,
- [0][1][2][1][RTW89_FCC][119] = 127,
- [0][1][2][1][RTW89_ETSI][119] = 127,
- [0][1][2][1][RTW89_KCC][119] = 127,
- [1][0][2][0][RTW89_FCC][1] = 34,
- [1][0][2][0][RTW89_ETSI][1] = 66,
- [1][0][2][0][RTW89_KCC][1] = 40,
- [1][0][2][0][RTW89_FCC][5] = 34,
- [1][0][2][0][RTW89_ETSI][5] = 66,
- [1][0][2][0][RTW89_KCC][5] = 40,
- [1][0][2][0][RTW89_FCC][9] = 34,
- [1][0][2][0][RTW89_ETSI][9] = 66,
- [1][0][2][0][RTW89_KCC][9] = 40,
- [1][0][2][0][RTW89_FCC][13] = 34,
- [1][0][2][0][RTW89_ETSI][13] = 66,
- [1][0][2][0][RTW89_KCC][13] = 40,
- [1][0][2][0][RTW89_FCC][16] = 34,
- [1][0][2][0][RTW89_ETSI][16] = 66,
- [1][0][2][0][RTW89_KCC][16] = 40,
- [1][0][2][0][RTW89_FCC][20] = 34,
- [1][0][2][0][RTW89_ETSI][20] = 66,
- [1][0][2][0][RTW89_KCC][20] = 40,
- [1][0][2][0][RTW89_FCC][24] = 36,
- [1][0][2][0][RTW89_ETSI][24] = 66,
- [1][0][2][0][RTW89_KCC][24] = 40,
- [1][0][2][0][RTW89_FCC][28] = 34,
- [1][0][2][0][RTW89_ETSI][28] = 66,
- [1][0][2][0][RTW89_KCC][28] = 40,
- [1][0][2][0][RTW89_FCC][31] = 34,
- [1][0][2][0][RTW89_ETSI][31] = 66,
- [1][0][2][0][RTW89_KCC][31] = 40,
- [1][0][2][0][RTW89_FCC][35] = 34,
- [1][0][2][0][RTW89_ETSI][35] = 66,
- [1][0][2][0][RTW89_KCC][35] = 40,
- [1][0][2][0][RTW89_FCC][39] = 34,
- [1][0][2][0][RTW89_ETSI][39] = 66,
- [1][0][2][0][RTW89_KCC][39] = 40,
- [1][0][2][0][RTW89_FCC][43] = 34,
- [1][0][2][0][RTW89_ETSI][43] = 66,
- [1][0][2][0][RTW89_KCC][43] = 40,
- [1][0][2][0][RTW89_FCC][46] = 34,
- [1][0][2][0][RTW89_ETSI][46] = 127,
- [1][0][2][0][RTW89_KCC][46] = 40,
- [1][0][2][0][RTW89_FCC][50] = 34,
- [1][0][2][0][RTW89_ETSI][50] = 127,
- [1][0][2][0][RTW89_KCC][50] = 40,
- [1][0][2][0][RTW89_FCC][54] = 36,
- [1][0][2][0][RTW89_ETSI][54] = 127,
- [1][0][2][0][RTW89_KCC][54] = 40,
- [1][0][2][0][RTW89_FCC][58] = 36,
- [1][0][2][0][RTW89_ETSI][58] = 127,
- [1][0][2][0][RTW89_KCC][58] = 40,
- [1][0][2][0][RTW89_FCC][61] = 34,
- [1][0][2][0][RTW89_ETSI][61] = 127,
- [1][0][2][0][RTW89_KCC][61] = 40,
- [1][0][2][0][RTW89_FCC][65] = 34,
- [1][0][2][0][RTW89_ETSI][65] = 127,
- [1][0][2][0][RTW89_KCC][65] = 40,
- [1][0][2][0][RTW89_FCC][69] = 34,
- [1][0][2][0][RTW89_ETSI][69] = 127,
- [1][0][2][0][RTW89_KCC][69] = 40,
- [1][0][2][0][RTW89_FCC][73] = 34,
- [1][0][2][0][RTW89_ETSI][73] = 127,
- [1][0][2][0][RTW89_KCC][73] = 40,
- [1][0][2][0][RTW89_FCC][76] = 34,
- [1][0][2][0][RTW89_ETSI][76] = 127,
- [1][0][2][0][RTW89_KCC][76] = 40,
- [1][0][2][0][RTW89_FCC][80] = 34,
- [1][0][2][0][RTW89_ETSI][80] = 127,
- [1][0][2][0][RTW89_KCC][80] = 42,
- [1][0][2][0][RTW89_FCC][84] = 34,
- [1][0][2][0][RTW89_ETSI][84] = 127,
- [1][0][2][0][RTW89_KCC][84] = 42,
- [1][0][2][0][RTW89_FCC][88] = 34,
- [1][0][2][0][RTW89_ETSI][88] = 127,
- [1][0][2][0][RTW89_KCC][88] = 42,
- [1][0][2][0][RTW89_FCC][91] = 36,
- [1][0][2][0][RTW89_ETSI][91] = 127,
- [1][0][2][0][RTW89_KCC][91] = 42,
- [1][0][2][0][RTW89_FCC][95] = 34,
- [1][0][2][0][RTW89_ETSI][95] = 127,
- [1][0][2][0][RTW89_KCC][95] = 42,
- [1][0][2][0][RTW89_FCC][99] = 34,
- [1][0][2][0][RTW89_ETSI][99] = 127,
- [1][0][2][0][RTW89_KCC][99] = 42,
- [1][0][2][0][RTW89_FCC][103] = 34,
- [1][0][2][0][RTW89_ETSI][103] = 127,
- [1][0][2][0][RTW89_KCC][103] = 42,
- [1][0][2][0][RTW89_FCC][106] = 36,
- [1][0][2][0][RTW89_ETSI][106] = 127,
- [1][0][2][0][RTW89_KCC][106] = 42,
- [1][0][2][0][RTW89_FCC][110] = 127,
- [1][0][2][0][RTW89_ETSI][110] = 127,
- [1][0][2][0][RTW89_KCC][110] = 127,
- [1][0][2][0][RTW89_FCC][114] = 127,
- [1][0][2][0][RTW89_ETSI][114] = 127,
- [1][0][2][0][RTW89_KCC][114] = 127,
- [1][0][2][0][RTW89_FCC][118] = 127,
- [1][0][2][0][RTW89_ETSI][118] = 127,
- [1][0][2][0][RTW89_KCC][118] = 127,
- [1][1][2][0][RTW89_FCC][1] = 10,
- [1][1][2][0][RTW89_ETSI][1] = 54,
- [1][1][2][0][RTW89_KCC][1] = 28,
- [1][1][2][0][RTW89_FCC][5] = 10,
- [1][1][2][0][RTW89_ETSI][5] = 54,
- [1][1][2][0][RTW89_KCC][5] = 28,
- [1][1][2][0][RTW89_FCC][9] = 10,
- [1][1][2][0][RTW89_ETSI][9] = 54,
- [1][1][2][0][RTW89_KCC][9] = 28,
- [1][1][2][0][RTW89_FCC][13] = 10,
- [1][1][2][0][RTW89_ETSI][13] = 54,
- [1][1][2][0][RTW89_KCC][13] = 28,
- [1][1][2][0][RTW89_FCC][16] = 10,
- [1][1][2][0][RTW89_ETSI][16] = 54,
- [1][1][2][0][RTW89_KCC][16] = 28,
- [1][1][2][0][RTW89_FCC][20] = 10,
- [1][1][2][0][RTW89_ETSI][20] = 54,
- [1][1][2][0][RTW89_KCC][20] = 28,
- [1][1][2][0][RTW89_FCC][24] = 10,
- [1][1][2][0][RTW89_ETSI][24] = 54,
- [1][1][2][0][RTW89_KCC][24] = 28,
- [1][1][2][0][RTW89_FCC][28] = 10,
- [1][1][2][0][RTW89_ETSI][28] = 54,
- [1][1][2][0][RTW89_KCC][28] = 28,
- [1][1][2][0][RTW89_FCC][31] = 10,
- [1][1][2][0][RTW89_ETSI][31] = 54,
- [1][1][2][0][RTW89_KCC][31] = 28,
- [1][1][2][0][RTW89_FCC][35] = 10,
- [1][1][2][0][RTW89_ETSI][35] = 54,
- [1][1][2][0][RTW89_KCC][35] = 28,
- [1][1][2][0][RTW89_FCC][39] = 10,
- [1][1][2][0][RTW89_ETSI][39] = 54,
- [1][1][2][0][RTW89_KCC][39] = 28,
- [1][1][2][0][RTW89_FCC][43] = 10,
- [1][1][2][0][RTW89_ETSI][43] = 54,
- [1][1][2][0][RTW89_KCC][43] = 28,
- [1][1][2][0][RTW89_FCC][46] = 12,
- [1][1][2][0][RTW89_ETSI][46] = 127,
- [1][1][2][0][RTW89_KCC][46] = 28,
- [1][1][2][0][RTW89_FCC][50] = 12,
- [1][1][2][0][RTW89_ETSI][50] = 127,
- [1][1][2][0][RTW89_KCC][50] = 28,
- [1][1][2][0][RTW89_FCC][54] = 10,
- [1][1][2][0][RTW89_ETSI][54] = 127,
- [1][1][2][0][RTW89_KCC][54] = 28,
- [1][1][2][0][RTW89_FCC][58] = 10,
- [1][1][2][0][RTW89_ETSI][58] = 127,
- [1][1][2][0][RTW89_KCC][58] = 28,
- [1][1][2][0][RTW89_FCC][61] = 10,
- [1][1][2][0][RTW89_ETSI][61] = 127,
- [1][1][2][0][RTW89_KCC][61] = 28,
- [1][1][2][0][RTW89_FCC][65] = 10,
- [1][1][2][0][RTW89_ETSI][65] = 127,
- [1][1][2][0][RTW89_KCC][65] = 28,
- [1][1][2][0][RTW89_FCC][69] = 10,
- [1][1][2][0][RTW89_ETSI][69] = 127,
- [1][1][2][0][RTW89_KCC][69] = 28,
- [1][1][2][0][RTW89_FCC][73] = 10,
- [1][1][2][0][RTW89_ETSI][73] = 127,
- [1][1][2][0][RTW89_KCC][73] = 28,
- [1][1][2][0][RTW89_FCC][76] = 10,
- [1][1][2][0][RTW89_ETSI][76] = 127,
- [1][1][2][0][RTW89_KCC][76] = 28,
- [1][1][2][0][RTW89_FCC][80] = 10,
- [1][1][2][0][RTW89_ETSI][80] = 127,
- [1][1][2][0][RTW89_KCC][80] = 32,
- [1][1][2][0][RTW89_FCC][84] = 10,
- [1][1][2][0][RTW89_ETSI][84] = 127,
- [1][1][2][0][RTW89_KCC][84] = 32,
- [1][1][2][0][RTW89_FCC][88] = 10,
- [1][1][2][0][RTW89_ETSI][88] = 127,
- [1][1][2][0][RTW89_KCC][88] = 32,
- [1][1][2][0][RTW89_FCC][91] = 12,
- [1][1][2][0][RTW89_ETSI][91] = 127,
- [1][1][2][0][RTW89_KCC][91] = 32,
- [1][1][2][0][RTW89_FCC][95] = 10,
- [1][1][2][0][RTW89_ETSI][95] = 127,
- [1][1][2][0][RTW89_KCC][95] = 32,
- [1][1][2][0][RTW89_FCC][99] = 10,
- [1][1][2][0][RTW89_ETSI][99] = 127,
- [1][1][2][0][RTW89_KCC][99] = 32,
- [1][1][2][0][RTW89_FCC][103] = 10,
- [1][1][2][0][RTW89_ETSI][103] = 127,
- [1][1][2][0][RTW89_KCC][103] = 32,
- [1][1][2][0][RTW89_FCC][106] = 12,
- [1][1][2][0][RTW89_ETSI][106] = 127,
- [1][1][2][0][RTW89_KCC][106] = 32,
- [1][1][2][0][RTW89_FCC][110] = 127,
- [1][1][2][0][RTW89_ETSI][110] = 127,
- [1][1][2][0][RTW89_KCC][110] = 127,
- [1][1][2][0][RTW89_FCC][114] = 127,
- [1][1][2][0][RTW89_ETSI][114] = 127,
- [1][1][2][0][RTW89_KCC][114] = 127,
- [1][1][2][0][RTW89_FCC][118] = 127,
- [1][1][2][0][RTW89_ETSI][118] = 127,
- [1][1][2][0][RTW89_KCC][118] = 127,
- [1][1][2][1][RTW89_FCC][1] = 10,
- [1][1][2][1][RTW89_ETSI][1] = 42,
- [1][1][2][1][RTW89_KCC][1] = 28,
- [1][1][2][1][RTW89_FCC][5] = 10,
- [1][1][2][1][RTW89_ETSI][5] = 42,
- [1][1][2][1][RTW89_KCC][5] = 28,
- [1][1][2][1][RTW89_FCC][9] = 10,
- [1][1][2][1][RTW89_ETSI][9] = 42,
- [1][1][2][1][RTW89_KCC][9] = 28,
- [1][1][2][1][RTW89_FCC][13] = 10,
- [1][1][2][1][RTW89_ETSI][13] = 42,
- [1][1][2][1][RTW89_KCC][13] = 28,
- [1][1][2][1][RTW89_FCC][16] = 10,
- [1][1][2][1][RTW89_ETSI][16] = 42,
- [1][1][2][1][RTW89_KCC][16] = 28,
- [1][1][2][1][RTW89_FCC][20] = 10,
- [1][1][2][1][RTW89_ETSI][20] = 42,
- [1][1][2][1][RTW89_KCC][20] = 28,
- [1][1][2][1][RTW89_FCC][24] = 10,
- [1][1][2][1][RTW89_ETSI][24] = 42,
- [1][1][2][1][RTW89_KCC][24] = 28,
- [1][1][2][1][RTW89_FCC][28] = 10,
- [1][1][2][1][RTW89_ETSI][28] = 42,
- [1][1][2][1][RTW89_KCC][28] = 28,
- [1][1][2][1][RTW89_FCC][31] = 10,
- [1][1][2][1][RTW89_ETSI][31] = 42,
- [1][1][2][1][RTW89_KCC][31] = 28,
- [1][1][2][1][RTW89_FCC][35] = 10,
- [1][1][2][1][RTW89_ETSI][35] = 42,
- [1][1][2][1][RTW89_KCC][35] = 28,
- [1][1][2][1][RTW89_FCC][39] = 10,
- [1][1][2][1][RTW89_ETSI][39] = 42,
- [1][1][2][1][RTW89_KCC][39] = 28,
- [1][1][2][1][RTW89_FCC][43] = 10,
- [1][1][2][1][RTW89_ETSI][43] = 42,
- [1][1][2][1][RTW89_KCC][43] = 28,
- [1][1][2][1][RTW89_FCC][46] = 12,
- [1][1][2][1][RTW89_ETSI][46] = 127,
- [1][1][2][1][RTW89_KCC][46] = 28,
- [1][1][2][1][RTW89_FCC][50] = 12,
- [1][1][2][1][RTW89_ETSI][50] = 127,
- [1][1][2][1][RTW89_KCC][50] = 28,
- [1][1][2][1][RTW89_FCC][54] = 10,
- [1][1][2][1][RTW89_ETSI][54] = 127,
- [1][1][2][1][RTW89_KCC][54] = 28,
- [1][1][2][1][RTW89_FCC][58] = 10,
- [1][1][2][1][RTW89_ETSI][58] = 127,
- [1][1][2][1][RTW89_KCC][58] = 28,
- [1][1][2][1][RTW89_FCC][61] = 10,
- [1][1][2][1][RTW89_ETSI][61] = 127,
- [1][1][2][1][RTW89_KCC][61] = 28,
- [1][1][2][1][RTW89_FCC][65] = 10,
- [1][1][2][1][RTW89_ETSI][65] = 127,
- [1][1][2][1][RTW89_KCC][65] = 28,
- [1][1][2][1][RTW89_FCC][69] = 10,
- [1][1][2][1][RTW89_ETSI][69] = 127,
- [1][1][2][1][RTW89_KCC][69] = 28,
- [1][1][2][1][RTW89_FCC][73] = 10,
- [1][1][2][1][RTW89_ETSI][73] = 127,
- [1][1][2][1][RTW89_KCC][73] = 28,
- [1][1][2][1][RTW89_FCC][76] = 10,
- [1][1][2][1][RTW89_ETSI][76] = 127,
- [1][1][2][1][RTW89_KCC][76] = 28,
- [1][1][2][1][RTW89_FCC][80] = 10,
- [1][1][2][1][RTW89_ETSI][80] = 127,
- [1][1][2][1][RTW89_KCC][80] = 32,
- [1][1][2][1][RTW89_FCC][84] = 10,
- [1][1][2][1][RTW89_ETSI][84] = 127,
- [1][1][2][1][RTW89_KCC][84] = 32,
- [1][1][2][1][RTW89_FCC][88] = 10,
- [1][1][2][1][RTW89_ETSI][88] = 127,
- [1][1][2][1][RTW89_KCC][88] = 32,
- [1][1][2][1][RTW89_FCC][91] = 12,
- [1][1][2][1][RTW89_ETSI][91] = 127,
- [1][1][2][1][RTW89_KCC][91] = 32,
- [1][1][2][1][RTW89_FCC][95] = 10,
- [1][1][2][1][RTW89_ETSI][95] = 127,
- [1][1][2][1][RTW89_KCC][95] = 32,
- [1][1][2][1][RTW89_FCC][99] = 10,
- [1][1][2][1][RTW89_ETSI][99] = 127,
- [1][1][2][1][RTW89_KCC][99] = 32,
- [1][1][2][1][RTW89_FCC][103] = 10,
- [1][1][2][1][RTW89_ETSI][103] = 127,
- [1][1][2][1][RTW89_KCC][103] = 32,
- [1][1][2][1][RTW89_FCC][106] = 12,
- [1][1][2][1][RTW89_ETSI][106] = 127,
- [1][1][2][1][RTW89_KCC][106] = 32,
- [1][1][2][1][RTW89_FCC][110] = 127,
- [1][1][2][1][RTW89_ETSI][110] = 127,
- [1][1][2][1][RTW89_KCC][110] = 127,
- [1][1][2][1][RTW89_FCC][114] = 127,
- [1][1][2][1][RTW89_ETSI][114] = 127,
- [1][1][2][1][RTW89_KCC][114] = 127,
- [1][1][2][1][RTW89_FCC][118] = 127,
- [1][1][2][1][RTW89_ETSI][118] = 127,
- [1][1][2][1][RTW89_KCC][118] = 127,
- [2][0][2][0][RTW89_FCC][3] = 46,
- [2][0][2][0][RTW89_ETSI][3] = 48,
- [2][0][2][0][RTW89_KCC][3] = 50,
- [2][0][2][0][RTW89_FCC][11] = 46,
- [2][0][2][0][RTW89_ETSI][11] = 48,
- [2][0][2][0][RTW89_KCC][11] = 50,
- [2][0][2][0][RTW89_FCC][18] = 46,
- [2][0][2][0][RTW89_ETSI][18] = 48,
- [2][0][2][0][RTW89_KCC][18] = 50,
- [2][0][2][0][RTW89_FCC][26] = 46,
- [2][0][2][0][RTW89_ETSI][26] = 48,
- [2][0][2][0][RTW89_KCC][26] = 50,
- [2][0][2][0][RTW89_FCC][33] = 46,
- [2][0][2][0][RTW89_ETSI][33] = 48,
- [2][0][2][0][RTW89_KCC][33] = 50,
- [2][0][2][0][RTW89_FCC][41] = 46,
- [2][0][2][0][RTW89_ETSI][41] = 48,
- [2][0][2][0][RTW89_KCC][41] = 50,
- [2][0][2][0][RTW89_FCC][48] = 46,
- [2][0][2][0][RTW89_ETSI][48] = 127,
- [2][0][2][0][RTW89_KCC][48] = 48,
- [2][0][2][0][RTW89_FCC][56] = 46,
- [2][0][2][0][RTW89_ETSI][56] = 127,
- [2][0][2][0][RTW89_KCC][56] = 48,
- [2][0][2][0][RTW89_FCC][63] = 46,
- [2][0][2][0][RTW89_ETSI][63] = 127,
- [2][0][2][0][RTW89_KCC][63] = 48,
- [2][0][2][0][RTW89_FCC][71] = 46,
- [2][0][2][0][RTW89_ETSI][71] = 127,
- [2][0][2][0][RTW89_KCC][71] = 48,
- [2][0][2][0][RTW89_FCC][78] = 46,
- [2][0][2][0][RTW89_ETSI][78] = 127,
- [2][0][2][0][RTW89_KCC][78] = 52,
- [2][0][2][0][RTW89_FCC][86] = 46,
- [2][0][2][0][RTW89_ETSI][86] = 127,
- [2][0][2][0][RTW89_KCC][86] = 52,
- [2][0][2][0][RTW89_FCC][93] = 46,
- [2][0][2][0][RTW89_ETSI][93] = 127,
- [2][0][2][0][RTW89_KCC][93] = 50,
- [2][0][2][0][RTW89_FCC][101] = 44,
- [2][0][2][0][RTW89_ETSI][101] = 127,
- [2][0][2][0][RTW89_KCC][101] = 50,
- [2][0][2][0][RTW89_FCC][108] = 127,
- [2][0][2][0][RTW89_ETSI][108] = 127,
- [2][0][2][0][RTW89_KCC][108] = 127,
- [2][0][2][0][RTW89_FCC][116] = 127,
- [2][0][2][0][RTW89_ETSI][116] = 127,
- [2][0][2][0][RTW89_KCC][116] = 127,
- [2][1][2][0][RTW89_FCC][3] = 22,
- [2][1][2][0][RTW89_ETSI][3] = 48,
- [2][1][2][0][RTW89_KCC][3] = 38,
- [2][1][2][0][RTW89_FCC][11] = 20,
- [2][1][2][0][RTW89_ETSI][11] = 48,
- [2][1][2][0][RTW89_KCC][11] = 38,
- [2][1][2][0][RTW89_FCC][18] = 20,
- [2][1][2][0][RTW89_ETSI][18] = 48,
- [2][1][2][0][RTW89_KCC][18] = 38,
- [2][1][2][0][RTW89_FCC][26] = 20,
- [2][1][2][0][RTW89_ETSI][26] = 48,
- [2][1][2][0][RTW89_KCC][26] = 38,
- [2][1][2][0][RTW89_FCC][33] = 20,
- [2][1][2][0][RTW89_ETSI][33] = 48,
- [2][1][2][0][RTW89_KCC][33] = 38,
- [2][1][2][0][RTW89_FCC][41] = 22,
- [2][1][2][0][RTW89_ETSI][41] = 48,
- [2][1][2][0][RTW89_KCC][41] = 38,
- [2][1][2][0][RTW89_FCC][48] = 22,
- [2][1][2][0][RTW89_ETSI][48] = 127,
- [2][1][2][0][RTW89_KCC][48] = 38,
- [2][1][2][0][RTW89_FCC][56] = 20,
- [2][1][2][0][RTW89_ETSI][56] = 127,
- [2][1][2][0][RTW89_KCC][56] = 38,
- [2][1][2][0][RTW89_FCC][63] = 22,
- [2][1][2][0][RTW89_ETSI][63] = 127,
- [2][1][2][0][RTW89_KCC][63] = 38,
- [2][1][2][0][RTW89_FCC][71] = 20,
- [2][1][2][0][RTW89_ETSI][71] = 127,
- [2][1][2][0][RTW89_KCC][71] = 38,
- [2][1][2][0][RTW89_FCC][78] = 20,
- [2][1][2][0][RTW89_ETSI][78] = 127,
- [2][1][2][0][RTW89_KCC][78] = 38,
- [2][1][2][0][RTW89_FCC][86] = 20,
- [2][1][2][0][RTW89_ETSI][86] = 127,
- [2][1][2][0][RTW89_KCC][86] = 38,
- [2][1][2][0][RTW89_FCC][93] = 22,
- [2][1][2][0][RTW89_ETSI][93] = 127,
- [2][1][2][0][RTW89_KCC][93] = 38,
- [2][1][2][0][RTW89_FCC][101] = 22,
- [2][1][2][0][RTW89_ETSI][101] = 127,
- [2][1][2][0][RTW89_KCC][101] = 38,
- [2][1][2][0][RTW89_FCC][108] = 127,
- [2][1][2][0][RTW89_ETSI][108] = 127,
- [2][1][2][0][RTW89_KCC][108] = 127,
- [2][1][2][0][RTW89_FCC][116] = 127,
- [2][1][2][0][RTW89_ETSI][116] = 127,
- [2][1][2][0][RTW89_KCC][116] = 127,
- [2][1][2][1][RTW89_FCC][3] = 22,
- [2][1][2][1][RTW89_ETSI][3] = 42,
- [2][1][2][1][RTW89_KCC][3] = 38,
- [2][1][2][1][RTW89_FCC][11] = 20,
- [2][1][2][1][RTW89_ETSI][11] = 42,
- [2][1][2][1][RTW89_KCC][11] = 38,
- [2][1][2][1][RTW89_FCC][18] = 20,
- [2][1][2][1][RTW89_ETSI][18] = 42,
- [2][1][2][1][RTW89_KCC][18] = 38,
- [2][1][2][1][RTW89_FCC][26] = 20,
- [2][1][2][1][RTW89_ETSI][26] = 42,
- [2][1][2][1][RTW89_KCC][26] = 38,
- [2][1][2][1][RTW89_FCC][33] = 20,
- [2][1][2][1][RTW89_ETSI][33] = 42,
- [2][1][2][1][RTW89_KCC][33] = 38,
- [2][1][2][1][RTW89_FCC][41] = 22,
- [2][1][2][1][RTW89_ETSI][41] = 42,
- [2][1][2][1][RTW89_KCC][41] = 38,
- [2][1][2][1][RTW89_FCC][48] = 22,
- [2][1][2][1][RTW89_ETSI][48] = 127,
- [2][1][2][1][RTW89_KCC][48] = 38,
- [2][1][2][1][RTW89_FCC][56] = 20,
- [2][1][2][1][RTW89_ETSI][56] = 127,
- [2][1][2][1][RTW89_KCC][56] = 38,
- [2][1][2][1][RTW89_FCC][63] = 22,
- [2][1][2][1][RTW89_ETSI][63] = 127,
- [2][1][2][1][RTW89_KCC][63] = 38,
- [2][1][2][1][RTW89_FCC][71] = 20,
- [2][1][2][1][RTW89_ETSI][71] = 127,
- [2][1][2][1][RTW89_KCC][71] = 38,
- [2][1][2][1][RTW89_FCC][78] = 20,
- [2][1][2][1][RTW89_ETSI][78] = 127,
- [2][1][2][1][RTW89_KCC][78] = 38,
- [2][1][2][1][RTW89_FCC][86] = 20,
- [2][1][2][1][RTW89_ETSI][86] = 127,
- [2][1][2][1][RTW89_KCC][86] = 38,
- [2][1][2][1][RTW89_FCC][93] = 22,
- [2][1][2][1][RTW89_ETSI][93] = 127,
- [2][1][2][1][RTW89_KCC][93] = 38,
- [2][1][2][1][RTW89_FCC][101] = 22,
- [2][1][2][1][RTW89_ETSI][101] = 127,
- [2][1][2][1][RTW89_KCC][101] = 38,
- [2][1][2][1][RTW89_FCC][108] = 127,
- [2][1][2][1][RTW89_ETSI][108] = 127,
- [2][1][2][1][RTW89_KCC][108] = 127,
- [2][1][2][1][RTW89_FCC][116] = 127,
- [2][1][2][1][RTW89_ETSI][116] = 127,
- [2][1][2][1][RTW89_KCC][116] = 127,
- [3][0][2][0][RTW89_FCC][7] = 52,
- [3][0][2][0][RTW89_ETSI][7] = 38,
- [3][0][2][0][RTW89_KCC][7] = 42,
- [3][0][2][0][RTW89_FCC][22] = 52,
- [3][0][2][0][RTW89_ETSI][22] = 38,
- [3][0][2][0][RTW89_KCC][22] = 42,
- [3][0][2][0][RTW89_FCC][37] = 52,
- [3][0][2][0][RTW89_ETSI][37] = 38,
- [3][0][2][0][RTW89_KCC][37] = 42,
- [3][0][2][0][RTW89_FCC][52] = 54,
- [3][0][2][0][RTW89_ETSI][52] = 127,
- [3][0][2][0][RTW89_KCC][52] = 56,
- [3][0][2][0][RTW89_FCC][67] = 54,
- [3][0][2][0][RTW89_ETSI][67] = 127,
- [3][0][2][0][RTW89_KCC][67] = 54,
- [3][0][2][0][RTW89_FCC][82] = 54,
- [3][0][2][0][RTW89_ETSI][82] = 127,
- [3][0][2][0][RTW89_KCC][82] = 26,
- [3][0][2][0][RTW89_FCC][97] = 40,
- [3][0][2][0][RTW89_ETSI][97] = 127,
- [3][0][2][0][RTW89_KCC][97] = 26,
- [3][0][2][0][RTW89_FCC][112] = 127,
- [3][0][2][0][RTW89_ETSI][112] = 127,
- [3][0][2][0][RTW89_KCC][112] = 127,
- [3][1][2][0][RTW89_FCC][7] = 32,
- [3][1][2][0][RTW89_ETSI][7] = 38,
- [3][1][2][0][RTW89_KCC][7] = 40,
- [3][1][2][0][RTW89_FCC][22] = 30,
- [3][1][2][0][RTW89_ETSI][22] = 38,
- [3][1][2][0][RTW89_KCC][22] = 40,
- [3][1][2][0][RTW89_FCC][37] = 30,
- [3][1][2][0][RTW89_ETSI][37] = 38,
- [3][1][2][0][RTW89_KCC][37] = 40,
- [3][1][2][0][RTW89_FCC][52] = 30,
- [3][1][2][0][RTW89_ETSI][52] = 127,
- [3][1][2][0][RTW89_KCC][52] = 48,
- [3][1][2][0][RTW89_FCC][67] = 32,
- [3][1][2][0][RTW89_ETSI][67] = 127,
- [3][1][2][0][RTW89_KCC][67] = 48,
- [3][1][2][0][RTW89_FCC][82] = 32,
- [3][1][2][0][RTW89_ETSI][82] = 127,
- [3][1][2][0][RTW89_KCC][82] = 24,
- [3][1][2][0][RTW89_FCC][97] = 14,
- [3][1][2][0][RTW89_ETSI][97] = 127,
- [3][1][2][0][RTW89_KCC][97] = 24,
- [3][1][2][0][RTW89_FCC][112] = 127,
- [3][1][2][0][RTW89_ETSI][112] = 127,
- [3][1][2][0][RTW89_KCC][112] = 127,
- [3][1][2][1][RTW89_FCC][7] = 32,
- [3][1][2][1][RTW89_ETSI][7] = 38,
- [3][1][2][1][RTW89_KCC][7] = 40,
- [3][1][2][1][RTW89_FCC][22] = 30,
- [3][1][2][1][RTW89_ETSI][22] = 38,
- [3][1][2][1][RTW89_KCC][22] = 40,
- [3][1][2][1][RTW89_FCC][37] = 30,
- [3][1][2][1][RTW89_ETSI][37] = 38,
- [3][1][2][1][RTW89_KCC][37] = 40,
- [3][1][2][1][RTW89_FCC][52] = 30,
- [3][1][2][1][RTW89_ETSI][52] = 127,
- [3][1][2][1][RTW89_KCC][52] = 48,
- [3][1][2][1][RTW89_FCC][67] = 32,
- [3][1][2][1][RTW89_ETSI][67] = 127,
- [3][1][2][1][RTW89_KCC][67] = 48,
- [3][1][2][1][RTW89_FCC][82] = 32,
- [3][1][2][1][RTW89_ETSI][82] = 127,
- [3][1][2][1][RTW89_KCC][82] = 24,
- [3][1][2][1][RTW89_FCC][97] = 14,
- [3][1][2][1][RTW89_ETSI][97] = 127,
- [3][1][2][1][RTW89_KCC][97] = 24,
- [3][1][2][1][RTW89_FCC][112] = 127,
- [3][1][2][1][RTW89_ETSI][112] = 127,
- [3][1][2][1][RTW89_KCC][112] = 127,
+ [RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER]
+ [RTW89_6G_CH_NUM] = {
+ [0][0][1][0][RTW89_WW][0][0] = 24,
+ [0][0][1][0][RTW89_WW][1][0] = 24,
+ [0][0][1][0][RTW89_WW][2][0] = 56,
+ [0][0][1][0][RTW89_WW][0][2] = 22,
+ [0][0][1][0][RTW89_WW][1][2] = 22,
+ [0][0][1][0][RTW89_WW][2][2] = 56,
+ [0][0][1][0][RTW89_WW][0][4] = 22,
+ [0][0][1][0][RTW89_WW][1][4] = 22,
+ [0][0][1][0][RTW89_WW][2][4] = 56,
+ [0][0][1][0][RTW89_WW][0][6] = 22,
+ [0][0][1][0][RTW89_WW][1][6] = 22,
+ [0][0][1][0][RTW89_WW][2][6] = 56,
+ [0][0][1][0][RTW89_WW][0][8] = 22,
+ [0][0][1][0][RTW89_WW][1][8] = 22,
+ [0][0][1][0][RTW89_WW][2][8] = 56,
+ [0][0][1][0][RTW89_WW][0][10] = 22,
+ [0][0][1][0][RTW89_WW][1][10] = 22,
+ [0][0][1][0][RTW89_WW][2][10] = 56,
+ [0][0][1][0][RTW89_WW][0][12] = 22,
+ [0][0][1][0][RTW89_WW][1][12] = 22,
+ [0][0][1][0][RTW89_WW][2][12] = 56,
+ [0][0][1][0][RTW89_WW][0][14] = 22,
+ [0][0][1][0][RTW89_WW][1][14] = 22,
+ [0][0][1][0][RTW89_WW][2][14] = 56,
+ [0][0][1][0][RTW89_WW][0][15] = 22,
+ [0][0][1][0][RTW89_WW][1][15] = 22,
+ [0][0][1][0][RTW89_WW][2][15] = 56,
+ [0][0][1][0][RTW89_WW][0][17] = 22,
+ [0][0][1][0][RTW89_WW][1][17] = 22,
+ [0][0][1][0][RTW89_WW][2][17] = 56,
+ [0][0][1][0][RTW89_WW][0][19] = 22,
+ [0][0][1][0][RTW89_WW][1][19] = 22,
+ [0][0][1][0][RTW89_WW][2][19] = 56,
+ [0][0][1][0][RTW89_WW][0][21] = 22,
+ [0][0][1][0][RTW89_WW][1][21] = 22,
+ [0][0][1][0][RTW89_WW][2][21] = 56,
+ [0][0][1][0][RTW89_WW][0][23] = 22,
+ [0][0][1][0][RTW89_WW][1][23] = 22,
+ [0][0][1][0][RTW89_WW][2][23] = 70,
+ [0][0][1][0][RTW89_WW][0][25] = 22,
+ [0][0][1][0][RTW89_WW][1][25] = 22,
+ [0][0][1][0][RTW89_WW][2][25] = 70,
+ [0][0][1][0][RTW89_WW][0][27] = 22,
+ [0][0][1][0][RTW89_WW][1][27] = 22,
+ [0][0][1][0][RTW89_WW][2][27] = 70,
+ [0][0][1][0][RTW89_WW][0][29] = 22,
+ [0][0][1][0][RTW89_WW][1][29] = 22,
+ [0][0][1][0][RTW89_WW][2][29] = 70,
+ [0][0][1][0][RTW89_WW][0][30] = 22,
+ [0][0][1][0][RTW89_WW][1][30] = 22,
+ [0][0][1][0][RTW89_WW][2][30] = 70,
+ [0][0][1][0][RTW89_WW][0][32] = 22,
+ [0][0][1][0][RTW89_WW][1][32] = 22,
+ [0][0][1][0][RTW89_WW][2][32] = 70,
+ [0][0][1][0][RTW89_WW][0][34] = 22,
+ [0][0][1][0][RTW89_WW][1][34] = 22,
+ [0][0][1][0][RTW89_WW][2][34] = 70,
+ [0][0][1][0][RTW89_WW][0][36] = 22,
+ [0][0][1][0][RTW89_WW][1][36] = 22,
+ [0][0][1][0][RTW89_WW][2][36] = 70,
+ [0][0][1][0][RTW89_WW][0][38] = 22,
+ [0][0][1][0][RTW89_WW][1][38] = 22,
+ [0][0][1][0][RTW89_WW][2][38] = 70,
+ [0][0][1][0][RTW89_WW][0][40] = 22,
+ [0][0][1][0][RTW89_WW][1][40] = 22,
+ [0][0][1][0][RTW89_WW][2][40] = 70,
+ [0][0][1][0][RTW89_WW][0][42] = 22,
+ [0][0][1][0][RTW89_WW][1][42] = 22,
+ [0][0][1][0][RTW89_WW][2][42] = 70,
+ [0][0][1][0][RTW89_WW][0][44] = 22,
+ [0][0][1][0][RTW89_WW][1][44] = 22,
+ [0][0][1][0][RTW89_WW][2][44] = 70,
+ [0][0][1][0][RTW89_WW][0][45] = 22,
+ [0][0][1][0][RTW89_WW][1][45] = 22,
+ [0][0][1][0][RTW89_WW][2][45] = 0,
+ [0][0][1][0][RTW89_WW][0][47] = 22,
+ [0][0][1][0][RTW89_WW][1][47] = 22,
+ [0][0][1][0][RTW89_WW][2][47] = 0,
+ [0][0][1][0][RTW89_WW][0][49] = 24,
+ [0][0][1][0][RTW89_WW][1][49] = 24,
+ [0][0][1][0][RTW89_WW][2][49] = 0,
+ [0][0][1][0][RTW89_WW][0][51] = 22,
+ [0][0][1][0][RTW89_WW][1][51] = 22,
+ [0][0][1][0][RTW89_WW][2][51] = 0,
+ [0][0][1][0][RTW89_WW][0][53] = 22,
+ [0][0][1][0][RTW89_WW][1][53] = 22,
+ [0][0][1][0][RTW89_WW][2][53] = 0,
+ [0][0][1][0][RTW89_WW][0][55] = 22,
+ [0][0][1][0][RTW89_WW][1][55] = 22,
+ [0][0][1][0][RTW89_WW][2][55] = 68,
+ [0][0][1][0][RTW89_WW][0][57] = 22,
+ [0][0][1][0][RTW89_WW][1][57] = 22,
+ [0][0][1][0][RTW89_WW][2][57] = 68,
+ [0][0][1][0][RTW89_WW][0][59] = 22,
+ [0][0][1][0][RTW89_WW][1][59] = 22,
+ [0][0][1][0][RTW89_WW][2][59] = 68,
+ [0][0][1][0][RTW89_WW][0][60] = 22,
+ [0][0][1][0][RTW89_WW][1][60] = 22,
+ [0][0][1][0][RTW89_WW][2][60] = 68,
+ [0][0][1][0][RTW89_WW][0][62] = 22,
+ [0][0][1][0][RTW89_WW][1][62] = 22,
+ [0][0][1][0][RTW89_WW][2][62] = 68,
+ [0][0][1][0][RTW89_WW][0][64] = 22,
+ [0][0][1][0][RTW89_WW][1][64] = 22,
+ [0][0][1][0][RTW89_WW][2][64] = 68,
+ [0][0][1][0][RTW89_WW][0][66] = 22,
+ [0][0][1][0][RTW89_WW][1][66] = 22,
+ [0][0][1][0][RTW89_WW][2][66] = 68,
+ [0][0][1][0][RTW89_WW][0][68] = 22,
+ [0][0][1][0][RTW89_WW][1][68] = 22,
+ [0][0][1][0][RTW89_WW][2][68] = 68,
+ [0][0][1][0][RTW89_WW][0][70] = 24,
+ [0][0][1][0][RTW89_WW][1][70] = 24,
+ [0][0][1][0][RTW89_WW][2][70] = 68,
+ [0][0][1][0][RTW89_WW][0][72] = 22,
+ [0][0][1][0][RTW89_WW][1][72] = 22,
+ [0][0][1][0][RTW89_WW][2][72] = 68,
+ [0][0][1][0][RTW89_WW][0][74] = 22,
+ [0][0][1][0][RTW89_WW][1][74] = 22,
+ [0][0][1][0][RTW89_WW][2][74] = 68,
+ [0][0][1][0][RTW89_WW][0][75] = 22,
+ [0][0][1][0][RTW89_WW][1][75] = 22,
+ [0][0][1][0][RTW89_WW][2][75] = 68,
+ [0][0][1][0][RTW89_WW][0][77] = 22,
+ [0][0][1][0][RTW89_WW][1][77] = 22,
+ [0][0][1][0][RTW89_WW][2][77] = 68,
+ [0][0][1][0][RTW89_WW][0][79] = 22,
+ [0][0][1][0][RTW89_WW][1][79] = 22,
+ [0][0][1][0][RTW89_WW][2][79] = 68,
+ [0][0][1][0][RTW89_WW][0][81] = 22,
+ [0][0][1][0][RTW89_WW][1][81] = 22,
+ [0][0][1][0][RTW89_WW][2][81] = 68,
+ [0][0][1][0][RTW89_WW][0][83] = 22,
+ [0][0][1][0][RTW89_WW][1][83] = 22,
+ [0][0][1][0][RTW89_WW][2][83] = 68,
+ [0][0][1][0][RTW89_WW][0][85] = 22,
+ [0][0][1][0][RTW89_WW][1][85] = 22,
+ [0][0][1][0][RTW89_WW][2][85] = 68,
+ [0][0][1][0][RTW89_WW][0][87] = 22,
+ [0][0][1][0][RTW89_WW][1][87] = 22,
+ [0][0][1][0][RTW89_WW][2][87] = 0,
+ [0][0][1][0][RTW89_WW][0][89] = 22,
+ [0][0][1][0][RTW89_WW][1][89] = 22,
+ [0][0][1][0][RTW89_WW][2][89] = 0,
+ [0][0][1][0][RTW89_WW][0][90] = 22,
+ [0][0][1][0][RTW89_WW][1][90] = 22,
+ [0][0][1][0][RTW89_WW][2][90] = 0,
+ [0][0][1][0][RTW89_WW][0][92] = 22,
+ [0][0][1][0][RTW89_WW][1][92] = 22,
+ [0][0][1][0][RTW89_WW][2][92] = 0,
+ [0][0][1][0][RTW89_WW][0][94] = 22,
+ [0][0][1][0][RTW89_WW][1][94] = 22,
+ [0][0][1][0][RTW89_WW][2][94] = 0,
+ [0][0][1][0][RTW89_WW][0][96] = 22,
+ [0][0][1][0][RTW89_WW][1][96] = 22,
+ [0][0][1][0][RTW89_WW][2][96] = 0,
+ [0][0][1][0][RTW89_WW][0][98] = 22,
+ [0][0][1][0][RTW89_WW][1][98] = 22,
+ [0][0][1][0][RTW89_WW][2][98] = 0,
+ [0][0][1][0][RTW89_WW][0][100] = 22,
+ [0][0][1][0][RTW89_WW][1][100] = 22,
+ [0][0][1][0][RTW89_WW][2][100] = 0,
+ [0][0][1][0][RTW89_WW][0][102] = 22,
+ [0][0][1][0][RTW89_WW][1][102] = 22,
+ [0][0][1][0][RTW89_WW][2][102] = 0,
+ [0][0][1][0][RTW89_WW][0][104] = 22,
+ [0][0][1][0][RTW89_WW][1][104] = 22,
+ [0][0][1][0][RTW89_WW][2][104] = 0,
+ [0][0][1][0][RTW89_WW][0][105] = 22,
+ [0][0][1][0][RTW89_WW][1][105] = 22,
+ [0][0][1][0][RTW89_WW][2][105] = 0,
+ [0][0][1][0][RTW89_WW][0][107] = 24,
+ [0][0][1][0][RTW89_WW][1][107] = 24,
+ [0][0][1][0][RTW89_WW][2][107] = 0,
+ [0][0][1][0][RTW89_WW][0][109] = 24,
+ [0][0][1][0][RTW89_WW][1][109] = 24,
+ [0][0][1][0][RTW89_WW][2][109] = 0,
+ [0][0][1][0][RTW89_WW][0][111] = 0,
+ [0][0][1][0][RTW89_WW][1][111] = 0,
+ [0][0][1][0][RTW89_WW][2][111] = 0,
+ [0][0][1][0][RTW89_WW][0][113] = 0,
+ [0][0][1][0][RTW89_WW][1][113] = 0,
+ [0][0][1][0][RTW89_WW][2][113] = 0,
+ [0][0][1][0][RTW89_WW][0][115] = 0,
+ [0][0][1][0][RTW89_WW][1][115] = 0,
+ [0][0][1][0][RTW89_WW][2][115] = 0,
+ [0][0][1][0][RTW89_WW][0][117] = 0,
+ [0][0][1][0][RTW89_WW][1][117] = 0,
+ [0][0][1][0][RTW89_WW][2][117] = 0,
+ [0][0][1][0][RTW89_WW][0][119] = 0,
+ [0][0][1][0][RTW89_WW][1][119] = 0,
+ [0][0][1][0][RTW89_WW][2][119] = 0,
+ [0][1][1][0][RTW89_WW][0][0] = -2,
+ [0][1][1][0][RTW89_WW][1][0] = -2,
+ [0][1][1][0][RTW89_WW][2][0] = 54,
+ [0][1][1][0][RTW89_WW][0][2] = -4,
+ [0][1][1][0][RTW89_WW][1][2] = -4,
+ [0][1][1][0][RTW89_WW][2][2] = 54,
+ [0][1][1][0][RTW89_WW][0][4] = -4,
+ [0][1][1][0][RTW89_WW][1][4] = -4,
+ [0][1][1][0][RTW89_WW][2][4] = 54,
+ [0][1][1][0][RTW89_WW][0][6] = -4,
+ [0][1][1][0][RTW89_WW][1][6] = -4,
+ [0][1][1][0][RTW89_WW][2][6] = 54,
+ [0][1][1][0][RTW89_WW][0][8] = -4,
+ [0][1][1][0][RTW89_WW][1][8] = -4,
+ [0][1][1][0][RTW89_WW][2][8] = 54,
+ [0][1][1][0][RTW89_WW][0][10] = -4,
+ [0][1][1][0][RTW89_WW][1][10] = -4,
+ [0][1][1][0][RTW89_WW][2][10] = 54,
+ [0][1][1][0][RTW89_WW][0][12] = -4,
+ [0][1][1][0][RTW89_WW][1][12] = -4,
+ [0][1][1][0][RTW89_WW][2][12] = 54,
+ [0][1][1][0][RTW89_WW][0][14] = -4,
+ [0][1][1][0][RTW89_WW][1][14] = -4,
+ [0][1][1][0][RTW89_WW][2][14] = 54,
+ [0][1][1][0][RTW89_WW][0][15] = -4,
+ [0][1][1][0][RTW89_WW][1][15] = -4,
+ [0][1][1][0][RTW89_WW][2][15] = 54,
+ [0][1][1][0][RTW89_WW][0][17] = -4,
+ [0][1][1][0][RTW89_WW][1][17] = -4,
+ [0][1][1][0][RTW89_WW][2][17] = 54,
+ [0][1][1][0][RTW89_WW][0][19] = -4,
+ [0][1][1][0][RTW89_WW][1][19] = -4,
+ [0][1][1][0][RTW89_WW][2][19] = 54,
+ [0][1][1][0][RTW89_WW][0][21] = -4,
+ [0][1][1][0][RTW89_WW][1][21] = -4,
+ [0][1][1][0][RTW89_WW][2][21] = 54,
+ [0][1][1][0][RTW89_WW][0][23] = -4,
+ [0][1][1][0][RTW89_WW][1][23] = -4,
+ [0][1][1][0][RTW89_WW][2][23] = 68,
+ [0][1][1][0][RTW89_WW][0][25] = -4,
+ [0][1][1][0][RTW89_WW][1][25] = -4,
+ [0][1][1][0][RTW89_WW][2][25] = 68,
+ [0][1][1][0][RTW89_WW][0][27] = -4,
+ [0][1][1][0][RTW89_WW][1][27] = -4,
+ [0][1][1][0][RTW89_WW][2][27] = 68,
+ [0][1][1][0][RTW89_WW][0][29] = -4,
+ [0][1][1][0][RTW89_WW][1][29] = -4,
+ [0][1][1][0][RTW89_WW][2][29] = 68,
+ [0][1][1][0][RTW89_WW][0][30] = -4,
+ [0][1][1][0][RTW89_WW][1][30] = -4,
+ [0][1][1][0][RTW89_WW][2][30] = 68,
+ [0][1][1][0][RTW89_WW][0][32] = -4,
+ [0][1][1][0][RTW89_WW][1][32] = -4,
+ [0][1][1][0][RTW89_WW][2][32] = 68,
+ [0][1][1][0][RTW89_WW][0][34] = -4,
+ [0][1][1][0][RTW89_WW][1][34] = -4,
+ [0][1][1][0][RTW89_WW][2][34] = 68,
+ [0][1][1][0][RTW89_WW][0][36] = -4,
+ [0][1][1][0][RTW89_WW][1][36] = -4,
+ [0][1][1][0][RTW89_WW][2][36] = 68,
+ [0][1][1][0][RTW89_WW][0][38] = -4,
+ [0][1][1][0][RTW89_WW][1][38] = -4,
+ [0][1][1][0][RTW89_WW][2][38] = 68,
+ [0][1][1][0][RTW89_WW][0][40] = -4,
+ [0][1][1][0][RTW89_WW][1][40] = -4,
+ [0][1][1][0][RTW89_WW][2][40] = 68,
+ [0][1][1][0][RTW89_WW][0][42] = -4,
+ [0][1][1][0][RTW89_WW][1][42] = -4,
+ [0][1][1][0][RTW89_WW][2][42] = 68,
+ [0][1][1][0][RTW89_WW][0][44] = -2,
+ [0][1][1][0][RTW89_WW][1][44] = -2,
+ [0][1][1][0][RTW89_WW][2][44] = 68,
+ [0][1][1][0][RTW89_WW][0][45] = -2,
+ [0][1][1][0][RTW89_WW][1][45] = -2,
+ [0][1][1][0][RTW89_WW][2][45] = 0,
+ [0][1][1][0][RTW89_WW][0][47] = -2,
+ [0][1][1][0][RTW89_WW][1][47] = -2,
+ [0][1][1][0][RTW89_WW][2][47] = 0,
+ [0][1][1][0][RTW89_WW][0][49] = -2,
+ [0][1][1][0][RTW89_WW][1][49] = -2,
+ [0][1][1][0][RTW89_WW][2][49] = 0,
+ [0][1][1][0][RTW89_WW][0][51] = -2,
+ [0][1][1][0][RTW89_WW][1][51] = -2,
+ [0][1][1][0][RTW89_WW][2][51] = 0,
+ [0][1][1][0][RTW89_WW][0][53] = -2,
+ [0][1][1][0][RTW89_WW][1][53] = -2,
+ [0][1][1][0][RTW89_WW][2][53] = 0,
+ [0][1][1][0][RTW89_WW][0][55] = -2,
+ [0][1][1][0][RTW89_WW][1][55] = -2,
+ [0][1][1][0][RTW89_WW][2][55] = 68,
+ [0][1][1][0][RTW89_WW][0][57] = -2,
+ [0][1][1][0][RTW89_WW][1][57] = -2,
+ [0][1][1][0][RTW89_WW][2][57] = 68,
+ [0][1][1][0][RTW89_WW][0][59] = -2,
+ [0][1][1][0][RTW89_WW][1][59] = -2,
+ [0][1][1][0][RTW89_WW][2][59] = 68,
+ [0][1][1][0][RTW89_WW][0][60] = -2,
+ [0][1][1][0][RTW89_WW][1][60] = -2,
+ [0][1][1][0][RTW89_WW][2][60] = 68,
+ [0][1][1][0][RTW89_WW][0][62] = -2,
+ [0][1][1][0][RTW89_WW][1][62] = -2,
+ [0][1][1][0][RTW89_WW][2][62] = 68,
+ [0][1][1][0][RTW89_WW][0][64] = -2,
+ [0][1][1][0][RTW89_WW][1][64] = -2,
+ [0][1][1][0][RTW89_WW][2][64] = 68,
+ [0][1][1][0][RTW89_WW][0][66] = -2,
+ [0][1][1][0][RTW89_WW][1][66] = -2,
+ [0][1][1][0][RTW89_WW][2][66] = 68,
+ [0][1][1][0][RTW89_WW][0][68] = -2,
+ [0][1][1][0][RTW89_WW][1][68] = -2,
+ [0][1][1][0][RTW89_WW][2][68] = 68,
+ [0][1][1][0][RTW89_WW][0][70] = -2,
+ [0][1][1][0][RTW89_WW][1][70] = -2,
+ [0][1][1][0][RTW89_WW][2][70] = 68,
+ [0][1][1][0][RTW89_WW][0][72] = -2,
+ [0][1][1][0][RTW89_WW][1][72] = -2,
+ [0][1][1][0][RTW89_WW][2][72] = 68,
+ [0][1][1][0][RTW89_WW][0][74] = -2,
+ [0][1][1][0][RTW89_WW][1][74] = -2,
+ [0][1][1][0][RTW89_WW][2][74] = 68,
+ [0][1][1][0][RTW89_WW][0][75] = -2,
+ [0][1][1][0][RTW89_WW][1][75] = -2,
+ [0][1][1][0][RTW89_WW][2][75] = 68,
+ [0][1][1][0][RTW89_WW][0][77] = -2,
+ [0][1][1][0][RTW89_WW][1][77] = -2,
+ [0][1][1][0][RTW89_WW][2][77] = 68,
+ [0][1][1][0][RTW89_WW][0][79] = -2,
+ [0][1][1][0][RTW89_WW][1][79] = -2,
+ [0][1][1][0][RTW89_WW][2][79] = 68,
+ [0][1][1][0][RTW89_WW][0][81] = -2,
+ [0][1][1][0][RTW89_WW][1][81] = -2,
+ [0][1][1][0][RTW89_WW][2][81] = 68,
+ [0][1][1][0][RTW89_WW][0][83] = -2,
+ [0][1][1][0][RTW89_WW][1][83] = -2,
+ [0][1][1][0][RTW89_WW][2][83] = 68,
+ [0][1][1][0][RTW89_WW][0][85] = -2,
+ [0][1][1][0][RTW89_WW][1][85] = -2,
+ [0][1][1][0][RTW89_WW][2][85] = 68,
+ [0][1][1][0][RTW89_WW][0][87] = -2,
+ [0][1][1][0][RTW89_WW][1][87] = -2,
+ [0][1][1][0][RTW89_WW][2][87] = 0,
+ [0][1][1][0][RTW89_WW][0][89] = -2,
+ [0][1][1][0][RTW89_WW][1][89] = -2,
+ [0][1][1][0][RTW89_WW][2][89] = 0,
+ [0][1][1][0][RTW89_WW][0][90] = -2,
+ [0][1][1][0][RTW89_WW][1][90] = -2,
+ [0][1][1][0][RTW89_WW][2][90] = 0,
+ [0][1][1][0][RTW89_WW][0][92] = -2,
+ [0][1][1][0][RTW89_WW][1][92] = -2,
+ [0][1][1][0][RTW89_WW][2][92] = 0,
+ [0][1][1][0][RTW89_WW][0][94] = -2,
+ [0][1][1][0][RTW89_WW][1][94] = -2,
+ [0][1][1][0][RTW89_WW][2][94] = 0,
+ [0][1][1][0][RTW89_WW][0][96] = -2,
+ [0][1][1][0][RTW89_WW][1][96] = -2,
+ [0][1][1][0][RTW89_WW][2][96] = 0,
+ [0][1][1][0][RTW89_WW][0][98] = -2,
+ [0][1][1][0][RTW89_WW][1][98] = -2,
+ [0][1][1][0][RTW89_WW][2][98] = 0,
+ [0][1][1][0][RTW89_WW][0][100] = -2,
+ [0][1][1][0][RTW89_WW][1][100] = -2,
+ [0][1][1][0][RTW89_WW][2][100] = 0,
+ [0][1][1][0][RTW89_WW][0][102] = -2,
+ [0][1][1][0][RTW89_WW][1][102] = -2,
+ [0][1][1][0][RTW89_WW][2][102] = 0,
+ [0][1][1][0][RTW89_WW][0][104] = -2,
+ [0][1][1][0][RTW89_WW][1][104] = -2,
+ [0][1][1][0][RTW89_WW][2][104] = 0,
+ [0][1][1][0][RTW89_WW][0][105] = -2,
+ [0][1][1][0][RTW89_WW][1][105] = -2,
+ [0][1][1][0][RTW89_WW][2][105] = 0,
+ [0][1][1][0][RTW89_WW][0][107] = 1,
+ [0][1][1][0][RTW89_WW][1][107] = 1,
+ [0][1][1][0][RTW89_WW][2][107] = 0,
+ [0][1][1][0][RTW89_WW][0][109] = 1,
+ [0][1][1][0][RTW89_WW][1][109] = 1,
+ [0][1][1][0][RTW89_WW][2][109] = 0,
+ [0][1][1][0][RTW89_WW][0][111] = 0,
+ [0][1][1][0][RTW89_WW][1][111] = 0,
+ [0][1][1][0][RTW89_WW][2][111] = 0,
+ [0][1][1][0][RTW89_WW][0][113] = 0,
+ [0][1][1][0][RTW89_WW][1][113] = 0,
+ [0][1][1][0][RTW89_WW][2][113] = 0,
+ [0][1][1][0][RTW89_WW][0][115] = 0,
+ [0][1][1][0][RTW89_WW][1][115] = 0,
+ [0][1][1][0][RTW89_WW][2][115] = 0,
+ [0][1][1][0][RTW89_WW][0][117] = 0,
+ [0][1][1][0][RTW89_WW][1][117] = 0,
+ [0][1][1][0][RTW89_WW][2][117] = 0,
+ [0][1][1][0][RTW89_WW][0][119] = 0,
+ [0][1][1][0][RTW89_WW][1][119] = 0,
+ [0][1][1][0][RTW89_WW][2][119] = 0,
+ [0][0][2][0][RTW89_WW][0][0] = 24,
+ [0][0][2][0][RTW89_WW][1][0] = 24,
+ [0][0][2][0][RTW89_WW][2][0] = 56,
+ [0][0][2][0][RTW89_WW][0][2] = 22,
+ [0][0][2][0][RTW89_WW][1][2] = 22,
+ [0][0][2][0][RTW89_WW][2][2] = 56,
+ [0][0][2][0][RTW89_WW][0][4] = 22,
+ [0][0][2][0][RTW89_WW][1][4] = 22,
+ [0][0][2][0][RTW89_WW][2][4] = 56,
+ [0][0][2][0][RTW89_WW][0][6] = 22,
+ [0][0][2][0][RTW89_WW][1][6] = 22,
+ [0][0][2][0][RTW89_WW][2][6] = 56,
+ [0][0][2][0][RTW89_WW][0][8] = 22,
+ [0][0][2][0][RTW89_WW][1][8] = 22,
+ [0][0][2][0][RTW89_WW][2][8] = 56,
+ [0][0][2][0][RTW89_WW][0][10] = 22,
+ [0][0][2][0][RTW89_WW][1][10] = 22,
+ [0][0][2][0][RTW89_WW][2][10] = 56,
+ [0][0][2][0][RTW89_WW][0][12] = 22,
+ [0][0][2][0][RTW89_WW][1][12] = 22,
+ [0][0][2][0][RTW89_WW][2][12] = 56,
+ [0][0][2][0][RTW89_WW][0][14] = 22,
+ [0][0][2][0][RTW89_WW][1][14] = 22,
+ [0][0][2][0][RTW89_WW][2][14] = 56,
+ [0][0][2][0][RTW89_WW][0][15] = 22,
+ [0][0][2][0][RTW89_WW][1][15] = 22,
+ [0][0][2][0][RTW89_WW][2][15] = 56,
+ [0][0][2][0][RTW89_WW][0][17] = 22,
+ [0][0][2][0][RTW89_WW][1][17] = 22,
+ [0][0][2][0][RTW89_WW][2][17] = 56,
+ [0][0][2][0][RTW89_WW][0][19] = 22,
+ [0][0][2][0][RTW89_WW][1][19] = 22,
+ [0][0][2][0][RTW89_WW][2][19] = 56,
+ [0][0][2][0][RTW89_WW][0][21] = 22,
+ [0][0][2][0][RTW89_WW][1][21] = 22,
+ [0][0][2][0][RTW89_WW][2][21] = 56,
+ [0][0][2][0][RTW89_WW][0][23] = 22,
+ [0][0][2][0][RTW89_WW][1][23] = 22,
+ [0][0][2][0][RTW89_WW][2][23] = 70,
+ [0][0][2][0][RTW89_WW][0][25] = 22,
+ [0][0][2][0][RTW89_WW][1][25] = 22,
+ [0][0][2][0][RTW89_WW][2][25] = 70,
+ [0][0][2][0][RTW89_WW][0][27] = 22,
+ [0][0][2][0][RTW89_WW][1][27] = 22,
+ [0][0][2][0][RTW89_WW][2][27] = 70,
+ [0][0][2][0][RTW89_WW][0][29] = 22,
+ [0][0][2][0][RTW89_WW][1][29] = 22,
+ [0][0][2][0][RTW89_WW][2][29] = 70,
+ [0][0][2][0][RTW89_WW][0][30] = 22,
+ [0][0][2][0][RTW89_WW][1][30] = 22,
+ [0][0][2][0][RTW89_WW][2][30] = 70,
+ [0][0][2][0][RTW89_WW][0][32] = 22,
+ [0][0][2][0][RTW89_WW][1][32] = 22,
+ [0][0][2][0][RTW89_WW][2][32] = 70,
+ [0][0][2][0][RTW89_WW][0][34] = 22,
+ [0][0][2][0][RTW89_WW][1][34] = 22,
+ [0][0][2][0][RTW89_WW][2][34] = 70,
+ [0][0][2][0][RTW89_WW][0][36] = 22,
+ [0][0][2][0][RTW89_WW][1][36] = 22,
+ [0][0][2][0][RTW89_WW][2][36] = 70,
+ [0][0][2][0][RTW89_WW][0][38] = 22,
+ [0][0][2][0][RTW89_WW][1][38] = 22,
+ [0][0][2][0][RTW89_WW][2][38] = 70,
+ [0][0][2][0][RTW89_WW][0][40] = 22,
+ [0][0][2][0][RTW89_WW][1][40] = 22,
+ [0][0][2][0][RTW89_WW][2][40] = 70,
+ [0][0][2][0][RTW89_WW][0][42] = 22,
+ [0][0][2][0][RTW89_WW][1][42] = 22,
+ [0][0][2][0][RTW89_WW][2][42] = 70,
+ [0][0][2][0][RTW89_WW][0][44] = 22,
+ [0][0][2][0][RTW89_WW][1][44] = 22,
+ [0][0][2][0][RTW89_WW][2][44] = 70,
+ [0][0][2][0][RTW89_WW][0][45] = 22,
+ [0][0][2][0][RTW89_WW][1][45] = 22,
+ [0][0][2][0][RTW89_WW][2][45] = 0,
+ [0][0][2][0][RTW89_WW][0][47] = 22,
+ [0][0][2][0][RTW89_WW][1][47] = 22,
+ [0][0][2][0][RTW89_WW][2][47] = 0,
+ [0][0][2][0][RTW89_WW][0][49] = 24,
+ [0][0][2][0][RTW89_WW][1][49] = 24,
+ [0][0][2][0][RTW89_WW][2][49] = 0,
+ [0][0][2][0][RTW89_WW][0][51] = 22,
+ [0][0][2][0][RTW89_WW][1][51] = 22,
+ [0][0][2][0][RTW89_WW][2][51] = 0,
+ [0][0][2][0][RTW89_WW][0][53] = 22,
+ [0][0][2][0][RTW89_WW][1][53] = 22,
+ [0][0][2][0][RTW89_WW][2][53] = 0,
+ [0][0][2][0][RTW89_WW][0][55] = 22,
+ [0][0][2][0][RTW89_WW][1][55] = 22,
+ [0][0][2][0][RTW89_WW][2][55] = 68,
+ [0][0][2][0][RTW89_WW][0][57] = 22,
+ [0][0][2][0][RTW89_WW][1][57] = 22,
+ [0][0][2][0][RTW89_WW][2][57] = 68,
+ [0][0][2][0][RTW89_WW][0][59] = 22,
+ [0][0][2][0][RTW89_WW][1][59] = 22,
+ [0][0][2][0][RTW89_WW][2][59] = 68,
+ [0][0][2][0][RTW89_WW][0][60] = 22,
+ [0][0][2][0][RTW89_WW][1][60] = 22,
+ [0][0][2][0][RTW89_WW][2][60] = 68,
+ [0][0][2][0][RTW89_WW][0][62] = 22,
+ [0][0][2][0][RTW89_WW][1][62] = 22,
+ [0][0][2][0][RTW89_WW][2][62] = 68,
+ [0][0][2][0][RTW89_WW][0][64] = 22,
+ [0][0][2][0][RTW89_WW][1][64] = 22,
+ [0][0][2][0][RTW89_WW][2][64] = 68,
+ [0][0][2][0][RTW89_WW][0][66] = 22,
+ [0][0][2][0][RTW89_WW][1][66] = 22,
+ [0][0][2][0][RTW89_WW][2][66] = 68,
+ [0][0][2][0][RTW89_WW][0][68] = 22,
+ [0][0][2][0][RTW89_WW][1][68] = 22,
+ [0][0][2][0][RTW89_WW][2][68] = 68,
+ [0][0][2][0][RTW89_WW][0][70] = 24,
+ [0][0][2][0][RTW89_WW][1][70] = 24,
+ [0][0][2][0][RTW89_WW][2][70] = 68,
+ [0][0][2][0][RTW89_WW][0][72] = 22,
+ [0][0][2][0][RTW89_WW][1][72] = 22,
+ [0][0][2][0][RTW89_WW][2][72] = 68,
+ [0][0][2][0][RTW89_WW][0][74] = 22,
+ [0][0][2][0][RTW89_WW][1][74] = 22,
+ [0][0][2][0][RTW89_WW][2][74] = 68,
+ [0][0][2][0][RTW89_WW][0][75] = 22,
+ [0][0][2][0][RTW89_WW][1][75] = 22,
+ [0][0][2][0][RTW89_WW][2][75] = 68,
+ [0][0][2][0][RTW89_WW][0][77] = 22,
+ [0][0][2][0][RTW89_WW][1][77] = 22,
+ [0][0][2][0][RTW89_WW][2][77] = 68,
+ [0][0][2][0][RTW89_WW][0][79] = 22,
+ [0][0][2][0][RTW89_WW][1][79] = 22,
+ [0][0][2][0][RTW89_WW][2][79] = 68,
+ [0][0][2][0][RTW89_WW][0][81] = 22,
+ [0][0][2][0][RTW89_WW][1][81] = 22,
+ [0][0][2][0][RTW89_WW][2][81] = 68,
+ [0][0][2][0][RTW89_WW][0][83] = 22,
+ [0][0][2][0][RTW89_WW][1][83] = 22,
+ [0][0][2][0][RTW89_WW][2][83] = 68,
+ [0][0][2][0][RTW89_WW][0][85] = 22,
+ [0][0][2][0][RTW89_WW][1][85] = 22,
+ [0][0][2][0][RTW89_WW][2][85] = 68,
+ [0][0][2][0][RTW89_WW][0][87] = 22,
+ [0][0][2][0][RTW89_WW][1][87] = 22,
+ [0][0][2][0][RTW89_WW][2][87] = 0,
+ [0][0][2][0][RTW89_WW][0][89] = 22,
+ [0][0][2][0][RTW89_WW][1][89] = 22,
+ [0][0][2][0][RTW89_WW][2][89] = 0,
+ [0][0][2][0][RTW89_WW][0][90] = 22,
+ [0][0][2][0][RTW89_WW][1][90] = 22,
+ [0][0][2][0][RTW89_WW][2][90] = 0,
+ [0][0][2][0][RTW89_WW][0][92] = 22,
+ [0][0][2][0][RTW89_WW][1][92] = 22,
+ [0][0][2][0][RTW89_WW][2][92] = 0,
+ [0][0][2][0][RTW89_WW][0][94] = 22,
+ [0][0][2][0][RTW89_WW][1][94] = 22,
+ [0][0][2][0][RTW89_WW][2][94] = 0,
+ [0][0][2][0][RTW89_WW][0][96] = 22,
+ [0][0][2][0][RTW89_WW][1][96] = 22,
+ [0][0][2][0][RTW89_WW][2][96] = 0,
+ [0][0][2][0][RTW89_WW][0][98] = 22,
+ [0][0][2][0][RTW89_WW][1][98] = 22,
+ [0][0][2][0][RTW89_WW][2][98] = 0,
+ [0][0][2][0][RTW89_WW][0][100] = 22,
+ [0][0][2][0][RTW89_WW][1][100] = 22,
+ [0][0][2][0][RTW89_WW][2][100] = 0,
+ [0][0][2][0][RTW89_WW][0][102] = 22,
+ [0][0][2][0][RTW89_WW][1][102] = 22,
+ [0][0][2][0][RTW89_WW][2][102] = 0,
+ [0][0][2][0][RTW89_WW][0][104] = 22,
+ [0][0][2][0][RTW89_WW][1][104] = 22,
+ [0][0][2][0][RTW89_WW][2][104] = 0,
+ [0][0][2][0][RTW89_WW][0][105] = 22,
+ [0][0][2][0][RTW89_WW][1][105] = 22,
+ [0][0][2][0][RTW89_WW][2][105] = 0,
+ [0][0][2][0][RTW89_WW][0][107] = 24,
+ [0][0][2][0][RTW89_WW][1][107] = 24,
+ [0][0][2][0][RTW89_WW][2][107] = 0,
+ [0][0][2][0][RTW89_WW][0][109] = 24,
+ [0][0][2][0][RTW89_WW][1][109] = 24,
+ [0][0][2][0][RTW89_WW][2][109] = 0,
+ [0][0][2][0][RTW89_WW][0][111] = 0,
+ [0][0][2][0][RTW89_WW][1][111] = 0,
+ [0][0][2][0][RTW89_WW][2][111] = 0,
+ [0][0][2][0][RTW89_WW][0][113] = 0,
+ [0][0][2][0][RTW89_WW][1][113] = 0,
+ [0][0][2][0][RTW89_WW][2][113] = 0,
+ [0][0][2][0][RTW89_WW][0][115] = 0,
+ [0][0][2][0][RTW89_WW][1][115] = 0,
+ [0][0][2][0][RTW89_WW][2][115] = 0,
+ [0][0][2][0][RTW89_WW][0][117] = 0,
+ [0][0][2][0][RTW89_WW][1][117] = 0,
+ [0][0][2][0][RTW89_WW][2][117] = 0,
+ [0][0][2][0][RTW89_WW][0][119] = 0,
+ [0][0][2][0][RTW89_WW][1][119] = 0,
+ [0][0][2][0][RTW89_WW][2][119] = 0,
+ [0][1][2][0][RTW89_WW][0][0] = -2,
+ [0][1][2][0][RTW89_WW][1][0] = -2,
+ [0][1][2][0][RTW89_WW][2][0] = 54,
+ [0][1][2][0][RTW89_WW][0][2] = -4,
+ [0][1][2][0][RTW89_WW][1][2] = -4,
+ [0][1][2][0][RTW89_WW][2][2] = 54,
+ [0][1][2][0][RTW89_WW][0][4] = -4,
+ [0][1][2][0][RTW89_WW][1][4] = -4,
+ [0][1][2][0][RTW89_WW][2][4] = 54,
+ [0][1][2][0][RTW89_WW][0][6] = -4,
+ [0][1][2][0][RTW89_WW][1][6] = -4,
+ [0][1][2][0][RTW89_WW][2][6] = 54,
+ [0][1][2][0][RTW89_WW][0][8] = -4,
+ [0][1][2][0][RTW89_WW][1][8] = -4,
+ [0][1][2][0][RTW89_WW][2][8] = 54,
+ [0][1][2][0][RTW89_WW][0][10] = -4,
+ [0][1][2][0][RTW89_WW][1][10] = -4,
+ [0][1][2][0][RTW89_WW][2][10] = 54,
+ [0][1][2][0][RTW89_WW][0][12] = -4,
+ [0][1][2][0][RTW89_WW][1][12] = -4,
+ [0][1][2][0][RTW89_WW][2][12] = 54,
+ [0][1][2][0][RTW89_WW][0][14] = -4,
+ [0][1][2][0][RTW89_WW][1][14] = -4,
+ [0][1][2][0][RTW89_WW][2][14] = 54,
+ [0][1][2][0][RTW89_WW][0][15] = -4,
+ [0][1][2][0][RTW89_WW][1][15] = -4,
+ [0][1][2][0][RTW89_WW][2][15] = 54,
+ [0][1][2][0][RTW89_WW][0][17] = -4,
+ [0][1][2][0][RTW89_WW][1][17] = -4,
+ [0][1][2][0][RTW89_WW][2][17] = 54,
+ [0][1][2][0][RTW89_WW][0][19] = -4,
+ [0][1][2][0][RTW89_WW][1][19] = -4,
+ [0][1][2][0][RTW89_WW][2][19] = 54,
+ [0][1][2][0][RTW89_WW][0][21] = -4,
+ [0][1][2][0][RTW89_WW][1][21] = -4,
+ [0][1][2][0][RTW89_WW][2][21] = 54,
+ [0][1][2][0][RTW89_WW][0][23] = -4,
+ [0][1][2][0][RTW89_WW][1][23] = -4,
+ [0][1][2][0][RTW89_WW][2][23] = 68,
+ [0][1][2][0][RTW89_WW][0][25] = -4,
+ [0][1][2][0][RTW89_WW][1][25] = -4,
+ [0][1][2][0][RTW89_WW][2][25] = 68,
+ [0][1][2][0][RTW89_WW][0][27] = -4,
+ [0][1][2][0][RTW89_WW][1][27] = -4,
+ [0][1][2][0][RTW89_WW][2][27] = 68,
+ [0][1][2][0][RTW89_WW][0][29] = -4,
+ [0][1][2][0][RTW89_WW][1][29] = -4,
+ [0][1][2][0][RTW89_WW][2][29] = 68,
+ [0][1][2][0][RTW89_WW][0][30] = -4,
+ [0][1][2][0][RTW89_WW][1][30] = -4,
+ [0][1][2][0][RTW89_WW][2][30] = 68,
+ [0][1][2][0][RTW89_WW][0][32] = -4,
+ [0][1][2][0][RTW89_WW][1][32] = -4,
+ [0][1][2][0][RTW89_WW][2][32] = 68,
+ [0][1][2][0][RTW89_WW][0][34] = -4,
+ [0][1][2][0][RTW89_WW][1][34] = -4,
+ [0][1][2][0][RTW89_WW][2][34] = 68,
+ [0][1][2][0][RTW89_WW][0][36] = -4,
+ [0][1][2][0][RTW89_WW][1][36] = -4,
+ [0][1][2][0][RTW89_WW][2][36] = 68,
+ [0][1][2][0][RTW89_WW][0][38] = -4,
+ [0][1][2][0][RTW89_WW][1][38] = -4,
+ [0][1][2][0][RTW89_WW][2][38] = 68,
+ [0][1][2][0][RTW89_WW][0][40] = -4,
+ [0][1][2][0][RTW89_WW][1][40] = -4,
+ [0][1][2][0][RTW89_WW][2][40] = 68,
+ [0][1][2][0][RTW89_WW][0][42] = -4,
+ [0][1][2][0][RTW89_WW][1][42] = -4,
+ [0][1][2][0][RTW89_WW][2][42] = 68,
+ [0][1][2][0][RTW89_WW][0][44] = -2,
+ [0][1][2][0][RTW89_WW][1][44] = -2,
+ [0][1][2][0][RTW89_WW][2][44] = 68,
+ [0][1][2][0][RTW89_WW][0][45] = -2,
+ [0][1][2][0][RTW89_WW][1][45] = -2,
+ [0][1][2][0][RTW89_WW][2][45] = 0,
+ [0][1][2][0][RTW89_WW][0][47] = -2,
+ [0][1][2][0][RTW89_WW][1][47] = -2,
+ [0][1][2][0][RTW89_WW][2][47] = 0,
+ [0][1][2][0][RTW89_WW][0][49] = -2,
+ [0][1][2][0][RTW89_WW][1][49] = -2,
+ [0][1][2][0][RTW89_WW][2][49] = 0,
+ [0][1][2][0][RTW89_WW][0][51] = -2,
+ [0][1][2][0][RTW89_WW][1][51] = -2,
+ [0][1][2][0][RTW89_WW][2][51] = 0,
+ [0][1][2][0][RTW89_WW][0][53] = -2,
+ [0][1][2][0][RTW89_WW][1][53] = -2,
+ [0][1][2][0][RTW89_WW][2][53] = 0,
+ [0][1][2][0][RTW89_WW][0][55] = -2,
+ [0][1][2][0][RTW89_WW][1][55] = -2,
+ [0][1][2][0][RTW89_WW][2][55] = 68,
+ [0][1][2][0][RTW89_WW][0][57] = -2,
+ [0][1][2][0][RTW89_WW][1][57] = -2,
+ [0][1][2][0][RTW89_WW][2][57] = 68,
+ [0][1][2][0][RTW89_WW][0][59] = -2,
+ [0][1][2][0][RTW89_WW][1][59] = -2,
+ [0][1][2][0][RTW89_WW][2][59] = 68,
+ [0][1][2][0][RTW89_WW][0][60] = -2,
+ [0][1][2][0][RTW89_WW][1][60] = -2,
+ [0][1][2][0][RTW89_WW][2][60] = 68,
+ [0][1][2][0][RTW89_WW][0][62] = -2,
+ [0][1][2][0][RTW89_WW][1][62] = -2,
+ [0][1][2][0][RTW89_WW][2][62] = 68,
+ [0][1][2][0][RTW89_WW][0][64] = -2,
+ [0][1][2][0][RTW89_WW][1][64] = -2,
+ [0][1][2][0][RTW89_WW][2][64] = 68,
+ [0][1][2][0][RTW89_WW][0][66] = -2,
+ [0][1][2][0][RTW89_WW][1][66] = -2,
+ [0][1][2][0][RTW89_WW][2][66] = 68,
+ [0][1][2][0][RTW89_WW][0][68] = -2,
+ [0][1][2][0][RTW89_WW][1][68] = -2,
+ [0][1][2][0][RTW89_WW][2][68] = 68,
+ [0][1][2][0][RTW89_WW][0][70] = -2,
+ [0][1][2][0][RTW89_WW][1][70] = -2,
+ [0][1][2][0][RTW89_WW][2][70] = 68,
+ [0][1][2][0][RTW89_WW][0][72] = -2,
+ [0][1][2][0][RTW89_WW][1][72] = -2,
+ [0][1][2][0][RTW89_WW][2][72] = 68,
+ [0][1][2][0][RTW89_WW][0][74] = -2,
+ [0][1][2][0][RTW89_WW][1][74] = -2,
+ [0][1][2][0][RTW89_WW][2][74] = 68,
+ [0][1][2][0][RTW89_WW][0][75] = -2,
+ [0][1][2][0][RTW89_WW][1][75] = -2,
+ [0][1][2][0][RTW89_WW][2][75] = 68,
+ [0][1][2][0][RTW89_WW][0][77] = -2,
+ [0][1][2][0][RTW89_WW][1][77] = -2,
+ [0][1][2][0][RTW89_WW][2][77] = 68,
+ [0][1][2][0][RTW89_WW][0][79] = -2,
+ [0][1][2][0][RTW89_WW][1][79] = -2,
+ [0][1][2][0][RTW89_WW][2][79] = 68,
+ [0][1][2][0][RTW89_WW][0][81] = -2,
+ [0][1][2][0][RTW89_WW][1][81] = -2,
+ [0][1][2][0][RTW89_WW][2][81] = 68,
+ [0][1][2][0][RTW89_WW][0][83] = -2,
+ [0][1][2][0][RTW89_WW][1][83] = -2,
+ [0][1][2][0][RTW89_WW][2][83] = 68,
+ [0][1][2][0][RTW89_WW][0][85] = -2,
+ [0][1][2][0][RTW89_WW][1][85] = -2,
+ [0][1][2][0][RTW89_WW][2][85] = 68,
+ [0][1][2][0][RTW89_WW][0][87] = -2,
+ [0][1][2][0][RTW89_WW][1][87] = -2,
+ [0][1][2][0][RTW89_WW][2][87] = 0,
+ [0][1][2][0][RTW89_WW][0][89] = -2,
+ [0][1][2][0][RTW89_WW][1][89] = -2,
+ [0][1][2][0][RTW89_WW][2][89] = 0,
+ [0][1][2][0][RTW89_WW][0][90] = -2,
+ [0][1][2][0][RTW89_WW][1][90] = -2,
+ [0][1][2][0][RTW89_WW][2][90] = 0,
+ [0][1][2][0][RTW89_WW][0][92] = -2,
+ [0][1][2][0][RTW89_WW][1][92] = -2,
+ [0][1][2][0][RTW89_WW][2][92] = 0,
+ [0][1][2][0][RTW89_WW][0][94] = -2,
+ [0][1][2][0][RTW89_WW][1][94] = -2,
+ [0][1][2][0][RTW89_WW][2][94] = 0,
+ [0][1][2][0][RTW89_WW][0][96] = -2,
+ [0][1][2][0][RTW89_WW][1][96] = -2,
+ [0][1][2][0][RTW89_WW][2][96] = 0,
+ [0][1][2][0][RTW89_WW][0][98] = -2,
+ [0][1][2][0][RTW89_WW][1][98] = -2,
+ [0][1][2][0][RTW89_WW][2][98] = 0,
+ [0][1][2][0][RTW89_WW][0][100] = -2,
+ [0][1][2][0][RTW89_WW][1][100] = -2,
+ [0][1][2][0][RTW89_WW][2][100] = 0,
+ [0][1][2][0][RTW89_WW][0][102] = -2,
+ [0][1][2][0][RTW89_WW][1][102] = -2,
+ [0][1][2][0][RTW89_WW][2][102] = 0,
+ [0][1][2][0][RTW89_WW][0][104] = -2,
+ [0][1][2][0][RTW89_WW][1][104] = -2,
+ [0][1][2][0][RTW89_WW][2][104] = 0,
+ [0][1][2][0][RTW89_WW][0][105] = -2,
+ [0][1][2][0][RTW89_WW][1][105] = -2,
+ [0][1][2][0][RTW89_WW][2][105] = 0,
+ [0][1][2][0][RTW89_WW][0][107] = 1,
+ [0][1][2][0][RTW89_WW][1][107] = 1,
+ [0][1][2][0][RTW89_WW][2][107] = 0,
+ [0][1][2][0][RTW89_WW][0][109] = 1,
+ [0][1][2][0][RTW89_WW][1][109] = 1,
+ [0][1][2][0][RTW89_WW][2][109] = 0,
+ [0][1][2][0][RTW89_WW][0][111] = 0,
+ [0][1][2][0][RTW89_WW][1][111] = 0,
+ [0][1][2][0][RTW89_WW][2][111] = 0,
+ [0][1][2][0][RTW89_WW][0][113] = 0,
+ [0][1][2][0][RTW89_WW][1][113] = 0,
+ [0][1][2][0][RTW89_WW][2][113] = 0,
+ [0][1][2][0][RTW89_WW][0][115] = 0,
+ [0][1][2][0][RTW89_WW][1][115] = 0,
+ [0][1][2][0][RTW89_WW][2][115] = 0,
+ [0][1][2][0][RTW89_WW][0][117] = 0,
+ [0][1][2][0][RTW89_WW][1][117] = 0,
+ [0][1][2][0][RTW89_WW][2][117] = 0,
+ [0][1][2][0][RTW89_WW][0][119] = 0,
+ [0][1][2][0][RTW89_WW][1][119] = 0,
+ [0][1][2][0][RTW89_WW][2][119] = 0,
+ [0][1][2][1][RTW89_WW][0][0] = -2,
+ [0][1][2][1][RTW89_WW][1][0] = -2,
+ [0][1][2][1][RTW89_WW][2][0] = 54,
+ [0][1][2][1][RTW89_WW][0][2] = -4,
+ [0][1][2][1][RTW89_WW][1][2] = -4,
+ [0][1][2][1][RTW89_WW][2][2] = 54,
+ [0][1][2][1][RTW89_WW][0][4] = -4,
+ [0][1][2][1][RTW89_WW][1][4] = -4,
+ [0][1][2][1][RTW89_WW][2][4] = 54,
+ [0][1][2][1][RTW89_WW][0][6] = -4,
+ [0][1][2][1][RTW89_WW][1][6] = -4,
+ [0][1][2][1][RTW89_WW][2][6] = 54,
+ [0][1][2][1][RTW89_WW][0][8] = -4,
+ [0][1][2][1][RTW89_WW][1][8] = -4,
+ [0][1][2][1][RTW89_WW][2][8] = 54,
+ [0][1][2][1][RTW89_WW][0][10] = -4,
+ [0][1][2][1][RTW89_WW][1][10] = -4,
+ [0][1][2][1][RTW89_WW][2][10] = 54,
+ [0][1][2][1][RTW89_WW][0][12] = -4,
+ [0][1][2][1][RTW89_WW][1][12] = -4,
+ [0][1][2][1][RTW89_WW][2][12] = 54,
+ [0][1][2][1][RTW89_WW][0][14] = -4,
+ [0][1][2][1][RTW89_WW][1][14] = -4,
+ [0][1][2][1][RTW89_WW][2][14] = 54,
+ [0][1][2][1][RTW89_WW][0][15] = -4,
+ [0][1][2][1][RTW89_WW][1][15] = -4,
+ [0][1][2][1][RTW89_WW][2][15] = 54,
+ [0][1][2][1][RTW89_WW][0][17] = -4,
+ [0][1][2][1][RTW89_WW][1][17] = -4,
+ [0][1][2][1][RTW89_WW][2][17] = 54,
+ [0][1][2][1][RTW89_WW][0][19] = -4,
+ [0][1][2][1][RTW89_WW][1][19] = -4,
+ [0][1][2][1][RTW89_WW][2][19] = 54,
+ [0][1][2][1][RTW89_WW][0][21] = -4,
+ [0][1][2][1][RTW89_WW][1][21] = -4,
+ [0][1][2][1][RTW89_WW][2][21] = 54,
+ [0][1][2][1][RTW89_WW][0][23] = -4,
+ [0][1][2][1][RTW89_WW][1][23] = -4,
+ [0][1][2][1][RTW89_WW][2][23] = 68,
+ [0][1][2][1][RTW89_WW][0][25] = -4,
+ [0][1][2][1][RTW89_WW][1][25] = -4,
+ [0][1][2][1][RTW89_WW][2][25] = 68,
+ [0][1][2][1][RTW89_WW][0][27] = -4,
+ [0][1][2][1][RTW89_WW][1][27] = -4,
+ [0][1][2][1][RTW89_WW][2][27] = 68,
+ [0][1][2][1][RTW89_WW][0][29] = -4,
+ [0][1][2][1][RTW89_WW][1][29] = -4,
+ [0][1][2][1][RTW89_WW][2][29] = 68,
+ [0][1][2][1][RTW89_WW][0][30] = -4,
+ [0][1][2][1][RTW89_WW][1][30] = -4,
+ [0][1][2][1][RTW89_WW][2][30] = 68,
+ [0][1][2][1][RTW89_WW][0][32] = -4,
+ [0][1][2][1][RTW89_WW][1][32] = -4,
+ [0][1][2][1][RTW89_WW][2][32] = 68,
+ [0][1][2][1][RTW89_WW][0][34] = -4,
+ [0][1][2][1][RTW89_WW][1][34] = -4,
+ [0][1][2][1][RTW89_WW][2][34] = 68,
+ [0][1][2][1][RTW89_WW][0][36] = -4,
+ [0][1][2][1][RTW89_WW][1][36] = -4,
+ [0][1][2][1][RTW89_WW][2][36] = 68,
+ [0][1][2][1][RTW89_WW][0][38] = -4,
+ [0][1][2][1][RTW89_WW][1][38] = -4,
+ [0][1][2][1][RTW89_WW][2][38] = 68,
+ [0][1][2][1][RTW89_WW][0][40] = -4,
+ [0][1][2][1][RTW89_WW][1][40] = -4,
+ [0][1][2][1][RTW89_WW][2][40] = 68,
+ [0][1][2][1][RTW89_WW][0][42] = -4,
+ [0][1][2][1][RTW89_WW][1][42] = -4,
+ [0][1][2][1][RTW89_WW][2][42] = 68,
+ [0][1][2][1][RTW89_WW][0][44] = -2,
+ [0][1][2][1][RTW89_WW][1][44] = -2,
+ [0][1][2][1][RTW89_WW][2][44] = 68,
+ [0][1][2][1][RTW89_WW][0][45] = -2,
+ [0][1][2][1][RTW89_WW][1][45] = -2,
+ [0][1][2][1][RTW89_WW][2][45] = 0,
+ [0][1][2][1][RTW89_WW][0][47] = -2,
+ [0][1][2][1][RTW89_WW][1][47] = -2,
+ [0][1][2][1][RTW89_WW][2][47] = 0,
+ [0][1][2][1][RTW89_WW][0][49] = -2,
+ [0][1][2][1][RTW89_WW][1][49] = -2,
+ [0][1][2][1][RTW89_WW][2][49] = 0,
+ [0][1][2][1][RTW89_WW][0][51] = -2,
+ [0][1][2][1][RTW89_WW][1][51] = -2,
+ [0][1][2][1][RTW89_WW][2][51] = 0,
+ [0][1][2][1][RTW89_WW][0][53] = -2,
+ [0][1][2][1][RTW89_WW][1][53] = -2,
+ [0][1][2][1][RTW89_WW][2][53] = 0,
+ [0][1][2][1][RTW89_WW][0][55] = -2,
+ [0][1][2][1][RTW89_WW][1][55] = -2,
+ [0][1][2][1][RTW89_WW][2][55] = 68,
+ [0][1][2][1][RTW89_WW][0][57] = -2,
+ [0][1][2][1][RTW89_WW][1][57] = -2,
+ [0][1][2][1][RTW89_WW][2][57] = 68,
+ [0][1][2][1][RTW89_WW][0][59] = -2,
+ [0][1][2][1][RTW89_WW][1][59] = -2,
+ [0][1][2][1][RTW89_WW][2][59] = 68,
+ [0][1][2][1][RTW89_WW][0][60] = -2,
+ [0][1][2][1][RTW89_WW][1][60] = -2,
+ [0][1][2][1][RTW89_WW][2][60] = 68,
+ [0][1][2][1][RTW89_WW][0][62] = -2,
+ [0][1][2][1][RTW89_WW][1][62] = -2,
+ [0][1][2][1][RTW89_WW][2][62] = 68,
+ [0][1][2][1][RTW89_WW][0][64] = -2,
+ [0][1][2][1][RTW89_WW][1][64] = -2,
+ [0][1][2][1][RTW89_WW][2][64] = 68,
+ [0][1][2][1][RTW89_WW][0][66] = -2,
+ [0][1][2][1][RTW89_WW][1][66] = -2,
+ [0][1][2][1][RTW89_WW][2][66] = 68,
+ [0][1][2][1][RTW89_WW][0][68] = -2,
+ [0][1][2][1][RTW89_WW][1][68] = -2,
+ [0][1][2][1][RTW89_WW][2][68] = 68,
+ [0][1][2][1][RTW89_WW][0][70] = -2,
+ [0][1][2][1][RTW89_WW][1][70] = -2,
+ [0][1][2][1][RTW89_WW][2][70] = 68,
+ [0][1][2][1][RTW89_WW][0][72] = -2,
+ [0][1][2][1][RTW89_WW][1][72] = -2,
+ [0][1][2][1][RTW89_WW][2][72] = 68,
+ [0][1][2][1][RTW89_WW][0][74] = -2,
+ [0][1][2][1][RTW89_WW][1][74] = -2,
+ [0][1][2][1][RTW89_WW][2][74] = 68,
+ [0][1][2][1][RTW89_WW][0][75] = -2,
+ [0][1][2][1][RTW89_WW][1][75] = -2,
+ [0][1][2][1][RTW89_WW][2][75] = 68,
+ [0][1][2][1][RTW89_WW][0][77] = -2,
+ [0][1][2][1][RTW89_WW][1][77] = -2,
+ [0][1][2][1][RTW89_WW][2][77] = 68,
+ [0][1][2][1][RTW89_WW][0][79] = -2,
+ [0][1][2][1][RTW89_WW][1][79] = -2,
+ [0][1][2][1][RTW89_WW][2][79] = 68,
+ [0][1][2][1][RTW89_WW][0][81] = -2,
+ [0][1][2][1][RTW89_WW][1][81] = -2,
+ [0][1][2][1][RTW89_WW][2][81] = 68,
+ [0][1][2][1][RTW89_WW][0][83] = -2,
+ [0][1][2][1][RTW89_WW][1][83] = -2,
+ [0][1][2][1][RTW89_WW][2][83] = 68,
+ [0][1][2][1][RTW89_WW][0][85] = -2,
+ [0][1][2][1][RTW89_WW][1][85] = -2,
+ [0][1][2][1][RTW89_WW][2][85] = 68,
+ [0][1][2][1][RTW89_WW][0][87] = -2,
+ [0][1][2][1][RTW89_WW][1][87] = -2,
+ [0][1][2][1][RTW89_WW][2][87] = 0,
+ [0][1][2][1][RTW89_WW][0][89] = -2,
+ [0][1][2][1][RTW89_WW][1][89] = -2,
+ [0][1][2][1][RTW89_WW][2][89] = 0,
+ [0][1][2][1][RTW89_WW][0][90] = -2,
+ [0][1][2][1][RTW89_WW][1][90] = -2,
+ [0][1][2][1][RTW89_WW][2][90] = 0,
+ [0][1][2][1][RTW89_WW][0][92] = -2,
+ [0][1][2][1][RTW89_WW][1][92] = -2,
+ [0][1][2][1][RTW89_WW][2][92] = 0,
+ [0][1][2][1][RTW89_WW][0][94] = -2,
+ [0][1][2][1][RTW89_WW][1][94] = -2,
+ [0][1][2][1][RTW89_WW][2][94] = 0,
+ [0][1][2][1][RTW89_WW][0][96] = -2,
+ [0][1][2][1][RTW89_WW][1][96] = -2,
+ [0][1][2][1][RTW89_WW][2][96] = 0,
+ [0][1][2][1][RTW89_WW][0][98] = -2,
+ [0][1][2][1][RTW89_WW][1][98] = -2,
+ [0][1][2][1][RTW89_WW][2][98] = 0,
+ [0][1][2][1][RTW89_WW][0][100] = -2,
+ [0][1][2][1][RTW89_WW][1][100] = -2,
+ [0][1][2][1][RTW89_WW][2][100] = 0,
+ [0][1][2][1][RTW89_WW][0][102] = -2,
+ [0][1][2][1][RTW89_WW][1][102] = -2,
+ [0][1][2][1][RTW89_WW][2][102] = 0,
+ [0][1][2][1][RTW89_WW][0][104] = -2,
+ [0][1][2][1][RTW89_WW][1][104] = -2,
+ [0][1][2][1][RTW89_WW][2][104] = 0,
+ [0][1][2][1][RTW89_WW][0][105] = -2,
+ [0][1][2][1][RTW89_WW][1][105] = -2,
+ [0][1][2][1][RTW89_WW][2][105] = 0,
+ [0][1][2][1][RTW89_WW][0][107] = 1,
+ [0][1][2][1][RTW89_WW][1][107] = 1,
+ [0][1][2][1][RTW89_WW][2][107] = 0,
+ [0][1][2][1][RTW89_WW][0][109] = 1,
+ [0][1][2][1][RTW89_WW][1][109] = 1,
+ [0][1][2][1][RTW89_WW][2][109] = 0,
+ [0][1][2][1][RTW89_WW][0][111] = 0,
+ [0][1][2][1][RTW89_WW][1][111] = 0,
+ [0][1][2][1][RTW89_WW][2][111] = 0,
+ [0][1][2][1][RTW89_WW][0][113] = 0,
+ [0][1][2][1][RTW89_WW][1][113] = 0,
+ [0][1][2][1][RTW89_WW][2][113] = 0,
+ [0][1][2][1][RTW89_WW][0][115] = 0,
+ [0][1][2][1][RTW89_WW][1][115] = 0,
+ [0][1][2][1][RTW89_WW][2][115] = 0,
+ [0][1][2][1][RTW89_WW][0][117] = 0,
+ [0][1][2][1][RTW89_WW][1][117] = 0,
+ [0][1][2][1][RTW89_WW][2][117] = 0,
+ [0][1][2][1][RTW89_WW][0][119] = 0,
+ [0][1][2][1][RTW89_WW][1][119] = 0,
+ [0][1][2][1][RTW89_WW][2][119] = 0,
+ [1][0][2][0][RTW89_WW][0][1] = 24,
+ [1][0][2][0][RTW89_WW][1][1] = 34,
+ [1][0][2][0][RTW89_WW][2][1] = 70,
+ [1][0][2][0][RTW89_WW][0][5] = 24,
+ [1][0][2][0][RTW89_WW][1][5] = 34,
+ [1][0][2][0][RTW89_WW][2][5] = 70,
+ [1][0][2][0][RTW89_WW][0][9] = 24,
+ [1][0][2][0][RTW89_WW][1][9] = 34,
+ [1][0][2][0][RTW89_WW][2][9] = 70,
+ [1][0][2][0][RTW89_WW][0][13] = 24,
+ [1][0][2][0][RTW89_WW][1][13] = 34,
+ [1][0][2][0][RTW89_WW][2][13] = 70,
+ [1][0][2][0][RTW89_WW][0][16] = 24,
+ [1][0][2][0][RTW89_WW][1][16] = 34,
+ [1][0][2][0][RTW89_WW][2][16] = 70,
+ [1][0][2][0][RTW89_WW][0][20] = 24,
+ [1][0][2][0][RTW89_WW][1][20] = 34,
+ [1][0][2][0][RTW89_WW][2][20] = 70,
+ [1][0][2][0][RTW89_WW][0][24] = 26,
+ [1][0][2][0][RTW89_WW][1][24] = 36,
+ [1][0][2][0][RTW89_WW][2][24] = 70,
+ [1][0][2][0][RTW89_WW][0][28] = 26,
+ [1][0][2][0][RTW89_WW][1][28] = 34,
+ [1][0][2][0][RTW89_WW][2][28] = 70,
+ [1][0][2][0][RTW89_WW][0][31] = 26,
+ [1][0][2][0][RTW89_WW][1][31] = 34,
+ [1][0][2][0][RTW89_WW][2][31] = 70,
+ [1][0][2][0][RTW89_WW][0][35] = 26,
+ [1][0][2][0][RTW89_WW][1][35] = 34,
+ [1][0][2][0][RTW89_WW][2][35] = 70,
+ [1][0][2][0][RTW89_WW][0][39] = 26,
+ [1][0][2][0][RTW89_WW][1][39] = 34,
+ [1][0][2][0][RTW89_WW][2][39] = 70,
+ [1][0][2][0][RTW89_WW][0][43] = 26,
+ [1][0][2][0][RTW89_WW][1][43] = 34,
+ [1][0][2][0][RTW89_WW][2][43] = 70,
+ [1][0][2][0][RTW89_WW][0][46] = 34,
+ [1][0][2][0][RTW89_WW][1][46] = 34,
+ [1][0][2][0][RTW89_WW][2][46] = 0,
+ [1][0][2][0][RTW89_WW][0][50] = 34,
+ [1][0][2][0][RTW89_WW][1][50] = 34,
+ [1][0][2][0][RTW89_WW][2][50] = 0,
+ [1][0][2][0][RTW89_WW][0][54] = 36,
+ [1][0][2][0][RTW89_WW][1][54] = 36,
+ [1][0][2][0][RTW89_WW][2][54] = 0,
+ [1][0][2][0][RTW89_WW][0][58] = 36,
+ [1][0][2][0][RTW89_WW][1][58] = 36,
+ [1][0][2][0][RTW89_WW][2][58] = 66,
+ [1][0][2][0][RTW89_WW][0][61] = 34,
+ [1][0][2][0][RTW89_WW][1][61] = 34,
+ [1][0][2][0][RTW89_WW][2][61] = 66,
+ [1][0][2][0][RTW89_WW][0][65] = 34,
+ [1][0][2][0][RTW89_WW][1][65] = 34,
+ [1][0][2][0][RTW89_WW][2][65] = 66,
+ [1][0][2][0][RTW89_WW][0][69] = 34,
+ [1][0][2][0][RTW89_WW][1][69] = 34,
+ [1][0][2][0][RTW89_WW][2][69] = 66,
+ [1][0][2][0][RTW89_WW][0][73] = 34,
+ [1][0][2][0][RTW89_WW][1][73] = 34,
+ [1][0][2][0][RTW89_WW][2][73] = 66,
+ [1][0][2][0][RTW89_WW][0][76] = 34,
+ [1][0][2][0][RTW89_WW][1][76] = 34,
+ [1][0][2][0][RTW89_WW][2][76] = 66,
+ [1][0][2][0][RTW89_WW][0][80] = 34,
+ [1][0][2][0][RTW89_WW][1][80] = 34,
+ [1][0][2][0][RTW89_WW][2][80] = 66,
+ [1][0][2][0][RTW89_WW][0][84] = 34,
+ [1][0][2][0][RTW89_WW][1][84] = 34,
+ [1][0][2][0][RTW89_WW][2][84] = 66,
+ [1][0][2][0][RTW89_WW][0][88] = 34,
+ [1][0][2][0][RTW89_WW][1][88] = 34,
+ [1][0][2][0][RTW89_WW][2][88] = 0,
+ [1][0][2][0][RTW89_WW][0][91] = 36,
+ [1][0][2][0][RTW89_WW][1][91] = 36,
+ [1][0][2][0][RTW89_WW][2][91] = 0,
+ [1][0][2][0][RTW89_WW][0][95] = 34,
+ [1][0][2][0][RTW89_WW][1][95] = 34,
+ [1][0][2][0][RTW89_WW][2][95] = 0,
+ [1][0][2][0][RTW89_WW][0][99] = 34,
+ [1][0][2][0][RTW89_WW][1][99] = 34,
+ [1][0][2][0][RTW89_WW][2][99] = 0,
+ [1][0][2][0][RTW89_WW][0][103] = 34,
+ [1][0][2][0][RTW89_WW][1][103] = 34,
+ [1][0][2][0][RTW89_WW][2][103] = 0,
+ [1][0][2][0][RTW89_WW][0][106] = 36,
+ [1][0][2][0][RTW89_WW][1][106] = 36,
+ [1][0][2][0][RTW89_WW][2][106] = 0,
+ [1][0][2][0][RTW89_WW][0][110] = 0,
+ [1][0][2][0][RTW89_WW][1][110] = 0,
+ [1][0][2][0][RTW89_WW][2][110] = 0,
+ [1][0][2][0][RTW89_WW][0][114] = 0,
+ [1][0][2][0][RTW89_WW][1][114] = 0,
+ [1][0][2][0][RTW89_WW][2][114] = 0,
+ [1][0][2][0][RTW89_WW][0][118] = 0,
+ [1][0][2][0][RTW89_WW][1][118] = 0,
+ [1][0][2][0][RTW89_WW][2][118] = 0,
+ [1][1][2][0][RTW89_WW][0][1] = 10,
+ [1][1][2][0][RTW89_WW][1][1] = 10,
+ [1][1][2][0][RTW89_WW][2][1] = 58,
+ [1][1][2][0][RTW89_WW][0][5] = 10,
+ [1][1][2][0][RTW89_WW][1][5] = 10,
+ [1][1][2][0][RTW89_WW][2][5] = 58,
+ [1][1][2][0][RTW89_WW][0][9] = 10,
+ [1][1][2][0][RTW89_WW][1][9] = 10,
+ [1][1][2][0][RTW89_WW][2][9] = 58,
+ [1][1][2][0][RTW89_WW][0][13] = 10,
+ [1][1][2][0][RTW89_WW][1][13] = 10,
+ [1][1][2][0][RTW89_WW][2][13] = 58,
+ [1][1][2][0][RTW89_WW][0][16] = 10,
+ [1][1][2][0][RTW89_WW][1][16] = 10,
+ [1][1][2][0][RTW89_WW][2][16] = 58,
+ [1][1][2][0][RTW89_WW][0][20] = 10,
+ [1][1][2][0][RTW89_WW][1][20] = 10,
+ [1][1][2][0][RTW89_WW][2][20] = 58,
+ [1][1][2][0][RTW89_WW][0][24] = 10,
+ [1][1][2][0][RTW89_WW][1][24] = 10,
+ [1][1][2][0][RTW89_WW][2][24] = 70,
+ [1][1][2][0][RTW89_WW][0][28] = 10,
+ [1][1][2][0][RTW89_WW][1][28] = 10,
+ [1][1][2][0][RTW89_WW][2][28] = 70,
+ [1][1][2][0][RTW89_WW][0][31] = 10,
+ [1][1][2][0][RTW89_WW][1][31] = 10,
+ [1][1][2][0][RTW89_WW][2][31] = 70,
+ [1][1][2][0][RTW89_WW][0][35] = 10,
+ [1][1][2][0][RTW89_WW][1][35] = 10,
+ [1][1][2][0][RTW89_WW][2][35] = 70,
+ [1][1][2][0][RTW89_WW][0][39] = 10,
+ [1][1][2][0][RTW89_WW][1][39] = 10,
+ [1][1][2][0][RTW89_WW][2][39] = 70,
+ [1][1][2][0][RTW89_WW][0][43] = 10,
+ [1][1][2][0][RTW89_WW][1][43] = 10,
+ [1][1][2][0][RTW89_WW][2][43] = 70,
+ [1][1][2][0][RTW89_WW][0][46] = 12,
+ [1][1][2][0][RTW89_WW][1][46] = 12,
+ [1][1][2][0][RTW89_WW][2][46] = 0,
+ [1][1][2][0][RTW89_WW][0][50] = 12,
+ [1][1][2][0][RTW89_WW][1][50] = 12,
+ [1][1][2][0][RTW89_WW][2][50] = 0,
+ [1][1][2][0][RTW89_WW][0][54] = 10,
+ [1][1][2][0][RTW89_WW][1][54] = 10,
+ [1][1][2][0][RTW89_WW][2][54] = 0,
+ [1][1][2][0][RTW89_WW][0][58] = 10,
+ [1][1][2][0][RTW89_WW][1][58] = 10,
+ [1][1][2][0][RTW89_WW][2][58] = 66,
+ [1][1][2][0][RTW89_WW][0][61] = 10,
+ [1][1][2][0][RTW89_WW][1][61] = 10,
+ [1][1][2][0][RTW89_WW][2][61] = 66,
+ [1][1][2][0][RTW89_WW][0][65] = 10,
+ [1][1][2][0][RTW89_WW][1][65] = 10,
+ [1][1][2][0][RTW89_WW][2][65] = 66,
+ [1][1][2][0][RTW89_WW][0][69] = 10,
+ [1][1][2][0][RTW89_WW][1][69] = 10,
+ [1][1][2][0][RTW89_WW][2][69] = 66,
+ [1][1][2][0][RTW89_WW][0][73] = 10,
+ [1][1][2][0][RTW89_WW][1][73] = 10,
+ [1][1][2][0][RTW89_WW][2][73] = 66,
+ [1][1][2][0][RTW89_WW][0][76] = 10,
+ [1][1][2][0][RTW89_WW][1][76] = 10,
+ [1][1][2][0][RTW89_WW][2][76] = 66,
+ [1][1][2][0][RTW89_WW][0][80] = 10,
+ [1][1][2][0][RTW89_WW][1][80] = 10,
+ [1][1][2][0][RTW89_WW][2][80] = 66,
+ [1][1][2][0][RTW89_WW][0][84] = 10,
+ [1][1][2][0][RTW89_WW][1][84] = 10,
+ [1][1][2][0][RTW89_WW][2][84] = 66,
+ [1][1][2][0][RTW89_WW][0][88] = 10,
+ [1][1][2][0][RTW89_WW][1][88] = 10,
+ [1][1][2][0][RTW89_WW][2][88] = 0,
+ [1][1][2][0][RTW89_WW][0][91] = 12,
+ [1][1][2][0][RTW89_WW][1][91] = 12,
+ [1][1][2][0][RTW89_WW][2][91] = 0,
+ [1][1][2][0][RTW89_WW][0][95] = 10,
+ [1][1][2][0][RTW89_WW][1][95] = 10,
+ [1][1][2][0][RTW89_WW][2][95] = 0,
+ [1][1][2][0][RTW89_WW][0][99] = 10,
+ [1][1][2][0][RTW89_WW][1][99] = 10,
+ [1][1][2][0][RTW89_WW][2][99] = 0,
+ [1][1][2][0][RTW89_WW][0][103] = 10,
+ [1][1][2][0][RTW89_WW][1][103] = 10,
+ [1][1][2][0][RTW89_WW][2][103] = 0,
+ [1][1][2][0][RTW89_WW][0][106] = 12,
+ [1][1][2][0][RTW89_WW][1][106] = 12,
+ [1][1][2][0][RTW89_WW][2][106] = 0,
+ [1][1][2][0][RTW89_WW][0][110] = 0,
+ [1][1][2][0][RTW89_WW][1][110] = 0,
+ [1][1][2][0][RTW89_WW][2][110] = 0,
+ [1][1][2][0][RTW89_WW][0][114] = 0,
+ [1][1][2][0][RTW89_WW][1][114] = 0,
+ [1][1][2][0][RTW89_WW][2][114] = 0,
+ [1][1][2][0][RTW89_WW][0][118] = 0,
+ [1][1][2][0][RTW89_WW][1][118] = 0,
+ [1][1][2][0][RTW89_WW][2][118] = 0,
+ [1][1][2][1][RTW89_WW][0][1] = 6,
+ [1][1][2][1][RTW89_WW][1][1] = 10,
+ [1][1][2][1][RTW89_WW][2][1] = 58,
+ [1][1][2][1][RTW89_WW][0][5] = 6,
+ [1][1][2][1][RTW89_WW][1][5] = 10,
+ [1][1][2][1][RTW89_WW][2][5] = 58,
+ [1][1][2][1][RTW89_WW][0][9] = 6,
+ [1][1][2][1][RTW89_WW][1][9] = 10,
+ [1][1][2][1][RTW89_WW][2][9] = 58,
+ [1][1][2][1][RTW89_WW][0][13] = 6,
+ [1][1][2][1][RTW89_WW][1][13] = 10,
+ [1][1][2][1][RTW89_WW][2][13] = 58,
+ [1][1][2][1][RTW89_WW][0][16] = 6,
+ [1][1][2][1][RTW89_WW][1][16] = 10,
+ [1][1][2][1][RTW89_WW][2][16] = 58,
+ [1][1][2][1][RTW89_WW][0][20] = 6,
+ [1][1][2][1][RTW89_WW][1][20] = 10,
+ [1][1][2][1][RTW89_WW][2][20] = 58,
+ [1][1][2][1][RTW89_WW][0][24] = 6,
+ [1][1][2][1][RTW89_WW][1][24] = 10,
+ [1][1][2][1][RTW89_WW][2][24] = 70,
+ [1][1][2][1][RTW89_WW][0][28] = 6,
+ [1][1][2][1][RTW89_WW][1][28] = 10,
+ [1][1][2][1][RTW89_WW][2][28] = 70,
+ [1][1][2][1][RTW89_WW][0][31] = 6,
+ [1][1][2][1][RTW89_WW][1][31] = 10,
+ [1][1][2][1][RTW89_WW][2][31] = 70,
+ [1][1][2][1][RTW89_WW][0][35] = 6,
+ [1][1][2][1][RTW89_WW][1][35] = 10,
+ [1][1][2][1][RTW89_WW][2][35] = 70,
+ [1][1][2][1][RTW89_WW][0][39] = 6,
+ [1][1][2][1][RTW89_WW][1][39] = 10,
+ [1][1][2][1][RTW89_WW][2][39] = 70,
+ [1][1][2][1][RTW89_WW][0][43] = 6,
+ [1][1][2][1][RTW89_WW][1][43] = 10,
+ [1][1][2][1][RTW89_WW][2][43] = 70,
+ [1][1][2][1][RTW89_WW][0][46] = 12,
+ [1][1][2][1][RTW89_WW][1][46] = 12,
+ [1][1][2][1][RTW89_WW][2][46] = 0,
+ [1][1][2][1][RTW89_WW][0][50] = 12,
+ [1][1][2][1][RTW89_WW][1][50] = 12,
+ [1][1][2][1][RTW89_WW][2][50] = 0,
+ [1][1][2][1][RTW89_WW][0][54] = 10,
+ [1][1][2][1][RTW89_WW][1][54] = 10,
+ [1][1][2][1][RTW89_WW][2][54] = 0,
+ [1][1][2][1][RTW89_WW][0][58] = 10,
+ [1][1][2][1][RTW89_WW][1][58] = 10,
+ [1][1][2][1][RTW89_WW][2][58] = 66,
+ [1][1][2][1][RTW89_WW][0][61] = 10,
+ [1][1][2][1][RTW89_WW][1][61] = 10,
+ [1][1][2][1][RTW89_WW][2][61] = 66,
+ [1][1][2][1][RTW89_WW][0][65] = 10,
+ [1][1][2][1][RTW89_WW][1][65] = 10,
+ [1][1][2][1][RTW89_WW][2][65] = 66,
+ [1][1][2][1][RTW89_WW][0][69] = 10,
+ [1][1][2][1][RTW89_WW][1][69] = 10,
+ [1][1][2][1][RTW89_WW][2][69] = 66,
+ [1][1][2][1][RTW89_WW][0][73] = 10,
+ [1][1][2][1][RTW89_WW][1][73] = 10,
+ [1][1][2][1][RTW89_WW][2][73] = 66,
+ [1][1][2][1][RTW89_WW][0][76] = 10,
+ [1][1][2][1][RTW89_WW][1][76] = 10,
+ [1][1][2][1][RTW89_WW][2][76] = 66,
+ [1][1][2][1][RTW89_WW][0][80] = 10,
+ [1][1][2][1][RTW89_WW][1][80] = 10,
+ [1][1][2][1][RTW89_WW][2][80] = 66,
+ [1][1][2][1][RTW89_WW][0][84] = 10,
+ [1][1][2][1][RTW89_WW][1][84] = 10,
+ [1][1][2][1][RTW89_WW][2][84] = 66,
+ [1][1][2][1][RTW89_WW][0][88] = 10,
+ [1][1][2][1][RTW89_WW][1][88] = 10,
+ [1][1][2][1][RTW89_WW][2][88] = 0,
+ [1][1][2][1][RTW89_WW][0][91] = 12,
+ [1][1][2][1][RTW89_WW][1][91] = 12,
+ [1][1][2][1][RTW89_WW][2][91] = 0,
+ [1][1][2][1][RTW89_WW][0][95] = 10,
+ [1][1][2][1][RTW89_WW][1][95] = 10,
+ [1][1][2][1][RTW89_WW][2][95] = 0,
+ [1][1][2][1][RTW89_WW][0][99] = 10,
+ [1][1][2][1][RTW89_WW][1][99] = 10,
+ [1][1][2][1][RTW89_WW][2][99] = 0,
+ [1][1][2][1][RTW89_WW][0][103] = 10,
+ [1][1][2][1][RTW89_WW][1][103] = 10,
+ [1][1][2][1][RTW89_WW][2][103] = 0,
+ [1][1][2][1][RTW89_WW][0][106] = 12,
+ [1][1][2][1][RTW89_WW][1][106] = 12,
+ [1][1][2][1][RTW89_WW][2][106] = 0,
+ [1][1][2][1][RTW89_WW][0][110] = 0,
+ [1][1][2][1][RTW89_WW][1][110] = 0,
+ [1][1][2][1][RTW89_WW][2][110] = 0,
+ [1][1][2][1][RTW89_WW][0][114] = 0,
+ [1][1][2][1][RTW89_WW][1][114] = 0,
+ [1][1][2][1][RTW89_WW][2][114] = 0,
+ [1][1][2][1][RTW89_WW][0][118] = 0,
+ [1][1][2][1][RTW89_WW][1][118] = 0,
+ [1][1][2][1][RTW89_WW][2][118] = 0,
+ [2][0][2][0][RTW89_WW][0][3] = 24,
+ [2][0][2][0][RTW89_WW][1][3] = 46,
+ [2][0][2][0][RTW89_WW][2][3] = 60,
+ [2][0][2][0][RTW89_WW][0][11] = 24,
+ [2][0][2][0][RTW89_WW][1][11] = 46,
+ [2][0][2][0][RTW89_WW][2][11] = 60,
+ [2][0][2][0][RTW89_WW][0][18] = 24,
+ [2][0][2][0][RTW89_WW][1][18] = 46,
+ [2][0][2][0][RTW89_WW][2][18] = 60,
+ [2][0][2][0][RTW89_WW][0][26] = 24,
+ [2][0][2][0][RTW89_WW][1][26] = 46,
+ [2][0][2][0][RTW89_WW][2][26] = 60,
+ [2][0][2][0][RTW89_WW][0][33] = 24,
+ [2][0][2][0][RTW89_WW][1][33] = 46,
+ [2][0][2][0][RTW89_WW][2][33] = 60,
+ [2][0][2][0][RTW89_WW][0][41] = 24,
+ [2][0][2][0][RTW89_WW][1][41] = 46,
+ [2][0][2][0][RTW89_WW][2][41] = 60,
+ [2][0][2][0][RTW89_WW][0][48] = 46,
+ [2][0][2][0][RTW89_WW][1][48] = 46,
+ [2][0][2][0][RTW89_WW][2][48] = 0,
+ [2][0][2][0][RTW89_WW][0][56] = 46,
+ [2][0][2][0][RTW89_WW][1][56] = 46,
+ [2][0][2][0][RTW89_WW][2][56] = 0,
+ [2][0][2][0][RTW89_WW][0][63] = 46,
+ [2][0][2][0][RTW89_WW][1][63] = 46,
+ [2][0][2][0][RTW89_WW][2][63] = 58,
+ [2][0][2][0][RTW89_WW][0][71] = 46,
+ [2][0][2][0][RTW89_WW][1][71] = 46,
+ [2][0][2][0][RTW89_WW][2][71] = 58,
+ [2][0][2][0][RTW89_WW][0][78] = 46,
+ [2][0][2][0][RTW89_WW][1][78] = 46,
+ [2][0][2][0][RTW89_WW][2][78] = 58,
+ [2][0][2][0][RTW89_WW][0][86] = 46,
+ [2][0][2][0][RTW89_WW][1][86] = 46,
+ [2][0][2][0][RTW89_WW][2][86] = 0,
+ [2][0][2][0][RTW89_WW][0][93] = 46,
+ [2][0][2][0][RTW89_WW][1][93] = 46,
+ [2][0][2][0][RTW89_WW][2][93] = 0,
+ [2][0][2][0][RTW89_WW][0][101] = 44,
+ [2][0][2][0][RTW89_WW][1][101] = 44,
+ [2][0][2][0][RTW89_WW][2][101] = 0,
+ [2][0][2][0][RTW89_WW][0][108] = 0,
+ [2][0][2][0][RTW89_WW][1][108] = 0,
+ [2][0][2][0][RTW89_WW][2][108] = 0,
+ [2][0][2][0][RTW89_WW][0][116] = 0,
+ [2][0][2][0][RTW89_WW][1][116] = 0,
+ [2][0][2][0][RTW89_WW][2][116] = 0,
+ [2][1][2][0][RTW89_WW][0][3] = 12,
+ [2][1][2][0][RTW89_WW][1][3] = 22,
+ [2][1][2][0][RTW89_WW][2][3] = 50,
+ [2][1][2][0][RTW89_WW][0][11] = 12,
+ [2][1][2][0][RTW89_WW][1][11] = 20,
+ [2][1][2][0][RTW89_WW][2][11] = 50,
+ [2][1][2][0][RTW89_WW][0][18] = 12,
+ [2][1][2][0][RTW89_WW][1][18] = 20,
+ [2][1][2][0][RTW89_WW][2][18] = 50,
+ [2][1][2][0][RTW89_WW][0][26] = 12,
+ [2][1][2][0][RTW89_WW][1][26] = 20,
+ [2][1][2][0][RTW89_WW][2][26] = 60,
+ [2][1][2][0][RTW89_WW][0][33] = 12,
+ [2][1][2][0][RTW89_WW][1][33] = 20,
+ [2][1][2][0][RTW89_WW][2][33] = 60,
+ [2][1][2][0][RTW89_WW][0][41] = 12,
+ [2][1][2][0][RTW89_WW][1][41] = 22,
+ [2][1][2][0][RTW89_WW][2][41] = 60,
+ [2][1][2][0][RTW89_WW][0][48] = 22,
+ [2][1][2][0][RTW89_WW][1][48] = 22,
+ [2][1][2][0][RTW89_WW][2][48] = 0,
+ [2][1][2][0][RTW89_WW][0][56] = 20,
+ [2][1][2][0][RTW89_WW][1][56] = 20,
+ [2][1][2][0][RTW89_WW][2][56] = 0,
+ [2][1][2][0][RTW89_WW][0][63] = 22,
+ [2][1][2][0][RTW89_WW][1][63] = 22,
+ [2][1][2][0][RTW89_WW][2][63] = 58,
+ [2][1][2][0][RTW89_WW][0][71] = 20,
+ [2][1][2][0][RTW89_WW][1][71] = 20,
+ [2][1][2][0][RTW89_WW][2][71] = 58,
+ [2][1][2][0][RTW89_WW][0][78] = 20,
+ [2][1][2][0][RTW89_WW][1][78] = 20,
+ [2][1][2][0][RTW89_WW][2][78] = 58,
+ [2][1][2][0][RTW89_WW][0][86] = 20,
+ [2][1][2][0][RTW89_WW][1][86] = 20,
+ [2][1][2][0][RTW89_WW][2][86] = 0,
+ [2][1][2][0][RTW89_WW][0][93] = 22,
+ [2][1][2][0][RTW89_WW][1][93] = 22,
+ [2][1][2][0][RTW89_WW][2][93] = 0,
+ [2][1][2][0][RTW89_WW][0][101] = 22,
+ [2][1][2][0][RTW89_WW][1][101] = 22,
+ [2][1][2][0][RTW89_WW][2][101] = 0,
+ [2][1][2][0][RTW89_WW][0][108] = 0,
+ [2][1][2][0][RTW89_WW][1][108] = 0,
+ [2][1][2][0][RTW89_WW][2][108] = 0,
+ [2][1][2][0][RTW89_WW][0][116] = 0,
+ [2][1][2][0][RTW89_WW][1][116] = 0,
+ [2][1][2][0][RTW89_WW][2][116] = 0,
+ [2][1][2][1][RTW89_WW][0][3] = 6,
+ [2][1][2][1][RTW89_WW][1][3] = 22,
+ [2][1][2][1][RTW89_WW][2][3] = 50,
+ [2][1][2][1][RTW89_WW][0][11] = 6,
+ [2][1][2][1][RTW89_WW][1][11] = 20,
+ [2][1][2][1][RTW89_WW][2][11] = 50,
+ [2][1][2][1][RTW89_WW][0][18] = 6,
+ [2][1][2][1][RTW89_WW][1][18] = 20,
+ [2][1][2][1][RTW89_WW][2][18] = 50,
+ [2][1][2][1][RTW89_WW][0][26] = 6,
+ [2][1][2][1][RTW89_WW][1][26] = 20,
+ [2][1][2][1][RTW89_WW][2][26] = 60,
+ [2][1][2][1][RTW89_WW][0][33] = 6,
+ [2][1][2][1][RTW89_WW][1][33] = 20,
+ [2][1][2][1][RTW89_WW][2][33] = 60,
+ [2][1][2][1][RTW89_WW][0][41] = 6,
+ [2][1][2][1][RTW89_WW][1][41] = 22,
+ [2][1][2][1][RTW89_WW][2][41] = 60,
+ [2][1][2][1][RTW89_WW][0][48] = 22,
+ [2][1][2][1][RTW89_WW][1][48] = 22,
+ [2][1][2][1][RTW89_WW][2][48] = 0,
+ [2][1][2][1][RTW89_WW][0][56] = 20,
+ [2][1][2][1][RTW89_WW][1][56] = 20,
+ [2][1][2][1][RTW89_WW][2][56] = 0,
+ [2][1][2][1][RTW89_WW][0][63] = 22,
+ [2][1][2][1][RTW89_WW][1][63] = 22,
+ [2][1][2][1][RTW89_WW][2][63] = 58,
+ [2][1][2][1][RTW89_WW][0][71] = 20,
+ [2][1][2][1][RTW89_WW][1][71] = 20,
+ [2][1][2][1][RTW89_WW][2][71] = 58,
+ [2][1][2][1][RTW89_WW][0][78] = 20,
+ [2][1][2][1][RTW89_WW][1][78] = 20,
+ [2][1][2][1][RTW89_WW][2][78] = 58,
+ [2][1][2][1][RTW89_WW][0][86] = 20,
+ [2][1][2][1][RTW89_WW][1][86] = 20,
+ [2][1][2][1][RTW89_WW][2][86] = 0,
+ [2][1][2][1][RTW89_WW][0][93] = 22,
+ [2][1][2][1][RTW89_WW][1][93] = 22,
+ [2][1][2][1][RTW89_WW][2][93] = 0,
+ [2][1][2][1][RTW89_WW][0][101] = 22,
+ [2][1][2][1][RTW89_WW][1][101] = 22,
+ [2][1][2][1][RTW89_WW][2][101] = 0,
+ [2][1][2][1][RTW89_WW][0][108] = 0,
+ [2][1][2][1][RTW89_WW][1][108] = 0,
+ [2][1][2][1][RTW89_WW][2][108] = 0,
+ [2][1][2][1][RTW89_WW][0][116] = 0,
+ [2][1][2][1][RTW89_WW][1][116] = 0,
+ [2][1][2][1][RTW89_WW][2][116] = 0,
+ [3][0][2][0][RTW89_WW][0][7] = 22,
+ [3][0][2][0][RTW89_WW][1][7] = 42,
+ [3][0][2][0][RTW89_WW][2][7] = 52,
+ [3][0][2][0][RTW89_WW][0][22] = 20,
+ [3][0][2][0][RTW89_WW][1][22] = 42,
+ [3][0][2][0][RTW89_WW][2][22] = 52,
+ [3][0][2][0][RTW89_WW][0][37] = 20,
+ [3][0][2][0][RTW89_WW][1][37] = 42,
+ [3][0][2][0][RTW89_WW][2][37] = 52,
+ [3][0][2][0][RTW89_WW][0][52] = 54,
+ [3][0][2][0][RTW89_WW][1][52] = 54,
+ [3][0][2][0][RTW89_WW][2][52] = 0,
+ [3][0][2][0][RTW89_WW][0][67] = 54,
+ [3][0][2][0][RTW89_WW][1][67] = 54,
+ [3][0][2][0][RTW89_WW][2][67] = 54,
+ [3][0][2][0][RTW89_WW][0][82] = 26,
+ [3][0][2][0][RTW89_WW][1][82] = 26,
+ [3][0][2][0][RTW89_WW][2][82] = 0,
+ [3][0][2][0][RTW89_WW][0][97] = 26,
+ [3][0][2][0][RTW89_WW][1][97] = 26,
+ [3][0][2][0][RTW89_WW][2][97] = 0,
+ [3][0][2][0][RTW89_WW][0][112] = 0,
+ [3][0][2][0][RTW89_WW][1][112] = 0,
+ [3][0][2][0][RTW89_WW][2][112] = 0,
+ [3][1][2][0][RTW89_WW][0][7] = 10,
+ [3][1][2][0][RTW89_WW][1][7] = 32,
+ [3][1][2][0][RTW89_WW][2][7] = 46,
+ [3][1][2][0][RTW89_WW][0][22] = 8,
+ [3][1][2][0][RTW89_WW][1][22] = 30,
+ [3][1][2][0][RTW89_WW][2][22] = 52,
+ [3][1][2][0][RTW89_WW][0][37] = 8,
+ [3][1][2][0][RTW89_WW][1][37] = 30,
+ [3][1][2][0][RTW89_WW][2][37] = 52,
+ [3][1][2][0][RTW89_WW][0][52] = 30,
+ [3][1][2][0][RTW89_WW][1][52] = 30,
+ [3][1][2][0][RTW89_WW][2][52] = 0,
+ [3][1][2][0][RTW89_WW][0][67] = 32,
+ [3][1][2][0][RTW89_WW][1][67] = 32,
+ [3][1][2][0][RTW89_WW][2][67] = 54,
+ [3][1][2][0][RTW89_WW][0][82] = 24,
+ [3][1][2][0][RTW89_WW][1][82] = 24,
+ [3][1][2][0][RTW89_WW][2][82] = 0,
+ [3][1][2][0][RTW89_WW][0][97] = 24,
+ [3][1][2][0][RTW89_WW][1][97] = 24,
+ [3][1][2][0][RTW89_WW][2][97] = 0,
+ [3][1][2][0][RTW89_WW][0][112] = 0,
+ [3][1][2][0][RTW89_WW][1][112] = 0,
+ [3][1][2][0][RTW89_WW][2][112] = 0,
+ [3][1][2][1][RTW89_WW][0][7] = 6,
+ [3][1][2][1][RTW89_WW][1][7] = 32,
+ [3][1][2][1][RTW89_WW][2][7] = 46,
+ [3][1][2][1][RTW89_WW][0][22] = 6,
+ [3][1][2][1][RTW89_WW][1][22] = 30,
+ [3][1][2][1][RTW89_WW][2][22] = 52,
+ [3][1][2][1][RTW89_WW][0][37] = 6,
+ [3][1][2][1][RTW89_WW][1][37] = 30,
+ [3][1][2][1][RTW89_WW][2][37] = 52,
+ [3][1][2][1][RTW89_WW][0][52] = 30,
+ [3][1][2][1][RTW89_WW][1][52] = 30,
+ [3][1][2][1][RTW89_WW][2][52] = 0,
+ [3][1][2][1][RTW89_WW][0][67] = 32,
+ [3][1][2][1][RTW89_WW][1][67] = 32,
+ [3][1][2][1][RTW89_WW][2][67] = 54,
+ [3][1][2][1][RTW89_WW][0][82] = 24,
+ [3][1][2][1][RTW89_WW][1][82] = 24,
+ [3][1][2][1][RTW89_WW][2][82] = 0,
+ [3][1][2][1][RTW89_WW][0][97] = 24,
+ [3][1][2][1][RTW89_WW][1][97] = 24,
+ [3][1][2][1][RTW89_WW][2][97] = 0,
+ [3][1][2][1][RTW89_WW][0][112] = 0,
+ [3][1][2][1][RTW89_WW][1][112] = 0,
+ [3][1][2][1][RTW89_WW][2][112] = 0,
+ [0][0][1][0][RTW89_FCC][1][0] = 24,
+ [0][0][1][0][RTW89_FCC][2][0] = 56,
+ [0][0][1][0][RTW89_ETSI][1][0] = 66,
+ [0][0][1][0][RTW89_ETSI][0][0] = 28,
+ [0][0][1][0][RTW89_MKK][1][0] = 66,
+ [0][0][1][0][RTW89_MKK][0][0] = 26,
+ [0][0][1][0][RTW89_IC][1][0] = 24,
+ [0][0][1][0][RTW89_KCC][1][0] = 24,
+ [0][0][1][0][RTW89_KCC][0][0] = 24,
+ [0][0][1][0][RTW89_ACMA][1][0] = 66,
+ [0][0][1][0][RTW89_ACMA][0][0] = 28,
+ [0][0][1][0][RTW89_CHILE][1][0] = 24,
+ [0][0][1][0][RTW89_QATAR][1][0] = 66,
+ [0][0][1][0][RTW89_QATAR][0][0] = 28,
+ [0][0][1][0][RTW89_UK][1][0] = 66,
+ [0][0][1][0][RTW89_UK][0][0] = 28,
+ [0][0][1][0][RTW89_FCC][1][2] = 22,
+ [0][0][1][0][RTW89_FCC][2][2] = 56,
+ [0][0][1][0][RTW89_ETSI][1][2] = 66,
+ [0][0][1][0][RTW89_ETSI][0][2] = 28,
+ [0][0][1][0][RTW89_MKK][1][2] = 66,
+ [0][0][1][0][RTW89_MKK][0][2] = 26,
+ [0][0][1][0][RTW89_IC][1][2] = 22,
+ [0][0][1][0][RTW89_KCC][1][2] = 24,
+ [0][0][1][0][RTW89_KCC][0][2] = 24,
+ [0][0][1][0][RTW89_ACMA][1][2] = 66,
+ [0][0][1][0][RTW89_ACMA][0][2] = 28,
+ [0][0][1][0][RTW89_CHILE][1][2] = 22,
+ [0][0][1][0][RTW89_QATAR][1][2] = 66,
+ [0][0][1][0][RTW89_QATAR][0][2] = 28,
+ [0][0][1][0][RTW89_UK][1][2] = 66,
+ [0][0][1][0][RTW89_UK][0][2] = 28,
+ [0][0][1][0][RTW89_FCC][1][4] = 22,
+ [0][0][1][0][RTW89_FCC][2][4] = 56,
+ [0][0][1][0][RTW89_ETSI][1][4] = 66,
+ [0][0][1][0][RTW89_ETSI][0][4] = 28,
+ [0][0][1][0][RTW89_MKK][1][4] = 66,
+ [0][0][1][0][RTW89_MKK][0][4] = 26,
+ [0][0][1][0][RTW89_IC][1][4] = 22,
+ [0][0][1][0][RTW89_KCC][1][4] = 24,
+ [0][0][1][0][RTW89_KCC][0][4] = 24,
+ [0][0][1][0][RTW89_ACMA][1][4] = 66,
+ [0][0][1][0][RTW89_ACMA][0][4] = 28,
+ [0][0][1][0][RTW89_CHILE][1][4] = 22,
+ [0][0][1][0][RTW89_QATAR][1][4] = 66,
+ [0][0][1][0][RTW89_QATAR][0][4] = 28,
+ [0][0][1][0][RTW89_UK][1][4] = 66,
+ [0][0][1][0][RTW89_UK][0][4] = 28,
+ [0][0][1][0][RTW89_FCC][1][6] = 22,
+ [0][0][1][0][RTW89_FCC][2][6] = 56,
+ [0][0][1][0][RTW89_ETSI][1][6] = 66,
+ [0][0][1][0][RTW89_ETSI][0][6] = 28,
+ [0][0][1][0][RTW89_MKK][1][6] = 66,
+ [0][0][1][0][RTW89_MKK][0][6] = 26,
+ [0][0][1][0][RTW89_IC][1][6] = 22,
+ [0][0][1][0][RTW89_KCC][1][6] = 24,
+ [0][0][1][0][RTW89_KCC][0][6] = 24,
+ [0][0][1][0][RTW89_ACMA][1][6] = 66,
+ [0][0][1][0][RTW89_ACMA][0][6] = 28,
+ [0][0][1][0][RTW89_CHILE][1][6] = 22,
+ [0][0][1][0][RTW89_QATAR][1][6] = 66,
+ [0][0][1][0][RTW89_QATAR][0][6] = 28,
+ [0][0][1][0][RTW89_UK][1][6] = 66,
+ [0][0][1][0][RTW89_UK][0][6] = 28,
+ [0][0][1][0][RTW89_FCC][1][8] = 22,
+ [0][0][1][0][RTW89_FCC][2][8] = 56,
+ [0][0][1][0][RTW89_ETSI][1][8] = 66,
+ [0][0][1][0][RTW89_ETSI][0][8] = 28,
+ [0][0][1][0][RTW89_MKK][1][8] = 66,
+ [0][0][1][0][RTW89_MKK][0][8] = 26,
+ [0][0][1][0][RTW89_IC][1][8] = 22,
+ [0][0][1][0][RTW89_KCC][1][8] = 24,
+ [0][0][1][0][RTW89_KCC][0][8] = 24,
+ [0][0][1][0][RTW89_ACMA][1][8] = 66,
+ [0][0][1][0][RTW89_ACMA][0][8] = 28,
+ [0][0][1][0][RTW89_CHILE][1][8] = 22,
+ [0][0][1][0][RTW89_QATAR][1][8] = 66,
+ [0][0][1][0][RTW89_QATAR][0][8] = 28,
+ [0][0][1][0][RTW89_UK][1][8] = 66,
+ [0][0][1][0][RTW89_UK][0][8] = 28,
+ [0][0][1][0][RTW89_FCC][1][10] = 22,
+ [0][0][1][0][RTW89_FCC][2][10] = 56,
+ [0][0][1][0][RTW89_ETSI][1][10] = 66,
+ [0][0][1][0][RTW89_ETSI][0][10] = 28,
+ [0][0][1][0][RTW89_MKK][1][10] = 66,
+ [0][0][1][0][RTW89_MKK][0][10] = 26,
+ [0][0][1][0][RTW89_IC][1][10] = 22,
+ [0][0][1][0][RTW89_KCC][1][10] = 24,
+ [0][0][1][0][RTW89_KCC][0][10] = 24,
+ [0][0][1][0][RTW89_ACMA][1][10] = 66,
+ [0][0][1][0][RTW89_ACMA][0][10] = 28,
+ [0][0][1][0][RTW89_CHILE][1][10] = 22,
+ [0][0][1][0][RTW89_QATAR][1][10] = 66,
+ [0][0][1][0][RTW89_QATAR][0][10] = 28,
+ [0][0][1][0][RTW89_UK][1][10] = 66,
+ [0][0][1][0][RTW89_UK][0][10] = 28,
+ [0][0][1][0][RTW89_FCC][1][12] = 22,
+ [0][0][1][0][RTW89_FCC][2][12] = 56,
+ [0][0][1][0][RTW89_ETSI][1][12] = 66,
+ [0][0][1][0][RTW89_ETSI][0][12] = 28,
+ [0][0][1][0][RTW89_MKK][1][12] = 66,
+ [0][0][1][0][RTW89_MKK][0][12] = 26,
+ [0][0][1][0][RTW89_IC][1][12] = 22,
+ [0][0][1][0][RTW89_KCC][1][12] = 24,
+ [0][0][1][0][RTW89_KCC][0][12] = 24,
+ [0][0][1][0][RTW89_ACMA][1][12] = 66,
+ [0][0][1][0][RTW89_ACMA][0][12] = 28,
+ [0][0][1][0][RTW89_CHILE][1][12] = 22,
+ [0][0][1][0][RTW89_QATAR][1][12] = 66,
+ [0][0][1][0][RTW89_QATAR][0][12] = 28,
+ [0][0][1][0][RTW89_UK][1][12] = 66,
+ [0][0][1][0][RTW89_UK][0][12] = 28,
+ [0][0][1][0][RTW89_FCC][1][14] = 22,
+ [0][0][1][0][RTW89_FCC][2][14] = 56,
+ [0][0][1][0][RTW89_ETSI][1][14] = 66,
+ [0][0][1][0][RTW89_ETSI][0][14] = 28,
+ [0][0][1][0][RTW89_MKK][1][14] = 66,
+ [0][0][1][0][RTW89_MKK][0][14] = 26,
+ [0][0][1][0][RTW89_IC][1][14] = 22,
+ [0][0][1][0][RTW89_KCC][1][14] = 24,
+ [0][0][1][0][RTW89_KCC][0][14] = 24,
+ [0][0][1][0][RTW89_ACMA][1][14] = 66,
+ [0][0][1][0][RTW89_ACMA][0][14] = 28,
+ [0][0][1][0][RTW89_CHILE][1][14] = 22,
+ [0][0][1][0][RTW89_QATAR][1][14] = 66,
+ [0][0][1][0][RTW89_QATAR][0][14] = 28,
+ [0][0][1][0][RTW89_UK][1][14] = 66,
+ [0][0][1][0][RTW89_UK][0][14] = 28,
+ [0][0][1][0][RTW89_FCC][1][15] = 22,
+ [0][0][1][0][RTW89_FCC][2][15] = 56,
+ [0][0][1][0][RTW89_ETSI][1][15] = 66,
+ [0][0][1][0][RTW89_ETSI][0][15] = 28,
+ [0][0][1][0][RTW89_MKK][1][15] = 66,
+ [0][0][1][0][RTW89_MKK][0][15] = 26,
+ [0][0][1][0][RTW89_IC][1][15] = 22,
+ [0][0][1][0][RTW89_KCC][1][15] = 24,
+ [0][0][1][0][RTW89_KCC][0][15] = 24,
+ [0][0][1][0][RTW89_ACMA][1][15] = 66,
+ [0][0][1][0][RTW89_ACMA][0][15] = 28,
+ [0][0][1][0][RTW89_CHILE][1][15] = 22,
+ [0][0][1][0][RTW89_QATAR][1][15] = 66,
+ [0][0][1][0][RTW89_QATAR][0][15] = 28,
+ [0][0][1][0][RTW89_UK][1][15] = 66,
+ [0][0][1][0][RTW89_UK][0][15] = 28,
+ [0][0][1][0][RTW89_FCC][1][17] = 22,
+ [0][0][1][0][RTW89_FCC][2][17] = 56,
+ [0][0][1][0][RTW89_ETSI][1][17] = 66,
+ [0][0][1][0][RTW89_ETSI][0][17] = 28,
+ [0][0][1][0][RTW89_MKK][1][17] = 66,
+ [0][0][1][0][RTW89_MKK][0][17] = 26,
+ [0][0][1][0][RTW89_IC][1][17] = 22,
+ [0][0][1][0][RTW89_KCC][1][17] = 24,
+ [0][0][1][0][RTW89_KCC][0][17] = 24,
+ [0][0][1][0][RTW89_ACMA][1][17] = 66,
+ [0][0][1][0][RTW89_ACMA][0][17] = 28,
+ [0][0][1][0][RTW89_CHILE][1][17] = 22,
+ [0][0][1][0][RTW89_QATAR][1][17] = 66,
+ [0][0][1][0][RTW89_QATAR][0][17] = 28,
+ [0][0][1][0][RTW89_UK][1][17] = 66,
+ [0][0][1][0][RTW89_UK][0][17] = 28,
+ [0][0][1][0][RTW89_FCC][1][19] = 22,
+ [0][0][1][0][RTW89_FCC][2][19] = 56,
+ [0][0][1][0][RTW89_ETSI][1][19] = 66,
+ [0][0][1][0][RTW89_ETSI][0][19] = 28,
+ [0][0][1][0][RTW89_MKK][1][19] = 66,
+ [0][0][1][0][RTW89_MKK][0][19] = 26,
+ [0][0][1][0][RTW89_IC][1][19] = 22,
+ [0][0][1][0][RTW89_KCC][1][19] = 24,
+ [0][0][1][0][RTW89_KCC][0][19] = 24,
+ [0][0][1][0][RTW89_ACMA][1][19] = 66,
+ [0][0][1][0][RTW89_ACMA][0][19] = 28,
+ [0][0][1][0][RTW89_CHILE][1][19] = 22,
+ [0][0][1][0][RTW89_QATAR][1][19] = 66,
+ [0][0][1][0][RTW89_QATAR][0][19] = 28,
+ [0][0][1][0][RTW89_UK][1][19] = 66,
+ [0][0][1][0][RTW89_UK][0][19] = 28,
+ [0][0][1][0][RTW89_FCC][1][21] = 22,
+ [0][0][1][0][RTW89_FCC][2][21] = 56,
+ [0][0][1][0][RTW89_ETSI][1][21] = 66,
+ [0][0][1][0][RTW89_ETSI][0][21] = 28,
+ [0][0][1][0][RTW89_MKK][1][21] = 66,
+ [0][0][1][0][RTW89_MKK][0][21] = 26,
+ [0][0][1][0][RTW89_IC][1][21] = 22,
+ [0][0][1][0][RTW89_KCC][1][21] = 24,
+ [0][0][1][0][RTW89_KCC][0][21] = 24,
+ [0][0][1][0][RTW89_ACMA][1][21] = 66,
+ [0][0][1][0][RTW89_ACMA][0][21] = 28,
+ [0][0][1][0][RTW89_CHILE][1][21] = 22,
+ [0][0][1][0][RTW89_QATAR][1][21] = 66,
+ [0][0][1][0][RTW89_QATAR][0][21] = 28,
+ [0][0][1][0][RTW89_UK][1][21] = 66,
+ [0][0][1][0][RTW89_UK][0][21] = 28,
+ [0][0][1][0][RTW89_FCC][1][23] = 22,
+ [0][0][1][0][RTW89_FCC][2][23] = 70,
+ [0][0][1][0][RTW89_ETSI][1][23] = 66,
+ [0][0][1][0][RTW89_ETSI][0][23] = 28,
+ [0][0][1][0][RTW89_MKK][1][23] = 66,
+ [0][0][1][0][RTW89_MKK][0][23] = 26,
+ [0][0][1][0][RTW89_IC][1][23] = 22,
+ [0][0][1][0][RTW89_KCC][1][23] = 24,
+ [0][0][1][0][RTW89_KCC][0][23] = 26,
+ [0][0][1][0][RTW89_ACMA][1][23] = 66,
+ [0][0][1][0][RTW89_ACMA][0][23] = 28,
+ [0][0][1][0][RTW89_CHILE][1][23] = 22,
+ [0][0][1][0][RTW89_QATAR][1][23] = 66,
+ [0][0][1][0][RTW89_QATAR][0][23] = 28,
+ [0][0][1][0][RTW89_UK][1][23] = 66,
+ [0][0][1][0][RTW89_UK][0][23] = 28,
+ [0][0][1][0][RTW89_FCC][1][25] = 22,
+ [0][0][1][0][RTW89_FCC][2][25] = 70,
+ [0][0][1][0][RTW89_ETSI][1][25] = 66,
+ [0][0][1][0][RTW89_ETSI][0][25] = 28,
+ [0][0][1][0][RTW89_MKK][1][25] = 66,
+ [0][0][1][0][RTW89_MKK][0][25] = 26,
+ [0][0][1][0][RTW89_IC][1][25] = 22,
+ [0][0][1][0][RTW89_KCC][1][25] = 24,
+ [0][0][1][0][RTW89_KCC][0][25] = 26,
+ [0][0][1][0][RTW89_ACMA][1][25] = 66,
+ [0][0][1][0][RTW89_ACMA][0][25] = 28,
+ [0][0][1][0][RTW89_CHILE][1][25] = 22,
+ [0][0][1][0][RTW89_QATAR][1][25] = 66,
+ [0][0][1][0][RTW89_QATAR][0][25] = 28,
+ [0][0][1][0][RTW89_UK][1][25] = 66,
+ [0][0][1][0][RTW89_UK][0][25] = 28,
+ [0][0][1][0][RTW89_FCC][1][27] = 22,
+ [0][0][1][0][RTW89_FCC][2][27] = 70,
+ [0][0][1][0][RTW89_ETSI][1][27] = 66,
+ [0][0][1][0][RTW89_ETSI][0][27] = 28,
+ [0][0][1][0][RTW89_MKK][1][27] = 66,
+ [0][0][1][0][RTW89_MKK][0][27] = 26,
+ [0][0][1][0][RTW89_IC][1][27] = 22,
+ [0][0][1][0][RTW89_KCC][1][27] = 24,
+ [0][0][1][0][RTW89_KCC][0][27] = 26,
+ [0][0][1][0][RTW89_ACMA][1][27] = 66,
+ [0][0][1][0][RTW89_ACMA][0][27] = 28,
+ [0][0][1][0][RTW89_CHILE][1][27] = 22,
+ [0][0][1][0][RTW89_QATAR][1][27] = 66,
+ [0][0][1][0][RTW89_QATAR][0][27] = 28,
+ [0][0][1][0][RTW89_UK][1][27] = 66,
+ [0][0][1][0][RTW89_UK][0][27] = 28,
+ [0][0][1][0][RTW89_FCC][1][29] = 22,
+ [0][0][1][0][RTW89_FCC][2][29] = 70,
+ [0][0][1][0][RTW89_ETSI][1][29] = 66,
+ [0][0][1][0][RTW89_ETSI][0][29] = 28,
+ [0][0][1][0][RTW89_MKK][1][29] = 66,
+ [0][0][1][0][RTW89_MKK][0][29] = 26,
+ [0][0][1][0][RTW89_IC][1][29] = 22,
+ [0][0][1][0][RTW89_KCC][1][29] = 24,
+ [0][0][1][0][RTW89_KCC][0][29] = 26,
+ [0][0][1][0][RTW89_ACMA][1][29] = 66,
+ [0][0][1][0][RTW89_ACMA][0][29] = 28,
+ [0][0][1][0][RTW89_CHILE][1][29] = 22,
+ [0][0][1][0][RTW89_QATAR][1][29] = 66,
+ [0][0][1][0][RTW89_QATAR][0][29] = 28,
+ [0][0][1][0][RTW89_UK][1][29] = 66,
+ [0][0][1][0][RTW89_UK][0][29] = 28,
+ [0][0][1][0][RTW89_FCC][1][30] = 22,
+ [0][0][1][0][RTW89_FCC][2][30] = 70,
+ [0][0][1][0][RTW89_ETSI][1][30] = 66,
+ [0][0][1][0][RTW89_ETSI][0][30] = 28,
+ [0][0][1][0][RTW89_MKK][1][30] = 66,
+ [0][0][1][0][RTW89_MKK][0][30] = 26,
+ [0][0][1][0][RTW89_IC][1][30] = 22,
+ [0][0][1][0][RTW89_KCC][1][30] = 24,
+ [0][0][1][0][RTW89_KCC][0][30] = 26,
+ [0][0][1][0][RTW89_ACMA][1][30] = 66,
+ [0][0][1][0][RTW89_ACMA][0][30] = 28,
+ [0][0][1][0][RTW89_CHILE][1][30] = 22,
+ [0][0][1][0][RTW89_QATAR][1][30] = 66,
+ [0][0][1][0][RTW89_QATAR][0][30] = 28,
+ [0][0][1][0][RTW89_UK][1][30] = 66,
+ [0][0][1][0][RTW89_UK][0][30] = 28,
+ [0][0][1][0][RTW89_FCC][1][32] = 22,
+ [0][0][1][0][RTW89_FCC][2][32] = 70,
+ [0][0][1][0][RTW89_ETSI][1][32] = 66,
+ [0][0][1][0][RTW89_ETSI][0][32] = 28,
+ [0][0][1][0][RTW89_MKK][1][32] = 66,
+ [0][0][1][0][RTW89_MKK][0][32] = 26,
+ [0][0][1][0][RTW89_IC][1][32] = 22,
+ [0][0][1][0][RTW89_KCC][1][32] = 24,
+ [0][0][1][0][RTW89_KCC][0][32] = 26,
+ [0][0][1][0][RTW89_ACMA][1][32] = 66,
+ [0][0][1][0][RTW89_ACMA][0][32] = 28,
+ [0][0][1][0][RTW89_CHILE][1][32] = 22,
+ [0][0][1][0][RTW89_QATAR][1][32] = 66,
+ [0][0][1][0][RTW89_QATAR][0][32] = 28,
+ [0][0][1][0][RTW89_UK][1][32] = 66,
+ [0][0][1][0][RTW89_UK][0][32] = 28,
+ [0][0][1][0][RTW89_FCC][1][34] = 22,
+ [0][0][1][0][RTW89_FCC][2][34] = 70,
+ [0][0][1][0][RTW89_ETSI][1][34] = 66,
+ [0][0][1][0][RTW89_ETSI][0][34] = 28,
+ [0][0][1][0][RTW89_MKK][1][34] = 66,
+ [0][0][1][0][RTW89_MKK][0][34] = 26,
+ [0][0][1][0][RTW89_IC][1][34] = 22,
+ [0][0][1][0][RTW89_KCC][1][34] = 24,
+ [0][0][1][0][RTW89_KCC][0][34] = 26,
+ [0][0][1][0][RTW89_ACMA][1][34] = 66,
+ [0][0][1][0][RTW89_ACMA][0][34] = 28,
+ [0][0][1][0][RTW89_CHILE][1][34] = 22,
+ [0][0][1][0][RTW89_QATAR][1][34] = 66,
+ [0][0][1][0][RTW89_QATAR][0][34] = 28,
+ [0][0][1][0][RTW89_UK][1][34] = 66,
+ [0][0][1][0][RTW89_UK][0][34] = 28,
+ [0][0][1][0][RTW89_FCC][1][36] = 22,
+ [0][0][1][0][RTW89_FCC][2][36] = 70,
+ [0][0][1][0][RTW89_ETSI][1][36] = 66,
+ [0][0][1][0][RTW89_ETSI][0][36] = 28,
+ [0][0][1][0][RTW89_MKK][1][36] = 66,
+ [0][0][1][0][RTW89_MKK][0][36] = 26,
+ [0][0][1][0][RTW89_IC][1][36] = 22,
+ [0][0][1][0][RTW89_KCC][1][36] = 24,
+ [0][0][1][0][RTW89_KCC][0][36] = 26,
+ [0][0][1][0][RTW89_ACMA][1][36] = 66,
+ [0][0][1][0][RTW89_ACMA][0][36] = 28,
+ [0][0][1][0][RTW89_CHILE][1][36] = 22,
+ [0][0][1][0][RTW89_QATAR][1][36] = 66,
+ [0][0][1][0][RTW89_QATAR][0][36] = 28,
+ [0][0][1][0][RTW89_UK][1][36] = 66,
+ [0][0][1][0][RTW89_UK][0][36] = 28,
+ [0][0][1][0][RTW89_FCC][1][38] = 22,
+ [0][0][1][0][RTW89_FCC][2][38] = 70,
+ [0][0][1][0][RTW89_ETSI][1][38] = 66,
+ [0][0][1][0][RTW89_ETSI][0][38] = 28,
+ [0][0][1][0][RTW89_MKK][1][38] = 66,
+ [0][0][1][0][RTW89_MKK][0][38] = 26,
+ [0][0][1][0][RTW89_IC][1][38] = 22,
+ [0][0][1][0][RTW89_KCC][1][38] = 24,
+ [0][0][1][0][RTW89_KCC][0][38] = 26,
+ [0][0][1][0][RTW89_ACMA][1][38] = 66,
+ [0][0][1][0][RTW89_ACMA][0][38] = 28,
+ [0][0][1][0][RTW89_CHILE][1][38] = 22,
+ [0][0][1][0][RTW89_QATAR][1][38] = 66,
+ [0][0][1][0][RTW89_QATAR][0][38] = 28,
+ [0][0][1][0][RTW89_UK][1][38] = 66,
+ [0][0][1][0][RTW89_UK][0][38] = 28,
+ [0][0][1][0][RTW89_FCC][1][40] = 22,
+ [0][0][1][0][RTW89_FCC][2][40] = 70,
+ [0][0][1][0][RTW89_ETSI][1][40] = 66,
+ [0][0][1][0][RTW89_ETSI][0][40] = 28,
+ [0][0][1][0][RTW89_MKK][1][40] = 66,
+ [0][0][1][0][RTW89_MKK][0][40] = 26,
+ [0][0][1][0][RTW89_IC][1][40] = 22,
+ [0][0][1][0][RTW89_KCC][1][40] = 24,
+ [0][0][1][0][RTW89_KCC][0][40] = 26,
+ [0][0][1][0][RTW89_ACMA][1][40] = 66,
+ [0][0][1][0][RTW89_ACMA][0][40] = 28,
+ [0][0][1][0][RTW89_CHILE][1][40] = 22,
+ [0][0][1][0][RTW89_QATAR][1][40] = 66,
+ [0][0][1][0][RTW89_QATAR][0][40] = 28,
+ [0][0][1][0][RTW89_UK][1][40] = 66,
+ [0][0][1][0][RTW89_UK][0][40] = 28,
+ [0][0][1][0][RTW89_FCC][1][42] = 22,
+ [0][0][1][0][RTW89_FCC][2][42] = 70,
+ [0][0][1][0][RTW89_ETSI][1][42] = 66,
+ [0][0][1][0][RTW89_ETSI][0][42] = 28,
+ [0][0][1][0][RTW89_MKK][1][42] = 66,
+ [0][0][1][0][RTW89_MKK][0][42] = 26,
+ [0][0][1][0][RTW89_IC][1][42] = 22,
+ [0][0][1][0][RTW89_KCC][1][42] = 24,
+ [0][0][1][0][RTW89_KCC][0][42] = 26,
+ [0][0][1][0][RTW89_ACMA][1][42] = 66,
+ [0][0][1][0][RTW89_ACMA][0][42] = 28,
+ [0][0][1][0][RTW89_CHILE][1][42] = 22,
+ [0][0][1][0][RTW89_QATAR][1][42] = 66,
+ [0][0][1][0][RTW89_QATAR][0][42] = 28,
+ [0][0][1][0][RTW89_UK][1][42] = 66,
+ [0][0][1][0][RTW89_UK][0][42] = 28,
+ [0][0][1][0][RTW89_FCC][1][44] = 22,
+ [0][0][1][0][RTW89_FCC][2][44] = 70,
+ [0][0][1][0][RTW89_ETSI][1][44] = 66,
+ [0][0][1][0][RTW89_ETSI][0][44] = 30,
+ [0][0][1][0][RTW89_MKK][1][44] = 44,
+ [0][0][1][0][RTW89_MKK][0][44] = 28,
+ [0][0][1][0][RTW89_IC][1][44] = 22,
+ [0][0][1][0][RTW89_KCC][1][44] = 24,
+ [0][0][1][0][RTW89_KCC][0][44] = 26,
+ [0][0][1][0][RTW89_ACMA][1][44] = 66,
+ [0][0][1][0][RTW89_ACMA][0][44] = 30,
+ [0][0][1][0][RTW89_CHILE][1][44] = 22,
+ [0][0][1][0][RTW89_QATAR][1][44] = 66,
+ [0][0][1][0][RTW89_QATAR][0][44] = 30,
+ [0][0][1][0][RTW89_UK][1][44] = 66,
+ [0][0][1][0][RTW89_UK][0][44] = 30,
+ [0][0][1][0][RTW89_FCC][1][45] = 22,
+ [0][0][1][0][RTW89_FCC][2][45] = 127,
+ [0][0][1][0][RTW89_ETSI][1][45] = 127,
+ [0][0][1][0][RTW89_ETSI][0][45] = 127,
+ [0][0][1][0][RTW89_MKK][1][45] = 127,
+ [0][0][1][0][RTW89_MKK][0][45] = 127,
+ [0][0][1][0][RTW89_IC][1][45] = 22,
+ [0][0][1][0][RTW89_KCC][1][45] = 24,
+ [0][0][1][0][RTW89_KCC][0][45] = 127,
+ [0][0][1][0][RTW89_ACMA][1][45] = 127,
+ [0][0][1][0][RTW89_ACMA][0][45] = 127,
+ [0][0][1][0][RTW89_CHILE][1][45] = 22,
+ [0][0][1][0][RTW89_QATAR][1][45] = 127,
+ [0][0][1][0][RTW89_QATAR][0][45] = 127,
+ [0][0][1][0][RTW89_UK][1][45] = 127,
+ [0][0][1][0][RTW89_UK][0][45] = 127,
+ [0][0][1][0][RTW89_FCC][1][47] = 22,
+ [0][0][1][0][RTW89_FCC][2][47] = 127,
+ [0][0][1][0][RTW89_ETSI][1][47] = 127,
+ [0][0][1][0][RTW89_ETSI][0][47] = 127,
+ [0][0][1][0][RTW89_MKK][1][47] = 127,
+ [0][0][1][0][RTW89_MKK][0][47] = 127,
+ [0][0][1][0][RTW89_IC][1][47] = 22,
+ [0][0][1][0][RTW89_KCC][1][47] = 24,
+ [0][0][1][0][RTW89_KCC][0][47] = 127,
+ [0][0][1][0][RTW89_ACMA][1][47] = 127,
+ [0][0][1][0][RTW89_ACMA][0][47] = 127,
+ [0][0][1][0][RTW89_CHILE][1][47] = 22,
+ [0][0][1][0][RTW89_QATAR][1][47] = 127,
+ [0][0][1][0][RTW89_QATAR][0][47] = 127,
+ [0][0][1][0][RTW89_UK][1][47] = 127,
+ [0][0][1][0][RTW89_UK][0][47] = 127,
+ [0][0][1][0][RTW89_FCC][1][49] = 24,
+ [0][0][1][0][RTW89_FCC][2][49] = 127,
+ [0][0][1][0][RTW89_ETSI][1][49] = 127,
+ [0][0][1][0][RTW89_ETSI][0][49] = 127,
+ [0][0][1][0][RTW89_MKK][1][49] = 127,
+ [0][0][1][0][RTW89_MKK][0][49] = 127,
+ [0][0][1][0][RTW89_IC][1][49] = 24,
+ [0][0][1][0][RTW89_KCC][1][49] = 24,
+ [0][0][1][0][RTW89_KCC][0][49] = 127,
+ [0][0][1][0][RTW89_ACMA][1][49] = 127,
+ [0][0][1][0][RTW89_ACMA][0][49] = 127,
+ [0][0][1][0][RTW89_CHILE][1][49] = 24,
+ [0][0][1][0][RTW89_QATAR][1][49] = 127,
+ [0][0][1][0][RTW89_QATAR][0][49] = 127,
+ [0][0][1][0][RTW89_UK][1][49] = 127,
+ [0][0][1][0][RTW89_UK][0][49] = 127,
+ [0][0][1][0][RTW89_FCC][1][51] = 22,
+ [0][0][1][0][RTW89_FCC][2][51] = 127,
+ [0][0][1][0][RTW89_ETSI][1][51] = 127,
+ [0][0][1][0][RTW89_ETSI][0][51] = 127,
+ [0][0][1][0][RTW89_MKK][1][51] = 127,
+ [0][0][1][0][RTW89_MKK][0][51] = 127,
+ [0][0][1][0][RTW89_IC][1][51] = 22,
+ [0][0][1][0][RTW89_KCC][1][51] = 24,
+ [0][0][1][0][RTW89_KCC][0][51] = 127,
+ [0][0][1][0][RTW89_ACMA][1][51] = 127,
+ [0][0][1][0][RTW89_ACMA][0][51] = 127,
+ [0][0][1][0][RTW89_CHILE][1][51] = 22,
+ [0][0][1][0][RTW89_QATAR][1][51] = 127,
+ [0][0][1][0][RTW89_QATAR][0][51] = 127,
+ [0][0][1][0][RTW89_UK][1][51] = 127,
+ [0][0][1][0][RTW89_UK][0][51] = 127,
+ [0][0][1][0][RTW89_FCC][1][53] = 22,
+ [0][0][1][0][RTW89_FCC][2][53] = 127,
+ [0][0][1][0][RTW89_ETSI][1][53] = 127,
+ [0][0][1][0][RTW89_ETSI][0][53] = 127,
+ [0][0][1][0][RTW89_MKK][1][53] = 127,
+ [0][0][1][0][RTW89_MKK][0][53] = 127,
+ [0][0][1][0][RTW89_IC][1][53] = 22,
+ [0][0][1][0][RTW89_KCC][1][53] = 24,
+ [0][0][1][0][RTW89_KCC][0][53] = 127,
+ [0][0][1][0][RTW89_ACMA][1][53] = 127,
+ [0][0][1][0][RTW89_ACMA][0][53] = 127,
+ [0][0][1][0][RTW89_CHILE][1][53] = 22,
+ [0][0][1][0][RTW89_QATAR][1][53] = 127,
+ [0][0][1][0][RTW89_QATAR][0][53] = 127,
+ [0][0][1][0][RTW89_UK][1][53] = 127,
+ [0][0][1][0][RTW89_UK][0][53] = 127,
+ [0][0][1][0][RTW89_FCC][1][55] = 22,
+ [0][0][1][0][RTW89_FCC][2][55] = 68,
+ [0][0][1][0][RTW89_ETSI][1][55] = 127,
+ [0][0][1][0][RTW89_ETSI][0][55] = 127,
+ [0][0][1][0][RTW89_MKK][1][55] = 127,
+ [0][0][1][0][RTW89_MKK][0][55] = 127,
+ [0][0][1][0][RTW89_IC][1][55] = 22,
+ [0][0][1][0][RTW89_KCC][1][55] = 26,
+ [0][0][1][0][RTW89_KCC][0][55] = 127,
+ [0][0][1][0][RTW89_ACMA][1][55] = 127,
+ [0][0][1][0][RTW89_ACMA][0][55] = 127,
+ [0][0][1][0][RTW89_CHILE][1][55] = 22,
+ [0][0][1][0][RTW89_QATAR][1][55] = 127,
+ [0][0][1][0][RTW89_QATAR][0][55] = 127,
+ [0][0][1][0][RTW89_UK][1][55] = 127,
+ [0][0][1][0][RTW89_UK][0][55] = 127,
+ [0][0][1][0][RTW89_FCC][1][57] = 22,
+ [0][0][1][0][RTW89_FCC][2][57] = 68,
+ [0][0][1][0][RTW89_ETSI][1][57] = 127,
+ [0][0][1][0][RTW89_ETSI][0][57] = 127,
+ [0][0][1][0][RTW89_MKK][1][57] = 127,
+ [0][0][1][0][RTW89_MKK][0][57] = 127,
+ [0][0][1][0][RTW89_IC][1][57] = 22,
+ [0][0][1][0][RTW89_KCC][1][57] = 26,
+ [0][0][1][0][RTW89_KCC][0][57] = 127,
+ [0][0][1][0][RTW89_ACMA][1][57] = 127,
+ [0][0][1][0][RTW89_ACMA][0][57] = 127,
+ [0][0][1][0][RTW89_CHILE][1][57] = 22,
+ [0][0][1][0][RTW89_QATAR][1][57] = 127,
+ [0][0][1][0][RTW89_QATAR][0][57] = 127,
+ [0][0][1][0][RTW89_UK][1][57] = 127,
+ [0][0][1][0][RTW89_UK][0][57] = 127,
+ [0][0][1][0][RTW89_FCC][1][59] = 22,
+ [0][0][1][0][RTW89_FCC][2][59] = 68,
+ [0][0][1][0][RTW89_ETSI][1][59] = 127,
+ [0][0][1][0][RTW89_ETSI][0][59] = 127,
+ [0][0][1][0][RTW89_MKK][1][59] = 127,
+ [0][0][1][0][RTW89_MKK][0][59] = 127,
+ [0][0][1][0][RTW89_IC][1][59] = 22,
+ [0][0][1][0][RTW89_KCC][1][59] = 26,
+ [0][0][1][0][RTW89_KCC][0][59] = 127,
+ [0][0][1][0][RTW89_ACMA][1][59] = 127,
+ [0][0][1][0][RTW89_ACMA][0][59] = 127,
+ [0][0][1][0][RTW89_CHILE][1][59] = 22,
+ [0][0][1][0][RTW89_QATAR][1][59] = 127,
+ [0][0][1][0][RTW89_QATAR][0][59] = 127,
+ [0][0][1][0][RTW89_UK][1][59] = 127,
+ [0][0][1][0][RTW89_UK][0][59] = 127,
+ [0][0][1][0][RTW89_FCC][1][60] = 22,
+ [0][0][1][0][RTW89_FCC][2][60] = 68,
+ [0][0][1][0][RTW89_ETSI][1][60] = 127,
+ [0][0][1][0][RTW89_ETSI][0][60] = 127,
+ [0][0][1][0][RTW89_MKK][1][60] = 127,
+ [0][0][1][0][RTW89_MKK][0][60] = 127,
+ [0][0][1][0][RTW89_IC][1][60] = 22,
+ [0][0][1][0][RTW89_KCC][1][60] = 26,
+ [0][0][1][0][RTW89_KCC][0][60] = 127,
+ [0][0][1][0][RTW89_ACMA][1][60] = 127,
+ [0][0][1][0][RTW89_ACMA][0][60] = 127,
+ [0][0][1][0][RTW89_CHILE][1][60] = 22,
+ [0][0][1][0][RTW89_QATAR][1][60] = 127,
+ [0][0][1][0][RTW89_QATAR][0][60] = 127,
+ [0][0][1][0][RTW89_UK][1][60] = 127,
+ [0][0][1][0][RTW89_UK][0][60] = 127,
+ [0][0][1][0][RTW89_FCC][1][62] = 22,
+ [0][0][1][0][RTW89_FCC][2][62] = 68,
+ [0][0][1][0][RTW89_ETSI][1][62] = 127,
+ [0][0][1][0][RTW89_ETSI][0][62] = 127,
+ [0][0][1][0][RTW89_MKK][1][62] = 127,
+ [0][0][1][0][RTW89_MKK][0][62] = 127,
+ [0][0][1][0][RTW89_IC][1][62] = 22,
+ [0][0][1][0][RTW89_KCC][1][62] = 26,
+ [0][0][1][0][RTW89_KCC][0][62] = 127,
+ [0][0][1][0][RTW89_ACMA][1][62] = 127,
+ [0][0][1][0][RTW89_ACMA][0][62] = 127,
+ [0][0][1][0][RTW89_CHILE][1][62] = 22,
+ [0][0][1][0][RTW89_QATAR][1][62] = 127,
+ [0][0][1][0][RTW89_QATAR][0][62] = 127,
+ [0][0][1][0][RTW89_UK][1][62] = 127,
+ [0][0][1][0][RTW89_UK][0][62] = 127,
+ [0][0][1][0][RTW89_FCC][1][64] = 22,
+ [0][0][1][0][RTW89_FCC][2][64] = 68,
+ [0][0][1][0][RTW89_ETSI][1][64] = 127,
+ [0][0][1][0][RTW89_ETSI][0][64] = 127,
+ [0][0][1][0][RTW89_MKK][1][64] = 127,
+ [0][0][1][0][RTW89_MKK][0][64] = 127,
+ [0][0][1][0][RTW89_IC][1][64] = 22,
+ [0][0][1][0][RTW89_KCC][1][64] = 26,
+ [0][0][1][0][RTW89_KCC][0][64] = 127,
+ [0][0][1][0][RTW89_ACMA][1][64] = 127,
+ [0][0][1][0][RTW89_ACMA][0][64] = 127,
+ [0][0][1][0][RTW89_CHILE][1][64] = 22,
+ [0][0][1][0][RTW89_QATAR][1][64] = 127,
+ [0][0][1][0][RTW89_QATAR][0][64] = 127,
+ [0][0][1][0][RTW89_UK][1][64] = 127,
+ [0][0][1][0][RTW89_UK][0][64] = 127,
+ [0][0][1][0][RTW89_FCC][1][66] = 22,
+ [0][0][1][0][RTW89_FCC][2][66] = 68,
+ [0][0][1][0][RTW89_ETSI][1][66] = 127,
+ [0][0][1][0][RTW89_ETSI][0][66] = 127,
+ [0][0][1][0][RTW89_MKK][1][66] = 127,
+ [0][0][1][0][RTW89_MKK][0][66] = 127,
+ [0][0][1][0][RTW89_IC][1][66] = 22,
+ [0][0][1][0][RTW89_KCC][1][66] = 26,
+ [0][0][1][0][RTW89_KCC][0][66] = 127,
+ [0][0][1][0][RTW89_ACMA][1][66] = 127,
+ [0][0][1][0][RTW89_ACMA][0][66] = 127,
+ [0][0][1][0][RTW89_CHILE][1][66] = 22,
+ [0][0][1][0][RTW89_QATAR][1][66] = 127,
+ [0][0][1][0][RTW89_QATAR][0][66] = 127,
+ [0][0][1][0][RTW89_UK][1][66] = 127,
+ [0][0][1][0][RTW89_UK][0][66] = 127,
+ [0][0][1][0][RTW89_FCC][1][68] = 22,
+ [0][0][1][0][RTW89_FCC][2][68] = 68,
+ [0][0][1][0][RTW89_ETSI][1][68] = 127,
+ [0][0][1][0][RTW89_ETSI][0][68] = 127,
+ [0][0][1][0][RTW89_MKK][1][68] = 127,
+ [0][0][1][0][RTW89_MKK][0][68] = 127,
+ [0][0][1][0][RTW89_IC][1][68] = 22,
+ [0][0][1][0][RTW89_KCC][1][68] = 26,
+ [0][0][1][0][RTW89_KCC][0][68] = 127,
+ [0][0][1][0][RTW89_ACMA][1][68] = 127,
+ [0][0][1][0][RTW89_ACMA][0][68] = 127,
+ [0][0][1][0][RTW89_CHILE][1][68] = 22,
+ [0][0][1][0][RTW89_QATAR][1][68] = 127,
+ [0][0][1][0][RTW89_QATAR][0][68] = 127,
+ [0][0][1][0][RTW89_UK][1][68] = 127,
+ [0][0][1][0][RTW89_UK][0][68] = 127,
+ [0][0][1][0][RTW89_FCC][1][70] = 24,
+ [0][0][1][0][RTW89_FCC][2][70] = 68,
+ [0][0][1][0][RTW89_ETSI][1][70] = 127,
+ [0][0][1][0][RTW89_ETSI][0][70] = 127,
+ [0][0][1][0][RTW89_MKK][1][70] = 127,
+ [0][0][1][0][RTW89_MKK][0][70] = 127,
+ [0][0][1][0][RTW89_IC][1][70] = 24,
+ [0][0][1][0][RTW89_KCC][1][70] = 26,
+ [0][0][1][0][RTW89_KCC][0][70] = 127,
+ [0][0][1][0][RTW89_ACMA][1][70] = 127,
+ [0][0][1][0][RTW89_ACMA][0][70] = 127,
+ [0][0][1][0][RTW89_CHILE][1][70] = 24,
+ [0][0][1][0][RTW89_QATAR][1][70] = 127,
+ [0][0][1][0][RTW89_QATAR][0][70] = 127,
+ [0][0][1][0][RTW89_UK][1][70] = 127,
+ [0][0][1][0][RTW89_UK][0][70] = 127,
+ [0][0][1][0][RTW89_FCC][1][72] = 22,
+ [0][0][1][0][RTW89_FCC][2][72] = 68,
+ [0][0][1][0][RTW89_ETSI][1][72] = 127,
+ [0][0][1][0][RTW89_ETSI][0][72] = 127,
+ [0][0][1][0][RTW89_MKK][1][72] = 127,
+ [0][0][1][0][RTW89_MKK][0][72] = 127,
+ [0][0][1][0][RTW89_IC][1][72] = 22,
+ [0][0][1][0][RTW89_KCC][1][72] = 26,
+ [0][0][1][0][RTW89_KCC][0][72] = 127,
+ [0][0][1][0][RTW89_ACMA][1][72] = 127,
+ [0][0][1][0][RTW89_ACMA][0][72] = 127,
+ [0][0][1][0][RTW89_CHILE][1][72] = 22,
+ [0][0][1][0][RTW89_QATAR][1][72] = 127,
+ [0][0][1][0][RTW89_QATAR][0][72] = 127,
+ [0][0][1][0][RTW89_UK][1][72] = 127,
+ [0][0][1][0][RTW89_UK][0][72] = 127,
+ [0][0][1][0][RTW89_FCC][1][74] = 22,
+ [0][0][1][0][RTW89_FCC][2][74] = 68,
+ [0][0][1][0][RTW89_ETSI][1][74] = 127,
+ [0][0][1][0][RTW89_ETSI][0][74] = 127,
+ [0][0][1][0][RTW89_MKK][1][74] = 127,
+ [0][0][1][0][RTW89_MKK][0][74] = 127,
+ [0][0][1][0][RTW89_IC][1][74] = 22,
+ [0][0][1][0][RTW89_KCC][1][74] = 26,
+ [0][0][1][0][RTW89_KCC][0][74] = 127,
+ [0][0][1][0][RTW89_ACMA][1][74] = 127,
+ [0][0][1][0][RTW89_ACMA][0][74] = 127,
+ [0][0][1][0][RTW89_CHILE][1][74] = 22,
+ [0][0][1][0][RTW89_QATAR][1][74] = 127,
+ [0][0][1][0][RTW89_QATAR][0][74] = 127,
+ [0][0][1][0][RTW89_UK][1][74] = 127,
+ [0][0][1][0][RTW89_UK][0][74] = 127,
+ [0][0][1][0][RTW89_FCC][1][75] = 22,
+ [0][0][1][0][RTW89_FCC][2][75] = 68,
+ [0][0][1][0][RTW89_ETSI][1][75] = 127,
+ [0][0][1][0][RTW89_ETSI][0][75] = 127,
+ [0][0][1][0][RTW89_MKK][1][75] = 127,
+ [0][0][1][0][RTW89_MKK][0][75] = 127,
+ [0][0][1][0][RTW89_IC][1][75] = 22,
+ [0][0][1][0][RTW89_KCC][1][75] = 26,
+ [0][0][1][0][RTW89_KCC][0][75] = 127,
+ [0][0][1][0][RTW89_ACMA][1][75] = 127,
+ [0][0][1][0][RTW89_ACMA][0][75] = 127,
+ [0][0][1][0][RTW89_CHILE][1][75] = 22,
+ [0][0][1][0][RTW89_QATAR][1][75] = 127,
+ [0][0][1][0][RTW89_QATAR][0][75] = 127,
+ [0][0][1][0][RTW89_UK][1][75] = 127,
+ [0][0][1][0][RTW89_UK][0][75] = 127,
+ [0][0][1][0][RTW89_FCC][1][77] = 22,
+ [0][0][1][0][RTW89_FCC][2][77] = 68,
+ [0][0][1][0][RTW89_ETSI][1][77] = 127,
+ [0][0][1][0][RTW89_ETSI][0][77] = 127,
+ [0][0][1][0][RTW89_MKK][1][77] = 127,
+ [0][0][1][0][RTW89_MKK][0][77] = 127,
+ [0][0][1][0][RTW89_IC][1][77] = 22,
+ [0][0][1][0][RTW89_KCC][1][77] = 26,
+ [0][0][1][0][RTW89_KCC][0][77] = 127,
+ [0][0][1][0][RTW89_ACMA][1][77] = 127,
+ [0][0][1][0][RTW89_ACMA][0][77] = 127,
+ [0][0][1][0][RTW89_CHILE][1][77] = 22,
+ [0][0][1][0][RTW89_QATAR][1][77] = 127,
+ [0][0][1][0][RTW89_QATAR][0][77] = 127,
+ [0][0][1][0][RTW89_UK][1][77] = 127,
+ [0][0][1][0][RTW89_UK][0][77] = 127,
+ [0][0][1][0][RTW89_FCC][1][79] = 22,
+ [0][0][1][0][RTW89_FCC][2][79] = 68,
+ [0][0][1][0][RTW89_ETSI][1][79] = 127,
+ [0][0][1][0][RTW89_ETSI][0][79] = 127,
+ [0][0][1][0][RTW89_MKK][1][79] = 127,
+ [0][0][1][0][RTW89_MKK][0][79] = 127,
+ [0][0][1][0][RTW89_IC][1][79] = 22,
+ [0][0][1][0][RTW89_KCC][1][79] = 26,
+ [0][0][1][0][RTW89_KCC][0][79] = 127,
+ [0][0][1][0][RTW89_ACMA][1][79] = 127,
+ [0][0][1][0][RTW89_ACMA][0][79] = 127,
+ [0][0][1][0][RTW89_CHILE][1][79] = 22,
+ [0][0][1][0][RTW89_QATAR][1][79] = 127,
+ [0][0][1][0][RTW89_QATAR][0][79] = 127,
+ [0][0][1][0][RTW89_UK][1][79] = 127,
+ [0][0][1][0][RTW89_UK][0][79] = 127,
+ [0][0][1][0][RTW89_FCC][1][81] = 22,
+ [0][0][1][0][RTW89_FCC][2][81] = 68,
+ [0][0][1][0][RTW89_ETSI][1][81] = 127,
+ [0][0][1][0][RTW89_ETSI][0][81] = 127,
+ [0][0][1][0][RTW89_MKK][1][81] = 127,
+ [0][0][1][0][RTW89_MKK][0][81] = 127,
+ [0][0][1][0][RTW89_IC][1][81] = 22,
+ [0][0][1][0][RTW89_KCC][1][81] = 26,
+ [0][0][1][0][RTW89_KCC][0][81] = 127,
+ [0][0][1][0][RTW89_ACMA][1][81] = 127,
+ [0][0][1][0][RTW89_ACMA][0][81] = 127,
+ [0][0][1][0][RTW89_CHILE][1][81] = 22,
+ [0][0][1][0][RTW89_QATAR][1][81] = 127,
+ [0][0][1][0][RTW89_QATAR][0][81] = 127,
+ [0][0][1][0][RTW89_UK][1][81] = 127,
+ [0][0][1][0][RTW89_UK][0][81] = 127,
+ [0][0][1][0][RTW89_FCC][1][83] = 22,
+ [0][0][1][0][RTW89_FCC][2][83] = 68,
+ [0][0][1][0][RTW89_ETSI][1][83] = 127,
+ [0][0][1][0][RTW89_ETSI][0][83] = 127,
+ [0][0][1][0][RTW89_MKK][1][83] = 127,
+ [0][0][1][0][RTW89_MKK][0][83] = 127,
+ [0][0][1][0][RTW89_IC][1][83] = 22,
+ [0][0][1][0][RTW89_KCC][1][83] = 32,
+ [0][0][1][0][RTW89_KCC][0][83] = 127,
+ [0][0][1][0][RTW89_ACMA][1][83] = 127,
+ [0][0][1][0][RTW89_ACMA][0][83] = 127,
+ [0][0][1][0][RTW89_CHILE][1][83] = 22,
+ [0][0][1][0][RTW89_QATAR][1][83] = 127,
+ [0][0][1][0][RTW89_QATAR][0][83] = 127,
+ [0][0][1][0][RTW89_UK][1][83] = 127,
+ [0][0][1][0][RTW89_UK][0][83] = 127,
+ [0][0][1][0][RTW89_FCC][1][85] = 22,
+ [0][0][1][0][RTW89_FCC][2][85] = 68,
+ [0][0][1][0][RTW89_ETSI][1][85] = 127,
+ [0][0][1][0][RTW89_ETSI][0][85] = 127,
+ [0][0][1][0][RTW89_MKK][1][85] = 127,
+ [0][0][1][0][RTW89_MKK][0][85] = 127,
+ [0][0][1][0][RTW89_IC][1][85] = 22,
+ [0][0][1][0][RTW89_KCC][1][85] = 32,
+ [0][0][1][0][RTW89_KCC][0][85] = 127,
+ [0][0][1][0][RTW89_ACMA][1][85] = 127,
+ [0][0][1][0][RTW89_ACMA][0][85] = 127,
+ [0][0][1][0][RTW89_CHILE][1][85] = 22,
+ [0][0][1][0][RTW89_QATAR][1][85] = 127,
+ [0][0][1][0][RTW89_QATAR][0][85] = 127,
+ [0][0][1][0][RTW89_UK][1][85] = 127,
+ [0][0][1][0][RTW89_UK][0][85] = 127,
+ [0][0][1][0][RTW89_FCC][1][87] = 22,
+ [0][0][1][0][RTW89_FCC][2][87] = 127,
+ [0][0][1][0][RTW89_ETSI][1][87] = 127,
+ [0][0][1][0][RTW89_ETSI][0][87] = 127,
+ [0][0][1][0][RTW89_MKK][1][87] = 127,
+ [0][0][1][0][RTW89_MKK][0][87] = 127,
+ [0][0][1][0][RTW89_IC][1][87] = 22,
+ [0][0][1][0][RTW89_KCC][1][87] = 32,
+ [0][0][1][0][RTW89_KCC][0][87] = 127,
+ [0][0][1][0][RTW89_ACMA][1][87] = 127,
+ [0][0][1][0][RTW89_ACMA][0][87] = 127,
+ [0][0][1][0][RTW89_CHILE][1][87] = 22,
+ [0][0][1][0][RTW89_QATAR][1][87] = 127,
+ [0][0][1][0][RTW89_QATAR][0][87] = 127,
+ [0][0][1][0][RTW89_UK][1][87] = 127,
+ [0][0][1][0][RTW89_UK][0][87] = 127,
+ [0][0][1][0][RTW89_FCC][1][89] = 22,
+ [0][0][1][0][RTW89_FCC][2][89] = 127,
+ [0][0][1][0][RTW89_ETSI][1][89] = 127,
+ [0][0][1][0][RTW89_ETSI][0][89] = 127,
+ [0][0][1][0][RTW89_MKK][1][89] = 127,
+ [0][0][1][0][RTW89_MKK][0][89] = 127,
+ [0][0][1][0][RTW89_IC][1][89] = 22,
+ [0][0][1][0][RTW89_KCC][1][89] = 32,
+ [0][0][1][0][RTW89_KCC][0][89] = 127,
+ [0][0][1][0][RTW89_ACMA][1][89] = 127,
+ [0][0][1][0][RTW89_ACMA][0][89] = 127,
+ [0][0][1][0][RTW89_CHILE][1][89] = 22,
+ [0][0][1][0][RTW89_QATAR][1][89] = 127,
+ [0][0][1][0][RTW89_QATAR][0][89] = 127,
+ [0][0][1][0][RTW89_UK][1][89] = 127,
+ [0][0][1][0][RTW89_UK][0][89] = 127,
+ [0][0][1][0][RTW89_FCC][1][90] = 22,
+ [0][0][1][0][RTW89_FCC][2][90] = 127,
+ [0][0][1][0][RTW89_ETSI][1][90] = 127,
+ [0][0][1][0][RTW89_ETSI][0][90] = 127,
+ [0][0][1][0][RTW89_MKK][1][90] = 127,
+ [0][0][1][0][RTW89_MKK][0][90] = 127,
+ [0][0][1][0][RTW89_IC][1][90] = 22,
+ [0][0][1][0][RTW89_KCC][1][90] = 32,
+ [0][0][1][0][RTW89_KCC][0][90] = 127,
+ [0][0][1][0][RTW89_ACMA][1][90] = 127,
+ [0][0][1][0][RTW89_ACMA][0][90] = 127,
+ [0][0][1][0][RTW89_CHILE][1][90] = 22,
+ [0][0][1][0][RTW89_QATAR][1][90] = 127,
+ [0][0][1][0][RTW89_QATAR][0][90] = 127,
+ [0][0][1][0][RTW89_UK][1][90] = 127,
+ [0][0][1][0][RTW89_UK][0][90] = 127,
+ [0][0][1][0][RTW89_FCC][1][92] = 22,
+ [0][0][1][0][RTW89_FCC][2][92] = 127,
+ [0][0][1][0][RTW89_ETSI][1][92] = 127,
+ [0][0][1][0][RTW89_ETSI][0][92] = 127,
+ [0][0][1][0][RTW89_MKK][1][92] = 127,
+ [0][0][1][0][RTW89_MKK][0][92] = 127,
+ [0][0][1][0][RTW89_IC][1][92] = 22,
+ [0][0][1][0][RTW89_KCC][1][92] = 32,
+ [0][0][1][0][RTW89_KCC][0][92] = 127,
+ [0][0][1][0][RTW89_ACMA][1][92] = 127,
+ [0][0][1][0][RTW89_ACMA][0][92] = 127,
+ [0][0][1][0][RTW89_CHILE][1][92] = 22,
+ [0][0][1][0][RTW89_QATAR][1][92] = 127,
+ [0][0][1][0][RTW89_QATAR][0][92] = 127,
+ [0][0][1][0][RTW89_UK][1][92] = 127,
+ [0][0][1][0][RTW89_UK][0][92] = 127,
+ [0][0][1][0][RTW89_FCC][1][94] = 22,
+ [0][0][1][0][RTW89_FCC][2][94] = 127,
+ [0][0][1][0][RTW89_ETSI][1][94] = 127,
+ [0][0][1][0][RTW89_ETSI][0][94] = 127,
+ [0][0][1][0][RTW89_MKK][1][94] = 127,
+ [0][0][1][0][RTW89_MKK][0][94] = 127,
+ [0][0][1][0][RTW89_IC][1][94] = 22,
+ [0][0][1][0][RTW89_KCC][1][94] = 32,
+ [0][0][1][0][RTW89_KCC][0][94] = 127,
+ [0][0][1][0][RTW89_ACMA][1][94] = 127,
+ [0][0][1][0][RTW89_ACMA][0][94] = 127,
+ [0][0][1][0][RTW89_CHILE][1][94] = 22,
+ [0][0][1][0][RTW89_QATAR][1][94] = 127,
+ [0][0][1][0][RTW89_QATAR][0][94] = 127,
+ [0][0][1][0][RTW89_UK][1][94] = 127,
+ [0][0][1][0][RTW89_UK][0][94] = 127,
+ [0][0][1][0][RTW89_FCC][1][96] = 22,
+ [0][0][1][0][RTW89_FCC][2][96] = 127,
+ [0][0][1][0][RTW89_ETSI][1][96] = 127,
+ [0][0][1][0][RTW89_ETSI][0][96] = 127,
+ [0][0][1][0][RTW89_MKK][1][96] = 127,
+ [0][0][1][0][RTW89_MKK][0][96] = 127,
+ [0][0][1][0][RTW89_IC][1][96] = 22,
+ [0][0][1][0][RTW89_KCC][1][96] = 32,
+ [0][0][1][0][RTW89_KCC][0][96] = 127,
+ [0][0][1][0][RTW89_ACMA][1][96] = 127,
+ [0][0][1][0][RTW89_ACMA][0][96] = 127,
+ [0][0][1][0][RTW89_CHILE][1][96] = 22,
+ [0][0][1][0][RTW89_QATAR][1][96] = 127,
+ [0][0][1][0][RTW89_QATAR][0][96] = 127,
+ [0][0][1][0][RTW89_UK][1][96] = 127,
+ [0][0][1][0][RTW89_UK][0][96] = 127,
+ [0][0][1][0][RTW89_FCC][1][98] = 22,
+ [0][0][1][0][RTW89_FCC][2][98] = 127,
+ [0][0][1][0][RTW89_ETSI][1][98] = 127,
+ [0][0][1][0][RTW89_ETSI][0][98] = 127,
+ [0][0][1][0][RTW89_MKK][1][98] = 127,
+ [0][0][1][0][RTW89_MKK][0][98] = 127,
+ [0][0][1][0][RTW89_IC][1][98] = 22,
+ [0][0][1][0][RTW89_KCC][1][98] = 32,
+ [0][0][1][0][RTW89_KCC][0][98] = 127,
+ [0][0][1][0][RTW89_ACMA][1][98] = 127,
+ [0][0][1][0][RTW89_ACMA][0][98] = 127,
+ [0][0][1][0][RTW89_CHILE][1][98] = 22,
+ [0][0][1][0][RTW89_QATAR][1][98] = 127,
+ [0][0][1][0][RTW89_QATAR][0][98] = 127,
+ [0][0][1][0][RTW89_UK][1][98] = 127,
+ [0][0][1][0][RTW89_UK][0][98] = 127,
+ [0][0][1][0][RTW89_FCC][1][100] = 22,
+ [0][0][1][0][RTW89_FCC][2][100] = 127,
+ [0][0][1][0][RTW89_ETSI][1][100] = 127,
+ [0][0][1][0][RTW89_ETSI][0][100] = 127,
+ [0][0][1][0][RTW89_MKK][1][100] = 127,
+ [0][0][1][0][RTW89_MKK][0][100] = 127,
+ [0][0][1][0][RTW89_IC][1][100] = 22,
+ [0][0][1][0][RTW89_KCC][1][100] = 32,
+ [0][0][1][0][RTW89_KCC][0][100] = 127,
+ [0][0][1][0][RTW89_ACMA][1][100] = 127,
+ [0][0][1][0][RTW89_ACMA][0][100] = 127,
+ [0][0][1][0][RTW89_CHILE][1][100] = 22,
+ [0][0][1][0][RTW89_QATAR][1][100] = 127,
+ [0][0][1][0][RTW89_QATAR][0][100] = 127,
+ [0][0][1][0][RTW89_UK][1][100] = 127,
+ [0][0][1][0][RTW89_UK][0][100] = 127,
+ [0][0][1][0][RTW89_FCC][1][102] = 22,
+ [0][0][1][0][RTW89_FCC][2][102] = 127,
+ [0][0][1][0][RTW89_ETSI][1][102] = 127,
+ [0][0][1][0][RTW89_ETSI][0][102] = 127,
+ [0][0][1][0][RTW89_MKK][1][102] = 127,
+ [0][0][1][0][RTW89_MKK][0][102] = 127,
+ [0][0][1][0][RTW89_IC][1][102] = 22,
+ [0][0][1][0][RTW89_KCC][1][102] = 32,
+ [0][0][1][0][RTW89_KCC][0][102] = 127,
+ [0][0][1][0][RTW89_ACMA][1][102] = 127,
+ [0][0][1][0][RTW89_ACMA][0][102] = 127,
+ [0][0][1][0][RTW89_CHILE][1][102] = 22,
+ [0][0][1][0][RTW89_QATAR][1][102] = 127,
+ [0][0][1][0][RTW89_QATAR][0][102] = 127,
+ [0][0][1][0][RTW89_UK][1][102] = 127,
+ [0][0][1][0][RTW89_UK][0][102] = 127,
+ [0][0][1][0][RTW89_FCC][1][104] = 22,
+ [0][0][1][0][RTW89_FCC][2][104] = 127,
+ [0][0][1][0][RTW89_ETSI][1][104] = 127,
+ [0][0][1][0][RTW89_ETSI][0][104] = 127,
+ [0][0][1][0][RTW89_MKK][1][104] = 127,
+ [0][0][1][0][RTW89_MKK][0][104] = 127,
+ [0][0][1][0][RTW89_IC][1][104] = 22,
+ [0][0][1][0][RTW89_KCC][1][104] = 32,
+ [0][0][1][0][RTW89_KCC][0][104] = 127,
+ [0][0][1][0][RTW89_ACMA][1][104] = 127,
+ [0][0][1][0][RTW89_ACMA][0][104] = 127,
+ [0][0][1][0][RTW89_CHILE][1][104] = 22,
+ [0][0][1][0][RTW89_QATAR][1][104] = 127,
+ [0][0][1][0][RTW89_QATAR][0][104] = 127,
+ [0][0][1][0][RTW89_UK][1][104] = 127,
+ [0][0][1][0][RTW89_UK][0][104] = 127,
+ [0][0][1][0][RTW89_FCC][1][105] = 22,
+ [0][0][1][0][RTW89_FCC][2][105] = 127,
+ [0][0][1][0][RTW89_ETSI][1][105] = 127,
+ [0][0][1][0][RTW89_ETSI][0][105] = 127,
+ [0][0][1][0][RTW89_MKK][1][105] = 127,
+ [0][0][1][0][RTW89_MKK][0][105] = 127,
+ [0][0][1][0][RTW89_IC][1][105] = 22,
+ [0][0][1][0][RTW89_KCC][1][105] = 32,
+ [0][0][1][0][RTW89_KCC][0][105] = 127,
+ [0][0][1][0][RTW89_ACMA][1][105] = 127,
+ [0][0][1][0][RTW89_ACMA][0][105] = 127,
+ [0][0][1][0][RTW89_CHILE][1][105] = 22,
+ [0][0][1][0][RTW89_QATAR][1][105] = 127,
+ [0][0][1][0][RTW89_QATAR][0][105] = 127,
+ [0][0][1][0][RTW89_UK][1][105] = 127,
+ [0][0][1][0][RTW89_UK][0][105] = 127,
+ [0][0][1][0][RTW89_FCC][1][107] = 24,
+ [0][0][1][0][RTW89_FCC][2][107] = 127,
+ [0][0][1][0][RTW89_ETSI][1][107] = 127,
+ [0][0][1][0][RTW89_ETSI][0][107] = 127,
+ [0][0][1][0][RTW89_MKK][1][107] = 127,
+ [0][0][1][0][RTW89_MKK][0][107] = 127,
+ [0][0][1][0][RTW89_IC][1][107] = 24,
+ [0][0][1][0][RTW89_KCC][1][107] = 32,
+ [0][0][1][0][RTW89_KCC][0][107] = 127,
+ [0][0][1][0][RTW89_ACMA][1][107] = 127,
+ [0][0][1][0][RTW89_ACMA][0][107] = 127,
+ [0][0][1][0][RTW89_CHILE][1][107] = 24,
+ [0][0][1][0][RTW89_QATAR][1][107] = 127,
+ [0][0][1][0][RTW89_QATAR][0][107] = 127,
+ [0][0][1][0][RTW89_UK][1][107] = 127,
+ [0][0][1][0][RTW89_UK][0][107] = 127,
+ [0][0][1][0][RTW89_FCC][1][109] = 24,
+ [0][0][1][0][RTW89_FCC][2][109] = 127,
+ [0][0][1][0][RTW89_ETSI][1][109] = 127,
+ [0][0][1][0][RTW89_ETSI][0][109] = 127,
+ [0][0][1][0][RTW89_MKK][1][109] = 127,
+ [0][0][1][0][RTW89_MKK][0][109] = 127,
+ [0][0][1][0][RTW89_IC][1][109] = 24,
+ [0][0][1][0][RTW89_KCC][1][109] = 32,
+ [0][0][1][0][RTW89_KCC][0][109] = 127,
+ [0][0][1][0][RTW89_ACMA][1][109] = 127,
+ [0][0][1][0][RTW89_ACMA][0][109] = 127,
+ [0][0][1][0][RTW89_CHILE][1][109] = 24,
+ [0][0][1][0][RTW89_QATAR][1][109] = 127,
+ [0][0][1][0][RTW89_QATAR][0][109] = 127,
+ [0][0][1][0][RTW89_UK][1][109] = 127,
+ [0][0][1][0][RTW89_UK][0][109] = 127,
+ [0][0][1][0][RTW89_FCC][1][111] = 127,
+ [0][0][1][0][RTW89_FCC][2][111] = 127,
+ [0][0][1][0][RTW89_ETSI][1][111] = 127,
+ [0][0][1][0][RTW89_ETSI][0][111] = 127,
+ [0][0][1][0][RTW89_MKK][1][111] = 127,
+ [0][0][1][0][RTW89_MKK][0][111] = 127,
+ [0][0][1][0][RTW89_IC][1][111] = 127,
+ [0][0][1][0][RTW89_KCC][1][111] = 127,
+ [0][0][1][0][RTW89_KCC][0][111] = 127,
+ [0][0][1][0][RTW89_ACMA][1][111] = 127,
+ [0][0][1][0][RTW89_ACMA][0][111] = 127,
+ [0][0][1][0][RTW89_CHILE][1][111] = 127,
+ [0][0][1][0][RTW89_QATAR][1][111] = 127,
+ [0][0][1][0][RTW89_QATAR][0][111] = 127,
+ [0][0][1][0][RTW89_UK][1][111] = 127,
+ [0][0][1][0][RTW89_UK][0][111] = 127,
+ [0][0][1][0][RTW89_FCC][1][113] = 127,
+ [0][0][1][0][RTW89_FCC][2][113] = 127,
+ [0][0][1][0][RTW89_ETSI][1][113] = 127,
+ [0][0][1][0][RTW89_ETSI][0][113] = 127,
+ [0][0][1][0][RTW89_MKK][1][113] = 127,
+ [0][0][1][0][RTW89_MKK][0][113] = 127,
+ [0][0][1][0][RTW89_IC][1][113] = 127,
+ [0][0][1][0][RTW89_KCC][1][113] = 127,
+ [0][0][1][0][RTW89_KCC][0][113] = 127,
+ [0][0][1][0][RTW89_ACMA][1][113] = 127,
+ [0][0][1][0][RTW89_ACMA][0][113] = 127,
+ [0][0][1][0][RTW89_CHILE][1][113] = 127,
+ [0][0][1][0][RTW89_QATAR][1][113] = 127,
+ [0][0][1][0][RTW89_QATAR][0][113] = 127,
+ [0][0][1][0][RTW89_UK][1][113] = 127,
+ [0][0][1][0][RTW89_UK][0][113] = 127,
+ [0][0][1][0][RTW89_FCC][1][115] = 127,
+ [0][0][1][0][RTW89_FCC][2][115] = 127,
+ [0][0][1][0][RTW89_ETSI][1][115] = 127,
+ [0][0][1][0][RTW89_ETSI][0][115] = 127,
+ [0][0][1][0][RTW89_MKK][1][115] = 127,
+ [0][0][1][0][RTW89_MKK][0][115] = 127,
+ [0][0][1][0][RTW89_IC][1][115] = 127,
+ [0][0][1][0][RTW89_KCC][1][115] = 127,
+ [0][0][1][0][RTW89_KCC][0][115] = 127,
+ [0][0][1][0][RTW89_ACMA][1][115] = 127,
+ [0][0][1][0][RTW89_ACMA][0][115] = 127,
+ [0][0][1][0][RTW89_CHILE][1][115] = 127,
+ [0][0][1][0][RTW89_QATAR][1][115] = 127,
+ [0][0][1][0][RTW89_QATAR][0][115] = 127,
+ [0][0][1][0][RTW89_UK][1][115] = 127,
+ [0][0][1][0][RTW89_UK][0][115] = 127,
+ [0][0][1][0][RTW89_FCC][1][117] = 127,
+ [0][0][1][0][RTW89_FCC][2][117] = 127,
+ [0][0][1][0][RTW89_ETSI][1][117] = 127,
+ [0][0][1][0][RTW89_ETSI][0][117] = 127,
+ [0][0][1][0][RTW89_MKK][1][117] = 127,
+ [0][0][1][0][RTW89_MKK][0][117] = 127,
+ [0][0][1][0][RTW89_IC][1][117] = 127,
+ [0][0][1][0][RTW89_KCC][1][117] = 127,
+ [0][0][1][0][RTW89_KCC][0][117] = 127,
+ [0][0][1][0][RTW89_ACMA][1][117] = 127,
+ [0][0][1][0][RTW89_ACMA][0][117] = 127,
+ [0][0][1][0][RTW89_CHILE][1][117] = 127,
+ [0][0][1][0][RTW89_QATAR][1][117] = 127,
+ [0][0][1][0][RTW89_QATAR][0][117] = 127,
+ [0][0][1][0][RTW89_UK][1][117] = 127,
+ [0][0][1][0][RTW89_UK][0][117] = 127,
+ [0][0][1][0][RTW89_FCC][1][119] = 127,
+ [0][0][1][0][RTW89_FCC][2][119] = 127,
+ [0][0][1][0][RTW89_ETSI][1][119] = 127,
+ [0][0][1][0][RTW89_ETSI][0][119] = 127,
+ [0][0][1][0][RTW89_MKK][1][119] = 127,
+ [0][0][1][0][RTW89_MKK][0][119] = 127,
+ [0][0][1][0][RTW89_IC][1][119] = 127,
+ [0][0][1][0][RTW89_KCC][1][119] = 127,
+ [0][0][1][0][RTW89_KCC][0][119] = 127,
+ [0][0][1][0][RTW89_ACMA][1][119] = 127,
+ [0][0][1][0][RTW89_ACMA][0][119] = 127,
+ [0][0][1][0][RTW89_CHILE][1][119] = 127,
+ [0][0][1][0][RTW89_QATAR][1][119] = 127,
+ [0][0][1][0][RTW89_QATAR][0][119] = 127,
+ [0][0][1][0][RTW89_UK][1][119] = 127,
+ [0][0][1][0][RTW89_UK][0][119] = 127,
+ [0][1][1][0][RTW89_FCC][1][0] = -2,
+ [0][1][1][0][RTW89_FCC][2][0] = 54,
+ [0][1][1][0][RTW89_ETSI][1][0] = 54,
+ [0][1][1][0][RTW89_ETSI][0][0] = 18,
+ [0][1][1][0][RTW89_MKK][1][0] = 56,
+ [0][1][1][0][RTW89_MKK][0][0] = 16,
+ [0][1][1][0][RTW89_IC][1][0] = -2,
+ [0][1][1][0][RTW89_KCC][1][0] = 12,
+ [0][1][1][0][RTW89_KCC][0][0] = 10,
+ [0][1][1][0][RTW89_ACMA][1][0] = 54,
+ [0][1][1][0][RTW89_ACMA][0][0] = 18,
+ [0][1][1][0][RTW89_CHILE][1][0] = -2,
+ [0][1][1][0][RTW89_QATAR][1][0] = 54,
+ [0][1][1][0][RTW89_QATAR][0][0] = 18,
+ [0][1][1][0][RTW89_UK][1][0] = 54,
+ [0][1][1][0][RTW89_UK][0][0] = 18,
+ [0][1][1][0][RTW89_FCC][1][2] = -4,
+ [0][1][1][0][RTW89_FCC][2][2] = 54,
+ [0][1][1][0][RTW89_ETSI][1][2] = 54,
+ [0][1][1][0][RTW89_ETSI][0][2] = 18,
+ [0][1][1][0][RTW89_MKK][1][2] = 54,
+ [0][1][1][0][RTW89_MKK][0][2] = 16,
+ [0][1][1][0][RTW89_IC][1][2] = -4,
+ [0][1][1][0][RTW89_KCC][1][2] = 12,
+ [0][1][1][0][RTW89_KCC][0][2] = 12,
+ [0][1][1][0][RTW89_ACMA][1][2] = 54,
+ [0][1][1][0][RTW89_ACMA][0][2] = 18,
+ [0][1][1][0][RTW89_CHILE][1][2] = -4,
+ [0][1][1][0][RTW89_QATAR][1][2] = 54,
+ [0][1][1][0][RTW89_QATAR][0][2] = 18,
+ [0][1][1][0][RTW89_UK][1][2] = 54,
+ [0][1][1][0][RTW89_UK][0][2] = 18,
+ [0][1][1][0][RTW89_FCC][1][4] = -4,
+ [0][1][1][0][RTW89_FCC][2][4] = 54,
+ [0][1][1][0][RTW89_ETSI][1][4] = 54,
+ [0][1][1][0][RTW89_ETSI][0][4] = 18,
+ [0][1][1][0][RTW89_MKK][1][4] = 54,
+ [0][1][1][0][RTW89_MKK][0][4] = 16,
+ [0][1][1][0][RTW89_IC][1][4] = -4,
+ [0][1][1][0][RTW89_KCC][1][4] = 12,
+ [0][1][1][0][RTW89_KCC][0][4] = 12,
+ [0][1][1][0][RTW89_ACMA][1][4] = 54,
+ [0][1][1][0][RTW89_ACMA][0][4] = 18,
+ [0][1][1][0][RTW89_CHILE][1][4] = -4,
+ [0][1][1][0][RTW89_QATAR][1][4] = 54,
+ [0][1][1][0][RTW89_QATAR][0][4] = 18,
+ [0][1][1][0][RTW89_UK][1][4] = 54,
+ [0][1][1][0][RTW89_UK][0][4] = 18,
+ [0][1][1][0][RTW89_FCC][1][6] = -4,
+ [0][1][1][0][RTW89_FCC][2][6] = 54,
+ [0][1][1][0][RTW89_ETSI][1][6] = 54,
+ [0][1][1][0][RTW89_ETSI][0][6] = 18,
+ [0][1][1][0][RTW89_MKK][1][6] = 54,
+ [0][1][1][0][RTW89_MKK][0][6] = 16,
+ [0][1][1][0][RTW89_IC][1][6] = -4,
+ [0][1][1][0][RTW89_KCC][1][6] = 12,
+ [0][1][1][0][RTW89_KCC][0][6] = 12,
+ [0][1][1][0][RTW89_ACMA][1][6] = 54,
+ [0][1][1][0][RTW89_ACMA][0][6] = 18,
+ [0][1][1][0][RTW89_CHILE][1][6] = -4,
+ [0][1][1][0][RTW89_QATAR][1][6] = 54,
+ [0][1][1][0][RTW89_QATAR][0][6] = 18,
+ [0][1][1][0][RTW89_UK][1][6] = 54,
+ [0][1][1][0][RTW89_UK][0][6] = 18,
+ [0][1][1][0][RTW89_FCC][1][8] = -4,
+ [0][1][1][0][RTW89_FCC][2][8] = 54,
+ [0][1][1][0][RTW89_ETSI][1][8] = 54,
+ [0][1][1][0][RTW89_ETSI][0][8] = 18,
+ [0][1][1][0][RTW89_MKK][1][8] = 54,
+ [0][1][1][0][RTW89_MKK][0][8] = 16,
+ [0][1][1][0][RTW89_IC][1][8] = -4,
+ [0][1][1][0][RTW89_KCC][1][8] = 12,
+ [0][1][1][0][RTW89_KCC][0][8] = 12,
+ [0][1][1][0][RTW89_ACMA][1][8] = 54,
+ [0][1][1][0][RTW89_ACMA][0][8] = 18,
+ [0][1][1][0][RTW89_CHILE][1][8] = -4,
+ [0][1][1][0][RTW89_QATAR][1][8] = 54,
+ [0][1][1][0][RTW89_QATAR][0][8] = 18,
+ [0][1][1][0][RTW89_UK][1][8] = 54,
+ [0][1][1][0][RTW89_UK][0][8] = 18,
+ [0][1][1][0][RTW89_FCC][1][10] = -4,
+ [0][1][1][0][RTW89_FCC][2][10] = 54,
+ [0][1][1][0][RTW89_ETSI][1][10] = 54,
+ [0][1][1][0][RTW89_ETSI][0][10] = 18,
+ [0][1][1][0][RTW89_MKK][1][10] = 54,
+ [0][1][1][0][RTW89_MKK][0][10] = 16,
+ [0][1][1][0][RTW89_IC][1][10] = -4,
+ [0][1][1][0][RTW89_KCC][1][10] = 12,
+ [0][1][1][0][RTW89_KCC][0][10] = 12,
+ [0][1][1][0][RTW89_ACMA][1][10] = 54,
+ [0][1][1][0][RTW89_ACMA][0][10] = 18,
+ [0][1][1][0][RTW89_CHILE][1][10] = -4,
+ [0][1][1][0][RTW89_QATAR][1][10] = 54,
+ [0][1][1][0][RTW89_QATAR][0][10] = 18,
+ [0][1][1][0][RTW89_UK][1][10] = 54,
+ [0][1][1][0][RTW89_UK][0][10] = 18,
+ [0][1][1][0][RTW89_FCC][1][12] = -4,
+ [0][1][1][0][RTW89_FCC][2][12] = 54,
+ [0][1][1][0][RTW89_ETSI][1][12] = 54,
+ [0][1][1][0][RTW89_ETSI][0][12] = 18,
+ [0][1][1][0][RTW89_MKK][1][12] = 54,
+ [0][1][1][0][RTW89_MKK][0][12] = 16,
+ [0][1][1][0][RTW89_IC][1][12] = -4,
+ [0][1][1][0][RTW89_KCC][1][12] = 12,
+ [0][1][1][0][RTW89_KCC][0][12] = 12,
+ [0][1][1][0][RTW89_ACMA][1][12] = 54,
+ [0][1][1][0][RTW89_ACMA][0][12] = 18,
+ [0][1][1][0][RTW89_CHILE][1][12] = -4,
+ [0][1][1][0][RTW89_QATAR][1][12] = 54,
+ [0][1][1][0][RTW89_QATAR][0][12] = 18,
+ [0][1][1][0][RTW89_UK][1][12] = 54,
+ [0][1][1][0][RTW89_UK][0][12] = 18,
+ [0][1][1][0][RTW89_FCC][1][14] = -4,
+ [0][1][1][0][RTW89_FCC][2][14] = 54,
+ [0][1][1][0][RTW89_ETSI][1][14] = 54,
+ [0][1][1][0][RTW89_ETSI][0][14] = 18,
+ [0][1][1][0][RTW89_MKK][1][14] = 54,
+ [0][1][1][0][RTW89_MKK][0][14] = 16,
+ [0][1][1][0][RTW89_IC][1][14] = -4,
+ [0][1][1][0][RTW89_KCC][1][14] = 12,
+ [0][1][1][0][RTW89_KCC][0][14] = 12,
+ [0][1][1][0][RTW89_ACMA][1][14] = 54,
+ [0][1][1][0][RTW89_ACMA][0][14] = 18,
+ [0][1][1][0][RTW89_CHILE][1][14] = -4,
+ [0][1][1][0][RTW89_QATAR][1][14] = 54,
+ [0][1][1][0][RTW89_QATAR][0][14] = 18,
+ [0][1][1][0][RTW89_UK][1][14] = 54,
+ [0][1][1][0][RTW89_UK][0][14] = 18,
+ [0][1][1][0][RTW89_FCC][1][15] = -4,
+ [0][1][1][0][RTW89_FCC][2][15] = 54,
+ [0][1][1][0][RTW89_ETSI][1][15] = 54,
+ [0][1][1][0][RTW89_ETSI][0][15] = 18,
+ [0][1][1][0][RTW89_MKK][1][15] = 54,
+ [0][1][1][0][RTW89_MKK][0][15] = 16,
+ [0][1][1][0][RTW89_IC][1][15] = -4,
+ [0][1][1][0][RTW89_KCC][1][15] = 12,
+ [0][1][1][0][RTW89_KCC][0][15] = 12,
+ [0][1][1][0][RTW89_ACMA][1][15] = 54,
+ [0][1][1][0][RTW89_ACMA][0][15] = 18,
+ [0][1][1][0][RTW89_CHILE][1][15] = -4,
+ [0][1][1][0][RTW89_QATAR][1][15] = 54,
+ [0][1][1][0][RTW89_QATAR][0][15] = 18,
+ [0][1][1][0][RTW89_UK][1][15] = 54,
+ [0][1][1][0][RTW89_UK][0][15] = 18,
+ [0][1][1][0][RTW89_FCC][1][17] = -4,
+ [0][1][1][0][RTW89_FCC][2][17] = 54,
+ [0][1][1][0][RTW89_ETSI][1][17] = 54,
+ [0][1][1][0][RTW89_ETSI][0][17] = 18,
+ [0][1][1][0][RTW89_MKK][1][17] = 54,
+ [0][1][1][0][RTW89_MKK][0][17] = 16,
+ [0][1][1][0][RTW89_IC][1][17] = -4,
+ [0][1][1][0][RTW89_KCC][1][17] = 12,
+ [0][1][1][0][RTW89_KCC][0][17] = 12,
+ [0][1][1][0][RTW89_ACMA][1][17] = 54,
+ [0][1][1][0][RTW89_ACMA][0][17] = 18,
+ [0][1][1][0][RTW89_CHILE][1][17] = -4,
+ [0][1][1][0][RTW89_QATAR][1][17] = 54,
+ [0][1][1][0][RTW89_QATAR][0][17] = 18,
+ [0][1][1][0][RTW89_UK][1][17] = 54,
+ [0][1][1][0][RTW89_UK][0][17] = 18,
+ [0][1][1][0][RTW89_FCC][1][19] = -4,
+ [0][1][1][0][RTW89_FCC][2][19] = 54,
+ [0][1][1][0][RTW89_ETSI][1][19] = 54,
+ [0][1][1][0][RTW89_ETSI][0][19] = 18,
+ [0][1][1][0][RTW89_MKK][1][19] = 54,
+ [0][1][1][0][RTW89_MKK][0][19] = 16,
+ [0][1][1][0][RTW89_IC][1][19] = -4,
+ [0][1][1][0][RTW89_KCC][1][19] = 12,
+ [0][1][1][0][RTW89_KCC][0][19] = 12,
+ [0][1][1][0][RTW89_ACMA][1][19] = 54,
+ [0][1][1][0][RTW89_ACMA][0][19] = 18,
+ [0][1][1][0][RTW89_CHILE][1][19] = -4,
+ [0][1][1][0][RTW89_QATAR][1][19] = 54,
+ [0][1][1][0][RTW89_QATAR][0][19] = 18,
+ [0][1][1][0][RTW89_UK][1][19] = 54,
+ [0][1][1][0][RTW89_UK][0][19] = 18,
+ [0][1][1][0][RTW89_FCC][1][21] = -4,
+ [0][1][1][0][RTW89_FCC][2][21] = 54,
+ [0][1][1][0][RTW89_ETSI][1][21] = 54,
+ [0][1][1][0][RTW89_ETSI][0][21] = 18,
+ [0][1][1][0][RTW89_MKK][1][21] = 54,
+ [0][1][1][0][RTW89_MKK][0][21] = 16,
+ [0][1][1][0][RTW89_IC][1][21] = -4,
+ [0][1][1][0][RTW89_KCC][1][21] = 12,
+ [0][1][1][0][RTW89_KCC][0][21] = 12,
+ [0][1][1][0][RTW89_ACMA][1][21] = 54,
+ [0][1][1][0][RTW89_ACMA][0][21] = 18,
+ [0][1][1][0][RTW89_CHILE][1][21] = -4,
+ [0][1][1][0][RTW89_QATAR][1][21] = 54,
+ [0][1][1][0][RTW89_QATAR][0][21] = 18,
+ [0][1][1][0][RTW89_UK][1][21] = 54,
+ [0][1][1][0][RTW89_UK][0][21] = 18,
+ [0][1][1][0][RTW89_FCC][1][23] = -4,
+ [0][1][1][0][RTW89_FCC][2][23] = 68,
+ [0][1][1][0][RTW89_ETSI][1][23] = 54,
+ [0][1][1][0][RTW89_ETSI][0][23] = 18,
+ [0][1][1][0][RTW89_MKK][1][23] = 54,
+ [0][1][1][0][RTW89_MKK][0][23] = 16,
+ [0][1][1][0][RTW89_IC][1][23] = -4,
+ [0][1][1][0][RTW89_KCC][1][23] = 12,
+ [0][1][1][0][RTW89_KCC][0][23] = 10,
+ [0][1][1][0][RTW89_ACMA][1][23] = 54,
+ [0][1][1][0][RTW89_ACMA][0][23] = 18,
+ [0][1][1][0][RTW89_CHILE][1][23] = -4,
+ [0][1][1][0][RTW89_QATAR][1][23] = 54,
+ [0][1][1][0][RTW89_QATAR][0][23] = 18,
+ [0][1][1][0][RTW89_UK][1][23] = 54,
+ [0][1][1][0][RTW89_UK][0][23] = 18,
+ [0][1][1][0][RTW89_FCC][1][25] = -4,
+ [0][1][1][0][RTW89_FCC][2][25] = 68,
+ [0][1][1][0][RTW89_ETSI][1][25] = 54,
+ [0][1][1][0][RTW89_ETSI][0][25] = 18,
+ [0][1][1][0][RTW89_MKK][1][25] = 54,
+ [0][1][1][0][RTW89_MKK][0][25] = 16,
+ [0][1][1][0][RTW89_IC][1][25] = -4,
+ [0][1][1][0][RTW89_KCC][1][25] = 12,
+ [0][1][1][0][RTW89_KCC][0][25] = 14,
+ [0][1][1][0][RTW89_ACMA][1][25] = 54,
+ [0][1][1][0][RTW89_ACMA][0][25] = 18,
+ [0][1][1][0][RTW89_CHILE][1][25] = -4,
+ [0][1][1][0][RTW89_QATAR][1][25] = 54,
+ [0][1][1][0][RTW89_QATAR][0][25] = 18,
+ [0][1][1][0][RTW89_UK][1][25] = 54,
+ [0][1][1][0][RTW89_UK][0][25] = 18,
+ [0][1][1][0][RTW89_FCC][1][27] = -4,
+ [0][1][1][0][RTW89_FCC][2][27] = 68,
+ [0][1][1][0][RTW89_ETSI][1][27] = 54,
+ [0][1][1][0][RTW89_ETSI][0][27] = 18,
+ [0][1][1][0][RTW89_MKK][1][27] = 54,
+ [0][1][1][0][RTW89_MKK][0][27] = 16,
+ [0][1][1][0][RTW89_IC][1][27] = -4,
+ [0][1][1][0][RTW89_KCC][1][27] = 12,
+ [0][1][1][0][RTW89_KCC][0][27] = 14,
+ [0][1][1][0][RTW89_ACMA][1][27] = 54,
+ [0][1][1][0][RTW89_ACMA][0][27] = 18,
+ [0][1][1][0][RTW89_CHILE][1][27] = -4,
+ [0][1][1][0][RTW89_QATAR][1][27] = 54,
+ [0][1][1][0][RTW89_QATAR][0][27] = 18,
+ [0][1][1][0][RTW89_UK][1][27] = 54,
+ [0][1][1][0][RTW89_UK][0][27] = 18,
+ [0][1][1][0][RTW89_FCC][1][29] = -4,
+ [0][1][1][0][RTW89_FCC][2][29] = 68,
+ [0][1][1][0][RTW89_ETSI][1][29] = 54,
+ [0][1][1][0][RTW89_ETSI][0][29] = 18,
+ [0][1][1][0][RTW89_MKK][1][29] = 54,
+ [0][1][1][0][RTW89_MKK][0][29] = 16,
+ [0][1][1][0][RTW89_IC][1][29] = -4,
+ [0][1][1][0][RTW89_KCC][1][29] = 12,
+ [0][1][1][0][RTW89_KCC][0][29] = 14,
+ [0][1][1][0][RTW89_ACMA][1][29] = 54,
+ [0][1][1][0][RTW89_ACMA][0][29] = 18,
+ [0][1][1][0][RTW89_CHILE][1][29] = -4,
+ [0][1][1][0][RTW89_QATAR][1][29] = 54,
+ [0][1][1][0][RTW89_QATAR][0][29] = 18,
+ [0][1][1][0][RTW89_UK][1][29] = 54,
+ [0][1][1][0][RTW89_UK][0][29] = 18,
+ [0][1][1][0][RTW89_FCC][1][30] = -4,
+ [0][1][1][0][RTW89_FCC][2][30] = 68,
+ [0][1][1][0][RTW89_ETSI][1][30] = 54,
+ [0][1][1][0][RTW89_ETSI][0][30] = 18,
+ [0][1][1][0][RTW89_MKK][1][30] = 54,
+ [0][1][1][0][RTW89_MKK][0][30] = 16,
+ [0][1][1][0][RTW89_IC][1][30] = -4,
+ [0][1][1][0][RTW89_KCC][1][30] = 12,
+ [0][1][1][0][RTW89_KCC][0][30] = 14,
+ [0][1][1][0][RTW89_ACMA][1][30] = 54,
+ [0][1][1][0][RTW89_ACMA][0][30] = 18,
+ [0][1][1][0][RTW89_CHILE][1][30] = -4,
+ [0][1][1][0][RTW89_QATAR][1][30] = 54,
+ [0][1][1][0][RTW89_QATAR][0][30] = 18,
+ [0][1][1][0][RTW89_UK][1][30] = 54,
+ [0][1][1][0][RTW89_UK][0][30] = 18,
+ [0][1][1][0][RTW89_FCC][1][32] = -4,
+ [0][1][1][0][RTW89_FCC][2][32] = 68,
+ [0][1][1][0][RTW89_ETSI][1][32] = 54,
+ [0][1][1][0][RTW89_ETSI][0][32] = 18,
+ [0][1][1][0][RTW89_MKK][1][32] = 54,
+ [0][1][1][0][RTW89_MKK][0][32] = 16,
+ [0][1][1][0][RTW89_IC][1][32] = -4,
+ [0][1][1][0][RTW89_KCC][1][32] = 12,
+ [0][1][1][0][RTW89_KCC][0][32] = 14,
+ [0][1][1][0][RTW89_ACMA][1][32] = 54,
+ [0][1][1][0][RTW89_ACMA][0][32] = 18,
+ [0][1][1][0][RTW89_CHILE][1][32] = -4,
+ [0][1][1][0][RTW89_QATAR][1][32] = 54,
+ [0][1][1][0][RTW89_QATAR][0][32] = 18,
+ [0][1][1][0][RTW89_UK][1][32] = 54,
+ [0][1][1][0][RTW89_UK][0][32] = 18,
+ [0][1][1][0][RTW89_FCC][1][34] = -4,
+ [0][1][1][0][RTW89_FCC][2][34] = 68,
+ [0][1][1][0][RTW89_ETSI][1][34] = 54,
+ [0][1][1][0][RTW89_ETSI][0][34] = 18,
+ [0][1][1][0][RTW89_MKK][1][34] = 54,
+ [0][1][1][0][RTW89_MKK][0][34] = 16,
+ [0][1][1][0][RTW89_IC][1][34] = -4,
+ [0][1][1][0][RTW89_KCC][1][34] = 12,
+ [0][1][1][0][RTW89_KCC][0][34] = 14,
+ [0][1][1][0][RTW89_ACMA][1][34] = 54,
+ [0][1][1][0][RTW89_ACMA][0][34] = 18,
+ [0][1][1][0][RTW89_CHILE][1][34] = -4,
+ [0][1][1][0][RTW89_QATAR][1][34] = 54,
+ [0][1][1][0][RTW89_QATAR][0][34] = 18,
+ [0][1][1][0][RTW89_UK][1][34] = 54,
+ [0][1][1][0][RTW89_UK][0][34] = 18,
+ [0][1][1][0][RTW89_FCC][1][36] = -4,
+ [0][1][1][0][RTW89_FCC][2][36] = 68,
+ [0][1][1][0][RTW89_ETSI][1][36] = 54,
+ [0][1][1][0][RTW89_ETSI][0][36] = 18,
+ [0][1][1][0][RTW89_MKK][1][36] = 54,
+ [0][1][1][0][RTW89_MKK][0][36] = 16,
+ [0][1][1][0][RTW89_IC][1][36] = -4,
+ [0][1][1][0][RTW89_KCC][1][36] = 12,
+ [0][1][1][0][RTW89_KCC][0][36] = 14,
+ [0][1][1][0][RTW89_ACMA][1][36] = 54,
+ [0][1][1][0][RTW89_ACMA][0][36] = 18,
+ [0][1][1][0][RTW89_CHILE][1][36] = -4,
+ [0][1][1][0][RTW89_QATAR][1][36] = 54,
+ [0][1][1][0][RTW89_QATAR][0][36] = 18,
+ [0][1][1][0][RTW89_UK][1][36] = 54,
+ [0][1][1][0][RTW89_UK][0][36] = 18,
+ [0][1][1][0][RTW89_FCC][1][38] = -4,
+ [0][1][1][0][RTW89_FCC][2][38] = 68,
+ [0][1][1][0][RTW89_ETSI][1][38] = 54,
+ [0][1][1][0][RTW89_ETSI][0][38] = 18,
+ [0][1][1][0][RTW89_MKK][1][38] = 54,
+ [0][1][1][0][RTW89_MKK][0][38] = 16,
+ [0][1][1][0][RTW89_IC][1][38] = -4,
+ [0][1][1][0][RTW89_KCC][1][38] = 12,
+ [0][1][1][0][RTW89_KCC][0][38] = 14,
+ [0][1][1][0][RTW89_ACMA][1][38] = 54,
+ [0][1][1][0][RTW89_ACMA][0][38] = 18,
+ [0][1][1][0][RTW89_CHILE][1][38] = -4,
+ [0][1][1][0][RTW89_QATAR][1][38] = 54,
+ [0][1][1][0][RTW89_QATAR][0][38] = 18,
+ [0][1][1][0][RTW89_UK][1][38] = 54,
+ [0][1][1][0][RTW89_UK][0][38] = 18,
+ [0][1][1][0][RTW89_FCC][1][40] = -4,
+ [0][1][1][0][RTW89_FCC][2][40] = 68,
+ [0][1][1][0][RTW89_ETSI][1][40] = 54,
+ [0][1][1][0][RTW89_ETSI][0][40] = 18,
+ [0][1][1][0][RTW89_MKK][1][40] = 54,
+ [0][1][1][0][RTW89_MKK][0][40] = 16,
+ [0][1][1][0][RTW89_IC][1][40] = -4,
+ [0][1][1][0][RTW89_KCC][1][40] = 12,
+ [0][1][1][0][RTW89_KCC][0][40] = 14,
+ [0][1][1][0][RTW89_ACMA][1][40] = 54,
+ [0][1][1][0][RTW89_ACMA][0][40] = 18,
+ [0][1][1][0][RTW89_CHILE][1][40] = -4,
+ [0][1][1][0][RTW89_QATAR][1][40] = 54,
+ [0][1][1][0][RTW89_QATAR][0][40] = 18,
+ [0][1][1][0][RTW89_UK][1][40] = 54,
+ [0][1][1][0][RTW89_UK][0][40] = 18,
+ [0][1][1][0][RTW89_FCC][1][42] = -4,
+ [0][1][1][0][RTW89_FCC][2][42] = 68,
+ [0][1][1][0][RTW89_ETSI][1][42] = 54,
+ [0][1][1][0][RTW89_ETSI][0][42] = 18,
+ [0][1][1][0][RTW89_MKK][1][42] = 54,
+ [0][1][1][0][RTW89_MKK][0][42] = 16,
+ [0][1][1][0][RTW89_IC][1][42] = -4,
+ [0][1][1][0][RTW89_KCC][1][42] = 12,
+ [0][1][1][0][RTW89_KCC][0][42] = 14,
+ [0][1][1][0][RTW89_ACMA][1][42] = 54,
+ [0][1][1][0][RTW89_ACMA][0][42] = 18,
+ [0][1][1][0][RTW89_CHILE][1][42] = -4,
+ [0][1][1][0][RTW89_QATAR][1][42] = 54,
+ [0][1][1][0][RTW89_QATAR][0][42] = 18,
+ [0][1][1][0][RTW89_UK][1][42] = 54,
+ [0][1][1][0][RTW89_UK][0][42] = 18,
+ [0][1][1][0][RTW89_FCC][1][44] = -2,
+ [0][1][1][0][RTW89_FCC][2][44] = 68,
+ [0][1][1][0][RTW89_ETSI][1][44] = 54,
+ [0][1][1][0][RTW89_ETSI][0][44] = 18,
+ [0][1][1][0][RTW89_MKK][1][44] = 34,
+ [0][1][1][0][RTW89_MKK][0][44] = 16,
+ [0][1][1][0][RTW89_IC][1][44] = -2,
+ [0][1][1][0][RTW89_KCC][1][44] = 12,
+ [0][1][1][0][RTW89_KCC][0][44] = 12,
+ [0][1][1][0][RTW89_ACMA][1][44] = 54,
+ [0][1][1][0][RTW89_ACMA][0][44] = 18,
+ [0][1][1][0][RTW89_CHILE][1][44] = -2,
+ [0][1][1][0][RTW89_QATAR][1][44] = 54,
+ [0][1][1][0][RTW89_QATAR][0][44] = 18,
+ [0][1][1][0][RTW89_UK][1][44] = 54,
+ [0][1][1][0][RTW89_UK][0][44] = 18,
+ [0][1][1][0][RTW89_FCC][1][45] = -2,
+ [0][1][1][0][RTW89_FCC][2][45] = 127,
+ [0][1][1][0][RTW89_ETSI][1][45] = 127,
+ [0][1][1][0][RTW89_ETSI][0][45] = 127,
+ [0][1][1][0][RTW89_MKK][1][45] = 127,
+ [0][1][1][0][RTW89_MKK][0][45] = 127,
+ [0][1][1][0][RTW89_IC][1][45] = -2,
+ [0][1][1][0][RTW89_KCC][1][45] = 12,
+ [0][1][1][0][RTW89_KCC][0][45] = 127,
+ [0][1][1][0][RTW89_ACMA][1][45] = 127,
+ [0][1][1][0][RTW89_ACMA][0][45] = 127,
+ [0][1][1][0][RTW89_CHILE][1][45] = -2,
+ [0][1][1][0][RTW89_QATAR][1][45] = 127,
+ [0][1][1][0][RTW89_QATAR][0][45] = 127,
+ [0][1][1][0][RTW89_UK][1][45] = 127,
+ [0][1][1][0][RTW89_UK][0][45] = 127,
+ [0][1][1][0][RTW89_FCC][1][47] = -2,
+ [0][1][1][0][RTW89_FCC][2][47] = 127,
+ [0][1][1][0][RTW89_ETSI][1][47] = 127,
+ [0][1][1][0][RTW89_ETSI][0][47] = 127,
+ [0][1][1][0][RTW89_MKK][1][47] = 127,
+ [0][1][1][0][RTW89_MKK][0][47] = 127,
+ [0][1][1][0][RTW89_IC][1][47] = -2,
+ [0][1][1][0][RTW89_KCC][1][47] = 12,
+ [0][1][1][0][RTW89_KCC][0][47] = 127,
+ [0][1][1][0][RTW89_ACMA][1][47] = 127,
+ [0][1][1][0][RTW89_ACMA][0][47] = 127,
+ [0][1][1][0][RTW89_CHILE][1][47] = -2,
+ [0][1][1][0][RTW89_QATAR][1][47] = 127,
+ [0][1][1][0][RTW89_QATAR][0][47] = 127,
+ [0][1][1][0][RTW89_UK][1][47] = 127,
+ [0][1][1][0][RTW89_UK][0][47] = 127,
+ [0][1][1][0][RTW89_FCC][1][49] = -2,
+ [0][1][1][0][RTW89_FCC][2][49] = 127,
+ [0][1][1][0][RTW89_ETSI][1][49] = 127,
+ [0][1][1][0][RTW89_ETSI][0][49] = 127,
+ [0][1][1][0][RTW89_MKK][1][49] = 127,
+ [0][1][1][0][RTW89_MKK][0][49] = 127,
+ [0][1][1][0][RTW89_IC][1][49] = -2,
+ [0][1][1][0][RTW89_KCC][1][49] = 12,
+ [0][1][1][0][RTW89_KCC][0][49] = 127,
+ [0][1][1][0][RTW89_ACMA][1][49] = 127,
+ [0][1][1][0][RTW89_ACMA][0][49] = 127,
+ [0][1][1][0][RTW89_CHILE][1][49] = -2,
+ [0][1][1][0][RTW89_QATAR][1][49] = 127,
+ [0][1][1][0][RTW89_QATAR][0][49] = 127,
+ [0][1][1][0][RTW89_UK][1][49] = 127,
+ [0][1][1][0][RTW89_UK][0][49] = 127,
+ [0][1][1][0][RTW89_FCC][1][51] = -2,
+ [0][1][1][0][RTW89_FCC][2][51] = 127,
+ [0][1][1][0][RTW89_ETSI][1][51] = 127,
+ [0][1][1][0][RTW89_ETSI][0][51] = 127,
+ [0][1][1][0][RTW89_MKK][1][51] = 127,
+ [0][1][1][0][RTW89_MKK][0][51] = 127,
+ [0][1][1][0][RTW89_IC][1][51] = -2,
+ [0][1][1][0][RTW89_KCC][1][51] = 12,
+ [0][1][1][0][RTW89_KCC][0][51] = 127,
+ [0][1][1][0][RTW89_ACMA][1][51] = 127,
+ [0][1][1][0][RTW89_ACMA][0][51] = 127,
+ [0][1][1][0][RTW89_CHILE][1][51] = -2,
+ [0][1][1][0][RTW89_QATAR][1][51] = 127,
+ [0][1][1][0][RTW89_QATAR][0][51] = 127,
+ [0][1][1][0][RTW89_UK][1][51] = 127,
+ [0][1][1][0][RTW89_UK][0][51] = 127,
+ [0][1][1][0][RTW89_FCC][1][53] = -2,
+ [0][1][1][0][RTW89_FCC][2][53] = 127,
+ [0][1][1][0][RTW89_ETSI][1][53] = 127,
+ [0][1][1][0][RTW89_ETSI][0][53] = 127,
+ [0][1][1][0][RTW89_MKK][1][53] = 127,
+ [0][1][1][0][RTW89_MKK][0][53] = 127,
+ [0][1][1][0][RTW89_IC][1][53] = -2,
+ [0][1][1][0][RTW89_KCC][1][53] = 12,
+ [0][1][1][0][RTW89_KCC][0][53] = 127,
+ [0][1][1][0][RTW89_ACMA][1][53] = 127,
+ [0][1][1][0][RTW89_ACMA][0][53] = 127,
+ [0][1][1][0][RTW89_CHILE][1][53] = -2,
+ [0][1][1][0][RTW89_QATAR][1][53] = 127,
+ [0][1][1][0][RTW89_QATAR][0][53] = 127,
+ [0][1][1][0][RTW89_UK][1][53] = 127,
+ [0][1][1][0][RTW89_UK][0][53] = 127,
+ [0][1][1][0][RTW89_FCC][1][55] = -2,
+ [0][1][1][0][RTW89_FCC][2][55] = 68,
+ [0][1][1][0][RTW89_ETSI][1][55] = 127,
+ [0][1][1][0][RTW89_ETSI][0][55] = 127,
+ [0][1][1][0][RTW89_MKK][1][55] = 127,
+ [0][1][1][0][RTW89_MKK][0][55] = 127,
+ [0][1][1][0][RTW89_IC][1][55] = -2,
+ [0][1][1][0][RTW89_KCC][1][55] = 12,
+ [0][1][1][0][RTW89_KCC][0][55] = 127,
+ [0][1][1][0][RTW89_ACMA][1][55] = 127,
+ [0][1][1][0][RTW89_ACMA][0][55] = 127,
+ [0][1][1][0][RTW89_CHILE][1][55] = -2,
+ [0][1][1][0][RTW89_QATAR][1][55] = 127,
+ [0][1][1][0][RTW89_QATAR][0][55] = 127,
+ [0][1][1][0][RTW89_UK][1][55] = 127,
+ [0][1][1][0][RTW89_UK][0][55] = 127,
+ [0][1][1][0][RTW89_FCC][1][57] = -2,
+ [0][1][1][0][RTW89_FCC][2][57] = 68,
+ [0][1][1][0][RTW89_ETSI][1][57] = 127,
+ [0][1][1][0][RTW89_ETSI][0][57] = 127,
+ [0][1][1][0][RTW89_MKK][1][57] = 127,
+ [0][1][1][0][RTW89_MKK][0][57] = 127,
+ [0][1][1][0][RTW89_IC][1][57] = -2,
+ [0][1][1][0][RTW89_KCC][1][57] = 12,
+ [0][1][1][0][RTW89_KCC][0][57] = 127,
+ [0][1][1][0][RTW89_ACMA][1][57] = 127,
+ [0][1][1][0][RTW89_ACMA][0][57] = 127,
+ [0][1][1][0][RTW89_CHILE][1][57] = -2,
+ [0][1][1][0][RTW89_QATAR][1][57] = 127,
+ [0][1][1][0][RTW89_QATAR][0][57] = 127,
+ [0][1][1][0][RTW89_UK][1][57] = 127,
+ [0][1][1][0][RTW89_UK][0][57] = 127,
+ [0][1][1][0][RTW89_FCC][1][59] = -2,
+ [0][1][1][0][RTW89_FCC][2][59] = 68,
+ [0][1][1][0][RTW89_ETSI][1][59] = 127,
+ [0][1][1][0][RTW89_ETSI][0][59] = 127,
+ [0][1][1][0][RTW89_MKK][1][59] = 127,
+ [0][1][1][0][RTW89_MKK][0][59] = 127,
+ [0][1][1][0][RTW89_IC][1][59] = -2,
+ [0][1][1][0][RTW89_KCC][1][59] = 12,
+ [0][1][1][0][RTW89_KCC][0][59] = 127,
+ [0][1][1][0][RTW89_ACMA][1][59] = 127,
+ [0][1][1][0][RTW89_ACMA][0][59] = 127,
+ [0][1][1][0][RTW89_CHILE][1][59] = -2,
+ [0][1][1][0][RTW89_QATAR][1][59] = 127,
+ [0][1][1][0][RTW89_QATAR][0][59] = 127,
+ [0][1][1][0][RTW89_UK][1][59] = 127,
+ [0][1][1][0][RTW89_UK][0][59] = 127,
+ [0][1][1][0][RTW89_FCC][1][60] = -2,
+ [0][1][1][0][RTW89_FCC][2][60] = 68,
+ [0][1][1][0][RTW89_ETSI][1][60] = 127,
+ [0][1][1][0][RTW89_ETSI][0][60] = 127,
+ [0][1][1][0][RTW89_MKK][1][60] = 127,
+ [0][1][1][0][RTW89_MKK][0][60] = 127,
+ [0][1][1][0][RTW89_IC][1][60] = -2,
+ [0][1][1][0][RTW89_KCC][1][60] = 12,
+ [0][1][1][0][RTW89_KCC][0][60] = 127,
+ [0][1][1][0][RTW89_ACMA][1][60] = 127,
+ [0][1][1][0][RTW89_ACMA][0][60] = 127,
+ [0][1][1][0][RTW89_CHILE][1][60] = -2,
+ [0][1][1][0][RTW89_QATAR][1][60] = 127,
+ [0][1][1][0][RTW89_QATAR][0][60] = 127,
+ [0][1][1][0][RTW89_UK][1][60] = 127,
+ [0][1][1][0][RTW89_UK][0][60] = 127,
+ [0][1][1][0][RTW89_FCC][1][62] = -2,
+ [0][1][1][0][RTW89_FCC][2][62] = 68,
+ [0][1][1][0][RTW89_ETSI][1][62] = 127,
+ [0][1][1][0][RTW89_ETSI][0][62] = 127,
+ [0][1][1][0][RTW89_MKK][1][62] = 127,
+ [0][1][1][0][RTW89_MKK][0][62] = 127,
+ [0][1][1][0][RTW89_IC][1][62] = -2,
+ [0][1][1][0][RTW89_KCC][1][62] = 12,
+ [0][1][1][0][RTW89_KCC][0][62] = 127,
+ [0][1][1][0][RTW89_ACMA][1][62] = 127,
+ [0][1][1][0][RTW89_ACMA][0][62] = 127,
+ [0][1][1][0][RTW89_CHILE][1][62] = -2,
+ [0][1][1][0][RTW89_QATAR][1][62] = 127,
+ [0][1][1][0][RTW89_QATAR][0][62] = 127,
+ [0][1][1][0][RTW89_UK][1][62] = 127,
+ [0][1][1][0][RTW89_UK][0][62] = 127,
+ [0][1][1][0][RTW89_FCC][1][64] = -2,
+ [0][1][1][0][RTW89_FCC][2][64] = 68,
+ [0][1][1][0][RTW89_ETSI][1][64] = 127,
+ [0][1][1][0][RTW89_ETSI][0][64] = 127,
+ [0][1][1][0][RTW89_MKK][1][64] = 127,
+ [0][1][1][0][RTW89_MKK][0][64] = 127,
+ [0][1][1][0][RTW89_IC][1][64] = -2,
+ [0][1][1][0][RTW89_KCC][1][64] = 12,
+ [0][1][1][0][RTW89_KCC][0][64] = 127,
+ [0][1][1][0][RTW89_ACMA][1][64] = 127,
+ [0][1][1][0][RTW89_ACMA][0][64] = 127,
+ [0][1][1][0][RTW89_CHILE][1][64] = -2,
+ [0][1][1][0][RTW89_QATAR][1][64] = 127,
+ [0][1][1][0][RTW89_QATAR][0][64] = 127,
+ [0][1][1][0][RTW89_UK][1][64] = 127,
+ [0][1][1][0][RTW89_UK][0][64] = 127,
+ [0][1][1][0][RTW89_FCC][1][66] = -2,
+ [0][1][1][0][RTW89_FCC][2][66] = 68,
+ [0][1][1][0][RTW89_ETSI][1][66] = 127,
+ [0][1][1][0][RTW89_ETSI][0][66] = 127,
+ [0][1][1][0][RTW89_MKK][1][66] = 127,
+ [0][1][1][0][RTW89_MKK][0][66] = 127,
+ [0][1][1][0][RTW89_IC][1][66] = -2,
+ [0][1][1][0][RTW89_KCC][1][66] = 12,
+ [0][1][1][0][RTW89_KCC][0][66] = 127,
+ [0][1][1][0][RTW89_ACMA][1][66] = 127,
+ [0][1][1][0][RTW89_ACMA][0][66] = 127,
+ [0][1][1][0][RTW89_CHILE][1][66] = -2,
+ [0][1][1][0][RTW89_QATAR][1][66] = 127,
+ [0][1][1][0][RTW89_QATAR][0][66] = 127,
+ [0][1][1][0][RTW89_UK][1][66] = 127,
+ [0][1][1][0][RTW89_UK][0][66] = 127,
+ [0][1][1][0][RTW89_FCC][1][68] = -2,
+ [0][1][1][0][RTW89_FCC][2][68] = 68,
+ [0][1][1][0][RTW89_ETSI][1][68] = 127,
+ [0][1][1][0][RTW89_ETSI][0][68] = 127,
+ [0][1][1][0][RTW89_MKK][1][68] = 127,
+ [0][1][1][0][RTW89_MKK][0][68] = 127,
+ [0][1][1][0][RTW89_IC][1][68] = -2,
+ [0][1][1][0][RTW89_KCC][1][68] = 12,
+ [0][1][1][0][RTW89_KCC][0][68] = 127,
+ [0][1][1][0][RTW89_ACMA][1][68] = 127,
+ [0][1][1][0][RTW89_ACMA][0][68] = 127,
+ [0][1][1][0][RTW89_CHILE][1][68] = -2,
+ [0][1][1][0][RTW89_QATAR][1][68] = 127,
+ [0][1][1][0][RTW89_QATAR][0][68] = 127,
+ [0][1][1][0][RTW89_UK][1][68] = 127,
+ [0][1][1][0][RTW89_UK][0][68] = 127,
+ [0][1][1][0][RTW89_FCC][1][70] = -2,
+ [0][1][1][0][RTW89_FCC][2][70] = 68,
+ [0][1][1][0][RTW89_ETSI][1][70] = 127,
+ [0][1][1][0][RTW89_ETSI][0][70] = 127,
+ [0][1][1][0][RTW89_MKK][1][70] = 127,
+ [0][1][1][0][RTW89_MKK][0][70] = 127,
+ [0][1][1][0][RTW89_IC][1][70] = -2,
+ [0][1][1][0][RTW89_KCC][1][70] = 12,
+ [0][1][1][0][RTW89_KCC][0][70] = 127,
+ [0][1][1][0][RTW89_ACMA][1][70] = 127,
+ [0][1][1][0][RTW89_ACMA][0][70] = 127,
+ [0][1][1][0][RTW89_CHILE][1][70] = -2,
+ [0][1][1][0][RTW89_QATAR][1][70] = 127,
+ [0][1][1][0][RTW89_QATAR][0][70] = 127,
+ [0][1][1][0][RTW89_UK][1][70] = 127,
+ [0][1][1][0][RTW89_UK][0][70] = 127,
+ [0][1][1][0][RTW89_FCC][1][72] = -2,
+ [0][1][1][0][RTW89_FCC][2][72] = 68,
+ [0][1][1][0][RTW89_ETSI][1][72] = 127,
+ [0][1][1][0][RTW89_ETSI][0][72] = 127,
+ [0][1][1][0][RTW89_MKK][1][72] = 127,
+ [0][1][1][0][RTW89_MKK][0][72] = 127,
+ [0][1][1][0][RTW89_IC][1][72] = -2,
+ [0][1][1][0][RTW89_KCC][1][72] = 12,
+ [0][1][1][0][RTW89_KCC][0][72] = 127,
+ [0][1][1][0][RTW89_ACMA][1][72] = 127,
+ [0][1][1][0][RTW89_ACMA][0][72] = 127,
+ [0][1][1][0][RTW89_CHILE][1][72] = -2,
+ [0][1][1][0][RTW89_QATAR][1][72] = 127,
+ [0][1][1][0][RTW89_QATAR][0][72] = 127,
+ [0][1][1][0][RTW89_UK][1][72] = 127,
+ [0][1][1][0][RTW89_UK][0][72] = 127,
+ [0][1][1][0][RTW89_FCC][1][74] = -2,
+ [0][1][1][0][RTW89_FCC][2][74] = 68,
+ [0][1][1][0][RTW89_ETSI][1][74] = 127,
+ [0][1][1][0][RTW89_ETSI][0][74] = 127,
+ [0][1][1][0][RTW89_MKK][1][74] = 127,
+ [0][1][1][0][RTW89_MKK][0][74] = 127,
+ [0][1][1][0][RTW89_IC][1][74] = -2,
+ [0][1][1][0][RTW89_KCC][1][74] = 12,
+ [0][1][1][0][RTW89_KCC][0][74] = 127,
+ [0][1][1][0][RTW89_ACMA][1][74] = 127,
+ [0][1][1][0][RTW89_ACMA][0][74] = 127,
+ [0][1][1][0][RTW89_CHILE][1][74] = -2,
+ [0][1][1][0][RTW89_QATAR][1][74] = 127,
+ [0][1][1][0][RTW89_QATAR][0][74] = 127,
+ [0][1][1][0][RTW89_UK][1][74] = 127,
+ [0][1][1][0][RTW89_UK][0][74] = 127,
+ [0][1][1][0][RTW89_FCC][1][75] = -2,
+ [0][1][1][0][RTW89_FCC][2][75] = 68,
+ [0][1][1][0][RTW89_ETSI][1][75] = 127,
+ [0][1][1][0][RTW89_ETSI][0][75] = 127,
+ [0][1][1][0][RTW89_MKK][1][75] = 127,
+ [0][1][1][0][RTW89_MKK][0][75] = 127,
+ [0][1][1][0][RTW89_IC][1][75] = -2,
+ [0][1][1][0][RTW89_KCC][1][75] = 12,
+ [0][1][1][0][RTW89_KCC][0][75] = 127,
+ [0][1][1][0][RTW89_ACMA][1][75] = 127,
+ [0][1][1][0][RTW89_ACMA][0][75] = 127,
+ [0][1][1][0][RTW89_CHILE][1][75] = -2,
+ [0][1][1][0][RTW89_QATAR][1][75] = 127,
+ [0][1][1][0][RTW89_QATAR][0][75] = 127,
+ [0][1][1][0][RTW89_UK][1][75] = 127,
+ [0][1][1][0][RTW89_UK][0][75] = 127,
+ [0][1][1][0][RTW89_FCC][1][77] = -2,
+ [0][1][1][0][RTW89_FCC][2][77] = 68,
+ [0][1][1][0][RTW89_ETSI][1][77] = 127,
+ [0][1][1][0][RTW89_ETSI][0][77] = 127,
+ [0][1][1][0][RTW89_MKK][1][77] = 127,
+ [0][1][1][0][RTW89_MKK][0][77] = 127,
+ [0][1][1][0][RTW89_IC][1][77] = -2,
+ [0][1][1][0][RTW89_KCC][1][77] = 12,
+ [0][1][1][0][RTW89_KCC][0][77] = 127,
+ [0][1][1][0][RTW89_ACMA][1][77] = 127,
+ [0][1][1][0][RTW89_ACMA][0][77] = 127,
+ [0][1][1][0][RTW89_CHILE][1][77] = -2,
+ [0][1][1][0][RTW89_QATAR][1][77] = 127,
+ [0][1][1][0][RTW89_QATAR][0][77] = 127,
+ [0][1][1][0][RTW89_UK][1][77] = 127,
+ [0][1][1][0][RTW89_UK][0][77] = 127,
+ [0][1][1][0][RTW89_FCC][1][79] = -2,
+ [0][1][1][0][RTW89_FCC][2][79] = 68,
+ [0][1][1][0][RTW89_ETSI][1][79] = 127,
+ [0][1][1][0][RTW89_ETSI][0][79] = 127,
+ [0][1][1][0][RTW89_MKK][1][79] = 127,
+ [0][1][1][0][RTW89_MKK][0][79] = 127,
+ [0][1][1][0][RTW89_IC][1][79] = -2,
+ [0][1][1][0][RTW89_KCC][1][79] = 12,
+ [0][1][1][0][RTW89_KCC][0][79] = 127,
+ [0][1][1][0][RTW89_ACMA][1][79] = 127,
+ [0][1][1][0][RTW89_ACMA][0][79] = 127,
+ [0][1][1][0][RTW89_CHILE][1][79] = -2,
+ [0][1][1][0][RTW89_QATAR][1][79] = 127,
+ [0][1][1][0][RTW89_QATAR][0][79] = 127,
+ [0][1][1][0][RTW89_UK][1][79] = 127,
+ [0][1][1][0][RTW89_UK][0][79] = 127,
+ [0][1][1][0][RTW89_FCC][1][81] = -2,
+ [0][1][1][0][RTW89_FCC][2][81] = 68,
+ [0][1][1][0][RTW89_ETSI][1][81] = 127,
+ [0][1][1][0][RTW89_ETSI][0][81] = 127,
+ [0][1][1][0][RTW89_MKK][1][81] = 127,
+ [0][1][1][0][RTW89_MKK][0][81] = 127,
+ [0][1][1][0][RTW89_IC][1][81] = -2,
+ [0][1][1][0][RTW89_KCC][1][81] = 12,
+ [0][1][1][0][RTW89_KCC][0][81] = 127,
+ [0][1][1][0][RTW89_ACMA][1][81] = 127,
+ [0][1][1][0][RTW89_ACMA][0][81] = 127,
+ [0][1][1][0][RTW89_CHILE][1][81] = -2,
+ [0][1][1][0][RTW89_QATAR][1][81] = 127,
+ [0][1][1][0][RTW89_QATAR][0][81] = 127,
+ [0][1][1][0][RTW89_UK][1][81] = 127,
+ [0][1][1][0][RTW89_UK][0][81] = 127,
+ [0][1][1][0][RTW89_FCC][1][83] = -2,
+ [0][1][1][0][RTW89_FCC][2][83] = 68,
+ [0][1][1][0][RTW89_ETSI][1][83] = 127,
+ [0][1][1][0][RTW89_ETSI][0][83] = 127,
+ [0][1][1][0][RTW89_MKK][1][83] = 127,
+ [0][1][1][0][RTW89_MKK][0][83] = 127,
+ [0][1][1][0][RTW89_IC][1][83] = -2,
+ [0][1][1][0][RTW89_KCC][1][83] = 20,
+ [0][1][1][0][RTW89_KCC][0][83] = 127,
+ [0][1][1][0][RTW89_ACMA][1][83] = 127,
+ [0][1][1][0][RTW89_ACMA][0][83] = 127,
+ [0][1][1][0][RTW89_CHILE][1][83] = -2,
+ [0][1][1][0][RTW89_QATAR][1][83] = 127,
+ [0][1][1][0][RTW89_QATAR][0][83] = 127,
+ [0][1][1][0][RTW89_UK][1][83] = 127,
+ [0][1][1][0][RTW89_UK][0][83] = 127,
+ [0][1][1][0][RTW89_FCC][1][85] = -2,
+ [0][1][1][0][RTW89_FCC][2][85] = 68,
+ [0][1][1][0][RTW89_ETSI][1][85] = 127,
+ [0][1][1][0][RTW89_ETSI][0][85] = 127,
+ [0][1][1][0][RTW89_MKK][1][85] = 127,
+ [0][1][1][0][RTW89_MKK][0][85] = 127,
+ [0][1][1][0][RTW89_IC][1][85] = -2,
+ [0][1][1][0][RTW89_KCC][1][85] = 20,
+ [0][1][1][0][RTW89_KCC][0][85] = 127,
+ [0][1][1][0][RTW89_ACMA][1][85] = 127,
+ [0][1][1][0][RTW89_ACMA][0][85] = 127,
+ [0][1][1][0][RTW89_CHILE][1][85] = -2,
+ [0][1][1][0][RTW89_QATAR][1][85] = 127,
+ [0][1][1][0][RTW89_QATAR][0][85] = 127,
+ [0][1][1][0][RTW89_UK][1][85] = 127,
+ [0][1][1][0][RTW89_UK][0][85] = 127,
+ [0][1][1][0][RTW89_FCC][1][87] = -2,
+ [0][1][1][0][RTW89_FCC][2][87] = 127,
+ [0][1][1][0][RTW89_ETSI][1][87] = 127,
+ [0][1][1][0][RTW89_ETSI][0][87] = 127,
+ [0][1][1][0][RTW89_MKK][1][87] = 127,
+ [0][1][1][0][RTW89_MKK][0][87] = 127,
+ [0][1][1][0][RTW89_IC][1][87] = -2,
+ [0][1][1][0][RTW89_KCC][1][87] = 20,
+ [0][1][1][0][RTW89_KCC][0][87] = 127,
+ [0][1][1][0][RTW89_ACMA][1][87] = 127,
+ [0][1][1][0][RTW89_ACMA][0][87] = 127,
+ [0][1][1][0][RTW89_CHILE][1][87] = -2,
+ [0][1][1][0][RTW89_QATAR][1][87] = 127,
+ [0][1][1][0][RTW89_QATAR][0][87] = 127,
+ [0][1][1][0][RTW89_UK][1][87] = 127,
+ [0][1][1][0][RTW89_UK][0][87] = 127,
+ [0][1][1][0][RTW89_FCC][1][89] = -2,
+ [0][1][1][0][RTW89_FCC][2][89] = 127,
+ [0][1][1][0][RTW89_ETSI][1][89] = 127,
+ [0][1][1][0][RTW89_ETSI][0][89] = 127,
+ [0][1][1][0][RTW89_MKK][1][89] = 127,
+ [0][1][1][0][RTW89_MKK][0][89] = 127,
+ [0][1][1][0][RTW89_IC][1][89] = -2,
+ [0][1][1][0][RTW89_KCC][1][89] = 20,
+ [0][1][1][0][RTW89_KCC][0][89] = 127,
+ [0][1][1][0][RTW89_ACMA][1][89] = 127,
+ [0][1][1][0][RTW89_ACMA][0][89] = 127,
+ [0][1][1][0][RTW89_CHILE][1][89] = -2,
+ [0][1][1][0][RTW89_QATAR][1][89] = 127,
+ [0][1][1][0][RTW89_QATAR][0][89] = 127,
+ [0][1][1][0][RTW89_UK][1][89] = 127,
+ [0][1][1][0][RTW89_UK][0][89] = 127,
+ [0][1][1][0][RTW89_FCC][1][90] = -2,
+ [0][1][1][0][RTW89_FCC][2][90] = 127,
+ [0][1][1][0][RTW89_ETSI][1][90] = 127,
+ [0][1][1][0][RTW89_ETSI][0][90] = 127,
+ [0][1][1][0][RTW89_MKK][1][90] = 127,
+ [0][1][1][0][RTW89_MKK][0][90] = 127,
+ [0][1][1][0][RTW89_IC][1][90] = -2,
+ [0][1][1][0][RTW89_KCC][1][90] = 20,
+ [0][1][1][0][RTW89_KCC][0][90] = 127,
+ [0][1][1][0][RTW89_ACMA][1][90] = 127,
+ [0][1][1][0][RTW89_ACMA][0][90] = 127,
+ [0][1][1][0][RTW89_CHILE][1][90] = -2,
+ [0][1][1][0][RTW89_QATAR][1][90] = 127,
+ [0][1][1][0][RTW89_QATAR][0][90] = 127,
+ [0][1][1][0][RTW89_UK][1][90] = 127,
+ [0][1][1][0][RTW89_UK][0][90] = 127,
+ [0][1][1][0][RTW89_FCC][1][92] = -2,
+ [0][1][1][0][RTW89_FCC][2][92] = 127,
+ [0][1][1][0][RTW89_ETSI][1][92] = 127,
+ [0][1][1][0][RTW89_ETSI][0][92] = 127,
+ [0][1][1][0][RTW89_MKK][1][92] = 127,
+ [0][1][1][0][RTW89_MKK][0][92] = 127,
+ [0][1][1][0][RTW89_IC][1][92] = -2,
+ [0][1][1][0][RTW89_KCC][1][92] = 20,
+ [0][1][1][0][RTW89_KCC][0][92] = 127,
+ [0][1][1][0][RTW89_ACMA][1][92] = 127,
+ [0][1][1][0][RTW89_ACMA][0][92] = 127,
+ [0][1][1][0][RTW89_CHILE][1][92] = -2,
+ [0][1][1][0][RTW89_QATAR][1][92] = 127,
+ [0][1][1][0][RTW89_QATAR][0][92] = 127,
+ [0][1][1][0][RTW89_UK][1][92] = 127,
+ [0][1][1][0][RTW89_UK][0][92] = 127,
+ [0][1][1][0][RTW89_FCC][1][94] = -2,
+ [0][1][1][0][RTW89_FCC][2][94] = 127,
+ [0][1][1][0][RTW89_ETSI][1][94] = 127,
+ [0][1][1][0][RTW89_ETSI][0][94] = 127,
+ [0][1][1][0][RTW89_MKK][1][94] = 127,
+ [0][1][1][0][RTW89_MKK][0][94] = 127,
+ [0][1][1][0][RTW89_IC][1][94] = -2,
+ [0][1][1][0][RTW89_KCC][1][94] = 20,
+ [0][1][1][0][RTW89_KCC][0][94] = 127,
+ [0][1][1][0][RTW89_ACMA][1][94] = 127,
+ [0][1][1][0][RTW89_ACMA][0][94] = 127,
+ [0][1][1][0][RTW89_CHILE][1][94] = -2,
+ [0][1][1][0][RTW89_QATAR][1][94] = 127,
+ [0][1][1][0][RTW89_QATAR][0][94] = 127,
+ [0][1][1][0][RTW89_UK][1][94] = 127,
+ [0][1][1][0][RTW89_UK][0][94] = 127,
+ [0][1][1][0][RTW89_FCC][1][96] = -2,
+ [0][1][1][0][RTW89_FCC][2][96] = 127,
+ [0][1][1][0][RTW89_ETSI][1][96] = 127,
+ [0][1][1][0][RTW89_ETSI][0][96] = 127,
+ [0][1][1][0][RTW89_MKK][1][96] = 127,
+ [0][1][1][0][RTW89_MKK][0][96] = 127,
+ [0][1][1][0][RTW89_IC][1][96] = -2,
+ [0][1][1][0][RTW89_KCC][1][96] = 20,
+ [0][1][1][0][RTW89_KCC][0][96] = 127,
+ [0][1][1][0][RTW89_ACMA][1][96] = 127,
+ [0][1][1][0][RTW89_ACMA][0][96] = 127,
+ [0][1][1][0][RTW89_CHILE][1][96] = -2,
+ [0][1][1][0][RTW89_QATAR][1][96] = 127,
+ [0][1][1][0][RTW89_QATAR][0][96] = 127,
+ [0][1][1][0][RTW89_UK][1][96] = 127,
+ [0][1][1][0][RTW89_UK][0][96] = 127,
+ [0][1][1][0][RTW89_FCC][1][98] = -2,
+ [0][1][1][0][RTW89_FCC][2][98] = 127,
+ [0][1][1][0][RTW89_ETSI][1][98] = 127,
+ [0][1][1][0][RTW89_ETSI][0][98] = 127,
+ [0][1][1][0][RTW89_MKK][1][98] = 127,
+ [0][1][1][0][RTW89_MKK][0][98] = 127,
+ [0][1][1][0][RTW89_IC][1][98] = -2,
+ [0][1][1][0][RTW89_KCC][1][98] = 20,
+ [0][1][1][0][RTW89_KCC][0][98] = 127,
+ [0][1][1][0][RTW89_ACMA][1][98] = 127,
+ [0][1][1][0][RTW89_ACMA][0][98] = 127,
+ [0][1][1][0][RTW89_CHILE][1][98] = -2,
+ [0][1][1][0][RTW89_QATAR][1][98] = 127,
+ [0][1][1][0][RTW89_QATAR][0][98] = 127,
+ [0][1][1][0][RTW89_UK][1][98] = 127,
+ [0][1][1][0][RTW89_UK][0][98] = 127,
+ [0][1][1][0][RTW89_FCC][1][100] = -2,
+ [0][1][1][0][RTW89_FCC][2][100] = 127,
+ [0][1][1][0][RTW89_ETSI][1][100] = 127,
+ [0][1][1][0][RTW89_ETSI][0][100] = 127,
+ [0][1][1][0][RTW89_MKK][1][100] = 127,
+ [0][1][1][0][RTW89_MKK][0][100] = 127,
+ [0][1][1][0][RTW89_IC][1][100] = -2,
+ [0][1][1][0][RTW89_KCC][1][100] = 20,
+ [0][1][1][0][RTW89_KCC][0][100] = 127,
+ [0][1][1][0][RTW89_ACMA][1][100] = 127,
+ [0][1][1][0][RTW89_ACMA][0][100] = 127,
+ [0][1][1][0][RTW89_CHILE][1][100] = -2,
+ [0][1][1][0][RTW89_QATAR][1][100] = 127,
+ [0][1][1][0][RTW89_QATAR][0][100] = 127,
+ [0][1][1][0][RTW89_UK][1][100] = 127,
+ [0][1][1][0][RTW89_UK][0][100] = 127,
+ [0][1][1][0][RTW89_FCC][1][102] = -2,
+ [0][1][1][0][RTW89_FCC][2][102] = 127,
+ [0][1][1][0][RTW89_ETSI][1][102] = 127,
+ [0][1][1][0][RTW89_ETSI][0][102] = 127,
+ [0][1][1][0][RTW89_MKK][1][102] = 127,
+ [0][1][1][0][RTW89_MKK][0][102] = 127,
+ [0][1][1][0][RTW89_IC][1][102] = -2,
+ [0][1][1][0][RTW89_KCC][1][102] = 20,
+ [0][1][1][0][RTW89_KCC][0][102] = 127,
+ [0][1][1][0][RTW89_ACMA][1][102] = 127,
+ [0][1][1][0][RTW89_ACMA][0][102] = 127,
+ [0][1][1][0][RTW89_CHILE][1][102] = -2,
+ [0][1][1][0][RTW89_QATAR][1][102] = 127,
+ [0][1][1][0][RTW89_QATAR][0][102] = 127,
+ [0][1][1][0][RTW89_UK][1][102] = 127,
+ [0][1][1][0][RTW89_UK][0][102] = 127,
+ [0][1][1][0][RTW89_FCC][1][104] = -2,
+ [0][1][1][0][RTW89_FCC][2][104] = 127,
+ [0][1][1][0][RTW89_ETSI][1][104] = 127,
+ [0][1][1][0][RTW89_ETSI][0][104] = 127,
+ [0][1][1][0][RTW89_MKK][1][104] = 127,
+ [0][1][1][0][RTW89_MKK][0][104] = 127,
+ [0][1][1][0][RTW89_IC][1][104] = -2,
+ [0][1][1][0][RTW89_KCC][1][104] = 20,
+ [0][1][1][0][RTW89_KCC][0][104] = 127,
+ [0][1][1][0][RTW89_ACMA][1][104] = 127,
+ [0][1][1][0][RTW89_ACMA][0][104] = 127,
+ [0][1][1][0][RTW89_CHILE][1][104] = -2,
+ [0][1][1][0][RTW89_QATAR][1][104] = 127,
+ [0][1][1][0][RTW89_QATAR][0][104] = 127,
+ [0][1][1][0][RTW89_UK][1][104] = 127,
+ [0][1][1][0][RTW89_UK][0][104] = 127,
+ [0][1][1][0][RTW89_FCC][1][105] = -2,
+ [0][1][1][0][RTW89_FCC][2][105] = 127,
+ [0][1][1][0][RTW89_ETSI][1][105] = 127,
+ [0][1][1][0][RTW89_ETSI][0][105] = 127,
+ [0][1][1][0][RTW89_MKK][1][105] = 127,
+ [0][1][1][0][RTW89_MKK][0][105] = 127,
+ [0][1][1][0][RTW89_IC][1][105] = -2,
+ [0][1][1][0][RTW89_KCC][1][105] = 20,
+ [0][1][1][0][RTW89_KCC][0][105] = 127,
+ [0][1][1][0][RTW89_ACMA][1][105] = 127,
+ [0][1][1][0][RTW89_ACMA][0][105] = 127,
+ [0][1][1][0][RTW89_CHILE][1][105] = -2,
+ [0][1][1][0][RTW89_QATAR][1][105] = 127,
+ [0][1][1][0][RTW89_QATAR][0][105] = 127,
+ [0][1][1][0][RTW89_UK][1][105] = 127,
+ [0][1][1][0][RTW89_UK][0][105] = 127,
+ [0][1][1][0][RTW89_FCC][1][107] = 1,
+ [0][1][1][0][RTW89_FCC][2][107] = 127,
+ [0][1][1][0][RTW89_ETSI][1][107] = 127,
+ [0][1][1][0][RTW89_ETSI][0][107] = 127,
+ [0][1][1][0][RTW89_MKK][1][107] = 127,
+ [0][1][1][0][RTW89_MKK][0][107] = 127,
+ [0][1][1][0][RTW89_IC][1][107] = 1,
+ [0][1][1][0][RTW89_KCC][1][107] = 20,
+ [0][1][1][0][RTW89_KCC][0][107] = 127,
+ [0][1][1][0][RTW89_ACMA][1][107] = 127,
+ [0][1][1][0][RTW89_ACMA][0][107] = 127,
+ [0][1][1][0][RTW89_CHILE][1][107] = 1,
+ [0][1][1][0][RTW89_QATAR][1][107] = 127,
+ [0][1][1][0][RTW89_QATAR][0][107] = 127,
+ [0][1][1][0][RTW89_UK][1][107] = 127,
+ [0][1][1][0][RTW89_UK][0][107] = 127,
+ [0][1][1][0][RTW89_FCC][1][109] = 1,
+ [0][1][1][0][RTW89_FCC][2][109] = 127,
+ [0][1][1][0][RTW89_ETSI][1][109] = 127,
+ [0][1][1][0][RTW89_ETSI][0][109] = 127,
+ [0][1][1][0][RTW89_MKK][1][109] = 127,
+ [0][1][1][0][RTW89_MKK][0][109] = 127,
+ [0][1][1][0][RTW89_IC][1][109] = 1,
+ [0][1][1][0][RTW89_KCC][1][109] = 20,
+ [0][1][1][0][RTW89_KCC][0][109] = 127,
+ [0][1][1][0][RTW89_ACMA][1][109] = 127,
+ [0][1][1][0][RTW89_ACMA][0][109] = 127,
+ [0][1][1][0][RTW89_CHILE][1][109] = 1,
+ [0][1][1][0][RTW89_QATAR][1][109] = 127,
+ [0][1][1][0][RTW89_QATAR][0][109] = 127,
+ [0][1][1][0][RTW89_UK][1][109] = 127,
+ [0][1][1][0][RTW89_UK][0][109] = 127,
+ [0][1][1][0][RTW89_FCC][1][111] = 127,
+ [0][1][1][0][RTW89_FCC][2][111] = 127,
+ [0][1][1][0][RTW89_ETSI][1][111] = 127,
+ [0][1][1][0][RTW89_ETSI][0][111] = 127,
+ [0][1][1][0][RTW89_MKK][1][111] = 127,
+ [0][1][1][0][RTW89_MKK][0][111] = 127,
+ [0][1][1][0][RTW89_IC][1][111] = 127,
+ [0][1][1][0][RTW89_KCC][1][111] = 127,
+ [0][1][1][0][RTW89_KCC][0][111] = 127,
+ [0][1][1][0][RTW89_ACMA][1][111] = 127,
+ [0][1][1][0][RTW89_ACMA][0][111] = 127,
+ [0][1][1][0][RTW89_CHILE][1][111] = 127,
+ [0][1][1][0][RTW89_QATAR][1][111] = 127,
+ [0][1][1][0][RTW89_QATAR][0][111] = 127,
+ [0][1][1][0][RTW89_UK][1][111] = 127,
+ [0][1][1][0][RTW89_UK][0][111] = 127,
+ [0][1][1][0][RTW89_FCC][1][113] = 127,
+ [0][1][1][0][RTW89_FCC][2][113] = 127,
+ [0][1][1][0][RTW89_ETSI][1][113] = 127,
+ [0][1][1][0][RTW89_ETSI][0][113] = 127,
+ [0][1][1][0][RTW89_MKK][1][113] = 127,
+ [0][1][1][0][RTW89_MKK][0][113] = 127,
+ [0][1][1][0][RTW89_IC][1][113] = 127,
+ [0][1][1][0][RTW89_KCC][1][113] = 127,
+ [0][1][1][0][RTW89_KCC][0][113] = 127,
+ [0][1][1][0][RTW89_ACMA][1][113] = 127,
+ [0][1][1][0][RTW89_ACMA][0][113] = 127,
+ [0][1][1][0][RTW89_CHILE][1][113] = 127,
+ [0][1][1][0][RTW89_QATAR][1][113] = 127,
+ [0][1][1][0][RTW89_QATAR][0][113] = 127,
+ [0][1][1][0][RTW89_UK][1][113] = 127,
+ [0][1][1][0][RTW89_UK][0][113] = 127,
+ [0][1][1][0][RTW89_FCC][1][115] = 127,
+ [0][1][1][0][RTW89_FCC][2][115] = 127,
+ [0][1][1][0][RTW89_ETSI][1][115] = 127,
+ [0][1][1][0][RTW89_ETSI][0][115] = 127,
+ [0][1][1][0][RTW89_MKK][1][115] = 127,
+ [0][1][1][0][RTW89_MKK][0][115] = 127,
+ [0][1][1][0][RTW89_IC][1][115] = 127,
+ [0][1][1][0][RTW89_KCC][1][115] = 127,
+ [0][1][1][0][RTW89_KCC][0][115] = 127,
+ [0][1][1][0][RTW89_ACMA][1][115] = 127,
+ [0][1][1][0][RTW89_ACMA][0][115] = 127,
+ [0][1][1][0][RTW89_CHILE][1][115] = 127,
+ [0][1][1][0][RTW89_QATAR][1][115] = 127,
+ [0][1][1][0][RTW89_QATAR][0][115] = 127,
+ [0][1][1][0][RTW89_UK][1][115] = 127,
+ [0][1][1][0][RTW89_UK][0][115] = 127,
+ [0][1][1][0][RTW89_FCC][1][117] = 127,
+ [0][1][1][0][RTW89_FCC][2][117] = 127,
+ [0][1][1][0][RTW89_ETSI][1][117] = 127,
+ [0][1][1][0][RTW89_ETSI][0][117] = 127,
+ [0][1][1][0][RTW89_MKK][1][117] = 127,
+ [0][1][1][0][RTW89_MKK][0][117] = 127,
+ [0][1][1][0][RTW89_IC][1][117] = 127,
+ [0][1][1][0][RTW89_KCC][1][117] = 127,
+ [0][1][1][0][RTW89_KCC][0][117] = 127,
+ [0][1][1][0][RTW89_ACMA][1][117] = 127,
+ [0][1][1][0][RTW89_ACMA][0][117] = 127,
+ [0][1][1][0][RTW89_CHILE][1][117] = 127,
+ [0][1][1][0][RTW89_QATAR][1][117] = 127,
+ [0][1][1][0][RTW89_QATAR][0][117] = 127,
+ [0][1][1][0][RTW89_UK][1][117] = 127,
+ [0][1][1][0][RTW89_UK][0][117] = 127,
+ [0][1][1][0][RTW89_FCC][1][119] = 127,
+ [0][1][1][0][RTW89_FCC][2][119] = 127,
+ [0][1][1][0][RTW89_ETSI][1][119] = 127,
+ [0][1][1][0][RTW89_ETSI][0][119] = 127,
+ [0][1][1][0][RTW89_MKK][1][119] = 127,
+ [0][1][1][0][RTW89_MKK][0][119] = 127,
+ [0][1][1][0][RTW89_IC][1][119] = 127,
+ [0][1][1][0][RTW89_KCC][1][119] = 127,
+ [0][1][1][0][RTW89_KCC][0][119] = 127,
+ [0][1][1][0][RTW89_ACMA][1][119] = 127,
+ [0][1][1][0][RTW89_ACMA][0][119] = 127,
+ [0][1][1][0][RTW89_CHILE][1][119] = 127,
+ [0][1][1][0][RTW89_QATAR][1][119] = 127,
+ [0][1][1][0][RTW89_QATAR][0][119] = 127,
+ [0][1][1][0][RTW89_UK][1][119] = 127,
+ [0][1][1][0][RTW89_UK][0][119] = 127,
+ [0][0][2][0][RTW89_FCC][1][0] = 24,
+ [0][0][2][0][RTW89_FCC][2][0] = 56,
+ [0][0][2][0][RTW89_ETSI][1][0] = 66,
+ [0][0][2][0][RTW89_ETSI][0][0] = 28,
+ [0][0][2][0][RTW89_MKK][1][0] = 66,
+ [0][0][2][0][RTW89_MKK][0][0] = 26,
+ [0][0][2][0][RTW89_IC][1][0] = 24,
+ [0][0][2][0][RTW89_KCC][1][0] = 24,
+ [0][0][2][0][RTW89_KCC][0][0] = 24,
+ [0][0][2][0][RTW89_ACMA][1][0] = 66,
+ [0][0][2][0][RTW89_ACMA][0][0] = 28,
+ [0][0][2][0][RTW89_CHILE][1][0] = 24,
+ [0][0][2][0][RTW89_QATAR][1][0] = 66,
+ [0][0][2][0][RTW89_QATAR][0][0] = 28,
+ [0][0][2][0][RTW89_UK][1][0] = 66,
+ [0][0][2][0][RTW89_UK][0][0] = 28,
+ [0][0][2][0][RTW89_FCC][1][2] = 22,
+ [0][0][2][0][RTW89_FCC][2][2] = 56,
+ [0][0][2][0][RTW89_ETSI][1][2] = 66,
+ [0][0][2][0][RTW89_ETSI][0][2] = 28,
+ [0][0][2][0][RTW89_MKK][1][2] = 66,
+ [0][0][2][0][RTW89_MKK][0][2] = 26,
+ [0][0][2][0][RTW89_IC][1][2] = 22,
+ [0][0][2][0][RTW89_KCC][1][2] = 24,
+ [0][0][2][0][RTW89_KCC][0][2] = 24,
+ [0][0][2][0][RTW89_ACMA][1][2] = 66,
+ [0][0][2][0][RTW89_ACMA][0][2] = 28,
+ [0][0][2][0][RTW89_CHILE][1][2] = 22,
+ [0][0][2][0][RTW89_QATAR][1][2] = 66,
+ [0][0][2][0][RTW89_QATAR][0][2] = 28,
+ [0][0][2][0][RTW89_UK][1][2] = 66,
+ [0][0][2][0][RTW89_UK][0][2] = 28,
+ [0][0][2][0][RTW89_FCC][1][4] = 22,
+ [0][0][2][0][RTW89_FCC][2][4] = 56,
+ [0][0][2][0][RTW89_ETSI][1][4] = 66,
+ [0][0][2][0][RTW89_ETSI][0][4] = 28,
+ [0][0][2][0][RTW89_MKK][1][4] = 66,
+ [0][0][2][0][RTW89_MKK][0][4] = 26,
+ [0][0][2][0][RTW89_IC][1][4] = 22,
+ [0][0][2][0][RTW89_KCC][1][4] = 24,
+ [0][0][2][0][RTW89_KCC][0][4] = 24,
+ [0][0][2][0][RTW89_ACMA][1][4] = 66,
+ [0][0][2][0][RTW89_ACMA][0][4] = 28,
+ [0][0][2][0][RTW89_CHILE][1][4] = 22,
+ [0][0][2][0][RTW89_QATAR][1][4] = 66,
+ [0][0][2][0][RTW89_QATAR][0][4] = 28,
+ [0][0][2][0][RTW89_UK][1][4] = 66,
+ [0][0][2][0][RTW89_UK][0][4] = 28,
+ [0][0][2][0][RTW89_FCC][1][6] = 22,
+ [0][0][2][0][RTW89_FCC][2][6] = 56,
+ [0][0][2][0][RTW89_ETSI][1][6] = 66,
+ [0][0][2][0][RTW89_ETSI][0][6] = 28,
+ [0][0][2][0][RTW89_MKK][1][6] = 66,
+ [0][0][2][0][RTW89_MKK][0][6] = 26,
+ [0][0][2][0][RTW89_IC][1][6] = 22,
+ [0][0][2][0][RTW89_KCC][1][6] = 24,
+ [0][0][2][0][RTW89_KCC][0][6] = 24,
+ [0][0][2][0][RTW89_ACMA][1][6] = 66,
+ [0][0][2][0][RTW89_ACMA][0][6] = 28,
+ [0][0][2][0][RTW89_CHILE][1][6] = 22,
+ [0][0][2][0][RTW89_QATAR][1][6] = 66,
+ [0][0][2][0][RTW89_QATAR][0][6] = 28,
+ [0][0][2][0][RTW89_UK][1][6] = 66,
+ [0][0][2][0][RTW89_UK][0][6] = 28,
+ [0][0][2][0][RTW89_FCC][1][8] = 22,
+ [0][0][2][0][RTW89_FCC][2][8] = 56,
+ [0][0][2][0][RTW89_ETSI][1][8] = 66,
+ [0][0][2][0][RTW89_ETSI][0][8] = 28,
+ [0][0][2][0][RTW89_MKK][1][8] = 66,
+ [0][0][2][0][RTW89_MKK][0][8] = 26,
+ [0][0][2][0][RTW89_IC][1][8] = 22,
+ [0][0][2][0][RTW89_KCC][1][8] = 24,
+ [0][0][2][0][RTW89_KCC][0][8] = 24,
+ [0][0][2][0][RTW89_ACMA][1][8] = 66,
+ [0][0][2][0][RTW89_ACMA][0][8] = 28,
+ [0][0][2][0][RTW89_CHILE][1][8] = 22,
+ [0][0][2][0][RTW89_QATAR][1][8] = 66,
+ [0][0][2][0][RTW89_QATAR][0][8] = 28,
+ [0][0][2][0][RTW89_UK][1][8] = 66,
+ [0][0][2][0][RTW89_UK][0][8] = 28,
+ [0][0][2][0][RTW89_FCC][1][10] = 22,
+ [0][0][2][0][RTW89_FCC][2][10] = 56,
+ [0][0][2][0][RTW89_ETSI][1][10] = 66,
+ [0][0][2][0][RTW89_ETSI][0][10] = 28,
+ [0][0][2][0][RTW89_MKK][1][10] = 66,
+ [0][0][2][0][RTW89_MKK][0][10] = 26,
+ [0][0][2][0][RTW89_IC][1][10] = 22,
+ [0][0][2][0][RTW89_KCC][1][10] = 24,
+ [0][0][2][0][RTW89_KCC][0][10] = 24,
+ [0][0][2][0][RTW89_ACMA][1][10] = 66,
+ [0][0][2][0][RTW89_ACMA][0][10] = 28,
+ [0][0][2][0][RTW89_CHILE][1][10] = 22,
+ [0][0][2][0][RTW89_QATAR][1][10] = 66,
+ [0][0][2][0][RTW89_QATAR][0][10] = 28,
+ [0][0][2][0][RTW89_UK][1][10] = 66,
+ [0][0][2][0][RTW89_UK][0][10] = 28,
+ [0][0][2][0][RTW89_FCC][1][12] = 22,
+ [0][0][2][0][RTW89_FCC][2][12] = 56,
+ [0][0][2][0][RTW89_ETSI][1][12] = 66,
+ [0][0][2][0][RTW89_ETSI][0][12] = 28,
+ [0][0][2][0][RTW89_MKK][1][12] = 66,
+ [0][0][2][0][RTW89_MKK][0][12] = 26,
+ [0][0][2][0][RTW89_IC][1][12] = 22,
+ [0][0][2][0][RTW89_KCC][1][12] = 24,
+ [0][0][2][0][RTW89_KCC][0][12] = 24,
+ [0][0][2][0][RTW89_ACMA][1][12] = 66,
+ [0][0][2][0][RTW89_ACMA][0][12] = 28,
+ [0][0][2][0][RTW89_CHILE][1][12] = 22,
+ [0][0][2][0][RTW89_QATAR][1][12] = 66,
+ [0][0][2][0][RTW89_QATAR][0][12] = 28,
+ [0][0][2][0][RTW89_UK][1][12] = 66,
+ [0][0][2][0][RTW89_UK][0][12] = 28,
+ [0][0][2][0][RTW89_FCC][1][14] = 22,
+ [0][0][2][0][RTW89_FCC][2][14] = 56,
+ [0][0][2][0][RTW89_ETSI][1][14] = 66,
+ [0][0][2][0][RTW89_ETSI][0][14] = 28,
+ [0][0][2][0][RTW89_MKK][1][14] = 66,
+ [0][0][2][0][RTW89_MKK][0][14] = 26,
+ [0][0][2][0][RTW89_IC][1][14] = 22,
+ [0][0][2][0][RTW89_KCC][1][14] = 24,
+ [0][0][2][0][RTW89_KCC][0][14] = 24,
+ [0][0][2][0][RTW89_ACMA][1][14] = 66,
+ [0][0][2][0][RTW89_ACMA][0][14] = 28,
+ [0][0][2][0][RTW89_CHILE][1][14] = 22,
+ [0][0][2][0][RTW89_QATAR][1][14] = 66,
+ [0][0][2][0][RTW89_QATAR][0][14] = 28,
+ [0][0][2][0][RTW89_UK][1][14] = 66,
+ [0][0][2][0][RTW89_UK][0][14] = 28,
+ [0][0][2][0][RTW89_FCC][1][15] = 22,
+ [0][0][2][0][RTW89_FCC][2][15] = 56,
+ [0][0][2][0][RTW89_ETSI][1][15] = 66,
+ [0][0][2][0][RTW89_ETSI][0][15] = 28,
+ [0][0][2][0][RTW89_MKK][1][15] = 66,
+ [0][0][2][0][RTW89_MKK][0][15] = 26,
+ [0][0][2][0][RTW89_IC][1][15] = 22,
+ [0][0][2][0][RTW89_KCC][1][15] = 24,
+ [0][0][2][0][RTW89_KCC][0][15] = 24,
+ [0][0][2][0][RTW89_ACMA][1][15] = 66,
+ [0][0][2][0][RTW89_ACMA][0][15] = 28,
+ [0][0][2][0][RTW89_CHILE][1][15] = 22,
+ [0][0][2][0][RTW89_QATAR][1][15] = 66,
+ [0][0][2][0][RTW89_QATAR][0][15] = 28,
+ [0][0][2][0][RTW89_UK][1][15] = 66,
+ [0][0][2][0][RTW89_UK][0][15] = 28,
+ [0][0][2][0][RTW89_FCC][1][17] = 22,
+ [0][0][2][0][RTW89_FCC][2][17] = 56,
+ [0][0][2][0][RTW89_ETSI][1][17] = 66,
+ [0][0][2][0][RTW89_ETSI][0][17] = 28,
+ [0][0][2][0][RTW89_MKK][1][17] = 66,
+ [0][0][2][0][RTW89_MKK][0][17] = 26,
+ [0][0][2][0][RTW89_IC][1][17] = 22,
+ [0][0][2][0][RTW89_KCC][1][17] = 24,
+ [0][0][2][0][RTW89_KCC][0][17] = 24,
+ [0][0][2][0][RTW89_ACMA][1][17] = 66,
+ [0][0][2][0][RTW89_ACMA][0][17] = 28,
+ [0][0][2][0][RTW89_CHILE][1][17] = 22,
+ [0][0][2][0][RTW89_QATAR][1][17] = 66,
+ [0][0][2][0][RTW89_QATAR][0][17] = 28,
+ [0][0][2][0][RTW89_UK][1][17] = 66,
+ [0][0][2][0][RTW89_UK][0][17] = 28,
+ [0][0][2][0][RTW89_FCC][1][19] = 22,
+ [0][0][2][0][RTW89_FCC][2][19] = 56,
+ [0][0][2][0][RTW89_ETSI][1][19] = 66,
+ [0][0][2][0][RTW89_ETSI][0][19] = 28,
+ [0][0][2][0][RTW89_MKK][1][19] = 66,
+ [0][0][2][0][RTW89_MKK][0][19] = 26,
+ [0][0][2][0][RTW89_IC][1][19] = 22,
+ [0][0][2][0][RTW89_KCC][1][19] = 24,
+ [0][0][2][0][RTW89_KCC][0][19] = 24,
+ [0][0][2][0][RTW89_ACMA][1][19] = 66,
+ [0][0][2][0][RTW89_ACMA][0][19] = 28,
+ [0][0][2][0][RTW89_CHILE][1][19] = 22,
+ [0][0][2][0][RTW89_QATAR][1][19] = 66,
+ [0][0][2][0][RTW89_QATAR][0][19] = 28,
+ [0][0][2][0][RTW89_UK][1][19] = 66,
+ [0][0][2][0][RTW89_UK][0][19] = 28,
+ [0][0][2][0][RTW89_FCC][1][21] = 22,
+ [0][0][2][0][RTW89_FCC][2][21] = 56,
+ [0][0][2][0][RTW89_ETSI][1][21] = 66,
+ [0][0][2][0][RTW89_ETSI][0][21] = 28,
+ [0][0][2][0][RTW89_MKK][1][21] = 66,
+ [0][0][2][0][RTW89_MKK][0][21] = 26,
+ [0][0][2][0][RTW89_IC][1][21] = 22,
+ [0][0][2][0][RTW89_KCC][1][21] = 24,
+ [0][0][2][0][RTW89_KCC][0][21] = 24,
+ [0][0][2][0][RTW89_ACMA][1][21] = 66,
+ [0][0][2][0][RTW89_ACMA][0][21] = 28,
+ [0][0][2][0][RTW89_CHILE][1][21] = 22,
+ [0][0][2][0][RTW89_QATAR][1][21] = 66,
+ [0][0][2][0][RTW89_QATAR][0][21] = 28,
+ [0][0][2][0][RTW89_UK][1][21] = 66,
+ [0][0][2][0][RTW89_UK][0][21] = 28,
+ [0][0][2][0][RTW89_FCC][1][23] = 22,
+ [0][0][2][0][RTW89_FCC][2][23] = 70,
+ [0][0][2][0][RTW89_ETSI][1][23] = 66,
+ [0][0][2][0][RTW89_ETSI][0][23] = 28,
+ [0][0][2][0][RTW89_MKK][1][23] = 66,
+ [0][0][2][0][RTW89_MKK][0][23] = 26,
+ [0][0][2][0][RTW89_IC][1][23] = 22,
+ [0][0][2][0][RTW89_KCC][1][23] = 24,
+ [0][0][2][0][RTW89_KCC][0][23] = 26,
+ [0][0][2][0][RTW89_ACMA][1][23] = 66,
+ [0][0][2][0][RTW89_ACMA][0][23] = 28,
+ [0][0][2][0][RTW89_CHILE][1][23] = 22,
+ [0][0][2][0][RTW89_QATAR][1][23] = 66,
+ [0][0][2][0][RTW89_QATAR][0][23] = 28,
+ [0][0][2][0][RTW89_UK][1][23] = 66,
+ [0][0][2][0][RTW89_UK][0][23] = 28,
+ [0][0][2][0][RTW89_FCC][1][25] = 22,
+ [0][0][2][0][RTW89_FCC][2][25] = 70,
+ [0][0][2][0][RTW89_ETSI][1][25] = 66,
+ [0][0][2][0][RTW89_ETSI][0][25] = 28,
+ [0][0][2][0][RTW89_MKK][1][25] = 66,
+ [0][0][2][0][RTW89_MKK][0][25] = 26,
+ [0][0][2][0][RTW89_IC][1][25] = 22,
+ [0][0][2][0][RTW89_KCC][1][25] = 24,
+ [0][0][2][0][RTW89_KCC][0][25] = 26,
+ [0][0][2][0][RTW89_ACMA][1][25] = 66,
+ [0][0][2][0][RTW89_ACMA][0][25] = 28,
+ [0][0][2][0][RTW89_CHILE][1][25] = 22,
+ [0][0][2][0][RTW89_QATAR][1][25] = 66,
+ [0][0][2][0][RTW89_QATAR][0][25] = 28,
+ [0][0][2][0][RTW89_UK][1][25] = 66,
+ [0][0][2][0][RTW89_UK][0][25] = 28,
+ [0][0][2][0][RTW89_FCC][1][27] = 22,
+ [0][0][2][0][RTW89_FCC][2][27] = 70,
+ [0][0][2][0][RTW89_ETSI][1][27] = 66,
+ [0][0][2][0][RTW89_ETSI][0][27] = 28,
+ [0][0][2][0][RTW89_MKK][1][27] = 66,
+ [0][0][2][0][RTW89_MKK][0][27] = 26,
+ [0][0][2][0][RTW89_IC][1][27] = 22,
+ [0][0][2][0][RTW89_KCC][1][27] = 24,
+ [0][0][2][0][RTW89_KCC][0][27] = 26,
+ [0][0][2][0][RTW89_ACMA][1][27] = 66,
+ [0][0][2][0][RTW89_ACMA][0][27] = 28,
+ [0][0][2][0][RTW89_CHILE][1][27] = 22,
+ [0][0][2][0][RTW89_QATAR][1][27] = 66,
+ [0][0][2][0][RTW89_QATAR][0][27] = 28,
+ [0][0][2][0][RTW89_UK][1][27] = 66,
+ [0][0][2][0][RTW89_UK][0][27] = 28,
+ [0][0][2][0][RTW89_FCC][1][29] = 22,
+ [0][0][2][0][RTW89_FCC][2][29] = 70,
+ [0][0][2][0][RTW89_ETSI][1][29] = 66,
+ [0][0][2][0][RTW89_ETSI][0][29] = 28,
+ [0][0][2][0][RTW89_MKK][1][29] = 66,
+ [0][0][2][0][RTW89_MKK][0][29] = 26,
+ [0][0][2][0][RTW89_IC][1][29] = 22,
+ [0][0][2][0][RTW89_KCC][1][29] = 24,
+ [0][0][2][0][RTW89_KCC][0][29] = 26,
+ [0][0][2][0][RTW89_ACMA][1][29] = 66,
+ [0][0][2][0][RTW89_ACMA][0][29] = 28,
+ [0][0][2][0][RTW89_CHILE][1][29] = 22,
+ [0][0][2][0][RTW89_QATAR][1][29] = 66,
+ [0][0][2][0][RTW89_QATAR][0][29] = 28,
+ [0][0][2][0][RTW89_UK][1][29] = 66,
+ [0][0][2][0][RTW89_UK][0][29] = 28,
+ [0][0][2][0][RTW89_FCC][1][30] = 22,
+ [0][0][2][0][RTW89_FCC][2][30] = 70,
+ [0][0][2][0][RTW89_ETSI][1][30] = 66,
+ [0][0][2][0][RTW89_ETSI][0][30] = 28,
+ [0][0][2][0][RTW89_MKK][1][30] = 66,
+ [0][0][2][0][RTW89_MKK][0][30] = 26,
+ [0][0][2][0][RTW89_IC][1][30] = 22,
+ [0][0][2][0][RTW89_KCC][1][30] = 24,
+ [0][0][2][0][RTW89_KCC][0][30] = 26,
+ [0][0][2][0][RTW89_ACMA][1][30] = 66,
+ [0][0][2][0][RTW89_ACMA][0][30] = 28,
+ [0][0][2][0][RTW89_CHILE][1][30] = 22,
+ [0][0][2][0][RTW89_QATAR][1][30] = 66,
+ [0][0][2][0][RTW89_QATAR][0][30] = 28,
+ [0][0][2][0][RTW89_UK][1][30] = 66,
+ [0][0][2][0][RTW89_UK][0][30] = 28,
+ [0][0][2][0][RTW89_FCC][1][32] = 22,
+ [0][0][2][0][RTW89_FCC][2][32] = 70,
+ [0][0][2][0][RTW89_ETSI][1][32] = 66,
+ [0][0][2][0][RTW89_ETSI][0][32] = 28,
+ [0][0][2][0][RTW89_MKK][1][32] = 66,
+ [0][0][2][0][RTW89_MKK][0][32] = 26,
+ [0][0][2][0][RTW89_IC][1][32] = 22,
+ [0][0][2][0][RTW89_KCC][1][32] = 24,
+ [0][0][2][0][RTW89_KCC][0][32] = 26,
+ [0][0][2][0][RTW89_ACMA][1][32] = 66,
+ [0][0][2][0][RTW89_ACMA][0][32] = 28,
+ [0][0][2][0][RTW89_CHILE][1][32] = 22,
+ [0][0][2][0][RTW89_QATAR][1][32] = 66,
+ [0][0][2][0][RTW89_QATAR][0][32] = 28,
+ [0][0][2][0][RTW89_UK][1][32] = 66,
+ [0][0][2][0][RTW89_UK][0][32] = 28,
+ [0][0][2][0][RTW89_FCC][1][34] = 22,
+ [0][0][2][0][RTW89_FCC][2][34] = 70,
+ [0][0][2][0][RTW89_ETSI][1][34] = 66,
+ [0][0][2][0][RTW89_ETSI][0][34] = 28,
+ [0][0][2][0][RTW89_MKK][1][34] = 66,
+ [0][0][2][0][RTW89_MKK][0][34] = 26,
+ [0][0][2][0][RTW89_IC][1][34] = 22,
+ [0][0][2][0][RTW89_KCC][1][34] = 24,
+ [0][0][2][0][RTW89_KCC][0][34] = 26,
+ [0][0][2][0][RTW89_ACMA][1][34] = 66,
+ [0][0][2][0][RTW89_ACMA][0][34] = 28,
+ [0][0][2][0][RTW89_CHILE][1][34] = 22,
+ [0][0][2][0][RTW89_QATAR][1][34] = 66,
+ [0][0][2][0][RTW89_QATAR][0][34] = 28,
+ [0][0][2][0][RTW89_UK][1][34] = 66,
+ [0][0][2][0][RTW89_UK][0][34] = 28,
+ [0][0][2][0][RTW89_FCC][1][36] = 22,
+ [0][0][2][0][RTW89_FCC][2][36] = 70,
+ [0][0][2][0][RTW89_ETSI][1][36] = 66,
+ [0][0][2][0][RTW89_ETSI][0][36] = 28,
+ [0][0][2][0][RTW89_MKK][1][36] = 66,
+ [0][0][2][0][RTW89_MKK][0][36] = 26,
+ [0][0][2][0][RTW89_IC][1][36] = 22,
+ [0][0][2][0][RTW89_KCC][1][36] = 24,
+ [0][0][2][0][RTW89_KCC][0][36] = 26,
+ [0][0][2][0][RTW89_ACMA][1][36] = 66,
+ [0][0][2][0][RTW89_ACMA][0][36] = 28,
+ [0][0][2][0][RTW89_CHILE][1][36] = 22,
+ [0][0][2][0][RTW89_QATAR][1][36] = 66,
+ [0][0][2][0][RTW89_QATAR][0][36] = 28,
+ [0][0][2][0][RTW89_UK][1][36] = 66,
+ [0][0][2][0][RTW89_UK][0][36] = 28,
+ [0][0][2][0][RTW89_FCC][1][38] = 22,
+ [0][0][2][0][RTW89_FCC][2][38] = 70,
+ [0][0][2][0][RTW89_ETSI][1][38] = 66,
+ [0][0][2][0][RTW89_ETSI][0][38] = 28,
+ [0][0][2][0][RTW89_MKK][1][38] = 66,
+ [0][0][2][0][RTW89_MKK][0][38] = 26,
+ [0][0][2][0][RTW89_IC][1][38] = 22,
+ [0][0][2][0][RTW89_KCC][1][38] = 24,
+ [0][0][2][0][RTW89_KCC][0][38] = 26,
+ [0][0][2][0][RTW89_ACMA][1][38] = 66,
+ [0][0][2][0][RTW89_ACMA][0][38] = 28,
+ [0][0][2][0][RTW89_CHILE][1][38] = 22,
+ [0][0][2][0][RTW89_QATAR][1][38] = 66,
+ [0][0][2][0][RTW89_QATAR][0][38] = 28,
+ [0][0][2][0][RTW89_UK][1][38] = 66,
+ [0][0][2][0][RTW89_UK][0][38] = 28,
+ [0][0][2][0][RTW89_FCC][1][40] = 22,
+ [0][0][2][0][RTW89_FCC][2][40] = 70,
+ [0][0][2][0][RTW89_ETSI][1][40] = 66,
+ [0][0][2][0][RTW89_ETSI][0][40] = 28,
+ [0][0][2][0][RTW89_MKK][1][40] = 66,
+ [0][0][2][0][RTW89_MKK][0][40] = 26,
+ [0][0][2][0][RTW89_IC][1][40] = 22,
+ [0][0][2][0][RTW89_KCC][1][40] = 24,
+ [0][0][2][0][RTW89_KCC][0][40] = 26,
+ [0][0][2][0][RTW89_ACMA][1][40] = 66,
+ [0][0][2][0][RTW89_ACMA][0][40] = 28,
+ [0][0][2][0][RTW89_CHILE][1][40] = 22,
+ [0][0][2][0][RTW89_QATAR][1][40] = 66,
+ [0][0][2][0][RTW89_QATAR][0][40] = 28,
+ [0][0][2][0][RTW89_UK][1][40] = 66,
+ [0][0][2][0][RTW89_UK][0][40] = 28,
+ [0][0][2][0][RTW89_FCC][1][42] = 22,
+ [0][0][2][0][RTW89_FCC][2][42] = 70,
+ [0][0][2][0][RTW89_ETSI][1][42] = 66,
+ [0][0][2][0][RTW89_ETSI][0][42] = 28,
+ [0][0][2][0][RTW89_MKK][1][42] = 66,
+ [0][0][2][0][RTW89_MKK][0][42] = 26,
+ [0][0][2][0][RTW89_IC][1][42] = 22,
+ [0][0][2][0][RTW89_KCC][1][42] = 24,
+ [0][0][2][0][RTW89_KCC][0][42] = 26,
+ [0][0][2][0][RTW89_ACMA][1][42] = 66,
+ [0][0][2][0][RTW89_ACMA][0][42] = 28,
+ [0][0][2][0][RTW89_CHILE][1][42] = 22,
+ [0][0][2][0][RTW89_QATAR][1][42] = 66,
+ [0][0][2][0][RTW89_QATAR][0][42] = 28,
+ [0][0][2][0][RTW89_UK][1][42] = 66,
+ [0][0][2][0][RTW89_UK][0][42] = 28,
+ [0][0][2][0][RTW89_FCC][1][44] = 22,
+ [0][0][2][0][RTW89_FCC][2][44] = 70,
+ [0][0][2][0][RTW89_ETSI][1][44] = 66,
+ [0][0][2][0][RTW89_ETSI][0][44] = 30,
+ [0][0][2][0][RTW89_MKK][1][44] = 44,
+ [0][0][2][0][RTW89_MKK][0][44] = 28,
+ [0][0][2][0][RTW89_IC][1][44] = 22,
+ [0][0][2][0][RTW89_KCC][1][44] = 24,
+ [0][0][2][0][RTW89_KCC][0][44] = 26,
+ [0][0][2][0][RTW89_ACMA][1][44] = 66,
+ [0][0][2][0][RTW89_ACMA][0][44] = 30,
+ [0][0][2][0][RTW89_CHILE][1][44] = 22,
+ [0][0][2][0][RTW89_QATAR][1][44] = 66,
+ [0][0][2][0][RTW89_QATAR][0][44] = 30,
+ [0][0][2][0][RTW89_UK][1][44] = 66,
+ [0][0][2][0][RTW89_UK][0][44] = 30,
+ [0][0][2][0][RTW89_FCC][1][45] = 22,
+ [0][0][2][0][RTW89_FCC][2][45] = 127,
+ [0][0][2][0][RTW89_ETSI][1][45] = 127,
+ [0][0][2][0][RTW89_ETSI][0][45] = 127,
+ [0][0][2][0][RTW89_MKK][1][45] = 127,
+ [0][0][2][0][RTW89_MKK][0][45] = 127,
+ [0][0][2][0][RTW89_IC][1][45] = 22,
+ [0][0][2][0][RTW89_KCC][1][45] = 24,
+ [0][0][2][0][RTW89_KCC][0][45] = 127,
+ [0][0][2][0][RTW89_ACMA][1][45] = 127,
+ [0][0][2][0][RTW89_ACMA][0][45] = 127,
+ [0][0][2][0][RTW89_CHILE][1][45] = 22,
+ [0][0][2][0][RTW89_QATAR][1][45] = 127,
+ [0][0][2][0][RTW89_QATAR][0][45] = 127,
+ [0][0][2][0][RTW89_UK][1][45] = 127,
+ [0][0][2][0][RTW89_UK][0][45] = 127,
+ [0][0][2][0][RTW89_FCC][1][47] = 22,
+ [0][0][2][0][RTW89_FCC][2][47] = 127,
+ [0][0][2][0][RTW89_ETSI][1][47] = 127,
+ [0][0][2][0][RTW89_ETSI][0][47] = 127,
+ [0][0][2][0][RTW89_MKK][1][47] = 127,
+ [0][0][2][0][RTW89_MKK][0][47] = 127,
+ [0][0][2][0][RTW89_IC][1][47] = 22,
+ [0][0][2][0][RTW89_KCC][1][47] = 24,
+ [0][0][2][0][RTW89_KCC][0][47] = 127,
+ [0][0][2][0][RTW89_ACMA][1][47] = 127,
+ [0][0][2][0][RTW89_ACMA][0][47] = 127,
+ [0][0][2][0][RTW89_CHILE][1][47] = 22,
+ [0][0][2][0][RTW89_QATAR][1][47] = 127,
+ [0][0][2][0][RTW89_QATAR][0][47] = 127,
+ [0][0][2][0][RTW89_UK][1][47] = 127,
+ [0][0][2][0][RTW89_UK][0][47] = 127,
+ [0][0][2][0][RTW89_FCC][1][49] = 24,
+ [0][0][2][0][RTW89_FCC][2][49] = 127,
+ [0][0][2][0][RTW89_ETSI][1][49] = 127,
+ [0][0][2][0][RTW89_ETSI][0][49] = 127,
+ [0][0][2][0][RTW89_MKK][1][49] = 127,
+ [0][0][2][0][RTW89_MKK][0][49] = 127,
+ [0][0][2][0][RTW89_IC][1][49] = 24,
+ [0][0][2][0][RTW89_KCC][1][49] = 24,
+ [0][0][2][0][RTW89_KCC][0][49] = 127,
+ [0][0][2][0][RTW89_ACMA][1][49] = 127,
+ [0][0][2][0][RTW89_ACMA][0][49] = 127,
+ [0][0][2][0][RTW89_CHILE][1][49] = 24,
+ [0][0][2][0][RTW89_QATAR][1][49] = 127,
+ [0][0][2][0][RTW89_QATAR][0][49] = 127,
+ [0][0][2][0][RTW89_UK][1][49] = 127,
+ [0][0][2][0][RTW89_UK][0][49] = 127,
+ [0][0][2][0][RTW89_FCC][1][51] = 22,
+ [0][0][2][0][RTW89_FCC][2][51] = 127,
+ [0][0][2][0][RTW89_ETSI][1][51] = 127,
+ [0][0][2][0][RTW89_ETSI][0][51] = 127,
+ [0][0][2][0][RTW89_MKK][1][51] = 127,
+ [0][0][2][0][RTW89_MKK][0][51] = 127,
+ [0][0][2][0][RTW89_IC][1][51] = 22,
+ [0][0][2][0][RTW89_KCC][1][51] = 24,
+ [0][0][2][0][RTW89_KCC][0][51] = 127,
+ [0][0][2][0][RTW89_ACMA][1][51] = 127,
+ [0][0][2][0][RTW89_ACMA][0][51] = 127,
+ [0][0][2][0][RTW89_CHILE][1][51] = 22,
+ [0][0][2][0][RTW89_QATAR][1][51] = 127,
+ [0][0][2][0][RTW89_QATAR][0][51] = 127,
+ [0][0][2][0][RTW89_UK][1][51] = 127,
+ [0][0][2][0][RTW89_UK][0][51] = 127,
+ [0][0][2][0][RTW89_FCC][1][53] = 22,
+ [0][0][2][0][RTW89_FCC][2][53] = 127,
+ [0][0][2][0][RTW89_ETSI][1][53] = 127,
+ [0][0][2][0][RTW89_ETSI][0][53] = 127,
+ [0][0][2][0][RTW89_MKK][1][53] = 127,
+ [0][0][2][0][RTW89_MKK][0][53] = 127,
+ [0][0][2][0][RTW89_IC][1][53] = 22,
+ [0][0][2][0][RTW89_KCC][1][53] = 24,
+ [0][0][2][0][RTW89_KCC][0][53] = 127,
+ [0][0][2][0][RTW89_ACMA][1][53] = 127,
+ [0][0][2][0][RTW89_ACMA][0][53] = 127,
+ [0][0][2][0][RTW89_CHILE][1][53] = 22,
+ [0][0][2][0][RTW89_QATAR][1][53] = 127,
+ [0][0][2][0][RTW89_QATAR][0][53] = 127,
+ [0][0][2][0][RTW89_UK][1][53] = 127,
+ [0][0][2][0][RTW89_UK][0][53] = 127,
+ [0][0][2][0][RTW89_FCC][1][55] = 22,
+ [0][0][2][0][RTW89_FCC][2][55] = 68,
+ [0][0][2][0][RTW89_ETSI][1][55] = 127,
+ [0][0][2][0][RTW89_ETSI][0][55] = 127,
+ [0][0][2][0][RTW89_MKK][1][55] = 127,
+ [0][0][2][0][RTW89_MKK][0][55] = 127,
+ [0][0][2][0][RTW89_IC][1][55] = 22,
+ [0][0][2][0][RTW89_KCC][1][55] = 26,
+ [0][0][2][0][RTW89_KCC][0][55] = 127,
+ [0][0][2][0][RTW89_ACMA][1][55] = 127,
+ [0][0][2][0][RTW89_ACMA][0][55] = 127,
+ [0][0][2][0][RTW89_CHILE][1][55] = 22,
+ [0][0][2][0][RTW89_QATAR][1][55] = 127,
+ [0][0][2][0][RTW89_QATAR][0][55] = 127,
+ [0][0][2][0][RTW89_UK][1][55] = 127,
+ [0][0][2][0][RTW89_UK][0][55] = 127,
+ [0][0][2][0][RTW89_FCC][1][57] = 22,
+ [0][0][2][0][RTW89_FCC][2][57] = 68,
+ [0][0][2][0][RTW89_ETSI][1][57] = 127,
+ [0][0][2][0][RTW89_ETSI][0][57] = 127,
+ [0][0][2][0][RTW89_MKK][1][57] = 127,
+ [0][0][2][0][RTW89_MKK][0][57] = 127,
+ [0][0][2][0][RTW89_IC][1][57] = 22,
+ [0][0][2][0][RTW89_KCC][1][57] = 26,
+ [0][0][2][0][RTW89_KCC][0][57] = 127,
+ [0][0][2][0][RTW89_ACMA][1][57] = 127,
+ [0][0][2][0][RTW89_ACMA][0][57] = 127,
+ [0][0][2][0][RTW89_CHILE][1][57] = 22,
+ [0][0][2][0][RTW89_QATAR][1][57] = 127,
+ [0][0][2][0][RTW89_QATAR][0][57] = 127,
+ [0][0][2][0][RTW89_UK][1][57] = 127,
+ [0][0][2][0][RTW89_UK][0][57] = 127,
+ [0][0][2][0][RTW89_FCC][1][59] = 22,
+ [0][0][2][0][RTW89_FCC][2][59] = 68,
+ [0][0][2][0][RTW89_ETSI][1][59] = 127,
+ [0][0][2][0][RTW89_ETSI][0][59] = 127,
+ [0][0][2][0][RTW89_MKK][1][59] = 127,
+ [0][0][2][0][RTW89_MKK][0][59] = 127,
+ [0][0][2][0][RTW89_IC][1][59] = 22,
+ [0][0][2][0][RTW89_KCC][1][59] = 26,
+ [0][0][2][0][RTW89_KCC][0][59] = 127,
+ [0][0][2][0][RTW89_ACMA][1][59] = 127,
+ [0][0][2][0][RTW89_ACMA][0][59] = 127,
+ [0][0][2][0][RTW89_CHILE][1][59] = 22,
+ [0][0][2][0][RTW89_QATAR][1][59] = 127,
+ [0][0][2][0][RTW89_QATAR][0][59] = 127,
+ [0][0][2][0][RTW89_UK][1][59] = 127,
+ [0][0][2][0][RTW89_UK][0][59] = 127,
+ [0][0][2][0][RTW89_FCC][1][60] = 22,
+ [0][0][2][0][RTW89_FCC][2][60] = 68,
+ [0][0][2][0][RTW89_ETSI][1][60] = 127,
+ [0][0][2][0][RTW89_ETSI][0][60] = 127,
+ [0][0][2][0][RTW89_MKK][1][60] = 127,
+ [0][0][2][0][RTW89_MKK][0][60] = 127,
+ [0][0][2][0][RTW89_IC][1][60] = 22,
+ [0][0][2][0][RTW89_KCC][1][60] = 26,
+ [0][0][2][0][RTW89_KCC][0][60] = 127,
+ [0][0][2][0][RTW89_ACMA][1][60] = 127,
+ [0][0][2][0][RTW89_ACMA][0][60] = 127,
+ [0][0][2][0][RTW89_CHILE][1][60] = 22,
+ [0][0][2][0][RTW89_QATAR][1][60] = 127,
+ [0][0][2][0][RTW89_QATAR][0][60] = 127,
+ [0][0][2][0][RTW89_UK][1][60] = 127,
+ [0][0][2][0][RTW89_UK][0][60] = 127,
+ [0][0][2][0][RTW89_FCC][1][62] = 22,
+ [0][0][2][0][RTW89_FCC][2][62] = 68,
+ [0][0][2][0][RTW89_ETSI][1][62] = 127,
+ [0][0][2][0][RTW89_ETSI][0][62] = 127,
+ [0][0][2][0][RTW89_MKK][1][62] = 127,
+ [0][0][2][0][RTW89_MKK][0][62] = 127,
+ [0][0][2][0][RTW89_IC][1][62] = 22,
+ [0][0][2][0][RTW89_KCC][1][62] = 26,
+ [0][0][2][0][RTW89_KCC][0][62] = 127,
+ [0][0][2][0][RTW89_ACMA][1][62] = 127,
+ [0][0][2][0][RTW89_ACMA][0][62] = 127,
+ [0][0][2][0][RTW89_CHILE][1][62] = 22,
+ [0][0][2][0][RTW89_QATAR][1][62] = 127,
+ [0][0][2][0][RTW89_QATAR][0][62] = 127,
+ [0][0][2][0][RTW89_UK][1][62] = 127,
+ [0][0][2][0][RTW89_UK][0][62] = 127,
+ [0][0][2][0][RTW89_FCC][1][64] = 22,
+ [0][0][2][0][RTW89_FCC][2][64] = 68,
+ [0][0][2][0][RTW89_ETSI][1][64] = 127,
+ [0][0][2][0][RTW89_ETSI][0][64] = 127,
+ [0][0][2][0][RTW89_MKK][1][64] = 127,
+ [0][0][2][0][RTW89_MKK][0][64] = 127,
+ [0][0][2][0][RTW89_IC][1][64] = 22,
+ [0][0][2][0][RTW89_KCC][1][64] = 26,
+ [0][0][2][0][RTW89_KCC][0][64] = 127,
+ [0][0][2][0][RTW89_ACMA][1][64] = 127,
+ [0][0][2][0][RTW89_ACMA][0][64] = 127,
+ [0][0][2][0][RTW89_CHILE][1][64] = 22,
+ [0][0][2][0][RTW89_QATAR][1][64] = 127,
+ [0][0][2][0][RTW89_QATAR][0][64] = 127,
+ [0][0][2][0][RTW89_UK][1][64] = 127,
+ [0][0][2][0][RTW89_UK][0][64] = 127,
+ [0][0][2][0][RTW89_FCC][1][66] = 22,
+ [0][0][2][0][RTW89_FCC][2][66] = 68,
+ [0][0][2][0][RTW89_ETSI][1][66] = 127,
+ [0][0][2][0][RTW89_ETSI][0][66] = 127,
+ [0][0][2][0][RTW89_MKK][1][66] = 127,
+ [0][0][2][0][RTW89_MKK][0][66] = 127,
+ [0][0][2][0][RTW89_IC][1][66] = 22,
+ [0][0][2][0][RTW89_KCC][1][66] = 26,
+ [0][0][2][0][RTW89_KCC][0][66] = 127,
+ [0][0][2][0][RTW89_ACMA][1][66] = 127,
+ [0][0][2][0][RTW89_ACMA][0][66] = 127,
+ [0][0][2][0][RTW89_CHILE][1][66] = 22,
+ [0][0][2][0][RTW89_QATAR][1][66] = 127,
+ [0][0][2][0][RTW89_QATAR][0][66] = 127,
+ [0][0][2][0][RTW89_UK][1][66] = 127,
+ [0][0][2][0][RTW89_UK][0][66] = 127,
+ [0][0][2][0][RTW89_FCC][1][68] = 22,
+ [0][0][2][0][RTW89_FCC][2][68] = 68,
+ [0][0][2][0][RTW89_ETSI][1][68] = 127,
+ [0][0][2][0][RTW89_ETSI][0][68] = 127,
+ [0][0][2][0][RTW89_MKK][1][68] = 127,
+ [0][0][2][0][RTW89_MKK][0][68] = 127,
+ [0][0][2][0][RTW89_IC][1][68] = 22,
+ [0][0][2][0][RTW89_KCC][1][68] = 26,
+ [0][0][2][0][RTW89_KCC][0][68] = 127,
+ [0][0][2][0][RTW89_ACMA][1][68] = 127,
+ [0][0][2][0][RTW89_ACMA][0][68] = 127,
+ [0][0][2][0][RTW89_CHILE][1][68] = 22,
+ [0][0][2][0][RTW89_QATAR][1][68] = 127,
+ [0][0][2][0][RTW89_QATAR][0][68] = 127,
+ [0][0][2][0][RTW89_UK][1][68] = 127,
+ [0][0][2][0][RTW89_UK][0][68] = 127,
+ [0][0][2][0][RTW89_FCC][1][70] = 24,
+ [0][0][2][0][RTW89_FCC][2][70] = 68,
+ [0][0][2][0][RTW89_ETSI][1][70] = 127,
+ [0][0][2][0][RTW89_ETSI][0][70] = 127,
+ [0][0][2][0][RTW89_MKK][1][70] = 127,
+ [0][0][2][0][RTW89_MKK][0][70] = 127,
+ [0][0][2][0][RTW89_IC][1][70] = 24,
+ [0][0][2][0][RTW89_KCC][1][70] = 26,
+ [0][0][2][0][RTW89_KCC][0][70] = 127,
+ [0][0][2][0][RTW89_ACMA][1][70] = 127,
+ [0][0][2][0][RTW89_ACMA][0][70] = 127,
+ [0][0][2][0][RTW89_CHILE][1][70] = 24,
+ [0][0][2][0][RTW89_QATAR][1][70] = 127,
+ [0][0][2][0][RTW89_QATAR][0][70] = 127,
+ [0][0][2][0][RTW89_UK][1][70] = 127,
+ [0][0][2][0][RTW89_UK][0][70] = 127,
+ [0][0][2][0][RTW89_FCC][1][72] = 22,
+ [0][0][2][0][RTW89_FCC][2][72] = 68,
+ [0][0][2][0][RTW89_ETSI][1][72] = 127,
+ [0][0][2][0][RTW89_ETSI][0][72] = 127,
+ [0][0][2][0][RTW89_MKK][1][72] = 127,
+ [0][0][2][0][RTW89_MKK][0][72] = 127,
+ [0][0][2][0][RTW89_IC][1][72] = 22,
+ [0][0][2][0][RTW89_KCC][1][72] = 26,
+ [0][0][2][0][RTW89_KCC][0][72] = 127,
+ [0][0][2][0][RTW89_ACMA][1][72] = 127,
+ [0][0][2][0][RTW89_ACMA][0][72] = 127,
+ [0][0][2][0][RTW89_CHILE][1][72] = 22,
+ [0][0][2][0][RTW89_QATAR][1][72] = 127,
+ [0][0][2][0][RTW89_QATAR][0][72] = 127,
+ [0][0][2][0][RTW89_UK][1][72] = 127,
+ [0][0][2][0][RTW89_UK][0][72] = 127,
+ [0][0][2][0][RTW89_FCC][1][74] = 22,
+ [0][0][2][0][RTW89_FCC][2][74] = 68,
+ [0][0][2][0][RTW89_ETSI][1][74] = 127,
+ [0][0][2][0][RTW89_ETSI][0][74] = 127,
+ [0][0][2][0][RTW89_MKK][1][74] = 127,
+ [0][0][2][0][RTW89_MKK][0][74] = 127,
+ [0][0][2][0][RTW89_IC][1][74] = 22,
+ [0][0][2][0][RTW89_KCC][1][74] = 26,
+ [0][0][2][0][RTW89_KCC][0][74] = 127,
+ [0][0][2][0][RTW89_ACMA][1][74] = 127,
+ [0][0][2][0][RTW89_ACMA][0][74] = 127,
+ [0][0][2][0][RTW89_CHILE][1][74] = 22,
+ [0][0][2][0][RTW89_QATAR][1][74] = 127,
+ [0][0][2][0][RTW89_QATAR][0][74] = 127,
+ [0][0][2][0][RTW89_UK][1][74] = 127,
+ [0][0][2][0][RTW89_UK][0][74] = 127,
+ [0][0][2][0][RTW89_FCC][1][75] = 22,
+ [0][0][2][0][RTW89_FCC][2][75] = 68,
+ [0][0][2][0][RTW89_ETSI][1][75] = 127,
+ [0][0][2][0][RTW89_ETSI][0][75] = 127,
+ [0][0][2][0][RTW89_MKK][1][75] = 127,
+ [0][0][2][0][RTW89_MKK][0][75] = 127,
+ [0][0][2][0][RTW89_IC][1][75] = 22,
+ [0][0][2][0][RTW89_KCC][1][75] = 26,
+ [0][0][2][0][RTW89_KCC][0][75] = 127,
+ [0][0][2][0][RTW89_ACMA][1][75] = 127,
+ [0][0][2][0][RTW89_ACMA][0][75] = 127,
+ [0][0][2][0][RTW89_CHILE][1][75] = 22,
+ [0][0][2][0][RTW89_QATAR][1][75] = 127,
+ [0][0][2][0][RTW89_QATAR][0][75] = 127,
+ [0][0][2][0][RTW89_UK][1][75] = 127,
+ [0][0][2][0][RTW89_UK][0][75] = 127,
+ [0][0][2][0][RTW89_FCC][1][77] = 22,
+ [0][0][2][0][RTW89_FCC][2][77] = 68,
+ [0][0][2][0][RTW89_ETSI][1][77] = 127,
+ [0][0][2][0][RTW89_ETSI][0][77] = 127,
+ [0][0][2][0][RTW89_MKK][1][77] = 127,
+ [0][0][2][0][RTW89_MKK][0][77] = 127,
+ [0][0][2][0][RTW89_IC][1][77] = 22,
+ [0][0][2][0][RTW89_KCC][1][77] = 26,
+ [0][0][2][0][RTW89_KCC][0][77] = 127,
+ [0][0][2][0][RTW89_ACMA][1][77] = 127,
+ [0][0][2][0][RTW89_ACMA][0][77] = 127,
+ [0][0][2][0][RTW89_CHILE][1][77] = 22,
+ [0][0][2][0][RTW89_QATAR][1][77] = 127,
+ [0][0][2][0][RTW89_QATAR][0][77] = 127,
+ [0][0][2][0][RTW89_UK][1][77] = 127,
+ [0][0][2][0][RTW89_UK][0][77] = 127,
+ [0][0][2][0][RTW89_FCC][1][79] = 22,
+ [0][0][2][0][RTW89_FCC][2][79] = 68,
+ [0][0][2][0][RTW89_ETSI][1][79] = 127,
+ [0][0][2][0][RTW89_ETSI][0][79] = 127,
+ [0][0][2][0][RTW89_MKK][1][79] = 127,
+ [0][0][2][0][RTW89_MKK][0][79] = 127,
+ [0][0][2][0][RTW89_IC][1][79] = 22,
+ [0][0][2][0][RTW89_KCC][1][79] = 26,
+ [0][0][2][0][RTW89_KCC][0][79] = 127,
+ [0][0][2][0][RTW89_ACMA][1][79] = 127,
+ [0][0][2][0][RTW89_ACMA][0][79] = 127,
+ [0][0][2][0][RTW89_CHILE][1][79] = 22,
+ [0][0][2][0][RTW89_QATAR][1][79] = 127,
+ [0][0][2][0][RTW89_QATAR][0][79] = 127,
+ [0][0][2][0][RTW89_UK][1][79] = 127,
+ [0][0][2][0][RTW89_UK][0][79] = 127,
+ [0][0][2][0][RTW89_FCC][1][81] = 22,
+ [0][0][2][0][RTW89_FCC][2][81] = 68,
+ [0][0][2][0][RTW89_ETSI][1][81] = 127,
+ [0][0][2][0][RTW89_ETSI][0][81] = 127,
+ [0][0][2][0][RTW89_MKK][1][81] = 127,
+ [0][0][2][0][RTW89_MKK][0][81] = 127,
+ [0][0][2][0][RTW89_IC][1][81] = 22,
+ [0][0][2][0][RTW89_KCC][1][81] = 26,
+ [0][0][2][0][RTW89_KCC][0][81] = 127,
+ [0][0][2][0][RTW89_ACMA][1][81] = 127,
+ [0][0][2][0][RTW89_ACMA][0][81] = 127,
+ [0][0][2][0][RTW89_CHILE][1][81] = 22,
+ [0][0][2][0][RTW89_QATAR][1][81] = 127,
+ [0][0][2][0][RTW89_QATAR][0][81] = 127,
+ [0][0][2][0][RTW89_UK][1][81] = 127,
+ [0][0][2][0][RTW89_UK][0][81] = 127,
+ [0][0][2][0][RTW89_FCC][1][83] = 22,
+ [0][0][2][0][RTW89_FCC][2][83] = 68,
+ [0][0][2][0][RTW89_ETSI][1][83] = 127,
+ [0][0][2][0][RTW89_ETSI][0][83] = 127,
+ [0][0][2][0][RTW89_MKK][1][83] = 127,
+ [0][0][2][0][RTW89_MKK][0][83] = 127,
+ [0][0][2][0][RTW89_IC][1][83] = 22,
+ [0][0][2][0][RTW89_KCC][1][83] = 32,
+ [0][0][2][0][RTW89_KCC][0][83] = 127,
+ [0][0][2][0][RTW89_ACMA][1][83] = 127,
+ [0][0][2][0][RTW89_ACMA][0][83] = 127,
+ [0][0][2][0][RTW89_CHILE][1][83] = 22,
+ [0][0][2][0][RTW89_QATAR][1][83] = 127,
+ [0][0][2][0][RTW89_QATAR][0][83] = 127,
+ [0][0][2][0][RTW89_UK][1][83] = 127,
+ [0][0][2][0][RTW89_UK][0][83] = 127,
+ [0][0][2][0][RTW89_FCC][1][85] = 22,
+ [0][0][2][0][RTW89_FCC][2][85] = 68,
+ [0][0][2][0][RTW89_ETSI][1][85] = 127,
+ [0][0][2][0][RTW89_ETSI][0][85] = 127,
+ [0][0][2][0][RTW89_MKK][1][85] = 127,
+ [0][0][2][0][RTW89_MKK][0][85] = 127,
+ [0][0][2][0][RTW89_IC][1][85] = 22,
+ [0][0][2][0][RTW89_KCC][1][85] = 32,
+ [0][0][2][0][RTW89_KCC][0][85] = 127,
+ [0][0][2][0][RTW89_ACMA][1][85] = 127,
+ [0][0][2][0][RTW89_ACMA][0][85] = 127,
+ [0][0][2][0][RTW89_CHILE][1][85] = 22,
+ [0][0][2][0][RTW89_QATAR][1][85] = 127,
+ [0][0][2][0][RTW89_QATAR][0][85] = 127,
+ [0][0][2][0][RTW89_UK][1][85] = 127,
+ [0][0][2][0][RTW89_UK][0][85] = 127,
+ [0][0][2][0][RTW89_FCC][1][87] = 22,
+ [0][0][2][0][RTW89_FCC][2][87] = 127,
+ [0][0][2][0][RTW89_ETSI][1][87] = 127,
+ [0][0][2][0][RTW89_ETSI][0][87] = 127,
+ [0][0][2][0][RTW89_MKK][1][87] = 127,
+ [0][0][2][0][RTW89_MKK][0][87] = 127,
+ [0][0][2][0][RTW89_IC][1][87] = 22,
+ [0][0][2][0][RTW89_KCC][1][87] = 32,
+ [0][0][2][0][RTW89_KCC][0][87] = 127,
+ [0][0][2][0][RTW89_ACMA][1][87] = 127,
+ [0][0][2][0][RTW89_ACMA][0][87] = 127,
+ [0][0][2][0][RTW89_CHILE][1][87] = 22,
+ [0][0][2][0][RTW89_QATAR][1][87] = 127,
+ [0][0][2][0][RTW89_QATAR][0][87] = 127,
+ [0][0][2][0][RTW89_UK][1][87] = 127,
+ [0][0][2][0][RTW89_UK][0][87] = 127,
+ [0][0][2][0][RTW89_FCC][1][89] = 22,
+ [0][0][2][0][RTW89_FCC][2][89] = 127,
+ [0][0][2][0][RTW89_ETSI][1][89] = 127,
+ [0][0][2][0][RTW89_ETSI][0][89] = 127,
+ [0][0][2][0][RTW89_MKK][1][89] = 127,
+ [0][0][2][0][RTW89_MKK][0][89] = 127,
+ [0][0][2][0][RTW89_IC][1][89] = 22,
+ [0][0][2][0][RTW89_KCC][1][89] = 32,
+ [0][0][2][0][RTW89_KCC][0][89] = 127,
+ [0][0][2][0][RTW89_ACMA][1][89] = 127,
+ [0][0][2][0][RTW89_ACMA][0][89] = 127,
+ [0][0][2][0][RTW89_CHILE][1][89] = 22,
+ [0][0][2][0][RTW89_QATAR][1][89] = 127,
+ [0][0][2][0][RTW89_QATAR][0][89] = 127,
+ [0][0][2][0][RTW89_UK][1][89] = 127,
+ [0][0][2][0][RTW89_UK][0][89] = 127,
+ [0][0][2][0][RTW89_FCC][1][90] = 22,
+ [0][0][2][0][RTW89_FCC][2][90] = 127,
+ [0][0][2][0][RTW89_ETSI][1][90] = 127,
+ [0][0][2][0][RTW89_ETSI][0][90] = 127,
+ [0][0][2][0][RTW89_MKK][1][90] = 127,
+ [0][0][2][0][RTW89_MKK][0][90] = 127,
+ [0][0][2][0][RTW89_IC][1][90] = 22,
+ [0][0][2][0][RTW89_KCC][1][90] = 32,
+ [0][0][2][0][RTW89_KCC][0][90] = 127,
+ [0][0][2][0][RTW89_ACMA][1][90] = 127,
+ [0][0][2][0][RTW89_ACMA][0][90] = 127,
+ [0][0][2][0][RTW89_CHILE][1][90] = 22,
+ [0][0][2][0][RTW89_QATAR][1][90] = 127,
+ [0][0][2][0][RTW89_QATAR][0][90] = 127,
+ [0][0][2][0][RTW89_UK][1][90] = 127,
+ [0][0][2][0][RTW89_UK][0][90] = 127,
+ [0][0][2][0][RTW89_FCC][1][92] = 22,
+ [0][0][2][0][RTW89_FCC][2][92] = 127,
+ [0][0][2][0][RTW89_ETSI][1][92] = 127,
+ [0][0][2][0][RTW89_ETSI][0][92] = 127,
+ [0][0][2][0][RTW89_MKK][1][92] = 127,
+ [0][0][2][0][RTW89_MKK][0][92] = 127,
+ [0][0][2][0][RTW89_IC][1][92] = 22,
+ [0][0][2][0][RTW89_KCC][1][92] = 32,
+ [0][0][2][0][RTW89_KCC][0][92] = 127,
+ [0][0][2][0][RTW89_ACMA][1][92] = 127,
+ [0][0][2][0][RTW89_ACMA][0][92] = 127,
+ [0][0][2][0][RTW89_CHILE][1][92] = 22,
+ [0][0][2][0][RTW89_QATAR][1][92] = 127,
+ [0][0][2][0][RTW89_QATAR][0][92] = 127,
+ [0][0][2][0][RTW89_UK][1][92] = 127,
+ [0][0][2][0][RTW89_UK][0][92] = 127,
+ [0][0][2][0][RTW89_FCC][1][94] = 22,
+ [0][0][2][0][RTW89_FCC][2][94] = 127,
+ [0][0][2][0][RTW89_ETSI][1][94] = 127,
+ [0][0][2][0][RTW89_ETSI][0][94] = 127,
+ [0][0][2][0][RTW89_MKK][1][94] = 127,
+ [0][0][2][0][RTW89_MKK][0][94] = 127,
+ [0][0][2][0][RTW89_IC][1][94] = 22,
+ [0][0][2][0][RTW89_KCC][1][94] = 32,
+ [0][0][2][0][RTW89_KCC][0][94] = 127,
+ [0][0][2][0][RTW89_ACMA][1][94] = 127,
+ [0][0][2][0][RTW89_ACMA][0][94] = 127,
+ [0][0][2][0][RTW89_CHILE][1][94] = 22,
+ [0][0][2][0][RTW89_QATAR][1][94] = 127,
+ [0][0][2][0][RTW89_QATAR][0][94] = 127,
+ [0][0][2][0][RTW89_UK][1][94] = 127,
+ [0][0][2][0][RTW89_UK][0][94] = 127,
+ [0][0][2][0][RTW89_FCC][1][96] = 22,
+ [0][0][2][0][RTW89_FCC][2][96] = 127,
+ [0][0][2][0][RTW89_ETSI][1][96] = 127,
+ [0][0][2][0][RTW89_ETSI][0][96] = 127,
+ [0][0][2][0][RTW89_MKK][1][96] = 127,
+ [0][0][2][0][RTW89_MKK][0][96] = 127,
+ [0][0][2][0][RTW89_IC][1][96] = 22,
+ [0][0][2][0][RTW89_KCC][1][96] = 32,
+ [0][0][2][0][RTW89_KCC][0][96] = 127,
+ [0][0][2][0][RTW89_ACMA][1][96] = 127,
+ [0][0][2][0][RTW89_ACMA][0][96] = 127,
+ [0][0][2][0][RTW89_CHILE][1][96] = 22,
+ [0][0][2][0][RTW89_QATAR][1][96] = 127,
+ [0][0][2][0][RTW89_QATAR][0][96] = 127,
+ [0][0][2][0][RTW89_UK][1][96] = 127,
+ [0][0][2][0][RTW89_UK][0][96] = 127,
+ [0][0][2][0][RTW89_FCC][1][98] = 22,
+ [0][0][2][0][RTW89_FCC][2][98] = 127,
+ [0][0][2][0][RTW89_ETSI][1][98] = 127,
+ [0][0][2][0][RTW89_ETSI][0][98] = 127,
+ [0][0][2][0][RTW89_MKK][1][98] = 127,
+ [0][0][2][0][RTW89_MKK][0][98] = 127,
+ [0][0][2][0][RTW89_IC][1][98] = 22,
+ [0][0][2][0][RTW89_KCC][1][98] = 32,
+ [0][0][2][0][RTW89_KCC][0][98] = 127,
+ [0][0][2][0][RTW89_ACMA][1][98] = 127,
+ [0][0][2][0][RTW89_ACMA][0][98] = 127,
+ [0][0][2][0][RTW89_CHILE][1][98] = 22,
+ [0][0][2][0][RTW89_QATAR][1][98] = 127,
+ [0][0][2][0][RTW89_QATAR][0][98] = 127,
+ [0][0][2][0][RTW89_UK][1][98] = 127,
+ [0][0][2][0][RTW89_UK][0][98] = 127,
+ [0][0][2][0][RTW89_FCC][1][100] = 22,
+ [0][0][2][0][RTW89_FCC][2][100] = 127,
+ [0][0][2][0][RTW89_ETSI][1][100] = 127,
+ [0][0][2][0][RTW89_ETSI][0][100] = 127,
+ [0][0][2][0][RTW89_MKK][1][100] = 127,
+ [0][0][2][0][RTW89_MKK][0][100] = 127,
+ [0][0][2][0][RTW89_IC][1][100] = 22,
+ [0][0][2][0][RTW89_KCC][1][100] = 32,
+ [0][0][2][0][RTW89_KCC][0][100] = 127,
+ [0][0][2][0][RTW89_ACMA][1][100] = 127,
+ [0][0][2][0][RTW89_ACMA][0][100] = 127,
+ [0][0][2][0][RTW89_CHILE][1][100] = 22,
+ [0][0][2][0][RTW89_QATAR][1][100] = 127,
+ [0][0][2][0][RTW89_QATAR][0][100] = 127,
+ [0][0][2][0][RTW89_UK][1][100] = 127,
+ [0][0][2][0][RTW89_UK][0][100] = 127,
+ [0][0][2][0][RTW89_FCC][1][102] = 22,
+ [0][0][2][0][RTW89_FCC][2][102] = 127,
+ [0][0][2][0][RTW89_ETSI][1][102] = 127,
+ [0][0][2][0][RTW89_ETSI][0][102] = 127,
+ [0][0][2][0][RTW89_MKK][1][102] = 127,
+ [0][0][2][0][RTW89_MKK][0][102] = 127,
+ [0][0][2][0][RTW89_IC][1][102] = 22,
+ [0][0][2][0][RTW89_KCC][1][102] = 32,
+ [0][0][2][0][RTW89_KCC][0][102] = 127,
+ [0][0][2][0][RTW89_ACMA][1][102] = 127,
+ [0][0][2][0][RTW89_ACMA][0][102] = 127,
+ [0][0][2][0][RTW89_CHILE][1][102] = 22,
+ [0][0][2][0][RTW89_QATAR][1][102] = 127,
+ [0][0][2][0][RTW89_QATAR][0][102] = 127,
+ [0][0][2][0][RTW89_UK][1][102] = 127,
+ [0][0][2][0][RTW89_UK][0][102] = 127,
+ [0][0][2][0][RTW89_FCC][1][104] = 22,
+ [0][0][2][0][RTW89_FCC][2][104] = 127,
+ [0][0][2][0][RTW89_ETSI][1][104] = 127,
+ [0][0][2][0][RTW89_ETSI][0][104] = 127,
+ [0][0][2][0][RTW89_MKK][1][104] = 127,
+ [0][0][2][0][RTW89_MKK][0][104] = 127,
+ [0][0][2][0][RTW89_IC][1][104] = 22,
+ [0][0][2][0][RTW89_KCC][1][104] = 32,
+ [0][0][2][0][RTW89_KCC][0][104] = 127,
+ [0][0][2][0][RTW89_ACMA][1][104] = 127,
+ [0][0][2][0][RTW89_ACMA][0][104] = 127,
+ [0][0][2][0][RTW89_CHILE][1][104] = 22,
+ [0][0][2][0][RTW89_QATAR][1][104] = 127,
+ [0][0][2][0][RTW89_QATAR][0][104] = 127,
+ [0][0][2][0][RTW89_UK][1][104] = 127,
+ [0][0][2][0][RTW89_UK][0][104] = 127,
+ [0][0][2][0][RTW89_FCC][1][105] = 22,
+ [0][0][2][0][RTW89_FCC][2][105] = 127,
+ [0][0][2][0][RTW89_ETSI][1][105] = 127,
+ [0][0][2][0][RTW89_ETSI][0][105] = 127,
+ [0][0][2][0][RTW89_MKK][1][105] = 127,
+ [0][0][2][0][RTW89_MKK][0][105] = 127,
+ [0][0][2][0][RTW89_IC][1][105] = 22,
+ [0][0][2][0][RTW89_KCC][1][105] = 32,
+ [0][0][2][0][RTW89_KCC][0][105] = 127,
+ [0][0][2][0][RTW89_ACMA][1][105] = 127,
+ [0][0][2][0][RTW89_ACMA][0][105] = 127,
+ [0][0][2][0][RTW89_CHILE][1][105] = 22,
+ [0][0][2][0][RTW89_QATAR][1][105] = 127,
+ [0][0][2][0][RTW89_QATAR][0][105] = 127,
+ [0][0][2][0][RTW89_UK][1][105] = 127,
+ [0][0][2][0][RTW89_UK][0][105] = 127,
+ [0][0][2][0][RTW89_FCC][1][107] = 24,
+ [0][0][2][0][RTW89_FCC][2][107] = 127,
+ [0][0][2][0][RTW89_ETSI][1][107] = 127,
+ [0][0][2][0][RTW89_ETSI][0][107] = 127,
+ [0][0][2][0][RTW89_MKK][1][107] = 127,
+ [0][0][2][0][RTW89_MKK][0][107] = 127,
+ [0][0][2][0][RTW89_IC][1][107] = 24,
+ [0][0][2][0][RTW89_KCC][1][107] = 32,
+ [0][0][2][0][RTW89_KCC][0][107] = 127,
+ [0][0][2][0][RTW89_ACMA][1][107] = 127,
+ [0][0][2][0][RTW89_ACMA][0][107] = 127,
+ [0][0][2][0][RTW89_CHILE][1][107] = 24,
+ [0][0][2][0][RTW89_QATAR][1][107] = 127,
+ [0][0][2][0][RTW89_QATAR][0][107] = 127,
+ [0][0][2][0][RTW89_UK][1][107] = 127,
+ [0][0][2][0][RTW89_UK][0][107] = 127,
+ [0][0][2][0][RTW89_FCC][1][109] = 24,
+ [0][0][2][0][RTW89_FCC][2][109] = 127,
+ [0][0][2][0][RTW89_ETSI][1][109] = 127,
+ [0][0][2][0][RTW89_ETSI][0][109] = 127,
+ [0][0][2][0][RTW89_MKK][1][109] = 127,
+ [0][0][2][0][RTW89_MKK][0][109] = 127,
+ [0][0][2][0][RTW89_IC][1][109] = 24,
+ [0][0][2][0][RTW89_KCC][1][109] = 32,
+ [0][0][2][0][RTW89_KCC][0][109] = 127,
+ [0][0][2][0][RTW89_ACMA][1][109] = 127,
+ [0][0][2][0][RTW89_ACMA][0][109] = 127,
+ [0][0][2][0][RTW89_CHILE][1][109] = 24,
+ [0][0][2][0][RTW89_QATAR][1][109] = 127,
+ [0][0][2][0][RTW89_QATAR][0][109] = 127,
+ [0][0][2][0][RTW89_UK][1][109] = 127,
+ [0][0][2][0][RTW89_UK][0][109] = 127,
+ [0][0][2][0][RTW89_FCC][1][111] = 127,
+ [0][0][2][0][RTW89_FCC][2][111] = 127,
+ [0][0][2][0][RTW89_ETSI][1][111] = 127,
+ [0][0][2][0][RTW89_ETSI][0][111] = 127,
+ [0][0][2][0][RTW89_MKK][1][111] = 127,
+ [0][0][2][0][RTW89_MKK][0][111] = 127,
+ [0][0][2][0][RTW89_IC][1][111] = 127,
+ [0][0][2][0][RTW89_KCC][1][111] = 127,
+ [0][0][2][0][RTW89_KCC][0][111] = 127,
+ [0][0][2][0][RTW89_ACMA][1][111] = 127,
+ [0][0][2][0][RTW89_ACMA][0][111] = 127,
+ [0][0][2][0][RTW89_CHILE][1][111] = 127,
+ [0][0][2][0][RTW89_QATAR][1][111] = 127,
+ [0][0][2][0][RTW89_QATAR][0][111] = 127,
+ [0][0][2][0][RTW89_UK][1][111] = 127,
+ [0][0][2][0][RTW89_UK][0][111] = 127,
+ [0][0][2][0][RTW89_FCC][1][113] = 127,
+ [0][0][2][0][RTW89_FCC][2][113] = 127,
+ [0][0][2][0][RTW89_ETSI][1][113] = 127,
+ [0][0][2][0][RTW89_ETSI][0][113] = 127,
+ [0][0][2][0][RTW89_MKK][1][113] = 127,
+ [0][0][2][0][RTW89_MKK][0][113] = 127,
+ [0][0][2][0][RTW89_IC][1][113] = 127,
+ [0][0][2][0][RTW89_KCC][1][113] = 127,
+ [0][0][2][0][RTW89_KCC][0][113] = 127,
+ [0][0][2][0][RTW89_ACMA][1][113] = 127,
+ [0][0][2][0][RTW89_ACMA][0][113] = 127,
+ [0][0][2][0][RTW89_CHILE][1][113] = 127,
+ [0][0][2][0][RTW89_QATAR][1][113] = 127,
+ [0][0][2][0][RTW89_QATAR][0][113] = 127,
+ [0][0][2][0][RTW89_UK][1][113] = 127,
+ [0][0][2][0][RTW89_UK][0][113] = 127,
+ [0][0][2][0][RTW89_FCC][1][115] = 127,
+ [0][0][2][0][RTW89_FCC][2][115] = 127,
+ [0][0][2][0][RTW89_ETSI][1][115] = 127,
+ [0][0][2][0][RTW89_ETSI][0][115] = 127,
+ [0][0][2][0][RTW89_MKK][1][115] = 127,
+ [0][0][2][0][RTW89_MKK][0][115] = 127,
+ [0][0][2][0][RTW89_IC][1][115] = 127,
+ [0][0][2][0][RTW89_KCC][1][115] = 127,
+ [0][0][2][0][RTW89_KCC][0][115] = 127,
+ [0][0][2][0][RTW89_ACMA][1][115] = 127,
+ [0][0][2][0][RTW89_ACMA][0][115] = 127,
+ [0][0][2][0][RTW89_CHILE][1][115] = 127,
+ [0][0][2][0][RTW89_QATAR][1][115] = 127,
+ [0][0][2][0][RTW89_QATAR][0][115] = 127,
+ [0][0][2][0][RTW89_UK][1][115] = 127,
+ [0][0][2][0][RTW89_UK][0][115] = 127,
+ [0][0][2][0][RTW89_FCC][1][117] = 127,
+ [0][0][2][0][RTW89_FCC][2][117] = 127,
+ [0][0][2][0][RTW89_ETSI][1][117] = 127,
+ [0][0][2][0][RTW89_ETSI][0][117] = 127,
+ [0][0][2][0][RTW89_MKK][1][117] = 127,
+ [0][0][2][0][RTW89_MKK][0][117] = 127,
+ [0][0][2][0][RTW89_IC][1][117] = 127,
+ [0][0][2][0][RTW89_KCC][1][117] = 127,
+ [0][0][2][0][RTW89_KCC][0][117] = 127,
+ [0][0][2][0][RTW89_ACMA][1][117] = 127,
+ [0][0][2][0][RTW89_ACMA][0][117] = 127,
+ [0][0][2][0][RTW89_CHILE][1][117] = 127,
+ [0][0][2][0][RTW89_QATAR][1][117] = 127,
+ [0][0][2][0][RTW89_QATAR][0][117] = 127,
+ [0][0][2][0][RTW89_UK][1][117] = 127,
+ [0][0][2][0][RTW89_UK][0][117] = 127,
+ [0][0][2][0][RTW89_FCC][1][119] = 127,
+ [0][0][2][0][RTW89_FCC][2][119] = 127,
+ [0][0][2][0][RTW89_ETSI][1][119] = 127,
+ [0][0][2][0][RTW89_ETSI][0][119] = 127,
+ [0][0][2][0][RTW89_MKK][1][119] = 127,
+ [0][0][2][0][RTW89_MKK][0][119] = 127,
+ [0][0][2][0][RTW89_IC][1][119] = 127,
+ [0][0][2][0][RTW89_KCC][1][119] = 127,
+ [0][0][2][0][RTW89_KCC][0][119] = 127,
+ [0][0][2][0][RTW89_ACMA][1][119] = 127,
+ [0][0][2][0][RTW89_ACMA][0][119] = 127,
+ [0][0][2][0][RTW89_CHILE][1][119] = 127,
+ [0][0][2][0][RTW89_QATAR][1][119] = 127,
+ [0][0][2][0][RTW89_QATAR][0][119] = 127,
+ [0][0][2][0][RTW89_UK][1][119] = 127,
+ [0][0][2][0][RTW89_UK][0][119] = 127,
+ [0][1][2][0][RTW89_FCC][1][0] = -2,
+ [0][1][2][0][RTW89_FCC][2][0] = 54,
+ [0][1][2][0][RTW89_ETSI][1][0] = 54,
+ [0][1][2][0][RTW89_ETSI][0][0] = 18,
+ [0][1][2][0][RTW89_MKK][1][0] = 56,
+ [0][1][2][0][RTW89_MKK][0][0] = 16,
+ [0][1][2][0][RTW89_IC][1][0] = -2,
+ [0][1][2][0][RTW89_KCC][1][0] = 12,
+ [0][1][2][0][RTW89_KCC][0][0] = 10,
+ [0][1][2][0][RTW89_ACMA][1][0] = 54,
+ [0][1][2][0][RTW89_ACMA][0][0] = 18,
+ [0][1][2][0][RTW89_CHILE][1][0] = -2,
+ [0][1][2][0][RTW89_QATAR][1][0] = 54,
+ [0][1][2][0][RTW89_QATAR][0][0] = 18,
+ [0][1][2][0][RTW89_UK][1][0] = 54,
+ [0][1][2][0][RTW89_UK][0][0] = 18,
+ [0][1][2][0][RTW89_FCC][1][2] = -4,
+ [0][1][2][0][RTW89_FCC][2][2] = 54,
+ [0][1][2][0][RTW89_ETSI][1][2] = 54,
+ [0][1][2][0][RTW89_ETSI][0][2] = 18,
+ [0][1][2][0][RTW89_MKK][1][2] = 54,
+ [0][1][2][0][RTW89_MKK][0][2] = 16,
+ [0][1][2][0][RTW89_IC][1][2] = -4,
+ [0][1][2][0][RTW89_KCC][1][2] = 12,
+ [0][1][2][0][RTW89_KCC][0][2] = 12,
+ [0][1][2][0][RTW89_ACMA][1][2] = 54,
+ [0][1][2][0][RTW89_ACMA][0][2] = 18,
+ [0][1][2][0][RTW89_CHILE][1][2] = -4,
+ [0][1][2][0][RTW89_QATAR][1][2] = 54,
+ [0][1][2][0][RTW89_QATAR][0][2] = 18,
+ [0][1][2][0][RTW89_UK][1][2] = 54,
+ [0][1][2][0][RTW89_UK][0][2] = 18,
+ [0][1][2][0][RTW89_FCC][1][4] = -4,
+ [0][1][2][0][RTW89_FCC][2][4] = 54,
+ [0][1][2][0][RTW89_ETSI][1][4] = 54,
+ [0][1][2][0][RTW89_ETSI][0][4] = 18,
+ [0][1][2][0][RTW89_MKK][1][4] = 54,
+ [0][1][2][0][RTW89_MKK][0][4] = 16,
+ [0][1][2][0][RTW89_IC][1][4] = -4,
+ [0][1][2][0][RTW89_KCC][1][4] = 12,
+ [0][1][2][0][RTW89_KCC][0][4] = 12,
+ [0][1][2][0][RTW89_ACMA][1][4] = 54,
+ [0][1][2][0][RTW89_ACMA][0][4] = 18,
+ [0][1][2][0][RTW89_CHILE][1][4] = -4,
+ [0][1][2][0][RTW89_QATAR][1][4] = 54,
+ [0][1][2][0][RTW89_QATAR][0][4] = 18,
+ [0][1][2][0][RTW89_UK][1][4] = 54,
+ [0][1][2][0][RTW89_UK][0][4] = 18,
+ [0][1][2][0][RTW89_FCC][1][6] = -4,
+ [0][1][2][0][RTW89_FCC][2][6] = 54,
+ [0][1][2][0][RTW89_ETSI][1][6] = 54,
+ [0][1][2][0][RTW89_ETSI][0][6] = 18,
+ [0][1][2][0][RTW89_MKK][1][6] = 54,
+ [0][1][2][0][RTW89_MKK][0][6] = 16,
+ [0][1][2][0][RTW89_IC][1][6] = -4,
+ [0][1][2][0][RTW89_KCC][1][6] = 12,
+ [0][1][2][0][RTW89_KCC][0][6] = 12,
+ [0][1][2][0][RTW89_ACMA][1][6] = 54,
+ [0][1][2][0][RTW89_ACMA][0][6] = 18,
+ [0][1][2][0][RTW89_CHILE][1][6] = -4,
+ [0][1][2][0][RTW89_QATAR][1][6] = 54,
+ [0][1][2][0][RTW89_QATAR][0][6] = 18,
+ [0][1][2][0][RTW89_UK][1][6] = 54,
+ [0][1][2][0][RTW89_UK][0][6] = 18,
+ [0][1][2][0][RTW89_FCC][1][8] = -4,
+ [0][1][2][0][RTW89_FCC][2][8] = 54,
+ [0][1][2][0][RTW89_ETSI][1][8] = 54,
+ [0][1][2][0][RTW89_ETSI][0][8] = 18,
+ [0][1][2][0][RTW89_MKK][1][8] = 54,
+ [0][1][2][0][RTW89_MKK][0][8] = 16,
+ [0][1][2][0][RTW89_IC][1][8] = -4,
+ [0][1][2][0][RTW89_KCC][1][8] = 12,
+ [0][1][2][0][RTW89_KCC][0][8] = 12,
+ [0][1][2][0][RTW89_ACMA][1][8] = 54,
+ [0][1][2][0][RTW89_ACMA][0][8] = 18,
+ [0][1][2][0][RTW89_CHILE][1][8] = -4,
+ [0][1][2][0][RTW89_QATAR][1][8] = 54,
+ [0][1][2][0][RTW89_QATAR][0][8] = 18,
+ [0][1][2][0][RTW89_UK][1][8] = 54,
+ [0][1][2][0][RTW89_UK][0][8] = 18,
+ [0][1][2][0][RTW89_FCC][1][10] = -4,
+ [0][1][2][0][RTW89_FCC][2][10] = 54,
+ [0][1][2][0][RTW89_ETSI][1][10] = 54,
+ [0][1][2][0][RTW89_ETSI][0][10] = 18,
+ [0][1][2][0][RTW89_MKK][1][10] = 54,
+ [0][1][2][0][RTW89_MKK][0][10] = 16,
+ [0][1][2][0][RTW89_IC][1][10] = -4,
+ [0][1][2][0][RTW89_KCC][1][10] = 12,
+ [0][1][2][0][RTW89_KCC][0][10] = 12,
+ [0][1][2][0][RTW89_ACMA][1][10] = 54,
+ [0][1][2][0][RTW89_ACMA][0][10] = 18,
+ [0][1][2][0][RTW89_CHILE][1][10] = -4,
+ [0][1][2][0][RTW89_QATAR][1][10] = 54,
+ [0][1][2][0][RTW89_QATAR][0][10] = 18,
+ [0][1][2][0][RTW89_UK][1][10] = 54,
+ [0][1][2][0][RTW89_UK][0][10] = 18,
+ [0][1][2][0][RTW89_FCC][1][12] = -4,
+ [0][1][2][0][RTW89_FCC][2][12] = 54,
+ [0][1][2][0][RTW89_ETSI][1][12] = 54,
+ [0][1][2][0][RTW89_ETSI][0][12] = 18,
+ [0][1][2][0][RTW89_MKK][1][12] = 54,
+ [0][1][2][0][RTW89_MKK][0][12] = 16,
+ [0][1][2][0][RTW89_IC][1][12] = -4,
+ [0][1][2][0][RTW89_KCC][1][12] = 12,
+ [0][1][2][0][RTW89_KCC][0][12] = 12,
+ [0][1][2][0][RTW89_ACMA][1][12] = 54,
+ [0][1][2][0][RTW89_ACMA][0][12] = 18,
+ [0][1][2][0][RTW89_CHILE][1][12] = -4,
+ [0][1][2][0][RTW89_QATAR][1][12] = 54,
+ [0][1][2][0][RTW89_QATAR][0][12] = 18,
+ [0][1][2][0][RTW89_UK][1][12] = 54,
+ [0][1][2][0][RTW89_UK][0][12] = 18,
+ [0][1][2][0][RTW89_FCC][1][14] = -4,
+ [0][1][2][0][RTW89_FCC][2][14] = 54,
+ [0][1][2][0][RTW89_ETSI][1][14] = 54,
+ [0][1][2][0][RTW89_ETSI][0][14] = 18,
+ [0][1][2][0][RTW89_MKK][1][14] = 54,
+ [0][1][2][0][RTW89_MKK][0][14] = 16,
+ [0][1][2][0][RTW89_IC][1][14] = -4,
+ [0][1][2][0][RTW89_KCC][1][14] = 12,
+ [0][1][2][0][RTW89_KCC][0][14] = 12,
+ [0][1][2][0][RTW89_ACMA][1][14] = 54,
+ [0][1][2][0][RTW89_ACMA][0][14] = 18,
+ [0][1][2][0][RTW89_CHILE][1][14] = -4,
+ [0][1][2][0][RTW89_QATAR][1][14] = 54,
+ [0][1][2][0][RTW89_QATAR][0][14] = 18,
+ [0][1][2][0][RTW89_UK][1][14] = 54,
+ [0][1][2][0][RTW89_UK][0][14] = 18,
+ [0][1][2][0][RTW89_FCC][1][15] = -4,
+ [0][1][2][0][RTW89_FCC][2][15] = 54,
+ [0][1][2][0][RTW89_ETSI][1][15] = 54,
+ [0][1][2][0][RTW89_ETSI][0][15] = 18,
+ [0][1][2][0][RTW89_MKK][1][15] = 54,
+ [0][1][2][0][RTW89_MKK][0][15] = 16,
+ [0][1][2][0][RTW89_IC][1][15] = -4,
+ [0][1][2][0][RTW89_KCC][1][15] = 12,
+ [0][1][2][0][RTW89_KCC][0][15] = 12,
+ [0][1][2][0][RTW89_ACMA][1][15] = 54,
+ [0][1][2][0][RTW89_ACMA][0][15] = 18,
+ [0][1][2][0][RTW89_CHILE][1][15] = -4,
+ [0][1][2][0][RTW89_QATAR][1][15] = 54,
+ [0][1][2][0][RTW89_QATAR][0][15] = 18,
+ [0][1][2][0][RTW89_UK][1][15] = 54,
+ [0][1][2][0][RTW89_UK][0][15] = 18,
+ [0][1][2][0][RTW89_FCC][1][17] = -4,
+ [0][1][2][0][RTW89_FCC][2][17] = 54,
+ [0][1][2][0][RTW89_ETSI][1][17] = 54,
+ [0][1][2][0][RTW89_ETSI][0][17] = 18,
+ [0][1][2][0][RTW89_MKK][1][17] = 54,
+ [0][1][2][0][RTW89_MKK][0][17] = 16,
+ [0][1][2][0][RTW89_IC][1][17] = -4,
+ [0][1][2][0][RTW89_KCC][1][17] = 12,
+ [0][1][2][0][RTW89_KCC][0][17] = 12,
+ [0][1][2][0][RTW89_ACMA][1][17] = 54,
+ [0][1][2][0][RTW89_ACMA][0][17] = 18,
+ [0][1][2][0][RTW89_CHILE][1][17] = -4,
+ [0][1][2][0][RTW89_QATAR][1][17] = 54,
+ [0][1][2][0][RTW89_QATAR][0][17] = 18,
+ [0][1][2][0][RTW89_UK][1][17] = 54,
+ [0][1][2][0][RTW89_UK][0][17] = 18,
+ [0][1][2][0][RTW89_FCC][1][19] = -4,
+ [0][1][2][0][RTW89_FCC][2][19] = 54,
+ [0][1][2][0][RTW89_ETSI][1][19] = 54,
+ [0][1][2][0][RTW89_ETSI][0][19] = 18,
+ [0][1][2][0][RTW89_MKK][1][19] = 54,
+ [0][1][2][0][RTW89_MKK][0][19] = 16,
+ [0][1][2][0][RTW89_IC][1][19] = -4,
+ [0][1][2][0][RTW89_KCC][1][19] = 12,
+ [0][1][2][0][RTW89_KCC][0][19] = 12,
+ [0][1][2][0][RTW89_ACMA][1][19] = 54,
+ [0][1][2][0][RTW89_ACMA][0][19] = 18,
+ [0][1][2][0][RTW89_CHILE][1][19] = -4,
+ [0][1][2][0][RTW89_QATAR][1][19] = 54,
+ [0][1][2][0][RTW89_QATAR][0][19] = 18,
+ [0][1][2][0][RTW89_UK][1][19] = 54,
+ [0][1][2][0][RTW89_UK][0][19] = 18,
+ [0][1][2][0][RTW89_FCC][1][21] = -4,
+ [0][1][2][0][RTW89_FCC][2][21] = 54,
+ [0][1][2][0][RTW89_ETSI][1][21] = 54,
+ [0][1][2][0][RTW89_ETSI][0][21] = 18,
+ [0][1][2][0][RTW89_MKK][1][21] = 54,
+ [0][1][2][0][RTW89_MKK][0][21] = 16,
+ [0][1][2][0][RTW89_IC][1][21] = -4,
+ [0][1][2][0][RTW89_KCC][1][21] = 12,
+ [0][1][2][0][RTW89_KCC][0][21] = 12,
+ [0][1][2][0][RTW89_ACMA][1][21] = 54,
+ [0][1][2][0][RTW89_ACMA][0][21] = 18,
+ [0][1][2][0][RTW89_CHILE][1][21] = -4,
+ [0][1][2][0][RTW89_QATAR][1][21] = 54,
+ [0][1][2][0][RTW89_QATAR][0][21] = 18,
+ [0][1][2][0][RTW89_UK][1][21] = 54,
+ [0][1][2][0][RTW89_UK][0][21] = 18,
+ [0][1][2][0][RTW89_FCC][1][23] = -4,
+ [0][1][2][0][RTW89_FCC][2][23] = 68,
+ [0][1][2][0][RTW89_ETSI][1][23] = 54,
+ [0][1][2][0][RTW89_ETSI][0][23] = 18,
+ [0][1][2][0][RTW89_MKK][1][23] = 54,
+ [0][1][2][0][RTW89_MKK][0][23] = 16,
+ [0][1][2][0][RTW89_IC][1][23] = -4,
+ [0][1][2][0][RTW89_KCC][1][23] = 12,
+ [0][1][2][0][RTW89_KCC][0][23] = 10,
+ [0][1][2][0][RTW89_ACMA][1][23] = 54,
+ [0][1][2][0][RTW89_ACMA][0][23] = 18,
+ [0][1][2][0][RTW89_CHILE][1][23] = -4,
+ [0][1][2][0][RTW89_QATAR][1][23] = 54,
+ [0][1][2][0][RTW89_QATAR][0][23] = 18,
+ [0][1][2][0][RTW89_UK][1][23] = 54,
+ [0][1][2][0][RTW89_UK][0][23] = 18,
+ [0][1][2][0][RTW89_FCC][1][25] = -4,
+ [0][1][2][0][RTW89_FCC][2][25] = 68,
+ [0][1][2][0][RTW89_ETSI][1][25] = 54,
+ [0][1][2][0][RTW89_ETSI][0][25] = 18,
+ [0][1][2][0][RTW89_MKK][1][25] = 54,
+ [0][1][2][0][RTW89_MKK][0][25] = 16,
+ [0][1][2][0][RTW89_IC][1][25] = -4,
+ [0][1][2][0][RTW89_KCC][1][25] = 12,
+ [0][1][2][0][RTW89_KCC][0][25] = 14,
+ [0][1][2][0][RTW89_ACMA][1][25] = 54,
+ [0][1][2][0][RTW89_ACMA][0][25] = 18,
+ [0][1][2][0][RTW89_CHILE][1][25] = -4,
+ [0][1][2][0][RTW89_QATAR][1][25] = 54,
+ [0][1][2][0][RTW89_QATAR][0][25] = 18,
+ [0][1][2][0][RTW89_UK][1][25] = 54,
+ [0][1][2][0][RTW89_UK][0][25] = 18,
+ [0][1][2][0][RTW89_FCC][1][27] = -4,
+ [0][1][2][0][RTW89_FCC][2][27] = 68,
+ [0][1][2][0][RTW89_ETSI][1][27] = 54,
+ [0][1][2][0][RTW89_ETSI][0][27] = 18,
+ [0][1][2][0][RTW89_MKK][1][27] = 54,
+ [0][1][2][0][RTW89_MKK][0][27] = 16,
+ [0][1][2][0][RTW89_IC][1][27] = -4,
+ [0][1][2][0][RTW89_KCC][1][27] = 12,
+ [0][1][2][0][RTW89_KCC][0][27] = 14,
+ [0][1][2][0][RTW89_ACMA][1][27] = 54,
+ [0][1][2][0][RTW89_ACMA][0][27] = 18,
+ [0][1][2][0][RTW89_CHILE][1][27] = -4,
+ [0][1][2][0][RTW89_QATAR][1][27] = 54,
+ [0][1][2][0][RTW89_QATAR][0][27] = 18,
+ [0][1][2][0][RTW89_UK][1][27] = 54,
+ [0][1][2][0][RTW89_UK][0][27] = 18,
+ [0][1][2][0][RTW89_FCC][1][29] = -4,
+ [0][1][2][0][RTW89_FCC][2][29] = 68,
+ [0][1][2][0][RTW89_ETSI][1][29] = 54,
+ [0][1][2][0][RTW89_ETSI][0][29] = 18,
+ [0][1][2][0][RTW89_MKK][1][29] = 54,
+ [0][1][2][0][RTW89_MKK][0][29] = 16,
+ [0][1][2][0][RTW89_IC][1][29] = -4,
+ [0][1][2][0][RTW89_KCC][1][29] = 12,
+ [0][1][2][0][RTW89_KCC][0][29] = 14,
+ [0][1][2][0][RTW89_ACMA][1][29] = 54,
+ [0][1][2][0][RTW89_ACMA][0][29] = 18,
+ [0][1][2][0][RTW89_CHILE][1][29] = -4,
+ [0][1][2][0][RTW89_QATAR][1][29] = 54,
+ [0][1][2][0][RTW89_QATAR][0][29] = 18,
+ [0][1][2][0][RTW89_UK][1][29] = 54,
+ [0][1][2][0][RTW89_UK][0][29] = 18,
+ [0][1][2][0][RTW89_FCC][1][30] = -4,
+ [0][1][2][0][RTW89_FCC][2][30] = 68,
+ [0][1][2][0][RTW89_ETSI][1][30] = 54,
+ [0][1][2][0][RTW89_ETSI][0][30] = 18,
+ [0][1][2][0][RTW89_MKK][1][30] = 54,
+ [0][1][2][0][RTW89_MKK][0][30] = 16,
+ [0][1][2][0][RTW89_IC][1][30] = -4,
+ [0][1][2][0][RTW89_KCC][1][30] = 12,
+ [0][1][2][0][RTW89_KCC][0][30] = 14,
+ [0][1][2][0][RTW89_ACMA][1][30] = 54,
+ [0][1][2][0][RTW89_ACMA][0][30] = 18,
+ [0][1][2][0][RTW89_CHILE][1][30] = -4,
+ [0][1][2][0][RTW89_QATAR][1][30] = 54,
+ [0][1][2][0][RTW89_QATAR][0][30] = 18,
+ [0][1][2][0][RTW89_UK][1][30] = 54,
+ [0][1][2][0][RTW89_UK][0][30] = 18,
+ [0][1][2][0][RTW89_FCC][1][32] = -4,
+ [0][1][2][0][RTW89_FCC][2][32] = 68,
+ [0][1][2][0][RTW89_ETSI][1][32] = 54,
+ [0][1][2][0][RTW89_ETSI][0][32] = 18,
+ [0][1][2][0][RTW89_MKK][1][32] = 54,
+ [0][1][2][0][RTW89_MKK][0][32] = 16,
+ [0][1][2][0][RTW89_IC][1][32] = -4,
+ [0][1][2][0][RTW89_KCC][1][32] = 12,
+ [0][1][2][0][RTW89_KCC][0][32] = 14,
+ [0][1][2][0][RTW89_ACMA][1][32] = 54,
+ [0][1][2][0][RTW89_ACMA][0][32] = 18,
+ [0][1][2][0][RTW89_CHILE][1][32] = -4,
+ [0][1][2][0][RTW89_QATAR][1][32] = 54,
+ [0][1][2][0][RTW89_QATAR][0][32] = 18,
+ [0][1][2][0][RTW89_UK][1][32] = 54,
+ [0][1][2][0][RTW89_UK][0][32] = 18,
+ [0][1][2][0][RTW89_FCC][1][34] = -4,
+ [0][1][2][0][RTW89_FCC][2][34] = 68,
+ [0][1][2][0][RTW89_ETSI][1][34] = 54,
+ [0][1][2][0][RTW89_ETSI][0][34] = 18,
+ [0][1][2][0][RTW89_MKK][1][34] = 54,
+ [0][1][2][0][RTW89_MKK][0][34] = 16,
+ [0][1][2][0][RTW89_IC][1][34] = -4,
+ [0][1][2][0][RTW89_KCC][1][34] = 12,
+ [0][1][2][0][RTW89_KCC][0][34] = 14,
+ [0][1][2][0][RTW89_ACMA][1][34] = 54,
+ [0][1][2][0][RTW89_ACMA][0][34] = 18,
+ [0][1][2][0][RTW89_CHILE][1][34] = -4,
+ [0][1][2][0][RTW89_QATAR][1][34] = 54,
+ [0][1][2][0][RTW89_QATAR][0][34] = 18,
+ [0][1][2][0][RTW89_UK][1][34] = 54,
+ [0][1][2][0][RTW89_UK][0][34] = 18,
+ [0][1][2][0][RTW89_FCC][1][36] = -4,
+ [0][1][2][0][RTW89_FCC][2][36] = 68,
+ [0][1][2][0][RTW89_ETSI][1][36] = 54,
+ [0][1][2][0][RTW89_ETSI][0][36] = 18,
+ [0][1][2][0][RTW89_MKK][1][36] = 54,
+ [0][1][2][0][RTW89_MKK][0][36] = 16,
+ [0][1][2][0][RTW89_IC][1][36] = -4,
+ [0][1][2][0][RTW89_KCC][1][36] = 12,
+ [0][1][2][0][RTW89_KCC][0][36] = 14,
+ [0][1][2][0][RTW89_ACMA][1][36] = 54,
+ [0][1][2][0][RTW89_ACMA][0][36] = 18,
+ [0][1][2][0][RTW89_CHILE][1][36] = -4,
+ [0][1][2][0][RTW89_QATAR][1][36] = 54,
+ [0][1][2][0][RTW89_QATAR][0][36] = 18,
+ [0][1][2][0][RTW89_UK][1][36] = 54,
+ [0][1][2][0][RTW89_UK][0][36] = 18,
+ [0][1][2][0][RTW89_FCC][1][38] = -4,
+ [0][1][2][0][RTW89_FCC][2][38] = 68,
+ [0][1][2][0][RTW89_ETSI][1][38] = 54,
+ [0][1][2][0][RTW89_ETSI][0][38] = 18,
+ [0][1][2][0][RTW89_MKK][1][38] = 54,
+ [0][1][2][0][RTW89_MKK][0][38] = 16,
+ [0][1][2][0][RTW89_IC][1][38] = -4,
+ [0][1][2][0][RTW89_KCC][1][38] = 12,
+ [0][1][2][0][RTW89_KCC][0][38] = 14,
+ [0][1][2][0][RTW89_ACMA][1][38] = 54,
+ [0][1][2][0][RTW89_ACMA][0][38] = 18,
+ [0][1][2][0][RTW89_CHILE][1][38] = -4,
+ [0][1][2][0][RTW89_QATAR][1][38] = 54,
+ [0][1][2][0][RTW89_QATAR][0][38] = 18,
+ [0][1][2][0][RTW89_UK][1][38] = 54,
+ [0][1][2][0][RTW89_UK][0][38] = 18,
+ [0][1][2][0][RTW89_FCC][1][40] = -4,
+ [0][1][2][0][RTW89_FCC][2][40] = 68,
+ [0][1][2][0][RTW89_ETSI][1][40] = 54,
+ [0][1][2][0][RTW89_ETSI][0][40] = 18,
+ [0][1][2][0][RTW89_MKK][1][40] = 54,
+ [0][1][2][0][RTW89_MKK][0][40] = 16,
+ [0][1][2][0][RTW89_IC][1][40] = -4,
+ [0][1][2][0][RTW89_KCC][1][40] = 12,
+ [0][1][2][0][RTW89_KCC][0][40] = 14,
+ [0][1][2][0][RTW89_ACMA][1][40] = 54,
+ [0][1][2][0][RTW89_ACMA][0][40] = 18,
+ [0][1][2][0][RTW89_CHILE][1][40] = -4,
+ [0][1][2][0][RTW89_QATAR][1][40] = 54,
+ [0][1][2][0][RTW89_QATAR][0][40] = 18,
+ [0][1][2][0][RTW89_UK][1][40] = 54,
+ [0][1][2][0][RTW89_UK][0][40] = 18,
+ [0][1][2][0][RTW89_FCC][1][42] = -4,
+ [0][1][2][0][RTW89_FCC][2][42] = 68,
+ [0][1][2][0][RTW89_ETSI][1][42] = 54,
+ [0][1][2][0][RTW89_ETSI][0][42] = 18,
+ [0][1][2][0][RTW89_MKK][1][42] = 54,
+ [0][1][2][0][RTW89_MKK][0][42] = 16,
+ [0][1][2][0][RTW89_IC][1][42] = -4,
+ [0][1][2][0][RTW89_KCC][1][42] = 12,
+ [0][1][2][0][RTW89_KCC][0][42] = 14,
+ [0][1][2][0][RTW89_ACMA][1][42] = 54,
+ [0][1][2][0][RTW89_ACMA][0][42] = 18,
+ [0][1][2][0][RTW89_CHILE][1][42] = -4,
+ [0][1][2][0][RTW89_QATAR][1][42] = 54,
+ [0][1][2][0][RTW89_QATAR][0][42] = 18,
+ [0][1][2][0][RTW89_UK][1][42] = 54,
+ [0][1][2][0][RTW89_UK][0][42] = 18,
+ [0][1][2][0][RTW89_FCC][1][44] = -2,
+ [0][1][2][0][RTW89_FCC][2][44] = 68,
+ [0][1][2][0][RTW89_ETSI][1][44] = 54,
+ [0][1][2][0][RTW89_ETSI][0][44] = 18,
+ [0][1][2][0][RTW89_MKK][1][44] = 34,
+ [0][1][2][0][RTW89_MKK][0][44] = 16,
+ [0][1][2][0][RTW89_IC][1][44] = -2,
+ [0][1][2][0][RTW89_KCC][1][44] = 12,
+ [0][1][2][0][RTW89_KCC][0][44] = 12,
+ [0][1][2][0][RTW89_ACMA][1][44] = 54,
+ [0][1][2][0][RTW89_ACMA][0][44] = 18,
+ [0][1][2][0][RTW89_CHILE][1][44] = -2,
+ [0][1][2][0][RTW89_QATAR][1][44] = 54,
+ [0][1][2][0][RTW89_QATAR][0][44] = 18,
+ [0][1][2][0][RTW89_UK][1][44] = 54,
+ [0][1][2][0][RTW89_UK][0][44] = 18,
+ [0][1][2][0][RTW89_FCC][1][45] = -2,
+ [0][1][2][0][RTW89_FCC][2][45] = 127,
+ [0][1][2][0][RTW89_ETSI][1][45] = 127,
+ [0][1][2][0][RTW89_ETSI][0][45] = 127,
+ [0][1][2][0][RTW89_MKK][1][45] = 127,
+ [0][1][2][0][RTW89_MKK][0][45] = 127,
+ [0][1][2][0][RTW89_IC][1][45] = -2,
+ [0][1][2][0][RTW89_KCC][1][45] = 12,
+ [0][1][2][0][RTW89_KCC][0][45] = 127,
+ [0][1][2][0][RTW89_ACMA][1][45] = 127,
+ [0][1][2][0][RTW89_ACMA][0][45] = 127,
+ [0][1][2][0][RTW89_CHILE][1][45] = -2,
+ [0][1][2][0][RTW89_QATAR][1][45] = 127,
+ [0][1][2][0][RTW89_QATAR][0][45] = 127,
+ [0][1][2][0][RTW89_UK][1][45] = 127,
+ [0][1][2][0][RTW89_UK][0][45] = 127,
+ [0][1][2][0][RTW89_FCC][1][47] = -2,
+ [0][1][2][0][RTW89_FCC][2][47] = 127,
+ [0][1][2][0][RTW89_ETSI][1][47] = 127,
+ [0][1][2][0][RTW89_ETSI][0][47] = 127,
+ [0][1][2][0][RTW89_MKK][1][47] = 127,
+ [0][1][2][0][RTW89_MKK][0][47] = 127,
+ [0][1][2][0][RTW89_IC][1][47] = -2,
+ [0][1][2][0][RTW89_KCC][1][47] = 12,
+ [0][1][2][0][RTW89_KCC][0][47] = 127,
+ [0][1][2][0][RTW89_ACMA][1][47] = 127,
+ [0][1][2][0][RTW89_ACMA][0][47] = 127,
+ [0][1][2][0][RTW89_CHILE][1][47] = -2,
+ [0][1][2][0][RTW89_QATAR][1][47] = 127,
+ [0][1][2][0][RTW89_QATAR][0][47] = 127,
+ [0][1][2][0][RTW89_UK][1][47] = 127,
+ [0][1][2][0][RTW89_UK][0][47] = 127,
+ [0][1][2][0][RTW89_FCC][1][49] = -2,
+ [0][1][2][0][RTW89_FCC][2][49] = 127,
+ [0][1][2][0][RTW89_ETSI][1][49] = 127,
+ [0][1][2][0][RTW89_ETSI][0][49] = 127,
+ [0][1][2][0][RTW89_MKK][1][49] = 127,
+ [0][1][2][0][RTW89_MKK][0][49] = 127,
+ [0][1][2][0][RTW89_IC][1][49] = -2,
+ [0][1][2][0][RTW89_KCC][1][49] = 12,
+ [0][1][2][0][RTW89_KCC][0][49] = 127,
+ [0][1][2][0][RTW89_ACMA][1][49] = 127,
+ [0][1][2][0][RTW89_ACMA][0][49] = 127,
+ [0][1][2][0][RTW89_CHILE][1][49] = -2,
+ [0][1][2][0][RTW89_QATAR][1][49] = 127,
+ [0][1][2][0][RTW89_QATAR][0][49] = 127,
+ [0][1][2][0][RTW89_UK][1][49] = 127,
+ [0][1][2][0][RTW89_UK][0][49] = 127,
+ [0][1][2][0][RTW89_FCC][1][51] = -2,
+ [0][1][2][0][RTW89_FCC][2][51] = 127,
+ [0][1][2][0][RTW89_ETSI][1][51] = 127,
+ [0][1][2][0][RTW89_ETSI][0][51] = 127,
+ [0][1][2][0][RTW89_MKK][1][51] = 127,
+ [0][1][2][0][RTW89_MKK][0][51] = 127,
+ [0][1][2][0][RTW89_IC][1][51] = -2,
+ [0][1][2][0][RTW89_KCC][1][51] = 12,
+ [0][1][2][0][RTW89_KCC][0][51] = 127,
+ [0][1][2][0][RTW89_ACMA][1][51] = 127,
+ [0][1][2][0][RTW89_ACMA][0][51] = 127,
+ [0][1][2][0][RTW89_CHILE][1][51] = -2,
+ [0][1][2][0][RTW89_QATAR][1][51] = 127,
+ [0][1][2][0][RTW89_QATAR][0][51] = 127,
+ [0][1][2][0][RTW89_UK][1][51] = 127,
+ [0][1][2][0][RTW89_UK][0][51] = 127,
+ [0][1][2][0][RTW89_FCC][1][53] = -2,
+ [0][1][2][0][RTW89_FCC][2][53] = 127,
+ [0][1][2][0][RTW89_ETSI][1][53] = 127,
+ [0][1][2][0][RTW89_ETSI][0][53] = 127,
+ [0][1][2][0][RTW89_MKK][1][53] = 127,
+ [0][1][2][0][RTW89_MKK][0][53] = 127,
+ [0][1][2][0][RTW89_IC][1][53] = -2,
+ [0][1][2][0][RTW89_KCC][1][53] = 12,
+ [0][1][2][0][RTW89_KCC][0][53] = 127,
+ [0][1][2][0][RTW89_ACMA][1][53] = 127,
+ [0][1][2][0][RTW89_ACMA][0][53] = 127,
+ [0][1][2][0][RTW89_CHILE][1][53] = -2,
+ [0][1][2][0][RTW89_QATAR][1][53] = 127,
+ [0][1][2][0][RTW89_QATAR][0][53] = 127,
+ [0][1][2][0][RTW89_UK][1][53] = 127,
+ [0][1][2][0][RTW89_UK][0][53] = 127,
+ [0][1][2][0][RTW89_FCC][1][55] = -2,
+ [0][1][2][0][RTW89_FCC][2][55] = 68,
+ [0][1][2][0][RTW89_ETSI][1][55] = 127,
+ [0][1][2][0][RTW89_ETSI][0][55] = 127,
+ [0][1][2][0][RTW89_MKK][1][55] = 127,
+ [0][1][2][0][RTW89_MKK][0][55] = 127,
+ [0][1][2][0][RTW89_IC][1][55] = -2,
+ [0][1][2][0][RTW89_KCC][1][55] = 12,
+ [0][1][2][0][RTW89_KCC][0][55] = 127,
+ [0][1][2][0][RTW89_ACMA][1][55] = 127,
+ [0][1][2][0][RTW89_ACMA][0][55] = 127,
+ [0][1][2][0][RTW89_CHILE][1][55] = -2,
+ [0][1][2][0][RTW89_QATAR][1][55] = 127,
+ [0][1][2][0][RTW89_QATAR][0][55] = 127,
+ [0][1][2][0][RTW89_UK][1][55] = 127,
+ [0][1][2][0][RTW89_UK][0][55] = 127,
+ [0][1][2][0][RTW89_FCC][1][57] = -2,
+ [0][1][2][0][RTW89_FCC][2][57] = 68,
+ [0][1][2][0][RTW89_ETSI][1][57] = 127,
+ [0][1][2][0][RTW89_ETSI][0][57] = 127,
+ [0][1][2][0][RTW89_MKK][1][57] = 127,
+ [0][1][2][0][RTW89_MKK][0][57] = 127,
+ [0][1][2][0][RTW89_IC][1][57] = -2,
+ [0][1][2][0][RTW89_KCC][1][57] = 12,
+ [0][1][2][0][RTW89_KCC][0][57] = 127,
+ [0][1][2][0][RTW89_ACMA][1][57] = 127,
+ [0][1][2][0][RTW89_ACMA][0][57] = 127,
+ [0][1][2][0][RTW89_CHILE][1][57] = -2,
+ [0][1][2][0][RTW89_QATAR][1][57] = 127,
+ [0][1][2][0][RTW89_QATAR][0][57] = 127,
+ [0][1][2][0][RTW89_UK][1][57] = 127,
+ [0][1][2][0][RTW89_UK][0][57] = 127,
+ [0][1][2][0][RTW89_FCC][1][59] = -2,
+ [0][1][2][0][RTW89_FCC][2][59] = 68,
+ [0][1][2][0][RTW89_ETSI][1][59] = 127,
+ [0][1][2][0][RTW89_ETSI][0][59] = 127,
+ [0][1][2][0][RTW89_MKK][1][59] = 127,
+ [0][1][2][0][RTW89_MKK][0][59] = 127,
+ [0][1][2][0][RTW89_IC][1][59] = -2,
+ [0][1][2][0][RTW89_KCC][1][59] = 12,
+ [0][1][2][0][RTW89_KCC][0][59] = 127,
+ [0][1][2][0][RTW89_ACMA][1][59] = 127,
+ [0][1][2][0][RTW89_ACMA][0][59] = 127,
+ [0][1][2][0][RTW89_CHILE][1][59] = -2,
+ [0][1][2][0][RTW89_QATAR][1][59] = 127,
+ [0][1][2][0][RTW89_QATAR][0][59] = 127,
+ [0][1][2][0][RTW89_UK][1][59] = 127,
+ [0][1][2][0][RTW89_UK][0][59] = 127,
+ [0][1][2][0][RTW89_FCC][1][60] = -2,
+ [0][1][2][0][RTW89_FCC][2][60] = 68,
+ [0][1][2][0][RTW89_ETSI][1][60] = 127,
+ [0][1][2][0][RTW89_ETSI][0][60] = 127,
+ [0][1][2][0][RTW89_MKK][1][60] = 127,
+ [0][1][2][0][RTW89_MKK][0][60] = 127,
+ [0][1][2][0][RTW89_IC][1][60] = -2,
+ [0][1][2][0][RTW89_KCC][1][60] = 12,
+ [0][1][2][0][RTW89_KCC][0][60] = 127,
+ [0][1][2][0][RTW89_ACMA][1][60] = 127,
+ [0][1][2][0][RTW89_ACMA][0][60] = 127,
+ [0][1][2][0][RTW89_CHILE][1][60] = -2,
+ [0][1][2][0][RTW89_QATAR][1][60] = 127,
+ [0][1][2][0][RTW89_QATAR][0][60] = 127,
+ [0][1][2][0][RTW89_UK][1][60] = 127,
+ [0][1][2][0][RTW89_UK][0][60] = 127,
+ [0][1][2][0][RTW89_FCC][1][62] = -2,
+ [0][1][2][0][RTW89_FCC][2][62] = 68,
+ [0][1][2][0][RTW89_ETSI][1][62] = 127,
+ [0][1][2][0][RTW89_ETSI][0][62] = 127,
+ [0][1][2][0][RTW89_MKK][1][62] = 127,
+ [0][1][2][0][RTW89_MKK][0][62] = 127,
+ [0][1][2][0][RTW89_IC][1][62] = -2,
+ [0][1][2][0][RTW89_KCC][1][62] = 12,
+ [0][1][2][0][RTW89_KCC][0][62] = 127,
+ [0][1][2][0][RTW89_ACMA][1][62] = 127,
+ [0][1][2][0][RTW89_ACMA][0][62] = 127,
+ [0][1][2][0][RTW89_CHILE][1][62] = -2,
+ [0][1][2][0][RTW89_QATAR][1][62] = 127,
+ [0][1][2][0][RTW89_QATAR][0][62] = 127,
+ [0][1][2][0][RTW89_UK][1][62] = 127,
+ [0][1][2][0][RTW89_UK][0][62] = 127,
+ [0][1][2][0][RTW89_FCC][1][64] = -2,
+ [0][1][2][0][RTW89_FCC][2][64] = 68,
+ [0][1][2][0][RTW89_ETSI][1][64] = 127,
+ [0][1][2][0][RTW89_ETSI][0][64] = 127,
+ [0][1][2][0][RTW89_MKK][1][64] = 127,
+ [0][1][2][0][RTW89_MKK][0][64] = 127,
+ [0][1][2][0][RTW89_IC][1][64] = -2,
+ [0][1][2][0][RTW89_KCC][1][64] = 12,
+ [0][1][2][0][RTW89_KCC][0][64] = 127,
+ [0][1][2][0][RTW89_ACMA][1][64] = 127,
+ [0][1][2][0][RTW89_ACMA][0][64] = 127,
+ [0][1][2][0][RTW89_CHILE][1][64] = -2,
+ [0][1][2][0][RTW89_QATAR][1][64] = 127,
+ [0][1][2][0][RTW89_QATAR][0][64] = 127,
+ [0][1][2][0][RTW89_UK][1][64] = 127,
+ [0][1][2][0][RTW89_UK][0][64] = 127,
+ [0][1][2][0][RTW89_FCC][1][66] = -2,
+ [0][1][2][0][RTW89_FCC][2][66] = 68,
+ [0][1][2][0][RTW89_ETSI][1][66] = 127,
+ [0][1][2][0][RTW89_ETSI][0][66] = 127,
+ [0][1][2][0][RTW89_MKK][1][66] = 127,
+ [0][1][2][0][RTW89_MKK][0][66] = 127,
+ [0][1][2][0][RTW89_IC][1][66] = -2,
+ [0][1][2][0][RTW89_KCC][1][66] = 12,
+ [0][1][2][0][RTW89_KCC][0][66] = 127,
+ [0][1][2][0][RTW89_ACMA][1][66] = 127,
+ [0][1][2][0][RTW89_ACMA][0][66] = 127,
+ [0][1][2][0][RTW89_CHILE][1][66] = -2,
+ [0][1][2][0][RTW89_QATAR][1][66] = 127,
+ [0][1][2][0][RTW89_QATAR][0][66] = 127,
+ [0][1][2][0][RTW89_UK][1][66] = 127,
+ [0][1][2][0][RTW89_UK][0][66] = 127,
+ [0][1][2][0][RTW89_FCC][1][68] = -2,
+ [0][1][2][0][RTW89_FCC][2][68] = 68,
+ [0][1][2][0][RTW89_ETSI][1][68] = 127,
+ [0][1][2][0][RTW89_ETSI][0][68] = 127,
+ [0][1][2][0][RTW89_MKK][1][68] = 127,
+ [0][1][2][0][RTW89_MKK][0][68] = 127,
+ [0][1][2][0][RTW89_IC][1][68] = -2,
+ [0][1][2][0][RTW89_KCC][1][68] = 12,
+ [0][1][2][0][RTW89_KCC][0][68] = 127,
+ [0][1][2][0][RTW89_ACMA][1][68] = 127,
+ [0][1][2][0][RTW89_ACMA][0][68] = 127,
+ [0][1][2][0][RTW89_CHILE][1][68] = -2,
+ [0][1][2][0][RTW89_QATAR][1][68] = 127,
+ [0][1][2][0][RTW89_QATAR][0][68] = 127,
+ [0][1][2][0][RTW89_UK][1][68] = 127,
+ [0][1][2][0][RTW89_UK][0][68] = 127,
+ [0][1][2][0][RTW89_FCC][1][70] = -2,
+ [0][1][2][0][RTW89_FCC][2][70] = 68,
+ [0][1][2][0][RTW89_ETSI][1][70] = 127,
+ [0][1][2][0][RTW89_ETSI][0][70] = 127,
+ [0][1][2][0][RTW89_MKK][1][70] = 127,
+ [0][1][2][0][RTW89_MKK][0][70] = 127,
+ [0][1][2][0][RTW89_IC][1][70] = -2,
+ [0][1][2][0][RTW89_KCC][1][70] = 12,
+ [0][1][2][0][RTW89_KCC][0][70] = 127,
+ [0][1][2][0][RTW89_ACMA][1][70] = 127,
+ [0][1][2][0][RTW89_ACMA][0][70] = 127,
+ [0][1][2][0][RTW89_CHILE][1][70] = -2,
+ [0][1][2][0][RTW89_QATAR][1][70] = 127,
+ [0][1][2][0][RTW89_QATAR][0][70] = 127,
+ [0][1][2][0][RTW89_UK][1][70] = 127,
+ [0][1][2][0][RTW89_UK][0][70] = 127,
+ [0][1][2][0][RTW89_FCC][1][72] = -2,
+ [0][1][2][0][RTW89_FCC][2][72] = 68,
+ [0][1][2][0][RTW89_ETSI][1][72] = 127,
+ [0][1][2][0][RTW89_ETSI][0][72] = 127,
+ [0][1][2][0][RTW89_MKK][1][72] = 127,
+ [0][1][2][0][RTW89_MKK][0][72] = 127,
+ [0][1][2][0][RTW89_IC][1][72] = -2,
+ [0][1][2][0][RTW89_KCC][1][72] = 12,
+ [0][1][2][0][RTW89_KCC][0][72] = 127,
+ [0][1][2][0][RTW89_ACMA][1][72] = 127,
+ [0][1][2][0][RTW89_ACMA][0][72] = 127,
+ [0][1][2][0][RTW89_CHILE][1][72] = -2,
+ [0][1][2][0][RTW89_QATAR][1][72] = 127,
+ [0][1][2][0][RTW89_QATAR][0][72] = 127,
+ [0][1][2][0][RTW89_UK][1][72] = 127,
+ [0][1][2][0][RTW89_UK][0][72] = 127,
+ [0][1][2][0][RTW89_FCC][1][74] = -2,
+ [0][1][2][0][RTW89_FCC][2][74] = 68,
+ [0][1][2][0][RTW89_ETSI][1][74] = 127,
+ [0][1][2][0][RTW89_ETSI][0][74] = 127,
+ [0][1][2][0][RTW89_MKK][1][74] = 127,
+ [0][1][2][0][RTW89_MKK][0][74] = 127,
+ [0][1][2][0][RTW89_IC][1][74] = -2,
+ [0][1][2][0][RTW89_KCC][1][74] = 12,
+ [0][1][2][0][RTW89_KCC][0][74] = 127,
+ [0][1][2][0][RTW89_ACMA][1][74] = 127,
+ [0][1][2][0][RTW89_ACMA][0][74] = 127,
+ [0][1][2][0][RTW89_CHILE][1][74] = -2,
+ [0][1][2][0][RTW89_QATAR][1][74] = 127,
+ [0][1][2][0][RTW89_QATAR][0][74] = 127,
+ [0][1][2][0][RTW89_UK][1][74] = 127,
+ [0][1][2][0][RTW89_UK][0][74] = 127,
+ [0][1][2][0][RTW89_FCC][1][75] = -2,
+ [0][1][2][0][RTW89_FCC][2][75] = 68,
+ [0][1][2][0][RTW89_ETSI][1][75] = 127,
+ [0][1][2][0][RTW89_ETSI][0][75] = 127,
+ [0][1][2][0][RTW89_MKK][1][75] = 127,
+ [0][1][2][0][RTW89_MKK][0][75] = 127,
+ [0][1][2][0][RTW89_IC][1][75] = -2,
+ [0][1][2][0][RTW89_KCC][1][75] = 12,
+ [0][1][2][0][RTW89_KCC][0][75] = 127,
+ [0][1][2][0][RTW89_ACMA][1][75] = 127,
+ [0][1][2][0][RTW89_ACMA][0][75] = 127,
+ [0][1][2][0][RTW89_CHILE][1][75] = -2,
+ [0][1][2][0][RTW89_QATAR][1][75] = 127,
+ [0][1][2][0][RTW89_QATAR][0][75] = 127,
+ [0][1][2][0][RTW89_UK][1][75] = 127,
+ [0][1][2][0][RTW89_UK][0][75] = 127,
+ [0][1][2][0][RTW89_FCC][1][77] = -2,
+ [0][1][2][0][RTW89_FCC][2][77] = 68,
+ [0][1][2][0][RTW89_ETSI][1][77] = 127,
+ [0][1][2][0][RTW89_ETSI][0][77] = 127,
+ [0][1][2][0][RTW89_MKK][1][77] = 127,
+ [0][1][2][0][RTW89_MKK][0][77] = 127,
+ [0][1][2][0][RTW89_IC][1][77] = -2,
+ [0][1][2][0][RTW89_KCC][1][77] = 12,
+ [0][1][2][0][RTW89_KCC][0][77] = 127,
+ [0][1][2][0][RTW89_ACMA][1][77] = 127,
+ [0][1][2][0][RTW89_ACMA][0][77] = 127,
+ [0][1][2][0][RTW89_CHILE][1][77] = -2,
+ [0][1][2][0][RTW89_QATAR][1][77] = 127,
+ [0][1][2][0][RTW89_QATAR][0][77] = 127,
+ [0][1][2][0][RTW89_UK][1][77] = 127,
+ [0][1][2][0][RTW89_UK][0][77] = 127,
+ [0][1][2][0][RTW89_FCC][1][79] = -2,
+ [0][1][2][0][RTW89_FCC][2][79] = 68,
+ [0][1][2][0][RTW89_ETSI][1][79] = 127,
+ [0][1][2][0][RTW89_ETSI][0][79] = 127,
+ [0][1][2][0][RTW89_MKK][1][79] = 127,
+ [0][1][2][0][RTW89_MKK][0][79] = 127,
+ [0][1][2][0][RTW89_IC][1][79] = -2,
+ [0][1][2][0][RTW89_KCC][1][79] = 12,
+ [0][1][2][0][RTW89_KCC][0][79] = 127,
+ [0][1][2][0][RTW89_ACMA][1][79] = 127,
+ [0][1][2][0][RTW89_ACMA][0][79] = 127,
+ [0][1][2][0][RTW89_CHILE][1][79] = -2,
+ [0][1][2][0][RTW89_QATAR][1][79] = 127,
+ [0][1][2][0][RTW89_QATAR][0][79] = 127,
+ [0][1][2][0][RTW89_UK][1][79] = 127,
+ [0][1][2][0][RTW89_UK][0][79] = 127,
+ [0][1][2][0][RTW89_FCC][1][81] = -2,
+ [0][1][2][0][RTW89_FCC][2][81] = 68,
+ [0][1][2][0][RTW89_ETSI][1][81] = 127,
+ [0][1][2][0][RTW89_ETSI][0][81] = 127,
+ [0][1][2][0][RTW89_MKK][1][81] = 127,
+ [0][1][2][0][RTW89_MKK][0][81] = 127,
+ [0][1][2][0][RTW89_IC][1][81] = -2,
+ [0][1][2][0][RTW89_KCC][1][81] = 12,
+ [0][1][2][0][RTW89_KCC][0][81] = 127,
+ [0][1][2][0][RTW89_ACMA][1][81] = 127,
+ [0][1][2][0][RTW89_ACMA][0][81] = 127,
+ [0][1][2][0][RTW89_CHILE][1][81] = -2,
+ [0][1][2][0][RTW89_QATAR][1][81] = 127,
+ [0][1][2][0][RTW89_QATAR][0][81] = 127,
+ [0][1][2][0][RTW89_UK][1][81] = 127,
+ [0][1][2][0][RTW89_UK][0][81] = 127,
+ [0][1][2][0][RTW89_FCC][1][83] = -2,
+ [0][1][2][0][RTW89_FCC][2][83] = 68,
+ [0][1][2][0][RTW89_ETSI][1][83] = 127,
+ [0][1][2][0][RTW89_ETSI][0][83] = 127,
+ [0][1][2][0][RTW89_MKK][1][83] = 127,
+ [0][1][2][0][RTW89_MKK][0][83] = 127,
+ [0][1][2][0][RTW89_IC][1][83] = -2,
+ [0][1][2][0][RTW89_KCC][1][83] = 20,
+ [0][1][2][0][RTW89_KCC][0][83] = 127,
+ [0][1][2][0][RTW89_ACMA][1][83] = 127,
+ [0][1][2][0][RTW89_ACMA][0][83] = 127,
+ [0][1][2][0][RTW89_CHILE][1][83] = -2,
+ [0][1][2][0][RTW89_QATAR][1][83] = 127,
+ [0][1][2][0][RTW89_QATAR][0][83] = 127,
+ [0][1][2][0][RTW89_UK][1][83] = 127,
+ [0][1][2][0][RTW89_UK][0][83] = 127,
+ [0][1][2][0][RTW89_FCC][1][85] = -2,
+ [0][1][2][0][RTW89_FCC][2][85] = 68,
+ [0][1][2][0][RTW89_ETSI][1][85] = 127,
+ [0][1][2][0][RTW89_ETSI][0][85] = 127,
+ [0][1][2][0][RTW89_MKK][1][85] = 127,
+ [0][1][2][0][RTW89_MKK][0][85] = 127,
+ [0][1][2][0][RTW89_IC][1][85] = -2,
+ [0][1][2][0][RTW89_KCC][1][85] = 20,
+ [0][1][2][0][RTW89_KCC][0][85] = 127,
+ [0][1][2][0][RTW89_ACMA][1][85] = 127,
+ [0][1][2][0][RTW89_ACMA][0][85] = 127,
+ [0][1][2][0][RTW89_CHILE][1][85] = -2,
+ [0][1][2][0][RTW89_QATAR][1][85] = 127,
+ [0][1][2][0][RTW89_QATAR][0][85] = 127,
+ [0][1][2][0][RTW89_UK][1][85] = 127,
+ [0][1][2][0][RTW89_UK][0][85] = 127,
+ [0][1][2][0][RTW89_FCC][1][87] = -2,
+ [0][1][2][0][RTW89_FCC][2][87] = 127,
+ [0][1][2][0][RTW89_ETSI][1][87] = 127,
+ [0][1][2][0][RTW89_ETSI][0][87] = 127,
+ [0][1][2][0][RTW89_MKK][1][87] = 127,
+ [0][1][2][0][RTW89_MKK][0][87] = 127,
+ [0][1][2][0][RTW89_IC][1][87] = -2,
+ [0][1][2][0][RTW89_KCC][1][87] = 20,
+ [0][1][2][0][RTW89_KCC][0][87] = 127,
+ [0][1][2][0][RTW89_ACMA][1][87] = 127,
+ [0][1][2][0][RTW89_ACMA][0][87] = 127,
+ [0][1][2][0][RTW89_CHILE][1][87] = -2,
+ [0][1][2][0][RTW89_QATAR][1][87] = 127,
+ [0][1][2][0][RTW89_QATAR][0][87] = 127,
+ [0][1][2][0][RTW89_UK][1][87] = 127,
+ [0][1][2][0][RTW89_UK][0][87] = 127,
+ [0][1][2][0][RTW89_FCC][1][89] = -2,
+ [0][1][2][0][RTW89_FCC][2][89] = 127,
+ [0][1][2][0][RTW89_ETSI][1][89] = 127,
+ [0][1][2][0][RTW89_ETSI][0][89] = 127,
+ [0][1][2][0][RTW89_MKK][1][89] = 127,
+ [0][1][2][0][RTW89_MKK][0][89] = 127,
+ [0][1][2][0][RTW89_IC][1][89] = -2,
+ [0][1][2][0][RTW89_KCC][1][89] = 20,
+ [0][1][2][0][RTW89_KCC][0][89] = 127,
+ [0][1][2][0][RTW89_ACMA][1][89] = 127,
+ [0][1][2][0][RTW89_ACMA][0][89] = 127,
+ [0][1][2][0][RTW89_CHILE][1][89] = -2,
+ [0][1][2][0][RTW89_QATAR][1][89] = 127,
+ [0][1][2][0][RTW89_QATAR][0][89] = 127,
+ [0][1][2][0][RTW89_UK][1][89] = 127,
+ [0][1][2][0][RTW89_UK][0][89] = 127,
+ [0][1][2][0][RTW89_FCC][1][90] = -2,
+ [0][1][2][0][RTW89_FCC][2][90] = 127,
+ [0][1][2][0][RTW89_ETSI][1][90] = 127,
+ [0][1][2][0][RTW89_ETSI][0][90] = 127,
+ [0][1][2][0][RTW89_MKK][1][90] = 127,
+ [0][1][2][0][RTW89_MKK][0][90] = 127,
+ [0][1][2][0][RTW89_IC][1][90] = -2,
+ [0][1][2][0][RTW89_KCC][1][90] = 20,
+ [0][1][2][0][RTW89_KCC][0][90] = 127,
+ [0][1][2][0][RTW89_ACMA][1][90] = 127,
+ [0][1][2][0][RTW89_ACMA][0][90] = 127,
+ [0][1][2][0][RTW89_CHILE][1][90] = -2,
+ [0][1][2][0][RTW89_QATAR][1][90] = 127,
+ [0][1][2][0][RTW89_QATAR][0][90] = 127,
+ [0][1][2][0][RTW89_UK][1][90] = 127,
+ [0][1][2][0][RTW89_UK][0][90] = 127,
+ [0][1][2][0][RTW89_FCC][1][92] = -2,
+ [0][1][2][0][RTW89_FCC][2][92] = 127,
+ [0][1][2][0][RTW89_ETSI][1][92] = 127,
+ [0][1][2][0][RTW89_ETSI][0][92] = 127,
+ [0][1][2][0][RTW89_MKK][1][92] = 127,
+ [0][1][2][0][RTW89_MKK][0][92] = 127,
+ [0][1][2][0][RTW89_IC][1][92] = -2,
+ [0][1][2][0][RTW89_KCC][1][92] = 20,
+ [0][1][2][0][RTW89_KCC][0][92] = 127,
+ [0][1][2][0][RTW89_ACMA][1][92] = 127,
+ [0][1][2][0][RTW89_ACMA][0][92] = 127,
+ [0][1][2][0][RTW89_CHILE][1][92] = -2,
+ [0][1][2][0][RTW89_QATAR][1][92] = 127,
+ [0][1][2][0][RTW89_QATAR][0][92] = 127,
+ [0][1][2][0][RTW89_UK][1][92] = 127,
+ [0][1][2][0][RTW89_UK][0][92] = 127,
+ [0][1][2][0][RTW89_FCC][1][94] = -2,
+ [0][1][2][0][RTW89_FCC][2][94] = 127,
+ [0][1][2][0][RTW89_ETSI][1][94] = 127,
+ [0][1][2][0][RTW89_ETSI][0][94] = 127,
+ [0][1][2][0][RTW89_MKK][1][94] = 127,
+ [0][1][2][0][RTW89_MKK][0][94] = 127,
+ [0][1][2][0][RTW89_IC][1][94] = -2,
+ [0][1][2][0][RTW89_KCC][1][94] = 20,
+ [0][1][2][0][RTW89_KCC][0][94] = 127,
+ [0][1][2][0][RTW89_ACMA][1][94] = 127,
+ [0][1][2][0][RTW89_ACMA][0][94] = 127,
+ [0][1][2][0][RTW89_CHILE][1][94] = -2,
+ [0][1][2][0][RTW89_QATAR][1][94] = 127,
+ [0][1][2][0][RTW89_QATAR][0][94] = 127,
+ [0][1][2][0][RTW89_UK][1][94] = 127,
+ [0][1][2][0][RTW89_UK][0][94] = 127,
+ [0][1][2][0][RTW89_FCC][1][96] = -2,
+ [0][1][2][0][RTW89_FCC][2][96] = 127,
+ [0][1][2][0][RTW89_ETSI][1][96] = 127,
+ [0][1][2][0][RTW89_ETSI][0][96] = 127,
+ [0][1][2][0][RTW89_MKK][1][96] = 127,
+ [0][1][2][0][RTW89_MKK][0][96] = 127,
+ [0][1][2][0][RTW89_IC][1][96] = -2,
+ [0][1][2][0][RTW89_KCC][1][96] = 20,
+ [0][1][2][0][RTW89_KCC][0][96] = 127,
+ [0][1][2][0][RTW89_ACMA][1][96] = 127,
+ [0][1][2][0][RTW89_ACMA][0][96] = 127,
+ [0][1][2][0][RTW89_CHILE][1][96] = -2,
+ [0][1][2][0][RTW89_QATAR][1][96] = 127,
+ [0][1][2][0][RTW89_QATAR][0][96] = 127,
+ [0][1][2][0][RTW89_UK][1][96] = 127,
+ [0][1][2][0][RTW89_UK][0][96] = 127,
+ [0][1][2][0][RTW89_FCC][1][98] = -2,
+ [0][1][2][0][RTW89_FCC][2][98] = 127,
+ [0][1][2][0][RTW89_ETSI][1][98] = 127,
+ [0][1][2][0][RTW89_ETSI][0][98] = 127,
+ [0][1][2][0][RTW89_MKK][1][98] = 127,
+ [0][1][2][0][RTW89_MKK][0][98] = 127,
+ [0][1][2][0][RTW89_IC][1][98] = -2,
+ [0][1][2][0][RTW89_KCC][1][98] = 20,
+ [0][1][2][0][RTW89_KCC][0][98] = 127,
+ [0][1][2][0][RTW89_ACMA][1][98] = 127,
+ [0][1][2][0][RTW89_ACMA][0][98] = 127,
+ [0][1][2][0][RTW89_CHILE][1][98] = -2,
+ [0][1][2][0][RTW89_QATAR][1][98] = 127,
+ [0][1][2][0][RTW89_QATAR][0][98] = 127,
+ [0][1][2][0][RTW89_UK][1][98] = 127,
+ [0][1][2][0][RTW89_UK][0][98] = 127,
+ [0][1][2][0][RTW89_FCC][1][100] = -2,
+ [0][1][2][0][RTW89_FCC][2][100] = 127,
+ [0][1][2][0][RTW89_ETSI][1][100] = 127,
+ [0][1][2][0][RTW89_ETSI][0][100] = 127,
+ [0][1][2][0][RTW89_MKK][1][100] = 127,
+ [0][1][2][0][RTW89_MKK][0][100] = 127,
+ [0][1][2][0][RTW89_IC][1][100] = -2,
+ [0][1][2][0][RTW89_KCC][1][100] = 20,
+ [0][1][2][0][RTW89_KCC][0][100] = 127,
+ [0][1][2][0][RTW89_ACMA][1][100] = 127,
+ [0][1][2][0][RTW89_ACMA][0][100] = 127,
+ [0][1][2][0][RTW89_CHILE][1][100] = -2,
+ [0][1][2][0][RTW89_QATAR][1][100] = 127,
+ [0][1][2][0][RTW89_QATAR][0][100] = 127,
+ [0][1][2][0][RTW89_UK][1][100] = 127,
+ [0][1][2][0][RTW89_UK][0][100] = 127,
+ [0][1][2][0][RTW89_FCC][1][102] = -2,
+ [0][1][2][0][RTW89_FCC][2][102] = 127,
+ [0][1][2][0][RTW89_ETSI][1][102] = 127,
+ [0][1][2][0][RTW89_ETSI][0][102] = 127,
+ [0][1][2][0][RTW89_MKK][1][102] = 127,
+ [0][1][2][0][RTW89_MKK][0][102] = 127,
+ [0][1][2][0][RTW89_IC][1][102] = -2,
+ [0][1][2][0][RTW89_KCC][1][102] = 20,
+ [0][1][2][0][RTW89_KCC][0][102] = 127,
+ [0][1][2][0][RTW89_ACMA][1][102] = 127,
+ [0][1][2][0][RTW89_ACMA][0][102] = 127,
+ [0][1][2][0][RTW89_CHILE][1][102] = -2,
+ [0][1][2][0][RTW89_QATAR][1][102] = 127,
+ [0][1][2][0][RTW89_QATAR][0][102] = 127,
+ [0][1][2][0][RTW89_UK][1][102] = 127,
+ [0][1][2][0][RTW89_UK][0][102] = 127,
+ [0][1][2][0][RTW89_FCC][1][104] = -2,
+ [0][1][2][0][RTW89_FCC][2][104] = 127,
+ [0][1][2][0][RTW89_ETSI][1][104] = 127,
+ [0][1][2][0][RTW89_ETSI][0][104] = 127,
+ [0][1][2][0][RTW89_MKK][1][104] = 127,
+ [0][1][2][0][RTW89_MKK][0][104] = 127,
+ [0][1][2][0][RTW89_IC][1][104] = -2,
+ [0][1][2][0][RTW89_KCC][1][104] = 20,
+ [0][1][2][0][RTW89_KCC][0][104] = 127,
+ [0][1][2][0][RTW89_ACMA][1][104] = 127,
+ [0][1][2][0][RTW89_ACMA][0][104] = 127,
+ [0][1][2][0][RTW89_CHILE][1][104] = -2,
+ [0][1][2][0][RTW89_QATAR][1][104] = 127,
+ [0][1][2][0][RTW89_QATAR][0][104] = 127,
+ [0][1][2][0][RTW89_UK][1][104] = 127,
+ [0][1][2][0][RTW89_UK][0][104] = 127,
+ [0][1][2][0][RTW89_FCC][1][105] = -2,
+ [0][1][2][0][RTW89_FCC][2][105] = 127,
+ [0][1][2][0][RTW89_ETSI][1][105] = 127,
+ [0][1][2][0][RTW89_ETSI][0][105] = 127,
+ [0][1][2][0][RTW89_MKK][1][105] = 127,
+ [0][1][2][0][RTW89_MKK][0][105] = 127,
+ [0][1][2][0][RTW89_IC][1][105] = -2,
+ [0][1][2][0][RTW89_KCC][1][105] = 20,
+ [0][1][2][0][RTW89_KCC][0][105] = 127,
+ [0][1][2][0][RTW89_ACMA][1][105] = 127,
+ [0][1][2][0][RTW89_ACMA][0][105] = 127,
+ [0][1][2][0][RTW89_CHILE][1][105] = -2,
+ [0][1][2][0][RTW89_QATAR][1][105] = 127,
+ [0][1][2][0][RTW89_QATAR][0][105] = 127,
+ [0][1][2][0][RTW89_UK][1][105] = 127,
+ [0][1][2][0][RTW89_UK][0][105] = 127,
+ [0][1][2][0][RTW89_FCC][1][107] = 1,
+ [0][1][2][0][RTW89_FCC][2][107] = 127,
+ [0][1][2][0][RTW89_ETSI][1][107] = 127,
+ [0][1][2][0][RTW89_ETSI][0][107] = 127,
+ [0][1][2][0][RTW89_MKK][1][107] = 127,
+ [0][1][2][0][RTW89_MKK][0][107] = 127,
+ [0][1][2][0][RTW89_IC][1][107] = 1,
+ [0][1][2][0][RTW89_KCC][1][107] = 20,
+ [0][1][2][0][RTW89_KCC][0][107] = 127,
+ [0][1][2][0][RTW89_ACMA][1][107] = 127,
+ [0][1][2][0][RTW89_ACMA][0][107] = 127,
+ [0][1][2][0][RTW89_CHILE][1][107] = 1,
+ [0][1][2][0][RTW89_QATAR][1][107] = 127,
+ [0][1][2][0][RTW89_QATAR][0][107] = 127,
+ [0][1][2][0][RTW89_UK][1][107] = 127,
+ [0][1][2][0][RTW89_UK][0][107] = 127,
+ [0][1][2][0][RTW89_FCC][1][109] = 1,
+ [0][1][2][0][RTW89_FCC][2][109] = 127,
+ [0][1][2][0][RTW89_ETSI][1][109] = 127,
+ [0][1][2][0][RTW89_ETSI][0][109] = 127,
+ [0][1][2][0][RTW89_MKK][1][109] = 127,
+ [0][1][2][0][RTW89_MKK][0][109] = 127,
+ [0][1][2][0][RTW89_IC][1][109] = 1,
+ [0][1][2][0][RTW89_KCC][1][109] = 20,
+ [0][1][2][0][RTW89_KCC][0][109] = 127,
+ [0][1][2][0][RTW89_ACMA][1][109] = 127,
+ [0][1][2][0][RTW89_ACMA][0][109] = 127,
+ [0][1][2][0][RTW89_CHILE][1][109] = 1,
+ [0][1][2][0][RTW89_QATAR][1][109] = 127,
+ [0][1][2][0][RTW89_QATAR][0][109] = 127,
+ [0][1][2][0][RTW89_UK][1][109] = 127,
+ [0][1][2][0][RTW89_UK][0][109] = 127,
+ [0][1][2][0][RTW89_FCC][1][111] = 127,
+ [0][1][2][0][RTW89_FCC][2][111] = 127,
+ [0][1][2][0][RTW89_ETSI][1][111] = 127,
+ [0][1][2][0][RTW89_ETSI][0][111] = 127,
+ [0][1][2][0][RTW89_MKK][1][111] = 127,
+ [0][1][2][0][RTW89_MKK][0][111] = 127,
+ [0][1][2][0][RTW89_IC][1][111] = 127,
+ [0][1][2][0][RTW89_KCC][1][111] = 127,
+ [0][1][2][0][RTW89_KCC][0][111] = 127,
+ [0][1][2][0][RTW89_ACMA][1][111] = 127,
+ [0][1][2][0][RTW89_ACMA][0][111] = 127,
+ [0][1][2][0][RTW89_CHILE][1][111] = 127,
+ [0][1][2][0][RTW89_QATAR][1][111] = 127,
+ [0][1][2][0][RTW89_QATAR][0][111] = 127,
+ [0][1][2][0][RTW89_UK][1][111] = 127,
+ [0][1][2][0][RTW89_UK][0][111] = 127,
+ [0][1][2][0][RTW89_FCC][1][113] = 127,
+ [0][1][2][0][RTW89_FCC][2][113] = 127,
+ [0][1][2][0][RTW89_ETSI][1][113] = 127,
+ [0][1][2][0][RTW89_ETSI][0][113] = 127,
+ [0][1][2][0][RTW89_MKK][1][113] = 127,
+ [0][1][2][0][RTW89_MKK][0][113] = 127,
+ [0][1][2][0][RTW89_IC][1][113] = 127,
+ [0][1][2][0][RTW89_KCC][1][113] = 127,
+ [0][1][2][0][RTW89_KCC][0][113] = 127,
+ [0][1][2][0][RTW89_ACMA][1][113] = 127,
+ [0][1][2][0][RTW89_ACMA][0][113] = 127,
+ [0][1][2][0][RTW89_CHILE][1][113] = 127,
+ [0][1][2][0][RTW89_QATAR][1][113] = 127,
+ [0][1][2][0][RTW89_QATAR][0][113] = 127,
+ [0][1][2][0][RTW89_UK][1][113] = 127,
+ [0][1][2][0][RTW89_UK][0][113] = 127,
+ [0][1][2][0][RTW89_FCC][1][115] = 127,
+ [0][1][2][0][RTW89_FCC][2][115] = 127,
+ [0][1][2][0][RTW89_ETSI][1][115] = 127,
+ [0][1][2][0][RTW89_ETSI][0][115] = 127,
+ [0][1][2][0][RTW89_MKK][1][115] = 127,
+ [0][1][2][0][RTW89_MKK][0][115] = 127,
+ [0][1][2][0][RTW89_IC][1][115] = 127,
+ [0][1][2][0][RTW89_KCC][1][115] = 127,
+ [0][1][2][0][RTW89_KCC][0][115] = 127,
+ [0][1][2][0][RTW89_ACMA][1][115] = 127,
+ [0][1][2][0][RTW89_ACMA][0][115] = 127,
+ [0][1][2][0][RTW89_CHILE][1][115] = 127,
+ [0][1][2][0][RTW89_QATAR][1][115] = 127,
+ [0][1][2][0][RTW89_QATAR][0][115] = 127,
+ [0][1][2][0][RTW89_UK][1][115] = 127,
+ [0][1][2][0][RTW89_UK][0][115] = 127,
+ [0][1][2][0][RTW89_FCC][1][117] = 127,
+ [0][1][2][0][RTW89_FCC][2][117] = 127,
+ [0][1][2][0][RTW89_ETSI][1][117] = 127,
+ [0][1][2][0][RTW89_ETSI][0][117] = 127,
+ [0][1][2][0][RTW89_MKK][1][117] = 127,
+ [0][1][2][0][RTW89_MKK][0][117] = 127,
+ [0][1][2][0][RTW89_IC][1][117] = 127,
+ [0][1][2][0][RTW89_KCC][1][117] = 127,
+ [0][1][2][0][RTW89_KCC][0][117] = 127,
+ [0][1][2][0][RTW89_ACMA][1][117] = 127,
+ [0][1][2][0][RTW89_ACMA][0][117] = 127,
+ [0][1][2][0][RTW89_CHILE][1][117] = 127,
+ [0][1][2][0][RTW89_QATAR][1][117] = 127,
+ [0][1][2][0][RTW89_QATAR][0][117] = 127,
+ [0][1][2][0][RTW89_UK][1][117] = 127,
+ [0][1][2][0][RTW89_UK][0][117] = 127,
+ [0][1][2][0][RTW89_FCC][1][119] = 127,
+ [0][1][2][0][RTW89_FCC][2][119] = 127,
+ [0][1][2][0][RTW89_ETSI][1][119] = 127,
+ [0][1][2][0][RTW89_ETSI][0][119] = 127,
+ [0][1][2][0][RTW89_MKK][1][119] = 127,
+ [0][1][2][0][RTW89_MKK][0][119] = 127,
+ [0][1][2][0][RTW89_IC][1][119] = 127,
+ [0][1][2][0][RTW89_KCC][1][119] = 127,
+ [0][1][2][0][RTW89_KCC][0][119] = 127,
+ [0][1][2][0][RTW89_ACMA][1][119] = 127,
+ [0][1][2][0][RTW89_ACMA][0][119] = 127,
+ [0][1][2][0][RTW89_CHILE][1][119] = 127,
+ [0][1][2][0][RTW89_QATAR][1][119] = 127,
+ [0][1][2][0][RTW89_QATAR][0][119] = 127,
+ [0][1][2][0][RTW89_UK][1][119] = 127,
+ [0][1][2][0][RTW89_UK][0][119] = 127,
+ [0][1][2][1][RTW89_FCC][1][0] = -2,
+ [0][1][2][1][RTW89_FCC][2][0] = 54,
+ [0][1][2][1][RTW89_ETSI][1][0] = 42,
+ [0][1][2][1][RTW89_ETSI][0][0] = 6,
+ [0][1][2][1][RTW89_MKK][1][0] = 56,
+ [0][1][2][1][RTW89_MKK][0][0] = 16,
+ [0][1][2][1][RTW89_IC][1][0] = -2,
+ [0][1][2][1][RTW89_KCC][1][0] = 12,
+ [0][1][2][1][RTW89_KCC][0][0] = 10,
+ [0][1][2][1][RTW89_ACMA][1][0] = 42,
+ [0][1][2][1][RTW89_ACMA][0][0] = 6,
+ [0][1][2][1][RTW89_CHILE][1][0] = -2,
+ [0][1][2][1][RTW89_QATAR][1][0] = 42,
+ [0][1][2][1][RTW89_QATAR][0][0] = 6,
+ [0][1][2][1][RTW89_UK][1][0] = 42,
+ [0][1][2][1][RTW89_UK][0][0] = 6,
+ [0][1][2][1][RTW89_FCC][1][2] = -4,
+ [0][1][2][1][RTW89_FCC][2][2] = 54,
+ [0][1][2][1][RTW89_ETSI][1][2] = 42,
+ [0][1][2][1][RTW89_ETSI][0][2] = 6,
+ [0][1][2][1][RTW89_MKK][1][2] = 54,
+ [0][1][2][1][RTW89_MKK][0][2] = 16,
+ [0][1][2][1][RTW89_IC][1][2] = -4,
+ [0][1][2][1][RTW89_KCC][1][2] = 12,
+ [0][1][2][1][RTW89_KCC][0][2] = 12,
+ [0][1][2][1][RTW89_ACMA][1][2] = 42,
+ [0][1][2][1][RTW89_ACMA][0][2] = 6,
+ [0][1][2][1][RTW89_CHILE][1][2] = -4,
+ [0][1][2][1][RTW89_QATAR][1][2] = 42,
+ [0][1][2][1][RTW89_QATAR][0][2] = 6,
+ [0][1][2][1][RTW89_UK][1][2] = 42,
+ [0][1][2][1][RTW89_UK][0][2] = 6,
+ [0][1][2][1][RTW89_FCC][1][4] = -4,
+ [0][1][2][1][RTW89_FCC][2][4] = 54,
+ [0][1][2][1][RTW89_ETSI][1][4] = 42,
+ [0][1][2][1][RTW89_ETSI][0][4] = 6,
+ [0][1][2][1][RTW89_MKK][1][4] = 54,
+ [0][1][2][1][RTW89_MKK][0][4] = 16,
+ [0][1][2][1][RTW89_IC][1][4] = -4,
+ [0][1][2][1][RTW89_KCC][1][4] = 12,
+ [0][1][2][1][RTW89_KCC][0][4] = 12,
+ [0][1][2][1][RTW89_ACMA][1][4] = 42,
+ [0][1][2][1][RTW89_ACMA][0][4] = 6,
+ [0][1][2][1][RTW89_CHILE][1][4] = -4,
+ [0][1][2][1][RTW89_QATAR][1][4] = 42,
+ [0][1][2][1][RTW89_QATAR][0][4] = 6,
+ [0][1][2][1][RTW89_UK][1][4] = 42,
+ [0][1][2][1][RTW89_UK][0][4] = 6,
+ [0][1][2][1][RTW89_FCC][1][6] = -4,
+ [0][1][2][1][RTW89_FCC][2][6] = 54,
+ [0][1][2][1][RTW89_ETSI][1][6] = 42,
+ [0][1][2][1][RTW89_ETSI][0][6] = 6,
+ [0][1][2][1][RTW89_MKK][1][6] = 54,
+ [0][1][2][1][RTW89_MKK][0][6] = 16,
+ [0][1][2][1][RTW89_IC][1][6] = -4,
+ [0][1][2][1][RTW89_KCC][1][6] = 12,
+ [0][1][2][1][RTW89_KCC][0][6] = 12,
+ [0][1][2][1][RTW89_ACMA][1][6] = 42,
+ [0][1][2][1][RTW89_ACMA][0][6] = 6,
+ [0][1][2][1][RTW89_CHILE][1][6] = -4,
+ [0][1][2][1][RTW89_QATAR][1][6] = 42,
+ [0][1][2][1][RTW89_QATAR][0][6] = 6,
+ [0][1][2][1][RTW89_UK][1][6] = 42,
+ [0][1][2][1][RTW89_UK][0][6] = 6,
+ [0][1][2][1][RTW89_FCC][1][8] = -4,
+ [0][1][2][1][RTW89_FCC][2][8] = 54,
+ [0][1][2][1][RTW89_ETSI][1][8] = 42,
+ [0][1][2][1][RTW89_ETSI][0][8] = 6,
+ [0][1][2][1][RTW89_MKK][1][8] = 54,
+ [0][1][2][1][RTW89_MKK][0][8] = 16,
+ [0][1][2][1][RTW89_IC][1][8] = -4,
+ [0][1][2][1][RTW89_KCC][1][8] = 12,
+ [0][1][2][1][RTW89_KCC][0][8] = 12,
+ [0][1][2][1][RTW89_ACMA][1][8] = 42,
+ [0][1][2][1][RTW89_ACMA][0][8] = 6,
+ [0][1][2][1][RTW89_CHILE][1][8] = -4,
+ [0][1][2][1][RTW89_QATAR][1][8] = 42,
+ [0][1][2][1][RTW89_QATAR][0][8] = 6,
+ [0][1][2][1][RTW89_UK][1][8] = 42,
+ [0][1][2][1][RTW89_UK][0][8] = 6,
+ [0][1][2][1][RTW89_FCC][1][10] = -4,
+ [0][1][2][1][RTW89_FCC][2][10] = 54,
+ [0][1][2][1][RTW89_ETSI][1][10] = 42,
+ [0][1][2][1][RTW89_ETSI][0][10] = 6,
+ [0][1][2][1][RTW89_MKK][1][10] = 54,
+ [0][1][2][1][RTW89_MKK][0][10] = 16,
+ [0][1][2][1][RTW89_IC][1][10] = -4,
+ [0][1][2][1][RTW89_KCC][1][10] = 12,
+ [0][1][2][1][RTW89_KCC][0][10] = 12,
+ [0][1][2][1][RTW89_ACMA][1][10] = 42,
+ [0][1][2][1][RTW89_ACMA][0][10] = 6,
+ [0][1][2][1][RTW89_CHILE][1][10] = -4,
+ [0][1][2][1][RTW89_QATAR][1][10] = 42,
+ [0][1][2][1][RTW89_QATAR][0][10] = 6,
+ [0][1][2][1][RTW89_UK][1][10] = 42,
+ [0][1][2][1][RTW89_UK][0][10] = 6,
+ [0][1][2][1][RTW89_FCC][1][12] = -4,
+ [0][1][2][1][RTW89_FCC][2][12] = 54,
+ [0][1][2][1][RTW89_ETSI][1][12] = 42,
+ [0][1][2][1][RTW89_ETSI][0][12] = 6,
+ [0][1][2][1][RTW89_MKK][1][12] = 54,
+ [0][1][2][1][RTW89_MKK][0][12] = 16,
+ [0][1][2][1][RTW89_IC][1][12] = -4,
+ [0][1][2][1][RTW89_KCC][1][12] = 12,
+ [0][1][2][1][RTW89_KCC][0][12] = 12,
+ [0][1][2][1][RTW89_ACMA][1][12] = 42,
+ [0][1][2][1][RTW89_ACMA][0][12] = 6,
+ [0][1][2][1][RTW89_CHILE][1][12] = -4,
+ [0][1][2][1][RTW89_QATAR][1][12] = 42,
+ [0][1][2][1][RTW89_QATAR][0][12] = 6,
+ [0][1][2][1][RTW89_UK][1][12] = 42,
+ [0][1][2][1][RTW89_UK][0][12] = 6,
+ [0][1][2][1][RTW89_FCC][1][14] = -4,
+ [0][1][2][1][RTW89_FCC][2][14] = 54,
+ [0][1][2][1][RTW89_ETSI][1][14] = 42,
+ [0][1][2][1][RTW89_ETSI][0][14] = 6,
+ [0][1][2][1][RTW89_MKK][1][14] = 54,
+ [0][1][2][1][RTW89_MKK][0][14] = 16,
+ [0][1][2][1][RTW89_IC][1][14] = -4,
+ [0][1][2][1][RTW89_KCC][1][14] = 12,
+ [0][1][2][1][RTW89_KCC][0][14] = 12,
+ [0][1][2][1][RTW89_ACMA][1][14] = 42,
+ [0][1][2][1][RTW89_ACMA][0][14] = 6,
+ [0][1][2][1][RTW89_CHILE][1][14] = -4,
+ [0][1][2][1][RTW89_QATAR][1][14] = 42,
+ [0][1][2][1][RTW89_QATAR][0][14] = 6,
+ [0][1][2][1][RTW89_UK][1][14] = 42,
+ [0][1][2][1][RTW89_UK][0][14] = 6,
+ [0][1][2][1][RTW89_FCC][1][15] = -4,
+ [0][1][2][1][RTW89_FCC][2][15] = 54,
+ [0][1][2][1][RTW89_ETSI][1][15] = 42,
+ [0][1][2][1][RTW89_ETSI][0][15] = 6,
+ [0][1][2][1][RTW89_MKK][1][15] = 54,
+ [0][1][2][1][RTW89_MKK][0][15] = 16,
+ [0][1][2][1][RTW89_IC][1][15] = -4,
+ [0][1][2][1][RTW89_KCC][1][15] = 12,
+ [0][1][2][1][RTW89_KCC][0][15] = 12,
+ [0][1][2][1][RTW89_ACMA][1][15] = 42,
+ [0][1][2][1][RTW89_ACMA][0][15] = 6,
+ [0][1][2][1][RTW89_CHILE][1][15] = -4,
+ [0][1][2][1][RTW89_QATAR][1][15] = 42,
+ [0][1][2][1][RTW89_QATAR][0][15] = 6,
+ [0][1][2][1][RTW89_UK][1][15] = 42,
+ [0][1][2][1][RTW89_UK][0][15] = 6,
+ [0][1][2][1][RTW89_FCC][1][17] = -4,
+ [0][1][2][1][RTW89_FCC][2][17] = 54,
+ [0][1][2][1][RTW89_ETSI][1][17] = 42,
+ [0][1][2][1][RTW89_ETSI][0][17] = 6,
+ [0][1][2][1][RTW89_MKK][1][17] = 54,
+ [0][1][2][1][RTW89_MKK][0][17] = 16,
+ [0][1][2][1][RTW89_IC][1][17] = -4,
+ [0][1][2][1][RTW89_KCC][1][17] = 12,
+ [0][1][2][1][RTW89_KCC][0][17] = 12,
+ [0][1][2][1][RTW89_ACMA][1][17] = 42,
+ [0][1][2][1][RTW89_ACMA][0][17] = 6,
+ [0][1][2][1][RTW89_CHILE][1][17] = -4,
+ [0][1][2][1][RTW89_QATAR][1][17] = 42,
+ [0][1][2][1][RTW89_QATAR][0][17] = 6,
+ [0][1][2][1][RTW89_UK][1][17] = 42,
+ [0][1][2][1][RTW89_UK][0][17] = 6,
+ [0][1][2][1][RTW89_FCC][1][19] = -4,
+ [0][1][2][1][RTW89_FCC][2][19] = 54,
+ [0][1][2][1][RTW89_ETSI][1][19] = 42,
+ [0][1][2][1][RTW89_ETSI][0][19] = 6,
+ [0][1][2][1][RTW89_MKK][1][19] = 54,
+ [0][1][2][1][RTW89_MKK][0][19] = 16,
+ [0][1][2][1][RTW89_IC][1][19] = -4,
+ [0][1][2][1][RTW89_KCC][1][19] = 12,
+ [0][1][2][1][RTW89_KCC][0][19] = 12,
+ [0][1][2][1][RTW89_ACMA][1][19] = 42,
+ [0][1][2][1][RTW89_ACMA][0][19] = 6,
+ [0][1][2][1][RTW89_CHILE][1][19] = -4,
+ [0][1][2][1][RTW89_QATAR][1][19] = 42,
+ [0][1][2][1][RTW89_QATAR][0][19] = 6,
+ [0][1][2][1][RTW89_UK][1][19] = 42,
+ [0][1][2][1][RTW89_UK][0][19] = 6,
+ [0][1][2][1][RTW89_FCC][1][21] = -4,
+ [0][1][2][1][RTW89_FCC][2][21] = 54,
+ [0][1][2][1][RTW89_ETSI][1][21] = 42,
+ [0][1][2][1][RTW89_ETSI][0][21] = 6,
+ [0][1][2][1][RTW89_MKK][1][21] = 54,
+ [0][1][2][1][RTW89_MKK][0][21] = 16,
+ [0][1][2][1][RTW89_IC][1][21] = -4,
+ [0][1][2][1][RTW89_KCC][1][21] = 12,
+ [0][1][2][1][RTW89_KCC][0][21] = 12,
+ [0][1][2][1][RTW89_ACMA][1][21] = 42,
+ [0][1][2][1][RTW89_ACMA][0][21] = 6,
+ [0][1][2][1][RTW89_CHILE][1][21] = -4,
+ [0][1][2][1][RTW89_QATAR][1][21] = 42,
+ [0][1][2][1][RTW89_QATAR][0][21] = 6,
+ [0][1][2][1][RTW89_UK][1][21] = 42,
+ [0][1][2][1][RTW89_UK][0][21] = 6,
+ [0][1][2][1][RTW89_FCC][1][23] = -4,
+ [0][1][2][1][RTW89_FCC][2][23] = 68,
+ [0][1][2][1][RTW89_ETSI][1][23] = 42,
+ [0][1][2][1][RTW89_ETSI][0][23] = 6,
+ [0][1][2][1][RTW89_MKK][1][23] = 54,
+ [0][1][2][1][RTW89_MKK][0][23] = 16,
+ [0][1][2][1][RTW89_IC][1][23] = -4,
+ [0][1][2][1][RTW89_KCC][1][23] = 12,
+ [0][1][2][1][RTW89_KCC][0][23] = 10,
+ [0][1][2][1][RTW89_ACMA][1][23] = 42,
+ [0][1][2][1][RTW89_ACMA][0][23] = 6,
+ [0][1][2][1][RTW89_CHILE][1][23] = -4,
+ [0][1][2][1][RTW89_QATAR][1][23] = 42,
+ [0][1][2][1][RTW89_QATAR][0][23] = 6,
+ [0][1][2][1][RTW89_UK][1][23] = 42,
+ [0][1][2][1][RTW89_UK][0][23] = 6,
+ [0][1][2][1][RTW89_FCC][1][25] = -4,
+ [0][1][2][1][RTW89_FCC][2][25] = 68,
+ [0][1][2][1][RTW89_ETSI][1][25] = 42,
+ [0][1][2][1][RTW89_ETSI][0][25] = 6,
+ [0][1][2][1][RTW89_MKK][1][25] = 54,
+ [0][1][2][1][RTW89_MKK][0][25] = 16,
+ [0][1][2][1][RTW89_IC][1][25] = -4,
+ [0][1][2][1][RTW89_KCC][1][25] = 12,
+ [0][1][2][1][RTW89_KCC][0][25] = 14,
+ [0][1][2][1][RTW89_ACMA][1][25] = 42,
+ [0][1][2][1][RTW89_ACMA][0][25] = 6,
+ [0][1][2][1][RTW89_CHILE][1][25] = -4,
+ [0][1][2][1][RTW89_QATAR][1][25] = 42,
+ [0][1][2][1][RTW89_QATAR][0][25] = 6,
+ [0][1][2][1][RTW89_UK][1][25] = 42,
+ [0][1][2][1][RTW89_UK][0][25] = 6,
+ [0][1][2][1][RTW89_FCC][1][27] = -4,
+ [0][1][2][1][RTW89_FCC][2][27] = 68,
+ [0][1][2][1][RTW89_ETSI][1][27] = 42,
+ [0][1][2][1][RTW89_ETSI][0][27] = 6,
+ [0][1][2][1][RTW89_MKK][1][27] = 54,
+ [0][1][2][1][RTW89_MKK][0][27] = 16,
+ [0][1][2][1][RTW89_IC][1][27] = -4,
+ [0][1][2][1][RTW89_KCC][1][27] = 12,
+ [0][1][2][1][RTW89_KCC][0][27] = 14,
+ [0][1][2][1][RTW89_ACMA][1][27] = 42,
+ [0][1][2][1][RTW89_ACMA][0][27] = 6,
+ [0][1][2][1][RTW89_CHILE][1][27] = -4,
+ [0][1][2][1][RTW89_QATAR][1][27] = 42,
+ [0][1][2][1][RTW89_QATAR][0][27] = 6,
+ [0][1][2][1][RTW89_UK][1][27] = 42,
+ [0][1][2][1][RTW89_UK][0][27] = 6,
+ [0][1][2][1][RTW89_FCC][1][29] = -4,
+ [0][1][2][1][RTW89_FCC][2][29] = 68,
+ [0][1][2][1][RTW89_ETSI][1][29] = 42,
+ [0][1][2][1][RTW89_ETSI][0][29] = 6,
+ [0][1][2][1][RTW89_MKK][1][29] = 54,
+ [0][1][2][1][RTW89_MKK][0][29] = 16,
+ [0][1][2][1][RTW89_IC][1][29] = -4,
+ [0][1][2][1][RTW89_KCC][1][29] = 12,
+ [0][1][2][1][RTW89_KCC][0][29] = 14,
+ [0][1][2][1][RTW89_ACMA][1][29] = 42,
+ [0][1][2][1][RTW89_ACMA][0][29] = 6,
+ [0][1][2][1][RTW89_CHILE][1][29] = -4,
+ [0][1][2][1][RTW89_QATAR][1][29] = 42,
+ [0][1][2][1][RTW89_QATAR][0][29] = 6,
+ [0][1][2][1][RTW89_UK][1][29] = 42,
+ [0][1][2][1][RTW89_UK][0][29] = 6,
+ [0][1][2][1][RTW89_FCC][1][30] = -4,
+ [0][1][2][1][RTW89_FCC][2][30] = 68,
+ [0][1][2][1][RTW89_ETSI][1][30] = 42,
+ [0][1][2][1][RTW89_ETSI][0][30] = 6,
+ [0][1][2][1][RTW89_MKK][1][30] = 54,
+ [0][1][2][1][RTW89_MKK][0][30] = 16,
+ [0][1][2][1][RTW89_IC][1][30] = -4,
+ [0][1][2][1][RTW89_KCC][1][30] = 12,
+ [0][1][2][1][RTW89_KCC][0][30] = 14,
+ [0][1][2][1][RTW89_ACMA][1][30] = 42,
+ [0][1][2][1][RTW89_ACMA][0][30] = 6,
+ [0][1][2][1][RTW89_CHILE][1][30] = -4,
+ [0][1][2][1][RTW89_QATAR][1][30] = 42,
+ [0][1][2][1][RTW89_QATAR][0][30] = 6,
+ [0][1][2][1][RTW89_UK][1][30] = 42,
+ [0][1][2][1][RTW89_UK][0][30] = 6,
+ [0][1][2][1][RTW89_FCC][1][32] = -4,
+ [0][1][2][1][RTW89_FCC][2][32] = 68,
+ [0][1][2][1][RTW89_ETSI][1][32] = 42,
+ [0][1][2][1][RTW89_ETSI][0][32] = 6,
+ [0][1][2][1][RTW89_MKK][1][32] = 54,
+ [0][1][2][1][RTW89_MKK][0][32] = 16,
+ [0][1][2][1][RTW89_IC][1][32] = -4,
+ [0][1][2][1][RTW89_KCC][1][32] = 12,
+ [0][1][2][1][RTW89_KCC][0][32] = 14,
+ [0][1][2][1][RTW89_ACMA][1][32] = 42,
+ [0][1][2][1][RTW89_ACMA][0][32] = 6,
+ [0][1][2][1][RTW89_CHILE][1][32] = -4,
+ [0][1][2][1][RTW89_QATAR][1][32] = 42,
+ [0][1][2][1][RTW89_QATAR][0][32] = 6,
+ [0][1][2][1][RTW89_UK][1][32] = 42,
+ [0][1][2][1][RTW89_UK][0][32] = 6,
+ [0][1][2][1][RTW89_FCC][1][34] = -4,
+ [0][1][2][1][RTW89_FCC][2][34] = 68,
+ [0][1][2][1][RTW89_ETSI][1][34] = 42,
+ [0][1][2][1][RTW89_ETSI][0][34] = 6,
+ [0][1][2][1][RTW89_MKK][1][34] = 54,
+ [0][1][2][1][RTW89_MKK][0][34] = 16,
+ [0][1][2][1][RTW89_IC][1][34] = -4,
+ [0][1][2][1][RTW89_KCC][1][34] = 12,
+ [0][1][2][1][RTW89_KCC][0][34] = 14,
+ [0][1][2][1][RTW89_ACMA][1][34] = 42,
+ [0][1][2][1][RTW89_ACMA][0][34] = 6,
+ [0][1][2][1][RTW89_CHILE][1][34] = -4,
+ [0][1][2][1][RTW89_QATAR][1][34] = 42,
+ [0][1][2][1][RTW89_QATAR][0][34] = 6,
+ [0][1][2][1][RTW89_UK][1][34] = 42,
+ [0][1][2][1][RTW89_UK][0][34] = 6,
+ [0][1][2][1][RTW89_FCC][1][36] = -4,
+ [0][1][2][1][RTW89_FCC][2][36] = 68,
+ [0][1][2][1][RTW89_ETSI][1][36] = 42,
+ [0][1][2][1][RTW89_ETSI][0][36] = 6,
+ [0][1][2][1][RTW89_MKK][1][36] = 54,
+ [0][1][2][1][RTW89_MKK][0][36] = 16,
+ [0][1][2][1][RTW89_IC][1][36] = -4,
+ [0][1][2][1][RTW89_KCC][1][36] = 12,
+ [0][1][2][1][RTW89_KCC][0][36] = 14,
+ [0][1][2][1][RTW89_ACMA][1][36] = 42,
+ [0][1][2][1][RTW89_ACMA][0][36] = 6,
+ [0][1][2][1][RTW89_CHILE][1][36] = -4,
+ [0][1][2][1][RTW89_QATAR][1][36] = 42,
+ [0][1][2][1][RTW89_QATAR][0][36] = 6,
+ [0][1][2][1][RTW89_UK][1][36] = 42,
+ [0][1][2][1][RTW89_UK][0][36] = 6,
+ [0][1][2][1][RTW89_FCC][1][38] = -4,
+ [0][1][2][1][RTW89_FCC][2][38] = 68,
+ [0][1][2][1][RTW89_ETSI][1][38] = 42,
+ [0][1][2][1][RTW89_ETSI][0][38] = 6,
+ [0][1][2][1][RTW89_MKK][1][38] = 54,
+ [0][1][2][1][RTW89_MKK][0][38] = 16,
+ [0][1][2][1][RTW89_IC][1][38] = -4,
+ [0][1][2][1][RTW89_KCC][1][38] = 12,
+ [0][1][2][1][RTW89_KCC][0][38] = 14,
+ [0][1][2][1][RTW89_ACMA][1][38] = 42,
+ [0][1][2][1][RTW89_ACMA][0][38] = 6,
+ [0][1][2][1][RTW89_CHILE][1][38] = -4,
+ [0][1][2][1][RTW89_QATAR][1][38] = 42,
+ [0][1][2][1][RTW89_QATAR][0][38] = 6,
+ [0][1][2][1][RTW89_UK][1][38] = 42,
+ [0][1][2][1][RTW89_UK][0][38] = 6,
+ [0][1][2][1][RTW89_FCC][1][40] = -4,
+ [0][1][2][1][RTW89_FCC][2][40] = 68,
+ [0][1][2][1][RTW89_ETSI][1][40] = 42,
+ [0][1][2][1][RTW89_ETSI][0][40] = 6,
+ [0][1][2][1][RTW89_MKK][1][40] = 54,
+ [0][1][2][1][RTW89_MKK][0][40] = 16,
+ [0][1][2][1][RTW89_IC][1][40] = -4,
+ [0][1][2][1][RTW89_KCC][1][40] = 12,
+ [0][1][2][1][RTW89_KCC][0][40] = 14,
+ [0][1][2][1][RTW89_ACMA][1][40] = 42,
+ [0][1][2][1][RTW89_ACMA][0][40] = 6,
+ [0][1][2][1][RTW89_CHILE][1][40] = -4,
+ [0][1][2][1][RTW89_QATAR][1][40] = 42,
+ [0][1][2][1][RTW89_QATAR][0][40] = 6,
+ [0][1][2][1][RTW89_UK][1][40] = 42,
+ [0][1][2][1][RTW89_UK][0][40] = 6,
+ [0][1][2][1][RTW89_FCC][1][42] = -4,
+ [0][1][2][1][RTW89_FCC][2][42] = 68,
+ [0][1][2][1][RTW89_ETSI][1][42] = 42,
+ [0][1][2][1][RTW89_ETSI][0][42] = 6,
+ [0][1][2][1][RTW89_MKK][1][42] = 54,
+ [0][1][2][1][RTW89_MKK][0][42] = 16,
+ [0][1][2][1][RTW89_IC][1][42] = -4,
+ [0][1][2][1][RTW89_KCC][1][42] = 12,
+ [0][1][2][1][RTW89_KCC][0][42] = 14,
+ [0][1][2][1][RTW89_ACMA][1][42] = 42,
+ [0][1][2][1][RTW89_ACMA][0][42] = 6,
+ [0][1][2][1][RTW89_CHILE][1][42] = -4,
+ [0][1][2][1][RTW89_QATAR][1][42] = 42,
+ [0][1][2][1][RTW89_QATAR][0][42] = 6,
+ [0][1][2][1][RTW89_UK][1][42] = 42,
+ [0][1][2][1][RTW89_UK][0][42] = 6,
+ [0][1][2][1][RTW89_FCC][1][44] = -2,
+ [0][1][2][1][RTW89_FCC][2][44] = 68,
+ [0][1][2][1][RTW89_ETSI][1][44] = 42,
+ [0][1][2][1][RTW89_ETSI][0][44] = 6,
+ [0][1][2][1][RTW89_MKK][1][44] = 34,
+ [0][1][2][1][RTW89_MKK][0][44] = 16,
+ [0][1][2][1][RTW89_IC][1][44] = -2,
+ [0][1][2][1][RTW89_KCC][1][44] = 12,
+ [0][1][2][1][RTW89_KCC][0][44] = 12,
+ [0][1][2][1][RTW89_ACMA][1][44] = 42,
+ [0][1][2][1][RTW89_ACMA][0][44] = 6,
+ [0][1][2][1][RTW89_CHILE][1][44] = -2,
+ [0][1][2][1][RTW89_QATAR][1][44] = 42,
+ [0][1][2][1][RTW89_QATAR][0][44] = 6,
+ [0][1][2][1][RTW89_UK][1][44] = 42,
+ [0][1][2][1][RTW89_UK][0][44] = 6,
+ [0][1][2][1][RTW89_FCC][1][45] = -2,
+ [0][1][2][1][RTW89_FCC][2][45] = 127,
+ [0][1][2][1][RTW89_ETSI][1][45] = 127,
+ [0][1][2][1][RTW89_ETSI][0][45] = 127,
+ [0][1][2][1][RTW89_MKK][1][45] = 127,
+ [0][1][2][1][RTW89_MKK][0][45] = 127,
+ [0][1][2][1][RTW89_IC][1][45] = -2,
+ [0][1][2][1][RTW89_KCC][1][45] = 12,
+ [0][1][2][1][RTW89_KCC][0][45] = 127,
+ [0][1][2][1][RTW89_ACMA][1][45] = 127,
+ [0][1][2][1][RTW89_ACMA][0][45] = 127,
+ [0][1][2][1][RTW89_CHILE][1][45] = -2,
+ [0][1][2][1][RTW89_QATAR][1][45] = 127,
+ [0][1][2][1][RTW89_QATAR][0][45] = 127,
+ [0][1][2][1][RTW89_UK][1][45] = 127,
+ [0][1][2][1][RTW89_UK][0][45] = 127,
+ [0][1][2][1][RTW89_FCC][1][47] = -2,
+ [0][1][2][1][RTW89_FCC][2][47] = 127,
+ [0][1][2][1][RTW89_ETSI][1][47] = 127,
+ [0][1][2][1][RTW89_ETSI][0][47] = 127,
+ [0][1][2][1][RTW89_MKK][1][47] = 127,
+ [0][1][2][1][RTW89_MKK][0][47] = 127,
+ [0][1][2][1][RTW89_IC][1][47] = -2,
+ [0][1][2][1][RTW89_KCC][1][47] = 12,
+ [0][1][2][1][RTW89_KCC][0][47] = 127,
+ [0][1][2][1][RTW89_ACMA][1][47] = 127,
+ [0][1][2][1][RTW89_ACMA][0][47] = 127,
+ [0][1][2][1][RTW89_CHILE][1][47] = -2,
+ [0][1][2][1][RTW89_QATAR][1][47] = 127,
+ [0][1][2][1][RTW89_QATAR][0][47] = 127,
+ [0][1][2][1][RTW89_UK][1][47] = 127,
+ [0][1][2][1][RTW89_UK][0][47] = 127,
+ [0][1][2][1][RTW89_FCC][1][49] = -2,
+ [0][1][2][1][RTW89_FCC][2][49] = 127,
+ [0][1][2][1][RTW89_ETSI][1][49] = 127,
+ [0][1][2][1][RTW89_ETSI][0][49] = 127,
+ [0][1][2][1][RTW89_MKK][1][49] = 127,
+ [0][1][2][1][RTW89_MKK][0][49] = 127,
+ [0][1][2][1][RTW89_IC][1][49] = -2,
+ [0][1][2][1][RTW89_KCC][1][49] = 12,
+ [0][1][2][1][RTW89_KCC][0][49] = 127,
+ [0][1][2][1][RTW89_ACMA][1][49] = 127,
+ [0][1][2][1][RTW89_ACMA][0][49] = 127,
+ [0][1][2][1][RTW89_CHILE][1][49] = -2,
+ [0][1][2][1][RTW89_QATAR][1][49] = 127,
+ [0][1][2][1][RTW89_QATAR][0][49] = 127,
+ [0][1][2][1][RTW89_UK][1][49] = 127,
+ [0][1][2][1][RTW89_UK][0][49] = 127,
+ [0][1][2][1][RTW89_FCC][1][51] = -2,
+ [0][1][2][1][RTW89_FCC][2][51] = 127,
+ [0][1][2][1][RTW89_ETSI][1][51] = 127,
+ [0][1][2][1][RTW89_ETSI][0][51] = 127,
+ [0][1][2][1][RTW89_MKK][1][51] = 127,
+ [0][1][2][1][RTW89_MKK][0][51] = 127,
+ [0][1][2][1][RTW89_IC][1][51] = -2,
+ [0][1][2][1][RTW89_KCC][1][51] = 12,
+ [0][1][2][1][RTW89_KCC][0][51] = 127,
+ [0][1][2][1][RTW89_ACMA][1][51] = 127,
+ [0][1][2][1][RTW89_ACMA][0][51] = 127,
+ [0][1][2][1][RTW89_CHILE][1][51] = -2,
+ [0][1][2][1][RTW89_QATAR][1][51] = 127,
+ [0][1][2][1][RTW89_QATAR][0][51] = 127,
+ [0][1][2][1][RTW89_UK][1][51] = 127,
+ [0][1][2][1][RTW89_UK][0][51] = 127,
+ [0][1][2][1][RTW89_FCC][1][53] = -2,
+ [0][1][2][1][RTW89_FCC][2][53] = 127,
+ [0][1][2][1][RTW89_ETSI][1][53] = 127,
+ [0][1][2][1][RTW89_ETSI][0][53] = 127,
+ [0][1][2][1][RTW89_MKK][1][53] = 127,
+ [0][1][2][1][RTW89_MKK][0][53] = 127,
+ [0][1][2][1][RTW89_IC][1][53] = -2,
+ [0][1][2][1][RTW89_KCC][1][53] = 12,
+ [0][1][2][1][RTW89_KCC][0][53] = 127,
+ [0][1][2][1][RTW89_ACMA][1][53] = 127,
+ [0][1][2][1][RTW89_ACMA][0][53] = 127,
+ [0][1][2][1][RTW89_CHILE][1][53] = -2,
+ [0][1][2][1][RTW89_QATAR][1][53] = 127,
+ [0][1][2][1][RTW89_QATAR][0][53] = 127,
+ [0][1][2][1][RTW89_UK][1][53] = 127,
+ [0][1][2][1][RTW89_UK][0][53] = 127,
+ [0][1][2][1][RTW89_FCC][1][55] = -2,
+ [0][1][2][1][RTW89_FCC][2][55] = 68,
+ [0][1][2][1][RTW89_ETSI][1][55] = 127,
+ [0][1][2][1][RTW89_ETSI][0][55] = 127,
+ [0][1][2][1][RTW89_MKK][1][55] = 127,
+ [0][1][2][1][RTW89_MKK][0][55] = 127,
+ [0][1][2][1][RTW89_IC][1][55] = -2,
+ [0][1][2][1][RTW89_KCC][1][55] = 12,
+ [0][1][2][1][RTW89_KCC][0][55] = 127,
+ [0][1][2][1][RTW89_ACMA][1][55] = 127,
+ [0][1][2][1][RTW89_ACMA][0][55] = 127,
+ [0][1][2][1][RTW89_CHILE][1][55] = -2,
+ [0][1][2][1][RTW89_QATAR][1][55] = 127,
+ [0][1][2][1][RTW89_QATAR][0][55] = 127,
+ [0][1][2][1][RTW89_UK][1][55] = 127,
+ [0][1][2][1][RTW89_UK][0][55] = 127,
+ [0][1][2][1][RTW89_FCC][1][57] = -2,
+ [0][1][2][1][RTW89_FCC][2][57] = 68,
+ [0][1][2][1][RTW89_ETSI][1][57] = 127,
+ [0][1][2][1][RTW89_ETSI][0][57] = 127,
+ [0][1][2][1][RTW89_MKK][1][57] = 127,
+ [0][1][2][1][RTW89_MKK][0][57] = 127,
+ [0][1][2][1][RTW89_IC][1][57] = -2,
+ [0][1][2][1][RTW89_KCC][1][57] = 12,
+ [0][1][2][1][RTW89_KCC][0][57] = 127,
+ [0][1][2][1][RTW89_ACMA][1][57] = 127,
+ [0][1][2][1][RTW89_ACMA][0][57] = 127,
+ [0][1][2][1][RTW89_CHILE][1][57] = -2,
+ [0][1][2][1][RTW89_QATAR][1][57] = 127,
+ [0][1][2][1][RTW89_QATAR][0][57] = 127,
+ [0][1][2][1][RTW89_UK][1][57] = 127,
+ [0][1][2][1][RTW89_UK][0][57] = 127,
+ [0][1][2][1][RTW89_FCC][1][59] = -2,
+ [0][1][2][1][RTW89_FCC][2][59] = 68,
+ [0][1][2][1][RTW89_ETSI][1][59] = 127,
+ [0][1][2][1][RTW89_ETSI][0][59] = 127,
+ [0][1][2][1][RTW89_MKK][1][59] = 127,
+ [0][1][2][1][RTW89_MKK][0][59] = 127,
+ [0][1][2][1][RTW89_IC][1][59] = -2,
+ [0][1][2][1][RTW89_KCC][1][59] = 12,
+ [0][1][2][1][RTW89_KCC][0][59] = 127,
+ [0][1][2][1][RTW89_ACMA][1][59] = 127,
+ [0][1][2][1][RTW89_ACMA][0][59] = 127,
+ [0][1][2][1][RTW89_CHILE][1][59] = -2,
+ [0][1][2][1][RTW89_QATAR][1][59] = 127,
+ [0][1][2][1][RTW89_QATAR][0][59] = 127,
+ [0][1][2][1][RTW89_UK][1][59] = 127,
+ [0][1][2][1][RTW89_UK][0][59] = 127,
+ [0][1][2][1][RTW89_FCC][1][60] = -2,
+ [0][1][2][1][RTW89_FCC][2][60] = 68,
+ [0][1][2][1][RTW89_ETSI][1][60] = 127,
+ [0][1][2][1][RTW89_ETSI][0][60] = 127,
+ [0][1][2][1][RTW89_MKK][1][60] = 127,
+ [0][1][2][1][RTW89_MKK][0][60] = 127,
+ [0][1][2][1][RTW89_IC][1][60] = -2,
+ [0][1][2][1][RTW89_KCC][1][60] = 12,
+ [0][1][2][1][RTW89_KCC][0][60] = 127,
+ [0][1][2][1][RTW89_ACMA][1][60] = 127,
+ [0][1][2][1][RTW89_ACMA][0][60] = 127,
+ [0][1][2][1][RTW89_CHILE][1][60] = -2,
+ [0][1][2][1][RTW89_QATAR][1][60] = 127,
+ [0][1][2][1][RTW89_QATAR][0][60] = 127,
+ [0][1][2][1][RTW89_UK][1][60] = 127,
+ [0][1][2][1][RTW89_UK][0][60] = 127,
+ [0][1][2][1][RTW89_FCC][1][62] = -2,
+ [0][1][2][1][RTW89_FCC][2][62] = 68,
+ [0][1][2][1][RTW89_ETSI][1][62] = 127,
+ [0][1][2][1][RTW89_ETSI][0][62] = 127,
+ [0][1][2][1][RTW89_MKK][1][62] = 127,
+ [0][1][2][1][RTW89_MKK][0][62] = 127,
+ [0][1][2][1][RTW89_IC][1][62] = -2,
+ [0][1][2][1][RTW89_KCC][1][62] = 12,
+ [0][1][2][1][RTW89_KCC][0][62] = 127,
+ [0][1][2][1][RTW89_ACMA][1][62] = 127,
+ [0][1][2][1][RTW89_ACMA][0][62] = 127,
+ [0][1][2][1][RTW89_CHILE][1][62] = -2,
+ [0][1][2][1][RTW89_QATAR][1][62] = 127,
+ [0][1][2][1][RTW89_QATAR][0][62] = 127,
+ [0][1][2][1][RTW89_UK][1][62] = 127,
+ [0][1][2][1][RTW89_UK][0][62] = 127,
+ [0][1][2][1][RTW89_FCC][1][64] = -2,
+ [0][1][2][1][RTW89_FCC][2][64] = 68,
+ [0][1][2][1][RTW89_ETSI][1][64] = 127,
+ [0][1][2][1][RTW89_ETSI][0][64] = 127,
+ [0][1][2][1][RTW89_MKK][1][64] = 127,
+ [0][1][2][1][RTW89_MKK][0][64] = 127,
+ [0][1][2][1][RTW89_IC][1][64] = -2,
+ [0][1][2][1][RTW89_KCC][1][64] = 12,
+ [0][1][2][1][RTW89_KCC][0][64] = 127,
+ [0][1][2][1][RTW89_ACMA][1][64] = 127,
+ [0][1][2][1][RTW89_ACMA][0][64] = 127,
+ [0][1][2][1][RTW89_CHILE][1][64] = -2,
+ [0][1][2][1][RTW89_QATAR][1][64] = 127,
+ [0][1][2][1][RTW89_QATAR][0][64] = 127,
+ [0][1][2][1][RTW89_UK][1][64] = 127,
+ [0][1][2][1][RTW89_UK][0][64] = 127,
+ [0][1][2][1][RTW89_FCC][1][66] = -2,
+ [0][1][2][1][RTW89_FCC][2][66] = 68,
+ [0][1][2][1][RTW89_ETSI][1][66] = 127,
+ [0][1][2][1][RTW89_ETSI][0][66] = 127,
+ [0][1][2][1][RTW89_MKK][1][66] = 127,
+ [0][1][2][1][RTW89_MKK][0][66] = 127,
+ [0][1][2][1][RTW89_IC][1][66] = -2,
+ [0][1][2][1][RTW89_KCC][1][66] = 12,
+ [0][1][2][1][RTW89_KCC][0][66] = 127,
+ [0][1][2][1][RTW89_ACMA][1][66] = 127,
+ [0][1][2][1][RTW89_ACMA][0][66] = 127,
+ [0][1][2][1][RTW89_CHILE][1][66] = -2,
+ [0][1][2][1][RTW89_QATAR][1][66] = 127,
+ [0][1][2][1][RTW89_QATAR][0][66] = 127,
+ [0][1][2][1][RTW89_UK][1][66] = 127,
+ [0][1][2][1][RTW89_UK][0][66] = 127,
+ [0][1][2][1][RTW89_FCC][1][68] = -2,
+ [0][1][2][1][RTW89_FCC][2][68] = 68,
+ [0][1][2][1][RTW89_ETSI][1][68] = 127,
+ [0][1][2][1][RTW89_ETSI][0][68] = 127,
+ [0][1][2][1][RTW89_MKK][1][68] = 127,
+ [0][1][2][1][RTW89_MKK][0][68] = 127,
+ [0][1][2][1][RTW89_IC][1][68] = -2,
+ [0][1][2][1][RTW89_KCC][1][68] = 12,
+ [0][1][2][1][RTW89_KCC][0][68] = 127,
+ [0][1][2][1][RTW89_ACMA][1][68] = 127,
+ [0][1][2][1][RTW89_ACMA][0][68] = 127,
+ [0][1][2][1][RTW89_CHILE][1][68] = -2,
+ [0][1][2][1][RTW89_QATAR][1][68] = 127,
+ [0][1][2][1][RTW89_QATAR][0][68] = 127,
+ [0][1][2][1][RTW89_UK][1][68] = 127,
+ [0][1][2][1][RTW89_UK][0][68] = 127,
+ [0][1][2][1][RTW89_FCC][1][70] = -2,
+ [0][1][2][1][RTW89_FCC][2][70] = 68,
+ [0][1][2][1][RTW89_ETSI][1][70] = 127,
+ [0][1][2][1][RTW89_ETSI][0][70] = 127,
+ [0][1][2][1][RTW89_MKK][1][70] = 127,
+ [0][1][2][1][RTW89_MKK][0][70] = 127,
+ [0][1][2][1][RTW89_IC][1][70] = -2,
+ [0][1][2][1][RTW89_KCC][1][70] = 12,
+ [0][1][2][1][RTW89_KCC][0][70] = 127,
+ [0][1][2][1][RTW89_ACMA][1][70] = 127,
+ [0][1][2][1][RTW89_ACMA][0][70] = 127,
+ [0][1][2][1][RTW89_CHILE][1][70] = -2,
+ [0][1][2][1][RTW89_QATAR][1][70] = 127,
+ [0][1][2][1][RTW89_QATAR][0][70] = 127,
+ [0][1][2][1][RTW89_UK][1][70] = 127,
+ [0][1][2][1][RTW89_UK][0][70] = 127,
+ [0][1][2][1][RTW89_FCC][1][72] = -2,
+ [0][1][2][1][RTW89_FCC][2][72] = 68,
+ [0][1][2][1][RTW89_ETSI][1][72] = 127,
+ [0][1][2][1][RTW89_ETSI][0][72] = 127,
+ [0][1][2][1][RTW89_MKK][1][72] = 127,
+ [0][1][2][1][RTW89_MKK][0][72] = 127,
+ [0][1][2][1][RTW89_IC][1][72] = -2,
+ [0][1][2][1][RTW89_KCC][1][72] = 12,
+ [0][1][2][1][RTW89_KCC][0][72] = 127,
+ [0][1][2][1][RTW89_ACMA][1][72] = 127,
+ [0][1][2][1][RTW89_ACMA][0][72] = 127,
+ [0][1][2][1][RTW89_CHILE][1][72] = -2,
+ [0][1][2][1][RTW89_QATAR][1][72] = 127,
+ [0][1][2][1][RTW89_QATAR][0][72] = 127,
+ [0][1][2][1][RTW89_UK][1][72] = 127,
+ [0][1][2][1][RTW89_UK][0][72] = 127,
+ [0][1][2][1][RTW89_FCC][1][74] = -2,
+ [0][1][2][1][RTW89_FCC][2][74] = 68,
+ [0][1][2][1][RTW89_ETSI][1][74] = 127,
+ [0][1][2][1][RTW89_ETSI][0][74] = 127,
+ [0][1][2][1][RTW89_MKK][1][74] = 127,
+ [0][1][2][1][RTW89_MKK][0][74] = 127,
+ [0][1][2][1][RTW89_IC][1][74] = -2,
+ [0][1][2][1][RTW89_KCC][1][74] = 12,
+ [0][1][2][1][RTW89_KCC][0][74] = 127,
+ [0][1][2][1][RTW89_ACMA][1][74] = 127,
+ [0][1][2][1][RTW89_ACMA][0][74] = 127,
+ [0][1][2][1][RTW89_CHILE][1][74] = -2,
+ [0][1][2][1][RTW89_QATAR][1][74] = 127,
+ [0][1][2][1][RTW89_QATAR][0][74] = 127,
+ [0][1][2][1][RTW89_UK][1][74] = 127,
+ [0][1][2][1][RTW89_UK][0][74] = 127,
+ [0][1][2][1][RTW89_FCC][1][75] = -2,
+ [0][1][2][1][RTW89_FCC][2][75] = 68,
+ [0][1][2][1][RTW89_ETSI][1][75] = 127,
+ [0][1][2][1][RTW89_ETSI][0][75] = 127,
+ [0][1][2][1][RTW89_MKK][1][75] = 127,
+ [0][1][2][1][RTW89_MKK][0][75] = 127,
+ [0][1][2][1][RTW89_IC][1][75] = -2,
+ [0][1][2][1][RTW89_KCC][1][75] = 12,
+ [0][1][2][1][RTW89_KCC][0][75] = 127,
+ [0][1][2][1][RTW89_ACMA][1][75] = 127,
+ [0][1][2][1][RTW89_ACMA][0][75] = 127,
+ [0][1][2][1][RTW89_CHILE][1][75] = -2,
+ [0][1][2][1][RTW89_QATAR][1][75] = 127,
+ [0][1][2][1][RTW89_QATAR][0][75] = 127,
+ [0][1][2][1][RTW89_UK][1][75] = 127,
+ [0][1][2][1][RTW89_UK][0][75] = 127,
+ [0][1][2][1][RTW89_FCC][1][77] = -2,
+ [0][1][2][1][RTW89_FCC][2][77] = 68,
+ [0][1][2][1][RTW89_ETSI][1][77] = 127,
+ [0][1][2][1][RTW89_ETSI][0][77] = 127,
+ [0][1][2][1][RTW89_MKK][1][77] = 127,
+ [0][1][2][1][RTW89_MKK][0][77] = 127,
+ [0][1][2][1][RTW89_IC][1][77] = -2,
+ [0][1][2][1][RTW89_KCC][1][77] = 12,
+ [0][1][2][1][RTW89_KCC][0][77] = 127,
+ [0][1][2][1][RTW89_ACMA][1][77] = 127,
+ [0][1][2][1][RTW89_ACMA][0][77] = 127,
+ [0][1][2][1][RTW89_CHILE][1][77] = -2,
+ [0][1][2][1][RTW89_QATAR][1][77] = 127,
+ [0][1][2][1][RTW89_QATAR][0][77] = 127,
+ [0][1][2][1][RTW89_UK][1][77] = 127,
+ [0][1][2][1][RTW89_UK][0][77] = 127,
+ [0][1][2][1][RTW89_FCC][1][79] = -2,
+ [0][1][2][1][RTW89_FCC][2][79] = 68,
+ [0][1][2][1][RTW89_ETSI][1][79] = 127,
+ [0][1][2][1][RTW89_ETSI][0][79] = 127,
+ [0][1][2][1][RTW89_MKK][1][79] = 127,
+ [0][1][2][1][RTW89_MKK][0][79] = 127,
+ [0][1][2][1][RTW89_IC][1][79] = -2,
+ [0][1][2][1][RTW89_KCC][1][79] = 12,
+ [0][1][2][1][RTW89_KCC][0][79] = 127,
+ [0][1][2][1][RTW89_ACMA][1][79] = 127,
+ [0][1][2][1][RTW89_ACMA][0][79] = 127,
+ [0][1][2][1][RTW89_CHILE][1][79] = -2,
+ [0][1][2][1][RTW89_QATAR][1][79] = 127,
+ [0][1][2][1][RTW89_QATAR][0][79] = 127,
+ [0][1][2][1][RTW89_UK][1][79] = 127,
+ [0][1][2][1][RTW89_UK][0][79] = 127,
+ [0][1][2][1][RTW89_FCC][1][81] = -2,
+ [0][1][2][1][RTW89_FCC][2][81] = 68,
+ [0][1][2][1][RTW89_ETSI][1][81] = 127,
+ [0][1][2][1][RTW89_ETSI][0][81] = 127,
+ [0][1][2][1][RTW89_MKK][1][81] = 127,
+ [0][1][2][1][RTW89_MKK][0][81] = 127,
+ [0][1][2][1][RTW89_IC][1][81] = -2,
+ [0][1][2][1][RTW89_KCC][1][81] = 12,
+ [0][1][2][1][RTW89_KCC][0][81] = 127,
+ [0][1][2][1][RTW89_ACMA][1][81] = 127,
+ [0][1][2][1][RTW89_ACMA][0][81] = 127,
+ [0][1][2][1][RTW89_CHILE][1][81] = -2,
+ [0][1][2][1][RTW89_QATAR][1][81] = 127,
+ [0][1][2][1][RTW89_QATAR][0][81] = 127,
+ [0][1][2][1][RTW89_UK][1][81] = 127,
+ [0][1][2][1][RTW89_UK][0][81] = 127,
+ [0][1][2][1][RTW89_FCC][1][83] = -2,
+ [0][1][2][1][RTW89_FCC][2][83] = 68,
+ [0][1][2][1][RTW89_ETSI][1][83] = 127,
+ [0][1][2][1][RTW89_ETSI][0][83] = 127,
+ [0][1][2][1][RTW89_MKK][1][83] = 127,
+ [0][1][2][1][RTW89_MKK][0][83] = 127,
+ [0][1][2][1][RTW89_IC][1][83] = -2,
+ [0][1][2][1][RTW89_KCC][1][83] = 20,
+ [0][1][2][1][RTW89_KCC][0][83] = 127,
+ [0][1][2][1][RTW89_ACMA][1][83] = 127,
+ [0][1][2][1][RTW89_ACMA][0][83] = 127,
+ [0][1][2][1][RTW89_CHILE][1][83] = -2,
+ [0][1][2][1][RTW89_QATAR][1][83] = 127,
+ [0][1][2][1][RTW89_QATAR][0][83] = 127,
+ [0][1][2][1][RTW89_UK][1][83] = 127,
+ [0][1][2][1][RTW89_UK][0][83] = 127,
+ [0][1][2][1][RTW89_FCC][1][85] = -2,
+ [0][1][2][1][RTW89_FCC][2][85] = 68,
+ [0][1][2][1][RTW89_ETSI][1][85] = 127,
+ [0][1][2][1][RTW89_ETSI][0][85] = 127,
+ [0][1][2][1][RTW89_MKK][1][85] = 127,
+ [0][1][2][1][RTW89_MKK][0][85] = 127,
+ [0][1][2][1][RTW89_IC][1][85] = -2,
+ [0][1][2][1][RTW89_KCC][1][85] = 20,
+ [0][1][2][1][RTW89_KCC][0][85] = 127,
+ [0][1][2][1][RTW89_ACMA][1][85] = 127,
+ [0][1][2][1][RTW89_ACMA][0][85] = 127,
+ [0][1][2][1][RTW89_CHILE][1][85] = -2,
+ [0][1][2][1][RTW89_QATAR][1][85] = 127,
+ [0][1][2][1][RTW89_QATAR][0][85] = 127,
+ [0][1][2][1][RTW89_UK][1][85] = 127,
+ [0][1][2][1][RTW89_UK][0][85] = 127,
+ [0][1][2][1][RTW89_FCC][1][87] = -2,
+ [0][1][2][1][RTW89_FCC][2][87] = 127,
+ [0][1][2][1][RTW89_ETSI][1][87] = 127,
+ [0][1][2][1][RTW89_ETSI][0][87] = 127,
+ [0][1][2][1][RTW89_MKK][1][87] = 127,
+ [0][1][2][1][RTW89_MKK][0][87] = 127,
+ [0][1][2][1][RTW89_IC][1][87] = -2,
+ [0][1][2][1][RTW89_KCC][1][87] = 20,
+ [0][1][2][1][RTW89_KCC][0][87] = 127,
+ [0][1][2][1][RTW89_ACMA][1][87] = 127,
+ [0][1][2][1][RTW89_ACMA][0][87] = 127,
+ [0][1][2][1][RTW89_CHILE][1][87] = -2,
+ [0][1][2][1][RTW89_QATAR][1][87] = 127,
+ [0][1][2][1][RTW89_QATAR][0][87] = 127,
+ [0][1][2][1][RTW89_UK][1][87] = 127,
+ [0][1][2][1][RTW89_UK][0][87] = 127,
+ [0][1][2][1][RTW89_FCC][1][89] = -2,
+ [0][1][2][1][RTW89_FCC][2][89] = 127,
+ [0][1][2][1][RTW89_ETSI][1][89] = 127,
+ [0][1][2][1][RTW89_ETSI][0][89] = 127,
+ [0][1][2][1][RTW89_MKK][1][89] = 127,
+ [0][1][2][1][RTW89_MKK][0][89] = 127,
+ [0][1][2][1][RTW89_IC][1][89] = -2,
+ [0][1][2][1][RTW89_KCC][1][89] = 20,
+ [0][1][2][1][RTW89_KCC][0][89] = 127,
+ [0][1][2][1][RTW89_ACMA][1][89] = 127,
+ [0][1][2][1][RTW89_ACMA][0][89] = 127,
+ [0][1][2][1][RTW89_CHILE][1][89] = -2,
+ [0][1][2][1][RTW89_QATAR][1][89] = 127,
+ [0][1][2][1][RTW89_QATAR][0][89] = 127,
+ [0][1][2][1][RTW89_UK][1][89] = 127,
+ [0][1][2][1][RTW89_UK][0][89] = 127,
+ [0][1][2][1][RTW89_FCC][1][90] = -2,
+ [0][1][2][1][RTW89_FCC][2][90] = 127,
+ [0][1][2][1][RTW89_ETSI][1][90] = 127,
+ [0][1][2][1][RTW89_ETSI][0][90] = 127,
+ [0][1][2][1][RTW89_MKK][1][90] = 127,
+ [0][1][2][1][RTW89_MKK][0][90] = 127,
+ [0][1][2][1][RTW89_IC][1][90] = -2,
+ [0][1][2][1][RTW89_KCC][1][90] = 20,
+ [0][1][2][1][RTW89_KCC][0][90] = 127,
+ [0][1][2][1][RTW89_ACMA][1][90] = 127,
+ [0][1][2][1][RTW89_ACMA][0][90] = 127,
+ [0][1][2][1][RTW89_CHILE][1][90] = -2,
+ [0][1][2][1][RTW89_QATAR][1][90] = 127,
+ [0][1][2][1][RTW89_QATAR][0][90] = 127,
+ [0][1][2][1][RTW89_UK][1][90] = 127,
+ [0][1][2][1][RTW89_UK][0][90] = 127,
+ [0][1][2][1][RTW89_FCC][1][92] = -2,
+ [0][1][2][1][RTW89_FCC][2][92] = 127,
+ [0][1][2][1][RTW89_ETSI][1][92] = 127,
+ [0][1][2][1][RTW89_ETSI][0][92] = 127,
+ [0][1][2][1][RTW89_MKK][1][92] = 127,
+ [0][1][2][1][RTW89_MKK][0][92] = 127,
+ [0][1][2][1][RTW89_IC][1][92] = -2,
+ [0][1][2][1][RTW89_KCC][1][92] = 20,
+ [0][1][2][1][RTW89_KCC][0][92] = 127,
+ [0][1][2][1][RTW89_ACMA][1][92] = 127,
+ [0][1][2][1][RTW89_ACMA][0][92] = 127,
+ [0][1][2][1][RTW89_CHILE][1][92] = -2,
+ [0][1][2][1][RTW89_QATAR][1][92] = 127,
+ [0][1][2][1][RTW89_QATAR][0][92] = 127,
+ [0][1][2][1][RTW89_UK][1][92] = 127,
+ [0][1][2][1][RTW89_UK][0][92] = 127,
+ [0][1][2][1][RTW89_FCC][1][94] = -2,
+ [0][1][2][1][RTW89_FCC][2][94] = 127,
+ [0][1][2][1][RTW89_ETSI][1][94] = 127,
+ [0][1][2][1][RTW89_ETSI][0][94] = 127,
+ [0][1][2][1][RTW89_MKK][1][94] = 127,
+ [0][1][2][1][RTW89_MKK][0][94] = 127,
+ [0][1][2][1][RTW89_IC][1][94] = -2,
+ [0][1][2][1][RTW89_KCC][1][94] = 20,
+ [0][1][2][1][RTW89_KCC][0][94] = 127,
+ [0][1][2][1][RTW89_ACMA][1][94] = 127,
+ [0][1][2][1][RTW89_ACMA][0][94] = 127,
+ [0][1][2][1][RTW89_CHILE][1][94] = -2,
+ [0][1][2][1][RTW89_QATAR][1][94] = 127,
+ [0][1][2][1][RTW89_QATAR][0][94] = 127,
+ [0][1][2][1][RTW89_UK][1][94] = 127,
+ [0][1][2][1][RTW89_UK][0][94] = 127,
+ [0][1][2][1][RTW89_FCC][1][96] = -2,
+ [0][1][2][1][RTW89_FCC][2][96] = 127,
+ [0][1][2][1][RTW89_ETSI][1][96] = 127,
+ [0][1][2][1][RTW89_ETSI][0][96] = 127,
+ [0][1][2][1][RTW89_MKK][1][96] = 127,
+ [0][1][2][1][RTW89_MKK][0][96] = 127,
+ [0][1][2][1][RTW89_IC][1][96] = -2,
+ [0][1][2][1][RTW89_KCC][1][96] = 20,
+ [0][1][2][1][RTW89_KCC][0][96] = 127,
+ [0][1][2][1][RTW89_ACMA][1][96] = 127,
+ [0][1][2][1][RTW89_ACMA][0][96] = 127,
+ [0][1][2][1][RTW89_CHILE][1][96] = -2,
+ [0][1][2][1][RTW89_QATAR][1][96] = 127,
+ [0][1][2][1][RTW89_QATAR][0][96] = 127,
+ [0][1][2][1][RTW89_UK][1][96] = 127,
+ [0][1][2][1][RTW89_UK][0][96] = 127,
+ [0][1][2][1][RTW89_FCC][1][98] = -2,
+ [0][1][2][1][RTW89_FCC][2][98] = 127,
+ [0][1][2][1][RTW89_ETSI][1][98] = 127,
+ [0][1][2][1][RTW89_ETSI][0][98] = 127,
+ [0][1][2][1][RTW89_MKK][1][98] = 127,
+ [0][1][2][1][RTW89_MKK][0][98] = 127,
+ [0][1][2][1][RTW89_IC][1][98] = -2,
+ [0][1][2][1][RTW89_KCC][1][98] = 20,
+ [0][1][2][1][RTW89_KCC][0][98] = 127,
+ [0][1][2][1][RTW89_ACMA][1][98] = 127,
+ [0][1][2][1][RTW89_ACMA][0][98] = 127,
+ [0][1][2][1][RTW89_CHILE][1][98] = -2,
+ [0][1][2][1][RTW89_QATAR][1][98] = 127,
+ [0][1][2][1][RTW89_QATAR][0][98] = 127,
+ [0][1][2][1][RTW89_UK][1][98] = 127,
+ [0][1][2][1][RTW89_UK][0][98] = 127,
+ [0][1][2][1][RTW89_FCC][1][100] = -2,
+ [0][1][2][1][RTW89_FCC][2][100] = 127,
+ [0][1][2][1][RTW89_ETSI][1][100] = 127,
+ [0][1][2][1][RTW89_ETSI][0][100] = 127,
+ [0][1][2][1][RTW89_MKK][1][100] = 127,
+ [0][1][2][1][RTW89_MKK][0][100] = 127,
+ [0][1][2][1][RTW89_IC][1][100] = -2,
+ [0][1][2][1][RTW89_KCC][1][100] = 20,
+ [0][1][2][1][RTW89_KCC][0][100] = 127,
+ [0][1][2][1][RTW89_ACMA][1][100] = 127,
+ [0][1][2][1][RTW89_ACMA][0][100] = 127,
+ [0][1][2][1][RTW89_CHILE][1][100] = -2,
+ [0][1][2][1][RTW89_QATAR][1][100] = 127,
+ [0][1][2][1][RTW89_QATAR][0][100] = 127,
+ [0][1][2][1][RTW89_UK][1][100] = 127,
+ [0][1][2][1][RTW89_UK][0][100] = 127,
+ [0][1][2][1][RTW89_FCC][1][102] = -2,
+ [0][1][2][1][RTW89_FCC][2][102] = 127,
+ [0][1][2][1][RTW89_ETSI][1][102] = 127,
+ [0][1][2][1][RTW89_ETSI][0][102] = 127,
+ [0][1][2][1][RTW89_MKK][1][102] = 127,
+ [0][1][2][1][RTW89_MKK][0][102] = 127,
+ [0][1][2][1][RTW89_IC][1][102] = -2,
+ [0][1][2][1][RTW89_KCC][1][102] = 20,
+ [0][1][2][1][RTW89_KCC][0][102] = 127,
+ [0][1][2][1][RTW89_ACMA][1][102] = 127,
+ [0][1][2][1][RTW89_ACMA][0][102] = 127,
+ [0][1][2][1][RTW89_CHILE][1][102] = -2,
+ [0][1][2][1][RTW89_QATAR][1][102] = 127,
+ [0][1][2][1][RTW89_QATAR][0][102] = 127,
+ [0][1][2][1][RTW89_UK][1][102] = 127,
+ [0][1][2][1][RTW89_UK][0][102] = 127,
+ [0][1][2][1][RTW89_FCC][1][104] = -2,
+ [0][1][2][1][RTW89_FCC][2][104] = 127,
+ [0][1][2][1][RTW89_ETSI][1][104] = 127,
+ [0][1][2][1][RTW89_ETSI][0][104] = 127,
+ [0][1][2][1][RTW89_MKK][1][104] = 127,
+ [0][1][2][1][RTW89_MKK][0][104] = 127,
+ [0][1][2][1][RTW89_IC][1][104] = -2,
+ [0][1][2][1][RTW89_KCC][1][104] = 20,
+ [0][1][2][1][RTW89_KCC][0][104] = 127,
+ [0][1][2][1][RTW89_ACMA][1][104] = 127,
+ [0][1][2][1][RTW89_ACMA][0][104] = 127,
+ [0][1][2][1][RTW89_CHILE][1][104] = -2,
+ [0][1][2][1][RTW89_QATAR][1][104] = 127,
+ [0][1][2][1][RTW89_QATAR][0][104] = 127,
+ [0][1][2][1][RTW89_UK][1][104] = 127,
+ [0][1][2][1][RTW89_UK][0][104] = 127,
+ [0][1][2][1][RTW89_FCC][1][105] = -2,
+ [0][1][2][1][RTW89_FCC][2][105] = 127,
+ [0][1][2][1][RTW89_ETSI][1][105] = 127,
+ [0][1][2][1][RTW89_ETSI][0][105] = 127,
+ [0][1][2][1][RTW89_MKK][1][105] = 127,
+ [0][1][2][1][RTW89_MKK][0][105] = 127,
+ [0][1][2][1][RTW89_IC][1][105] = -2,
+ [0][1][2][1][RTW89_KCC][1][105] = 20,
+ [0][1][2][1][RTW89_KCC][0][105] = 127,
+ [0][1][2][1][RTW89_ACMA][1][105] = 127,
+ [0][1][2][1][RTW89_ACMA][0][105] = 127,
+ [0][1][2][1][RTW89_CHILE][1][105] = -2,
+ [0][1][2][1][RTW89_QATAR][1][105] = 127,
+ [0][1][2][1][RTW89_QATAR][0][105] = 127,
+ [0][1][2][1][RTW89_UK][1][105] = 127,
+ [0][1][2][1][RTW89_UK][0][105] = 127,
+ [0][1][2][1][RTW89_FCC][1][107] = 1,
+ [0][1][2][1][RTW89_FCC][2][107] = 127,
+ [0][1][2][1][RTW89_ETSI][1][107] = 127,
+ [0][1][2][1][RTW89_ETSI][0][107] = 127,
+ [0][1][2][1][RTW89_MKK][1][107] = 127,
+ [0][1][2][1][RTW89_MKK][0][107] = 127,
+ [0][1][2][1][RTW89_IC][1][107] = 1,
+ [0][1][2][1][RTW89_KCC][1][107] = 20,
+ [0][1][2][1][RTW89_KCC][0][107] = 127,
+ [0][1][2][1][RTW89_ACMA][1][107] = 127,
+ [0][1][2][1][RTW89_ACMA][0][107] = 127,
+ [0][1][2][1][RTW89_CHILE][1][107] = 1,
+ [0][1][2][1][RTW89_QATAR][1][107] = 127,
+ [0][1][2][1][RTW89_QATAR][0][107] = 127,
+ [0][1][2][1][RTW89_UK][1][107] = 127,
+ [0][1][2][1][RTW89_UK][0][107] = 127,
+ [0][1][2][1][RTW89_FCC][1][109] = 1,
+ [0][1][2][1][RTW89_FCC][2][109] = 127,
+ [0][1][2][1][RTW89_ETSI][1][109] = 127,
+ [0][1][2][1][RTW89_ETSI][0][109] = 127,
+ [0][1][2][1][RTW89_MKK][1][109] = 127,
+ [0][1][2][1][RTW89_MKK][0][109] = 127,
+ [0][1][2][1][RTW89_IC][1][109] = 1,
+ [0][1][2][1][RTW89_KCC][1][109] = 20,
+ [0][1][2][1][RTW89_KCC][0][109] = 127,
+ [0][1][2][1][RTW89_ACMA][1][109] = 127,
+ [0][1][2][1][RTW89_ACMA][0][109] = 127,
+ [0][1][2][1][RTW89_CHILE][1][109] = 1,
+ [0][1][2][1][RTW89_QATAR][1][109] = 127,
+ [0][1][2][1][RTW89_QATAR][0][109] = 127,
+ [0][1][2][1][RTW89_UK][1][109] = 127,
+ [0][1][2][1][RTW89_UK][0][109] = 127,
+ [0][1][2][1][RTW89_FCC][1][111] = 127,
+ [0][1][2][1][RTW89_FCC][2][111] = 127,
+ [0][1][2][1][RTW89_ETSI][1][111] = 127,
+ [0][1][2][1][RTW89_ETSI][0][111] = 127,
+ [0][1][2][1][RTW89_MKK][1][111] = 127,
+ [0][1][2][1][RTW89_MKK][0][111] = 127,
+ [0][1][2][1][RTW89_IC][1][111] = 127,
+ [0][1][2][1][RTW89_KCC][1][111] = 127,
+ [0][1][2][1][RTW89_KCC][0][111] = 127,
+ [0][1][2][1][RTW89_ACMA][1][111] = 127,
+ [0][1][2][1][RTW89_ACMA][0][111] = 127,
+ [0][1][2][1][RTW89_CHILE][1][111] = 127,
+ [0][1][2][1][RTW89_QATAR][1][111] = 127,
+ [0][1][2][1][RTW89_QATAR][0][111] = 127,
+ [0][1][2][1][RTW89_UK][1][111] = 127,
+ [0][1][2][1][RTW89_UK][0][111] = 127,
+ [0][1][2][1][RTW89_FCC][1][113] = 127,
+ [0][1][2][1][RTW89_FCC][2][113] = 127,
+ [0][1][2][1][RTW89_ETSI][1][113] = 127,
+ [0][1][2][1][RTW89_ETSI][0][113] = 127,
+ [0][1][2][1][RTW89_MKK][1][113] = 127,
+ [0][1][2][1][RTW89_MKK][0][113] = 127,
+ [0][1][2][1][RTW89_IC][1][113] = 127,
+ [0][1][2][1][RTW89_KCC][1][113] = 127,
+ [0][1][2][1][RTW89_KCC][0][113] = 127,
+ [0][1][2][1][RTW89_ACMA][1][113] = 127,
+ [0][1][2][1][RTW89_ACMA][0][113] = 127,
+ [0][1][2][1][RTW89_CHILE][1][113] = 127,
+ [0][1][2][1][RTW89_QATAR][1][113] = 127,
+ [0][1][2][1][RTW89_QATAR][0][113] = 127,
+ [0][1][2][1][RTW89_UK][1][113] = 127,
+ [0][1][2][1][RTW89_UK][0][113] = 127,
+ [0][1][2][1][RTW89_FCC][1][115] = 127,
+ [0][1][2][1][RTW89_FCC][2][115] = 127,
+ [0][1][2][1][RTW89_ETSI][1][115] = 127,
+ [0][1][2][1][RTW89_ETSI][0][115] = 127,
+ [0][1][2][1][RTW89_MKK][1][115] = 127,
+ [0][1][2][1][RTW89_MKK][0][115] = 127,
+ [0][1][2][1][RTW89_IC][1][115] = 127,
+ [0][1][2][1][RTW89_KCC][1][115] = 127,
+ [0][1][2][1][RTW89_KCC][0][115] = 127,
+ [0][1][2][1][RTW89_ACMA][1][115] = 127,
+ [0][1][2][1][RTW89_ACMA][0][115] = 127,
+ [0][1][2][1][RTW89_CHILE][1][115] = 127,
+ [0][1][2][1][RTW89_QATAR][1][115] = 127,
+ [0][1][2][1][RTW89_QATAR][0][115] = 127,
+ [0][1][2][1][RTW89_UK][1][115] = 127,
+ [0][1][2][1][RTW89_UK][0][115] = 127,
+ [0][1][2][1][RTW89_FCC][1][117] = 127,
+ [0][1][2][1][RTW89_FCC][2][117] = 127,
+ [0][1][2][1][RTW89_ETSI][1][117] = 127,
+ [0][1][2][1][RTW89_ETSI][0][117] = 127,
+ [0][1][2][1][RTW89_MKK][1][117] = 127,
+ [0][1][2][1][RTW89_MKK][0][117] = 127,
+ [0][1][2][1][RTW89_IC][1][117] = 127,
+ [0][1][2][1][RTW89_KCC][1][117] = 127,
+ [0][1][2][1][RTW89_KCC][0][117] = 127,
+ [0][1][2][1][RTW89_ACMA][1][117] = 127,
+ [0][1][2][1][RTW89_ACMA][0][117] = 127,
+ [0][1][2][1][RTW89_CHILE][1][117] = 127,
+ [0][1][2][1][RTW89_QATAR][1][117] = 127,
+ [0][1][2][1][RTW89_QATAR][0][117] = 127,
+ [0][1][2][1][RTW89_UK][1][117] = 127,
+ [0][1][2][1][RTW89_UK][0][117] = 127,
+ [0][1][2][1][RTW89_FCC][1][119] = 127,
+ [0][1][2][1][RTW89_FCC][2][119] = 127,
+ [0][1][2][1][RTW89_ETSI][1][119] = 127,
+ [0][1][2][1][RTW89_ETSI][0][119] = 127,
+ [0][1][2][1][RTW89_MKK][1][119] = 127,
+ [0][1][2][1][RTW89_MKK][0][119] = 127,
+ [0][1][2][1][RTW89_IC][1][119] = 127,
+ [0][1][2][1][RTW89_KCC][1][119] = 127,
+ [0][1][2][1][RTW89_KCC][0][119] = 127,
+ [0][1][2][1][RTW89_ACMA][1][119] = 127,
+ [0][1][2][1][RTW89_ACMA][0][119] = 127,
+ [0][1][2][1][RTW89_CHILE][1][119] = 127,
+ [0][1][2][1][RTW89_QATAR][1][119] = 127,
+ [0][1][2][1][RTW89_QATAR][0][119] = 127,
+ [0][1][2][1][RTW89_UK][1][119] = 127,
+ [0][1][2][1][RTW89_UK][0][119] = 127,
+ [1][0][2][0][RTW89_FCC][1][1] = 34,
+ [1][0][2][0][RTW89_FCC][2][1] = 70,
+ [1][0][2][0][RTW89_ETSI][1][1] = 66,
+ [1][0][2][0][RTW89_ETSI][0][1] = 30,
+ [1][0][2][0][RTW89_MKK][1][1] = 62,
+ [1][0][2][0][RTW89_MKK][0][1] = 26,
+ [1][0][2][0][RTW89_IC][1][1] = 34,
+ [1][0][2][0][RTW89_KCC][1][1] = 40,
+ [1][0][2][0][RTW89_KCC][0][1] = 24,
+ [1][0][2][0][RTW89_ACMA][1][1] = 66,
+ [1][0][2][0][RTW89_ACMA][0][1] = 30,
+ [1][0][2][0][RTW89_CHILE][1][1] = 34,
+ [1][0][2][0][RTW89_QATAR][1][1] = 66,
+ [1][0][2][0][RTW89_QATAR][0][1] = 30,
+ [1][0][2][0][RTW89_UK][1][1] = 66,
+ [1][0][2][0][RTW89_UK][0][1] = 30,
+ [1][0][2][0][RTW89_FCC][1][5] = 34,
+ [1][0][2][0][RTW89_FCC][2][5] = 70,
+ [1][0][2][0][RTW89_ETSI][1][5] = 66,
+ [1][0][2][0][RTW89_ETSI][0][5] = 30,
+ [1][0][2][0][RTW89_MKK][1][5] = 62,
+ [1][0][2][0][RTW89_MKK][0][5] = 26,
+ [1][0][2][0][RTW89_IC][1][5] = 34,
+ [1][0][2][0][RTW89_KCC][1][5] = 40,
+ [1][0][2][0][RTW89_KCC][0][5] = 24,
+ [1][0][2][0][RTW89_ACMA][1][5] = 66,
+ [1][0][2][0][RTW89_ACMA][0][5] = 30,
+ [1][0][2][0][RTW89_CHILE][1][5] = 34,
+ [1][0][2][0][RTW89_QATAR][1][5] = 66,
+ [1][0][2][0][RTW89_QATAR][0][5] = 30,
+ [1][0][2][0][RTW89_UK][1][5] = 66,
+ [1][0][2][0][RTW89_UK][0][5] = 30,
+ [1][0][2][0][RTW89_FCC][1][9] = 34,
+ [1][0][2][0][RTW89_FCC][2][9] = 70,
+ [1][0][2][0][RTW89_ETSI][1][9] = 66,
+ [1][0][2][0][RTW89_ETSI][0][9] = 30,
+ [1][0][2][0][RTW89_MKK][1][9] = 62,
+ [1][0][2][0][RTW89_MKK][0][9] = 26,
+ [1][0][2][0][RTW89_IC][1][9] = 34,
+ [1][0][2][0][RTW89_KCC][1][9] = 40,
+ [1][0][2][0][RTW89_KCC][0][9] = 24,
+ [1][0][2][0][RTW89_ACMA][1][9] = 66,
+ [1][0][2][0][RTW89_ACMA][0][9] = 30,
+ [1][0][2][0][RTW89_CHILE][1][9] = 34,
+ [1][0][2][0][RTW89_QATAR][1][9] = 66,
+ [1][0][2][0][RTW89_QATAR][0][9] = 30,
+ [1][0][2][0][RTW89_UK][1][9] = 66,
+ [1][0][2][0][RTW89_UK][0][9] = 30,
+ [1][0][2][0][RTW89_FCC][1][13] = 34,
+ [1][0][2][0][RTW89_FCC][2][13] = 70,
+ [1][0][2][0][RTW89_ETSI][1][13] = 66,
+ [1][0][2][0][RTW89_ETSI][0][13] = 30,
+ [1][0][2][0][RTW89_MKK][1][13] = 62,
+ [1][0][2][0][RTW89_MKK][0][13] = 26,
+ [1][0][2][0][RTW89_IC][1][13] = 34,
+ [1][0][2][0][RTW89_KCC][1][13] = 40,
+ [1][0][2][0][RTW89_KCC][0][13] = 24,
+ [1][0][2][0][RTW89_ACMA][1][13] = 66,
+ [1][0][2][0][RTW89_ACMA][0][13] = 30,
+ [1][0][2][0][RTW89_CHILE][1][13] = 34,
+ [1][0][2][0][RTW89_QATAR][1][13] = 66,
+ [1][0][2][0][RTW89_QATAR][0][13] = 30,
+ [1][0][2][0][RTW89_UK][1][13] = 66,
+ [1][0][2][0][RTW89_UK][0][13] = 30,
+ [1][0][2][0][RTW89_FCC][1][16] = 34,
+ [1][0][2][0][RTW89_FCC][2][16] = 70,
+ [1][0][2][0][RTW89_ETSI][1][16] = 66,
+ [1][0][2][0][RTW89_ETSI][0][16] = 30,
+ [1][0][2][0][RTW89_MKK][1][16] = 62,
+ [1][0][2][0][RTW89_MKK][0][16] = 26,
+ [1][0][2][0][RTW89_IC][1][16] = 34,
+ [1][0][2][0][RTW89_KCC][1][16] = 40,
+ [1][0][2][0][RTW89_KCC][0][16] = 24,
+ [1][0][2][0][RTW89_ACMA][1][16] = 66,
+ [1][0][2][0][RTW89_ACMA][0][16] = 30,
+ [1][0][2][0][RTW89_CHILE][1][16] = 34,
+ [1][0][2][0][RTW89_QATAR][1][16] = 66,
+ [1][0][2][0][RTW89_QATAR][0][16] = 30,
+ [1][0][2][0][RTW89_UK][1][16] = 66,
+ [1][0][2][0][RTW89_UK][0][16] = 30,
+ [1][0][2][0][RTW89_FCC][1][20] = 34,
+ [1][0][2][0][RTW89_FCC][2][20] = 70,
+ [1][0][2][0][RTW89_ETSI][1][20] = 66,
+ [1][0][2][0][RTW89_ETSI][0][20] = 30,
+ [1][0][2][0][RTW89_MKK][1][20] = 62,
+ [1][0][2][0][RTW89_MKK][0][20] = 26,
+ [1][0][2][0][RTW89_IC][1][20] = 34,
+ [1][0][2][0][RTW89_KCC][1][20] = 40,
+ [1][0][2][0][RTW89_KCC][0][20] = 24,
+ [1][0][2][0][RTW89_ACMA][1][20] = 66,
+ [1][0][2][0][RTW89_ACMA][0][20] = 30,
+ [1][0][2][0][RTW89_CHILE][1][20] = 34,
+ [1][0][2][0][RTW89_QATAR][1][20] = 66,
+ [1][0][2][0][RTW89_QATAR][0][20] = 30,
+ [1][0][2][0][RTW89_UK][1][20] = 66,
+ [1][0][2][0][RTW89_UK][0][20] = 30,
+ [1][0][2][0][RTW89_FCC][1][24] = 36,
+ [1][0][2][0][RTW89_FCC][2][24] = 70,
+ [1][0][2][0][RTW89_ETSI][1][24] = 66,
+ [1][0][2][0][RTW89_ETSI][0][24] = 30,
+ [1][0][2][0][RTW89_MKK][1][24] = 64,
+ [1][0][2][0][RTW89_MKK][0][24] = 28,
+ [1][0][2][0][RTW89_IC][1][24] = 36,
+ [1][0][2][0][RTW89_KCC][1][24] = 40,
+ [1][0][2][0][RTW89_KCC][0][24] = 26,
+ [1][0][2][0][RTW89_ACMA][1][24] = 66,
+ [1][0][2][0][RTW89_ACMA][0][24] = 30,
+ [1][0][2][0][RTW89_CHILE][1][24] = 36,
+ [1][0][2][0][RTW89_QATAR][1][24] = 66,
+ [1][0][2][0][RTW89_QATAR][0][24] = 30,
+ [1][0][2][0][RTW89_UK][1][24] = 66,
+ [1][0][2][0][RTW89_UK][0][24] = 30,
+ [1][0][2][0][RTW89_FCC][1][28] = 34,
+ [1][0][2][0][RTW89_FCC][2][28] = 70,
+ [1][0][2][0][RTW89_ETSI][1][28] = 66,
+ [1][0][2][0][RTW89_ETSI][0][28] = 30,
+ [1][0][2][0][RTW89_MKK][1][28] = 64,
+ [1][0][2][0][RTW89_MKK][0][28] = 26,
+ [1][0][2][0][RTW89_IC][1][28] = 34,
+ [1][0][2][0][RTW89_KCC][1][28] = 40,
+ [1][0][2][0][RTW89_KCC][0][28] = 26,
+ [1][0][2][0][RTW89_ACMA][1][28] = 66,
+ [1][0][2][0][RTW89_ACMA][0][28] = 30,
+ [1][0][2][0][RTW89_CHILE][1][28] = 34,
+ [1][0][2][0][RTW89_QATAR][1][28] = 66,
+ [1][0][2][0][RTW89_QATAR][0][28] = 30,
+ [1][0][2][0][RTW89_UK][1][28] = 66,
+ [1][0][2][0][RTW89_UK][0][28] = 30,
+ [1][0][2][0][RTW89_FCC][1][31] = 34,
+ [1][0][2][0][RTW89_FCC][2][31] = 70,
+ [1][0][2][0][RTW89_ETSI][1][31] = 66,
+ [1][0][2][0][RTW89_ETSI][0][31] = 30,
+ [1][0][2][0][RTW89_MKK][1][31] = 64,
+ [1][0][2][0][RTW89_MKK][0][31] = 26,
+ [1][0][2][0][RTW89_IC][1][31] = 34,
+ [1][0][2][0][RTW89_KCC][1][31] = 40,
+ [1][0][2][0][RTW89_KCC][0][31] = 26,
+ [1][0][2][0][RTW89_ACMA][1][31] = 66,
+ [1][0][2][0][RTW89_ACMA][0][31] = 30,
+ [1][0][2][0][RTW89_CHILE][1][31] = 34,
+ [1][0][2][0][RTW89_QATAR][1][31] = 66,
+ [1][0][2][0][RTW89_QATAR][0][31] = 30,
+ [1][0][2][0][RTW89_UK][1][31] = 66,
+ [1][0][2][0][RTW89_UK][0][31] = 30,
+ [1][0][2][0][RTW89_FCC][1][35] = 34,
+ [1][0][2][0][RTW89_FCC][2][35] = 70,
+ [1][0][2][0][RTW89_ETSI][1][35] = 66,
+ [1][0][2][0][RTW89_ETSI][0][35] = 30,
+ [1][0][2][0][RTW89_MKK][1][35] = 64,
+ [1][0][2][0][RTW89_MKK][0][35] = 26,
+ [1][0][2][0][RTW89_IC][1][35] = 34,
+ [1][0][2][0][RTW89_KCC][1][35] = 40,
+ [1][0][2][0][RTW89_KCC][0][35] = 26,
+ [1][0][2][0][RTW89_ACMA][1][35] = 66,
+ [1][0][2][0][RTW89_ACMA][0][35] = 30,
+ [1][0][2][0][RTW89_CHILE][1][35] = 34,
+ [1][0][2][0][RTW89_QATAR][1][35] = 66,
+ [1][0][2][0][RTW89_QATAR][0][35] = 30,
+ [1][0][2][0][RTW89_UK][1][35] = 66,
+ [1][0][2][0][RTW89_UK][0][35] = 30,
+ [1][0][2][0][RTW89_FCC][1][39] = 34,
+ [1][0][2][0][RTW89_FCC][2][39] = 70,
+ [1][0][2][0][RTW89_ETSI][1][39] = 66,
+ [1][0][2][0][RTW89_ETSI][0][39] = 30,
+ [1][0][2][0][RTW89_MKK][1][39] = 64,
+ [1][0][2][0][RTW89_MKK][0][39] = 26,
+ [1][0][2][0][RTW89_IC][1][39] = 34,
+ [1][0][2][0][RTW89_KCC][1][39] = 40,
+ [1][0][2][0][RTW89_KCC][0][39] = 26,
+ [1][0][2][0][RTW89_ACMA][1][39] = 66,
+ [1][0][2][0][RTW89_ACMA][0][39] = 30,
+ [1][0][2][0][RTW89_CHILE][1][39] = 34,
+ [1][0][2][0][RTW89_QATAR][1][39] = 66,
+ [1][0][2][0][RTW89_QATAR][0][39] = 30,
+ [1][0][2][0][RTW89_UK][1][39] = 66,
+ [1][0][2][0][RTW89_UK][0][39] = 30,
+ [1][0][2][0][RTW89_FCC][1][43] = 34,
+ [1][0][2][0][RTW89_FCC][2][43] = 70,
+ [1][0][2][0][RTW89_ETSI][1][43] = 66,
+ [1][0][2][0][RTW89_ETSI][0][43] = 30,
+ [1][0][2][0][RTW89_MKK][1][43] = 64,
+ [1][0][2][0][RTW89_MKK][0][43] = 26,
+ [1][0][2][0][RTW89_IC][1][43] = 34,
+ [1][0][2][0][RTW89_KCC][1][43] = 40,
+ [1][0][2][0][RTW89_KCC][0][43] = 26,
+ [1][0][2][0][RTW89_ACMA][1][43] = 66,
+ [1][0][2][0][RTW89_ACMA][0][43] = 30,
+ [1][0][2][0][RTW89_CHILE][1][43] = 34,
+ [1][0][2][0][RTW89_QATAR][1][43] = 66,
+ [1][0][2][0][RTW89_QATAR][0][43] = 30,
+ [1][0][2][0][RTW89_UK][1][43] = 66,
+ [1][0][2][0][RTW89_UK][0][43] = 30,
+ [1][0][2][0][RTW89_FCC][1][46] = 34,
+ [1][0][2][0][RTW89_FCC][2][46] = 127,
+ [1][0][2][0][RTW89_ETSI][1][46] = 127,
+ [1][0][2][0][RTW89_ETSI][0][46] = 127,
+ [1][0][2][0][RTW89_MKK][1][46] = 127,
+ [1][0][2][0][RTW89_MKK][0][46] = 127,
+ [1][0][2][0][RTW89_IC][1][46] = 34,
+ [1][0][2][0][RTW89_KCC][1][46] = 40,
+ [1][0][2][0][RTW89_KCC][0][46] = 127,
+ [1][0][2][0][RTW89_ACMA][1][46] = 127,
+ [1][0][2][0][RTW89_ACMA][0][46] = 127,
+ [1][0][2][0][RTW89_CHILE][1][46] = 34,
+ [1][0][2][0][RTW89_QATAR][1][46] = 127,
+ [1][0][2][0][RTW89_QATAR][0][46] = 127,
+ [1][0][2][0][RTW89_UK][1][46] = 127,
+ [1][0][2][0][RTW89_UK][0][46] = 127,
+ [1][0][2][0][RTW89_FCC][1][50] = 34,
+ [1][0][2][0][RTW89_FCC][2][50] = 127,
+ [1][0][2][0][RTW89_ETSI][1][50] = 127,
+ [1][0][2][0][RTW89_ETSI][0][50] = 127,
+ [1][0][2][0][RTW89_MKK][1][50] = 127,
+ [1][0][2][0][RTW89_MKK][0][50] = 127,
+ [1][0][2][0][RTW89_IC][1][50] = 34,
+ [1][0][2][0][RTW89_KCC][1][50] = 40,
+ [1][0][2][0][RTW89_KCC][0][50] = 127,
+ [1][0][2][0][RTW89_ACMA][1][50] = 127,
+ [1][0][2][0][RTW89_ACMA][0][50] = 127,
+ [1][0][2][0][RTW89_CHILE][1][50] = 34,
+ [1][0][2][0][RTW89_QATAR][1][50] = 127,
+ [1][0][2][0][RTW89_QATAR][0][50] = 127,
+ [1][0][2][0][RTW89_UK][1][50] = 127,
+ [1][0][2][0][RTW89_UK][0][50] = 127,
+ [1][0][2][0][RTW89_FCC][1][54] = 36,
+ [1][0][2][0][RTW89_FCC][2][54] = 127,
+ [1][0][2][0][RTW89_ETSI][1][54] = 127,
+ [1][0][2][0][RTW89_ETSI][0][54] = 127,
+ [1][0][2][0][RTW89_MKK][1][54] = 127,
+ [1][0][2][0][RTW89_MKK][0][54] = 127,
+ [1][0][2][0][RTW89_IC][1][54] = 36,
+ [1][0][2][0][RTW89_KCC][1][54] = 40,
+ [1][0][2][0][RTW89_KCC][0][54] = 127,
+ [1][0][2][0][RTW89_ACMA][1][54] = 127,
+ [1][0][2][0][RTW89_ACMA][0][54] = 127,
+ [1][0][2][0][RTW89_CHILE][1][54] = 36,
+ [1][0][2][0][RTW89_QATAR][1][54] = 127,
+ [1][0][2][0][RTW89_QATAR][0][54] = 127,
+ [1][0][2][0][RTW89_UK][1][54] = 127,
+ [1][0][2][0][RTW89_UK][0][54] = 127,
+ [1][0][2][0][RTW89_FCC][1][58] = 36,
+ [1][0][2][0][RTW89_FCC][2][58] = 66,
+ [1][0][2][0][RTW89_ETSI][1][58] = 127,
+ [1][0][2][0][RTW89_ETSI][0][58] = 127,
+ [1][0][2][0][RTW89_MKK][1][58] = 127,
+ [1][0][2][0][RTW89_MKK][0][58] = 127,
+ [1][0][2][0][RTW89_IC][1][58] = 36,
+ [1][0][2][0][RTW89_KCC][1][58] = 40,
+ [1][0][2][0][RTW89_KCC][0][58] = 127,
+ [1][0][2][0][RTW89_ACMA][1][58] = 127,
+ [1][0][2][0][RTW89_ACMA][0][58] = 127,
+ [1][0][2][0][RTW89_CHILE][1][58] = 36,
+ [1][0][2][0][RTW89_QATAR][1][58] = 127,
+ [1][0][2][0][RTW89_QATAR][0][58] = 127,
+ [1][0][2][0][RTW89_UK][1][58] = 127,
+ [1][0][2][0][RTW89_UK][0][58] = 127,
+ [1][0][2][0][RTW89_FCC][1][61] = 34,
+ [1][0][2][0][RTW89_FCC][2][61] = 66,
+ [1][0][2][0][RTW89_ETSI][1][61] = 127,
+ [1][0][2][0][RTW89_ETSI][0][61] = 127,
+ [1][0][2][0][RTW89_MKK][1][61] = 127,
+ [1][0][2][0][RTW89_MKK][0][61] = 127,
+ [1][0][2][0][RTW89_IC][1][61] = 34,
+ [1][0][2][0][RTW89_KCC][1][61] = 40,
+ [1][0][2][0][RTW89_KCC][0][61] = 127,
+ [1][0][2][0][RTW89_ACMA][1][61] = 127,
+ [1][0][2][0][RTW89_ACMA][0][61] = 127,
+ [1][0][2][0][RTW89_CHILE][1][61] = 34,
+ [1][0][2][0][RTW89_QATAR][1][61] = 127,
+ [1][0][2][0][RTW89_QATAR][0][61] = 127,
+ [1][0][2][0][RTW89_UK][1][61] = 127,
+ [1][0][2][0][RTW89_UK][0][61] = 127,
+ [1][0][2][0][RTW89_FCC][1][65] = 34,
+ [1][0][2][0][RTW89_FCC][2][65] = 66,
+ [1][0][2][0][RTW89_ETSI][1][65] = 127,
+ [1][0][2][0][RTW89_ETSI][0][65] = 127,
+ [1][0][2][0][RTW89_MKK][1][65] = 127,
+ [1][0][2][0][RTW89_MKK][0][65] = 127,
+ [1][0][2][0][RTW89_IC][1][65] = 34,
+ [1][0][2][0][RTW89_KCC][1][65] = 40,
+ [1][0][2][0][RTW89_KCC][0][65] = 127,
+ [1][0][2][0][RTW89_ACMA][1][65] = 127,
+ [1][0][2][0][RTW89_ACMA][0][65] = 127,
+ [1][0][2][0][RTW89_CHILE][1][65] = 34,
+ [1][0][2][0][RTW89_QATAR][1][65] = 127,
+ [1][0][2][0][RTW89_QATAR][0][65] = 127,
+ [1][0][2][0][RTW89_UK][1][65] = 127,
+ [1][0][2][0][RTW89_UK][0][65] = 127,
+ [1][0][2][0][RTW89_FCC][1][69] = 34,
+ [1][0][2][0][RTW89_FCC][2][69] = 66,
+ [1][0][2][0][RTW89_ETSI][1][69] = 127,
+ [1][0][2][0][RTW89_ETSI][0][69] = 127,
+ [1][0][2][0][RTW89_MKK][1][69] = 127,
+ [1][0][2][0][RTW89_MKK][0][69] = 127,
+ [1][0][2][0][RTW89_IC][1][69] = 34,
+ [1][0][2][0][RTW89_KCC][1][69] = 40,
+ [1][0][2][0][RTW89_KCC][0][69] = 127,
+ [1][0][2][0][RTW89_ACMA][1][69] = 127,
+ [1][0][2][0][RTW89_ACMA][0][69] = 127,
+ [1][0][2][0][RTW89_CHILE][1][69] = 34,
+ [1][0][2][0][RTW89_QATAR][1][69] = 127,
+ [1][0][2][0][RTW89_QATAR][0][69] = 127,
+ [1][0][2][0][RTW89_UK][1][69] = 127,
+ [1][0][2][0][RTW89_UK][0][69] = 127,
+ [1][0][2][0][RTW89_FCC][1][73] = 34,
+ [1][0][2][0][RTW89_FCC][2][73] = 66,
+ [1][0][2][0][RTW89_ETSI][1][73] = 127,
+ [1][0][2][0][RTW89_ETSI][0][73] = 127,
+ [1][0][2][0][RTW89_MKK][1][73] = 127,
+ [1][0][2][0][RTW89_MKK][0][73] = 127,
+ [1][0][2][0][RTW89_IC][1][73] = 34,
+ [1][0][2][0][RTW89_KCC][1][73] = 40,
+ [1][0][2][0][RTW89_KCC][0][73] = 127,
+ [1][0][2][0][RTW89_ACMA][1][73] = 127,
+ [1][0][2][0][RTW89_ACMA][0][73] = 127,
+ [1][0][2][0][RTW89_CHILE][1][73] = 34,
+ [1][0][2][0][RTW89_QATAR][1][73] = 127,
+ [1][0][2][0][RTW89_QATAR][0][73] = 127,
+ [1][0][2][0][RTW89_UK][1][73] = 127,
+ [1][0][2][0][RTW89_UK][0][73] = 127,
+ [1][0][2][0][RTW89_FCC][1][76] = 34,
+ [1][0][2][0][RTW89_FCC][2][76] = 66,
+ [1][0][2][0][RTW89_ETSI][1][76] = 127,
+ [1][0][2][0][RTW89_ETSI][0][76] = 127,
+ [1][0][2][0][RTW89_MKK][1][76] = 127,
+ [1][0][2][0][RTW89_MKK][0][76] = 127,
+ [1][0][2][0][RTW89_IC][1][76] = 34,
+ [1][0][2][0][RTW89_KCC][1][76] = 40,
+ [1][0][2][0][RTW89_KCC][0][76] = 127,
+ [1][0][2][0][RTW89_ACMA][1][76] = 127,
+ [1][0][2][0][RTW89_ACMA][0][76] = 127,
+ [1][0][2][0][RTW89_CHILE][1][76] = 34,
+ [1][0][2][0][RTW89_QATAR][1][76] = 127,
+ [1][0][2][0][RTW89_QATAR][0][76] = 127,
+ [1][0][2][0][RTW89_UK][1][76] = 127,
+ [1][0][2][0][RTW89_UK][0][76] = 127,
+ [1][0][2][0][RTW89_FCC][1][80] = 34,
+ [1][0][2][0][RTW89_FCC][2][80] = 66,
+ [1][0][2][0][RTW89_ETSI][1][80] = 127,
+ [1][0][2][0][RTW89_ETSI][0][80] = 127,
+ [1][0][2][0][RTW89_MKK][1][80] = 127,
+ [1][0][2][0][RTW89_MKK][0][80] = 127,
+ [1][0][2][0][RTW89_IC][1][80] = 34,
+ [1][0][2][0][RTW89_KCC][1][80] = 42,
+ [1][0][2][0][RTW89_KCC][0][80] = 127,
+ [1][0][2][0][RTW89_ACMA][1][80] = 127,
+ [1][0][2][0][RTW89_ACMA][0][80] = 127,
+ [1][0][2][0][RTW89_CHILE][1][80] = 34,
+ [1][0][2][0][RTW89_QATAR][1][80] = 127,
+ [1][0][2][0][RTW89_QATAR][0][80] = 127,
+ [1][0][2][0][RTW89_UK][1][80] = 127,
+ [1][0][2][0][RTW89_UK][0][80] = 127,
+ [1][0][2][0][RTW89_FCC][1][84] = 34,
+ [1][0][2][0][RTW89_FCC][2][84] = 66,
+ [1][0][2][0][RTW89_ETSI][1][84] = 127,
+ [1][0][2][0][RTW89_ETSI][0][84] = 127,
+ [1][0][2][0][RTW89_MKK][1][84] = 127,
+ [1][0][2][0][RTW89_MKK][0][84] = 127,
+ [1][0][2][0][RTW89_IC][1][84] = 34,
+ [1][0][2][0][RTW89_KCC][1][84] = 42,
+ [1][0][2][0][RTW89_KCC][0][84] = 127,
+ [1][0][2][0][RTW89_ACMA][1][84] = 127,
+ [1][0][2][0][RTW89_ACMA][0][84] = 127,
+ [1][0][2][0][RTW89_CHILE][1][84] = 34,
+ [1][0][2][0][RTW89_QATAR][1][84] = 127,
+ [1][0][2][0][RTW89_QATAR][0][84] = 127,
+ [1][0][2][0][RTW89_UK][1][84] = 127,
+ [1][0][2][0][RTW89_UK][0][84] = 127,
+ [1][0][2][0][RTW89_FCC][1][88] = 34,
+ [1][0][2][0][RTW89_FCC][2][88] = 127,
+ [1][0][2][0][RTW89_ETSI][1][88] = 127,
+ [1][0][2][0][RTW89_ETSI][0][88] = 127,
+ [1][0][2][0][RTW89_MKK][1][88] = 127,
+ [1][0][2][0][RTW89_MKK][0][88] = 127,
+ [1][0][2][0][RTW89_IC][1][88] = 34,
+ [1][0][2][0][RTW89_KCC][1][88] = 42,
+ [1][0][2][0][RTW89_KCC][0][88] = 127,
+ [1][0][2][0][RTW89_ACMA][1][88] = 127,
+ [1][0][2][0][RTW89_ACMA][0][88] = 127,
+ [1][0][2][0][RTW89_CHILE][1][88] = 34,
+ [1][0][2][0][RTW89_QATAR][1][88] = 127,
+ [1][0][2][0][RTW89_QATAR][0][88] = 127,
+ [1][0][2][0][RTW89_UK][1][88] = 127,
+ [1][0][2][0][RTW89_UK][0][88] = 127,
+ [1][0][2][0][RTW89_FCC][1][91] = 36,
+ [1][0][2][0][RTW89_FCC][2][91] = 127,
+ [1][0][2][0][RTW89_ETSI][1][91] = 127,
+ [1][0][2][0][RTW89_ETSI][0][91] = 127,
+ [1][0][2][0][RTW89_MKK][1][91] = 127,
+ [1][0][2][0][RTW89_MKK][0][91] = 127,
+ [1][0][2][0][RTW89_IC][1][91] = 36,
+ [1][0][2][0][RTW89_KCC][1][91] = 42,
+ [1][0][2][0][RTW89_KCC][0][91] = 127,
+ [1][0][2][0][RTW89_ACMA][1][91] = 127,
+ [1][0][2][0][RTW89_ACMA][0][91] = 127,
+ [1][0][2][0][RTW89_CHILE][1][91] = 36,
+ [1][0][2][0][RTW89_QATAR][1][91] = 127,
+ [1][0][2][0][RTW89_QATAR][0][91] = 127,
+ [1][0][2][0][RTW89_UK][1][91] = 127,
+ [1][0][2][0][RTW89_UK][0][91] = 127,
+ [1][0][2][0][RTW89_FCC][1][95] = 34,
+ [1][0][2][0][RTW89_FCC][2][95] = 127,
+ [1][0][2][0][RTW89_ETSI][1][95] = 127,
+ [1][0][2][0][RTW89_ETSI][0][95] = 127,
+ [1][0][2][0][RTW89_MKK][1][95] = 127,
+ [1][0][2][0][RTW89_MKK][0][95] = 127,
+ [1][0][2][0][RTW89_IC][1][95] = 34,
+ [1][0][2][0][RTW89_KCC][1][95] = 42,
+ [1][0][2][0][RTW89_KCC][0][95] = 127,
+ [1][0][2][0][RTW89_ACMA][1][95] = 127,
+ [1][0][2][0][RTW89_ACMA][0][95] = 127,
+ [1][0][2][0][RTW89_CHILE][1][95] = 34,
+ [1][0][2][0][RTW89_QATAR][1][95] = 127,
+ [1][0][2][0][RTW89_QATAR][0][95] = 127,
+ [1][0][2][0][RTW89_UK][1][95] = 127,
+ [1][0][2][0][RTW89_UK][0][95] = 127,
+ [1][0][2][0][RTW89_FCC][1][99] = 34,
+ [1][0][2][0][RTW89_FCC][2][99] = 127,
+ [1][0][2][0][RTW89_ETSI][1][99] = 127,
+ [1][0][2][0][RTW89_ETSI][0][99] = 127,
+ [1][0][2][0][RTW89_MKK][1][99] = 127,
+ [1][0][2][0][RTW89_MKK][0][99] = 127,
+ [1][0][2][0][RTW89_IC][1][99] = 34,
+ [1][0][2][0][RTW89_KCC][1][99] = 42,
+ [1][0][2][0][RTW89_KCC][0][99] = 127,
+ [1][0][2][0][RTW89_ACMA][1][99] = 127,
+ [1][0][2][0][RTW89_ACMA][0][99] = 127,
+ [1][0][2][0][RTW89_CHILE][1][99] = 34,
+ [1][0][2][0][RTW89_QATAR][1][99] = 127,
+ [1][0][2][0][RTW89_QATAR][0][99] = 127,
+ [1][0][2][0][RTW89_UK][1][99] = 127,
+ [1][0][2][0][RTW89_UK][0][99] = 127,
+ [1][0][2][0][RTW89_FCC][1][103] = 34,
+ [1][0][2][0][RTW89_FCC][2][103] = 127,
+ [1][0][2][0][RTW89_ETSI][1][103] = 127,
+ [1][0][2][0][RTW89_ETSI][0][103] = 127,
+ [1][0][2][0][RTW89_MKK][1][103] = 127,
+ [1][0][2][0][RTW89_MKK][0][103] = 127,
+ [1][0][2][0][RTW89_IC][1][103] = 34,
+ [1][0][2][0][RTW89_KCC][1][103] = 42,
+ [1][0][2][0][RTW89_KCC][0][103] = 127,
+ [1][0][2][0][RTW89_ACMA][1][103] = 127,
+ [1][0][2][0][RTW89_ACMA][0][103] = 127,
+ [1][0][2][0][RTW89_CHILE][1][103] = 34,
+ [1][0][2][0][RTW89_QATAR][1][103] = 127,
+ [1][0][2][0][RTW89_QATAR][0][103] = 127,
+ [1][0][2][0][RTW89_UK][1][103] = 127,
+ [1][0][2][0][RTW89_UK][0][103] = 127,
+ [1][0][2][0][RTW89_FCC][1][106] = 36,
+ [1][0][2][0][RTW89_FCC][2][106] = 127,
+ [1][0][2][0][RTW89_ETSI][1][106] = 127,
+ [1][0][2][0][RTW89_ETSI][0][106] = 127,
+ [1][0][2][0][RTW89_MKK][1][106] = 127,
+ [1][0][2][0][RTW89_MKK][0][106] = 127,
+ [1][0][2][0][RTW89_IC][1][106] = 36,
+ [1][0][2][0][RTW89_KCC][1][106] = 42,
+ [1][0][2][0][RTW89_KCC][0][106] = 127,
+ [1][0][2][0][RTW89_ACMA][1][106] = 127,
+ [1][0][2][0][RTW89_ACMA][0][106] = 127,
+ [1][0][2][0][RTW89_CHILE][1][106] = 36,
+ [1][0][2][0][RTW89_QATAR][1][106] = 127,
+ [1][0][2][0][RTW89_QATAR][0][106] = 127,
+ [1][0][2][0][RTW89_UK][1][106] = 127,
+ [1][0][2][0][RTW89_UK][0][106] = 127,
+ [1][0][2][0][RTW89_FCC][1][110] = 127,
+ [1][0][2][0][RTW89_FCC][2][110] = 127,
+ [1][0][2][0][RTW89_ETSI][1][110] = 127,
+ [1][0][2][0][RTW89_ETSI][0][110] = 127,
+ [1][0][2][0][RTW89_MKK][1][110] = 127,
+ [1][0][2][0][RTW89_MKK][0][110] = 127,
+ [1][0][2][0][RTW89_IC][1][110] = 127,
+ [1][0][2][0][RTW89_KCC][1][110] = 127,
+ [1][0][2][0][RTW89_KCC][0][110] = 127,
+ [1][0][2][0][RTW89_ACMA][1][110] = 127,
+ [1][0][2][0][RTW89_ACMA][0][110] = 127,
+ [1][0][2][0][RTW89_CHILE][1][110] = 127,
+ [1][0][2][0][RTW89_QATAR][1][110] = 127,
+ [1][0][2][0][RTW89_QATAR][0][110] = 127,
+ [1][0][2][0][RTW89_UK][1][110] = 127,
+ [1][0][2][0][RTW89_UK][0][110] = 127,
+ [1][0][2][0][RTW89_FCC][1][114] = 127,
+ [1][0][2][0][RTW89_FCC][2][114] = 127,
+ [1][0][2][0][RTW89_ETSI][1][114] = 127,
+ [1][0][2][0][RTW89_ETSI][0][114] = 127,
+ [1][0][2][0][RTW89_MKK][1][114] = 127,
+ [1][0][2][0][RTW89_MKK][0][114] = 127,
+ [1][0][2][0][RTW89_IC][1][114] = 127,
+ [1][0][2][0][RTW89_KCC][1][114] = 127,
+ [1][0][2][0][RTW89_KCC][0][114] = 127,
+ [1][0][2][0][RTW89_ACMA][1][114] = 127,
+ [1][0][2][0][RTW89_ACMA][0][114] = 127,
+ [1][0][2][0][RTW89_CHILE][1][114] = 127,
+ [1][0][2][0][RTW89_QATAR][1][114] = 127,
+ [1][0][2][0][RTW89_QATAR][0][114] = 127,
+ [1][0][2][0][RTW89_UK][1][114] = 127,
+ [1][0][2][0][RTW89_UK][0][114] = 127,
+ [1][0][2][0][RTW89_FCC][1][118] = 127,
+ [1][0][2][0][RTW89_FCC][2][118] = 127,
+ [1][0][2][0][RTW89_ETSI][1][118] = 127,
+ [1][0][2][0][RTW89_ETSI][0][118] = 127,
+ [1][0][2][0][RTW89_MKK][1][118] = 127,
+ [1][0][2][0][RTW89_MKK][0][118] = 127,
+ [1][0][2][0][RTW89_IC][1][118] = 127,
+ [1][0][2][0][RTW89_KCC][1][118] = 127,
+ [1][0][2][0][RTW89_KCC][0][118] = 127,
+ [1][0][2][0][RTW89_ACMA][1][118] = 127,
+ [1][0][2][0][RTW89_ACMA][0][118] = 127,
+ [1][0][2][0][RTW89_CHILE][1][118] = 127,
+ [1][0][2][0][RTW89_QATAR][1][118] = 127,
+ [1][0][2][0][RTW89_QATAR][0][118] = 127,
+ [1][0][2][0][RTW89_UK][1][118] = 127,
+ [1][0][2][0][RTW89_UK][0][118] = 127,
+ [1][1][2][0][RTW89_FCC][1][1] = 10,
+ [1][1][2][0][RTW89_FCC][2][1] = 58,
+ [1][1][2][0][RTW89_ETSI][1][1] = 54,
+ [1][1][2][0][RTW89_ETSI][0][1] = 18,
+ [1][1][2][0][RTW89_MKK][1][1] = 52,
+ [1][1][2][0][RTW89_MKK][0][1] = 12,
+ [1][1][2][0][RTW89_IC][1][1] = 10,
+ [1][1][2][0][RTW89_KCC][1][1] = 28,
+ [1][1][2][0][RTW89_KCC][0][1] = 12,
+ [1][1][2][0][RTW89_ACMA][1][1] = 54,
+ [1][1][2][0][RTW89_ACMA][0][1] = 18,
+ [1][1][2][0][RTW89_CHILE][1][1] = 10,
+ [1][1][2][0][RTW89_QATAR][1][1] = 54,
+ [1][1][2][0][RTW89_QATAR][0][1] = 18,
+ [1][1][2][0][RTW89_UK][1][1] = 54,
+ [1][1][2][0][RTW89_UK][0][1] = 18,
+ [1][1][2][0][RTW89_FCC][1][5] = 10,
+ [1][1][2][0][RTW89_FCC][2][5] = 58,
+ [1][1][2][0][RTW89_ETSI][1][5] = 54,
+ [1][1][2][0][RTW89_ETSI][0][5] = 16,
+ [1][1][2][0][RTW89_MKK][1][5] = 52,
+ [1][1][2][0][RTW89_MKK][0][5] = 12,
+ [1][1][2][0][RTW89_IC][1][5] = 10,
+ [1][1][2][0][RTW89_KCC][1][5] = 28,
+ [1][1][2][0][RTW89_KCC][0][5] = 12,
+ [1][1][2][0][RTW89_ACMA][1][5] = 54,
+ [1][1][2][0][RTW89_ACMA][0][5] = 16,
+ [1][1][2][0][RTW89_CHILE][1][5] = 10,
+ [1][1][2][0][RTW89_QATAR][1][5] = 54,
+ [1][1][2][0][RTW89_QATAR][0][5] = 16,
+ [1][1][2][0][RTW89_UK][1][5] = 54,
+ [1][1][2][0][RTW89_UK][0][5] = 16,
+ [1][1][2][0][RTW89_FCC][1][9] = 10,
+ [1][1][2][0][RTW89_FCC][2][9] = 58,
+ [1][1][2][0][RTW89_ETSI][1][9] = 54,
+ [1][1][2][0][RTW89_ETSI][0][9] = 16,
+ [1][1][2][0][RTW89_MKK][1][9] = 52,
+ [1][1][2][0][RTW89_MKK][0][9] = 12,
+ [1][1][2][0][RTW89_IC][1][9] = 10,
+ [1][1][2][0][RTW89_KCC][1][9] = 28,
+ [1][1][2][0][RTW89_KCC][0][9] = 12,
+ [1][1][2][0][RTW89_ACMA][1][9] = 54,
+ [1][1][2][0][RTW89_ACMA][0][9] = 16,
+ [1][1][2][0][RTW89_CHILE][1][9] = 10,
+ [1][1][2][0][RTW89_QATAR][1][9] = 54,
+ [1][1][2][0][RTW89_QATAR][0][9] = 16,
+ [1][1][2][0][RTW89_UK][1][9] = 54,
+ [1][1][2][0][RTW89_UK][0][9] = 16,
+ [1][1][2][0][RTW89_FCC][1][13] = 10,
+ [1][1][2][0][RTW89_FCC][2][13] = 58,
+ [1][1][2][0][RTW89_ETSI][1][13] = 54,
+ [1][1][2][0][RTW89_ETSI][0][13] = 16,
+ [1][1][2][0][RTW89_MKK][1][13] = 52,
+ [1][1][2][0][RTW89_MKK][0][13] = 12,
+ [1][1][2][0][RTW89_IC][1][13] = 10,
+ [1][1][2][0][RTW89_KCC][1][13] = 28,
+ [1][1][2][0][RTW89_KCC][0][13] = 12,
+ [1][1][2][0][RTW89_ACMA][1][13] = 54,
+ [1][1][2][0][RTW89_ACMA][0][13] = 16,
+ [1][1][2][0][RTW89_CHILE][1][13] = 10,
+ [1][1][2][0][RTW89_QATAR][1][13] = 54,
+ [1][1][2][0][RTW89_QATAR][0][13] = 16,
+ [1][1][2][0][RTW89_UK][1][13] = 54,
+ [1][1][2][0][RTW89_UK][0][13] = 16,
+ [1][1][2][0][RTW89_FCC][1][16] = 10,
+ [1][1][2][0][RTW89_FCC][2][16] = 58,
+ [1][1][2][0][RTW89_ETSI][1][16] = 54,
+ [1][1][2][0][RTW89_ETSI][0][16] = 16,
+ [1][1][2][0][RTW89_MKK][1][16] = 52,
+ [1][1][2][0][RTW89_MKK][0][16] = 12,
+ [1][1][2][0][RTW89_IC][1][16] = 10,
+ [1][1][2][0][RTW89_KCC][1][16] = 28,
+ [1][1][2][0][RTW89_KCC][0][16] = 12,
+ [1][1][2][0][RTW89_ACMA][1][16] = 54,
+ [1][1][2][0][RTW89_ACMA][0][16] = 16,
+ [1][1][2][0][RTW89_CHILE][1][16] = 10,
+ [1][1][2][0][RTW89_QATAR][1][16] = 54,
+ [1][1][2][0][RTW89_QATAR][0][16] = 16,
+ [1][1][2][0][RTW89_UK][1][16] = 54,
+ [1][1][2][0][RTW89_UK][0][16] = 16,
+ [1][1][2][0][RTW89_FCC][1][20] = 10,
+ [1][1][2][0][RTW89_FCC][2][20] = 58,
+ [1][1][2][0][RTW89_ETSI][1][20] = 54,
+ [1][1][2][0][RTW89_ETSI][0][20] = 16,
+ [1][1][2][0][RTW89_MKK][1][20] = 52,
+ [1][1][2][0][RTW89_MKK][0][20] = 12,
+ [1][1][2][0][RTW89_IC][1][20] = 10,
+ [1][1][2][0][RTW89_KCC][1][20] = 28,
+ [1][1][2][0][RTW89_KCC][0][20] = 12,
+ [1][1][2][0][RTW89_ACMA][1][20] = 54,
+ [1][1][2][0][RTW89_ACMA][0][20] = 16,
+ [1][1][2][0][RTW89_CHILE][1][20] = 10,
+ [1][1][2][0][RTW89_QATAR][1][20] = 54,
+ [1][1][2][0][RTW89_QATAR][0][20] = 16,
+ [1][1][2][0][RTW89_UK][1][20] = 54,
+ [1][1][2][0][RTW89_UK][0][20] = 16,
+ [1][1][2][0][RTW89_FCC][1][24] = 10,
+ [1][1][2][0][RTW89_FCC][2][24] = 70,
+ [1][1][2][0][RTW89_ETSI][1][24] = 54,
+ [1][1][2][0][RTW89_ETSI][0][24] = 16,
+ [1][1][2][0][RTW89_MKK][1][24] = 54,
+ [1][1][2][0][RTW89_MKK][0][24] = 14,
+ [1][1][2][0][RTW89_IC][1][24] = 10,
+ [1][1][2][0][RTW89_KCC][1][24] = 28,
+ [1][1][2][0][RTW89_KCC][0][24] = 12,
+ [1][1][2][0][RTW89_ACMA][1][24] = 54,
+ [1][1][2][0][RTW89_ACMA][0][24] = 16,
+ [1][1][2][0][RTW89_CHILE][1][24] = 10,
+ [1][1][2][0][RTW89_QATAR][1][24] = 54,
+ [1][1][2][0][RTW89_QATAR][0][24] = 16,
+ [1][1][2][0][RTW89_UK][1][24] = 54,
+ [1][1][2][0][RTW89_UK][0][24] = 16,
+ [1][1][2][0][RTW89_FCC][1][28] = 10,
+ [1][1][2][0][RTW89_FCC][2][28] = 70,
+ [1][1][2][0][RTW89_ETSI][1][28] = 54,
+ [1][1][2][0][RTW89_ETSI][0][28] = 16,
+ [1][1][2][0][RTW89_MKK][1][28] = 52,
+ [1][1][2][0][RTW89_MKK][0][28] = 14,
+ [1][1][2][0][RTW89_IC][1][28] = 10,
+ [1][1][2][0][RTW89_KCC][1][28] = 28,
+ [1][1][2][0][RTW89_KCC][0][28] = 14,
+ [1][1][2][0][RTW89_ACMA][1][28] = 54,
+ [1][1][2][0][RTW89_ACMA][0][28] = 16,
+ [1][1][2][0][RTW89_CHILE][1][28] = 10,
+ [1][1][2][0][RTW89_QATAR][1][28] = 54,
+ [1][1][2][0][RTW89_QATAR][0][28] = 16,
+ [1][1][2][0][RTW89_UK][1][28] = 54,
+ [1][1][2][0][RTW89_UK][0][28] = 16,
+ [1][1][2][0][RTW89_FCC][1][31] = 10,
+ [1][1][2][0][RTW89_FCC][2][31] = 70,
+ [1][1][2][0][RTW89_ETSI][1][31] = 54,
+ [1][1][2][0][RTW89_ETSI][0][31] = 16,
+ [1][1][2][0][RTW89_MKK][1][31] = 52,
+ [1][1][2][0][RTW89_MKK][0][31] = 14,
+ [1][1][2][0][RTW89_IC][1][31] = 10,
+ [1][1][2][0][RTW89_KCC][1][31] = 28,
+ [1][1][2][0][RTW89_KCC][0][31] = 14,
+ [1][1][2][0][RTW89_ACMA][1][31] = 54,
+ [1][1][2][0][RTW89_ACMA][0][31] = 16,
+ [1][1][2][0][RTW89_CHILE][1][31] = 10,
+ [1][1][2][0][RTW89_QATAR][1][31] = 54,
+ [1][1][2][0][RTW89_QATAR][0][31] = 16,
+ [1][1][2][0][RTW89_UK][1][31] = 54,
+ [1][1][2][0][RTW89_UK][0][31] = 16,
+ [1][1][2][0][RTW89_FCC][1][35] = 10,
+ [1][1][2][0][RTW89_FCC][2][35] = 70,
+ [1][1][2][0][RTW89_ETSI][1][35] = 54,
+ [1][1][2][0][RTW89_ETSI][0][35] = 16,
+ [1][1][2][0][RTW89_MKK][1][35] = 52,
+ [1][1][2][0][RTW89_MKK][0][35] = 14,
+ [1][1][2][0][RTW89_IC][1][35] = 10,
+ [1][1][2][0][RTW89_KCC][1][35] = 28,
+ [1][1][2][0][RTW89_KCC][0][35] = 14,
+ [1][1][2][0][RTW89_ACMA][1][35] = 54,
+ [1][1][2][0][RTW89_ACMA][0][35] = 16,
+ [1][1][2][0][RTW89_CHILE][1][35] = 10,
+ [1][1][2][0][RTW89_QATAR][1][35] = 54,
+ [1][1][2][0][RTW89_QATAR][0][35] = 16,
+ [1][1][2][0][RTW89_UK][1][35] = 54,
+ [1][1][2][0][RTW89_UK][0][35] = 16,
+ [1][1][2][0][RTW89_FCC][1][39] = 10,
+ [1][1][2][0][RTW89_FCC][2][39] = 70,
+ [1][1][2][0][RTW89_ETSI][1][39] = 54,
+ [1][1][2][0][RTW89_ETSI][0][39] = 16,
+ [1][1][2][0][RTW89_MKK][1][39] = 52,
+ [1][1][2][0][RTW89_MKK][0][39] = 14,
+ [1][1][2][0][RTW89_IC][1][39] = 10,
+ [1][1][2][0][RTW89_KCC][1][39] = 28,
+ [1][1][2][0][RTW89_KCC][0][39] = 14,
+ [1][1][2][0][RTW89_ACMA][1][39] = 54,
+ [1][1][2][0][RTW89_ACMA][0][39] = 16,
+ [1][1][2][0][RTW89_CHILE][1][39] = 10,
+ [1][1][2][0][RTW89_QATAR][1][39] = 54,
+ [1][1][2][0][RTW89_QATAR][0][39] = 16,
+ [1][1][2][0][RTW89_UK][1][39] = 54,
+ [1][1][2][0][RTW89_UK][0][39] = 16,
+ [1][1][2][0][RTW89_FCC][1][43] = 10,
+ [1][1][2][0][RTW89_FCC][2][43] = 70,
+ [1][1][2][0][RTW89_ETSI][1][43] = 54,
+ [1][1][2][0][RTW89_ETSI][0][43] = 16,
+ [1][1][2][0][RTW89_MKK][1][43] = 52,
+ [1][1][2][0][RTW89_MKK][0][43] = 14,
+ [1][1][2][0][RTW89_IC][1][43] = 10,
+ [1][1][2][0][RTW89_KCC][1][43] = 28,
+ [1][1][2][0][RTW89_KCC][0][43] = 14,
+ [1][1][2][0][RTW89_ACMA][1][43] = 54,
+ [1][1][2][0][RTW89_ACMA][0][43] = 16,
+ [1][1][2][0][RTW89_CHILE][1][43] = 10,
+ [1][1][2][0][RTW89_QATAR][1][43] = 54,
+ [1][1][2][0][RTW89_QATAR][0][43] = 16,
+ [1][1][2][0][RTW89_UK][1][43] = 54,
+ [1][1][2][0][RTW89_UK][0][43] = 16,
+ [1][1][2][0][RTW89_FCC][1][46] = 12,
+ [1][1][2][0][RTW89_FCC][2][46] = 127,
+ [1][1][2][0][RTW89_ETSI][1][46] = 127,
+ [1][1][2][0][RTW89_ETSI][0][46] = 127,
+ [1][1][2][0][RTW89_MKK][1][46] = 127,
+ [1][1][2][0][RTW89_MKK][0][46] = 127,
+ [1][1][2][0][RTW89_IC][1][46] = 12,
+ [1][1][2][0][RTW89_KCC][1][46] = 28,
+ [1][1][2][0][RTW89_KCC][0][46] = 127,
+ [1][1][2][0][RTW89_ACMA][1][46] = 127,
+ [1][1][2][0][RTW89_ACMA][0][46] = 127,
+ [1][1][2][0][RTW89_CHILE][1][46] = 12,
+ [1][1][2][0][RTW89_QATAR][1][46] = 127,
+ [1][1][2][0][RTW89_QATAR][0][46] = 127,
+ [1][1][2][0][RTW89_UK][1][46] = 127,
+ [1][1][2][0][RTW89_UK][0][46] = 127,
+ [1][1][2][0][RTW89_FCC][1][50] = 12,
+ [1][1][2][0][RTW89_FCC][2][50] = 127,
+ [1][1][2][0][RTW89_ETSI][1][50] = 127,
+ [1][1][2][0][RTW89_ETSI][0][50] = 127,
+ [1][1][2][0][RTW89_MKK][1][50] = 127,
+ [1][1][2][0][RTW89_MKK][0][50] = 127,
+ [1][1][2][0][RTW89_IC][1][50] = 12,
+ [1][1][2][0][RTW89_KCC][1][50] = 28,
+ [1][1][2][0][RTW89_KCC][0][50] = 127,
+ [1][1][2][0][RTW89_ACMA][1][50] = 127,
+ [1][1][2][0][RTW89_ACMA][0][50] = 127,
+ [1][1][2][0][RTW89_CHILE][1][50] = 12,
+ [1][1][2][0][RTW89_QATAR][1][50] = 127,
+ [1][1][2][0][RTW89_QATAR][0][50] = 127,
+ [1][1][2][0][RTW89_UK][1][50] = 127,
+ [1][1][2][0][RTW89_UK][0][50] = 127,
+ [1][1][2][0][RTW89_FCC][1][54] = 10,
+ [1][1][2][0][RTW89_FCC][2][54] = 127,
+ [1][1][2][0][RTW89_ETSI][1][54] = 127,
+ [1][1][2][0][RTW89_ETSI][0][54] = 127,
+ [1][1][2][0][RTW89_MKK][1][54] = 127,
+ [1][1][2][0][RTW89_MKK][0][54] = 127,
+ [1][1][2][0][RTW89_IC][1][54] = 10,
+ [1][1][2][0][RTW89_KCC][1][54] = 28,
+ [1][1][2][0][RTW89_KCC][0][54] = 127,
+ [1][1][2][0][RTW89_ACMA][1][54] = 127,
+ [1][1][2][0][RTW89_ACMA][0][54] = 127,
+ [1][1][2][0][RTW89_CHILE][1][54] = 10,
+ [1][1][2][0][RTW89_QATAR][1][54] = 127,
+ [1][1][2][0][RTW89_QATAR][0][54] = 127,
+ [1][1][2][0][RTW89_UK][1][54] = 127,
+ [1][1][2][0][RTW89_UK][0][54] = 127,
+ [1][1][2][0][RTW89_FCC][1][58] = 10,
+ [1][1][2][0][RTW89_FCC][2][58] = 66,
+ [1][1][2][0][RTW89_ETSI][1][58] = 127,
+ [1][1][2][0][RTW89_ETSI][0][58] = 127,
+ [1][1][2][0][RTW89_MKK][1][58] = 127,
+ [1][1][2][0][RTW89_MKK][0][58] = 127,
+ [1][1][2][0][RTW89_IC][1][58] = 10,
+ [1][1][2][0][RTW89_KCC][1][58] = 28,
+ [1][1][2][0][RTW89_KCC][0][58] = 127,
+ [1][1][2][0][RTW89_ACMA][1][58] = 127,
+ [1][1][2][0][RTW89_ACMA][0][58] = 127,
+ [1][1][2][0][RTW89_CHILE][1][58] = 10,
+ [1][1][2][0][RTW89_QATAR][1][58] = 127,
+ [1][1][2][0][RTW89_QATAR][0][58] = 127,
+ [1][1][2][0][RTW89_UK][1][58] = 127,
+ [1][1][2][0][RTW89_UK][0][58] = 127,
+ [1][1][2][0][RTW89_FCC][1][61] = 10,
+ [1][1][2][0][RTW89_FCC][2][61] = 66,
+ [1][1][2][0][RTW89_ETSI][1][61] = 127,
+ [1][1][2][0][RTW89_ETSI][0][61] = 127,
+ [1][1][2][0][RTW89_MKK][1][61] = 127,
+ [1][1][2][0][RTW89_MKK][0][61] = 127,
+ [1][1][2][0][RTW89_IC][1][61] = 10,
+ [1][1][2][0][RTW89_KCC][1][61] = 28,
+ [1][1][2][0][RTW89_KCC][0][61] = 127,
+ [1][1][2][0][RTW89_ACMA][1][61] = 127,
+ [1][1][2][0][RTW89_ACMA][0][61] = 127,
+ [1][1][2][0][RTW89_CHILE][1][61] = 10,
+ [1][1][2][0][RTW89_QATAR][1][61] = 127,
+ [1][1][2][0][RTW89_QATAR][0][61] = 127,
+ [1][1][2][0][RTW89_UK][1][61] = 127,
+ [1][1][2][0][RTW89_UK][0][61] = 127,
+ [1][1][2][0][RTW89_FCC][1][65] = 10,
+ [1][1][2][0][RTW89_FCC][2][65] = 66,
+ [1][1][2][0][RTW89_ETSI][1][65] = 127,
+ [1][1][2][0][RTW89_ETSI][0][65] = 127,
+ [1][1][2][0][RTW89_MKK][1][65] = 127,
+ [1][1][2][0][RTW89_MKK][0][65] = 127,
+ [1][1][2][0][RTW89_IC][1][65] = 10,
+ [1][1][2][0][RTW89_KCC][1][65] = 28,
+ [1][1][2][0][RTW89_KCC][0][65] = 127,
+ [1][1][2][0][RTW89_ACMA][1][65] = 127,
+ [1][1][2][0][RTW89_ACMA][0][65] = 127,
+ [1][1][2][0][RTW89_CHILE][1][65] = 10,
+ [1][1][2][0][RTW89_QATAR][1][65] = 127,
+ [1][1][2][0][RTW89_QATAR][0][65] = 127,
+ [1][1][2][0][RTW89_UK][1][65] = 127,
+ [1][1][2][0][RTW89_UK][0][65] = 127,
+ [1][1][2][0][RTW89_FCC][1][69] = 10,
+ [1][1][2][0][RTW89_FCC][2][69] = 66,
+ [1][1][2][0][RTW89_ETSI][1][69] = 127,
+ [1][1][2][0][RTW89_ETSI][0][69] = 127,
+ [1][1][2][0][RTW89_MKK][1][69] = 127,
+ [1][1][2][0][RTW89_MKK][0][69] = 127,
+ [1][1][2][0][RTW89_IC][1][69] = 10,
+ [1][1][2][0][RTW89_KCC][1][69] = 28,
+ [1][1][2][0][RTW89_KCC][0][69] = 127,
+ [1][1][2][0][RTW89_ACMA][1][69] = 127,
+ [1][1][2][0][RTW89_ACMA][0][69] = 127,
+ [1][1][2][0][RTW89_CHILE][1][69] = 10,
+ [1][1][2][0][RTW89_QATAR][1][69] = 127,
+ [1][1][2][0][RTW89_QATAR][0][69] = 127,
+ [1][1][2][0][RTW89_UK][1][69] = 127,
+ [1][1][2][0][RTW89_UK][0][69] = 127,
+ [1][1][2][0][RTW89_FCC][1][73] = 10,
+ [1][1][2][0][RTW89_FCC][2][73] = 66,
+ [1][1][2][0][RTW89_ETSI][1][73] = 127,
+ [1][1][2][0][RTW89_ETSI][0][73] = 127,
+ [1][1][2][0][RTW89_MKK][1][73] = 127,
+ [1][1][2][0][RTW89_MKK][0][73] = 127,
+ [1][1][2][0][RTW89_IC][1][73] = 10,
+ [1][1][2][0][RTW89_KCC][1][73] = 28,
+ [1][1][2][0][RTW89_KCC][0][73] = 127,
+ [1][1][2][0][RTW89_ACMA][1][73] = 127,
+ [1][1][2][0][RTW89_ACMA][0][73] = 127,
+ [1][1][2][0][RTW89_CHILE][1][73] = 10,
+ [1][1][2][0][RTW89_QATAR][1][73] = 127,
+ [1][1][2][0][RTW89_QATAR][0][73] = 127,
+ [1][1][2][0][RTW89_UK][1][73] = 127,
+ [1][1][2][0][RTW89_UK][0][73] = 127,
+ [1][1][2][0][RTW89_FCC][1][76] = 10,
+ [1][1][2][0][RTW89_FCC][2][76] = 66,
+ [1][1][2][0][RTW89_ETSI][1][76] = 127,
+ [1][1][2][0][RTW89_ETSI][0][76] = 127,
+ [1][1][2][0][RTW89_MKK][1][76] = 127,
+ [1][1][2][0][RTW89_MKK][0][76] = 127,
+ [1][1][2][0][RTW89_IC][1][76] = 10,
+ [1][1][2][0][RTW89_KCC][1][76] = 28,
+ [1][1][2][0][RTW89_KCC][0][76] = 127,
+ [1][1][2][0][RTW89_ACMA][1][76] = 127,
+ [1][1][2][0][RTW89_ACMA][0][76] = 127,
+ [1][1][2][0][RTW89_CHILE][1][76] = 10,
+ [1][1][2][0][RTW89_QATAR][1][76] = 127,
+ [1][1][2][0][RTW89_QATAR][0][76] = 127,
+ [1][1][2][0][RTW89_UK][1][76] = 127,
+ [1][1][2][0][RTW89_UK][0][76] = 127,
+ [1][1][2][0][RTW89_FCC][1][80] = 10,
+ [1][1][2][0][RTW89_FCC][2][80] = 66,
+ [1][1][2][0][RTW89_ETSI][1][80] = 127,
+ [1][1][2][0][RTW89_ETSI][0][80] = 127,
+ [1][1][2][0][RTW89_MKK][1][80] = 127,
+ [1][1][2][0][RTW89_MKK][0][80] = 127,
+ [1][1][2][0][RTW89_IC][1][80] = 10,
+ [1][1][2][0][RTW89_KCC][1][80] = 32,
+ [1][1][2][0][RTW89_KCC][0][80] = 127,
+ [1][1][2][0][RTW89_ACMA][1][80] = 127,
+ [1][1][2][0][RTW89_ACMA][0][80] = 127,
+ [1][1][2][0][RTW89_CHILE][1][80] = 10,
+ [1][1][2][0][RTW89_QATAR][1][80] = 127,
+ [1][1][2][0][RTW89_QATAR][0][80] = 127,
+ [1][1][2][0][RTW89_UK][1][80] = 127,
+ [1][1][2][0][RTW89_UK][0][80] = 127,
+ [1][1][2][0][RTW89_FCC][1][84] = 10,
+ [1][1][2][0][RTW89_FCC][2][84] = 66,
+ [1][1][2][0][RTW89_ETSI][1][84] = 127,
+ [1][1][2][0][RTW89_ETSI][0][84] = 127,
+ [1][1][2][0][RTW89_MKK][1][84] = 127,
+ [1][1][2][0][RTW89_MKK][0][84] = 127,
+ [1][1][2][0][RTW89_IC][1][84] = 10,
+ [1][1][2][0][RTW89_KCC][1][84] = 32,
+ [1][1][2][0][RTW89_KCC][0][84] = 127,
+ [1][1][2][0][RTW89_ACMA][1][84] = 127,
+ [1][1][2][0][RTW89_ACMA][0][84] = 127,
+ [1][1][2][0][RTW89_CHILE][1][84] = 10,
+ [1][1][2][0][RTW89_QATAR][1][84] = 127,
+ [1][1][2][0][RTW89_QATAR][0][84] = 127,
+ [1][1][2][0][RTW89_UK][1][84] = 127,
+ [1][1][2][0][RTW89_UK][0][84] = 127,
+ [1][1][2][0][RTW89_FCC][1][88] = 10,
+ [1][1][2][0][RTW89_FCC][2][88] = 127,
+ [1][1][2][0][RTW89_ETSI][1][88] = 127,
+ [1][1][2][0][RTW89_ETSI][0][88] = 127,
+ [1][1][2][0][RTW89_MKK][1][88] = 127,
+ [1][1][2][0][RTW89_MKK][0][88] = 127,
+ [1][1][2][0][RTW89_IC][1][88] = 10,
+ [1][1][2][0][RTW89_KCC][1][88] = 32,
+ [1][1][2][0][RTW89_KCC][0][88] = 127,
+ [1][1][2][0][RTW89_ACMA][1][88] = 127,
+ [1][1][2][0][RTW89_ACMA][0][88] = 127,
+ [1][1][2][0][RTW89_CHILE][1][88] = 10,
+ [1][1][2][0][RTW89_QATAR][1][88] = 127,
+ [1][1][2][0][RTW89_QATAR][0][88] = 127,
+ [1][1][2][0][RTW89_UK][1][88] = 127,
+ [1][1][2][0][RTW89_UK][0][88] = 127,
+ [1][1][2][0][RTW89_FCC][1][91] = 12,
+ [1][1][2][0][RTW89_FCC][2][91] = 127,
+ [1][1][2][0][RTW89_ETSI][1][91] = 127,
+ [1][1][2][0][RTW89_ETSI][0][91] = 127,
+ [1][1][2][0][RTW89_MKK][1][91] = 127,
+ [1][1][2][0][RTW89_MKK][0][91] = 127,
+ [1][1][2][0][RTW89_IC][1][91] = 12,
+ [1][1][2][0][RTW89_KCC][1][91] = 32,
+ [1][1][2][0][RTW89_KCC][0][91] = 127,
+ [1][1][2][0][RTW89_ACMA][1][91] = 127,
+ [1][1][2][0][RTW89_ACMA][0][91] = 127,
+ [1][1][2][0][RTW89_CHILE][1][91] = 12,
+ [1][1][2][0][RTW89_QATAR][1][91] = 127,
+ [1][1][2][0][RTW89_QATAR][0][91] = 127,
+ [1][1][2][0][RTW89_UK][1][91] = 127,
+ [1][1][2][0][RTW89_UK][0][91] = 127,
+ [1][1][2][0][RTW89_FCC][1][95] = 10,
+ [1][1][2][0][RTW89_FCC][2][95] = 127,
+ [1][1][2][0][RTW89_ETSI][1][95] = 127,
+ [1][1][2][0][RTW89_ETSI][0][95] = 127,
+ [1][1][2][0][RTW89_MKK][1][95] = 127,
+ [1][1][2][0][RTW89_MKK][0][95] = 127,
+ [1][1][2][0][RTW89_IC][1][95] = 10,
+ [1][1][2][0][RTW89_KCC][1][95] = 32,
+ [1][1][2][0][RTW89_KCC][0][95] = 127,
+ [1][1][2][0][RTW89_ACMA][1][95] = 127,
+ [1][1][2][0][RTW89_ACMA][0][95] = 127,
+ [1][1][2][0][RTW89_CHILE][1][95] = 10,
+ [1][1][2][0][RTW89_QATAR][1][95] = 127,
+ [1][1][2][0][RTW89_QATAR][0][95] = 127,
+ [1][1][2][0][RTW89_UK][1][95] = 127,
+ [1][1][2][0][RTW89_UK][0][95] = 127,
+ [1][1][2][0][RTW89_FCC][1][99] = 10,
+ [1][1][2][0][RTW89_FCC][2][99] = 127,
+ [1][1][2][0][RTW89_ETSI][1][99] = 127,
+ [1][1][2][0][RTW89_ETSI][0][99] = 127,
+ [1][1][2][0][RTW89_MKK][1][99] = 127,
+ [1][1][2][0][RTW89_MKK][0][99] = 127,
+ [1][1][2][0][RTW89_IC][1][99] = 10,
+ [1][1][2][0][RTW89_KCC][1][99] = 32,
+ [1][1][2][0][RTW89_KCC][0][99] = 127,
+ [1][1][2][0][RTW89_ACMA][1][99] = 127,
+ [1][1][2][0][RTW89_ACMA][0][99] = 127,
+ [1][1][2][0][RTW89_CHILE][1][99] = 10,
+ [1][1][2][0][RTW89_QATAR][1][99] = 127,
+ [1][1][2][0][RTW89_QATAR][0][99] = 127,
+ [1][1][2][0][RTW89_UK][1][99] = 127,
+ [1][1][2][0][RTW89_UK][0][99] = 127,
+ [1][1][2][0][RTW89_FCC][1][103] = 10,
+ [1][1][2][0][RTW89_FCC][2][103] = 127,
+ [1][1][2][0][RTW89_ETSI][1][103] = 127,
+ [1][1][2][0][RTW89_ETSI][0][103] = 127,
+ [1][1][2][0][RTW89_MKK][1][103] = 127,
+ [1][1][2][0][RTW89_MKK][0][103] = 127,
+ [1][1][2][0][RTW89_IC][1][103] = 10,
+ [1][1][2][0][RTW89_KCC][1][103] = 32,
+ [1][1][2][0][RTW89_KCC][0][103] = 127,
+ [1][1][2][0][RTW89_ACMA][1][103] = 127,
+ [1][1][2][0][RTW89_ACMA][0][103] = 127,
+ [1][1][2][0][RTW89_CHILE][1][103] = 10,
+ [1][1][2][0][RTW89_QATAR][1][103] = 127,
+ [1][1][2][0][RTW89_QATAR][0][103] = 127,
+ [1][1][2][0][RTW89_UK][1][103] = 127,
+ [1][1][2][0][RTW89_UK][0][103] = 127,
+ [1][1][2][0][RTW89_FCC][1][106] = 12,
+ [1][1][2][0][RTW89_FCC][2][106] = 127,
+ [1][1][2][0][RTW89_ETSI][1][106] = 127,
+ [1][1][2][0][RTW89_ETSI][0][106] = 127,
+ [1][1][2][0][RTW89_MKK][1][106] = 127,
+ [1][1][2][0][RTW89_MKK][0][106] = 127,
+ [1][1][2][0][RTW89_IC][1][106] = 12,
+ [1][1][2][0][RTW89_KCC][1][106] = 32,
+ [1][1][2][0][RTW89_KCC][0][106] = 127,
+ [1][1][2][0][RTW89_ACMA][1][106] = 127,
+ [1][1][2][0][RTW89_ACMA][0][106] = 127,
+ [1][1][2][0][RTW89_CHILE][1][106] = 12,
+ [1][1][2][0][RTW89_QATAR][1][106] = 127,
+ [1][1][2][0][RTW89_QATAR][0][106] = 127,
+ [1][1][2][0][RTW89_UK][1][106] = 127,
+ [1][1][2][0][RTW89_UK][0][106] = 127,
+ [1][1][2][0][RTW89_FCC][1][110] = 127,
+ [1][1][2][0][RTW89_FCC][2][110] = 127,
+ [1][1][2][0][RTW89_ETSI][1][110] = 127,
+ [1][1][2][0][RTW89_ETSI][0][110] = 127,
+ [1][1][2][0][RTW89_MKK][1][110] = 127,
+ [1][1][2][0][RTW89_MKK][0][110] = 127,
+ [1][1][2][0][RTW89_IC][1][110] = 127,
+ [1][1][2][0][RTW89_KCC][1][110] = 127,
+ [1][1][2][0][RTW89_KCC][0][110] = 127,
+ [1][1][2][0][RTW89_ACMA][1][110] = 127,
+ [1][1][2][0][RTW89_ACMA][0][110] = 127,
+ [1][1][2][0][RTW89_CHILE][1][110] = 127,
+ [1][1][2][0][RTW89_QATAR][1][110] = 127,
+ [1][1][2][0][RTW89_QATAR][0][110] = 127,
+ [1][1][2][0][RTW89_UK][1][110] = 127,
+ [1][1][2][0][RTW89_UK][0][110] = 127,
+ [1][1][2][0][RTW89_FCC][1][114] = 127,
+ [1][1][2][0][RTW89_FCC][2][114] = 127,
+ [1][1][2][0][RTW89_ETSI][1][114] = 127,
+ [1][1][2][0][RTW89_ETSI][0][114] = 127,
+ [1][1][2][0][RTW89_MKK][1][114] = 127,
+ [1][1][2][0][RTW89_MKK][0][114] = 127,
+ [1][1][2][0][RTW89_IC][1][114] = 127,
+ [1][1][2][0][RTW89_KCC][1][114] = 127,
+ [1][1][2][0][RTW89_KCC][0][114] = 127,
+ [1][1][2][0][RTW89_ACMA][1][114] = 127,
+ [1][1][2][0][RTW89_ACMA][0][114] = 127,
+ [1][1][2][0][RTW89_CHILE][1][114] = 127,
+ [1][1][2][0][RTW89_QATAR][1][114] = 127,
+ [1][1][2][0][RTW89_QATAR][0][114] = 127,
+ [1][1][2][0][RTW89_UK][1][114] = 127,
+ [1][1][2][0][RTW89_UK][0][114] = 127,
+ [1][1][2][0][RTW89_FCC][1][118] = 127,
+ [1][1][2][0][RTW89_FCC][2][118] = 127,
+ [1][1][2][0][RTW89_ETSI][1][118] = 127,
+ [1][1][2][0][RTW89_ETSI][0][118] = 127,
+ [1][1][2][0][RTW89_MKK][1][118] = 127,
+ [1][1][2][0][RTW89_MKK][0][118] = 127,
+ [1][1][2][0][RTW89_IC][1][118] = 127,
+ [1][1][2][0][RTW89_KCC][1][118] = 127,
+ [1][1][2][0][RTW89_KCC][0][118] = 127,
+ [1][1][2][0][RTW89_ACMA][1][118] = 127,
+ [1][1][2][0][RTW89_ACMA][0][118] = 127,
+ [1][1][2][0][RTW89_CHILE][1][118] = 127,
+ [1][1][2][0][RTW89_QATAR][1][118] = 127,
+ [1][1][2][0][RTW89_QATAR][0][118] = 127,
+ [1][1][2][0][RTW89_UK][1][118] = 127,
+ [1][1][2][0][RTW89_UK][0][118] = 127,
+ [1][1][2][1][RTW89_FCC][1][1] = 10,
+ [1][1][2][1][RTW89_FCC][2][1] = 58,
+ [1][1][2][1][RTW89_ETSI][1][1] = 42,
+ [1][1][2][1][RTW89_ETSI][0][1] = 6,
+ [1][1][2][1][RTW89_MKK][1][1] = 52,
+ [1][1][2][1][RTW89_MKK][0][1] = 12,
+ [1][1][2][1][RTW89_IC][1][1] = 10,
+ [1][1][2][1][RTW89_KCC][1][1] = 28,
+ [1][1][2][1][RTW89_KCC][0][1] = 12,
+ [1][1][2][1][RTW89_ACMA][1][1] = 42,
+ [1][1][2][1][RTW89_ACMA][0][1] = 6,
+ [1][1][2][1][RTW89_CHILE][1][1] = 10,
+ [1][1][2][1][RTW89_QATAR][1][1] = 42,
+ [1][1][2][1][RTW89_QATAR][0][1] = 6,
+ [1][1][2][1][RTW89_UK][1][1] = 42,
+ [1][1][2][1][RTW89_UK][0][1] = 6,
+ [1][1][2][1][RTW89_FCC][1][5] = 10,
+ [1][1][2][1][RTW89_FCC][2][5] = 58,
+ [1][1][2][1][RTW89_ETSI][1][5] = 42,
+ [1][1][2][1][RTW89_ETSI][0][5] = 6,
+ [1][1][2][1][RTW89_MKK][1][5] = 52,
+ [1][1][2][1][RTW89_MKK][0][5] = 12,
+ [1][1][2][1][RTW89_IC][1][5] = 10,
+ [1][1][2][1][RTW89_KCC][1][5] = 28,
+ [1][1][2][1][RTW89_KCC][0][5] = 12,
+ [1][1][2][1][RTW89_ACMA][1][5] = 42,
+ [1][1][2][1][RTW89_ACMA][0][5] = 6,
+ [1][1][2][1][RTW89_CHILE][1][5] = 10,
+ [1][1][2][1][RTW89_QATAR][1][5] = 42,
+ [1][1][2][1][RTW89_QATAR][0][5] = 6,
+ [1][1][2][1][RTW89_UK][1][5] = 42,
+ [1][1][2][1][RTW89_UK][0][5] = 6,
+ [1][1][2][1][RTW89_FCC][1][9] = 10,
+ [1][1][2][1][RTW89_FCC][2][9] = 58,
+ [1][1][2][1][RTW89_ETSI][1][9] = 42,
+ [1][1][2][1][RTW89_ETSI][0][9] = 6,
+ [1][1][2][1][RTW89_MKK][1][9] = 52,
+ [1][1][2][1][RTW89_MKK][0][9] = 12,
+ [1][1][2][1][RTW89_IC][1][9] = 10,
+ [1][1][2][1][RTW89_KCC][1][9] = 28,
+ [1][1][2][1][RTW89_KCC][0][9] = 12,
+ [1][1][2][1][RTW89_ACMA][1][9] = 42,
+ [1][1][2][1][RTW89_ACMA][0][9] = 6,
+ [1][1][2][1][RTW89_CHILE][1][9] = 10,
+ [1][1][2][1][RTW89_QATAR][1][9] = 42,
+ [1][1][2][1][RTW89_QATAR][0][9] = 6,
+ [1][1][2][1][RTW89_UK][1][9] = 42,
+ [1][1][2][1][RTW89_UK][0][9] = 6,
+ [1][1][2][1][RTW89_FCC][1][13] = 10,
+ [1][1][2][1][RTW89_FCC][2][13] = 58,
+ [1][1][2][1][RTW89_ETSI][1][13] = 42,
+ [1][1][2][1][RTW89_ETSI][0][13] = 6,
+ [1][1][2][1][RTW89_MKK][1][13] = 52,
+ [1][1][2][1][RTW89_MKK][0][13] = 12,
+ [1][1][2][1][RTW89_IC][1][13] = 10,
+ [1][1][2][1][RTW89_KCC][1][13] = 28,
+ [1][1][2][1][RTW89_KCC][0][13] = 12,
+ [1][1][2][1][RTW89_ACMA][1][13] = 42,
+ [1][1][2][1][RTW89_ACMA][0][13] = 6,
+ [1][1][2][1][RTW89_CHILE][1][13] = 10,
+ [1][1][2][1][RTW89_QATAR][1][13] = 42,
+ [1][1][2][1][RTW89_QATAR][0][13] = 6,
+ [1][1][2][1][RTW89_UK][1][13] = 42,
+ [1][1][2][1][RTW89_UK][0][13] = 6,
+ [1][1][2][1][RTW89_FCC][1][16] = 10,
+ [1][1][2][1][RTW89_FCC][2][16] = 58,
+ [1][1][2][1][RTW89_ETSI][1][16] = 42,
+ [1][1][2][1][RTW89_ETSI][0][16] = 6,
+ [1][1][2][1][RTW89_MKK][1][16] = 52,
+ [1][1][2][1][RTW89_MKK][0][16] = 12,
+ [1][1][2][1][RTW89_IC][1][16] = 10,
+ [1][1][2][1][RTW89_KCC][1][16] = 28,
+ [1][1][2][1][RTW89_KCC][0][16] = 12,
+ [1][1][2][1][RTW89_ACMA][1][16] = 42,
+ [1][1][2][1][RTW89_ACMA][0][16] = 6,
+ [1][1][2][1][RTW89_CHILE][1][16] = 10,
+ [1][1][2][1][RTW89_QATAR][1][16] = 42,
+ [1][1][2][1][RTW89_QATAR][0][16] = 6,
+ [1][1][2][1][RTW89_UK][1][16] = 42,
+ [1][1][2][1][RTW89_UK][0][16] = 6,
+ [1][1][2][1][RTW89_FCC][1][20] = 10,
+ [1][1][2][1][RTW89_FCC][2][20] = 58,
+ [1][1][2][1][RTW89_ETSI][1][20] = 42,
+ [1][1][2][1][RTW89_ETSI][0][20] = 6,
+ [1][1][2][1][RTW89_MKK][1][20] = 52,
+ [1][1][2][1][RTW89_MKK][0][20] = 12,
+ [1][1][2][1][RTW89_IC][1][20] = 10,
+ [1][1][2][1][RTW89_KCC][1][20] = 28,
+ [1][1][2][1][RTW89_KCC][0][20] = 12,
+ [1][1][2][1][RTW89_ACMA][1][20] = 42,
+ [1][1][2][1][RTW89_ACMA][0][20] = 6,
+ [1][1][2][1][RTW89_CHILE][1][20] = 10,
+ [1][1][2][1][RTW89_QATAR][1][20] = 42,
+ [1][1][2][1][RTW89_QATAR][0][20] = 6,
+ [1][1][2][1][RTW89_UK][1][20] = 42,
+ [1][1][2][1][RTW89_UK][0][20] = 6,
+ [1][1][2][1][RTW89_FCC][1][24] = 10,
+ [1][1][2][1][RTW89_FCC][2][24] = 70,
+ [1][1][2][1][RTW89_ETSI][1][24] = 42,
+ [1][1][2][1][RTW89_ETSI][0][24] = 6,
+ [1][1][2][1][RTW89_MKK][1][24] = 54,
+ [1][1][2][1][RTW89_MKK][0][24] = 14,
+ [1][1][2][1][RTW89_IC][1][24] = 10,
+ [1][1][2][1][RTW89_KCC][1][24] = 28,
+ [1][1][2][1][RTW89_KCC][0][24] = 12,
+ [1][1][2][1][RTW89_ACMA][1][24] = 42,
+ [1][1][2][1][RTW89_ACMA][0][24] = 6,
+ [1][1][2][1][RTW89_CHILE][1][24] = 10,
+ [1][1][2][1][RTW89_QATAR][1][24] = 42,
+ [1][1][2][1][RTW89_QATAR][0][24] = 6,
+ [1][1][2][1][RTW89_UK][1][24] = 42,
+ [1][1][2][1][RTW89_UK][0][24] = 6,
+ [1][1][2][1][RTW89_FCC][1][28] = 10,
+ [1][1][2][1][RTW89_FCC][2][28] = 70,
+ [1][1][2][1][RTW89_ETSI][1][28] = 42,
+ [1][1][2][1][RTW89_ETSI][0][28] = 6,
+ [1][1][2][1][RTW89_MKK][1][28] = 52,
+ [1][1][2][1][RTW89_MKK][0][28] = 14,
+ [1][1][2][1][RTW89_IC][1][28] = 10,
+ [1][1][2][1][RTW89_KCC][1][28] = 28,
+ [1][1][2][1][RTW89_KCC][0][28] = 14,
+ [1][1][2][1][RTW89_ACMA][1][28] = 42,
+ [1][1][2][1][RTW89_ACMA][0][28] = 6,
+ [1][1][2][1][RTW89_CHILE][1][28] = 10,
+ [1][1][2][1][RTW89_QATAR][1][28] = 42,
+ [1][1][2][1][RTW89_QATAR][0][28] = 6,
+ [1][1][2][1][RTW89_UK][1][28] = 42,
+ [1][1][2][1][RTW89_UK][0][28] = 6,
+ [1][1][2][1][RTW89_FCC][1][31] = 10,
+ [1][1][2][1][RTW89_FCC][2][31] = 70,
+ [1][1][2][1][RTW89_ETSI][1][31] = 42,
+ [1][1][2][1][RTW89_ETSI][0][31] = 6,
+ [1][1][2][1][RTW89_MKK][1][31] = 52,
+ [1][1][2][1][RTW89_MKK][0][31] = 14,
+ [1][1][2][1][RTW89_IC][1][31] = 10,
+ [1][1][2][1][RTW89_KCC][1][31] = 28,
+ [1][1][2][1][RTW89_KCC][0][31] = 14,
+ [1][1][2][1][RTW89_ACMA][1][31] = 42,
+ [1][1][2][1][RTW89_ACMA][0][31] = 6,
+ [1][1][2][1][RTW89_CHILE][1][31] = 10,
+ [1][1][2][1][RTW89_QATAR][1][31] = 42,
+ [1][1][2][1][RTW89_QATAR][0][31] = 6,
+ [1][1][2][1][RTW89_UK][1][31] = 42,
+ [1][1][2][1][RTW89_UK][0][31] = 6,
+ [1][1][2][1][RTW89_FCC][1][35] = 10,
+ [1][1][2][1][RTW89_FCC][2][35] = 70,
+ [1][1][2][1][RTW89_ETSI][1][35] = 42,
+ [1][1][2][1][RTW89_ETSI][0][35] = 6,
+ [1][1][2][1][RTW89_MKK][1][35] = 52,
+ [1][1][2][1][RTW89_MKK][0][35] = 14,
+ [1][1][2][1][RTW89_IC][1][35] = 10,
+ [1][1][2][1][RTW89_KCC][1][35] = 28,
+ [1][1][2][1][RTW89_KCC][0][35] = 14,
+ [1][1][2][1][RTW89_ACMA][1][35] = 42,
+ [1][1][2][1][RTW89_ACMA][0][35] = 6,
+ [1][1][2][1][RTW89_CHILE][1][35] = 10,
+ [1][1][2][1][RTW89_QATAR][1][35] = 42,
+ [1][1][2][1][RTW89_QATAR][0][35] = 6,
+ [1][1][2][1][RTW89_UK][1][35] = 42,
+ [1][1][2][1][RTW89_UK][0][35] = 6,
+ [1][1][2][1][RTW89_FCC][1][39] = 10,
+ [1][1][2][1][RTW89_FCC][2][39] = 70,
+ [1][1][2][1][RTW89_ETSI][1][39] = 42,
+ [1][1][2][1][RTW89_ETSI][0][39] = 6,
+ [1][1][2][1][RTW89_MKK][1][39] = 52,
+ [1][1][2][1][RTW89_MKK][0][39] = 14,
+ [1][1][2][1][RTW89_IC][1][39] = 10,
+ [1][1][2][1][RTW89_KCC][1][39] = 28,
+ [1][1][2][1][RTW89_KCC][0][39] = 14,
+ [1][1][2][1][RTW89_ACMA][1][39] = 42,
+ [1][1][2][1][RTW89_ACMA][0][39] = 6,
+ [1][1][2][1][RTW89_CHILE][1][39] = 10,
+ [1][1][2][1][RTW89_QATAR][1][39] = 42,
+ [1][1][2][1][RTW89_QATAR][0][39] = 6,
+ [1][1][2][1][RTW89_UK][1][39] = 42,
+ [1][1][2][1][RTW89_UK][0][39] = 6,
+ [1][1][2][1][RTW89_FCC][1][43] = 10,
+ [1][1][2][1][RTW89_FCC][2][43] = 70,
+ [1][1][2][1][RTW89_ETSI][1][43] = 42,
+ [1][1][2][1][RTW89_ETSI][0][43] = 6,
+ [1][1][2][1][RTW89_MKK][1][43] = 52,
+ [1][1][2][1][RTW89_MKK][0][43] = 14,
+ [1][1][2][1][RTW89_IC][1][43] = 10,
+ [1][1][2][1][RTW89_KCC][1][43] = 28,
+ [1][1][2][1][RTW89_KCC][0][43] = 14,
+ [1][1][2][1][RTW89_ACMA][1][43] = 42,
+ [1][1][2][1][RTW89_ACMA][0][43] = 6,
+ [1][1][2][1][RTW89_CHILE][1][43] = 10,
+ [1][1][2][1][RTW89_QATAR][1][43] = 42,
+ [1][1][2][1][RTW89_QATAR][0][43] = 6,
+ [1][1][2][1][RTW89_UK][1][43] = 42,
+ [1][1][2][1][RTW89_UK][0][43] = 6,
+ [1][1][2][1][RTW89_FCC][1][46] = 12,
+ [1][1][2][1][RTW89_FCC][2][46] = 127,
+ [1][1][2][1][RTW89_ETSI][1][46] = 127,
+ [1][1][2][1][RTW89_ETSI][0][46] = 127,
+ [1][1][2][1][RTW89_MKK][1][46] = 127,
+ [1][1][2][1][RTW89_MKK][0][46] = 127,
+ [1][1][2][1][RTW89_IC][1][46] = 12,
+ [1][1][2][1][RTW89_KCC][1][46] = 28,
+ [1][1][2][1][RTW89_KCC][0][46] = 127,
+ [1][1][2][1][RTW89_ACMA][1][46] = 127,
+ [1][1][2][1][RTW89_ACMA][0][46] = 127,
+ [1][1][2][1][RTW89_CHILE][1][46] = 12,
+ [1][1][2][1][RTW89_QATAR][1][46] = 127,
+ [1][1][2][1][RTW89_QATAR][0][46] = 127,
+ [1][1][2][1][RTW89_UK][1][46] = 127,
+ [1][1][2][1][RTW89_UK][0][46] = 127,
+ [1][1][2][1][RTW89_FCC][1][50] = 12,
+ [1][1][2][1][RTW89_FCC][2][50] = 127,
+ [1][1][2][1][RTW89_ETSI][1][50] = 127,
+ [1][1][2][1][RTW89_ETSI][0][50] = 127,
+ [1][1][2][1][RTW89_MKK][1][50] = 127,
+ [1][1][2][1][RTW89_MKK][0][50] = 127,
+ [1][1][2][1][RTW89_IC][1][50] = 12,
+ [1][1][2][1][RTW89_KCC][1][50] = 28,
+ [1][1][2][1][RTW89_KCC][0][50] = 127,
+ [1][1][2][1][RTW89_ACMA][1][50] = 127,
+ [1][1][2][1][RTW89_ACMA][0][50] = 127,
+ [1][1][2][1][RTW89_CHILE][1][50] = 12,
+ [1][1][2][1][RTW89_QATAR][1][50] = 127,
+ [1][1][2][1][RTW89_QATAR][0][50] = 127,
+ [1][1][2][1][RTW89_UK][1][50] = 127,
+ [1][1][2][1][RTW89_UK][0][50] = 127,
+ [1][1][2][1][RTW89_FCC][1][54] = 10,
+ [1][1][2][1][RTW89_FCC][2][54] = 127,
+ [1][1][2][1][RTW89_ETSI][1][54] = 127,
+ [1][1][2][1][RTW89_ETSI][0][54] = 127,
+ [1][1][2][1][RTW89_MKK][1][54] = 127,
+ [1][1][2][1][RTW89_MKK][0][54] = 127,
+ [1][1][2][1][RTW89_IC][1][54] = 10,
+ [1][1][2][1][RTW89_KCC][1][54] = 28,
+ [1][1][2][1][RTW89_KCC][0][54] = 127,
+ [1][1][2][1][RTW89_ACMA][1][54] = 127,
+ [1][1][2][1][RTW89_ACMA][0][54] = 127,
+ [1][1][2][1][RTW89_CHILE][1][54] = 10,
+ [1][1][2][1][RTW89_QATAR][1][54] = 127,
+ [1][1][2][1][RTW89_QATAR][0][54] = 127,
+ [1][1][2][1][RTW89_UK][1][54] = 127,
+ [1][1][2][1][RTW89_UK][0][54] = 127,
+ [1][1][2][1][RTW89_FCC][1][58] = 10,
+ [1][1][2][1][RTW89_FCC][2][58] = 66,
+ [1][1][2][1][RTW89_ETSI][1][58] = 127,
+ [1][1][2][1][RTW89_ETSI][0][58] = 127,
+ [1][1][2][1][RTW89_MKK][1][58] = 127,
+ [1][1][2][1][RTW89_MKK][0][58] = 127,
+ [1][1][2][1][RTW89_IC][1][58] = 10,
+ [1][1][2][1][RTW89_KCC][1][58] = 28,
+ [1][1][2][1][RTW89_KCC][0][58] = 127,
+ [1][1][2][1][RTW89_ACMA][1][58] = 127,
+ [1][1][2][1][RTW89_ACMA][0][58] = 127,
+ [1][1][2][1][RTW89_CHILE][1][58] = 10,
+ [1][1][2][1][RTW89_QATAR][1][58] = 127,
+ [1][1][2][1][RTW89_QATAR][0][58] = 127,
+ [1][1][2][1][RTW89_UK][1][58] = 127,
+ [1][1][2][1][RTW89_UK][0][58] = 127,
+ [1][1][2][1][RTW89_FCC][1][61] = 10,
+ [1][1][2][1][RTW89_FCC][2][61] = 66,
+ [1][1][2][1][RTW89_ETSI][1][61] = 127,
+ [1][1][2][1][RTW89_ETSI][0][61] = 127,
+ [1][1][2][1][RTW89_MKK][1][61] = 127,
+ [1][1][2][1][RTW89_MKK][0][61] = 127,
+ [1][1][2][1][RTW89_IC][1][61] = 10,
+ [1][1][2][1][RTW89_KCC][1][61] = 28,
+ [1][1][2][1][RTW89_KCC][0][61] = 127,
+ [1][1][2][1][RTW89_ACMA][1][61] = 127,
+ [1][1][2][1][RTW89_ACMA][0][61] = 127,
+ [1][1][2][1][RTW89_CHILE][1][61] = 10,
+ [1][1][2][1][RTW89_QATAR][1][61] = 127,
+ [1][1][2][1][RTW89_QATAR][0][61] = 127,
+ [1][1][2][1][RTW89_UK][1][61] = 127,
+ [1][1][2][1][RTW89_UK][0][61] = 127,
+ [1][1][2][1][RTW89_FCC][1][65] = 10,
+ [1][1][2][1][RTW89_FCC][2][65] = 66,
+ [1][1][2][1][RTW89_ETSI][1][65] = 127,
+ [1][1][2][1][RTW89_ETSI][0][65] = 127,
+ [1][1][2][1][RTW89_MKK][1][65] = 127,
+ [1][1][2][1][RTW89_MKK][0][65] = 127,
+ [1][1][2][1][RTW89_IC][1][65] = 10,
+ [1][1][2][1][RTW89_KCC][1][65] = 28,
+ [1][1][2][1][RTW89_KCC][0][65] = 127,
+ [1][1][2][1][RTW89_ACMA][1][65] = 127,
+ [1][1][2][1][RTW89_ACMA][0][65] = 127,
+ [1][1][2][1][RTW89_CHILE][1][65] = 10,
+ [1][1][2][1][RTW89_QATAR][1][65] = 127,
+ [1][1][2][1][RTW89_QATAR][0][65] = 127,
+ [1][1][2][1][RTW89_UK][1][65] = 127,
+ [1][1][2][1][RTW89_UK][0][65] = 127,
+ [1][1][2][1][RTW89_FCC][1][69] = 10,
+ [1][1][2][1][RTW89_FCC][2][69] = 66,
+ [1][1][2][1][RTW89_ETSI][1][69] = 127,
+ [1][1][2][1][RTW89_ETSI][0][69] = 127,
+ [1][1][2][1][RTW89_MKK][1][69] = 127,
+ [1][1][2][1][RTW89_MKK][0][69] = 127,
+ [1][1][2][1][RTW89_IC][1][69] = 10,
+ [1][1][2][1][RTW89_KCC][1][69] = 28,
+ [1][1][2][1][RTW89_KCC][0][69] = 127,
+ [1][1][2][1][RTW89_ACMA][1][69] = 127,
+ [1][1][2][1][RTW89_ACMA][0][69] = 127,
+ [1][1][2][1][RTW89_CHILE][1][69] = 10,
+ [1][1][2][1][RTW89_QATAR][1][69] = 127,
+ [1][1][2][1][RTW89_QATAR][0][69] = 127,
+ [1][1][2][1][RTW89_UK][1][69] = 127,
+ [1][1][2][1][RTW89_UK][0][69] = 127,
+ [1][1][2][1][RTW89_FCC][1][73] = 10,
+ [1][1][2][1][RTW89_FCC][2][73] = 66,
+ [1][1][2][1][RTW89_ETSI][1][73] = 127,
+ [1][1][2][1][RTW89_ETSI][0][73] = 127,
+ [1][1][2][1][RTW89_MKK][1][73] = 127,
+ [1][1][2][1][RTW89_MKK][0][73] = 127,
+ [1][1][2][1][RTW89_IC][1][73] = 10,
+ [1][1][2][1][RTW89_KCC][1][73] = 28,
+ [1][1][2][1][RTW89_KCC][0][73] = 127,
+ [1][1][2][1][RTW89_ACMA][1][73] = 127,
+ [1][1][2][1][RTW89_ACMA][0][73] = 127,
+ [1][1][2][1][RTW89_CHILE][1][73] = 10,
+ [1][1][2][1][RTW89_QATAR][1][73] = 127,
+ [1][1][2][1][RTW89_QATAR][0][73] = 127,
+ [1][1][2][1][RTW89_UK][1][73] = 127,
+ [1][1][2][1][RTW89_UK][0][73] = 127,
+ [1][1][2][1][RTW89_FCC][1][76] = 10,
+ [1][1][2][1][RTW89_FCC][2][76] = 66,
+ [1][1][2][1][RTW89_ETSI][1][76] = 127,
+ [1][1][2][1][RTW89_ETSI][0][76] = 127,
+ [1][1][2][1][RTW89_MKK][1][76] = 127,
+ [1][1][2][1][RTW89_MKK][0][76] = 127,
+ [1][1][2][1][RTW89_IC][1][76] = 10,
+ [1][1][2][1][RTW89_KCC][1][76] = 28,
+ [1][1][2][1][RTW89_KCC][0][76] = 127,
+ [1][1][2][1][RTW89_ACMA][1][76] = 127,
+ [1][1][2][1][RTW89_ACMA][0][76] = 127,
+ [1][1][2][1][RTW89_CHILE][1][76] = 10,
+ [1][1][2][1][RTW89_QATAR][1][76] = 127,
+ [1][1][2][1][RTW89_QATAR][0][76] = 127,
+ [1][1][2][1][RTW89_UK][1][76] = 127,
+ [1][1][2][1][RTW89_UK][0][76] = 127,
+ [1][1][2][1][RTW89_FCC][1][80] = 10,
+ [1][1][2][1][RTW89_FCC][2][80] = 66,
+ [1][1][2][1][RTW89_ETSI][1][80] = 127,
+ [1][1][2][1][RTW89_ETSI][0][80] = 127,
+ [1][1][2][1][RTW89_MKK][1][80] = 127,
+ [1][1][2][1][RTW89_MKK][0][80] = 127,
+ [1][1][2][1][RTW89_IC][1][80] = 10,
+ [1][1][2][1][RTW89_KCC][1][80] = 32,
+ [1][1][2][1][RTW89_KCC][0][80] = 127,
+ [1][1][2][1][RTW89_ACMA][1][80] = 127,
+ [1][1][2][1][RTW89_ACMA][0][80] = 127,
+ [1][1][2][1][RTW89_CHILE][1][80] = 10,
+ [1][1][2][1][RTW89_QATAR][1][80] = 127,
+ [1][1][2][1][RTW89_QATAR][0][80] = 127,
+ [1][1][2][1][RTW89_UK][1][80] = 127,
+ [1][1][2][1][RTW89_UK][0][80] = 127,
+ [1][1][2][1][RTW89_FCC][1][84] = 10,
+ [1][1][2][1][RTW89_FCC][2][84] = 66,
+ [1][1][2][1][RTW89_ETSI][1][84] = 127,
+ [1][1][2][1][RTW89_ETSI][0][84] = 127,
+ [1][1][2][1][RTW89_MKK][1][84] = 127,
+ [1][1][2][1][RTW89_MKK][0][84] = 127,
+ [1][1][2][1][RTW89_IC][1][84] = 10,
+ [1][1][2][1][RTW89_KCC][1][84] = 32,
+ [1][1][2][1][RTW89_KCC][0][84] = 127,
+ [1][1][2][1][RTW89_ACMA][1][84] = 127,
+ [1][1][2][1][RTW89_ACMA][0][84] = 127,
+ [1][1][2][1][RTW89_CHILE][1][84] = 10,
+ [1][1][2][1][RTW89_QATAR][1][84] = 127,
+ [1][1][2][1][RTW89_QATAR][0][84] = 127,
+ [1][1][2][1][RTW89_UK][1][84] = 127,
+ [1][1][2][1][RTW89_UK][0][84] = 127,
+ [1][1][2][1][RTW89_FCC][1][88] = 10,
+ [1][1][2][1][RTW89_FCC][2][88] = 127,
+ [1][1][2][1][RTW89_ETSI][1][88] = 127,
+ [1][1][2][1][RTW89_ETSI][0][88] = 127,
+ [1][1][2][1][RTW89_MKK][1][88] = 127,
+ [1][1][2][1][RTW89_MKK][0][88] = 127,
+ [1][1][2][1][RTW89_IC][1][88] = 10,
+ [1][1][2][1][RTW89_KCC][1][88] = 32,
+ [1][1][2][1][RTW89_KCC][0][88] = 127,
+ [1][1][2][1][RTW89_ACMA][1][88] = 127,
+ [1][1][2][1][RTW89_ACMA][0][88] = 127,
+ [1][1][2][1][RTW89_CHILE][1][88] = 10,
+ [1][1][2][1][RTW89_QATAR][1][88] = 127,
+ [1][1][2][1][RTW89_QATAR][0][88] = 127,
+ [1][1][2][1][RTW89_UK][1][88] = 127,
+ [1][1][2][1][RTW89_UK][0][88] = 127,
+ [1][1][2][1][RTW89_FCC][1][91] = 12,
+ [1][1][2][1][RTW89_FCC][2][91] = 127,
+ [1][1][2][1][RTW89_ETSI][1][91] = 127,
+ [1][1][2][1][RTW89_ETSI][0][91] = 127,
+ [1][1][2][1][RTW89_MKK][1][91] = 127,
+ [1][1][2][1][RTW89_MKK][0][91] = 127,
+ [1][1][2][1][RTW89_IC][1][91] = 12,
+ [1][1][2][1][RTW89_KCC][1][91] = 32,
+ [1][1][2][1][RTW89_KCC][0][91] = 127,
+ [1][1][2][1][RTW89_ACMA][1][91] = 127,
+ [1][1][2][1][RTW89_ACMA][0][91] = 127,
+ [1][1][2][1][RTW89_CHILE][1][91] = 12,
+ [1][1][2][1][RTW89_QATAR][1][91] = 127,
+ [1][1][2][1][RTW89_QATAR][0][91] = 127,
+ [1][1][2][1][RTW89_UK][1][91] = 127,
+ [1][1][2][1][RTW89_UK][0][91] = 127,
+ [1][1][2][1][RTW89_FCC][1][95] = 10,
+ [1][1][2][1][RTW89_FCC][2][95] = 127,
+ [1][1][2][1][RTW89_ETSI][1][95] = 127,
+ [1][1][2][1][RTW89_ETSI][0][95] = 127,
+ [1][1][2][1][RTW89_MKK][1][95] = 127,
+ [1][1][2][1][RTW89_MKK][0][95] = 127,
+ [1][1][2][1][RTW89_IC][1][95] = 10,
+ [1][1][2][1][RTW89_KCC][1][95] = 32,
+ [1][1][2][1][RTW89_KCC][0][95] = 127,
+ [1][1][2][1][RTW89_ACMA][1][95] = 127,
+ [1][1][2][1][RTW89_ACMA][0][95] = 127,
+ [1][1][2][1][RTW89_CHILE][1][95] = 10,
+ [1][1][2][1][RTW89_QATAR][1][95] = 127,
+ [1][1][2][1][RTW89_QATAR][0][95] = 127,
+ [1][1][2][1][RTW89_UK][1][95] = 127,
+ [1][1][2][1][RTW89_UK][0][95] = 127,
+ [1][1][2][1][RTW89_FCC][1][99] = 10,
+ [1][1][2][1][RTW89_FCC][2][99] = 127,
+ [1][1][2][1][RTW89_ETSI][1][99] = 127,
+ [1][1][2][1][RTW89_ETSI][0][99] = 127,
+ [1][1][2][1][RTW89_MKK][1][99] = 127,
+ [1][1][2][1][RTW89_MKK][0][99] = 127,
+ [1][1][2][1][RTW89_IC][1][99] = 10,
+ [1][1][2][1][RTW89_KCC][1][99] = 32,
+ [1][1][2][1][RTW89_KCC][0][99] = 127,
+ [1][1][2][1][RTW89_ACMA][1][99] = 127,
+ [1][1][2][1][RTW89_ACMA][0][99] = 127,
+ [1][1][2][1][RTW89_CHILE][1][99] = 10,
+ [1][1][2][1][RTW89_QATAR][1][99] = 127,
+ [1][1][2][1][RTW89_QATAR][0][99] = 127,
+ [1][1][2][1][RTW89_UK][1][99] = 127,
+ [1][1][2][1][RTW89_UK][0][99] = 127,
+ [1][1][2][1][RTW89_FCC][1][103] = 10,
+ [1][1][2][1][RTW89_FCC][2][103] = 127,
+ [1][1][2][1][RTW89_ETSI][1][103] = 127,
+ [1][1][2][1][RTW89_ETSI][0][103] = 127,
+ [1][1][2][1][RTW89_MKK][1][103] = 127,
+ [1][1][2][1][RTW89_MKK][0][103] = 127,
+ [1][1][2][1][RTW89_IC][1][103] = 10,
+ [1][1][2][1][RTW89_KCC][1][103] = 32,
+ [1][1][2][1][RTW89_KCC][0][103] = 127,
+ [1][1][2][1][RTW89_ACMA][1][103] = 127,
+ [1][1][2][1][RTW89_ACMA][0][103] = 127,
+ [1][1][2][1][RTW89_CHILE][1][103] = 10,
+ [1][1][2][1][RTW89_QATAR][1][103] = 127,
+ [1][1][2][1][RTW89_QATAR][0][103] = 127,
+ [1][1][2][1][RTW89_UK][1][103] = 127,
+ [1][1][2][1][RTW89_UK][0][103] = 127,
+ [1][1][2][1][RTW89_FCC][1][106] = 12,
+ [1][1][2][1][RTW89_FCC][2][106] = 127,
+ [1][1][2][1][RTW89_ETSI][1][106] = 127,
+ [1][1][2][1][RTW89_ETSI][0][106] = 127,
+ [1][1][2][1][RTW89_MKK][1][106] = 127,
+ [1][1][2][1][RTW89_MKK][0][106] = 127,
+ [1][1][2][1][RTW89_IC][1][106] = 12,
+ [1][1][2][1][RTW89_KCC][1][106] = 32,
+ [1][1][2][1][RTW89_KCC][0][106] = 127,
+ [1][1][2][1][RTW89_ACMA][1][106] = 127,
+ [1][1][2][1][RTW89_ACMA][0][106] = 127,
+ [1][1][2][1][RTW89_CHILE][1][106] = 12,
+ [1][1][2][1][RTW89_QATAR][1][106] = 127,
+ [1][1][2][1][RTW89_QATAR][0][106] = 127,
+ [1][1][2][1][RTW89_UK][1][106] = 127,
+ [1][1][2][1][RTW89_UK][0][106] = 127,
+ [1][1][2][1][RTW89_FCC][1][110] = 127,
+ [1][1][2][1][RTW89_FCC][2][110] = 127,
+ [1][1][2][1][RTW89_ETSI][1][110] = 127,
+ [1][1][2][1][RTW89_ETSI][0][110] = 127,
+ [1][1][2][1][RTW89_MKK][1][110] = 127,
+ [1][1][2][1][RTW89_MKK][0][110] = 127,
+ [1][1][2][1][RTW89_IC][1][110] = 127,
+ [1][1][2][1][RTW89_KCC][1][110] = 127,
+ [1][1][2][1][RTW89_KCC][0][110] = 127,
+ [1][1][2][1][RTW89_ACMA][1][110] = 127,
+ [1][1][2][1][RTW89_ACMA][0][110] = 127,
+ [1][1][2][1][RTW89_CHILE][1][110] = 127,
+ [1][1][2][1][RTW89_QATAR][1][110] = 127,
+ [1][1][2][1][RTW89_QATAR][0][110] = 127,
+ [1][1][2][1][RTW89_UK][1][110] = 127,
+ [1][1][2][1][RTW89_UK][0][110] = 127,
+ [1][1][2][1][RTW89_FCC][1][114] = 127,
+ [1][1][2][1][RTW89_FCC][2][114] = 127,
+ [1][1][2][1][RTW89_ETSI][1][114] = 127,
+ [1][1][2][1][RTW89_ETSI][0][114] = 127,
+ [1][1][2][1][RTW89_MKK][1][114] = 127,
+ [1][1][2][1][RTW89_MKK][0][114] = 127,
+ [1][1][2][1][RTW89_IC][1][114] = 127,
+ [1][1][2][1][RTW89_KCC][1][114] = 127,
+ [1][1][2][1][RTW89_KCC][0][114] = 127,
+ [1][1][2][1][RTW89_ACMA][1][114] = 127,
+ [1][1][2][1][RTW89_ACMA][0][114] = 127,
+ [1][1][2][1][RTW89_CHILE][1][114] = 127,
+ [1][1][2][1][RTW89_QATAR][1][114] = 127,
+ [1][1][2][1][RTW89_QATAR][0][114] = 127,
+ [1][1][2][1][RTW89_UK][1][114] = 127,
+ [1][1][2][1][RTW89_UK][0][114] = 127,
+ [1][1][2][1][RTW89_FCC][1][118] = 127,
+ [1][1][2][1][RTW89_FCC][2][118] = 127,
+ [1][1][2][1][RTW89_ETSI][1][118] = 127,
+ [1][1][2][1][RTW89_ETSI][0][118] = 127,
+ [1][1][2][1][RTW89_MKK][1][118] = 127,
+ [1][1][2][1][RTW89_MKK][0][118] = 127,
+ [1][1][2][1][RTW89_IC][1][118] = 127,
+ [1][1][2][1][RTW89_KCC][1][118] = 127,
+ [1][1][2][1][RTW89_KCC][0][118] = 127,
+ [1][1][2][1][RTW89_ACMA][1][118] = 127,
+ [1][1][2][1][RTW89_ACMA][0][118] = 127,
+ [1][1][2][1][RTW89_CHILE][1][118] = 127,
+ [1][1][2][1][RTW89_QATAR][1][118] = 127,
+ [1][1][2][1][RTW89_QATAR][0][118] = 127,
+ [1][1][2][1][RTW89_UK][1][118] = 127,
+ [1][1][2][1][RTW89_UK][0][118] = 127,
+ [2][0][2][0][RTW89_FCC][1][3] = 46,
+ [2][0][2][0][RTW89_FCC][2][3] = 60,
+ [2][0][2][0][RTW89_ETSI][1][3] = 58,
+ [2][0][2][0][RTW89_ETSI][0][3] = 30,
+ [2][0][2][0][RTW89_MKK][1][3] = 58,
+ [2][0][2][0][RTW89_MKK][0][3] = 26,
+ [2][0][2][0][RTW89_IC][1][3] = 46,
+ [2][0][2][0][RTW89_KCC][1][3] = 50,
+ [2][0][2][0][RTW89_KCC][0][3] = 24,
+ [2][0][2][0][RTW89_ACMA][1][3] = 58,
+ [2][0][2][0][RTW89_ACMA][0][3] = 30,
+ [2][0][2][0][RTW89_CHILE][1][3] = 46,
+ [2][0][2][0][RTW89_QATAR][1][3] = 58,
+ [2][0][2][0][RTW89_QATAR][0][3] = 30,
+ [2][0][2][0][RTW89_UK][1][3] = 58,
+ [2][0][2][0][RTW89_UK][0][3] = 30,
+ [2][0][2][0][RTW89_FCC][1][11] = 46,
+ [2][0][2][0][RTW89_FCC][2][11] = 60,
+ [2][0][2][0][RTW89_ETSI][1][11] = 58,
+ [2][0][2][0][RTW89_ETSI][0][11] = 30,
+ [2][0][2][0][RTW89_MKK][1][11] = 58,
+ [2][0][2][0][RTW89_MKK][0][11] = 24,
+ [2][0][2][0][RTW89_IC][1][11] = 46,
+ [2][0][2][0][RTW89_KCC][1][11] = 50,
+ [2][0][2][0][RTW89_KCC][0][11] = 24,
+ [2][0][2][0][RTW89_ACMA][1][11] = 58,
+ [2][0][2][0][RTW89_ACMA][0][11] = 30,
+ [2][0][2][0][RTW89_CHILE][1][11] = 46,
+ [2][0][2][0][RTW89_QATAR][1][11] = 58,
+ [2][0][2][0][RTW89_QATAR][0][11] = 30,
+ [2][0][2][0][RTW89_UK][1][11] = 58,
+ [2][0][2][0][RTW89_UK][0][11] = 30,
+ [2][0][2][0][RTW89_FCC][1][18] = 46,
+ [2][0][2][0][RTW89_FCC][2][18] = 60,
+ [2][0][2][0][RTW89_ETSI][1][18] = 58,
+ [2][0][2][0][RTW89_ETSI][0][18] = 30,
+ [2][0][2][0][RTW89_MKK][1][18] = 58,
+ [2][0][2][0][RTW89_MKK][0][18] = 24,
+ [2][0][2][0][RTW89_IC][1][18] = 46,
+ [2][0][2][0][RTW89_KCC][1][18] = 50,
+ [2][0][2][0][RTW89_KCC][0][18] = 24,
+ [2][0][2][0][RTW89_ACMA][1][18] = 58,
+ [2][0][2][0][RTW89_ACMA][0][18] = 30,
+ [2][0][2][0][RTW89_CHILE][1][18] = 46,
+ [2][0][2][0][RTW89_QATAR][1][18] = 58,
+ [2][0][2][0][RTW89_QATAR][0][18] = 30,
+ [2][0][2][0][RTW89_UK][1][18] = 58,
+ [2][0][2][0][RTW89_UK][0][18] = 30,
+ [2][0][2][0][RTW89_FCC][1][26] = 46,
+ [2][0][2][0][RTW89_FCC][2][26] = 60,
+ [2][0][2][0][RTW89_ETSI][1][26] = 58,
+ [2][0][2][0][RTW89_ETSI][0][26] = 30,
+ [2][0][2][0][RTW89_MKK][1][26] = 58,
+ [2][0][2][0][RTW89_MKK][0][26] = 24,
+ [2][0][2][0][RTW89_IC][1][26] = 46,
+ [2][0][2][0][RTW89_KCC][1][26] = 50,
+ [2][0][2][0][RTW89_KCC][0][26] = 26,
+ [2][0][2][0][RTW89_ACMA][1][26] = 58,
+ [2][0][2][0][RTW89_ACMA][0][26] = 30,
+ [2][0][2][0][RTW89_CHILE][1][26] = 46,
+ [2][0][2][0][RTW89_QATAR][1][26] = 58,
+ [2][0][2][0][RTW89_QATAR][0][26] = 30,
+ [2][0][2][0][RTW89_UK][1][26] = 58,
+ [2][0][2][0][RTW89_UK][0][26] = 30,
+ [2][0][2][0][RTW89_FCC][1][33] = 46,
+ [2][0][2][0][RTW89_FCC][2][33] = 60,
+ [2][0][2][0][RTW89_ETSI][1][33] = 58,
+ [2][0][2][0][RTW89_ETSI][0][33] = 30,
+ [2][0][2][0][RTW89_MKK][1][33] = 58,
+ [2][0][2][0][RTW89_MKK][0][33] = 24,
+ [2][0][2][0][RTW89_IC][1][33] = 46,
+ [2][0][2][0][RTW89_KCC][1][33] = 50,
+ [2][0][2][0][RTW89_KCC][0][33] = 24,
+ [2][0][2][0][RTW89_ACMA][1][33] = 58,
+ [2][0][2][0][RTW89_ACMA][0][33] = 30,
+ [2][0][2][0][RTW89_CHILE][1][33] = 46,
+ [2][0][2][0][RTW89_QATAR][1][33] = 58,
+ [2][0][2][0][RTW89_QATAR][0][33] = 30,
+ [2][0][2][0][RTW89_UK][1][33] = 58,
+ [2][0][2][0][RTW89_UK][0][33] = 30,
+ [2][0][2][0][RTW89_FCC][1][41] = 46,
+ [2][0][2][0][RTW89_FCC][2][41] = 60,
+ [2][0][2][0][RTW89_ETSI][1][41] = 58,
+ [2][0][2][0][RTW89_ETSI][0][41] = 30,
+ [2][0][2][0][RTW89_MKK][1][41] = 58,
+ [2][0][2][0][RTW89_MKK][0][41] = 24,
+ [2][0][2][0][RTW89_IC][1][41] = 46,
+ [2][0][2][0][RTW89_KCC][1][41] = 50,
+ [2][0][2][0][RTW89_KCC][0][41] = 24,
+ [2][0][2][0][RTW89_ACMA][1][41] = 58,
+ [2][0][2][0][RTW89_ACMA][0][41] = 30,
+ [2][0][2][0][RTW89_CHILE][1][41] = 46,
+ [2][0][2][0][RTW89_QATAR][1][41] = 58,
+ [2][0][2][0][RTW89_QATAR][0][41] = 30,
+ [2][0][2][0][RTW89_UK][1][41] = 58,
+ [2][0][2][0][RTW89_UK][0][41] = 30,
+ [2][0][2][0][RTW89_FCC][1][48] = 46,
+ [2][0][2][0][RTW89_FCC][2][48] = 127,
+ [2][0][2][0][RTW89_ETSI][1][48] = 127,
+ [2][0][2][0][RTW89_ETSI][0][48] = 127,
+ [2][0][2][0][RTW89_MKK][1][48] = 127,
+ [2][0][2][0][RTW89_MKK][0][48] = 127,
+ [2][0][2][0][RTW89_IC][1][48] = 46,
+ [2][0][2][0][RTW89_KCC][1][48] = 48,
+ [2][0][2][0][RTW89_KCC][0][48] = 127,
+ [2][0][2][0][RTW89_ACMA][1][48] = 127,
+ [2][0][2][0][RTW89_ACMA][0][48] = 127,
+ [2][0][2][0][RTW89_CHILE][1][48] = 46,
+ [2][0][2][0][RTW89_QATAR][1][48] = 127,
+ [2][0][2][0][RTW89_QATAR][0][48] = 127,
+ [2][0][2][0][RTW89_UK][1][48] = 127,
+ [2][0][2][0][RTW89_UK][0][48] = 127,
+ [2][0][2][0][RTW89_FCC][1][56] = 46,
+ [2][0][2][0][RTW89_FCC][2][56] = 127,
+ [2][0][2][0][RTW89_ETSI][1][56] = 127,
+ [2][0][2][0][RTW89_ETSI][0][56] = 127,
+ [2][0][2][0][RTW89_MKK][1][56] = 127,
+ [2][0][2][0][RTW89_MKK][0][56] = 127,
+ [2][0][2][0][RTW89_IC][1][56] = 46,
+ [2][0][2][0][RTW89_KCC][1][56] = 48,
+ [2][0][2][0][RTW89_KCC][0][56] = 127,
+ [2][0][2][0][RTW89_ACMA][1][56] = 127,
+ [2][0][2][0][RTW89_ACMA][0][56] = 127,
+ [2][0][2][0][RTW89_CHILE][1][56] = 46,
+ [2][0][2][0][RTW89_QATAR][1][56] = 127,
+ [2][0][2][0][RTW89_QATAR][0][56] = 127,
+ [2][0][2][0][RTW89_UK][1][56] = 127,
+ [2][0][2][0][RTW89_UK][0][56] = 127,
+ [2][0][2][0][RTW89_FCC][1][63] = 46,
+ [2][0][2][0][RTW89_FCC][2][63] = 58,
+ [2][0][2][0][RTW89_ETSI][1][63] = 127,
+ [2][0][2][0][RTW89_ETSI][0][63] = 127,
+ [2][0][2][0][RTW89_MKK][1][63] = 127,
+ [2][0][2][0][RTW89_MKK][0][63] = 127,
+ [2][0][2][0][RTW89_IC][1][63] = 46,
+ [2][0][2][0][RTW89_KCC][1][63] = 48,
+ [2][0][2][0][RTW89_KCC][0][63] = 127,
+ [2][0][2][0][RTW89_ACMA][1][63] = 127,
+ [2][0][2][0][RTW89_ACMA][0][63] = 127,
+ [2][0][2][0][RTW89_CHILE][1][63] = 46,
+ [2][0][2][0][RTW89_QATAR][1][63] = 127,
+ [2][0][2][0][RTW89_QATAR][0][63] = 127,
+ [2][0][2][0][RTW89_UK][1][63] = 127,
+ [2][0][2][0][RTW89_UK][0][63] = 127,
+ [2][0][2][0][RTW89_FCC][1][71] = 46,
+ [2][0][2][0][RTW89_FCC][2][71] = 58,
+ [2][0][2][0][RTW89_ETSI][1][71] = 127,
+ [2][0][2][0][RTW89_ETSI][0][71] = 127,
+ [2][0][2][0][RTW89_MKK][1][71] = 127,
+ [2][0][2][0][RTW89_MKK][0][71] = 127,
+ [2][0][2][0][RTW89_IC][1][71] = 46,
+ [2][0][2][0][RTW89_KCC][1][71] = 48,
+ [2][0][2][0][RTW89_KCC][0][71] = 127,
+ [2][0][2][0][RTW89_ACMA][1][71] = 127,
+ [2][0][2][0][RTW89_ACMA][0][71] = 127,
+ [2][0][2][0][RTW89_CHILE][1][71] = 46,
+ [2][0][2][0][RTW89_QATAR][1][71] = 127,
+ [2][0][2][0][RTW89_QATAR][0][71] = 127,
+ [2][0][2][0][RTW89_UK][1][71] = 127,
+ [2][0][2][0][RTW89_UK][0][71] = 127,
+ [2][0][2][0][RTW89_FCC][1][78] = 46,
+ [2][0][2][0][RTW89_FCC][2][78] = 58,
+ [2][0][2][0][RTW89_ETSI][1][78] = 127,
+ [2][0][2][0][RTW89_ETSI][0][78] = 127,
+ [2][0][2][0][RTW89_MKK][1][78] = 127,
+ [2][0][2][0][RTW89_MKK][0][78] = 127,
+ [2][0][2][0][RTW89_IC][1][78] = 46,
+ [2][0][2][0][RTW89_KCC][1][78] = 52,
+ [2][0][2][0][RTW89_KCC][0][78] = 127,
+ [2][0][2][0][RTW89_ACMA][1][78] = 127,
+ [2][0][2][0][RTW89_ACMA][0][78] = 127,
+ [2][0][2][0][RTW89_CHILE][1][78] = 46,
+ [2][0][2][0][RTW89_QATAR][1][78] = 127,
+ [2][0][2][0][RTW89_QATAR][0][78] = 127,
+ [2][0][2][0][RTW89_UK][1][78] = 127,
+ [2][0][2][0][RTW89_UK][0][78] = 127,
+ [2][0][2][0][RTW89_FCC][1][86] = 46,
+ [2][0][2][0][RTW89_FCC][2][86] = 127,
+ [2][0][2][0][RTW89_ETSI][1][86] = 127,
+ [2][0][2][0][RTW89_ETSI][0][86] = 127,
+ [2][0][2][0][RTW89_MKK][1][86] = 127,
+ [2][0][2][0][RTW89_MKK][0][86] = 127,
+ [2][0][2][0][RTW89_IC][1][86] = 46,
+ [2][0][2][0][RTW89_KCC][1][86] = 52,
+ [2][0][2][0][RTW89_KCC][0][86] = 127,
+ [2][0][2][0][RTW89_ACMA][1][86] = 127,
+ [2][0][2][0][RTW89_ACMA][0][86] = 127,
+ [2][0][2][0][RTW89_CHILE][1][86] = 46,
+ [2][0][2][0][RTW89_QATAR][1][86] = 127,
+ [2][0][2][0][RTW89_QATAR][0][86] = 127,
+ [2][0][2][0][RTW89_UK][1][86] = 127,
+ [2][0][2][0][RTW89_UK][0][86] = 127,
+ [2][0][2][0][RTW89_FCC][1][93] = 46,
+ [2][0][2][0][RTW89_FCC][2][93] = 127,
+ [2][0][2][0][RTW89_ETSI][1][93] = 127,
+ [2][0][2][0][RTW89_ETSI][0][93] = 127,
+ [2][0][2][0][RTW89_MKK][1][93] = 127,
+ [2][0][2][0][RTW89_MKK][0][93] = 127,
+ [2][0][2][0][RTW89_IC][1][93] = 46,
+ [2][0][2][0][RTW89_KCC][1][93] = 50,
+ [2][0][2][0][RTW89_KCC][0][93] = 127,
+ [2][0][2][0][RTW89_ACMA][1][93] = 127,
+ [2][0][2][0][RTW89_ACMA][0][93] = 127,
+ [2][0][2][0][RTW89_CHILE][1][93] = 46,
+ [2][0][2][0][RTW89_QATAR][1][93] = 127,
+ [2][0][2][0][RTW89_QATAR][0][93] = 127,
+ [2][0][2][0][RTW89_UK][1][93] = 127,
+ [2][0][2][0][RTW89_UK][0][93] = 127,
+ [2][0][2][0][RTW89_FCC][1][101] = 44,
+ [2][0][2][0][RTW89_FCC][2][101] = 127,
+ [2][0][2][0][RTW89_ETSI][1][101] = 127,
+ [2][0][2][0][RTW89_ETSI][0][101] = 127,
+ [2][0][2][0][RTW89_MKK][1][101] = 127,
+ [2][0][2][0][RTW89_MKK][0][101] = 127,
+ [2][0][2][0][RTW89_IC][1][101] = 44,
+ [2][0][2][0][RTW89_KCC][1][101] = 50,
+ [2][0][2][0][RTW89_KCC][0][101] = 127,
+ [2][0][2][0][RTW89_ACMA][1][101] = 127,
+ [2][0][2][0][RTW89_ACMA][0][101] = 127,
+ [2][0][2][0][RTW89_CHILE][1][101] = 44,
+ [2][0][2][0][RTW89_QATAR][1][101] = 127,
+ [2][0][2][0][RTW89_QATAR][0][101] = 127,
+ [2][0][2][0][RTW89_UK][1][101] = 127,
+ [2][0][2][0][RTW89_UK][0][101] = 127,
+ [2][0][2][0][RTW89_FCC][1][108] = 127,
+ [2][0][2][0][RTW89_FCC][2][108] = 127,
+ [2][0][2][0][RTW89_ETSI][1][108] = 127,
+ [2][0][2][0][RTW89_ETSI][0][108] = 127,
+ [2][0][2][0][RTW89_MKK][1][108] = 127,
+ [2][0][2][0][RTW89_MKK][0][108] = 127,
+ [2][0][2][0][RTW89_IC][1][108] = 127,
+ [2][0][2][0][RTW89_KCC][1][108] = 127,
+ [2][0][2][0][RTW89_KCC][0][108] = 127,
+ [2][0][2][0][RTW89_ACMA][1][108] = 127,
+ [2][0][2][0][RTW89_ACMA][0][108] = 127,
+ [2][0][2][0][RTW89_CHILE][1][108] = 127,
+ [2][0][2][0][RTW89_QATAR][1][108] = 127,
+ [2][0][2][0][RTW89_QATAR][0][108] = 127,
+ [2][0][2][0][RTW89_UK][1][108] = 127,
+ [2][0][2][0][RTW89_UK][0][108] = 127,
+ [2][0][2][0][RTW89_FCC][1][116] = 127,
+ [2][0][2][0][RTW89_FCC][2][116] = 127,
+ [2][0][2][0][RTW89_ETSI][1][116] = 127,
+ [2][0][2][0][RTW89_ETSI][0][116] = 127,
+ [2][0][2][0][RTW89_MKK][1][116] = 127,
+ [2][0][2][0][RTW89_MKK][0][116] = 127,
+ [2][0][2][0][RTW89_IC][1][116] = 127,
+ [2][0][2][0][RTW89_KCC][1][116] = 127,
+ [2][0][2][0][RTW89_KCC][0][116] = 127,
+ [2][0][2][0][RTW89_ACMA][1][116] = 127,
+ [2][0][2][0][RTW89_ACMA][0][116] = 127,
+ [2][0][2][0][RTW89_CHILE][1][116] = 127,
+ [2][0][2][0][RTW89_QATAR][1][116] = 127,
+ [2][0][2][0][RTW89_QATAR][0][116] = 127,
+ [2][0][2][0][RTW89_UK][1][116] = 127,
+ [2][0][2][0][RTW89_UK][0][116] = 127,
+ [2][1][2][0][RTW89_FCC][1][3] = 22,
+ [2][1][2][0][RTW89_FCC][2][3] = 50,
+ [2][1][2][0][RTW89_ETSI][1][3] = 54,
+ [2][1][2][0][RTW89_ETSI][0][3] = 16,
+ [2][1][2][0][RTW89_MKK][1][3] = 52,
+ [2][1][2][0][RTW89_MKK][0][3] = 14,
+ [2][1][2][0][RTW89_IC][1][3] = 22,
+ [2][1][2][0][RTW89_KCC][1][3] = 38,
+ [2][1][2][0][RTW89_KCC][0][3] = 12,
+ [2][1][2][0][RTW89_ACMA][1][3] = 54,
+ [2][1][2][0][RTW89_ACMA][0][3] = 16,
+ [2][1][2][0][RTW89_CHILE][1][3] = 22,
+ [2][1][2][0][RTW89_QATAR][1][3] = 54,
+ [2][1][2][0][RTW89_QATAR][0][3] = 16,
+ [2][1][2][0][RTW89_UK][1][3] = 54,
+ [2][1][2][0][RTW89_UK][0][3] = 16,
+ [2][1][2][0][RTW89_FCC][1][11] = 20,
+ [2][1][2][0][RTW89_FCC][2][11] = 50,
+ [2][1][2][0][RTW89_ETSI][1][11] = 54,
+ [2][1][2][0][RTW89_ETSI][0][11] = 16,
+ [2][1][2][0][RTW89_MKK][1][11] = 52,
+ [2][1][2][0][RTW89_MKK][0][11] = 12,
+ [2][1][2][0][RTW89_IC][1][11] = 20,
+ [2][1][2][0][RTW89_KCC][1][11] = 38,
+ [2][1][2][0][RTW89_KCC][0][11] = 12,
+ [2][1][2][0][RTW89_ACMA][1][11] = 54,
+ [2][1][2][0][RTW89_ACMA][0][11] = 16,
+ [2][1][2][0][RTW89_CHILE][1][11] = 20,
+ [2][1][2][0][RTW89_QATAR][1][11] = 54,
+ [2][1][2][0][RTW89_QATAR][0][11] = 16,
+ [2][1][2][0][RTW89_UK][1][11] = 54,
+ [2][1][2][0][RTW89_UK][0][11] = 16,
+ [2][1][2][0][RTW89_FCC][1][18] = 20,
+ [2][1][2][0][RTW89_FCC][2][18] = 50,
+ [2][1][2][0][RTW89_ETSI][1][18] = 54,
+ [2][1][2][0][RTW89_ETSI][0][18] = 16,
+ [2][1][2][0][RTW89_MKK][1][18] = 52,
+ [2][1][2][0][RTW89_MKK][0][18] = 12,
+ [2][1][2][0][RTW89_IC][1][18] = 20,
+ [2][1][2][0][RTW89_KCC][1][18] = 38,
+ [2][1][2][0][RTW89_KCC][0][18] = 12,
+ [2][1][2][0][RTW89_ACMA][1][18] = 54,
+ [2][1][2][0][RTW89_ACMA][0][18] = 16,
+ [2][1][2][0][RTW89_CHILE][1][18] = 20,
+ [2][1][2][0][RTW89_QATAR][1][18] = 54,
+ [2][1][2][0][RTW89_QATAR][0][18] = 16,
+ [2][1][2][0][RTW89_UK][1][18] = 54,
+ [2][1][2][0][RTW89_UK][0][18] = 16,
+ [2][1][2][0][RTW89_FCC][1][26] = 20,
+ [2][1][2][0][RTW89_FCC][2][26] = 60,
+ [2][1][2][0][RTW89_ETSI][1][26] = 54,
+ [2][1][2][0][RTW89_ETSI][0][26] = 16,
+ [2][1][2][0][RTW89_MKK][1][26] = 52,
+ [2][1][2][0][RTW89_MKK][0][26] = 12,
+ [2][1][2][0][RTW89_IC][1][26] = 20,
+ [2][1][2][0][RTW89_KCC][1][26] = 38,
+ [2][1][2][0][RTW89_KCC][0][26] = 12,
+ [2][1][2][0][RTW89_ACMA][1][26] = 54,
+ [2][1][2][0][RTW89_ACMA][0][26] = 16,
+ [2][1][2][0][RTW89_CHILE][1][26] = 20,
+ [2][1][2][0][RTW89_QATAR][1][26] = 54,
+ [2][1][2][0][RTW89_QATAR][0][26] = 16,
+ [2][1][2][0][RTW89_UK][1][26] = 54,
+ [2][1][2][0][RTW89_UK][0][26] = 16,
+ [2][1][2][0][RTW89_FCC][1][33] = 20,
+ [2][1][2][0][RTW89_FCC][2][33] = 60,
+ [2][1][2][0][RTW89_ETSI][1][33] = 54,
+ [2][1][2][0][RTW89_ETSI][0][33] = 16,
+ [2][1][2][0][RTW89_MKK][1][33] = 48,
+ [2][1][2][0][RTW89_MKK][0][33] = 12,
+ [2][1][2][0][RTW89_IC][1][33] = 20,
+ [2][1][2][0][RTW89_KCC][1][33] = 38,
+ [2][1][2][0][RTW89_KCC][0][33] = 12,
+ [2][1][2][0][RTW89_ACMA][1][33] = 54,
+ [2][1][2][0][RTW89_ACMA][0][33] = 16,
+ [2][1][2][0][RTW89_CHILE][1][33] = 20,
+ [2][1][2][0][RTW89_QATAR][1][33] = 54,
+ [2][1][2][0][RTW89_QATAR][0][33] = 16,
+ [2][1][2][0][RTW89_UK][1][33] = 54,
+ [2][1][2][0][RTW89_UK][0][33] = 16,
+ [2][1][2][0][RTW89_FCC][1][41] = 22,
+ [2][1][2][0][RTW89_FCC][2][41] = 60,
+ [2][1][2][0][RTW89_ETSI][1][41] = 54,
+ [2][1][2][0][RTW89_ETSI][0][41] = 18,
+ [2][1][2][0][RTW89_MKK][1][41] = 48,
+ [2][1][2][0][RTW89_MKK][0][41] = 12,
+ [2][1][2][0][RTW89_IC][1][41] = 22,
+ [2][1][2][0][RTW89_KCC][1][41] = 38,
+ [2][1][2][0][RTW89_KCC][0][41] = 12,
+ [2][1][2][0][RTW89_ACMA][1][41] = 54,
+ [2][1][2][0][RTW89_ACMA][0][41] = 18,
+ [2][1][2][0][RTW89_CHILE][1][41] = 22,
+ [2][1][2][0][RTW89_QATAR][1][41] = 54,
+ [2][1][2][0][RTW89_QATAR][0][41] = 18,
+ [2][1][2][0][RTW89_UK][1][41] = 54,
+ [2][1][2][0][RTW89_UK][0][41] = 18,
+ [2][1][2][0][RTW89_FCC][1][48] = 22,
+ [2][1][2][0][RTW89_FCC][2][48] = 127,
+ [2][1][2][0][RTW89_ETSI][1][48] = 127,
+ [2][1][2][0][RTW89_ETSI][0][48] = 127,
+ [2][1][2][0][RTW89_MKK][1][48] = 127,
+ [2][1][2][0][RTW89_MKK][0][48] = 127,
+ [2][1][2][0][RTW89_IC][1][48] = 22,
+ [2][1][2][0][RTW89_KCC][1][48] = 38,
+ [2][1][2][0][RTW89_KCC][0][48] = 127,
+ [2][1][2][0][RTW89_ACMA][1][48] = 127,
+ [2][1][2][0][RTW89_ACMA][0][48] = 127,
+ [2][1][2][0][RTW89_CHILE][1][48] = 22,
+ [2][1][2][0][RTW89_QATAR][1][48] = 127,
+ [2][1][2][0][RTW89_QATAR][0][48] = 127,
+ [2][1][2][0][RTW89_UK][1][48] = 127,
+ [2][1][2][0][RTW89_UK][0][48] = 127,
+ [2][1][2][0][RTW89_FCC][1][56] = 20,
+ [2][1][2][0][RTW89_FCC][2][56] = 127,
+ [2][1][2][0][RTW89_ETSI][1][56] = 127,
+ [2][1][2][0][RTW89_ETSI][0][56] = 127,
+ [2][1][2][0][RTW89_MKK][1][56] = 127,
+ [2][1][2][0][RTW89_MKK][0][56] = 127,
+ [2][1][2][0][RTW89_IC][1][56] = 20,
+ [2][1][2][0][RTW89_KCC][1][56] = 38,
+ [2][1][2][0][RTW89_KCC][0][56] = 127,
+ [2][1][2][0][RTW89_ACMA][1][56] = 127,
+ [2][1][2][0][RTW89_ACMA][0][56] = 127,
+ [2][1][2][0][RTW89_CHILE][1][56] = 20,
+ [2][1][2][0][RTW89_QATAR][1][56] = 127,
+ [2][1][2][0][RTW89_QATAR][0][56] = 127,
+ [2][1][2][0][RTW89_UK][1][56] = 127,
+ [2][1][2][0][RTW89_UK][0][56] = 127,
+ [2][1][2][0][RTW89_FCC][1][63] = 22,
+ [2][1][2][0][RTW89_FCC][2][63] = 58,
+ [2][1][2][0][RTW89_ETSI][1][63] = 127,
+ [2][1][2][0][RTW89_ETSI][0][63] = 127,
+ [2][1][2][0][RTW89_MKK][1][63] = 127,
+ [2][1][2][0][RTW89_MKK][0][63] = 127,
+ [2][1][2][0][RTW89_IC][1][63] = 22,
+ [2][1][2][0][RTW89_KCC][1][63] = 38,
+ [2][1][2][0][RTW89_KCC][0][63] = 127,
+ [2][1][2][0][RTW89_ACMA][1][63] = 127,
+ [2][1][2][0][RTW89_ACMA][0][63] = 127,
+ [2][1][2][0][RTW89_CHILE][1][63] = 22,
+ [2][1][2][0][RTW89_QATAR][1][63] = 127,
+ [2][1][2][0][RTW89_QATAR][0][63] = 127,
+ [2][1][2][0][RTW89_UK][1][63] = 127,
+ [2][1][2][0][RTW89_UK][0][63] = 127,
+ [2][1][2][0][RTW89_FCC][1][71] = 20,
+ [2][1][2][0][RTW89_FCC][2][71] = 58,
+ [2][1][2][0][RTW89_ETSI][1][71] = 127,
+ [2][1][2][0][RTW89_ETSI][0][71] = 127,
+ [2][1][2][0][RTW89_MKK][1][71] = 127,
+ [2][1][2][0][RTW89_MKK][0][71] = 127,
+ [2][1][2][0][RTW89_IC][1][71] = 20,
+ [2][1][2][0][RTW89_KCC][1][71] = 38,
+ [2][1][2][0][RTW89_KCC][0][71] = 127,
+ [2][1][2][0][RTW89_ACMA][1][71] = 127,
+ [2][1][2][0][RTW89_ACMA][0][71] = 127,
+ [2][1][2][0][RTW89_CHILE][1][71] = 20,
+ [2][1][2][0][RTW89_QATAR][1][71] = 127,
+ [2][1][2][0][RTW89_QATAR][0][71] = 127,
+ [2][1][2][0][RTW89_UK][1][71] = 127,
+ [2][1][2][0][RTW89_UK][0][71] = 127,
+ [2][1][2][0][RTW89_FCC][1][78] = 20,
+ [2][1][2][0][RTW89_FCC][2][78] = 58,
+ [2][1][2][0][RTW89_ETSI][1][78] = 127,
+ [2][1][2][0][RTW89_ETSI][0][78] = 127,
+ [2][1][2][0][RTW89_MKK][1][78] = 127,
+ [2][1][2][0][RTW89_MKK][0][78] = 127,
+ [2][1][2][0][RTW89_IC][1][78] = 20,
+ [2][1][2][0][RTW89_KCC][1][78] = 38,
+ [2][1][2][0][RTW89_KCC][0][78] = 127,
+ [2][1][2][0][RTW89_ACMA][1][78] = 127,
+ [2][1][2][0][RTW89_ACMA][0][78] = 127,
+ [2][1][2][0][RTW89_CHILE][1][78] = 20,
+ [2][1][2][0][RTW89_QATAR][1][78] = 127,
+ [2][1][2][0][RTW89_QATAR][0][78] = 127,
+ [2][1][2][0][RTW89_UK][1][78] = 127,
+ [2][1][2][0][RTW89_UK][0][78] = 127,
+ [2][1][2][0][RTW89_FCC][1][86] = 20,
+ [2][1][2][0][RTW89_FCC][2][86] = 127,
+ [2][1][2][0][RTW89_ETSI][1][86] = 127,
+ [2][1][2][0][RTW89_ETSI][0][86] = 127,
+ [2][1][2][0][RTW89_MKK][1][86] = 127,
+ [2][1][2][0][RTW89_MKK][0][86] = 127,
+ [2][1][2][0][RTW89_IC][1][86] = 20,
+ [2][1][2][0][RTW89_KCC][1][86] = 38,
+ [2][1][2][0][RTW89_KCC][0][86] = 127,
+ [2][1][2][0][RTW89_ACMA][1][86] = 127,
+ [2][1][2][0][RTW89_ACMA][0][86] = 127,
+ [2][1][2][0][RTW89_CHILE][1][86] = 20,
+ [2][1][2][0][RTW89_QATAR][1][86] = 127,
+ [2][1][2][0][RTW89_QATAR][0][86] = 127,
+ [2][1][2][0][RTW89_UK][1][86] = 127,
+ [2][1][2][0][RTW89_UK][0][86] = 127,
+ [2][1][2][0][RTW89_FCC][1][93] = 22,
+ [2][1][2][0][RTW89_FCC][2][93] = 127,
+ [2][1][2][0][RTW89_ETSI][1][93] = 127,
+ [2][1][2][0][RTW89_ETSI][0][93] = 127,
+ [2][1][2][0][RTW89_MKK][1][93] = 127,
+ [2][1][2][0][RTW89_MKK][0][93] = 127,
+ [2][1][2][0][RTW89_IC][1][93] = 22,
+ [2][1][2][0][RTW89_KCC][1][93] = 38,
+ [2][1][2][0][RTW89_KCC][0][93] = 127,
+ [2][1][2][0][RTW89_ACMA][1][93] = 127,
+ [2][1][2][0][RTW89_ACMA][0][93] = 127,
+ [2][1][2][0][RTW89_CHILE][1][93] = 22,
+ [2][1][2][0][RTW89_QATAR][1][93] = 127,
+ [2][1][2][0][RTW89_QATAR][0][93] = 127,
+ [2][1][2][0][RTW89_UK][1][93] = 127,
+ [2][1][2][0][RTW89_UK][0][93] = 127,
+ [2][1][2][0][RTW89_FCC][1][101] = 22,
+ [2][1][2][0][RTW89_FCC][2][101] = 127,
+ [2][1][2][0][RTW89_ETSI][1][101] = 127,
+ [2][1][2][0][RTW89_ETSI][0][101] = 127,
+ [2][1][2][0][RTW89_MKK][1][101] = 127,
+ [2][1][2][0][RTW89_MKK][0][101] = 127,
+ [2][1][2][0][RTW89_IC][1][101] = 22,
+ [2][1][2][0][RTW89_KCC][1][101] = 38,
+ [2][1][2][0][RTW89_KCC][0][101] = 127,
+ [2][1][2][0][RTW89_ACMA][1][101] = 127,
+ [2][1][2][0][RTW89_ACMA][0][101] = 127,
+ [2][1][2][0][RTW89_CHILE][1][101] = 22,
+ [2][1][2][0][RTW89_QATAR][1][101] = 127,
+ [2][1][2][0][RTW89_QATAR][0][101] = 127,
+ [2][1][2][0][RTW89_UK][1][101] = 127,
+ [2][1][2][0][RTW89_UK][0][101] = 127,
+ [2][1][2][0][RTW89_FCC][1][108] = 127,
+ [2][1][2][0][RTW89_FCC][2][108] = 127,
+ [2][1][2][0][RTW89_ETSI][1][108] = 127,
+ [2][1][2][0][RTW89_ETSI][0][108] = 127,
+ [2][1][2][0][RTW89_MKK][1][108] = 127,
+ [2][1][2][0][RTW89_MKK][0][108] = 127,
+ [2][1][2][0][RTW89_IC][1][108] = 127,
+ [2][1][2][0][RTW89_KCC][1][108] = 127,
+ [2][1][2][0][RTW89_KCC][0][108] = 127,
+ [2][1][2][0][RTW89_ACMA][1][108] = 127,
+ [2][1][2][0][RTW89_ACMA][0][108] = 127,
+ [2][1][2][0][RTW89_CHILE][1][108] = 127,
+ [2][1][2][0][RTW89_QATAR][1][108] = 127,
+ [2][1][2][0][RTW89_QATAR][0][108] = 127,
+ [2][1][2][0][RTW89_UK][1][108] = 127,
+ [2][1][2][0][RTW89_UK][0][108] = 127,
+ [2][1][2][0][RTW89_FCC][1][116] = 127,
+ [2][1][2][0][RTW89_FCC][2][116] = 127,
+ [2][1][2][0][RTW89_ETSI][1][116] = 127,
+ [2][1][2][0][RTW89_ETSI][0][116] = 127,
+ [2][1][2][0][RTW89_MKK][1][116] = 127,
+ [2][1][2][0][RTW89_MKK][0][116] = 127,
+ [2][1][2][0][RTW89_IC][1][116] = 127,
+ [2][1][2][0][RTW89_KCC][1][116] = 127,
+ [2][1][2][0][RTW89_KCC][0][116] = 127,
+ [2][1][2][0][RTW89_ACMA][1][116] = 127,
+ [2][1][2][0][RTW89_ACMA][0][116] = 127,
+ [2][1][2][0][RTW89_CHILE][1][116] = 127,
+ [2][1][2][0][RTW89_QATAR][1][116] = 127,
+ [2][1][2][0][RTW89_QATAR][0][116] = 127,
+ [2][1][2][0][RTW89_UK][1][116] = 127,
+ [2][1][2][0][RTW89_UK][0][116] = 127,
+ [2][1][2][1][RTW89_FCC][1][3] = 22,
+ [2][1][2][1][RTW89_FCC][2][3] = 50,
+ [2][1][2][1][RTW89_ETSI][1][3] = 42,
+ [2][1][2][1][RTW89_ETSI][0][3] = 6,
+ [2][1][2][1][RTW89_MKK][1][3] = 52,
+ [2][1][2][1][RTW89_MKK][0][3] = 14,
+ [2][1][2][1][RTW89_IC][1][3] = 22,
+ [2][1][2][1][RTW89_KCC][1][3] = 38,
+ [2][1][2][1][RTW89_KCC][0][3] = 12,
+ [2][1][2][1][RTW89_ACMA][1][3] = 42,
+ [2][1][2][1][RTW89_ACMA][0][3] = 6,
+ [2][1][2][1][RTW89_CHILE][1][3] = 22,
+ [2][1][2][1][RTW89_QATAR][1][3] = 42,
+ [2][1][2][1][RTW89_QATAR][0][3] = 6,
+ [2][1][2][1][RTW89_UK][1][3] = 42,
+ [2][1][2][1][RTW89_UK][0][3] = 6,
+ [2][1][2][1][RTW89_FCC][1][11] = 20,
+ [2][1][2][1][RTW89_FCC][2][11] = 50,
+ [2][1][2][1][RTW89_ETSI][1][11] = 42,
+ [2][1][2][1][RTW89_ETSI][0][11] = 6,
+ [2][1][2][1][RTW89_MKK][1][11] = 52,
+ [2][1][2][1][RTW89_MKK][0][11] = 12,
+ [2][1][2][1][RTW89_IC][1][11] = 20,
+ [2][1][2][1][RTW89_KCC][1][11] = 38,
+ [2][1][2][1][RTW89_KCC][0][11] = 12,
+ [2][1][2][1][RTW89_ACMA][1][11] = 42,
+ [2][1][2][1][RTW89_ACMA][0][11] = 6,
+ [2][1][2][1][RTW89_CHILE][1][11] = 20,
+ [2][1][2][1][RTW89_QATAR][1][11] = 42,
+ [2][1][2][1][RTW89_QATAR][0][11] = 6,
+ [2][1][2][1][RTW89_UK][1][11] = 42,
+ [2][1][2][1][RTW89_UK][0][11] = 6,
+ [2][1][2][1][RTW89_FCC][1][18] = 20,
+ [2][1][2][1][RTW89_FCC][2][18] = 50,
+ [2][1][2][1][RTW89_ETSI][1][18] = 42,
+ [2][1][2][1][RTW89_ETSI][0][18] = 6,
+ [2][1][2][1][RTW89_MKK][1][18] = 52,
+ [2][1][2][1][RTW89_MKK][0][18] = 12,
+ [2][1][2][1][RTW89_IC][1][18] = 20,
+ [2][1][2][1][RTW89_KCC][1][18] = 38,
+ [2][1][2][1][RTW89_KCC][0][18] = 12,
+ [2][1][2][1][RTW89_ACMA][1][18] = 42,
+ [2][1][2][1][RTW89_ACMA][0][18] = 6,
+ [2][1][2][1][RTW89_CHILE][1][18] = 20,
+ [2][1][2][1][RTW89_QATAR][1][18] = 42,
+ [2][1][2][1][RTW89_QATAR][0][18] = 6,
+ [2][1][2][1][RTW89_UK][1][18] = 42,
+ [2][1][2][1][RTW89_UK][0][18] = 6,
+ [2][1][2][1][RTW89_FCC][1][26] = 20,
+ [2][1][2][1][RTW89_FCC][2][26] = 60,
+ [2][1][2][1][RTW89_ETSI][1][26] = 42,
+ [2][1][2][1][RTW89_ETSI][0][26] = 6,
+ [2][1][2][1][RTW89_MKK][1][26] = 52,
+ [2][1][2][1][RTW89_MKK][0][26] = 12,
+ [2][1][2][1][RTW89_IC][1][26] = 20,
+ [2][1][2][1][RTW89_KCC][1][26] = 38,
+ [2][1][2][1][RTW89_KCC][0][26] = 12,
+ [2][1][2][1][RTW89_ACMA][1][26] = 42,
+ [2][1][2][1][RTW89_ACMA][0][26] = 6,
+ [2][1][2][1][RTW89_CHILE][1][26] = 20,
+ [2][1][2][1][RTW89_QATAR][1][26] = 42,
+ [2][1][2][1][RTW89_QATAR][0][26] = 6,
+ [2][1][2][1][RTW89_UK][1][26] = 42,
+ [2][1][2][1][RTW89_UK][0][26] = 6,
+ [2][1][2][1][RTW89_FCC][1][33] = 20,
+ [2][1][2][1][RTW89_FCC][2][33] = 60,
+ [2][1][2][1][RTW89_ETSI][1][33] = 42,
+ [2][1][2][1][RTW89_ETSI][0][33] = 6,
+ [2][1][2][1][RTW89_MKK][1][33] = 48,
+ [2][1][2][1][RTW89_MKK][0][33] = 12,
+ [2][1][2][1][RTW89_IC][1][33] = 20,
+ [2][1][2][1][RTW89_KCC][1][33] = 38,
+ [2][1][2][1][RTW89_KCC][0][33] = 12,
+ [2][1][2][1][RTW89_ACMA][1][33] = 42,
+ [2][1][2][1][RTW89_ACMA][0][33] = 6,
+ [2][1][2][1][RTW89_CHILE][1][33] = 20,
+ [2][1][2][1][RTW89_QATAR][1][33] = 42,
+ [2][1][2][1][RTW89_QATAR][0][33] = 6,
+ [2][1][2][1][RTW89_UK][1][33] = 42,
+ [2][1][2][1][RTW89_UK][0][33] = 6,
+ [2][1][2][1][RTW89_FCC][1][41] = 22,
+ [2][1][2][1][RTW89_FCC][2][41] = 60,
+ [2][1][2][1][RTW89_ETSI][1][41] = 42,
+ [2][1][2][1][RTW89_ETSI][0][41] = 6,
+ [2][1][2][1][RTW89_MKK][1][41] = 48,
+ [2][1][2][1][RTW89_MKK][0][41] = 12,
+ [2][1][2][1][RTW89_IC][1][41] = 22,
+ [2][1][2][1][RTW89_KCC][1][41] = 38,
+ [2][1][2][1][RTW89_KCC][0][41] = 12,
+ [2][1][2][1][RTW89_ACMA][1][41] = 42,
+ [2][1][2][1][RTW89_ACMA][0][41] = 6,
+ [2][1][2][1][RTW89_CHILE][1][41] = 22,
+ [2][1][2][1][RTW89_QATAR][1][41] = 42,
+ [2][1][2][1][RTW89_QATAR][0][41] = 6,
+ [2][1][2][1][RTW89_UK][1][41] = 42,
+ [2][1][2][1][RTW89_UK][0][41] = 6,
+ [2][1][2][1][RTW89_FCC][1][48] = 22,
+ [2][1][2][1][RTW89_FCC][2][48] = 127,
+ [2][1][2][1][RTW89_ETSI][1][48] = 127,
+ [2][1][2][1][RTW89_ETSI][0][48] = 127,
+ [2][1][2][1][RTW89_MKK][1][48] = 127,
+ [2][1][2][1][RTW89_MKK][0][48] = 127,
+ [2][1][2][1][RTW89_IC][1][48] = 22,
+ [2][1][2][1][RTW89_KCC][1][48] = 38,
+ [2][1][2][1][RTW89_KCC][0][48] = 127,
+ [2][1][2][1][RTW89_ACMA][1][48] = 127,
+ [2][1][2][1][RTW89_ACMA][0][48] = 127,
+ [2][1][2][1][RTW89_CHILE][1][48] = 22,
+ [2][1][2][1][RTW89_QATAR][1][48] = 127,
+ [2][1][2][1][RTW89_QATAR][0][48] = 127,
+ [2][1][2][1][RTW89_UK][1][48] = 127,
+ [2][1][2][1][RTW89_UK][0][48] = 127,
+ [2][1][2][1][RTW89_FCC][1][56] = 20,
+ [2][1][2][1][RTW89_FCC][2][56] = 127,
+ [2][1][2][1][RTW89_ETSI][1][56] = 127,
+ [2][1][2][1][RTW89_ETSI][0][56] = 127,
+ [2][1][2][1][RTW89_MKK][1][56] = 127,
+ [2][1][2][1][RTW89_MKK][0][56] = 127,
+ [2][1][2][1][RTW89_IC][1][56] = 20,
+ [2][1][2][1][RTW89_KCC][1][56] = 38,
+ [2][1][2][1][RTW89_KCC][0][56] = 127,
+ [2][1][2][1][RTW89_ACMA][1][56] = 127,
+ [2][1][2][1][RTW89_ACMA][0][56] = 127,
+ [2][1][2][1][RTW89_CHILE][1][56] = 20,
+ [2][1][2][1][RTW89_QATAR][1][56] = 127,
+ [2][1][2][1][RTW89_QATAR][0][56] = 127,
+ [2][1][2][1][RTW89_UK][1][56] = 127,
+ [2][1][2][1][RTW89_UK][0][56] = 127,
+ [2][1][2][1][RTW89_FCC][1][63] = 22,
+ [2][1][2][1][RTW89_FCC][2][63] = 58,
+ [2][1][2][1][RTW89_ETSI][1][63] = 127,
+ [2][1][2][1][RTW89_ETSI][0][63] = 127,
+ [2][1][2][1][RTW89_MKK][1][63] = 127,
+ [2][1][2][1][RTW89_MKK][0][63] = 127,
+ [2][1][2][1][RTW89_IC][1][63] = 22,
+ [2][1][2][1][RTW89_KCC][1][63] = 38,
+ [2][1][2][1][RTW89_KCC][0][63] = 127,
+ [2][1][2][1][RTW89_ACMA][1][63] = 127,
+ [2][1][2][1][RTW89_ACMA][0][63] = 127,
+ [2][1][2][1][RTW89_CHILE][1][63] = 22,
+ [2][1][2][1][RTW89_QATAR][1][63] = 127,
+ [2][1][2][1][RTW89_QATAR][0][63] = 127,
+ [2][1][2][1][RTW89_UK][1][63] = 127,
+ [2][1][2][1][RTW89_UK][0][63] = 127,
+ [2][1][2][1][RTW89_FCC][1][71] = 20,
+ [2][1][2][1][RTW89_FCC][2][71] = 58,
+ [2][1][2][1][RTW89_ETSI][1][71] = 127,
+ [2][1][2][1][RTW89_ETSI][0][71] = 127,
+ [2][1][2][1][RTW89_MKK][1][71] = 127,
+ [2][1][2][1][RTW89_MKK][0][71] = 127,
+ [2][1][2][1][RTW89_IC][1][71] = 20,
+ [2][1][2][1][RTW89_KCC][1][71] = 38,
+ [2][1][2][1][RTW89_KCC][0][71] = 127,
+ [2][1][2][1][RTW89_ACMA][1][71] = 127,
+ [2][1][2][1][RTW89_ACMA][0][71] = 127,
+ [2][1][2][1][RTW89_CHILE][1][71] = 20,
+ [2][1][2][1][RTW89_QATAR][1][71] = 127,
+ [2][1][2][1][RTW89_QATAR][0][71] = 127,
+ [2][1][2][1][RTW89_UK][1][71] = 127,
+ [2][1][2][1][RTW89_UK][0][71] = 127,
+ [2][1][2][1][RTW89_FCC][1][78] = 20,
+ [2][1][2][1][RTW89_FCC][2][78] = 58,
+ [2][1][2][1][RTW89_ETSI][1][78] = 127,
+ [2][1][2][1][RTW89_ETSI][0][78] = 127,
+ [2][1][2][1][RTW89_MKK][1][78] = 127,
+ [2][1][2][1][RTW89_MKK][0][78] = 127,
+ [2][1][2][1][RTW89_IC][1][78] = 20,
+ [2][1][2][1][RTW89_KCC][1][78] = 38,
+ [2][1][2][1][RTW89_KCC][0][78] = 127,
+ [2][1][2][1][RTW89_ACMA][1][78] = 127,
+ [2][1][2][1][RTW89_ACMA][0][78] = 127,
+ [2][1][2][1][RTW89_CHILE][1][78] = 20,
+ [2][1][2][1][RTW89_QATAR][1][78] = 127,
+ [2][1][2][1][RTW89_QATAR][0][78] = 127,
+ [2][1][2][1][RTW89_UK][1][78] = 127,
+ [2][1][2][1][RTW89_UK][0][78] = 127,
+ [2][1][2][1][RTW89_FCC][1][86] = 20,
+ [2][1][2][1][RTW89_FCC][2][86] = 127,
+ [2][1][2][1][RTW89_ETSI][1][86] = 127,
+ [2][1][2][1][RTW89_ETSI][0][86] = 127,
+ [2][1][2][1][RTW89_MKK][1][86] = 127,
+ [2][1][2][1][RTW89_MKK][0][86] = 127,
+ [2][1][2][1][RTW89_IC][1][86] = 20,
+ [2][1][2][1][RTW89_KCC][1][86] = 38,
+ [2][1][2][1][RTW89_KCC][0][86] = 127,
+ [2][1][2][1][RTW89_ACMA][1][86] = 127,
+ [2][1][2][1][RTW89_ACMA][0][86] = 127,
+ [2][1][2][1][RTW89_CHILE][1][86] = 20,
+ [2][1][2][1][RTW89_QATAR][1][86] = 127,
+ [2][1][2][1][RTW89_QATAR][0][86] = 127,
+ [2][1][2][1][RTW89_UK][1][86] = 127,
+ [2][1][2][1][RTW89_UK][0][86] = 127,
+ [2][1][2][1][RTW89_FCC][1][93] = 22,
+ [2][1][2][1][RTW89_FCC][2][93] = 127,
+ [2][1][2][1][RTW89_ETSI][1][93] = 127,
+ [2][1][2][1][RTW89_ETSI][0][93] = 127,
+ [2][1][2][1][RTW89_MKK][1][93] = 127,
+ [2][1][2][1][RTW89_MKK][0][93] = 127,
+ [2][1][2][1][RTW89_IC][1][93] = 22,
+ [2][1][2][1][RTW89_KCC][1][93] = 38,
+ [2][1][2][1][RTW89_KCC][0][93] = 127,
+ [2][1][2][1][RTW89_ACMA][1][93] = 127,
+ [2][1][2][1][RTW89_ACMA][0][93] = 127,
+ [2][1][2][1][RTW89_CHILE][1][93] = 22,
+ [2][1][2][1][RTW89_QATAR][1][93] = 127,
+ [2][1][2][1][RTW89_QATAR][0][93] = 127,
+ [2][1][2][1][RTW89_UK][1][93] = 127,
+ [2][1][2][1][RTW89_UK][0][93] = 127,
+ [2][1][2][1][RTW89_FCC][1][101] = 22,
+ [2][1][2][1][RTW89_FCC][2][101] = 127,
+ [2][1][2][1][RTW89_ETSI][1][101] = 127,
+ [2][1][2][1][RTW89_ETSI][0][101] = 127,
+ [2][1][2][1][RTW89_MKK][1][101] = 127,
+ [2][1][2][1][RTW89_MKK][0][101] = 127,
+ [2][1][2][1][RTW89_IC][1][101] = 22,
+ [2][1][2][1][RTW89_KCC][1][101] = 38,
+ [2][1][2][1][RTW89_KCC][0][101] = 127,
+ [2][1][2][1][RTW89_ACMA][1][101] = 127,
+ [2][1][2][1][RTW89_ACMA][0][101] = 127,
+ [2][1][2][1][RTW89_CHILE][1][101] = 22,
+ [2][1][2][1][RTW89_QATAR][1][101] = 127,
+ [2][1][2][1][RTW89_QATAR][0][101] = 127,
+ [2][1][2][1][RTW89_UK][1][101] = 127,
+ [2][1][2][1][RTW89_UK][0][101] = 127,
+ [2][1][2][1][RTW89_FCC][1][108] = 127,
+ [2][1][2][1][RTW89_FCC][2][108] = 127,
+ [2][1][2][1][RTW89_ETSI][1][108] = 127,
+ [2][1][2][1][RTW89_ETSI][0][108] = 127,
+ [2][1][2][1][RTW89_MKK][1][108] = 127,
+ [2][1][2][1][RTW89_MKK][0][108] = 127,
+ [2][1][2][1][RTW89_IC][1][108] = 127,
+ [2][1][2][1][RTW89_KCC][1][108] = 127,
+ [2][1][2][1][RTW89_KCC][0][108] = 127,
+ [2][1][2][1][RTW89_ACMA][1][108] = 127,
+ [2][1][2][1][RTW89_ACMA][0][108] = 127,
+ [2][1][2][1][RTW89_CHILE][1][108] = 127,
+ [2][1][2][1][RTW89_QATAR][1][108] = 127,
+ [2][1][2][1][RTW89_QATAR][0][108] = 127,
+ [2][1][2][1][RTW89_UK][1][108] = 127,
+ [2][1][2][1][RTW89_UK][0][108] = 127,
+ [2][1][2][1][RTW89_FCC][1][116] = 127,
+ [2][1][2][1][RTW89_FCC][2][116] = 127,
+ [2][1][2][1][RTW89_ETSI][1][116] = 127,
+ [2][1][2][1][RTW89_ETSI][0][116] = 127,
+ [2][1][2][1][RTW89_MKK][1][116] = 127,
+ [2][1][2][1][RTW89_MKK][0][116] = 127,
+ [2][1][2][1][RTW89_IC][1][116] = 127,
+ [2][1][2][1][RTW89_KCC][1][116] = 127,
+ [2][1][2][1][RTW89_KCC][0][116] = 127,
+ [2][1][2][1][RTW89_ACMA][1][116] = 127,
+ [2][1][2][1][RTW89_ACMA][0][116] = 127,
+ [2][1][2][1][RTW89_CHILE][1][116] = 127,
+ [2][1][2][1][RTW89_QATAR][1][116] = 127,
+ [2][1][2][1][RTW89_QATAR][0][116] = 127,
+ [2][1][2][1][RTW89_UK][1][116] = 127,
+ [2][1][2][1][RTW89_UK][0][116] = 127,
+ [3][0][2][0][RTW89_FCC][1][7] = 52,
+ [3][0][2][0][RTW89_FCC][2][7] = 52,
+ [3][0][2][0][RTW89_ETSI][1][7] = 50,
+ [3][0][2][0][RTW89_ETSI][0][7] = 30,
+ [3][0][2][0][RTW89_MKK][1][7] = 50,
+ [3][0][2][0][RTW89_MKK][0][7] = 22,
+ [3][0][2][0][RTW89_IC][1][7] = 52,
+ [3][0][2][0][RTW89_KCC][1][7] = 42,
+ [3][0][2][0][RTW89_KCC][0][7] = 24,
+ [3][0][2][0][RTW89_ACMA][1][7] = 50,
+ [3][0][2][0][RTW89_ACMA][0][7] = 30,
+ [3][0][2][0][RTW89_CHILE][1][7] = 52,
+ [3][0][2][0][RTW89_QATAR][1][7] = 50,
+ [3][0][2][0][RTW89_QATAR][0][7] = 30,
+ [3][0][2][0][RTW89_UK][1][7] = 50,
+ [3][0][2][0][RTW89_UK][0][7] = 30,
+ [3][0][2][0][RTW89_FCC][1][22] = 52,
+ [3][0][2][0][RTW89_FCC][2][22] = 52,
+ [3][0][2][0][RTW89_ETSI][1][22] = 50,
+ [3][0][2][0][RTW89_ETSI][0][22] = 30,
+ [3][0][2][0][RTW89_MKK][1][22] = 50,
+ [3][0][2][0][RTW89_MKK][0][22] = 20,
+ [3][0][2][0][RTW89_IC][1][22] = 52,
+ [3][0][2][0][RTW89_KCC][1][22] = 42,
+ [3][0][2][0][RTW89_KCC][0][22] = 24,
+ [3][0][2][0][RTW89_ACMA][1][22] = 50,
+ [3][0][2][0][RTW89_ACMA][0][22] = 30,
+ [3][0][2][0][RTW89_CHILE][1][22] = 52,
+ [3][0][2][0][RTW89_QATAR][1][22] = 50,
+ [3][0][2][0][RTW89_QATAR][0][22] = 30,
+ [3][0][2][0][RTW89_UK][1][22] = 50,
+ [3][0][2][0][RTW89_UK][0][22] = 30,
+ [3][0][2][0][RTW89_FCC][1][37] = 52,
+ [3][0][2][0][RTW89_FCC][2][37] = 52,
+ [3][0][2][0][RTW89_ETSI][1][37] = 50,
+ [3][0][2][0][RTW89_ETSI][0][37] = 30,
+ [3][0][2][0][RTW89_MKK][1][37] = 50,
+ [3][0][2][0][RTW89_MKK][0][37] = 20,
+ [3][0][2][0][RTW89_IC][1][37] = 52,
+ [3][0][2][0][RTW89_KCC][1][37] = 42,
+ [3][0][2][0][RTW89_KCC][0][37] = 24,
+ [3][0][2][0][RTW89_ACMA][1][37] = 50,
+ [3][0][2][0][RTW89_ACMA][0][37] = 30,
+ [3][0][2][0][RTW89_CHILE][1][37] = 52,
+ [3][0][2][0][RTW89_QATAR][1][37] = 50,
+ [3][0][2][0][RTW89_QATAR][0][37] = 30,
+ [3][0][2][0][RTW89_UK][1][37] = 50,
+ [3][0][2][0][RTW89_UK][0][37] = 30,
+ [3][0][2][0][RTW89_FCC][1][52] = 54,
+ [3][0][2][0][RTW89_FCC][2][52] = 127,
+ [3][0][2][0][RTW89_ETSI][1][52] = 127,
+ [3][0][2][0][RTW89_ETSI][0][52] = 127,
+ [3][0][2][0][RTW89_MKK][1][52] = 127,
+ [3][0][2][0][RTW89_MKK][0][52] = 127,
+ [3][0][2][0][RTW89_IC][1][52] = 54,
+ [3][0][2][0][RTW89_KCC][1][52] = 56,
+ [3][0][2][0][RTW89_KCC][0][52] = 127,
+ [3][0][2][0][RTW89_ACMA][1][52] = 127,
+ [3][0][2][0][RTW89_ACMA][0][52] = 127,
+ [3][0][2][0][RTW89_CHILE][1][52] = 54,
+ [3][0][2][0][RTW89_QATAR][1][52] = 127,
+ [3][0][2][0][RTW89_QATAR][0][52] = 127,
+ [3][0][2][0][RTW89_UK][1][52] = 127,
+ [3][0][2][0][RTW89_UK][0][52] = 127,
+ [3][0][2][0][RTW89_FCC][1][67] = 54,
+ [3][0][2][0][RTW89_FCC][2][67] = 54,
+ [3][0][2][0][RTW89_ETSI][1][67] = 127,
+ [3][0][2][0][RTW89_ETSI][0][67] = 127,
+ [3][0][2][0][RTW89_MKK][1][67] = 127,
+ [3][0][2][0][RTW89_MKK][0][67] = 127,
+ [3][0][2][0][RTW89_IC][1][67] = 54,
+ [3][0][2][0][RTW89_KCC][1][67] = 54,
+ [3][0][2][0][RTW89_KCC][0][67] = 127,
+ [3][0][2][0][RTW89_ACMA][1][67] = 127,
+ [3][0][2][0][RTW89_ACMA][0][67] = 127,
+ [3][0][2][0][RTW89_CHILE][1][67] = 54,
+ [3][0][2][0][RTW89_QATAR][1][67] = 127,
+ [3][0][2][0][RTW89_QATAR][0][67] = 127,
+ [3][0][2][0][RTW89_UK][1][67] = 127,
+ [3][0][2][0][RTW89_UK][0][67] = 127,
+ [3][0][2][0][RTW89_FCC][1][82] = 46,
+ [3][0][2][0][RTW89_FCC][2][82] = 127,
+ [3][0][2][0][RTW89_ETSI][1][82] = 127,
+ [3][0][2][0][RTW89_ETSI][0][82] = 127,
+ [3][0][2][0][RTW89_MKK][1][82] = 127,
+ [3][0][2][0][RTW89_MKK][0][82] = 127,
+ [3][0][2][0][RTW89_IC][1][82] = 46,
+ [3][0][2][0][RTW89_KCC][1][82] = 26,
+ [3][0][2][0][RTW89_KCC][0][82] = 127,
+ [3][0][2][0][RTW89_ACMA][1][82] = 127,
+ [3][0][2][0][RTW89_ACMA][0][82] = 127,
+ [3][0][2][0][RTW89_CHILE][1][82] = 46,
+ [3][0][2][0][RTW89_QATAR][1][82] = 127,
+ [3][0][2][0][RTW89_QATAR][0][82] = 127,
+ [3][0][2][0][RTW89_UK][1][82] = 127,
+ [3][0][2][0][RTW89_UK][0][82] = 127,
+ [3][0][2][0][RTW89_FCC][1][97] = 40,
+ [3][0][2][0][RTW89_FCC][2][97] = 127,
+ [3][0][2][0][RTW89_ETSI][1][97] = 127,
+ [3][0][2][0][RTW89_ETSI][0][97] = 127,
+ [3][0][2][0][RTW89_MKK][1][97] = 127,
+ [3][0][2][0][RTW89_MKK][0][97] = 127,
+ [3][0][2][0][RTW89_IC][1][97] = 40,
+ [3][0][2][0][RTW89_KCC][1][97] = 26,
+ [3][0][2][0][RTW89_KCC][0][97] = 127,
+ [3][0][2][0][RTW89_ACMA][1][97] = 127,
+ [3][0][2][0][RTW89_ACMA][0][97] = 127,
+ [3][0][2][0][RTW89_CHILE][1][97] = 40,
+ [3][0][2][0][RTW89_QATAR][1][97] = 127,
+ [3][0][2][0][RTW89_QATAR][0][97] = 127,
+ [3][0][2][0][RTW89_UK][1][97] = 127,
+ [3][0][2][0][RTW89_UK][0][97] = 127,
+ [3][0][2][0][RTW89_FCC][1][112] = 127,
+ [3][0][2][0][RTW89_FCC][2][112] = 127,
+ [3][0][2][0][RTW89_ETSI][1][112] = 127,
+ [3][0][2][0][RTW89_ETSI][0][112] = 127,
+ [3][0][2][0][RTW89_MKK][1][112] = 127,
+ [3][0][2][0][RTW89_MKK][0][112] = 127,
+ [3][0][2][0][RTW89_IC][1][112] = 127,
+ [3][0][2][0][RTW89_KCC][1][112] = 127,
+ [3][0][2][0][RTW89_KCC][0][112] = 127,
+ [3][0][2][0][RTW89_ACMA][1][112] = 127,
+ [3][0][2][0][RTW89_ACMA][0][112] = 127,
+ [3][0][2][0][RTW89_CHILE][1][112] = 127,
+ [3][0][2][0][RTW89_QATAR][1][112] = 127,
+ [3][0][2][0][RTW89_QATAR][0][112] = 127,
+ [3][0][2][0][RTW89_UK][1][112] = 127,
+ [3][0][2][0][RTW89_UK][0][112] = 127,
+ [3][1][2][0][RTW89_FCC][1][7] = 32,
+ [3][1][2][0][RTW89_FCC][2][7] = 46,
+ [3][1][2][0][RTW89_ETSI][1][7] = 50,
+ [3][1][2][0][RTW89_ETSI][0][7] = 18,
+ [3][1][2][0][RTW89_MKK][1][7] = 38,
+ [3][1][2][0][RTW89_MKK][0][7] = 10,
+ [3][1][2][0][RTW89_IC][1][7] = 32,
+ [3][1][2][0][RTW89_KCC][1][7] = 40,
+ [3][1][2][0][RTW89_KCC][0][7] = 12,
+ [3][1][2][0][RTW89_ACMA][1][7] = 50,
+ [3][1][2][0][RTW89_ACMA][0][7] = 18,
+ [3][1][2][0][RTW89_CHILE][1][7] = 32,
+ [3][1][2][0][RTW89_QATAR][1][7] = 50,
+ [3][1][2][0][RTW89_QATAR][0][7] = 18,
+ [3][1][2][0][RTW89_UK][1][7] = 50,
+ [3][1][2][0][RTW89_UK][0][7] = 18,
+ [3][1][2][0][RTW89_FCC][1][22] = 30,
+ [3][1][2][0][RTW89_FCC][2][22] = 52,
+ [3][1][2][0][RTW89_ETSI][1][22] = 46,
+ [3][1][2][0][RTW89_ETSI][0][22] = 16,
+ [3][1][2][0][RTW89_MKK][1][22] = 48,
+ [3][1][2][0][RTW89_MKK][0][22] = 8,
+ [3][1][2][0][RTW89_IC][1][22] = 30,
+ [3][1][2][0][RTW89_KCC][1][22] = 40,
+ [3][1][2][0][RTW89_KCC][0][22] = 12,
+ [3][1][2][0][RTW89_ACMA][1][22] = 46,
+ [3][1][2][0][RTW89_ACMA][0][22] = 16,
+ [3][1][2][0][RTW89_CHILE][1][22] = 30,
+ [3][1][2][0][RTW89_QATAR][1][22] = 46,
+ [3][1][2][0][RTW89_QATAR][0][22] = 16,
+ [3][1][2][0][RTW89_UK][1][22] = 46,
+ [3][1][2][0][RTW89_UK][0][22] = 16,
+ [3][1][2][0][RTW89_FCC][1][37] = 30,
+ [3][1][2][0][RTW89_FCC][2][37] = 52,
+ [3][1][2][0][RTW89_ETSI][1][37] = 46,
+ [3][1][2][0][RTW89_ETSI][0][37] = 16,
+ [3][1][2][0][RTW89_MKK][1][37] = 48,
+ [3][1][2][0][RTW89_MKK][0][37] = 8,
+ [3][1][2][0][RTW89_IC][1][37] = 30,
+ [3][1][2][0][RTW89_KCC][1][37] = 40,
+ [3][1][2][0][RTW89_KCC][0][37] = 12,
+ [3][1][2][0][RTW89_ACMA][1][37] = 46,
+ [3][1][2][0][RTW89_ACMA][0][37] = 16,
+ [3][1][2][0][RTW89_CHILE][1][37] = 30,
+ [3][1][2][0][RTW89_QATAR][1][37] = 46,
+ [3][1][2][0][RTW89_QATAR][0][37] = 16,
+ [3][1][2][0][RTW89_UK][1][37] = 46,
+ [3][1][2][0][RTW89_UK][0][37] = 16,
+ [3][1][2][0][RTW89_FCC][1][52] = 30,
+ [3][1][2][0][RTW89_FCC][2][52] = 127,
+ [3][1][2][0][RTW89_ETSI][1][52] = 127,
+ [3][1][2][0][RTW89_ETSI][0][52] = 127,
+ [3][1][2][0][RTW89_MKK][1][52] = 127,
+ [3][1][2][0][RTW89_MKK][0][52] = 127,
+ [3][1][2][0][RTW89_IC][1][52] = 30,
+ [3][1][2][0][RTW89_KCC][1][52] = 48,
+ [3][1][2][0][RTW89_KCC][0][52] = 127,
+ [3][1][2][0][RTW89_ACMA][1][52] = 127,
+ [3][1][2][0][RTW89_ACMA][0][52] = 127,
+ [3][1][2][0][RTW89_CHILE][1][52] = 30,
+ [3][1][2][0][RTW89_QATAR][1][52] = 127,
+ [3][1][2][0][RTW89_QATAR][0][52] = 127,
+ [3][1][2][0][RTW89_UK][1][52] = 127,
+ [3][1][2][0][RTW89_UK][0][52] = 127,
+ [3][1][2][0][RTW89_FCC][1][67] = 32,
+ [3][1][2][0][RTW89_FCC][2][67] = 54,
+ [3][1][2][0][RTW89_ETSI][1][67] = 127,
+ [3][1][2][0][RTW89_ETSI][0][67] = 127,
+ [3][1][2][0][RTW89_MKK][1][67] = 127,
+ [3][1][2][0][RTW89_MKK][0][67] = 127,
+ [3][1][2][0][RTW89_IC][1][67] = 32,
+ [3][1][2][0][RTW89_KCC][1][67] = 48,
+ [3][1][2][0][RTW89_KCC][0][67] = 127,
+ [3][1][2][0][RTW89_ACMA][1][67] = 127,
+ [3][1][2][0][RTW89_ACMA][0][67] = 127,
+ [3][1][2][0][RTW89_CHILE][1][67] = 32,
+ [3][1][2][0][RTW89_QATAR][1][67] = 127,
+ [3][1][2][0][RTW89_QATAR][0][67] = 127,
+ [3][1][2][0][RTW89_UK][1][67] = 127,
+ [3][1][2][0][RTW89_UK][0][67] = 127,
+ [3][1][2][0][RTW89_FCC][1][82] = 32,
+ [3][1][2][0][RTW89_FCC][2][82] = 127,
+ [3][1][2][0][RTW89_ETSI][1][82] = 127,
+ [3][1][2][0][RTW89_ETSI][0][82] = 127,
+ [3][1][2][0][RTW89_MKK][1][82] = 127,
+ [3][1][2][0][RTW89_MKK][0][82] = 127,
+ [3][1][2][0][RTW89_IC][1][82] = 32,
+ [3][1][2][0][RTW89_KCC][1][82] = 24,
+ [3][1][2][0][RTW89_KCC][0][82] = 127,
+ [3][1][2][0][RTW89_ACMA][1][82] = 127,
+ [3][1][2][0][RTW89_ACMA][0][82] = 127,
+ [3][1][2][0][RTW89_CHILE][1][82] = 32,
+ [3][1][2][0][RTW89_QATAR][1][82] = 127,
+ [3][1][2][0][RTW89_QATAR][0][82] = 127,
+ [3][1][2][0][RTW89_UK][1][82] = 127,
+ [3][1][2][0][RTW89_UK][0][82] = 127,
+ [3][1][2][0][RTW89_FCC][1][97] = 32,
+ [3][1][2][0][RTW89_FCC][2][97] = 127,
+ [3][1][2][0][RTW89_ETSI][1][97] = 127,
+ [3][1][2][0][RTW89_ETSI][0][97] = 127,
+ [3][1][2][0][RTW89_MKK][1][97] = 127,
+ [3][1][2][0][RTW89_MKK][0][97] = 127,
+ [3][1][2][0][RTW89_IC][1][97] = 32,
+ [3][1][2][0][RTW89_KCC][1][97] = 24,
+ [3][1][2][0][RTW89_KCC][0][97] = 127,
+ [3][1][2][0][RTW89_ACMA][1][97] = 127,
+ [3][1][2][0][RTW89_ACMA][0][97] = 127,
+ [3][1][2][0][RTW89_CHILE][1][97] = 32,
+ [3][1][2][0][RTW89_QATAR][1][97] = 127,
+ [3][1][2][0][RTW89_QATAR][0][97] = 127,
+ [3][1][2][0][RTW89_UK][1][97] = 127,
+ [3][1][2][0][RTW89_UK][0][97] = 127,
+ [3][1][2][0][RTW89_FCC][1][112] = 127,
+ [3][1][2][0][RTW89_FCC][2][112] = 127,
+ [3][1][2][0][RTW89_ETSI][1][112] = 127,
+ [3][1][2][0][RTW89_ETSI][0][112] = 127,
+ [3][1][2][0][RTW89_MKK][1][112] = 127,
+ [3][1][2][0][RTW89_MKK][0][112] = 127,
+ [3][1][2][0][RTW89_IC][1][112] = 127,
+ [3][1][2][0][RTW89_KCC][1][112] = 127,
+ [3][1][2][0][RTW89_KCC][0][112] = 127,
+ [3][1][2][0][RTW89_ACMA][1][112] = 127,
+ [3][1][2][0][RTW89_ACMA][0][112] = 127,
+ [3][1][2][0][RTW89_CHILE][1][112] = 127,
+ [3][1][2][0][RTW89_QATAR][1][112] = 127,
+ [3][1][2][0][RTW89_QATAR][0][112] = 127,
+ [3][1][2][0][RTW89_UK][1][112] = 127,
+ [3][1][2][0][RTW89_UK][0][112] = 127,
+ [3][1][2][1][RTW89_FCC][1][7] = 32,
+ [3][1][2][1][RTW89_FCC][2][7] = 46,
+ [3][1][2][1][RTW89_ETSI][1][7] = 42,
+ [3][1][2][1][RTW89_ETSI][0][7] = 6,
+ [3][1][2][1][RTW89_MKK][1][7] = 38,
+ [3][1][2][1][RTW89_MKK][0][7] = 10,
+ [3][1][2][1][RTW89_IC][1][7] = 32,
+ [3][1][2][1][RTW89_KCC][1][7] = 40,
+ [3][1][2][1][RTW89_KCC][0][7] = 12,
+ [3][1][2][1][RTW89_ACMA][1][7] = 42,
+ [3][1][2][1][RTW89_ACMA][0][7] = 6,
+ [3][1][2][1][RTW89_CHILE][1][7] = 32,
+ [3][1][2][1][RTW89_QATAR][1][7] = 42,
+ [3][1][2][1][RTW89_QATAR][0][7] = 6,
+ [3][1][2][1][RTW89_UK][1][7] = 42,
+ [3][1][2][1][RTW89_UK][0][7] = 6,
+ [3][1][2][1][RTW89_FCC][1][22] = 30,
+ [3][1][2][1][RTW89_FCC][2][22] = 52,
+ [3][1][2][1][RTW89_ETSI][1][22] = 42,
+ [3][1][2][1][RTW89_ETSI][0][22] = 6,
+ [3][1][2][1][RTW89_MKK][1][22] = 48,
+ [3][1][2][1][RTW89_MKK][0][22] = 8,
+ [3][1][2][1][RTW89_IC][1][22] = 30,
+ [3][1][2][1][RTW89_KCC][1][22] = 40,
+ [3][1][2][1][RTW89_KCC][0][22] = 12,
+ [3][1][2][1][RTW89_ACMA][1][22] = 42,
+ [3][1][2][1][RTW89_ACMA][0][22] = 6,
+ [3][1][2][1][RTW89_CHILE][1][22] = 30,
+ [3][1][2][1][RTW89_QATAR][1][22] = 42,
+ [3][1][2][1][RTW89_QATAR][0][22] = 6,
+ [3][1][2][1][RTW89_UK][1][22] = 42,
+ [3][1][2][1][RTW89_UK][0][22] = 6,
+ [3][1][2][1][RTW89_FCC][1][37] = 30,
+ [3][1][2][1][RTW89_FCC][2][37] = 52,
+ [3][1][2][1][RTW89_ETSI][1][37] = 42,
+ [3][1][2][1][RTW89_ETSI][0][37] = 6,
+ [3][1][2][1][RTW89_MKK][1][37] = 48,
+ [3][1][2][1][RTW89_MKK][0][37] = 8,
+ [3][1][2][1][RTW89_IC][1][37] = 30,
+ [3][1][2][1][RTW89_KCC][1][37] = 40,
+ [3][1][2][1][RTW89_KCC][0][37] = 12,
+ [3][1][2][1][RTW89_ACMA][1][37] = 42,
+ [3][1][2][1][RTW89_ACMA][0][37] = 6,
+ [3][1][2][1][RTW89_CHILE][1][37] = 30,
+ [3][1][2][1][RTW89_QATAR][1][37] = 42,
+ [3][1][2][1][RTW89_QATAR][0][37] = 6,
+ [3][1][2][1][RTW89_UK][1][37] = 42,
+ [3][1][2][1][RTW89_UK][0][37] = 6,
+ [3][1][2][1][RTW89_FCC][1][52] = 30,
+ [3][1][2][1][RTW89_FCC][2][52] = 127,
+ [3][1][2][1][RTW89_ETSI][1][52] = 127,
+ [3][1][2][1][RTW89_ETSI][0][52] = 127,
+ [3][1][2][1][RTW89_MKK][1][52] = 127,
+ [3][1][2][1][RTW89_MKK][0][52] = 127,
+ [3][1][2][1][RTW89_IC][1][52] = 30,
+ [3][1][2][1][RTW89_KCC][1][52] = 48,
+ [3][1][2][1][RTW89_KCC][0][52] = 127,
+ [3][1][2][1][RTW89_ACMA][1][52] = 127,
+ [3][1][2][1][RTW89_ACMA][0][52] = 127,
+ [3][1][2][1][RTW89_CHILE][1][52] = 30,
+ [3][1][2][1][RTW89_QATAR][1][52] = 127,
+ [3][1][2][1][RTW89_QATAR][0][52] = 127,
+ [3][1][2][1][RTW89_UK][1][52] = 127,
+ [3][1][2][1][RTW89_UK][0][52] = 127,
+ [3][1][2][1][RTW89_FCC][1][67] = 32,
+ [3][1][2][1][RTW89_FCC][2][67] = 54,
+ [3][1][2][1][RTW89_ETSI][1][67] = 127,
+ [3][1][2][1][RTW89_ETSI][0][67] = 127,
+ [3][1][2][1][RTW89_MKK][1][67] = 127,
+ [3][1][2][1][RTW89_MKK][0][67] = 127,
+ [3][1][2][1][RTW89_IC][1][67] = 32,
+ [3][1][2][1][RTW89_KCC][1][67] = 48,
+ [3][1][2][1][RTW89_KCC][0][67] = 127,
+ [3][1][2][1][RTW89_ACMA][1][67] = 127,
+ [3][1][2][1][RTW89_ACMA][0][67] = 127,
+ [3][1][2][1][RTW89_CHILE][1][67] = 32,
+ [3][1][2][1][RTW89_QATAR][1][67] = 127,
+ [3][1][2][1][RTW89_QATAR][0][67] = 127,
+ [3][1][2][1][RTW89_UK][1][67] = 127,
+ [3][1][2][1][RTW89_UK][0][67] = 127,
+ [3][1][2][1][RTW89_FCC][1][82] = 32,
+ [3][1][2][1][RTW89_FCC][2][82] = 127,
+ [3][1][2][1][RTW89_ETSI][1][82] = 127,
+ [3][1][2][1][RTW89_ETSI][0][82] = 127,
+ [3][1][2][1][RTW89_MKK][1][82] = 127,
+ [3][1][2][1][RTW89_MKK][0][82] = 127,
+ [3][1][2][1][RTW89_IC][1][82] = 32,
+ [3][1][2][1][RTW89_KCC][1][82] = 24,
+ [3][1][2][1][RTW89_KCC][0][82] = 127,
+ [3][1][2][1][RTW89_ACMA][1][82] = 127,
+ [3][1][2][1][RTW89_ACMA][0][82] = 127,
+ [3][1][2][1][RTW89_CHILE][1][82] = 32,
+ [3][1][2][1][RTW89_QATAR][1][82] = 127,
+ [3][1][2][1][RTW89_QATAR][0][82] = 127,
+ [3][1][2][1][RTW89_UK][1][82] = 127,
+ [3][1][2][1][RTW89_UK][0][82] = 127,
+ [3][1][2][1][RTW89_FCC][1][97] = 32,
+ [3][1][2][1][RTW89_FCC][2][97] = 127,
+ [3][1][2][1][RTW89_ETSI][1][97] = 127,
+ [3][1][2][1][RTW89_ETSI][0][97] = 127,
+ [3][1][2][1][RTW89_MKK][1][97] = 127,
+ [3][1][2][1][RTW89_MKK][0][97] = 127,
+ [3][1][2][1][RTW89_IC][1][97] = 32,
+ [3][1][2][1][RTW89_KCC][1][97] = 24,
+ [3][1][2][1][RTW89_KCC][0][97] = 127,
+ [3][1][2][1][RTW89_ACMA][1][97] = 127,
+ [3][1][2][1][RTW89_ACMA][0][97] = 127,
+ [3][1][2][1][RTW89_CHILE][1][97] = 32,
+ [3][1][2][1][RTW89_QATAR][1][97] = 127,
+ [3][1][2][1][RTW89_QATAR][0][97] = 127,
+ [3][1][2][1][RTW89_UK][1][97] = 127,
+ [3][1][2][1][RTW89_UK][0][97] = 127,
+ [3][1][2][1][RTW89_FCC][1][112] = 127,
+ [3][1][2][1][RTW89_FCC][2][112] = 127,
+ [3][1][2][1][RTW89_ETSI][1][112] = 127,
+ [3][1][2][1][RTW89_ETSI][0][112] = 127,
+ [3][1][2][1][RTW89_MKK][1][112] = 127,
+ [3][1][2][1][RTW89_MKK][0][112] = 127,
+ [3][1][2][1][RTW89_IC][1][112] = 127,
+ [3][1][2][1][RTW89_KCC][1][112] = 127,
+ [3][1][2][1][RTW89_KCC][0][112] = 127,
+ [3][1][2][1][RTW89_ACMA][1][112] = 127,
+ [3][1][2][1][RTW89_ACMA][0][112] = 127,
+ [3][1][2][1][RTW89_CHILE][1][112] = 127,
+ [3][1][2][1][RTW89_QATAR][1][112] = 127,
+ [3][1][2][1][RTW89_QATAR][0][112] = 127,
+ [3][1][2][1][RTW89_UK][1][112] = 127,
+ [3][1][2][1][RTW89_UK][0][112] = 127,
};
static
@@ -34017,10 +45842,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_WW][3] = 44,
[1][0][RTW89_WW][4] = 44,
[1][0][RTW89_WW][5] = 44,
- [1][0][RTW89_WW][6] = 44,
- [1][0][RTW89_WW][7] = 44,
- [1][0][RTW89_WW][8] = 44,
- [1][0][RTW89_WW][9] = 44,
+ [1][0][RTW89_WW][6] = 40,
+ [1][0][RTW89_WW][7] = 40,
+ [1][0][RTW89_WW][8] = 40,
+ [1][0][RTW89_WW][9] = 40,
[1][0][RTW89_WW][10] = 44,
[1][0][RTW89_WW][11] = 36,
[1][0][RTW89_WW][12] = 4,
@@ -34031,24 +45856,24 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][1][RTW89_WW][3] = 32,
[1][1][RTW89_WW][4] = 32,
[1][1][RTW89_WW][5] = 32,
- [1][1][RTW89_WW][6] = 32,
- [1][1][RTW89_WW][7] = 32,
- [1][1][RTW89_WW][8] = 32,
- [1][1][RTW89_WW][9] = 32,
+ [1][1][RTW89_WW][6] = 30,
+ [1][1][RTW89_WW][7] = 30,
+ [1][1][RTW89_WW][8] = 30,
+ [1][1][RTW89_WW][9] = 30,
[1][1][RTW89_WW][10] = 32,
[1][1][RTW89_WW][11] = 30,
[1][1][RTW89_WW][12] = -6,
[1][1][RTW89_WW][13] = 0,
[2][0][RTW89_WW][0] = 56,
- [2][0][RTW89_WW][1] = 56,
- [2][0][RTW89_WW][2] = 56,
- [2][0][RTW89_WW][3] = 56,
- [2][0][RTW89_WW][4] = 56,
+ [2][0][RTW89_WW][1] = 54,
+ [2][0][RTW89_WW][2] = 54,
+ [2][0][RTW89_WW][3] = 54,
+ [2][0][RTW89_WW][4] = 54,
[2][0][RTW89_WW][5] = 56,
- [2][0][RTW89_WW][6] = 56,
- [2][0][RTW89_WW][7] = 56,
- [2][0][RTW89_WW][8] = 56,
- [2][0][RTW89_WW][9] = 56,
+ [2][0][RTW89_WW][6] = 48,
+ [2][0][RTW89_WW][7] = 48,
+ [2][0][RTW89_WW][8] = 48,
+ [2][0][RTW89_WW][9] = 48,
[2][0][RTW89_WW][10] = 56,
[2][0][RTW89_WW][11] = 48,
[2][0][RTW89_WW][12] = 16,
@@ -34059,10 +45884,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][1][RTW89_WW][3] = 44,
[2][1][RTW89_WW][4] = 44,
[2][1][RTW89_WW][5] = 44,
- [2][1][RTW89_WW][6] = 44,
- [2][1][RTW89_WW][7] = 44,
- [2][1][RTW89_WW][8] = 44,
- [2][1][RTW89_WW][9] = 44,
+ [2][1][RTW89_WW][6] = 42,
+ [2][1][RTW89_WW][7] = 42,
+ [2][1][RTW89_WW][8] = 42,
+ [2][1][RTW89_WW][9] = 42,
[2][1][RTW89_WW][10] = 44,
[2][1][RTW89_WW][11] = 44,
[2][1][RTW89_WW][12] = 6,
@@ -34075,6 +45900,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][0] = 34,
[0][0][RTW89_CN][0] = 32,
[0][0][RTW89_UK][0] = 34,
+ [0][0][RTW89_MEXICO][0] = 60,
+ [0][0][RTW89_UKRAINE][0] = 34,
+ [0][0][RTW89_CHILE][0] = 60,
+ [0][0][RTW89_QATAR][0] = 34,
[0][0][RTW89_FCC][1] = 60,
[0][0][RTW89_ETSI][1] = 38,
[0][0][RTW89_MKK][1] = 40,
@@ -34083,6 +45912,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][1] = 38,
[0][0][RTW89_CN][1] = 32,
[0][0][RTW89_UK][1] = 38,
+ [0][0][RTW89_MEXICO][1] = 60,
+ [0][0][RTW89_UKRAINE][1] = 38,
+ [0][0][RTW89_CHILE][1] = 50,
+ [0][0][RTW89_QATAR][1] = 38,
[0][0][RTW89_FCC][2] = 64,
[0][0][RTW89_ETSI][2] = 38,
[0][0][RTW89_MKK][2] = 40,
@@ -34091,6 +45924,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][2] = 38,
[0][0][RTW89_CN][2] = 32,
[0][0][RTW89_UK][2] = 38,
+ [0][0][RTW89_MEXICO][2] = 64,
+ [0][0][RTW89_UKRAINE][2] = 38,
+ [0][0][RTW89_CHILE][2] = 50,
+ [0][0][RTW89_QATAR][2] = 38,
[0][0][RTW89_FCC][3] = 68,
[0][0][RTW89_ETSI][3] = 38,
[0][0][RTW89_MKK][3] = 40,
@@ -34099,78 +45936,118 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][3] = 38,
[0][0][RTW89_CN][3] = 32,
[0][0][RTW89_UK][3] = 38,
+ [0][0][RTW89_MEXICO][3] = 68,
+ [0][0][RTW89_UKRAINE][3] = 38,
+ [0][0][RTW89_CHILE][3] = 50,
+ [0][0][RTW89_QATAR][3] = 38,
[0][0][RTW89_FCC][4] = 68,
[0][0][RTW89_ETSI][4] = 38,
[0][0][RTW89_MKK][4] = 40,
[0][0][RTW89_IC][4] = 68,
- [0][0][RTW89_KCC][4] = 42,
+ [0][0][RTW89_KCC][4] = 44,
[0][0][RTW89_ACMA][4] = 38,
[0][0][RTW89_CN][4] = 32,
[0][0][RTW89_UK][4] = 38,
+ [0][0][RTW89_MEXICO][4] = 68,
+ [0][0][RTW89_UKRAINE][4] = 38,
+ [0][0][RTW89_CHILE][4] = 50,
+ [0][0][RTW89_QATAR][4] = 38,
[0][0][RTW89_FCC][5] = 78,
[0][0][RTW89_ETSI][5] = 38,
[0][0][RTW89_MKK][5] = 40,
[0][0][RTW89_IC][5] = 78,
- [0][0][RTW89_KCC][5] = 42,
+ [0][0][RTW89_KCC][5] = 44,
[0][0][RTW89_ACMA][5] = 38,
[0][0][RTW89_CN][5] = 32,
[0][0][RTW89_UK][5] = 38,
+ [0][0][RTW89_MEXICO][5] = 78,
+ [0][0][RTW89_UKRAINE][5] = 38,
+ [0][0][RTW89_CHILE][5] = 78,
+ [0][0][RTW89_QATAR][5] = 38,
[0][0][RTW89_FCC][6] = 54,
[0][0][RTW89_ETSI][6] = 38,
[0][0][RTW89_MKK][6] = 40,
[0][0][RTW89_IC][6] = 54,
- [0][0][RTW89_KCC][6] = 42,
+ [0][0][RTW89_KCC][6] = 44,
[0][0][RTW89_ACMA][6] = 38,
[0][0][RTW89_CN][6] = 32,
[0][0][RTW89_UK][6] = 38,
+ [0][0][RTW89_MEXICO][6] = 54,
+ [0][0][RTW89_UKRAINE][6] = 38,
+ [0][0][RTW89_CHILE][6] = 36,
+ [0][0][RTW89_QATAR][6] = 38,
[0][0][RTW89_FCC][7] = 54,
[0][0][RTW89_ETSI][7] = 38,
[0][0][RTW89_MKK][7] = 40,
[0][0][RTW89_IC][7] = 54,
- [0][0][RTW89_KCC][7] = 42,
+ [0][0][RTW89_KCC][7] = 44,
[0][0][RTW89_ACMA][7] = 38,
[0][0][RTW89_CN][7] = 32,
[0][0][RTW89_UK][7] = 38,
+ [0][0][RTW89_MEXICO][7] = 54,
+ [0][0][RTW89_UKRAINE][7] = 38,
+ [0][0][RTW89_CHILE][7] = 36,
+ [0][0][RTW89_QATAR][7] = 38,
[0][0][RTW89_FCC][8] = 50,
[0][0][RTW89_ETSI][8] = 38,
[0][0][RTW89_MKK][8] = 40,
[0][0][RTW89_IC][8] = 50,
- [0][0][RTW89_KCC][8] = 42,
+ [0][0][RTW89_KCC][8] = 44,
[0][0][RTW89_ACMA][8] = 38,
[0][0][RTW89_CN][8] = 32,
[0][0][RTW89_UK][8] = 38,
+ [0][0][RTW89_MEXICO][8] = 50,
+ [0][0][RTW89_UKRAINE][8] = 38,
+ [0][0][RTW89_CHILE][8] = 36,
+ [0][0][RTW89_QATAR][8] = 38,
[0][0][RTW89_FCC][9] = 46,
[0][0][RTW89_ETSI][9] = 38,
[0][0][RTW89_MKK][9] = 40,
[0][0][RTW89_IC][9] = 46,
- [0][0][RTW89_KCC][9] = 40,
+ [0][0][RTW89_KCC][9] = 42,
[0][0][RTW89_ACMA][9] = 38,
[0][0][RTW89_CN][9] = 32,
[0][0][RTW89_UK][9] = 38,
+ [0][0][RTW89_MEXICO][9] = 46,
+ [0][0][RTW89_UKRAINE][9] = 38,
+ [0][0][RTW89_CHILE][9] = 36,
+ [0][0][RTW89_QATAR][9] = 38,
[0][0][RTW89_FCC][10] = 46,
[0][0][RTW89_ETSI][10] = 38,
[0][0][RTW89_MKK][10] = 40,
[0][0][RTW89_IC][10] = 46,
- [0][0][RTW89_KCC][10] = 40,
+ [0][0][RTW89_KCC][10] = 42,
[0][0][RTW89_ACMA][10] = 38,
[0][0][RTW89_CN][10] = 32,
[0][0][RTW89_UK][10] = 38,
+ [0][0][RTW89_MEXICO][10] = 46,
+ [0][0][RTW89_UKRAINE][10] = 38,
+ [0][0][RTW89_CHILE][10] = 46,
+ [0][0][RTW89_QATAR][10] = 38,
[0][0][RTW89_FCC][11] = 26,
[0][0][RTW89_ETSI][11] = 38,
[0][0][RTW89_MKK][11] = 40,
[0][0][RTW89_IC][11] = 26,
- [0][0][RTW89_KCC][11] = 40,
+ [0][0][RTW89_KCC][11] = 42,
[0][0][RTW89_ACMA][11] = 38,
[0][0][RTW89_CN][11] = 32,
[0][0][RTW89_UK][11] = 38,
+ [0][0][RTW89_MEXICO][11] = 26,
+ [0][0][RTW89_UKRAINE][11] = 38,
+ [0][0][RTW89_CHILE][11] = 26,
+ [0][0][RTW89_QATAR][11] = 38,
[0][0][RTW89_FCC][12] = -20,
[0][0][RTW89_ETSI][12] = 34,
[0][0][RTW89_MKK][12] = 36,
[0][0][RTW89_IC][12] = -20,
- [0][0][RTW89_KCC][12] = 40,
+ [0][0][RTW89_KCC][12] = 42,
[0][0][RTW89_ACMA][12] = 34,
[0][0][RTW89_CN][12] = 32,
[0][0][RTW89_UK][12] = 34,
+ [0][0][RTW89_MEXICO][12] = -20,
+ [0][0][RTW89_UKRAINE][12] = 34,
+ [0][0][RTW89_CHILE][12] = -20,
+ [0][0][RTW89_QATAR][12] = 34,
[0][0][RTW89_FCC][13] = 127,
[0][0][RTW89_ETSI][13] = 127,
[0][0][RTW89_MKK][13] = 127,
@@ -34179,6 +46056,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][13] = 127,
[0][0][RTW89_CN][13] = 127,
[0][0][RTW89_UK][13] = 127,
+ [0][0][RTW89_MEXICO][13] = 127,
+ [0][0][RTW89_UKRAINE][13] = 127,
+ [0][0][RTW89_CHILE][13] = 127,
+ [0][0][RTW89_QATAR][13] = 127,
[0][1][RTW89_FCC][0] = 56,
[0][1][RTW89_ETSI][0] = 22,
[0][1][RTW89_MKK][0] = 24,
@@ -34187,6 +46068,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][0] = 22,
[0][1][RTW89_CN][0] = 20,
[0][1][RTW89_UK][0] = 22,
+ [0][1][RTW89_MEXICO][0] = 56,
+ [0][1][RTW89_UKRAINE][0] = 22,
+ [0][1][RTW89_CHILE][0] = 56,
+ [0][1][RTW89_QATAR][0] = 22,
[0][1][RTW89_FCC][1] = 56,
[0][1][RTW89_ETSI][1] = 24,
[0][1][RTW89_MKK][1] = 30,
@@ -34195,6 +46080,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][1] = 24,
[0][1][RTW89_CN][1] = 22,
[0][1][RTW89_UK][1] = 24,
+ [0][1][RTW89_MEXICO][1] = 56,
+ [0][1][RTW89_UKRAINE][1] = 24,
+ [0][1][RTW89_CHILE][1] = 40,
+ [0][1][RTW89_QATAR][1] = 24,
[0][1][RTW89_FCC][2] = 60,
[0][1][RTW89_ETSI][2] = 24,
[0][1][RTW89_MKK][2] = 30,
@@ -34203,6 +46092,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][2] = 24,
[0][1][RTW89_CN][2] = 22,
[0][1][RTW89_UK][2] = 24,
+ [0][1][RTW89_MEXICO][2] = 60,
+ [0][1][RTW89_UKRAINE][2] = 24,
+ [0][1][RTW89_CHILE][2] = 40,
+ [0][1][RTW89_QATAR][2] = 24,
[0][1][RTW89_FCC][3] = 64,
[0][1][RTW89_ETSI][3] = 24,
[0][1][RTW89_MKK][3] = 30,
@@ -34211,78 +46104,118 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][3] = 24,
[0][1][RTW89_CN][3] = 22,
[0][1][RTW89_UK][3] = 24,
+ [0][1][RTW89_MEXICO][3] = 64,
+ [0][1][RTW89_UKRAINE][3] = 24,
+ [0][1][RTW89_CHILE][3] = 40,
+ [0][1][RTW89_QATAR][3] = 24,
[0][1][RTW89_FCC][4] = 68,
[0][1][RTW89_ETSI][4] = 24,
[0][1][RTW89_MKK][4] = 30,
[0][1][RTW89_IC][4] = 68,
- [0][1][RTW89_KCC][4] = 28,
+ [0][1][RTW89_KCC][4] = 34,
[0][1][RTW89_ACMA][4] = 24,
[0][1][RTW89_CN][4] = 22,
[0][1][RTW89_UK][4] = 24,
+ [0][1][RTW89_MEXICO][4] = 68,
+ [0][1][RTW89_UKRAINE][4] = 24,
+ [0][1][RTW89_CHILE][4] = 40,
+ [0][1][RTW89_QATAR][4] = 24,
[0][1][RTW89_FCC][5] = 76,
[0][1][RTW89_ETSI][5] = 24,
[0][1][RTW89_MKK][5] = 30,
[0][1][RTW89_IC][5] = 76,
- [0][1][RTW89_KCC][5] = 28,
+ [0][1][RTW89_KCC][5] = 34,
[0][1][RTW89_ACMA][5] = 24,
[0][1][RTW89_CN][5] = 22,
[0][1][RTW89_UK][5] = 24,
+ [0][1][RTW89_MEXICO][5] = 76,
+ [0][1][RTW89_UKRAINE][5] = 24,
+ [0][1][RTW89_CHILE][5] = 76,
+ [0][1][RTW89_QATAR][5] = 24,
[0][1][RTW89_FCC][6] = 54,
[0][1][RTW89_ETSI][6] = 24,
[0][1][RTW89_MKK][6] = 30,
[0][1][RTW89_IC][6] = 54,
- [0][1][RTW89_KCC][6] = 28,
+ [0][1][RTW89_KCC][6] = 34,
[0][1][RTW89_ACMA][6] = 24,
[0][1][RTW89_CN][6] = 22,
[0][1][RTW89_UK][6] = 24,
+ [0][1][RTW89_MEXICO][6] = 54,
+ [0][1][RTW89_UKRAINE][6] = 24,
+ [0][1][RTW89_CHILE][6] = 26,
+ [0][1][RTW89_QATAR][6] = 24,
[0][1][RTW89_FCC][7] = 50,
[0][1][RTW89_ETSI][7] = 24,
[0][1][RTW89_MKK][7] = 30,
[0][1][RTW89_IC][7] = 50,
- [0][1][RTW89_KCC][7] = 28,
+ [0][1][RTW89_KCC][7] = 34,
[0][1][RTW89_ACMA][7] = 24,
[0][1][RTW89_CN][7] = 22,
[0][1][RTW89_UK][7] = 24,
+ [0][1][RTW89_MEXICO][7] = 50,
+ [0][1][RTW89_UKRAINE][7] = 24,
+ [0][1][RTW89_CHILE][7] = 26,
+ [0][1][RTW89_QATAR][7] = 24,
[0][1][RTW89_FCC][8] = 46,
[0][1][RTW89_ETSI][8] = 24,
[0][1][RTW89_MKK][8] = 30,
[0][1][RTW89_IC][8] = 46,
- [0][1][RTW89_KCC][8] = 28,
+ [0][1][RTW89_KCC][8] = 34,
[0][1][RTW89_ACMA][8] = 24,
[0][1][RTW89_CN][8] = 22,
[0][1][RTW89_UK][8] = 24,
+ [0][1][RTW89_MEXICO][8] = 46,
+ [0][1][RTW89_UKRAINE][8] = 24,
+ [0][1][RTW89_CHILE][8] = 26,
+ [0][1][RTW89_QATAR][8] = 24,
[0][1][RTW89_FCC][9] = 42,
[0][1][RTW89_ETSI][9] = 24,
[0][1][RTW89_MKK][9] = 30,
[0][1][RTW89_IC][9] = 42,
- [0][1][RTW89_KCC][9] = 28,
+ [0][1][RTW89_KCC][9] = 32,
[0][1][RTW89_ACMA][9] = 24,
[0][1][RTW89_CN][9] = 22,
[0][1][RTW89_UK][9] = 24,
+ [0][1][RTW89_MEXICO][9] = 42,
+ [0][1][RTW89_UKRAINE][9] = 24,
+ [0][1][RTW89_CHILE][9] = 26,
+ [0][1][RTW89_QATAR][9] = 24,
[0][1][RTW89_FCC][10] = 42,
[0][1][RTW89_ETSI][10] = 24,
[0][1][RTW89_MKK][10] = 30,
[0][1][RTW89_IC][10] = 42,
- [0][1][RTW89_KCC][10] = 28,
+ [0][1][RTW89_KCC][10] = 32,
[0][1][RTW89_ACMA][10] = 24,
[0][1][RTW89_CN][10] = 22,
[0][1][RTW89_UK][10] = 24,
+ [0][1][RTW89_MEXICO][10] = 42,
+ [0][1][RTW89_UKRAINE][10] = 24,
+ [0][1][RTW89_CHILE][10] = 42,
+ [0][1][RTW89_QATAR][10] = 24,
[0][1][RTW89_FCC][11] = 22,
[0][1][RTW89_ETSI][11] = 24,
[0][1][RTW89_MKK][11] = 30,
[0][1][RTW89_IC][11] = 22,
- [0][1][RTW89_KCC][11] = 28,
+ [0][1][RTW89_KCC][11] = 32,
[0][1][RTW89_ACMA][11] = 24,
[0][1][RTW89_CN][11] = 22,
[0][1][RTW89_UK][11] = 24,
+ [0][1][RTW89_MEXICO][11] = 22,
+ [0][1][RTW89_UKRAINE][11] = 24,
+ [0][1][RTW89_CHILE][11] = 22,
+ [0][1][RTW89_QATAR][11] = 24,
[0][1][RTW89_FCC][12] = -30,
[0][1][RTW89_ETSI][12] = 20,
[0][1][RTW89_MKK][12] = 24,
[0][1][RTW89_IC][12] = -30,
- [0][1][RTW89_KCC][12] = 28,
+ [0][1][RTW89_KCC][12] = 32,
[0][1][RTW89_ACMA][12] = 20,
[0][1][RTW89_CN][12] = 20,
[0][1][RTW89_UK][12] = 20,
+ [0][1][RTW89_MEXICO][12] = -30,
+ [0][1][RTW89_UKRAINE][12] = 20,
+ [0][1][RTW89_CHILE][12] = -30,
+ [0][1][RTW89_QATAR][12] = 20,
[0][1][RTW89_FCC][13] = 127,
[0][1][RTW89_ETSI][13] = 127,
[0][1][RTW89_MKK][13] = 127,
@@ -34291,110 +46224,166 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][13] = 127,
[0][1][RTW89_CN][13] = 127,
[0][1][RTW89_UK][13] = 127,
+ [0][1][RTW89_MEXICO][13] = 127,
+ [0][1][RTW89_UKRAINE][13] = 127,
+ [0][1][RTW89_CHILE][13] = 127,
+ [0][1][RTW89_QATAR][13] = 127,
[1][0][RTW89_FCC][0] = 66,
[1][0][RTW89_ETSI][0] = 46,
[1][0][RTW89_MKK][0] = 48,
[1][0][RTW89_IC][0] = 66,
- [1][0][RTW89_KCC][0] = 50,
+ [1][0][RTW89_KCC][0] = 54,
[1][0][RTW89_ACMA][0] = 46,
[1][0][RTW89_CN][0] = 42,
[1][0][RTW89_UK][0] = 46,
+ [1][0][RTW89_MEXICO][0] = 66,
+ [1][0][RTW89_UKRAINE][0] = 46,
+ [1][0][RTW89_CHILE][0] = 66,
+ [1][0][RTW89_QATAR][0] = 46,
[1][0][RTW89_FCC][1] = 66,
[1][0][RTW89_ETSI][1] = 46,
[1][0][RTW89_MKK][1] = 48,
[1][0][RTW89_IC][1] = 66,
- [1][0][RTW89_KCC][1] = 50,
+ [1][0][RTW89_KCC][1] = 54,
[1][0][RTW89_ACMA][1] = 46,
[1][0][RTW89_CN][1] = 44,
[1][0][RTW89_UK][1] = 46,
+ [1][0][RTW89_MEXICO][1] = 66,
+ [1][0][RTW89_UKRAINE][1] = 46,
+ [1][0][RTW89_CHILE][1] = 54,
+ [1][0][RTW89_QATAR][1] = 46,
[1][0][RTW89_FCC][2] = 70,
[1][0][RTW89_ETSI][2] = 46,
[1][0][RTW89_MKK][2] = 48,
[1][0][RTW89_IC][2] = 70,
- [1][0][RTW89_KCC][2] = 50,
+ [1][0][RTW89_KCC][2] = 54,
[1][0][RTW89_ACMA][2] = 46,
[1][0][RTW89_CN][2] = 44,
[1][0][RTW89_UK][2] = 46,
+ [1][0][RTW89_MEXICO][2] = 70,
+ [1][0][RTW89_UKRAINE][2] = 46,
+ [1][0][RTW89_CHILE][2] = 54,
+ [1][0][RTW89_QATAR][2] = 46,
[1][0][RTW89_FCC][3] = 72,
[1][0][RTW89_ETSI][3] = 46,
[1][0][RTW89_MKK][3] = 48,
[1][0][RTW89_IC][3] = 72,
- [1][0][RTW89_KCC][3] = 50,
+ [1][0][RTW89_KCC][3] = 54,
[1][0][RTW89_ACMA][3] = 46,
[1][0][RTW89_CN][3] = 44,
[1][0][RTW89_UK][3] = 46,
+ [1][0][RTW89_MEXICO][3] = 72,
+ [1][0][RTW89_UKRAINE][3] = 46,
+ [1][0][RTW89_CHILE][3] = 54,
+ [1][0][RTW89_QATAR][3] = 46,
[1][0][RTW89_FCC][4] = 72,
[1][0][RTW89_ETSI][4] = 46,
[1][0][RTW89_MKK][4] = 48,
[1][0][RTW89_IC][4] = 72,
- [1][0][RTW89_KCC][4] = 50,
+ [1][0][RTW89_KCC][4] = 56,
[1][0][RTW89_ACMA][4] = 46,
[1][0][RTW89_CN][4] = 44,
[1][0][RTW89_UK][4] = 46,
+ [1][0][RTW89_MEXICO][4] = 72,
+ [1][0][RTW89_UKRAINE][4] = 46,
+ [1][0][RTW89_CHILE][4] = 54,
+ [1][0][RTW89_QATAR][4] = 46,
[1][0][RTW89_FCC][5] = 82,
[1][0][RTW89_ETSI][5] = 46,
[1][0][RTW89_MKK][5] = 48,
[1][0][RTW89_IC][5] = 82,
- [1][0][RTW89_KCC][5] = 50,
+ [1][0][RTW89_KCC][5] = 56,
[1][0][RTW89_ACMA][5] = 46,
[1][0][RTW89_CN][5] = 44,
[1][0][RTW89_UK][5] = 46,
+ [1][0][RTW89_MEXICO][5] = 82,
+ [1][0][RTW89_UKRAINE][5] = 46,
+ [1][0][RTW89_CHILE][5] = 82,
+ [1][0][RTW89_QATAR][5] = 46,
[1][0][RTW89_FCC][6] = 58,
[1][0][RTW89_ETSI][6] = 44,
[1][0][RTW89_MKK][6] = 48,
[1][0][RTW89_IC][6] = 58,
- [1][0][RTW89_KCC][6] = 50,
+ [1][0][RTW89_KCC][6] = 56,
[1][0][RTW89_ACMA][6] = 44,
[1][0][RTW89_CN][6] = 44,
[1][0][RTW89_UK][6] = 44,
+ [1][0][RTW89_MEXICO][6] = 58,
+ [1][0][RTW89_UKRAINE][6] = 44,
+ [1][0][RTW89_CHILE][6] = 40,
+ [1][0][RTW89_QATAR][6] = 44,
[1][0][RTW89_FCC][7] = 58,
[1][0][RTW89_ETSI][7] = 46,
[1][0][RTW89_MKK][7] = 48,
[1][0][RTW89_IC][7] = 58,
- [1][0][RTW89_KCC][7] = 50,
+ [1][0][RTW89_KCC][7] = 56,
[1][0][RTW89_ACMA][7] = 46,
[1][0][RTW89_CN][7] = 44,
[1][0][RTW89_UK][7] = 46,
+ [1][0][RTW89_MEXICO][7] = 58,
+ [1][0][RTW89_UKRAINE][7] = 46,
+ [1][0][RTW89_CHILE][7] = 40,
+ [1][0][RTW89_QATAR][7] = 46,
[1][0][RTW89_FCC][8] = 58,
[1][0][RTW89_ETSI][8] = 46,
[1][0][RTW89_MKK][8] = 48,
[1][0][RTW89_IC][8] = 58,
- [1][0][RTW89_KCC][8] = 50,
+ [1][0][RTW89_KCC][8] = 56,
[1][0][RTW89_ACMA][8] = 46,
[1][0][RTW89_CN][8] = 44,
[1][0][RTW89_UK][8] = 46,
+ [1][0][RTW89_MEXICO][8] = 58,
+ [1][0][RTW89_UKRAINE][8] = 46,
+ [1][0][RTW89_CHILE][8] = 40,
+ [1][0][RTW89_QATAR][8] = 46,
[1][0][RTW89_FCC][9] = 54,
[1][0][RTW89_ETSI][9] = 46,
[1][0][RTW89_MKK][9] = 48,
[1][0][RTW89_IC][9] = 54,
- [1][0][RTW89_KCC][9] = 50,
+ [1][0][RTW89_KCC][9] = 56,
[1][0][RTW89_ACMA][9] = 46,
[1][0][RTW89_CN][9] = 44,
[1][0][RTW89_UK][9] = 46,
+ [1][0][RTW89_MEXICO][9] = 54,
+ [1][0][RTW89_UKRAINE][9] = 46,
+ [1][0][RTW89_CHILE][9] = 40,
+ [1][0][RTW89_QATAR][9] = 46,
[1][0][RTW89_FCC][10] = 54,
[1][0][RTW89_ETSI][10] = 46,
[1][0][RTW89_MKK][10] = 48,
[1][0][RTW89_IC][10] = 54,
- [1][0][RTW89_KCC][10] = 50,
+ [1][0][RTW89_KCC][10] = 56,
[1][0][RTW89_ACMA][10] = 46,
[1][0][RTW89_CN][10] = 44,
[1][0][RTW89_UK][10] = 46,
+ [1][0][RTW89_MEXICO][10] = 54,
+ [1][0][RTW89_UKRAINE][10] = 46,
+ [1][0][RTW89_CHILE][10] = 54,
+ [1][0][RTW89_QATAR][10] = 46,
[1][0][RTW89_FCC][11] = 36,
[1][0][RTW89_ETSI][11] = 46,
[1][0][RTW89_MKK][11] = 48,
[1][0][RTW89_IC][11] = 36,
- [1][0][RTW89_KCC][11] = 50,
+ [1][0][RTW89_KCC][11] = 56,
[1][0][RTW89_ACMA][11] = 46,
[1][0][RTW89_CN][11] = 44,
[1][0][RTW89_UK][11] = 46,
+ [1][0][RTW89_MEXICO][11] = 36,
+ [1][0][RTW89_UKRAINE][11] = 46,
+ [1][0][RTW89_CHILE][11] = 36,
+ [1][0][RTW89_QATAR][11] = 46,
[1][0][RTW89_FCC][12] = 4,
[1][0][RTW89_ETSI][12] = 46,
[1][0][RTW89_MKK][12] = 46,
[1][0][RTW89_IC][12] = 4,
- [1][0][RTW89_KCC][12] = 50,
+ [1][0][RTW89_KCC][12] = 56,
[1][0][RTW89_ACMA][12] = 46,
[1][0][RTW89_CN][12] = 42,
[1][0][RTW89_UK][12] = 46,
+ [1][0][RTW89_MEXICO][12] = 4,
+ [1][0][RTW89_UKRAINE][12] = 46,
+ [1][0][RTW89_CHILE][12] = 4,
+ [1][0][RTW89_QATAR][12] = 46,
[1][0][RTW89_FCC][13] = 127,
[1][0][RTW89_ETSI][13] = 127,
[1][0][RTW89_MKK][13] = 127,
@@ -34403,110 +46392,166 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][13] = 127,
[1][0][RTW89_CN][13] = 127,
[1][0][RTW89_UK][13] = 127,
+ [1][0][RTW89_MEXICO][13] = 127,
+ [1][0][RTW89_UKRAINE][13] = 127,
+ [1][0][RTW89_CHILE][13] = 127,
+ [1][0][RTW89_QATAR][13] = 127,
[1][1][RTW89_FCC][0] = 58,
[1][1][RTW89_ETSI][0] = 32,
[1][1][RTW89_MKK][0] = 34,
[1][1][RTW89_IC][0] = 58,
- [1][1][RTW89_KCC][0] = 38,
+ [1][1][RTW89_KCC][0] = 42,
[1][1][RTW89_ACMA][0] = 32,
[1][1][RTW89_CN][0] = 32,
[1][1][RTW89_UK][0] = 32,
+ [1][1][RTW89_MEXICO][0] = 58,
+ [1][1][RTW89_UKRAINE][0] = 32,
+ [1][1][RTW89_CHILE][0] = 58,
+ [1][1][RTW89_QATAR][0] = 32,
[1][1][RTW89_FCC][1] = 58,
[1][1][RTW89_ETSI][1] = 34,
[1][1][RTW89_MKK][1] = 34,
[1][1][RTW89_IC][1] = 58,
- [1][1][RTW89_KCC][1] = 38,
+ [1][1][RTW89_KCC][1] = 42,
[1][1][RTW89_ACMA][1] = 34,
[1][1][RTW89_CN][1] = 32,
[1][1][RTW89_UK][1] = 34,
+ [1][1][RTW89_MEXICO][1] = 58,
+ [1][1][RTW89_UKRAINE][1] = 34,
+ [1][1][RTW89_CHILE][1] = 40,
+ [1][1][RTW89_QATAR][1] = 34,
[1][1][RTW89_FCC][2] = 62,
[1][1][RTW89_ETSI][2] = 34,
[1][1][RTW89_MKK][2] = 34,
[1][1][RTW89_IC][2] = 62,
- [1][1][RTW89_KCC][2] = 38,
+ [1][1][RTW89_KCC][2] = 42,
[1][1][RTW89_ACMA][2] = 34,
[1][1][RTW89_CN][2] = 32,
[1][1][RTW89_UK][2] = 34,
+ [1][1][RTW89_MEXICO][2] = 62,
+ [1][1][RTW89_UKRAINE][2] = 34,
+ [1][1][RTW89_CHILE][2] = 40,
+ [1][1][RTW89_QATAR][2] = 34,
[1][1][RTW89_FCC][3] = 66,
[1][1][RTW89_ETSI][3] = 34,
[1][1][RTW89_MKK][3] = 34,
[1][1][RTW89_IC][3] = 66,
- [1][1][RTW89_KCC][3] = 38,
+ [1][1][RTW89_KCC][3] = 42,
[1][1][RTW89_ACMA][3] = 34,
[1][1][RTW89_CN][3] = 32,
[1][1][RTW89_UK][3] = 34,
+ [1][1][RTW89_MEXICO][3] = 66,
+ [1][1][RTW89_UKRAINE][3] = 34,
+ [1][1][RTW89_CHILE][3] = 40,
+ [1][1][RTW89_QATAR][3] = 34,
[1][1][RTW89_FCC][4] = 70,
[1][1][RTW89_ETSI][4] = 34,
[1][1][RTW89_MKK][4] = 34,
[1][1][RTW89_IC][4] = 70,
- [1][1][RTW89_KCC][4] = 38,
+ [1][1][RTW89_KCC][4] = 44,
[1][1][RTW89_ACMA][4] = 34,
[1][1][RTW89_CN][4] = 32,
[1][1][RTW89_UK][4] = 34,
+ [1][1][RTW89_MEXICO][4] = 70,
+ [1][1][RTW89_UKRAINE][4] = 34,
+ [1][1][RTW89_CHILE][4] = 40,
+ [1][1][RTW89_QATAR][4] = 34,
[1][1][RTW89_FCC][5] = 82,
[1][1][RTW89_ETSI][5] = 34,
[1][1][RTW89_MKK][5] = 34,
[1][1][RTW89_IC][5] = 82,
- [1][1][RTW89_KCC][5] = 38,
+ [1][1][RTW89_KCC][5] = 44,
[1][1][RTW89_ACMA][5] = 34,
[1][1][RTW89_CN][5] = 32,
[1][1][RTW89_UK][5] = 34,
+ [1][1][RTW89_MEXICO][5] = 82,
+ [1][1][RTW89_UKRAINE][5] = 34,
+ [1][1][RTW89_CHILE][5] = 78,
+ [1][1][RTW89_QATAR][5] = 34,
[1][1][RTW89_FCC][6] = 60,
[1][1][RTW89_ETSI][6] = 34,
[1][1][RTW89_MKK][6] = 34,
[1][1][RTW89_IC][6] = 60,
- [1][1][RTW89_KCC][6] = 38,
+ [1][1][RTW89_KCC][6] = 44,
[1][1][RTW89_ACMA][6] = 34,
[1][1][RTW89_CN][6] = 32,
[1][1][RTW89_UK][6] = 34,
+ [1][1][RTW89_MEXICO][6] = 60,
+ [1][1][RTW89_UKRAINE][6] = 34,
+ [1][1][RTW89_CHILE][6] = 30,
+ [1][1][RTW89_QATAR][6] = 34,
[1][1][RTW89_FCC][7] = 56,
[1][1][RTW89_ETSI][7] = 34,
[1][1][RTW89_MKK][7] = 34,
[1][1][RTW89_IC][7] = 56,
- [1][1][RTW89_KCC][7] = 38,
+ [1][1][RTW89_KCC][7] = 44,
[1][1][RTW89_ACMA][7] = 34,
[1][1][RTW89_CN][7] = 32,
[1][1][RTW89_UK][7] = 34,
+ [1][1][RTW89_MEXICO][7] = 56,
+ [1][1][RTW89_UKRAINE][7] = 34,
+ [1][1][RTW89_CHILE][7] = 30,
+ [1][1][RTW89_QATAR][7] = 34,
[1][1][RTW89_FCC][8] = 52,
[1][1][RTW89_ETSI][8] = 34,
[1][1][RTW89_MKK][8] = 34,
[1][1][RTW89_IC][8] = 52,
- [1][1][RTW89_KCC][8] = 38,
+ [1][1][RTW89_KCC][8] = 44,
[1][1][RTW89_ACMA][8] = 34,
[1][1][RTW89_CN][8] = 32,
[1][1][RTW89_UK][8] = 34,
+ [1][1][RTW89_MEXICO][8] = 52,
+ [1][1][RTW89_UKRAINE][8] = 34,
+ [1][1][RTW89_CHILE][8] = 30,
+ [1][1][RTW89_QATAR][8] = 34,
[1][1][RTW89_FCC][9] = 48,
[1][1][RTW89_ETSI][9] = 34,
[1][1][RTW89_MKK][9] = 34,
[1][1][RTW89_IC][9] = 48,
- [1][1][RTW89_KCC][9] = 38,
+ [1][1][RTW89_KCC][9] = 44,
[1][1][RTW89_ACMA][9] = 34,
[1][1][RTW89_CN][9] = 32,
[1][1][RTW89_UK][9] = 34,
+ [1][1][RTW89_MEXICO][9] = 48,
+ [1][1][RTW89_UKRAINE][9] = 34,
+ [1][1][RTW89_CHILE][9] = 30,
+ [1][1][RTW89_QATAR][9] = 34,
[1][1][RTW89_FCC][10] = 48,
[1][1][RTW89_ETSI][10] = 34,
[1][1][RTW89_MKK][10] = 34,
[1][1][RTW89_IC][10] = 48,
- [1][1][RTW89_KCC][10] = 38,
+ [1][1][RTW89_KCC][10] = 44,
[1][1][RTW89_ACMA][10] = 34,
[1][1][RTW89_CN][10] = 32,
[1][1][RTW89_UK][10] = 34,
+ [1][1][RTW89_MEXICO][10] = 48,
+ [1][1][RTW89_UKRAINE][10] = 34,
+ [1][1][RTW89_CHILE][10] = 48,
+ [1][1][RTW89_QATAR][10] = 34,
[1][1][RTW89_FCC][11] = 30,
[1][1][RTW89_ETSI][11] = 34,
[1][1][RTW89_MKK][11] = 34,
[1][1][RTW89_IC][11] = 30,
- [1][1][RTW89_KCC][11] = 38,
+ [1][1][RTW89_KCC][11] = 44,
[1][1][RTW89_ACMA][11] = 34,
[1][1][RTW89_CN][11] = 32,
[1][1][RTW89_UK][11] = 34,
+ [1][1][RTW89_MEXICO][11] = 30,
+ [1][1][RTW89_UKRAINE][11] = 34,
+ [1][1][RTW89_CHILE][11] = 30,
+ [1][1][RTW89_QATAR][11] = 34,
[1][1][RTW89_FCC][12] = -6,
[1][1][RTW89_ETSI][12] = 34,
[1][1][RTW89_MKK][12] = 34,
[1][1][RTW89_IC][12] = -6,
- [1][1][RTW89_KCC][12] = 38,
+ [1][1][RTW89_KCC][12] = 44,
[1][1][RTW89_ACMA][12] = 34,
[1][1][RTW89_CN][12] = 32,
[1][1][RTW89_UK][12] = 34,
+ [1][1][RTW89_MEXICO][12] = -6,
+ [1][1][RTW89_UKRAINE][12] = 34,
+ [1][1][RTW89_CHILE][12] = -6,
+ [1][1][RTW89_QATAR][12] = 34,
[1][1][RTW89_FCC][13] = 127,
[1][1][RTW89_ETSI][13] = 127,
[1][1][RTW89_MKK][13] = 127,
@@ -34515,110 +46560,166 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][1][RTW89_ACMA][13] = 127,
[1][1][RTW89_CN][13] = 127,
[1][1][RTW89_UK][13] = 127,
+ [1][1][RTW89_MEXICO][13] = 127,
+ [1][1][RTW89_UKRAINE][13] = 127,
+ [1][1][RTW89_CHILE][13] = 127,
+ [1][1][RTW89_QATAR][13] = 127,
[2][0][RTW89_FCC][0] = 70,
[2][0][RTW89_ETSI][0] = 58,
[2][0][RTW89_MKK][0] = 58,
[2][0][RTW89_IC][0] = 70,
- [2][0][RTW89_KCC][0] = 64,
+ [2][0][RTW89_KCC][0] = 60,
[2][0][RTW89_ACMA][0] = 58,
[2][0][RTW89_CN][0] = 56,
[2][0][RTW89_UK][0] = 58,
+ [2][0][RTW89_MEXICO][0] = 70,
+ [2][0][RTW89_UKRAINE][0] = 58,
+ [2][0][RTW89_CHILE][0] = 70,
+ [2][0][RTW89_QATAR][0] = 58,
[2][0][RTW89_FCC][1] = 70,
[2][0][RTW89_ETSI][1] = 58,
[2][0][RTW89_MKK][1] = 58,
[2][0][RTW89_IC][1] = 70,
- [2][0][RTW89_KCC][1] = 64,
+ [2][0][RTW89_KCC][1] = 60,
[2][0][RTW89_ACMA][1] = 58,
[2][0][RTW89_CN][1] = 56,
[2][0][RTW89_UK][1] = 58,
+ [2][0][RTW89_MEXICO][1] = 70,
+ [2][0][RTW89_UKRAINE][1] = 58,
+ [2][0][RTW89_CHILE][1] = 54,
+ [2][0][RTW89_QATAR][1] = 58,
[2][0][RTW89_FCC][2] = 72,
[2][0][RTW89_ETSI][2] = 58,
[2][0][RTW89_MKK][2] = 58,
[2][0][RTW89_IC][2] = 72,
- [2][0][RTW89_KCC][2] = 64,
+ [2][0][RTW89_KCC][2] = 60,
[2][0][RTW89_ACMA][2] = 58,
[2][0][RTW89_CN][2] = 56,
[2][0][RTW89_UK][2] = 58,
+ [2][0][RTW89_MEXICO][2] = 72,
+ [2][0][RTW89_UKRAINE][2] = 58,
+ [2][0][RTW89_CHILE][2] = 54,
+ [2][0][RTW89_QATAR][2] = 58,
[2][0][RTW89_FCC][3] = 72,
[2][0][RTW89_ETSI][3] = 58,
[2][0][RTW89_MKK][3] = 58,
[2][0][RTW89_IC][3] = 72,
- [2][0][RTW89_KCC][3] = 64,
+ [2][0][RTW89_KCC][3] = 60,
[2][0][RTW89_ACMA][3] = 58,
[2][0][RTW89_CN][3] = 56,
[2][0][RTW89_UK][3] = 58,
+ [2][0][RTW89_MEXICO][3] = 72,
+ [2][0][RTW89_UKRAINE][3] = 58,
+ [2][0][RTW89_CHILE][3] = 54,
+ [2][0][RTW89_QATAR][3] = 58,
[2][0][RTW89_FCC][4] = 72,
[2][0][RTW89_ETSI][4] = 58,
[2][0][RTW89_MKK][4] = 58,
[2][0][RTW89_IC][4] = 72,
- [2][0][RTW89_KCC][4] = 64,
+ [2][0][RTW89_KCC][4] = 60,
[2][0][RTW89_ACMA][4] = 58,
[2][0][RTW89_CN][4] = 56,
[2][0][RTW89_UK][4] = 58,
+ [2][0][RTW89_MEXICO][4] = 72,
+ [2][0][RTW89_UKRAINE][4] = 58,
+ [2][0][RTW89_CHILE][4] = 54,
+ [2][0][RTW89_QATAR][4] = 58,
[2][0][RTW89_FCC][5] = 82,
[2][0][RTW89_ETSI][5] = 58,
[2][0][RTW89_MKK][5] = 58,
[2][0][RTW89_IC][5] = 82,
- [2][0][RTW89_KCC][5] = 64,
+ [2][0][RTW89_KCC][5] = 60,
[2][0][RTW89_ACMA][5] = 58,
[2][0][RTW89_CN][5] = 56,
[2][0][RTW89_UK][5] = 58,
+ [2][0][RTW89_MEXICO][5] = 82,
+ [2][0][RTW89_UKRAINE][5] = 58,
+ [2][0][RTW89_CHILE][5] = 82,
+ [2][0][RTW89_QATAR][5] = 58,
[2][0][RTW89_FCC][6] = 66,
[2][0][RTW89_ETSI][6] = 56,
[2][0][RTW89_MKK][6] = 58,
[2][0][RTW89_IC][6] = 66,
- [2][0][RTW89_KCC][6] = 64,
+ [2][0][RTW89_KCC][6] = 60,
[2][0][RTW89_ACMA][6] = 56,
[2][0][RTW89_CN][6] = 56,
[2][0][RTW89_UK][6] = 56,
+ [2][0][RTW89_MEXICO][6] = 66,
+ [2][0][RTW89_UKRAINE][6] = 56,
+ [2][0][RTW89_CHILE][6] = 48,
+ [2][0][RTW89_QATAR][6] = 56,
[2][0][RTW89_FCC][7] = 66,
[2][0][RTW89_ETSI][7] = 58,
[2][0][RTW89_MKK][7] = 58,
[2][0][RTW89_IC][7] = 66,
- [2][0][RTW89_KCC][7] = 64,
+ [2][0][RTW89_KCC][7] = 60,
[2][0][RTW89_ACMA][7] = 58,
[2][0][RTW89_CN][7] = 56,
[2][0][RTW89_UK][7] = 58,
+ [2][0][RTW89_MEXICO][7] = 66,
+ [2][0][RTW89_UKRAINE][7] = 58,
+ [2][0][RTW89_CHILE][7] = 48,
+ [2][0][RTW89_QATAR][7] = 58,
[2][0][RTW89_FCC][8] = 66,
[2][0][RTW89_ETSI][8] = 58,
[2][0][RTW89_MKK][8] = 58,
[2][0][RTW89_IC][8] = 66,
- [2][0][RTW89_KCC][8] = 64,
+ [2][0][RTW89_KCC][8] = 60,
[2][0][RTW89_ACMA][8] = 58,
[2][0][RTW89_CN][8] = 56,
[2][0][RTW89_UK][8] = 58,
+ [2][0][RTW89_MEXICO][8] = 66,
+ [2][0][RTW89_UKRAINE][8] = 58,
+ [2][0][RTW89_CHILE][8] = 48,
+ [2][0][RTW89_QATAR][8] = 58,
[2][0][RTW89_FCC][9] = 64,
[2][0][RTW89_ETSI][9] = 58,
[2][0][RTW89_MKK][9] = 58,
[2][0][RTW89_IC][9] = 64,
- [2][0][RTW89_KCC][9] = 64,
+ [2][0][RTW89_KCC][9] = 60,
[2][0][RTW89_ACMA][9] = 58,
[2][0][RTW89_CN][9] = 56,
[2][0][RTW89_UK][9] = 58,
+ [2][0][RTW89_MEXICO][9] = 64,
+ [2][0][RTW89_UKRAINE][9] = 58,
+ [2][0][RTW89_CHILE][9] = 48,
+ [2][0][RTW89_QATAR][9] = 58,
[2][0][RTW89_FCC][10] = 64,
[2][0][RTW89_ETSI][10] = 58,
[2][0][RTW89_MKK][10] = 58,
[2][0][RTW89_IC][10] = 64,
- [2][0][RTW89_KCC][10] = 64,
+ [2][0][RTW89_KCC][10] = 60,
[2][0][RTW89_ACMA][10] = 58,
[2][0][RTW89_CN][10] = 56,
[2][0][RTW89_UK][10] = 58,
+ [2][0][RTW89_MEXICO][10] = 64,
+ [2][0][RTW89_UKRAINE][10] = 58,
+ [2][0][RTW89_CHILE][10] = 64,
+ [2][0][RTW89_QATAR][10] = 58,
[2][0][RTW89_FCC][11] = 48,
[2][0][RTW89_ETSI][11] = 58,
[2][0][RTW89_MKK][11] = 58,
[2][0][RTW89_IC][11] = 48,
- [2][0][RTW89_KCC][11] = 64,
+ [2][0][RTW89_KCC][11] = 60,
[2][0][RTW89_ACMA][11] = 58,
[2][0][RTW89_CN][11] = 56,
[2][0][RTW89_UK][11] = 58,
+ [2][0][RTW89_MEXICO][11] = 48,
+ [2][0][RTW89_UKRAINE][11] = 58,
+ [2][0][RTW89_CHILE][11] = 48,
+ [2][0][RTW89_QATAR][11] = 58,
[2][0][RTW89_FCC][12] = 16,
[2][0][RTW89_ETSI][12] = 58,
[2][0][RTW89_MKK][12] = 58,
[2][0][RTW89_IC][12] = 16,
- [2][0][RTW89_KCC][12] = 64,
+ [2][0][RTW89_KCC][12] = 60,
[2][0][RTW89_ACMA][12] = 58,
[2][0][RTW89_CN][12] = 56,
[2][0][RTW89_UK][12] = 58,
+ [2][0][RTW89_MEXICO][12] = 16,
+ [2][0][RTW89_UKRAINE][12] = 58,
+ [2][0][RTW89_CHILE][12] = 16,
+ [2][0][RTW89_QATAR][12] = 58,
[2][0][RTW89_FCC][13] = 127,
[2][0][RTW89_ETSI][13] = 127,
[2][0][RTW89_MKK][13] = 127,
@@ -34627,110 +46728,166 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][0][RTW89_ACMA][13] = 127,
[2][0][RTW89_CN][13] = 127,
[2][0][RTW89_UK][13] = 127,
+ [2][0][RTW89_MEXICO][13] = 127,
+ [2][0][RTW89_UKRAINE][13] = 127,
+ [2][0][RTW89_CHILE][13] = 127,
+ [2][0][RTW89_QATAR][13] = 127,
[2][1][RTW89_FCC][0] = 64,
[2][1][RTW89_ETSI][0] = 46,
[2][1][RTW89_MKK][0] = 46,
[2][1][RTW89_IC][0] = 64,
- [2][1][RTW89_KCC][0] = 52,
+ [2][1][RTW89_KCC][0] = 48,
[2][1][RTW89_ACMA][0] = 46,
[2][1][RTW89_CN][0] = 44,
[2][1][RTW89_UK][0] = 46,
+ [2][1][RTW89_MEXICO][0] = 64,
+ [2][1][RTW89_UKRAINE][0] = 46,
+ [2][1][RTW89_CHILE][0] = 64,
+ [2][1][RTW89_QATAR][0] = 46,
[2][1][RTW89_FCC][1] = 64,
[2][1][RTW89_ETSI][1] = 46,
[2][1][RTW89_MKK][1] = 46,
[2][1][RTW89_IC][1] = 64,
- [2][1][RTW89_KCC][1] = 52,
+ [2][1][RTW89_KCC][1] = 48,
[2][1][RTW89_ACMA][1] = 46,
[2][1][RTW89_CN][1] = 44,
[2][1][RTW89_UK][1] = 46,
+ [2][1][RTW89_MEXICO][1] = 64,
+ [2][1][RTW89_UKRAINE][1] = 46,
+ [2][1][RTW89_CHILE][1] = 44,
+ [2][1][RTW89_QATAR][1] = 46,
[2][1][RTW89_FCC][2] = 68,
[2][1][RTW89_ETSI][2] = 46,
[2][1][RTW89_MKK][2] = 46,
[2][1][RTW89_IC][2] = 68,
- [2][1][RTW89_KCC][2] = 52,
+ [2][1][RTW89_KCC][2] = 48,
[2][1][RTW89_ACMA][2] = 46,
[2][1][RTW89_CN][2] = 44,
[2][1][RTW89_UK][2] = 46,
+ [2][1][RTW89_MEXICO][2] = 68,
+ [2][1][RTW89_UKRAINE][2] = 46,
+ [2][1][RTW89_CHILE][2] = 44,
+ [2][1][RTW89_QATAR][2] = 46,
[2][1][RTW89_FCC][3] = 72,
[2][1][RTW89_ETSI][3] = 46,
[2][1][RTW89_MKK][3] = 46,
[2][1][RTW89_IC][3] = 72,
- [2][1][RTW89_KCC][3] = 52,
+ [2][1][RTW89_KCC][3] = 48,
[2][1][RTW89_ACMA][3] = 46,
[2][1][RTW89_CN][3] = 44,
[2][1][RTW89_UK][3] = 46,
+ [2][1][RTW89_MEXICO][3] = 72,
+ [2][1][RTW89_UKRAINE][3] = 46,
+ [2][1][RTW89_CHILE][3] = 44,
+ [2][1][RTW89_QATAR][3] = 46,
[2][1][RTW89_FCC][4] = 74,
[2][1][RTW89_ETSI][4] = 46,
[2][1][RTW89_MKK][4] = 46,
[2][1][RTW89_IC][4] = 74,
- [2][1][RTW89_KCC][4] = 50,
+ [2][1][RTW89_KCC][4] = 48,
[2][1][RTW89_ACMA][4] = 46,
[2][1][RTW89_CN][4] = 44,
[2][1][RTW89_UK][4] = 46,
+ [2][1][RTW89_MEXICO][4] = 74,
+ [2][1][RTW89_UKRAINE][4] = 46,
+ [2][1][RTW89_CHILE][4] = 44,
+ [2][1][RTW89_QATAR][4] = 46,
[2][1][RTW89_FCC][5] = 82,
[2][1][RTW89_ETSI][5] = 46,
[2][1][RTW89_MKK][5] = 46,
[2][1][RTW89_IC][5] = 82,
- [2][1][RTW89_KCC][5] = 50,
+ [2][1][RTW89_KCC][5] = 48,
[2][1][RTW89_ACMA][5] = 46,
[2][1][RTW89_CN][5] = 44,
[2][1][RTW89_UK][5] = 46,
+ [2][1][RTW89_MEXICO][5] = 82,
+ [2][1][RTW89_UKRAINE][5] = 46,
+ [2][1][RTW89_CHILE][5] = 78,
+ [2][1][RTW89_QATAR][5] = 46,
[2][1][RTW89_FCC][6] = 72,
[2][1][RTW89_ETSI][6] = 44,
[2][1][RTW89_MKK][6] = 46,
[2][1][RTW89_IC][6] = 72,
- [2][1][RTW89_KCC][6] = 50,
+ [2][1][RTW89_KCC][6] = 48,
[2][1][RTW89_ACMA][6] = 44,
[2][1][RTW89_CN][6] = 44,
[2][1][RTW89_UK][6] = 44,
+ [2][1][RTW89_MEXICO][6] = 72,
+ [2][1][RTW89_UKRAINE][6] = 44,
+ [2][1][RTW89_CHILE][6] = 42,
+ [2][1][RTW89_QATAR][6] = 44,
[2][1][RTW89_FCC][7] = 72,
[2][1][RTW89_ETSI][7] = 46,
[2][1][RTW89_MKK][7] = 46,
[2][1][RTW89_IC][7] = 72,
- [2][1][RTW89_KCC][7] = 50,
+ [2][1][RTW89_KCC][7] = 48,
[2][1][RTW89_ACMA][7] = 46,
[2][1][RTW89_CN][7] = 44,
[2][1][RTW89_UK][7] = 46,
+ [2][1][RTW89_MEXICO][7] = 72,
+ [2][1][RTW89_UKRAINE][7] = 46,
+ [2][1][RTW89_CHILE][7] = 42,
+ [2][1][RTW89_QATAR][7] = 46,
[2][1][RTW89_FCC][8] = 68,
[2][1][RTW89_ETSI][8] = 46,
[2][1][RTW89_MKK][8] = 46,
[2][1][RTW89_IC][8] = 68,
- [2][1][RTW89_KCC][8] = 50,
+ [2][1][RTW89_KCC][8] = 48,
[2][1][RTW89_ACMA][8] = 46,
[2][1][RTW89_CN][8] = 44,
[2][1][RTW89_UK][8] = 46,
+ [2][1][RTW89_MEXICO][8] = 68,
+ [2][1][RTW89_UKRAINE][8] = 46,
+ [2][1][RTW89_CHILE][8] = 42,
+ [2][1][RTW89_QATAR][8] = 46,
[2][1][RTW89_FCC][9] = 64,
[2][1][RTW89_ETSI][9] = 46,
[2][1][RTW89_MKK][9] = 46,
[2][1][RTW89_IC][9] = 64,
- [2][1][RTW89_KCC][9] = 52,
+ [2][1][RTW89_KCC][9] = 48,
[2][1][RTW89_ACMA][9] = 46,
[2][1][RTW89_CN][9] = 44,
[2][1][RTW89_UK][9] = 46,
+ [2][1][RTW89_MEXICO][9] = 64,
+ [2][1][RTW89_UKRAINE][9] = 46,
+ [2][1][RTW89_CHILE][9] = 42,
+ [2][1][RTW89_QATAR][9] = 46,
[2][1][RTW89_FCC][10] = 64,
[2][1][RTW89_ETSI][10] = 46,
[2][1][RTW89_MKK][10] = 46,
[2][1][RTW89_IC][10] = 64,
- [2][1][RTW89_KCC][10] = 52,
+ [2][1][RTW89_KCC][10] = 48,
[2][1][RTW89_ACMA][10] = 46,
[2][1][RTW89_CN][10] = 44,
[2][1][RTW89_UK][10] = 46,
+ [2][1][RTW89_MEXICO][10] = 64,
+ [2][1][RTW89_UKRAINE][10] = 46,
+ [2][1][RTW89_CHILE][10] = 64,
+ [2][1][RTW89_QATAR][10] = 46,
[2][1][RTW89_FCC][11] = 46,
[2][1][RTW89_ETSI][11] = 46,
[2][1][RTW89_MKK][11] = 46,
[2][1][RTW89_IC][11] = 46,
- [2][1][RTW89_KCC][11] = 52,
+ [2][1][RTW89_KCC][11] = 48,
[2][1][RTW89_ACMA][11] = 46,
[2][1][RTW89_CN][11] = 44,
[2][1][RTW89_UK][11] = 46,
+ [2][1][RTW89_MEXICO][11] = 46,
+ [2][1][RTW89_UKRAINE][11] = 46,
+ [2][1][RTW89_CHILE][11] = 46,
+ [2][1][RTW89_QATAR][11] = 46,
[2][1][RTW89_FCC][12] = 6,
[2][1][RTW89_ETSI][12] = 44,
[2][1][RTW89_MKK][12] = 46,
[2][1][RTW89_IC][12] = 6,
- [2][1][RTW89_KCC][12] = 52,
+ [2][1][RTW89_KCC][12] = 48,
[2][1][RTW89_ACMA][12] = 44,
[2][1][RTW89_CN][12] = 42,
[2][1][RTW89_UK][12] = 44,
+ [2][1][RTW89_MEXICO][12] = 6,
+ [2][1][RTW89_UKRAINE][12] = 44,
+ [2][1][RTW89_CHILE][12] = 6,
+ [2][1][RTW89_QATAR][12] = 44,
[2][1][RTW89_FCC][13] = 127,
[2][1][RTW89_ETSI][13] = 127,
[2][1][RTW89_MKK][13] = 127,
@@ -34739,6 +46896,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][1][RTW89_ACMA][13] = 127,
[2][1][RTW89_CN][13] = 127,
[2][1][RTW89_UK][13] = 127,
+ [2][1][RTW89_MEXICO][13] = 127,
+ [2][1][RTW89_UKRAINE][13] = 127,
+ [2][1][RTW89_CHILE][13] = 127,
+ [2][1][RTW89_QATAR][13] = 127,
};
static
@@ -34747,168 +46908,168 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_WW][0] = 16,
[0][0][RTW89_WW][2] = 16,
[0][0][RTW89_WW][4] = 16,
- [0][0][RTW89_WW][6] = 10,
+ [0][0][RTW89_WW][6] = 16,
[0][0][RTW89_WW][8] = 16,
[0][0][RTW89_WW][10] = 16,
[0][0][RTW89_WW][12] = 16,
[0][0][RTW89_WW][14] = 16,
- [0][0][RTW89_WW][15] = 30,
- [0][0][RTW89_WW][17] = 30,
- [0][0][RTW89_WW][19] = 30,
- [0][0][RTW89_WW][21] = 30,
- [0][0][RTW89_WW][23] = 30,
- [0][0][RTW89_WW][25] = 30,
- [0][0][RTW89_WW][27] = 30,
- [0][0][RTW89_WW][29] = 30,
- [0][0][RTW89_WW][31] = 30,
- [0][0][RTW89_WW][33] = 30,
- [0][0][RTW89_WW][35] = 30,
+ [0][0][RTW89_WW][15] = 22,
+ [0][0][RTW89_WW][17] = 22,
+ [0][0][RTW89_WW][19] = 22,
+ [0][0][RTW89_WW][21] = 22,
+ [0][0][RTW89_WW][23] = 22,
+ [0][0][RTW89_WW][25] = 22,
+ [0][0][RTW89_WW][27] = 22,
+ [0][0][RTW89_WW][29] = 22,
+ [0][0][RTW89_WW][31] = 22,
+ [0][0][RTW89_WW][33] = 22,
+ [0][0][RTW89_WW][35] = 22,
[0][0][RTW89_WW][37] = 30,
- [0][0][RTW89_WW][38] = 28,
- [0][0][RTW89_WW][40] = 28,
- [0][0][RTW89_WW][42] = 28,
- [0][0][RTW89_WW][44] = 28,
- [0][0][RTW89_WW][46] = 28,
+ [0][0][RTW89_WW][38] = 26,
+ [0][0][RTW89_WW][40] = 26,
+ [0][0][RTW89_WW][42] = 26,
+ [0][0][RTW89_WW][44] = 26,
+ [0][0][RTW89_WW][46] = 26,
[0][0][RTW89_WW][48] = 46,
[0][0][RTW89_WW][50] = 44,
[0][0][RTW89_WW][52] = 34,
[0][1][RTW89_WW][0] = 4,
[0][1][RTW89_WW][2] = 4,
[0][1][RTW89_WW][4] = 4,
- [0][1][RTW89_WW][6] = 1,
+ [0][1][RTW89_WW][6] = 4,
[0][1][RTW89_WW][8] = 4,
[0][1][RTW89_WW][10] = 4,
[0][1][RTW89_WW][12] = 4,
[0][1][RTW89_WW][14] = 4,
- [0][1][RTW89_WW][15] = 18,
- [0][1][RTW89_WW][17] = 18,
- [0][1][RTW89_WW][19] = 18,
- [0][1][RTW89_WW][21] = 18,
- [0][1][RTW89_WW][23] = 18,
- [0][1][RTW89_WW][25] = 18,
- [0][1][RTW89_WW][27] = 16,
- [0][1][RTW89_WW][29] = 16,
- [0][1][RTW89_WW][31] = 16,
- [0][1][RTW89_WW][33] = 16,
- [0][1][RTW89_WW][35] = 16,
+ [0][1][RTW89_WW][15] = 10,
+ [0][1][RTW89_WW][17] = 10,
+ [0][1][RTW89_WW][19] = 10,
+ [0][1][RTW89_WW][21] = 10,
+ [0][1][RTW89_WW][23] = 10,
+ [0][1][RTW89_WW][25] = 10,
+ [0][1][RTW89_WW][27] = 10,
+ [0][1][RTW89_WW][29] = 10,
+ [0][1][RTW89_WW][31] = 10,
+ [0][1][RTW89_WW][33] = 10,
+ [0][1][RTW89_WW][35] = 10,
[0][1][RTW89_WW][37] = 18,
- [0][1][RTW89_WW][38] = 16,
- [0][1][RTW89_WW][40] = 16,
- [0][1][RTW89_WW][42] = 16,
- [0][1][RTW89_WW][44] = 16,
- [0][1][RTW89_WW][46] = 16,
+ [0][1][RTW89_WW][38] = 14,
+ [0][1][RTW89_WW][40] = 14,
+ [0][1][RTW89_WW][42] = 14,
+ [0][1][RTW89_WW][44] = 14,
+ [0][1][RTW89_WW][46] = 14,
[0][1][RTW89_WW][48] = 20,
[0][1][RTW89_WW][50] = 20,
[0][1][RTW89_WW][52] = 8,
[1][0][RTW89_WW][0] = 26,
[1][0][RTW89_WW][2] = 26,
[1][0][RTW89_WW][4] = 26,
- [1][0][RTW89_WW][6] = 24,
+ [1][0][RTW89_WW][6] = 26,
[1][0][RTW89_WW][8] = 26,
[1][0][RTW89_WW][10] = 26,
[1][0][RTW89_WW][12] = 26,
[1][0][RTW89_WW][14] = 26,
- [1][0][RTW89_WW][15] = 40,
- [1][0][RTW89_WW][17] = 40,
- [1][0][RTW89_WW][19] = 40,
- [1][0][RTW89_WW][21] = 40,
- [1][0][RTW89_WW][23] = 40,
- [1][0][RTW89_WW][25] = 40,
- [1][0][RTW89_WW][27] = 42,
- [1][0][RTW89_WW][29] = 42,
- [1][0][RTW89_WW][31] = 42,
- [1][0][RTW89_WW][33] = 42,
- [1][0][RTW89_WW][35] = 42,
+ [1][0][RTW89_WW][15] = 32,
+ [1][0][RTW89_WW][17] = 32,
+ [1][0][RTW89_WW][19] = 32,
+ [1][0][RTW89_WW][21] = 32,
+ [1][0][RTW89_WW][23] = 32,
+ [1][0][RTW89_WW][25] = 32,
+ [1][0][RTW89_WW][27] = 32,
+ [1][0][RTW89_WW][29] = 32,
+ [1][0][RTW89_WW][31] = 32,
+ [1][0][RTW89_WW][33] = 32,
+ [1][0][RTW89_WW][35] = 32,
[1][0][RTW89_WW][37] = 42,
- [1][0][RTW89_WW][38] = 28,
- [1][0][RTW89_WW][40] = 28,
- [1][0][RTW89_WW][42] = 28,
- [1][0][RTW89_WW][44] = 28,
- [1][0][RTW89_WW][46] = 28,
+ [1][0][RTW89_WW][38] = 26,
+ [1][0][RTW89_WW][40] = 26,
+ [1][0][RTW89_WW][42] = 26,
+ [1][0][RTW89_WW][44] = 26,
+ [1][0][RTW89_WW][46] = 26,
[1][0][RTW89_WW][48] = 56,
[1][0][RTW89_WW][50] = 58,
[1][0][RTW89_WW][52] = 56,
[1][1][RTW89_WW][0] = 14,
[1][1][RTW89_WW][2] = 14,
[1][1][RTW89_WW][4] = 14,
- [1][1][RTW89_WW][6] = 8,
+ [1][1][RTW89_WW][6] = 14,
[1][1][RTW89_WW][8] = 14,
[1][1][RTW89_WW][10] = 14,
[1][1][RTW89_WW][12] = 14,
[1][1][RTW89_WW][14] = 14,
- [1][1][RTW89_WW][15] = 28,
- [1][1][RTW89_WW][17] = 28,
- [1][1][RTW89_WW][19] = 28,
- [1][1][RTW89_WW][21] = 28,
- [1][1][RTW89_WW][23] = 28,
- [1][1][RTW89_WW][25] = 28,
- [1][1][RTW89_WW][27] = 30,
- [1][1][RTW89_WW][29] = 30,
- [1][1][RTW89_WW][31] = 30,
- [1][1][RTW89_WW][33] = 30,
- [1][1][RTW89_WW][35] = 30,
+ [1][1][RTW89_WW][15] = 20,
+ [1][1][RTW89_WW][17] = 20,
+ [1][1][RTW89_WW][19] = 20,
+ [1][1][RTW89_WW][21] = 20,
+ [1][1][RTW89_WW][23] = 20,
+ [1][1][RTW89_WW][25] = 20,
+ [1][1][RTW89_WW][27] = 20,
+ [1][1][RTW89_WW][29] = 20,
+ [1][1][RTW89_WW][31] = 20,
+ [1][1][RTW89_WW][33] = 20,
+ [1][1][RTW89_WW][35] = 20,
[1][1][RTW89_WW][37] = 32,
- [1][1][RTW89_WW][38] = 16,
- [1][1][RTW89_WW][40] = 16,
- [1][1][RTW89_WW][42] = 16,
- [1][1][RTW89_WW][44] = 16,
- [1][1][RTW89_WW][46] = 16,
+ [1][1][RTW89_WW][38] = 14,
+ [1][1][RTW89_WW][40] = 14,
+ [1][1][RTW89_WW][42] = 14,
+ [1][1][RTW89_WW][44] = 14,
+ [1][1][RTW89_WW][46] = 14,
[1][1][RTW89_WW][48] = 34,
[1][1][RTW89_WW][50] = 34,
[1][1][RTW89_WW][52] = 30,
[2][0][RTW89_WW][0] = 40,
[2][0][RTW89_WW][2] = 40,
[2][0][RTW89_WW][4] = 40,
- [2][0][RTW89_WW][6] = 36,
+ [2][0][RTW89_WW][6] = 38,
[2][0][RTW89_WW][8] = 40,
[2][0][RTW89_WW][10] = 40,
[2][0][RTW89_WW][12] = 40,
[2][0][RTW89_WW][14] = 40,
- [2][0][RTW89_WW][15] = 52,
- [2][0][RTW89_WW][17] = 52,
- [2][0][RTW89_WW][19] = 52,
- [2][0][RTW89_WW][21] = 52,
- [2][0][RTW89_WW][23] = 52,
- [2][0][RTW89_WW][25] = 52,
- [2][0][RTW89_WW][27] = 52,
- [2][0][RTW89_WW][29] = 52,
- [2][0][RTW89_WW][31] = 52,
- [2][0][RTW89_WW][33] = 52,
- [2][0][RTW89_WW][35] = 52,
+ [2][0][RTW89_WW][15] = 46,
+ [2][0][RTW89_WW][17] = 46,
+ [2][0][RTW89_WW][19] = 46,
+ [2][0][RTW89_WW][21] = 46,
+ [2][0][RTW89_WW][23] = 46,
+ [2][0][RTW89_WW][25] = 46,
+ [2][0][RTW89_WW][27] = 46,
+ [2][0][RTW89_WW][29] = 46,
+ [2][0][RTW89_WW][31] = 46,
+ [2][0][RTW89_WW][33] = 46,
+ [2][0][RTW89_WW][35] = 46,
[2][0][RTW89_WW][37] = 52,
- [2][0][RTW89_WW][38] = 28,
- [2][0][RTW89_WW][40] = 28,
- [2][0][RTW89_WW][42] = 28,
- [2][0][RTW89_WW][44] = 28,
- [2][0][RTW89_WW][46] = 28,
+ [2][0][RTW89_WW][38] = 26,
+ [2][0][RTW89_WW][40] = 26,
+ [2][0][RTW89_WW][42] = 26,
+ [2][0][RTW89_WW][44] = 26,
+ [2][0][RTW89_WW][46] = 26,
[2][0][RTW89_WW][48] = 64,
[2][0][RTW89_WW][50] = 64,
[2][0][RTW89_WW][52] = 64,
[2][1][RTW89_WW][0] = 26,
[2][1][RTW89_WW][2] = 26,
[2][1][RTW89_WW][4] = 26,
- [2][1][RTW89_WW][6] = 20,
+ [2][1][RTW89_WW][6] = 26,
[2][1][RTW89_WW][8] = 28,
[2][1][RTW89_WW][10] = 28,
[2][1][RTW89_WW][12] = 28,
[2][1][RTW89_WW][14] = 28,
- [2][1][RTW89_WW][15] = 40,
- [2][1][RTW89_WW][17] = 40,
- [2][1][RTW89_WW][19] = 40,
- [2][1][RTW89_WW][21] = 40,
- [2][1][RTW89_WW][23] = 40,
- [2][1][RTW89_WW][25] = 40,
- [2][1][RTW89_WW][27] = 40,
- [2][1][RTW89_WW][29] = 40,
- [2][1][RTW89_WW][31] = 40,
- [2][1][RTW89_WW][33] = 40,
- [2][1][RTW89_WW][35] = 40,
+ [2][1][RTW89_WW][15] = 34,
+ [2][1][RTW89_WW][17] = 34,
+ [2][1][RTW89_WW][19] = 34,
+ [2][1][RTW89_WW][21] = 34,
+ [2][1][RTW89_WW][23] = 34,
+ [2][1][RTW89_WW][25] = 34,
+ [2][1][RTW89_WW][27] = 34,
+ [2][1][RTW89_WW][29] = 34,
+ [2][1][RTW89_WW][31] = 34,
+ [2][1][RTW89_WW][33] = 34,
+ [2][1][RTW89_WW][35] = 34,
[2][1][RTW89_WW][37] = 42,
- [2][1][RTW89_WW][38] = 16,
- [2][1][RTW89_WW][40] = 16,
- [2][1][RTW89_WW][42] = 16,
- [2][1][RTW89_WW][44] = 16,
- [2][1][RTW89_WW][46] = 16,
+ [2][1][RTW89_WW][38] = 14,
+ [2][1][RTW89_WW][40] = 14,
+ [2][1][RTW89_WW][42] = 14,
+ [2][1][RTW89_WW][44] = 14,
+ [2][1][RTW89_WW][46] = 14,
[2][1][RTW89_WW][48] = 40,
[2][1][RTW89_WW][50] = 40,
[2][1][RTW89_WW][52] = 40,
@@ -34920,6 +47081,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][0] = 30,
[0][0][RTW89_CN][0] = 16,
[0][0][RTW89_UK][0] = 30,
+ [0][0][RTW89_MEXICO][0] = 50,
+ [0][0][RTW89_UKRAINE][0] = 22,
+ [0][0][RTW89_CHILE][0] = 50,
+ [0][0][RTW89_QATAR][0] = 30,
[0][0][RTW89_FCC][2] = 50,
[0][0][RTW89_ETSI][2] = 30,
[0][0][RTW89_MKK][2] = 36,
@@ -34928,6 +47093,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][2] = 30,
[0][0][RTW89_CN][2] = 16,
[0][0][RTW89_UK][2] = 30,
+ [0][0][RTW89_MEXICO][2] = 50,
+ [0][0][RTW89_UKRAINE][2] = 22,
+ [0][0][RTW89_CHILE][2] = 50,
+ [0][0][RTW89_QATAR][2] = 30,
[0][0][RTW89_FCC][4] = 50,
[0][0][RTW89_ETSI][4] = 30,
[0][0][RTW89_MKK][4] = 22,
@@ -34936,30 +47105,46 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][4] = 30,
[0][0][RTW89_CN][4] = 16,
[0][0][RTW89_UK][4] = 30,
+ [0][0][RTW89_MEXICO][4] = 50,
+ [0][0][RTW89_UKRAINE][4] = 22,
+ [0][0][RTW89_CHILE][4] = 50,
+ [0][0][RTW89_QATAR][4] = 30,
[0][0][RTW89_FCC][6] = 50,
[0][0][RTW89_ETSI][6] = 30,
[0][0][RTW89_MKK][6] = 22,
[0][0][RTW89_IC][6] = 32,
- [0][0][RTW89_KCC][6] = 10,
+ [0][0][RTW89_KCC][6] = 18,
[0][0][RTW89_ACMA][6] = 30,
[0][0][RTW89_CN][6] = 16,
[0][0][RTW89_UK][6] = 30,
+ [0][0][RTW89_MEXICO][6] = 50,
+ [0][0][RTW89_UKRAINE][6] = 22,
+ [0][0][RTW89_CHILE][6] = 50,
+ [0][0][RTW89_QATAR][6] = 30,
[0][0][RTW89_FCC][8] = 52,
[0][0][RTW89_ETSI][8] = 28,
[0][0][RTW89_MKK][8] = 18,
[0][0][RTW89_IC][8] = 52,
- [0][0][RTW89_KCC][8] = 44,
+ [0][0][RTW89_KCC][8] = 40,
[0][0][RTW89_ACMA][8] = 28,
[0][0][RTW89_CN][8] = 16,
[0][0][RTW89_UK][8] = 28,
+ [0][0][RTW89_MEXICO][8] = 52,
+ [0][0][RTW89_UKRAINE][8] = 22,
+ [0][0][RTW89_CHILE][8] = 52,
+ [0][0][RTW89_QATAR][8] = 28,
[0][0][RTW89_FCC][10] = 52,
[0][0][RTW89_ETSI][10] = 28,
[0][0][RTW89_MKK][10] = 18,
[0][0][RTW89_IC][10] = 52,
- [0][0][RTW89_KCC][10] = 44,
+ [0][0][RTW89_KCC][10] = 40,
[0][0][RTW89_ACMA][10] = 28,
[0][0][RTW89_CN][10] = 16,
[0][0][RTW89_UK][10] = 28,
+ [0][0][RTW89_MEXICO][10] = 52,
+ [0][0][RTW89_UKRAINE][10] = 22,
+ [0][0][RTW89_CHILE][10] = 52,
+ [0][0][RTW89_QATAR][10] = 28,
[0][0][RTW89_FCC][12] = 52,
[0][0][RTW89_ETSI][12] = 28,
[0][0][RTW89_MKK][12] = 34,
@@ -34968,6 +47153,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][12] = 28,
[0][0][RTW89_CN][12] = 16,
[0][0][RTW89_UK][12] = 28,
+ [0][0][RTW89_MEXICO][12] = 52,
+ [0][0][RTW89_UKRAINE][12] = 22,
+ [0][0][RTW89_CHILE][12] = 52,
+ [0][0][RTW89_QATAR][12] = 28,
[0][0][RTW89_FCC][14] = 52,
[0][0][RTW89_ETSI][14] = 28,
[0][0][RTW89_MKK][14] = 34,
@@ -34976,70 +47165,106 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][14] = 28,
[0][0][RTW89_CN][14] = 16,
[0][0][RTW89_UK][14] = 28,
+ [0][0][RTW89_MEXICO][14] = 52,
+ [0][0][RTW89_UKRAINE][14] = 22,
+ [0][0][RTW89_CHILE][14] = 52,
+ [0][0][RTW89_QATAR][14] = 28,
[0][0][RTW89_FCC][15] = 52,
[0][0][RTW89_ETSI][15] = 30,
[0][0][RTW89_MKK][15] = 56,
[0][0][RTW89_IC][15] = 52,
- [0][0][RTW89_KCC][15] = 42,
+ [0][0][RTW89_KCC][15] = 40,
[0][0][RTW89_ACMA][15] = 30,
[0][0][RTW89_CN][15] = 127,
[0][0][RTW89_UK][15] = 30,
+ [0][0][RTW89_MEXICO][15] = 52,
+ [0][0][RTW89_UKRAINE][15] = 22,
+ [0][0][RTW89_CHILE][15] = 52,
+ [0][0][RTW89_QATAR][15] = 30,
[0][0][RTW89_FCC][17] = 52,
[0][0][RTW89_ETSI][17] = 30,
[0][0][RTW89_MKK][17] = 58,
[0][0][RTW89_IC][17] = 52,
- [0][0][RTW89_KCC][17] = 42,
+ [0][0][RTW89_KCC][17] = 40,
[0][0][RTW89_ACMA][17] = 30,
[0][0][RTW89_CN][17] = 127,
[0][0][RTW89_UK][17] = 30,
+ [0][0][RTW89_MEXICO][17] = 52,
+ [0][0][RTW89_UKRAINE][17] = 22,
+ [0][0][RTW89_CHILE][17] = 52,
+ [0][0][RTW89_QATAR][17] = 30,
[0][0][RTW89_FCC][19] = 52,
[0][0][RTW89_ETSI][19] = 30,
[0][0][RTW89_MKK][19] = 58,
[0][0][RTW89_IC][19] = 52,
- [0][0][RTW89_KCC][19] = 42,
+ [0][0][RTW89_KCC][19] = 40,
[0][0][RTW89_ACMA][19] = 30,
[0][0][RTW89_CN][19] = 127,
[0][0][RTW89_UK][19] = 30,
+ [0][0][RTW89_MEXICO][19] = 52,
+ [0][0][RTW89_UKRAINE][19] = 22,
+ [0][0][RTW89_CHILE][19] = 52,
+ [0][0][RTW89_QATAR][19] = 30,
[0][0][RTW89_FCC][21] = 52,
[0][0][RTW89_ETSI][21] = 30,
[0][0][RTW89_MKK][21] = 58,
[0][0][RTW89_IC][21] = 52,
- [0][0][RTW89_KCC][21] = 42,
+ [0][0][RTW89_KCC][21] = 40,
[0][0][RTW89_ACMA][21] = 30,
[0][0][RTW89_CN][21] = 127,
[0][0][RTW89_UK][21] = 30,
+ [0][0][RTW89_MEXICO][21] = 52,
+ [0][0][RTW89_UKRAINE][21] = 22,
+ [0][0][RTW89_CHILE][21] = 52,
+ [0][0][RTW89_QATAR][21] = 30,
[0][0][RTW89_FCC][23] = 52,
[0][0][RTW89_ETSI][23] = 30,
[0][0][RTW89_MKK][23] = 58,
[0][0][RTW89_IC][23] = 52,
- [0][0][RTW89_KCC][23] = 42,
+ [0][0][RTW89_KCC][23] = 40,
[0][0][RTW89_ACMA][23] = 30,
[0][0][RTW89_CN][23] = 127,
[0][0][RTW89_UK][23] = 30,
+ [0][0][RTW89_MEXICO][23] = 52,
+ [0][0][RTW89_UKRAINE][23] = 22,
+ [0][0][RTW89_CHILE][23] = 52,
+ [0][0][RTW89_QATAR][23] = 30,
[0][0][RTW89_FCC][25] = 52,
[0][0][RTW89_ETSI][25] = 30,
[0][0][RTW89_MKK][25] = 58,
[0][0][RTW89_IC][25] = 127,
- [0][0][RTW89_KCC][25] = 42,
+ [0][0][RTW89_KCC][25] = 40,
[0][0][RTW89_ACMA][25] = 127,
[0][0][RTW89_CN][25] = 127,
[0][0][RTW89_UK][25] = 30,
+ [0][0][RTW89_MEXICO][25] = 52,
+ [0][0][RTW89_UKRAINE][25] = 22,
+ [0][0][RTW89_CHILE][25] = 52,
+ [0][0][RTW89_QATAR][25] = 30,
[0][0][RTW89_FCC][27] = 52,
[0][0][RTW89_ETSI][27] = 30,
[0][0][RTW89_MKK][27] = 58,
[0][0][RTW89_IC][27] = 127,
- [0][0][RTW89_KCC][27] = 42,
+ [0][0][RTW89_KCC][27] = 40,
[0][0][RTW89_ACMA][27] = 127,
[0][0][RTW89_CN][27] = 127,
[0][0][RTW89_UK][27] = 30,
+ [0][0][RTW89_MEXICO][27] = 52,
+ [0][0][RTW89_UKRAINE][27] = 22,
+ [0][0][RTW89_CHILE][27] = 52,
+ [0][0][RTW89_QATAR][27] = 30,
[0][0][RTW89_FCC][29] = 52,
[0][0][RTW89_ETSI][29] = 30,
[0][0][RTW89_MKK][29] = 58,
[0][0][RTW89_IC][29] = 127,
- [0][0][RTW89_KCC][29] = 42,
+ [0][0][RTW89_KCC][29] = 40,
[0][0][RTW89_ACMA][29] = 127,
[0][0][RTW89_CN][29] = 127,
[0][0][RTW89_UK][29] = 30,
+ [0][0][RTW89_MEXICO][29] = 52,
+ [0][0][RTW89_UKRAINE][29] = 22,
+ [0][0][RTW89_CHILE][29] = 52,
+ [0][0][RTW89_QATAR][29] = 30,
[0][0][RTW89_FCC][31] = 52,
[0][0][RTW89_ETSI][31] = 30,
[0][0][RTW89_MKK][31] = 58,
@@ -35048,6 +47273,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][31] = 30,
[0][0][RTW89_CN][31] = 127,
[0][0][RTW89_UK][31] = 30,
+ [0][0][RTW89_MEXICO][31] = 52,
+ [0][0][RTW89_UKRAINE][31] = 22,
+ [0][0][RTW89_CHILE][31] = 52,
+ [0][0][RTW89_QATAR][31] = 30,
[0][0][RTW89_FCC][33] = 44,
[0][0][RTW89_ETSI][33] = 30,
[0][0][RTW89_MKK][33] = 58,
@@ -35056,6 +47285,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][33] = 30,
[0][0][RTW89_CN][33] = 127,
[0][0][RTW89_UK][33] = 30,
+ [0][0][RTW89_MEXICO][33] = 44,
+ [0][0][RTW89_UKRAINE][33] = 22,
+ [0][0][RTW89_CHILE][33] = 44,
+ [0][0][RTW89_QATAR][33] = 30,
[0][0][RTW89_FCC][35] = 44,
[0][0][RTW89_ETSI][35] = 30,
[0][0][RTW89_MKK][35] = 58,
@@ -35064,6 +47297,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][35] = 30,
[0][0][RTW89_CN][35] = 127,
[0][0][RTW89_UK][35] = 30,
+ [0][0][RTW89_MEXICO][35] = 44,
+ [0][0][RTW89_UKRAINE][35] = 22,
+ [0][0][RTW89_CHILE][35] = 44,
+ [0][0][RTW89_QATAR][35] = 30,
[0][0][RTW89_FCC][37] = 52,
[0][0][RTW89_ETSI][37] = 127,
[0][0][RTW89_MKK][37] = 58,
@@ -35072,6 +47309,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][37] = 52,
[0][0][RTW89_CN][37] = 127,
[0][0][RTW89_UK][37] = 30,
+ [0][0][RTW89_MEXICO][37] = 52,
+ [0][0][RTW89_UKRAINE][37] = 127,
+ [0][0][RTW89_CHILE][37] = 52,
+ [0][0][RTW89_QATAR][37] = 127,
[0][0][RTW89_FCC][38] = 64,
[0][0][RTW89_ETSI][38] = 28,
[0][0][RTW89_MKK][38] = 127,
@@ -35080,6 +47321,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][38] = 64,
[0][0][RTW89_CN][38] = 54,
[0][0][RTW89_UK][38] = 30,
+ [0][0][RTW89_MEXICO][38] = 64,
+ [0][0][RTW89_UKRAINE][38] = 26,
+ [0][0][RTW89_CHILE][38] = 64,
+ [0][0][RTW89_QATAR][38] = 26,
[0][0][RTW89_FCC][40] = 64,
[0][0][RTW89_ETSI][40] = 28,
[0][0][RTW89_MKK][40] = 127,
@@ -35088,6 +47333,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][40] = 64,
[0][0][RTW89_CN][40] = 54,
[0][0][RTW89_UK][40] = 30,
+ [0][0][RTW89_MEXICO][40] = 64,
+ [0][0][RTW89_UKRAINE][40] = 26,
+ [0][0][RTW89_CHILE][40] = 64,
+ [0][0][RTW89_QATAR][40] = 26,
[0][0][RTW89_FCC][42] = 60,
[0][0][RTW89_ETSI][42] = 28,
[0][0][RTW89_MKK][42] = 127,
@@ -35096,6 +47345,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][42] = 60,
[0][0][RTW89_CN][42] = 54,
[0][0][RTW89_UK][42] = 30,
+ [0][0][RTW89_MEXICO][42] = 60,
+ [0][0][RTW89_UKRAINE][42] = 26,
+ [0][0][RTW89_CHILE][42] = 60,
+ [0][0][RTW89_QATAR][42] = 26,
[0][0][RTW89_FCC][44] = 60,
[0][0][RTW89_ETSI][44] = 28,
[0][0][RTW89_MKK][44] = 127,
@@ -35104,6 +47357,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][44] = 60,
[0][0][RTW89_CN][44] = 54,
[0][0][RTW89_UK][44] = 30,
+ [0][0][RTW89_MEXICO][44] = 60,
+ [0][0][RTW89_UKRAINE][44] = 26,
+ [0][0][RTW89_CHILE][44] = 60,
+ [0][0][RTW89_QATAR][44] = 26,
[0][0][RTW89_FCC][46] = 60,
[0][0][RTW89_ETSI][46] = 28,
[0][0][RTW89_MKK][46] = 127,
@@ -35112,6 +47369,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][46] = 60,
[0][0][RTW89_CN][46] = 54,
[0][0][RTW89_UK][46] = 30,
+ [0][0][RTW89_MEXICO][46] = 60,
+ [0][0][RTW89_UKRAINE][46] = 26,
+ [0][0][RTW89_CHILE][46] = 60,
+ [0][0][RTW89_QATAR][46] = 26,
[0][0][RTW89_FCC][48] = 46,
[0][0][RTW89_ETSI][48] = 127,
[0][0][RTW89_MKK][48] = 127,
@@ -35120,6 +47381,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][48] = 127,
[0][0][RTW89_CN][48] = 127,
[0][0][RTW89_UK][48] = 127,
+ [0][0][RTW89_MEXICO][48] = 127,
+ [0][0][RTW89_UKRAINE][48] = 127,
+ [0][0][RTW89_CHILE][48] = 127,
+ [0][0][RTW89_QATAR][48] = 127,
[0][0][RTW89_FCC][50] = 44,
[0][0][RTW89_ETSI][50] = 127,
[0][0][RTW89_MKK][50] = 127,
@@ -35128,6 +47393,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][50] = 127,
[0][0][RTW89_CN][50] = 127,
[0][0][RTW89_UK][50] = 127,
+ [0][0][RTW89_MEXICO][50] = 127,
+ [0][0][RTW89_UKRAINE][50] = 127,
+ [0][0][RTW89_CHILE][50] = 127,
+ [0][0][RTW89_QATAR][50] = 127,
[0][0][RTW89_FCC][52] = 34,
[0][0][RTW89_ETSI][52] = 127,
[0][0][RTW89_MKK][52] = 127,
@@ -35136,38 +47405,58 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][52] = 127,
[0][0][RTW89_CN][52] = 127,
[0][0][RTW89_UK][52] = 127,
+ [0][0][RTW89_MEXICO][52] = 127,
+ [0][0][RTW89_UKRAINE][52] = 127,
+ [0][0][RTW89_CHILE][52] = 127,
+ [0][0][RTW89_QATAR][52] = 127,
[0][1][RTW89_FCC][0] = 30,
[0][1][RTW89_ETSI][0] = 18,
[0][1][RTW89_MKK][0] = 20,
[0][1][RTW89_IC][0] = 8,
- [0][1][RTW89_KCC][0] = 26,
+ [0][1][RTW89_KCC][0] = 32,
[0][1][RTW89_ACMA][0] = 18,
[0][1][RTW89_CN][0] = 4,
[0][1][RTW89_UK][0] = 18,
+ [0][1][RTW89_MEXICO][0] = 30,
+ [0][1][RTW89_UKRAINE][0] = 10,
+ [0][1][RTW89_CHILE][0] = 30,
+ [0][1][RTW89_QATAR][0] = 18,
[0][1][RTW89_FCC][2] = 32,
[0][1][RTW89_ETSI][2] = 18,
[0][1][RTW89_MKK][2] = 20,
[0][1][RTW89_IC][2] = 8,
- [0][1][RTW89_KCC][2] = 26,
+ [0][1][RTW89_KCC][2] = 32,
[0][1][RTW89_ACMA][2] = 18,
[0][1][RTW89_CN][2] = 4,
[0][1][RTW89_UK][2] = 18,
+ [0][1][RTW89_MEXICO][2] = 32,
+ [0][1][RTW89_UKRAINE][2] = 10,
+ [0][1][RTW89_CHILE][2] = 32,
+ [0][1][RTW89_QATAR][2] = 18,
[0][1][RTW89_FCC][4] = 30,
[0][1][RTW89_ETSI][4] = 18,
[0][1][RTW89_MKK][4] = 8,
[0][1][RTW89_IC][4] = 8,
- [0][1][RTW89_KCC][4] = 26,
+ [0][1][RTW89_KCC][4] = 32,
[0][1][RTW89_ACMA][4] = 18,
[0][1][RTW89_CN][4] = 4,
[0][1][RTW89_UK][4] = 18,
+ [0][1][RTW89_MEXICO][4] = 30,
+ [0][1][RTW89_UKRAINE][4] = 10,
+ [0][1][RTW89_CHILE][4] = 30,
+ [0][1][RTW89_QATAR][4] = 18,
[0][1][RTW89_FCC][6] = 30,
[0][1][RTW89_ETSI][6] = 18,
[0][1][RTW89_MKK][6] = 8,
[0][1][RTW89_IC][6] = 8,
- [0][1][RTW89_KCC][6] = 0,
+ [0][1][RTW89_KCC][6] = 6,
[0][1][RTW89_ACMA][6] = 18,
[0][1][RTW89_CN][6] = 4,
[0][1][RTW89_UK][6] = 18,
+ [0][1][RTW89_MEXICO][6] = 30,
+ [0][1][RTW89_UKRAINE][6] = 10,
+ [0][1][RTW89_CHILE][6] = 30,
+ [0][1][RTW89_QATAR][6] = 18,
[0][1][RTW89_FCC][8] = 30,
[0][1][RTW89_ETSI][8] = 16,
[0][1][RTW89_MKK][8] = 20,
@@ -35176,6 +47465,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][8] = 16,
[0][1][RTW89_CN][8] = 4,
[0][1][RTW89_UK][8] = 16,
+ [0][1][RTW89_MEXICO][8] = 30,
+ [0][1][RTW89_UKRAINE][8] = 10,
+ [0][1][RTW89_CHILE][8] = 30,
+ [0][1][RTW89_QATAR][8] = 16,
[0][1][RTW89_FCC][10] = 30,
[0][1][RTW89_ETSI][10] = 16,
[0][1][RTW89_MKK][10] = 20,
@@ -35184,22 +47477,34 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][10] = 16,
[0][1][RTW89_CN][10] = 4,
[0][1][RTW89_UK][10] = 16,
+ [0][1][RTW89_MEXICO][10] = 30,
+ [0][1][RTW89_UKRAINE][10] = 10,
+ [0][1][RTW89_CHILE][10] = 30,
+ [0][1][RTW89_QATAR][10] = 16,
[0][1][RTW89_FCC][12] = 30,
[0][1][RTW89_ETSI][12] = 16,
[0][1][RTW89_MKK][12] = 34,
[0][1][RTW89_IC][12] = 30,
- [0][1][RTW89_KCC][12] = 28,
+ [0][1][RTW89_KCC][12] = 26,
[0][1][RTW89_ACMA][12] = 16,
[0][1][RTW89_CN][12] = 4,
[0][1][RTW89_UK][12] = 16,
+ [0][1][RTW89_MEXICO][12] = 30,
+ [0][1][RTW89_UKRAINE][12] = 10,
+ [0][1][RTW89_CHILE][12] = 30,
+ [0][1][RTW89_QATAR][12] = 16,
[0][1][RTW89_FCC][14] = 30,
[0][1][RTW89_ETSI][14] = 16,
[0][1][RTW89_MKK][14] = 34,
[0][1][RTW89_IC][14] = 30,
- [0][1][RTW89_KCC][14] = 28,
+ [0][1][RTW89_KCC][14] = 26,
[0][1][RTW89_ACMA][14] = 16,
[0][1][RTW89_CN][14] = 4,
[0][1][RTW89_UK][14] = 16,
+ [0][1][RTW89_MEXICO][14] = 30,
+ [0][1][RTW89_UKRAINE][14] = 10,
+ [0][1][RTW89_CHILE][14] = 30,
+ [0][1][RTW89_QATAR][14] = 16,
[0][1][RTW89_FCC][15] = 32,
[0][1][RTW89_ETSI][15] = 18,
[0][1][RTW89_MKK][15] = 44,
@@ -35208,6 +47513,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][15] = 18,
[0][1][RTW89_CN][15] = 127,
[0][1][RTW89_UK][15] = 18,
+ [0][1][RTW89_MEXICO][15] = 32,
+ [0][1][RTW89_UKRAINE][15] = 10,
+ [0][1][RTW89_CHILE][15] = 32,
+ [0][1][RTW89_QATAR][15] = 18,
[0][1][RTW89_FCC][17] = 32,
[0][1][RTW89_ETSI][17] = 18,
[0][1][RTW89_MKK][17] = 44,
@@ -35216,6 +47525,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][17] = 18,
[0][1][RTW89_CN][17] = 127,
[0][1][RTW89_UK][17] = 18,
+ [0][1][RTW89_MEXICO][17] = 32,
+ [0][1][RTW89_UKRAINE][17] = 10,
+ [0][1][RTW89_CHILE][17] = 32,
+ [0][1][RTW89_QATAR][17] = 18,
[0][1][RTW89_FCC][19] = 32,
[0][1][RTW89_ETSI][19] = 18,
[0][1][RTW89_MKK][19] = 44,
@@ -35224,6 +47537,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][19] = 18,
[0][1][RTW89_CN][19] = 127,
[0][1][RTW89_UK][19] = 18,
+ [0][1][RTW89_MEXICO][19] = 32,
+ [0][1][RTW89_UKRAINE][19] = 10,
+ [0][1][RTW89_CHILE][19] = 32,
+ [0][1][RTW89_QATAR][19] = 18,
[0][1][RTW89_FCC][21] = 32,
[0][1][RTW89_ETSI][21] = 18,
[0][1][RTW89_MKK][21] = 44,
@@ -35232,6 +47549,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][21] = 18,
[0][1][RTW89_CN][21] = 127,
[0][1][RTW89_UK][21] = 18,
+ [0][1][RTW89_MEXICO][21] = 32,
+ [0][1][RTW89_UKRAINE][21] = 10,
+ [0][1][RTW89_CHILE][21] = 32,
+ [0][1][RTW89_QATAR][21] = 18,
[0][1][RTW89_FCC][23] = 32,
[0][1][RTW89_ETSI][23] = 18,
[0][1][RTW89_MKK][23] = 44,
@@ -35240,6 +47561,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][23] = 18,
[0][1][RTW89_CN][23] = 127,
[0][1][RTW89_UK][23] = 18,
+ [0][1][RTW89_MEXICO][23] = 32,
+ [0][1][RTW89_UKRAINE][23] = 10,
+ [0][1][RTW89_CHILE][23] = 32,
+ [0][1][RTW89_QATAR][23] = 18,
[0][1][RTW89_FCC][25] = 32,
[0][1][RTW89_ETSI][25] = 18,
[0][1][RTW89_MKK][25] = 44,
@@ -35248,6 +47573,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][25] = 127,
[0][1][RTW89_CN][25] = 127,
[0][1][RTW89_UK][25] = 18,
+ [0][1][RTW89_MEXICO][25] = 32,
+ [0][1][RTW89_UKRAINE][25] = 10,
+ [0][1][RTW89_CHILE][25] = 32,
+ [0][1][RTW89_QATAR][25] = 18,
[0][1][RTW89_FCC][27] = 32,
[0][1][RTW89_ETSI][27] = 16,
[0][1][RTW89_MKK][27] = 44,
@@ -35256,6 +47585,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][27] = 127,
[0][1][RTW89_CN][27] = 127,
[0][1][RTW89_UK][27] = 16,
+ [0][1][RTW89_MEXICO][27] = 32,
+ [0][1][RTW89_UKRAINE][27] = 10,
+ [0][1][RTW89_CHILE][27] = 32,
+ [0][1][RTW89_QATAR][27] = 16,
[0][1][RTW89_FCC][29] = 32,
[0][1][RTW89_ETSI][29] = 16,
[0][1][RTW89_MKK][29] = 44,
@@ -35264,6 +47597,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][29] = 127,
[0][1][RTW89_CN][29] = 127,
[0][1][RTW89_UK][29] = 16,
+ [0][1][RTW89_MEXICO][29] = 32,
+ [0][1][RTW89_UKRAINE][29] = 10,
+ [0][1][RTW89_CHILE][29] = 32,
+ [0][1][RTW89_QATAR][29] = 16,
[0][1][RTW89_FCC][31] = 32,
[0][1][RTW89_ETSI][31] = 16,
[0][1][RTW89_MKK][31] = 44,
@@ -35272,6 +47609,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][31] = 16,
[0][1][RTW89_CN][31] = 127,
[0][1][RTW89_UK][31] = 16,
+ [0][1][RTW89_MEXICO][31] = 32,
+ [0][1][RTW89_UKRAINE][31] = 10,
+ [0][1][RTW89_CHILE][31] = 32,
+ [0][1][RTW89_QATAR][31] = 16,
[0][1][RTW89_FCC][33] = 30,
[0][1][RTW89_ETSI][33] = 16,
[0][1][RTW89_MKK][33] = 44,
@@ -35280,6 +47621,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][33] = 16,
[0][1][RTW89_CN][33] = 127,
[0][1][RTW89_UK][33] = 16,
+ [0][1][RTW89_MEXICO][33] = 30,
+ [0][1][RTW89_UKRAINE][33] = 10,
+ [0][1][RTW89_CHILE][33] = 30,
+ [0][1][RTW89_QATAR][33] = 16,
[0][1][RTW89_FCC][35] = 30,
[0][1][RTW89_ETSI][35] = 16,
[0][1][RTW89_MKK][35] = 44,
@@ -35288,6 +47633,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][35] = 16,
[0][1][RTW89_CN][35] = 127,
[0][1][RTW89_UK][35] = 16,
+ [0][1][RTW89_MEXICO][35] = 30,
+ [0][1][RTW89_UKRAINE][35] = 10,
+ [0][1][RTW89_CHILE][35] = 30,
+ [0][1][RTW89_QATAR][35] = 16,
[0][1][RTW89_FCC][37] = 34,
[0][1][RTW89_ETSI][37] = 127,
[0][1][RTW89_MKK][37] = 44,
@@ -35296,46 +47645,70 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][37] = 34,
[0][1][RTW89_CN][37] = 127,
[0][1][RTW89_UK][37] = 18,
+ [0][1][RTW89_MEXICO][37] = 34,
+ [0][1][RTW89_UKRAINE][37] = 127,
+ [0][1][RTW89_CHILE][37] = 34,
+ [0][1][RTW89_QATAR][37] = 127,
[0][1][RTW89_FCC][38] = 62,
[0][1][RTW89_ETSI][38] = 16,
[0][1][RTW89_MKK][38] = 127,
[0][1][RTW89_IC][38] = 62,
- [0][1][RTW89_KCC][38] = 28,
+ [0][1][RTW89_KCC][38] = 30,
[0][1][RTW89_ACMA][38] = 62,
[0][1][RTW89_CN][38] = 42,
[0][1][RTW89_UK][38] = 18,
+ [0][1][RTW89_MEXICO][38] = 62,
+ [0][1][RTW89_UKRAINE][38] = 14,
+ [0][1][RTW89_CHILE][38] = 62,
+ [0][1][RTW89_QATAR][38] = 14,
[0][1][RTW89_FCC][40] = 62,
[0][1][RTW89_ETSI][40] = 16,
[0][1][RTW89_MKK][40] = 127,
[0][1][RTW89_IC][40] = 62,
- [0][1][RTW89_KCC][40] = 28,
+ [0][1][RTW89_KCC][40] = 30,
[0][1][RTW89_ACMA][40] = 62,
[0][1][RTW89_CN][40] = 42,
[0][1][RTW89_UK][40] = 18,
+ [0][1][RTW89_MEXICO][40] = 62,
+ [0][1][RTW89_UKRAINE][40] = 14,
+ [0][1][RTW89_CHILE][40] = 62,
+ [0][1][RTW89_QATAR][40] = 14,
[0][1][RTW89_FCC][42] = 58,
[0][1][RTW89_ETSI][42] = 16,
[0][1][RTW89_MKK][42] = 127,
[0][1][RTW89_IC][42] = 58,
- [0][1][RTW89_KCC][42] = 28,
+ [0][1][RTW89_KCC][42] = 30,
[0][1][RTW89_ACMA][42] = 58,
[0][1][RTW89_CN][42] = 42,
[0][1][RTW89_UK][42] = 18,
+ [0][1][RTW89_MEXICO][42] = 58,
+ [0][1][RTW89_UKRAINE][42] = 14,
+ [0][1][RTW89_CHILE][42] = 58,
+ [0][1][RTW89_QATAR][42] = 14,
[0][1][RTW89_FCC][44] = 56,
[0][1][RTW89_ETSI][44] = 16,
[0][1][RTW89_MKK][44] = 127,
[0][1][RTW89_IC][44] = 56,
- [0][1][RTW89_KCC][44] = 28,
+ [0][1][RTW89_KCC][44] = 30,
[0][1][RTW89_ACMA][44] = 56,
[0][1][RTW89_CN][44] = 42,
[0][1][RTW89_UK][44] = 18,
+ [0][1][RTW89_MEXICO][44] = 56,
+ [0][1][RTW89_UKRAINE][44] = 14,
+ [0][1][RTW89_CHILE][44] = 56,
+ [0][1][RTW89_QATAR][44] = 14,
[0][1][RTW89_FCC][46] = 56,
[0][1][RTW89_ETSI][46] = 16,
[0][1][RTW89_MKK][46] = 127,
[0][1][RTW89_IC][46] = 56,
- [0][1][RTW89_KCC][46] = 28,
+ [0][1][RTW89_KCC][46] = 30,
[0][1][RTW89_ACMA][46] = 56,
[0][1][RTW89_CN][46] = 42,
[0][1][RTW89_UK][46] = 18,
+ [0][1][RTW89_MEXICO][46] = 56,
+ [0][1][RTW89_UKRAINE][46] = 14,
+ [0][1][RTW89_CHILE][46] = 56,
+ [0][1][RTW89_QATAR][46] = 14,
[0][1][RTW89_FCC][48] = 20,
[0][1][RTW89_ETSI][48] = 127,
[0][1][RTW89_MKK][48] = 127,
@@ -35344,6 +47717,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][48] = 127,
[0][1][RTW89_CN][48] = 127,
[0][1][RTW89_UK][48] = 127,
+ [0][1][RTW89_MEXICO][48] = 127,
+ [0][1][RTW89_UKRAINE][48] = 127,
+ [0][1][RTW89_CHILE][48] = 127,
+ [0][1][RTW89_QATAR][48] = 127,
[0][1][RTW89_FCC][50] = 20,
[0][1][RTW89_ETSI][50] = 127,
[0][1][RTW89_MKK][50] = 127,
@@ -35352,6 +47729,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][50] = 127,
[0][1][RTW89_CN][50] = 127,
[0][1][RTW89_UK][50] = 127,
+ [0][1][RTW89_MEXICO][50] = 127,
+ [0][1][RTW89_UKRAINE][50] = 127,
+ [0][1][RTW89_CHILE][50] = 127,
+ [0][1][RTW89_QATAR][50] = 127,
[0][1][RTW89_FCC][52] = 8,
[0][1][RTW89_ETSI][52] = 127,
[0][1][RTW89_MKK][52] = 127,
@@ -35360,70 +47741,106 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][52] = 127,
[0][1][RTW89_CN][52] = 127,
[0][1][RTW89_UK][52] = 127,
+ [0][1][RTW89_MEXICO][52] = 127,
+ [0][1][RTW89_UKRAINE][52] = 127,
+ [0][1][RTW89_CHILE][52] = 127,
+ [0][1][RTW89_QATAR][52] = 127,
[1][0][RTW89_FCC][0] = 62,
[1][0][RTW89_ETSI][0] = 40,
[1][0][RTW89_MKK][0] = 48,
[1][0][RTW89_IC][0] = 42,
- [1][0][RTW89_KCC][0] = 50,
+ [1][0][RTW89_KCC][0] = 54,
[1][0][RTW89_ACMA][0] = 40,
[1][0][RTW89_CN][0] = 26,
[1][0][RTW89_UK][0] = 40,
+ [1][0][RTW89_MEXICO][0] = 62,
+ [1][0][RTW89_UKRAINE][0] = 32,
+ [1][0][RTW89_CHILE][0] = 62,
+ [1][0][RTW89_QATAR][0] = 40,
[1][0][RTW89_FCC][2] = 62,
[1][0][RTW89_ETSI][2] = 40,
[1][0][RTW89_MKK][2] = 48,
[1][0][RTW89_IC][2] = 42,
- [1][0][RTW89_KCC][2] = 50,
+ [1][0][RTW89_KCC][2] = 54,
[1][0][RTW89_ACMA][2] = 40,
[1][0][RTW89_CN][2] = 26,
[1][0][RTW89_UK][2] = 40,
+ [1][0][RTW89_MEXICO][2] = 62,
+ [1][0][RTW89_UKRAINE][2] = 32,
+ [1][0][RTW89_CHILE][2] = 62,
+ [1][0][RTW89_QATAR][2] = 40,
[1][0][RTW89_FCC][4] = 64,
[1][0][RTW89_ETSI][4] = 40,
[1][0][RTW89_MKK][4] = 40,
[1][0][RTW89_IC][4] = 42,
- [1][0][RTW89_KCC][4] = 50,
+ [1][0][RTW89_KCC][4] = 54,
[1][0][RTW89_ACMA][4] = 40,
[1][0][RTW89_CN][4] = 26,
[1][0][RTW89_UK][4] = 40,
+ [1][0][RTW89_MEXICO][4] = 64,
+ [1][0][RTW89_UKRAINE][4] = 32,
+ [1][0][RTW89_CHILE][4] = 64,
+ [1][0][RTW89_QATAR][4] = 40,
[1][0][RTW89_FCC][6] = 64,
[1][0][RTW89_ETSI][6] = 40,
[1][0][RTW89_MKK][6] = 40,
[1][0][RTW89_IC][6] = 42,
- [1][0][RTW89_KCC][6] = 24,
+ [1][0][RTW89_KCC][6] = 32,
[1][0][RTW89_ACMA][6] = 40,
[1][0][RTW89_CN][6] = 26,
[1][0][RTW89_UK][6] = 40,
+ [1][0][RTW89_MEXICO][6] = 64,
+ [1][0][RTW89_UKRAINE][6] = 32,
+ [1][0][RTW89_CHILE][6] = 64,
+ [1][0][RTW89_QATAR][6] = 40,
[1][0][RTW89_FCC][8] = 62,
[1][0][RTW89_ETSI][8] = 40,
[1][0][RTW89_MKK][8] = 34,
[1][0][RTW89_IC][8] = 62,
- [1][0][RTW89_KCC][8] = 52,
+ [1][0][RTW89_KCC][8] = 50,
[1][0][RTW89_ACMA][8] = 40,
[1][0][RTW89_CN][8] = 26,
[1][0][RTW89_UK][8] = 40,
+ [1][0][RTW89_MEXICO][8] = 62,
+ [1][0][RTW89_UKRAINE][8] = 32,
+ [1][0][RTW89_CHILE][8] = 62,
+ [1][0][RTW89_QATAR][8] = 40,
[1][0][RTW89_FCC][10] = 62,
[1][0][RTW89_ETSI][10] = 40,
[1][0][RTW89_MKK][10] = 34,
[1][0][RTW89_IC][10] = 62,
- [1][0][RTW89_KCC][10] = 52,
+ [1][0][RTW89_KCC][10] = 50,
[1][0][RTW89_ACMA][10] = 40,
[1][0][RTW89_CN][10] = 26,
[1][0][RTW89_UK][10] = 40,
+ [1][0][RTW89_MEXICO][10] = 62,
+ [1][0][RTW89_UKRAINE][10] = 32,
+ [1][0][RTW89_CHILE][10] = 62,
+ [1][0][RTW89_QATAR][10] = 40,
[1][0][RTW89_FCC][12] = 62,
[1][0][RTW89_ETSI][12] = 40,
[1][0][RTW89_MKK][12] = 46,
[1][0][RTW89_IC][12] = 62,
- [1][0][RTW89_KCC][12] = 52,
+ [1][0][RTW89_KCC][12] = 50,
[1][0][RTW89_ACMA][12] = 40,
[1][0][RTW89_CN][12] = 26,
[1][0][RTW89_UK][12] = 40,
+ [1][0][RTW89_MEXICO][12] = 62,
+ [1][0][RTW89_UKRAINE][12] = 32,
+ [1][0][RTW89_CHILE][12] = 62,
+ [1][0][RTW89_QATAR][12] = 40,
[1][0][RTW89_FCC][14] = 62,
[1][0][RTW89_ETSI][14] = 40,
[1][0][RTW89_MKK][14] = 46,
[1][0][RTW89_IC][14] = 62,
- [1][0][RTW89_KCC][14] = 52,
+ [1][0][RTW89_KCC][14] = 50,
[1][0][RTW89_ACMA][14] = 40,
[1][0][RTW89_CN][14] = 26,
[1][0][RTW89_UK][14] = 40,
+ [1][0][RTW89_MEXICO][14] = 62,
+ [1][0][RTW89_UKRAINE][14] = 32,
+ [1][0][RTW89_CHILE][14] = 62,
+ [1][0][RTW89_QATAR][14] = 40,
[1][0][RTW89_FCC][15] = 62,
[1][0][RTW89_ETSI][15] = 40,
[1][0][RTW89_MKK][15] = 62,
@@ -35432,6 +47849,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][15] = 40,
[1][0][RTW89_CN][15] = 127,
[1][0][RTW89_UK][15] = 40,
+ [1][0][RTW89_MEXICO][15] = 62,
+ [1][0][RTW89_UKRAINE][15] = 32,
+ [1][0][RTW89_CHILE][15] = 62,
+ [1][0][RTW89_QATAR][15] = 40,
[1][0][RTW89_FCC][17] = 62,
[1][0][RTW89_ETSI][17] = 40,
[1][0][RTW89_MKK][17] = 68,
@@ -35440,6 +47861,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][17] = 40,
[1][0][RTW89_CN][17] = 127,
[1][0][RTW89_UK][17] = 40,
+ [1][0][RTW89_MEXICO][17] = 62,
+ [1][0][RTW89_UKRAINE][17] = 32,
+ [1][0][RTW89_CHILE][17] = 62,
+ [1][0][RTW89_QATAR][17] = 40,
[1][0][RTW89_FCC][19] = 64,
[1][0][RTW89_ETSI][19] = 40,
[1][0][RTW89_MKK][19] = 68,
@@ -35448,6 +47873,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][19] = 40,
[1][0][RTW89_CN][19] = 127,
[1][0][RTW89_UK][19] = 40,
+ [1][0][RTW89_MEXICO][19] = 64,
+ [1][0][RTW89_UKRAINE][19] = 32,
+ [1][0][RTW89_CHILE][19] = 64,
+ [1][0][RTW89_QATAR][19] = 40,
[1][0][RTW89_FCC][21] = 64,
[1][0][RTW89_ETSI][21] = 40,
[1][0][RTW89_MKK][21] = 68,
@@ -35456,6 +47885,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][21] = 40,
[1][0][RTW89_CN][21] = 127,
[1][0][RTW89_UK][21] = 40,
+ [1][0][RTW89_MEXICO][21] = 64,
+ [1][0][RTW89_UKRAINE][21] = 32,
+ [1][0][RTW89_CHILE][21] = 64,
+ [1][0][RTW89_QATAR][21] = 40,
[1][0][RTW89_FCC][23] = 64,
[1][0][RTW89_ETSI][23] = 40,
[1][0][RTW89_MKK][23] = 68,
@@ -35464,6 +47897,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][23] = 40,
[1][0][RTW89_CN][23] = 127,
[1][0][RTW89_UK][23] = 40,
+ [1][0][RTW89_MEXICO][23] = 64,
+ [1][0][RTW89_UKRAINE][23] = 32,
+ [1][0][RTW89_CHILE][23] = 64,
+ [1][0][RTW89_QATAR][23] = 40,
[1][0][RTW89_FCC][25] = 64,
[1][0][RTW89_ETSI][25] = 40,
[1][0][RTW89_MKK][25] = 68,
@@ -35472,6 +47909,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][25] = 127,
[1][0][RTW89_CN][25] = 127,
[1][0][RTW89_UK][25] = 40,
+ [1][0][RTW89_MEXICO][25] = 64,
+ [1][0][RTW89_UKRAINE][25] = 32,
+ [1][0][RTW89_CHILE][25] = 64,
+ [1][0][RTW89_QATAR][25] = 40,
[1][0][RTW89_FCC][27] = 64,
[1][0][RTW89_ETSI][27] = 42,
[1][0][RTW89_MKK][27] = 68,
@@ -35480,6 +47921,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][27] = 127,
[1][0][RTW89_CN][27] = 127,
[1][0][RTW89_UK][27] = 42,
+ [1][0][RTW89_MEXICO][27] = 64,
+ [1][0][RTW89_UKRAINE][27] = 32,
+ [1][0][RTW89_CHILE][27] = 64,
+ [1][0][RTW89_QATAR][27] = 42,
[1][0][RTW89_FCC][29] = 64,
[1][0][RTW89_ETSI][29] = 42,
[1][0][RTW89_MKK][29] = 68,
@@ -35488,38 +47933,58 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][29] = 127,
[1][0][RTW89_CN][29] = 127,
[1][0][RTW89_UK][29] = 42,
+ [1][0][RTW89_MEXICO][29] = 64,
+ [1][0][RTW89_UKRAINE][29] = 32,
+ [1][0][RTW89_CHILE][29] = 64,
+ [1][0][RTW89_QATAR][29] = 42,
[1][0][RTW89_FCC][31] = 64,
[1][0][RTW89_ETSI][31] = 42,
[1][0][RTW89_MKK][31] = 68,
[1][0][RTW89_IC][31] = 56,
- [1][0][RTW89_KCC][31] = 52,
+ [1][0][RTW89_KCC][31] = 50,
[1][0][RTW89_ACMA][31] = 42,
[1][0][RTW89_CN][31] = 127,
[1][0][RTW89_UK][31] = 42,
+ [1][0][RTW89_MEXICO][31] = 64,
+ [1][0][RTW89_UKRAINE][31] = 32,
+ [1][0][RTW89_CHILE][31] = 64,
+ [1][0][RTW89_QATAR][31] = 42,
[1][0][RTW89_FCC][33] = 56,
[1][0][RTW89_ETSI][33] = 42,
[1][0][RTW89_MKK][33] = 68,
[1][0][RTW89_IC][33] = 56,
- [1][0][RTW89_KCC][33] = 52,
+ [1][0][RTW89_KCC][33] = 50,
[1][0][RTW89_ACMA][33] = 42,
[1][0][RTW89_CN][33] = 127,
[1][0][RTW89_UK][33] = 42,
+ [1][0][RTW89_MEXICO][33] = 56,
+ [1][0][RTW89_UKRAINE][33] = 32,
+ [1][0][RTW89_CHILE][33] = 56,
+ [1][0][RTW89_QATAR][33] = 42,
[1][0][RTW89_FCC][35] = 56,
[1][0][RTW89_ETSI][35] = 42,
[1][0][RTW89_MKK][35] = 68,
[1][0][RTW89_IC][35] = 56,
- [1][0][RTW89_KCC][35] = 52,
+ [1][0][RTW89_KCC][35] = 50,
[1][0][RTW89_ACMA][35] = 42,
[1][0][RTW89_CN][35] = 127,
[1][0][RTW89_UK][35] = 42,
+ [1][0][RTW89_MEXICO][35] = 56,
+ [1][0][RTW89_UKRAINE][35] = 32,
+ [1][0][RTW89_CHILE][35] = 56,
+ [1][0][RTW89_QATAR][35] = 42,
[1][0][RTW89_FCC][37] = 66,
[1][0][RTW89_ETSI][37] = 127,
[1][0][RTW89_MKK][37] = 68,
[1][0][RTW89_IC][37] = 66,
- [1][0][RTW89_KCC][37] = 52,
+ [1][0][RTW89_KCC][37] = 50,
[1][0][RTW89_ACMA][37] = 66,
[1][0][RTW89_CN][37] = 127,
[1][0][RTW89_UK][37] = 42,
+ [1][0][RTW89_MEXICO][37] = 66,
+ [1][0][RTW89_UKRAINE][37] = 127,
+ [1][0][RTW89_CHILE][37] = 66,
+ [1][0][RTW89_QATAR][37] = 127,
[1][0][RTW89_FCC][38] = 76,
[1][0][RTW89_ETSI][38] = 28,
[1][0][RTW89_MKK][38] = 127,
@@ -35528,6 +47993,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][38] = 76,
[1][0][RTW89_CN][38] = 66,
[1][0][RTW89_UK][38] = 44,
+ [1][0][RTW89_MEXICO][38] = 76,
+ [1][0][RTW89_UKRAINE][38] = 26,
+ [1][0][RTW89_CHILE][38] = 76,
+ [1][0][RTW89_QATAR][38] = 26,
[1][0][RTW89_FCC][40] = 76,
[1][0][RTW89_ETSI][40] = 28,
[1][0][RTW89_MKK][40] = 127,
@@ -35536,6 +48005,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][40] = 76,
[1][0][RTW89_CN][40] = 66,
[1][0][RTW89_UK][40] = 44,
+ [1][0][RTW89_MEXICO][40] = 76,
+ [1][0][RTW89_UKRAINE][40] = 26,
+ [1][0][RTW89_CHILE][40] = 76,
+ [1][0][RTW89_QATAR][40] = 26,
[1][0][RTW89_FCC][42] = 68,
[1][0][RTW89_ETSI][42] = 28,
[1][0][RTW89_MKK][42] = 127,
@@ -35544,6 +48017,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][42] = 68,
[1][0][RTW89_CN][42] = 66,
[1][0][RTW89_UK][42] = 44,
+ [1][0][RTW89_MEXICO][42] = 68,
+ [1][0][RTW89_UKRAINE][42] = 26,
+ [1][0][RTW89_CHILE][42] = 68,
+ [1][0][RTW89_QATAR][42] = 26,
[1][0][RTW89_FCC][44] = 70,
[1][0][RTW89_ETSI][44] = 28,
[1][0][RTW89_MKK][44] = 127,
@@ -35552,6 +48029,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][44] = 70,
[1][0][RTW89_CN][44] = 66,
[1][0][RTW89_UK][44] = 42,
+ [1][0][RTW89_MEXICO][44] = 70,
+ [1][0][RTW89_UKRAINE][44] = 26,
+ [1][0][RTW89_CHILE][44] = 70,
+ [1][0][RTW89_QATAR][44] = 26,
[1][0][RTW89_FCC][46] = 70,
[1][0][RTW89_ETSI][46] = 28,
[1][0][RTW89_MKK][46] = 127,
@@ -35560,6 +48041,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][46] = 70,
[1][0][RTW89_CN][46] = 66,
[1][0][RTW89_UK][46] = 42,
+ [1][0][RTW89_MEXICO][46] = 70,
+ [1][0][RTW89_UKRAINE][46] = 26,
+ [1][0][RTW89_CHILE][46] = 70,
+ [1][0][RTW89_QATAR][46] = 26,
[1][0][RTW89_FCC][48] = 56,
[1][0][RTW89_ETSI][48] = 127,
[1][0][RTW89_MKK][48] = 127,
@@ -35568,6 +48053,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][48] = 127,
[1][0][RTW89_CN][48] = 127,
[1][0][RTW89_UK][48] = 127,
+ [1][0][RTW89_MEXICO][48] = 127,
+ [1][0][RTW89_UKRAINE][48] = 127,
+ [1][0][RTW89_CHILE][48] = 127,
+ [1][0][RTW89_QATAR][48] = 127,
[1][0][RTW89_FCC][50] = 58,
[1][0][RTW89_ETSI][50] = 127,
[1][0][RTW89_MKK][50] = 127,
@@ -35576,6 +48065,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][50] = 127,
[1][0][RTW89_CN][50] = 127,
[1][0][RTW89_UK][50] = 127,
+ [1][0][RTW89_MEXICO][50] = 127,
+ [1][0][RTW89_UKRAINE][50] = 127,
+ [1][0][RTW89_CHILE][50] = 127,
+ [1][0][RTW89_QATAR][50] = 127,
[1][0][RTW89_FCC][52] = 56,
[1][0][RTW89_ETSI][52] = 127,
[1][0][RTW89_MKK][52] = 127,
@@ -35584,54 +48077,82 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][52] = 127,
[1][0][RTW89_CN][52] = 127,
[1][0][RTW89_UK][52] = 127,
+ [1][0][RTW89_MEXICO][52] = 127,
+ [1][0][RTW89_UKRAINE][52] = 127,
+ [1][0][RTW89_CHILE][52] = 127,
+ [1][0][RTW89_QATAR][52] = 127,
[1][1][RTW89_FCC][0] = 44,
[1][1][RTW89_ETSI][0] = 30,
[1][1][RTW89_MKK][0] = 34,
[1][1][RTW89_IC][0] = 20,
- [1][1][RTW89_KCC][0] = 34,
+ [1][1][RTW89_KCC][0] = 40,
[1][1][RTW89_ACMA][0] = 30,
[1][1][RTW89_CN][0] = 14,
[1][1][RTW89_UK][0] = 30,
+ [1][1][RTW89_MEXICO][0] = 44,
+ [1][1][RTW89_UKRAINE][0] = 20,
+ [1][1][RTW89_CHILE][0] = 44,
+ [1][1][RTW89_QATAR][0] = 30,
[1][1][RTW89_FCC][2] = 44,
[1][1][RTW89_ETSI][2] = 30,
[1][1][RTW89_MKK][2] = 34,
[1][1][RTW89_IC][2] = 18,
- [1][1][RTW89_KCC][2] = 34,
+ [1][1][RTW89_KCC][2] = 40,
[1][1][RTW89_ACMA][2] = 30,
[1][1][RTW89_CN][2] = 14,
[1][1][RTW89_UK][2] = 30,
+ [1][1][RTW89_MEXICO][2] = 44,
+ [1][1][RTW89_UKRAINE][2] = 20,
+ [1][1][RTW89_CHILE][2] = 44,
+ [1][1][RTW89_QATAR][2] = 30,
[1][1][RTW89_FCC][4] = 46,
[1][1][RTW89_ETSI][4] = 30,
[1][1][RTW89_MKK][4] = 26,
[1][1][RTW89_IC][4] = 20,
- [1][1][RTW89_KCC][4] = 34,
+ [1][1][RTW89_KCC][4] = 40,
[1][1][RTW89_ACMA][4] = 30,
[1][1][RTW89_CN][4] = 14,
[1][1][RTW89_UK][4] = 30,
+ [1][1][RTW89_MEXICO][4] = 46,
+ [1][1][RTW89_UKRAINE][4] = 20,
+ [1][1][RTW89_CHILE][4] = 46,
+ [1][1][RTW89_QATAR][4] = 30,
[1][1][RTW89_FCC][6] = 46,
[1][1][RTW89_ETSI][6] = 30,
[1][1][RTW89_MKK][6] = 26,
[1][1][RTW89_IC][6] = 20,
- [1][1][RTW89_KCC][6] = 8,
+ [1][1][RTW89_KCC][6] = 18,
[1][1][RTW89_ACMA][6] = 30,
[1][1][RTW89_CN][6] = 14,
[1][1][RTW89_UK][6] = 30,
+ [1][1][RTW89_MEXICO][6] = 46,
+ [1][1][RTW89_UKRAINE][6] = 20,
+ [1][1][RTW89_CHILE][6] = 46,
+ [1][1][RTW89_QATAR][6] = 30,
[1][1][RTW89_FCC][8] = 44,
[1][1][RTW89_ETSI][8] = 30,
[1][1][RTW89_MKK][8] = 20,
[1][1][RTW89_IC][8] = 44,
- [1][1][RTW89_KCC][8] = 34,
+ [1][1][RTW89_KCC][8] = 38,
[1][1][RTW89_ACMA][8] = 30,
[1][1][RTW89_CN][8] = 14,
[1][1][RTW89_UK][8] = 30,
+ [1][1][RTW89_MEXICO][8] = 44,
+ [1][1][RTW89_UKRAINE][8] = 20,
+ [1][1][RTW89_CHILE][8] = 44,
+ [1][1][RTW89_QATAR][8] = 30,
[1][1][RTW89_FCC][10] = 44,
[1][1][RTW89_ETSI][10] = 30,
[1][1][RTW89_MKK][10] = 20,
[1][1][RTW89_IC][10] = 44,
- [1][1][RTW89_KCC][10] = 34,
+ [1][1][RTW89_KCC][10] = 38,
[1][1][RTW89_ACMA][10] = 30,
[1][1][RTW89_CN][10] = 14,
[1][1][RTW89_UK][10] = 30,
+ [1][1][RTW89_MEXICO][10] = 44,
+ [1][1][RTW89_UKRAINE][10] = 20,
+ [1][1][RTW89_CHILE][10] = 44,
+ [1][1][RTW89_QATAR][10] = 30,
[1][1][RTW89_FCC][12] = 44,
[1][1][RTW89_ETSI][12] = 30,
[1][1][RTW89_MKK][12] = 34,
@@ -35640,6 +48161,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][1][RTW89_ACMA][12] = 30,
[1][1][RTW89_CN][12] = 14,
[1][1][RTW89_UK][12] = 30,
+ [1][1][RTW89_MEXICO][12] = 44,
+ [1][1][RTW89_UKRAINE][12] = 20,
+ [1][1][RTW89_CHILE][12] = 44,
+ [1][1][RTW89_QATAR][12] = 30,
[1][1][RTW89_FCC][14] = 44,
[1][1][RTW89_ETSI][14] = 30,
[1][1][RTW89_MKK][14] = 34,
@@ -35648,142 +48173,214 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][1][RTW89_ACMA][14] = 30,
[1][1][RTW89_CN][14] = 14,
[1][1][RTW89_UK][14] = 30,
+ [1][1][RTW89_MEXICO][14] = 44,
+ [1][1][RTW89_UKRAINE][14] = 20,
+ [1][1][RTW89_CHILE][14] = 44,
+ [1][1][RTW89_QATAR][14] = 30,
[1][1][RTW89_FCC][15] = 44,
[1][1][RTW89_ETSI][15] = 28,
[1][1][RTW89_MKK][15] = 56,
[1][1][RTW89_IC][15] = 44,
- [1][1][RTW89_KCC][15] = 36,
+ [1][1][RTW89_KCC][15] = 38,
[1][1][RTW89_ACMA][15] = 28,
[1][1][RTW89_CN][15] = 127,
[1][1][RTW89_UK][15] = 28,
+ [1][1][RTW89_MEXICO][15] = 44,
+ [1][1][RTW89_UKRAINE][15] = 20,
+ [1][1][RTW89_CHILE][15] = 44,
+ [1][1][RTW89_QATAR][15] = 28,
[1][1][RTW89_FCC][17] = 44,
[1][1][RTW89_ETSI][17] = 28,
[1][1][RTW89_MKK][17] = 58,
[1][1][RTW89_IC][17] = 44,
- [1][1][RTW89_KCC][17] = 36,
+ [1][1][RTW89_KCC][17] = 38,
[1][1][RTW89_ACMA][17] = 28,
[1][1][RTW89_CN][17] = 127,
[1][1][RTW89_UK][17] = 28,
+ [1][1][RTW89_MEXICO][17] = 44,
+ [1][1][RTW89_UKRAINE][17] = 20,
+ [1][1][RTW89_CHILE][17] = 44,
+ [1][1][RTW89_QATAR][17] = 28,
[1][1][RTW89_FCC][19] = 44,
[1][1][RTW89_ETSI][19] = 28,
[1][1][RTW89_MKK][19] = 58,
[1][1][RTW89_IC][19] = 44,
- [1][1][RTW89_KCC][19] = 36,
+ [1][1][RTW89_KCC][19] = 38,
[1][1][RTW89_ACMA][19] = 28,
[1][1][RTW89_CN][19] = 127,
[1][1][RTW89_UK][19] = 28,
+ [1][1][RTW89_MEXICO][19] = 44,
+ [1][1][RTW89_UKRAINE][19] = 20,
+ [1][1][RTW89_CHILE][19] = 44,
+ [1][1][RTW89_QATAR][19] = 28,
[1][1][RTW89_FCC][21] = 44,
[1][1][RTW89_ETSI][21] = 28,
[1][1][RTW89_MKK][21] = 58,
[1][1][RTW89_IC][21] = 44,
- [1][1][RTW89_KCC][21] = 36,
+ [1][1][RTW89_KCC][21] = 38,
[1][1][RTW89_ACMA][21] = 28,
[1][1][RTW89_CN][21] = 127,
[1][1][RTW89_UK][21] = 28,
+ [1][1][RTW89_MEXICO][21] = 44,
+ [1][1][RTW89_UKRAINE][21] = 20,
+ [1][1][RTW89_CHILE][21] = 44,
+ [1][1][RTW89_QATAR][21] = 28,
[1][1][RTW89_FCC][23] = 44,
[1][1][RTW89_ETSI][23] = 28,
[1][1][RTW89_MKK][23] = 58,
[1][1][RTW89_IC][23] = 44,
- [1][1][RTW89_KCC][23] = 36,
+ [1][1][RTW89_KCC][23] = 38,
[1][1][RTW89_ACMA][23] = 28,
[1][1][RTW89_CN][23] = 127,
[1][1][RTW89_UK][23] = 28,
+ [1][1][RTW89_MEXICO][23] = 44,
+ [1][1][RTW89_UKRAINE][23] = 20,
+ [1][1][RTW89_CHILE][23] = 44,
+ [1][1][RTW89_QATAR][23] = 28,
[1][1][RTW89_FCC][25] = 44,
[1][1][RTW89_ETSI][25] = 28,
[1][1][RTW89_MKK][25] = 58,
[1][1][RTW89_IC][25] = 127,
- [1][1][RTW89_KCC][25] = 36,
+ [1][1][RTW89_KCC][25] = 38,
[1][1][RTW89_ACMA][25] = 127,
[1][1][RTW89_CN][25] = 127,
[1][1][RTW89_UK][25] = 28,
+ [1][1][RTW89_MEXICO][25] = 44,
+ [1][1][RTW89_UKRAINE][25] = 20,
+ [1][1][RTW89_CHILE][25] = 44,
+ [1][1][RTW89_QATAR][25] = 28,
[1][1][RTW89_FCC][27] = 44,
[1][1][RTW89_ETSI][27] = 30,
[1][1][RTW89_MKK][27] = 58,
[1][1][RTW89_IC][27] = 127,
- [1][1][RTW89_KCC][27] = 36,
+ [1][1][RTW89_KCC][27] = 38,
[1][1][RTW89_ACMA][27] = 127,
[1][1][RTW89_CN][27] = 127,
[1][1][RTW89_UK][27] = 30,
+ [1][1][RTW89_MEXICO][27] = 44,
+ [1][1][RTW89_UKRAINE][27] = 20,
+ [1][1][RTW89_CHILE][27] = 44,
+ [1][1][RTW89_QATAR][27] = 30,
[1][1][RTW89_FCC][29] = 44,
[1][1][RTW89_ETSI][29] = 30,
[1][1][RTW89_MKK][29] = 58,
[1][1][RTW89_IC][29] = 127,
- [1][1][RTW89_KCC][29] = 36,
+ [1][1][RTW89_KCC][29] = 38,
[1][1][RTW89_ACMA][29] = 127,
[1][1][RTW89_CN][29] = 127,
[1][1][RTW89_UK][29] = 30,
+ [1][1][RTW89_MEXICO][29] = 44,
+ [1][1][RTW89_UKRAINE][29] = 20,
+ [1][1][RTW89_CHILE][29] = 44,
+ [1][1][RTW89_QATAR][29] = 30,
[1][1][RTW89_FCC][31] = 44,
[1][1][RTW89_ETSI][31] = 30,
[1][1][RTW89_MKK][31] = 58,
[1][1][RTW89_IC][31] = 38,
- [1][1][RTW89_KCC][31] = 36,
+ [1][1][RTW89_KCC][31] = 40,
[1][1][RTW89_ACMA][31] = 30,
[1][1][RTW89_CN][31] = 127,
[1][1][RTW89_UK][31] = 30,
+ [1][1][RTW89_MEXICO][31] = 44,
+ [1][1][RTW89_UKRAINE][31] = 20,
+ [1][1][RTW89_CHILE][31] = 44,
+ [1][1][RTW89_QATAR][31] = 30,
[1][1][RTW89_FCC][33] = 38,
[1][1][RTW89_ETSI][33] = 30,
[1][1][RTW89_MKK][33] = 58,
[1][1][RTW89_IC][33] = 38,
- [1][1][RTW89_KCC][33] = 36,
+ [1][1][RTW89_KCC][33] = 40,
[1][1][RTW89_ACMA][33] = 30,
[1][1][RTW89_CN][33] = 127,
[1][1][RTW89_UK][33] = 30,
+ [1][1][RTW89_MEXICO][33] = 38,
+ [1][1][RTW89_UKRAINE][33] = 20,
+ [1][1][RTW89_CHILE][33] = 38,
+ [1][1][RTW89_QATAR][33] = 30,
[1][1][RTW89_FCC][35] = 38,
[1][1][RTW89_ETSI][35] = 30,
[1][1][RTW89_MKK][35] = 58,
[1][1][RTW89_IC][35] = 38,
- [1][1][RTW89_KCC][35] = 36,
+ [1][1][RTW89_KCC][35] = 40,
[1][1][RTW89_ACMA][35] = 30,
[1][1][RTW89_CN][35] = 127,
[1][1][RTW89_UK][35] = 30,
+ [1][1][RTW89_MEXICO][35] = 38,
+ [1][1][RTW89_UKRAINE][35] = 20,
+ [1][1][RTW89_CHILE][35] = 38,
+ [1][1][RTW89_QATAR][35] = 30,
[1][1][RTW89_FCC][37] = 46,
[1][1][RTW89_ETSI][37] = 127,
[1][1][RTW89_MKK][37] = 58,
[1][1][RTW89_IC][37] = 46,
- [1][1][RTW89_KCC][37] = 36,
+ [1][1][RTW89_KCC][37] = 40,
[1][1][RTW89_ACMA][37] = 46,
[1][1][RTW89_CN][37] = 127,
[1][1][RTW89_UK][37] = 32,
+ [1][1][RTW89_MEXICO][37] = 46,
+ [1][1][RTW89_UKRAINE][37] = 127,
+ [1][1][RTW89_CHILE][37] = 46,
+ [1][1][RTW89_QATAR][37] = 127,
[1][1][RTW89_FCC][38] = 74,
[1][1][RTW89_ETSI][38] = 16,
[1][1][RTW89_MKK][38] = 127,
[1][1][RTW89_IC][38] = 74,
- [1][1][RTW89_KCC][38] = 36,
+ [1][1][RTW89_KCC][38] = 38,
[1][1][RTW89_ACMA][38] = 74,
[1][1][RTW89_CN][38] = 54,
[1][1][RTW89_UK][38] = 30,
+ [1][1][RTW89_MEXICO][38] = 74,
+ [1][1][RTW89_UKRAINE][38] = 14,
+ [1][1][RTW89_CHILE][38] = 72,
+ [1][1][RTW89_QATAR][38] = 14,
[1][1][RTW89_FCC][40] = 74,
[1][1][RTW89_ETSI][40] = 16,
[1][1][RTW89_MKK][40] = 127,
[1][1][RTW89_IC][40] = 74,
- [1][1][RTW89_KCC][40] = 36,
+ [1][1][RTW89_KCC][40] = 38,
[1][1][RTW89_ACMA][40] = 74,
[1][1][RTW89_CN][40] = 54,
[1][1][RTW89_UK][40] = 30,
+ [1][1][RTW89_MEXICO][40] = 74,
+ [1][1][RTW89_UKRAINE][40] = 14,
+ [1][1][RTW89_CHILE][40] = 72,
+ [1][1][RTW89_QATAR][40] = 14,
[1][1][RTW89_FCC][42] = 74,
[1][1][RTW89_ETSI][42] = 16,
[1][1][RTW89_MKK][42] = 127,
[1][1][RTW89_IC][42] = 74,
- [1][1][RTW89_KCC][42] = 36,
+ [1][1][RTW89_KCC][42] = 38,
[1][1][RTW89_ACMA][42] = 74,
[1][1][RTW89_CN][42] = 54,
[1][1][RTW89_UK][42] = 30,
+ [1][1][RTW89_MEXICO][42] = 74,
+ [1][1][RTW89_UKRAINE][42] = 14,
+ [1][1][RTW89_CHILE][42] = 72,
+ [1][1][RTW89_QATAR][42] = 14,
[1][1][RTW89_FCC][44] = 74,
[1][1][RTW89_ETSI][44] = 16,
[1][1][RTW89_MKK][44] = 127,
[1][1][RTW89_IC][44] = 74,
- [1][1][RTW89_KCC][44] = 36,
+ [1][1][RTW89_KCC][44] = 38,
[1][1][RTW89_ACMA][44] = 74,
[1][1][RTW89_CN][44] = 54,
[1][1][RTW89_UK][44] = 30,
+ [1][1][RTW89_MEXICO][44] = 74,
+ [1][1][RTW89_UKRAINE][44] = 14,
+ [1][1][RTW89_CHILE][44] = 72,
+ [1][1][RTW89_QATAR][44] = 14,
[1][1][RTW89_FCC][46] = 74,
[1][1][RTW89_ETSI][46] = 16,
[1][1][RTW89_MKK][46] = 127,
[1][1][RTW89_IC][46] = 74,
- [1][1][RTW89_KCC][46] = 36,
+ [1][1][RTW89_KCC][46] = 38,
[1][1][RTW89_ACMA][46] = 74,
[1][1][RTW89_CN][46] = 54,
[1][1][RTW89_UK][46] = 30,
+ [1][1][RTW89_MEXICO][46] = 74,
+ [1][1][RTW89_UKRAINE][46] = 14,
+ [1][1][RTW89_CHILE][46] = 72,
+ [1][1][RTW89_QATAR][46] = 14,
[1][1][RTW89_FCC][48] = 34,
[1][1][RTW89_ETSI][48] = 127,
[1][1][RTW89_MKK][48] = 127,
@@ -35792,6 +48389,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][1][RTW89_ACMA][48] = 127,
[1][1][RTW89_CN][48] = 127,
[1][1][RTW89_UK][48] = 127,
+ [1][1][RTW89_MEXICO][48] = 127,
+ [1][1][RTW89_UKRAINE][48] = 127,
+ [1][1][RTW89_CHILE][48] = 127,
+ [1][1][RTW89_QATAR][48] = 127,
[1][1][RTW89_FCC][50] = 34,
[1][1][RTW89_ETSI][50] = 127,
[1][1][RTW89_MKK][50] = 127,
@@ -35800,6 +48401,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][1][RTW89_ACMA][50] = 127,
[1][1][RTW89_CN][50] = 127,
[1][1][RTW89_UK][50] = 127,
+ [1][1][RTW89_MEXICO][50] = 127,
+ [1][1][RTW89_UKRAINE][50] = 127,
+ [1][1][RTW89_CHILE][50] = 127,
+ [1][1][RTW89_QATAR][50] = 127,
[1][1][RTW89_FCC][52] = 30,
[1][1][RTW89_ETSI][52] = 127,
[1][1][RTW89_MKK][52] = 127,
@@ -35808,206 +48413,310 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][1][RTW89_ACMA][52] = 127,
[1][1][RTW89_CN][52] = 127,
[1][1][RTW89_UK][52] = 127,
+ [1][1][RTW89_MEXICO][52] = 127,
+ [1][1][RTW89_UKRAINE][52] = 127,
+ [1][1][RTW89_CHILE][52] = 127,
+ [1][1][RTW89_QATAR][52] = 127,
[2][0][RTW89_FCC][0] = 68,
[2][0][RTW89_ETSI][0] = 52,
[2][0][RTW89_MKK][0] = 60,
[2][0][RTW89_IC][0] = 52,
- [2][0][RTW89_KCC][0] = 64,
+ [2][0][RTW89_KCC][0] = 60,
[2][0][RTW89_ACMA][0] = 52,
[2][0][RTW89_CN][0] = 40,
[2][0][RTW89_UK][0] = 52,
+ [2][0][RTW89_MEXICO][0] = 62,
+ [2][0][RTW89_UKRAINE][0] = 46,
+ [2][0][RTW89_CHILE][0] = 68,
+ [2][0][RTW89_QATAR][0] = 52,
[2][0][RTW89_FCC][2] = 64,
[2][0][RTW89_ETSI][2] = 52,
[2][0][RTW89_MKK][2] = 60,
[2][0][RTW89_IC][2] = 50,
- [2][0][RTW89_KCC][2] = 64,
+ [2][0][RTW89_KCC][2] = 60,
[2][0][RTW89_ACMA][2] = 52,
[2][0][RTW89_CN][2] = 40,
[2][0][RTW89_UK][2] = 52,
+ [2][0][RTW89_MEXICO][2] = 62,
+ [2][0][RTW89_UKRAINE][2] = 46,
+ [2][0][RTW89_CHILE][2] = 64,
+ [2][0][RTW89_QATAR][2] = 52,
[2][0][RTW89_FCC][4] = 68,
[2][0][RTW89_ETSI][4] = 52,
[2][0][RTW89_MKK][4] = 50,
[2][0][RTW89_IC][4] = 50,
- [2][0][RTW89_KCC][4] = 64,
+ [2][0][RTW89_KCC][4] = 60,
[2][0][RTW89_ACMA][4] = 52,
[2][0][RTW89_CN][4] = 40,
[2][0][RTW89_UK][4] = 52,
+ [2][0][RTW89_MEXICO][4] = 62,
+ [2][0][RTW89_UKRAINE][4] = 46,
+ [2][0][RTW89_CHILE][4] = 68,
+ [2][0][RTW89_QATAR][4] = 52,
[2][0][RTW89_FCC][6] = 68,
[2][0][RTW89_ETSI][6] = 52,
[2][0][RTW89_MKK][6] = 50,
[2][0][RTW89_IC][6] = 50,
- [2][0][RTW89_KCC][6] = 36,
+ [2][0][RTW89_KCC][6] = 38,
[2][0][RTW89_ACMA][6] = 52,
[2][0][RTW89_CN][6] = 40,
[2][0][RTW89_UK][6] = 52,
+ [2][0][RTW89_MEXICO][6] = 62,
+ [2][0][RTW89_UKRAINE][6] = 46,
+ [2][0][RTW89_CHILE][6] = 68,
+ [2][0][RTW89_QATAR][6] = 52,
[2][0][RTW89_FCC][8] = 68,
[2][0][RTW89_ETSI][8] = 52,
[2][0][RTW89_MKK][8] = 44,
[2][0][RTW89_IC][8] = 64,
- [2][0][RTW89_KCC][8] = 62,
+ [2][0][RTW89_KCC][8] = 56,
[2][0][RTW89_ACMA][8] = 52,
[2][0][RTW89_CN][8] = 40,
[2][0][RTW89_UK][8] = 52,
+ [2][0][RTW89_MEXICO][8] = 68,
+ [2][0][RTW89_UKRAINE][8] = 46,
+ [2][0][RTW89_CHILE][8] = 68,
+ [2][0][RTW89_QATAR][8] = 52,
[2][0][RTW89_FCC][10] = 68,
[2][0][RTW89_ETSI][10] = 52,
[2][0][RTW89_MKK][10] = 44,
[2][0][RTW89_IC][10] = 64,
- [2][0][RTW89_KCC][10] = 62,
+ [2][0][RTW89_KCC][10] = 56,
[2][0][RTW89_ACMA][10] = 52,
[2][0][RTW89_CN][10] = 40,
[2][0][RTW89_UK][10] = 52,
+ [2][0][RTW89_MEXICO][10] = 68,
+ [2][0][RTW89_UKRAINE][10] = 46,
+ [2][0][RTW89_CHILE][10] = 68,
+ [2][0][RTW89_QATAR][10] = 52,
[2][0][RTW89_FCC][12] = 68,
[2][0][RTW89_ETSI][12] = 52,
[2][0][RTW89_MKK][12] = 58,
[2][0][RTW89_IC][12] = 64,
- [2][0][RTW89_KCC][12] = 62,
+ [2][0][RTW89_KCC][12] = 58,
[2][0][RTW89_ACMA][12] = 52,
[2][0][RTW89_CN][12] = 40,
[2][0][RTW89_UK][12] = 52,
+ [2][0][RTW89_MEXICO][12] = 68,
+ [2][0][RTW89_UKRAINE][12] = 46,
+ [2][0][RTW89_CHILE][12] = 68,
+ [2][0][RTW89_QATAR][12] = 52,
[2][0][RTW89_FCC][14] = 68,
[2][0][RTW89_ETSI][14] = 52,
[2][0][RTW89_MKK][14] = 58,
[2][0][RTW89_IC][14] = 64,
- [2][0][RTW89_KCC][14] = 62,
+ [2][0][RTW89_KCC][14] = 58,
[2][0][RTW89_ACMA][14] = 52,
[2][0][RTW89_CN][14] = 40,
[2][0][RTW89_UK][14] = 52,
+ [2][0][RTW89_MEXICO][14] = 68,
+ [2][0][RTW89_UKRAINE][14] = 46,
+ [2][0][RTW89_CHILE][14] = 68,
+ [2][0][RTW89_QATAR][14] = 52,
[2][0][RTW89_FCC][15] = 68,
[2][0][RTW89_ETSI][15] = 52,
[2][0][RTW89_MKK][15] = 68,
[2][0][RTW89_IC][15] = 68,
- [2][0][RTW89_KCC][15] = 62,
+ [2][0][RTW89_KCC][15] = 58,
[2][0][RTW89_ACMA][15] = 52,
[2][0][RTW89_CN][15] = 127,
[2][0][RTW89_UK][15] = 52,
+ [2][0][RTW89_MEXICO][15] = 68,
+ [2][0][RTW89_UKRAINE][15] = 46,
+ [2][0][RTW89_CHILE][15] = 68,
+ [2][0][RTW89_QATAR][15] = 52,
[2][0][RTW89_FCC][17] = 68,
[2][0][RTW89_ETSI][17] = 52,
[2][0][RTW89_MKK][17] = 74,
[2][0][RTW89_IC][17] = 68,
- [2][0][RTW89_KCC][17] = 62,
+ [2][0][RTW89_KCC][17] = 58,
[2][0][RTW89_ACMA][17] = 52,
[2][0][RTW89_CN][17] = 127,
[2][0][RTW89_UK][17] = 52,
+ [2][0][RTW89_MEXICO][17] = 68,
+ [2][0][RTW89_UKRAINE][17] = 46,
+ [2][0][RTW89_CHILE][17] = 68,
+ [2][0][RTW89_QATAR][17] = 52,
[2][0][RTW89_FCC][19] = 70,
[2][0][RTW89_ETSI][19] = 52,
[2][0][RTW89_MKK][19] = 74,
[2][0][RTW89_IC][19] = 70,
- [2][0][RTW89_KCC][19] = 62,
+ [2][0][RTW89_KCC][19] = 58,
[2][0][RTW89_ACMA][19] = 52,
[2][0][RTW89_CN][19] = 127,
[2][0][RTW89_UK][19] = 52,
+ [2][0][RTW89_MEXICO][19] = 70,
+ [2][0][RTW89_UKRAINE][19] = 46,
+ [2][0][RTW89_CHILE][19] = 70,
+ [2][0][RTW89_QATAR][19] = 52,
[2][0][RTW89_FCC][21] = 70,
[2][0][RTW89_ETSI][21] = 52,
[2][0][RTW89_MKK][21] = 74,
[2][0][RTW89_IC][21] = 70,
- [2][0][RTW89_KCC][21] = 62,
+ [2][0][RTW89_KCC][21] = 58,
[2][0][RTW89_ACMA][21] = 52,
[2][0][RTW89_CN][21] = 127,
[2][0][RTW89_UK][21] = 52,
+ [2][0][RTW89_MEXICO][21] = 70,
+ [2][0][RTW89_UKRAINE][21] = 46,
+ [2][0][RTW89_CHILE][21] = 70,
+ [2][0][RTW89_QATAR][21] = 52,
[2][0][RTW89_FCC][23] = 70,
[2][0][RTW89_ETSI][23] = 52,
[2][0][RTW89_MKK][23] = 74,
[2][0][RTW89_IC][23] = 70,
- [2][0][RTW89_KCC][23] = 62,
+ [2][0][RTW89_KCC][23] = 58,
[2][0][RTW89_ACMA][23] = 52,
[2][0][RTW89_CN][23] = 127,
[2][0][RTW89_UK][23] = 52,
+ [2][0][RTW89_MEXICO][23] = 70,
+ [2][0][RTW89_UKRAINE][23] = 46,
+ [2][0][RTW89_CHILE][23] = 70,
+ [2][0][RTW89_QATAR][23] = 52,
[2][0][RTW89_FCC][25] = 70,
[2][0][RTW89_ETSI][25] = 52,
[2][0][RTW89_MKK][25] = 74,
[2][0][RTW89_IC][25] = 127,
- [2][0][RTW89_KCC][25] = 62,
+ [2][0][RTW89_KCC][25] = 58,
[2][0][RTW89_ACMA][25] = 127,
[2][0][RTW89_CN][25] = 127,
[2][0][RTW89_UK][25] = 52,
+ [2][0][RTW89_MEXICO][25] = 70,
+ [2][0][RTW89_UKRAINE][25] = 46,
+ [2][0][RTW89_CHILE][25] = 70,
+ [2][0][RTW89_QATAR][25] = 52,
[2][0][RTW89_FCC][27] = 70,
[2][0][RTW89_ETSI][27] = 52,
[2][0][RTW89_MKK][27] = 74,
[2][0][RTW89_IC][27] = 127,
- [2][0][RTW89_KCC][27] = 62,
+ [2][0][RTW89_KCC][27] = 58,
[2][0][RTW89_ACMA][27] = 127,
[2][0][RTW89_CN][27] = 127,
[2][0][RTW89_UK][27] = 52,
+ [2][0][RTW89_MEXICO][27] = 70,
+ [2][0][RTW89_UKRAINE][27] = 46,
+ [2][0][RTW89_CHILE][27] = 70,
+ [2][0][RTW89_QATAR][27] = 52,
[2][0][RTW89_FCC][29] = 70,
[2][0][RTW89_ETSI][29] = 52,
[2][0][RTW89_MKK][29] = 74,
[2][0][RTW89_IC][29] = 127,
- [2][0][RTW89_KCC][29] = 62,
+ [2][0][RTW89_KCC][29] = 58,
[2][0][RTW89_ACMA][29] = 127,
[2][0][RTW89_CN][29] = 127,
[2][0][RTW89_UK][29] = 52,
+ [2][0][RTW89_MEXICO][29] = 70,
+ [2][0][RTW89_UKRAINE][29] = 46,
+ [2][0][RTW89_CHILE][29] = 70,
+ [2][0][RTW89_QATAR][29] = 52,
[2][0][RTW89_FCC][31] = 70,
[2][0][RTW89_ETSI][31] = 52,
[2][0][RTW89_MKK][31] = 74,
[2][0][RTW89_IC][31] = 62,
- [2][0][RTW89_KCC][31] = 62,
+ [2][0][RTW89_KCC][31] = 56,
[2][0][RTW89_ACMA][31] = 52,
[2][0][RTW89_CN][31] = 127,
[2][0][RTW89_UK][31] = 52,
+ [2][0][RTW89_MEXICO][31] = 70,
+ [2][0][RTW89_UKRAINE][31] = 46,
+ [2][0][RTW89_CHILE][31] = 70,
+ [2][0][RTW89_QATAR][31] = 52,
[2][0][RTW89_FCC][33] = 62,
[2][0][RTW89_ETSI][33] = 52,
[2][0][RTW89_MKK][33] = 74,
[2][0][RTW89_IC][33] = 62,
- [2][0][RTW89_KCC][33] = 62,
+ [2][0][RTW89_KCC][33] = 56,
[2][0][RTW89_ACMA][33] = 52,
[2][0][RTW89_CN][33] = 127,
[2][0][RTW89_UK][33] = 52,
+ [2][0][RTW89_MEXICO][33] = 62,
+ [2][0][RTW89_UKRAINE][33] = 46,
+ [2][0][RTW89_CHILE][33] = 62,
+ [2][0][RTW89_QATAR][33] = 52,
[2][0][RTW89_FCC][35] = 62,
[2][0][RTW89_ETSI][35] = 52,
[2][0][RTW89_MKK][35] = 74,
[2][0][RTW89_IC][35] = 62,
- [2][0][RTW89_KCC][35] = 62,
+ [2][0][RTW89_KCC][35] = 56,
[2][0][RTW89_ACMA][35] = 52,
[2][0][RTW89_CN][35] = 127,
[2][0][RTW89_UK][35] = 52,
+ [2][0][RTW89_MEXICO][35] = 62,
+ [2][0][RTW89_UKRAINE][35] = 46,
+ [2][0][RTW89_CHILE][35] = 62,
+ [2][0][RTW89_QATAR][35] = 52,
[2][0][RTW89_FCC][37] = 70,
[2][0][RTW89_ETSI][37] = 127,
[2][0][RTW89_MKK][37] = 74,
[2][0][RTW89_IC][37] = 70,
- [2][0][RTW89_KCC][37] = 62,
+ [2][0][RTW89_KCC][37] = 56,
[2][0][RTW89_ACMA][37] = 70,
[2][0][RTW89_CN][37] = 127,
[2][0][RTW89_UK][37] = 52,
+ [2][0][RTW89_MEXICO][37] = 70,
+ [2][0][RTW89_UKRAINE][37] = 127,
+ [2][0][RTW89_CHILE][37] = 70,
+ [2][0][RTW89_QATAR][37] = 127,
[2][0][RTW89_FCC][38] = 82,
[2][0][RTW89_ETSI][38] = 28,
[2][0][RTW89_MKK][38] = 127,
[2][0][RTW89_IC][38] = 82,
- [2][0][RTW89_KCC][38] = 64,
+ [2][0][RTW89_KCC][38] = 60,
[2][0][RTW89_ACMA][38] = 82,
[2][0][RTW89_CN][38] = 68,
[2][0][RTW89_UK][38] = 54,
+ [2][0][RTW89_MEXICO][38] = 82,
+ [2][0][RTW89_UKRAINE][38] = 26,
+ [2][0][RTW89_CHILE][38] = 82,
+ [2][0][RTW89_QATAR][38] = 26,
[2][0][RTW89_FCC][40] = 82,
[2][0][RTW89_ETSI][40] = 28,
[2][0][RTW89_MKK][40] = 127,
[2][0][RTW89_IC][40] = 82,
- [2][0][RTW89_KCC][40] = 64,
+ [2][0][RTW89_KCC][40] = 60,
[2][0][RTW89_ACMA][40] = 82,
[2][0][RTW89_CN][40] = 68,
[2][0][RTW89_UK][40] = 54,
+ [2][0][RTW89_MEXICO][40] = 82,
+ [2][0][RTW89_UKRAINE][40] = 26,
+ [2][0][RTW89_CHILE][40] = 82,
+ [2][0][RTW89_QATAR][40] = 26,
[2][0][RTW89_FCC][42] = 76,
[2][0][RTW89_ETSI][42] = 28,
[2][0][RTW89_MKK][42] = 127,
[2][0][RTW89_IC][42] = 76,
- [2][0][RTW89_KCC][42] = 64,
+ [2][0][RTW89_KCC][42] = 60,
[2][0][RTW89_ACMA][42] = 76,
[2][0][RTW89_CN][42] = 68,
[2][0][RTW89_UK][42] = 54,
+ [2][0][RTW89_MEXICO][42] = 76,
+ [2][0][RTW89_UKRAINE][42] = 26,
+ [2][0][RTW89_CHILE][42] = 76,
+ [2][0][RTW89_QATAR][42] = 26,
[2][0][RTW89_FCC][44] = 80,
[2][0][RTW89_ETSI][44] = 28,
[2][0][RTW89_MKK][44] = 127,
[2][0][RTW89_IC][44] = 80,
- [2][0][RTW89_KCC][44] = 64,
+ [2][0][RTW89_KCC][44] = 60,
[2][0][RTW89_ACMA][44] = 80,
[2][0][RTW89_CN][44] = 68,
[2][0][RTW89_UK][44] = 54,
+ [2][0][RTW89_MEXICO][44] = 80,
+ [2][0][RTW89_UKRAINE][44] = 26,
+ [2][0][RTW89_CHILE][44] = 80,
+ [2][0][RTW89_QATAR][44] = 26,
[2][0][RTW89_FCC][46] = 80,
[2][0][RTW89_ETSI][46] = 28,
[2][0][RTW89_MKK][46] = 127,
[2][0][RTW89_IC][46] = 80,
- [2][0][RTW89_KCC][46] = 64,
+ [2][0][RTW89_KCC][46] = 60,
[2][0][RTW89_ACMA][46] = 80,
[2][0][RTW89_CN][46] = 68,
[2][0][RTW89_UK][46] = 54,
+ [2][0][RTW89_MEXICO][46] = 80,
+ [2][0][RTW89_UKRAINE][46] = 26,
+ [2][0][RTW89_CHILE][46] = 80,
+ [2][0][RTW89_QATAR][46] = 26,
[2][0][RTW89_FCC][48] = 64,
[2][0][RTW89_ETSI][48] = 127,
[2][0][RTW89_MKK][48] = 127,
@@ -36016,6 +48725,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][0][RTW89_ACMA][48] = 127,
[2][0][RTW89_CN][48] = 127,
[2][0][RTW89_UK][48] = 127,
+ [2][0][RTW89_MEXICO][48] = 127,
+ [2][0][RTW89_UKRAINE][48] = 127,
+ [2][0][RTW89_CHILE][48] = 127,
+ [2][0][RTW89_QATAR][48] = 127,
[2][0][RTW89_FCC][50] = 64,
[2][0][RTW89_ETSI][50] = 127,
[2][0][RTW89_MKK][50] = 127,
@@ -36024,6 +48737,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][0][RTW89_ACMA][50] = 127,
[2][0][RTW89_CN][50] = 127,
[2][0][RTW89_UK][50] = 127,
+ [2][0][RTW89_MEXICO][50] = 127,
+ [2][0][RTW89_UKRAINE][50] = 127,
+ [2][0][RTW89_CHILE][50] = 127,
+ [2][0][RTW89_QATAR][50] = 127,
[2][0][RTW89_FCC][52] = 64,
[2][0][RTW89_ETSI][52] = 127,
[2][0][RTW89_MKK][52] = 127,
@@ -36032,206 +48749,310 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][0][RTW89_ACMA][52] = 127,
[2][0][RTW89_CN][52] = 127,
[2][0][RTW89_UK][52] = 127,
+ [2][0][RTW89_MEXICO][52] = 127,
+ [2][0][RTW89_UKRAINE][52] = 127,
+ [2][0][RTW89_CHILE][52] = 127,
+ [2][0][RTW89_QATAR][52] = 127,
[2][1][RTW89_FCC][0] = 50,
[2][1][RTW89_ETSI][0] = 40,
[2][1][RTW89_MKK][0] = 44,
[2][1][RTW89_IC][0] = 26,
- [2][1][RTW89_KCC][0] = 44,
+ [2][1][RTW89_KCC][0] = 52,
[2][1][RTW89_ACMA][0] = 40,
[2][1][RTW89_CN][0] = 28,
[2][1][RTW89_UK][0] = 40,
+ [2][1][RTW89_MEXICO][0] = 50,
+ [2][1][RTW89_UKRAINE][0] = 34,
+ [2][1][RTW89_CHILE][0] = 50,
+ [2][1][RTW89_QATAR][0] = 40,
[2][1][RTW89_FCC][2] = 50,
[2][1][RTW89_ETSI][2] = 40,
[2][1][RTW89_MKK][2] = 44,
[2][1][RTW89_IC][2] = 26,
- [2][1][RTW89_KCC][2] = 44,
+ [2][1][RTW89_KCC][2] = 52,
[2][1][RTW89_ACMA][2] = 40,
[2][1][RTW89_CN][2] = 28,
[2][1][RTW89_UK][2] = 40,
+ [2][1][RTW89_MEXICO][2] = 50,
+ [2][1][RTW89_UKRAINE][2] = 34,
+ [2][1][RTW89_CHILE][2] = 50,
+ [2][1][RTW89_QATAR][2] = 40,
[2][1][RTW89_FCC][4] = 50,
[2][1][RTW89_ETSI][4] = 40,
[2][1][RTW89_MKK][4] = 36,
[2][1][RTW89_IC][4] = 26,
- [2][1][RTW89_KCC][4] = 44,
+ [2][1][RTW89_KCC][4] = 52,
[2][1][RTW89_ACMA][4] = 40,
[2][1][RTW89_CN][4] = 28,
[2][1][RTW89_UK][4] = 40,
+ [2][1][RTW89_MEXICO][4] = 50,
+ [2][1][RTW89_UKRAINE][4] = 34,
+ [2][1][RTW89_CHILE][4] = 50,
+ [2][1][RTW89_QATAR][4] = 40,
[2][1][RTW89_FCC][6] = 50,
[2][1][RTW89_ETSI][6] = 40,
[2][1][RTW89_MKK][6] = 36,
[2][1][RTW89_IC][6] = 26,
- [2][1][RTW89_KCC][6] = 20,
+ [2][1][RTW89_KCC][6] = 30,
[2][1][RTW89_ACMA][6] = 40,
[2][1][RTW89_CN][6] = 28,
[2][1][RTW89_UK][6] = 40,
+ [2][1][RTW89_MEXICO][6] = 50,
+ [2][1][RTW89_UKRAINE][6] = 34,
+ [2][1][RTW89_CHILE][6] = 50,
+ [2][1][RTW89_QATAR][6] = 40,
[2][1][RTW89_FCC][8] = 50,
[2][1][RTW89_ETSI][8] = 40,
[2][1][RTW89_MKK][8] = 32,
[2][1][RTW89_IC][8] = 50,
- [2][1][RTW89_KCC][8] = 46,
+ [2][1][RTW89_KCC][8] = 50,
[2][1][RTW89_ACMA][8] = 40,
[2][1][RTW89_CN][8] = 28,
[2][1][RTW89_UK][8] = 40,
+ [2][1][RTW89_MEXICO][8] = 50,
+ [2][1][RTW89_UKRAINE][8] = 34,
+ [2][1][RTW89_CHILE][8] = 50,
+ [2][1][RTW89_QATAR][8] = 40,
[2][1][RTW89_FCC][10] = 50,
[2][1][RTW89_ETSI][10] = 40,
[2][1][RTW89_MKK][10] = 32,
[2][1][RTW89_IC][10] = 50,
- [2][1][RTW89_KCC][10] = 46,
+ [2][1][RTW89_KCC][10] = 50,
[2][1][RTW89_ACMA][10] = 40,
[2][1][RTW89_CN][10] = 28,
[2][1][RTW89_UK][10] = 40,
+ [2][1][RTW89_MEXICO][10] = 50,
+ [2][1][RTW89_UKRAINE][10] = 34,
+ [2][1][RTW89_CHILE][10] = 50,
+ [2][1][RTW89_QATAR][10] = 40,
[2][1][RTW89_FCC][12] = 48,
[2][1][RTW89_ETSI][12] = 40,
[2][1][RTW89_MKK][12] = 44,
[2][1][RTW89_IC][12] = 48,
- [2][1][RTW89_KCC][12] = 46,
+ [2][1][RTW89_KCC][12] = 48,
[2][1][RTW89_ACMA][12] = 40,
[2][1][RTW89_CN][12] = 28,
[2][1][RTW89_UK][12] = 40,
+ [2][1][RTW89_MEXICO][12] = 48,
+ [2][1][RTW89_UKRAINE][12] = 34,
+ [2][1][RTW89_CHILE][12] = 48,
+ [2][1][RTW89_QATAR][12] = 40,
[2][1][RTW89_FCC][14] = 48,
[2][1][RTW89_ETSI][14] = 40,
[2][1][RTW89_MKK][14] = 44,
[2][1][RTW89_IC][14] = 48,
- [2][1][RTW89_KCC][14] = 46,
+ [2][1][RTW89_KCC][14] = 48,
[2][1][RTW89_ACMA][14] = 40,
[2][1][RTW89_CN][14] = 28,
[2][1][RTW89_UK][14] = 40,
+ [2][1][RTW89_MEXICO][14] = 48,
+ [2][1][RTW89_UKRAINE][14] = 34,
+ [2][1][RTW89_CHILE][14] = 48,
+ [2][1][RTW89_QATAR][14] = 40,
[2][1][RTW89_FCC][15] = 50,
[2][1][RTW89_ETSI][15] = 40,
[2][1][RTW89_MKK][15] = 66,
[2][1][RTW89_IC][15] = 50,
- [2][1][RTW89_KCC][15] = 46,
+ [2][1][RTW89_KCC][15] = 48,
[2][1][RTW89_ACMA][15] = 40,
[2][1][RTW89_CN][15] = 127,
[2][1][RTW89_UK][15] = 40,
+ [2][1][RTW89_MEXICO][15] = 50,
+ [2][1][RTW89_UKRAINE][15] = 34,
+ [2][1][RTW89_CHILE][15] = 50,
+ [2][1][RTW89_QATAR][15] = 40,
[2][1][RTW89_FCC][17] = 50,
[2][1][RTW89_ETSI][17] = 40,
[2][1][RTW89_MKK][17] = 66,
[2][1][RTW89_IC][17] = 50,
- [2][1][RTW89_KCC][17] = 46,
+ [2][1][RTW89_KCC][17] = 48,
[2][1][RTW89_ACMA][17] = 40,
[2][1][RTW89_CN][17] = 127,
[2][1][RTW89_UK][17] = 40,
+ [2][1][RTW89_MEXICO][17] = 50,
+ [2][1][RTW89_UKRAINE][17] = 34,
+ [2][1][RTW89_CHILE][17] = 50,
+ [2][1][RTW89_QATAR][17] = 40,
[2][1][RTW89_FCC][19] = 50,
[2][1][RTW89_ETSI][19] = 40,
[2][1][RTW89_MKK][19] = 66,
[2][1][RTW89_IC][19] = 50,
- [2][1][RTW89_KCC][19] = 46,
+ [2][1][RTW89_KCC][19] = 48,
[2][1][RTW89_ACMA][19] = 40,
[2][1][RTW89_CN][19] = 127,
[2][1][RTW89_UK][19] = 40,
+ [2][1][RTW89_MEXICO][19] = 50,
+ [2][1][RTW89_UKRAINE][19] = 34,
+ [2][1][RTW89_CHILE][19] = 50,
+ [2][1][RTW89_QATAR][19] = 40,
[2][1][RTW89_FCC][21] = 50,
[2][1][RTW89_ETSI][21] = 40,
[2][1][RTW89_MKK][21] = 66,
[2][1][RTW89_IC][21] = 50,
- [2][1][RTW89_KCC][21] = 46,
+ [2][1][RTW89_KCC][21] = 48,
[2][1][RTW89_ACMA][21] = 40,
[2][1][RTW89_CN][21] = 127,
[2][1][RTW89_UK][21] = 40,
+ [2][1][RTW89_MEXICO][21] = 50,
+ [2][1][RTW89_UKRAINE][21] = 34,
+ [2][1][RTW89_CHILE][21] = 50,
+ [2][1][RTW89_QATAR][21] = 40,
[2][1][RTW89_FCC][23] = 50,
[2][1][RTW89_ETSI][23] = 40,
[2][1][RTW89_MKK][23] = 66,
[2][1][RTW89_IC][23] = 50,
- [2][1][RTW89_KCC][23] = 46,
+ [2][1][RTW89_KCC][23] = 48,
[2][1][RTW89_ACMA][23] = 40,
[2][1][RTW89_CN][23] = 127,
[2][1][RTW89_UK][23] = 40,
+ [2][1][RTW89_MEXICO][23] = 50,
+ [2][1][RTW89_UKRAINE][23] = 34,
+ [2][1][RTW89_CHILE][23] = 50,
+ [2][1][RTW89_QATAR][23] = 40,
[2][1][RTW89_FCC][25] = 50,
[2][1][RTW89_ETSI][25] = 40,
[2][1][RTW89_MKK][25] = 66,
[2][1][RTW89_IC][25] = 127,
- [2][1][RTW89_KCC][25] = 46,
+ [2][1][RTW89_KCC][25] = 48,
[2][1][RTW89_ACMA][25] = 127,
[2][1][RTW89_CN][25] = 127,
[2][1][RTW89_UK][25] = 40,
+ [2][1][RTW89_MEXICO][25] = 50,
+ [2][1][RTW89_UKRAINE][25] = 34,
+ [2][1][RTW89_CHILE][25] = 50,
+ [2][1][RTW89_QATAR][25] = 40,
[2][1][RTW89_FCC][27] = 50,
[2][1][RTW89_ETSI][27] = 40,
[2][1][RTW89_MKK][27] = 66,
[2][1][RTW89_IC][27] = 127,
- [2][1][RTW89_KCC][27] = 46,
+ [2][1][RTW89_KCC][27] = 48,
[2][1][RTW89_ACMA][27] = 127,
[2][1][RTW89_CN][27] = 127,
[2][1][RTW89_UK][27] = 40,
+ [2][1][RTW89_MEXICO][27] = 50,
+ [2][1][RTW89_UKRAINE][27] = 34,
+ [2][1][RTW89_CHILE][27] = 50,
+ [2][1][RTW89_QATAR][27] = 40,
[2][1][RTW89_FCC][29] = 50,
[2][1][RTW89_ETSI][29] = 40,
[2][1][RTW89_MKK][29] = 66,
[2][1][RTW89_IC][29] = 127,
- [2][1][RTW89_KCC][29] = 46,
+ [2][1][RTW89_KCC][29] = 48,
[2][1][RTW89_ACMA][29] = 127,
[2][1][RTW89_CN][29] = 127,
[2][1][RTW89_UK][29] = 40,
+ [2][1][RTW89_MEXICO][29] = 50,
+ [2][1][RTW89_UKRAINE][29] = 34,
+ [2][1][RTW89_CHILE][29] = 50,
+ [2][1][RTW89_QATAR][29] = 40,
[2][1][RTW89_FCC][31] = 50,
[2][1][RTW89_ETSI][31] = 40,
[2][1][RTW89_MKK][31] = 66,
[2][1][RTW89_IC][31] = 48,
- [2][1][RTW89_KCC][31] = 46,
+ [2][1][RTW89_KCC][31] = 48,
[2][1][RTW89_ACMA][31] = 40,
[2][1][RTW89_CN][31] = 127,
[2][1][RTW89_UK][31] = 40,
+ [2][1][RTW89_MEXICO][31] = 50,
+ [2][1][RTW89_UKRAINE][31] = 34,
+ [2][1][RTW89_CHILE][31] = 50,
+ [2][1][RTW89_QATAR][31] = 40,
[2][1][RTW89_FCC][33] = 48,
[2][1][RTW89_ETSI][33] = 40,
[2][1][RTW89_MKK][33] = 66,
[2][1][RTW89_IC][33] = 48,
- [2][1][RTW89_KCC][33] = 46,
+ [2][1][RTW89_KCC][33] = 48,
[2][1][RTW89_ACMA][33] = 40,
[2][1][RTW89_CN][33] = 127,
[2][1][RTW89_UK][33] = 40,
+ [2][1][RTW89_MEXICO][33] = 48,
+ [2][1][RTW89_UKRAINE][33] = 34,
+ [2][1][RTW89_CHILE][33] = 48,
+ [2][1][RTW89_QATAR][33] = 40,
[2][1][RTW89_FCC][35] = 48,
[2][1][RTW89_ETSI][35] = 40,
[2][1][RTW89_MKK][35] = 66,
[2][1][RTW89_IC][35] = 48,
- [2][1][RTW89_KCC][35] = 46,
+ [2][1][RTW89_KCC][35] = 48,
[2][1][RTW89_ACMA][35] = 40,
[2][1][RTW89_CN][35] = 127,
[2][1][RTW89_UK][35] = 40,
+ [2][1][RTW89_MEXICO][35] = 48,
+ [2][1][RTW89_UKRAINE][35] = 34,
+ [2][1][RTW89_CHILE][35] = 48,
+ [2][1][RTW89_QATAR][35] = 40,
[2][1][RTW89_FCC][37] = 52,
[2][1][RTW89_ETSI][37] = 127,
[2][1][RTW89_MKK][37] = 66,
[2][1][RTW89_IC][37] = 52,
- [2][1][RTW89_KCC][37] = 46,
+ [2][1][RTW89_KCC][37] = 48,
[2][1][RTW89_ACMA][37] = 52,
[2][1][RTW89_CN][37] = 127,
[2][1][RTW89_UK][37] = 42,
+ [2][1][RTW89_MEXICO][37] = 52,
+ [2][1][RTW89_UKRAINE][37] = 127,
+ [2][1][RTW89_CHILE][37] = 52,
+ [2][1][RTW89_QATAR][37] = 127,
[2][1][RTW89_FCC][38] = 78,
[2][1][RTW89_ETSI][38] = 16,
[2][1][RTW89_MKK][38] = 127,
[2][1][RTW89_IC][38] = 78,
- [2][1][RTW89_KCC][38] = 46,
+ [2][1][RTW89_KCC][38] = 50,
[2][1][RTW89_ACMA][38] = 78,
[2][1][RTW89_CN][38] = 56,
[2][1][RTW89_UK][38] = 42,
+ [2][1][RTW89_MEXICO][38] = 78,
+ [2][1][RTW89_UKRAINE][38] = 14,
+ [2][1][RTW89_CHILE][38] = 72,
+ [2][1][RTW89_QATAR][38] = 14,
[2][1][RTW89_FCC][40] = 78,
[2][1][RTW89_ETSI][40] = 16,
[2][1][RTW89_MKK][40] = 127,
[2][1][RTW89_IC][40] = 78,
- [2][1][RTW89_KCC][40] = 46,
+ [2][1][RTW89_KCC][40] = 50,
[2][1][RTW89_ACMA][40] = 78,
[2][1][RTW89_CN][40] = 56,
[2][1][RTW89_UK][40] = 42,
+ [2][1][RTW89_MEXICO][40] = 78,
+ [2][1][RTW89_UKRAINE][40] = 14,
+ [2][1][RTW89_CHILE][40] = 72,
+ [2][1][RTW89_QATAR][40] = 14,
[2][1][RTW89_FCC][42] = 78,
[2][1][RTW89_ETSI][42] = 16,
[2][1][RTW89_MKK][42] = 127,
[2][1][RTW89_IC][42] = 78,
- [2][1][RTW89_KCC][42] = 46,
+ [2][1][RTW89_KCC][42] = 50,
[2][1][RTW89_ACMA][42] = 78,
[2][1][RTW89_CN][42] = 56,
[2][1][RTW89_UK][42] = 42,
+ [2][1][RTW89_MEXICO][42] = 78,
+ [2][1][RTW89_UKRAINE][42] = 14,
+ [2][1][RTW89_CHILE][42] = 72,
+ [2][1][RTW89_QATAR][42] = 14,
[2][1][RTW89_FCC][44] = 74,
[2][1][RTW89_ETSI][44] = 16,
[2][1][RTW89_MKK][44] = 127,
[2][1][RTW89_IC][44] = 74,
- [2][1][RTW89_KCC][44] = 46,
+ [2][1][RTW89_KCC][44] = 50,
[2][1][RTW89_ACMA][44] = 74,
[2][1][RTW89_CN][44] = 56,
[2][1][RTW89_UK][44] = 42,
+ [2][1][RTW89_MEXICO][44] = 74,
+ [2][1][RTW89_UKRAINE][44] = 14,
+ [2][1][RTW89_CHILE][44] = 72,
+ [2][1][RTW89_QATAR][44] = 14,
[2][1][RTW89_FCC][46] = 74,
[2][1][RTW89_ETSI][46] = 16,
[2][1][RTW89_MKK][46] = 127,
[2][1][RTW89_IC][46] = 74,
- [2][1][RTW89_KCC][46] = 46,
+ [2][1][RTW89_KCC][46] = 50,
[2][1][RTW89_ACMA][46] = 74,
[2][1][RTW89_CN][46] = 56,
[2][1][RTW89_UK][46] = 42,
+ [2][1][RTW89_MEXICO][46] = 74,
+ [2][1][RTW89_UKRAINE][46] = 14,
+ [2][1][RTW89_CHILE][46] = 72,
+ [2][1][RTW89_QATAR][46] = 14,
[2][1][RTW89_FCC][48] = 40,
[2][1][RTW89_ETSI][48] = 127,
[2][1][RTW89_MKK][48] = 127,
@@ -36240,6 +49061,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][1][RTW89_ACMA][48] = 127,
[2][1][RTW89_CN][48] = 127,
[2][1][RTW89_UK][48] = 127,
+ [2][1][RTW89_MEXICO][48] = 127,
+ [2][1][RTW89_UKRAINE][48] = 127,
+ [2][1][RTW89_CHILE][48] = 127,
+ [2][1][RTW89_QATAR][48] = 127,
[2][1][RTW89_FCC][50] = 40,
[2][1][RTW89_ETSI][50] = 127,
[2][1][RTW89_MKK][50] = 127,
@@ -36248,6 +49073,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][1][RTW89_ACMA][50] = 127,
[2][1][RTW89_CN][50] = 127,
[2][1][RTW89_UK][50] = 127,
+ [2][1][RTW89_MEXICO][50] = 127,
+ [2][1][RTW89_UKRAINE][50] = 127,
+ [2][1][RTW89_CHILE][50] = 127,
+ [2][1][RTW89_QATAR][50] = 127,
[2][1][RTW89_FCC][52] = 40,
[2][1][RTW89_ETSI][52] = 127,
[2][1][RTW89_MKK][52] = 127,
@@ -36256,1163 +49085,7312 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][1][RTW89_ACMA][52] = 127,
[2][1][RTW89_CN][52] = 127,
[2][1][RTW89_UK][52] = 127,
+ [2][1][RTW89_MEXICO][52] = 127,
+ [2][1][RTW89_UKRAINE][52] = 127,
+ [2][1][RTW89_CHILE][52] = 127,
+ [2][1][RTW89_QATAR][52] = 127,
};
static
const s8 rtw89_8852c_txpwr_lmt_ru_6g[RTW89_RU_NUM][RTW89_NTX_NUM]
- [RTW89_REGD_NUM][RTW89_6G_CH_NUM] = {
- [0][0][RTW89_WW][0] = -16,
- [0][0][RTW89_WW][2] = -18,
- [0][0][RTW89_WW][4] = -18,
- [0][0][RTW89_WW][6] = -18,
- [0][0][RTW89_WW][8] = -18,
- [0][0][RTW89_WW][10] = -18,
- [0][0][RTW89_WW][12] = -18,
- [0][0][RTW89_WW][14] = -18,
- [0][0][RTW89_WW][15] = -18,
- [0][0][RTW89_WW][17] = -18,
- [0][0][RTW89_WW][19] = -18,
- [0][0][RTW89_WW][21] = -18,
- [0][0][RTW89_WW][23] = -18,
- [0][0][RTW89_WW][25] = -18,
- [0][0][RTW89_WW][27] = -18,
- [0][0][RTW89_WW][29] = -18,
- [0][0][RTW89_WW][30] = -18,
- [0][0][RTW89_WW][32] = -18,
- [0][0][RTW89_WW][34] = -18,
- [0][0][RTW89_WW][36] = -18,
- [0][0][RTW89_WW][38] = -18,
- [0][0][RTW89_WW][40] = -18,
- [0][0][RTW89_WW][42] = -18,
- [0][0][RTW89_WW][44] = -16,
- [0][0][RTW89_WW][45] = -16,
- [0][0][RTW89_WW][47] = -18,
- [0][0][RTW89_WW][49] = -18,
- [0][0][RTW89_WW][51] = -18,
- [0][0][RTW89_WW][53] = -16,
- [0][0][RTW89_WW][55] = -18,
- [0][0][RTW89_WW][57] = -18,
- [0][0][RTW89_WW][59] = -18,
- [0][0][RTW89_WW][60] = -18,
- [0][0][RTW89_WW][62] = -18,
- [0][0][RTW89_WW][64] = -18,
- [0][0][RTW89_WW][66] = -18,
- [0][0][RTW89_WW][68] = -18,
- [0][0][RTW89_WW][70] = -16,
- [0][0][RTW89_WW][72] = -18,
- [0][0][RTW89_WW][74] = -18,
- [0][0][RTW89_WW][75] = -18,
- [0][0][RTW89_WW][77] = -18,
- [0][0][RTW89_WW][79] = -18,
- [0][0][RTW89_WW][81] = -18,
- [0][0][RTW89_WW][83] = -18,
- [0][0][RTW89_WW][85] = -18,
- [0][0][RTW89_WW][87] = -16,
- [0][0][RTW89_WW][89] = -16,
- [0][0][RTW89_WW][90] = -16,
- [0][0][RTW89_WW][92] = -16,
- [0][0][RTW89_WW][94] = -16,
- [0][0][RTW89_WW][96] = -16,
- [0][0][RTW89_WW][98] = -16,
- [0][0][RTW89_WW][100] = -16,
- [0][0][RTW89_WW][102] = -16,
- [0][0][RTW89_WW][104] = -16,
- [0][0][RTW89_WW][105] = -16,
- [0][0][RTW89_WW][107] = -12,
- [0][0][RTW89_WW][109] = -12,
- [0][0][RTW89_WW][111] = 0,
- [0][0][RTW89_WW][113] = 0,
- [0][0][RTW89_WW][115] = 0,
- [0][0][RTW89_WW][117] = 0,
- [0][0][RTW89_WW][119] = 0,
- [0][1][RTW89_WW][0] = -40,
- [0][1][RTW89_WW][2] = -40,
- [0][1][RTW89_WW][4] = -40,
- [0][1][RTW89_WW][6] = -40,
- [0][1][RTW89_WW][8] = -40,
- [0][1][RTW89_WW][10] = -40,
- [0][1][RTW89_WW][12] = -40,
- [0][1][RTW89_WW][14] = -40,
- [0][1][RTW89_WW][15] = -40,
- [0][1][RTW89_WW][17] = -40,
- [0][1][RTW89_WW][19] = -40,
- [0][1][RTW89_WW][21] = -40,
- [0][1][RTW89_WW][23] = -40,
- [0][1][RTW89_WW][25] = -40,
- [0][1][RTW89_WW][27] = -40,
- [0][1][RTW89_WW][29] = -40,
- [0][1][RTW89_WW][30] = -40,
- [0][1][RTW89_WW][32] = -40,
- [0][1][RTW89_WW][34] = -40,
- [0][1][RTW89_WW][36] = -40,
- [0][1][RTW89_WW][38] = -40,
- [0][1][RTW89_WW][40] = -40,
- [0][1][RTW89_WW][42] = -40,
- [0][1][RTW89_WW][44] = -40,
- [0][1][RTW89_WW][45] = -40,
- [0][1][RTW89_WW][47] = -40,
- [0][1][RTW89_WW][49] = -40,
- [0][1][RTW89_WW][51] = -40,
- [0][1][RTW89_WW][53] = -40,
- [0][1][RTW89_WW][55] = -40,
- [0][1][RTW89_WW][57] = -40,
- [0][1][RTW89_WW][59] = -40,
- [0][1][RTW89_WW][60] = -40,
- [0][1][RTW89_WW][62] = -40,
- [0][1][RTW89_WW][64] = -40,
- [0][1][RTW89_WW][66] = -40,
- [0][1][RTW89_WW][68] = -40,
- [0][1][RTW89_WW][70] = -38,
- [0][1][RTW89_WW][72] = -38,
- [0][1][RTW89_WW][74] = -38,
- [0][1][RTW89_WW][75] = -38,
- [0][1][RTW89_WW][77] = -38,
- [0][1][RTW89_WW][79] = -38,
- [0][1][RTW89_WW][81] = -38,
- [0][1][RTW89_WW][83] = -38,
- [0][1][RTW89_WW][85] = -38,
- [0][1][RTW89_WW][87] = -40,
- [0][1][RTW89_WW][89] = -38,
- [0][1][RTW89_WW][90] = -38,
- [0][1][RTW89_WW][92] = -38,
- [0][1][RTW89_WW][94] = -38,
- [0][1][RTW89_WW][96] = -38,
- [0][1][RTW89_WW][98] = -38,
- [0][1][RTW89_WW][100] = -38,
- [0][1][RTW89_WW][102] = -38,
- [0][1][RTW89_WW][104] = -38,
- [0][1][RTW89_WW][105] = -38,
- [0][1][RTW89_WW][107] = -34,
- [0][1][RTW89_WW][109] = -34,
- [0][1][RTW89_WW][111] = 0,
- [0][1][RTW89_WW][113] = 0,
- [0][1][RTW89_WW][115] = 0,
- [0][1][RTW89_WW][117] = 0,
- [0][1][RTW89_WW][119] = 0,
- [1][0][RTW89_WW][0] = -4,
- [1][0][RTW89_WW][2] = -4,
- [1][0][RTW89_WW][4] = -4,
- [1][0][RTW89_WW][6] = -4,
- [1][0][RTW89_WW][8] = -4,
- [1][0][RTW89_WW][10] = -4,
- [1][0][RTW89_WW][12] = -4,
- [1][0][RTW89_WW][14] = -4,
- [1][0][RTW89_WW][15] = -4,
- [1][0][RTW89_WW][17] = -4,
- [1][0][RTW89_WW][19] = -4,
- [1][0][RTW89_WW][21] = -4,
- [1][0][RTW89_WW][23] = -4,
- [1][0][RTW89_WW][25] = -4,
- [1][0][RTW89_WW][27] = -4,
- [1][0][RTW89_WW][29] = -4,
- [1][0][RTW89_WW][30] = -4,
- [1][0][RTW89_WW][32] = -4,
- [1][0][RTW89_WW][34] = -4,
- [1][0][RTW89_WW][36] = -4,
- [1][0][RTW89_WW][38] = -4,
- [1][0][RTW89_WW][40] = -4,
- [1][0][RTW89_WW][42] = -4,
- [1][0][RTW89_WW][44] = -4,
- [1][0][RTW89_WW][45] = -4,
- [1][0][RTW89_WW][47] = -4,
- [1][0][RTW89_WW][49] = -4,
- [1][0][RTW89_WW][51] = -4,
- [1][0][RTW89_WW][53] = -4,
- [1][0][RTW89_WW][55] = -4,
- [1][0][RTW89_WW][57] = -4,
- [1][0][RTW89_WW][59] = -4,
- [1][0][RTW89_WW][60] = -4,
- [1][0][RTW89_WW][62] = -4,
- [1][0][RTW89_WW][64] = -4,
- [1][0][RTW89_WW][66] = -4,
- [1][0][RTW89_WW][68] = -4,
- [1][0][RTW89_WW][70] = -4,
- [1][0][RTW89_WW][72] = -4,
- [1][0][RTW89_WW][74] = -4,
- [1][0][RTW89_WW][75] = -4,
- [1][0][RTW89_WW][77] = -4,
- [1][0][RTW89_WW][79] = -4,
- [1][0][RTW89_WW][81] = -4,
- [1][0][RTW89_WW][83] = -4,
- [1][0][RTW89_WW][85] = -4,
- [1][0][RTW89_WW][87] = -4,
- [1][0][RTW89_WW][89] = -4,
- [1][0][RTW89_WW][90] = -4,
- [1][0][RTW89_WW][92] = -4,
- [1][0][RTW89_WW][94] = -4,
- [1][0][RTW89_WW][96] = -4,
- [1][0][RTW89_WW][98] = -4,
- [1][0][RTW89_WW][100] = -4,
- [1][0][RTW89_WW][102] = -4,
- [1][0][RTW89_WW][104] = -4,
- [1][0][RTW89_WW][105] = -4,
- [1][0][RTW89_WW][107] = 1,
- [1][0][RTW89_WW][109] = 2,
- [1][0][RTW89_WW][111] = 0,
- [1][0][RTW89_WW][113] = 0,
- [1][0][RTW89_WW][115] = 0,
- [1][0][RTW89_WW][117] = 0,
- [1][0][RTW89_WW][119] = 0,
- [1][1][RTW89_WW][0] = -26,
- [1][1][RTW89_WW][2] = -28,
- [1][1][RTW89_WW][4] = -28,
- [1][1][RTW89_WW][6] = -28,
- [1][1][RTW89_WW][8] = -28,
- [1][1][RTW89_WW][10] = -28,
- [1][1][RTW89_WW][12] = -28,
- [1][1][RTW89_WW][14] = -28,
- [1][1][RTW89_WW][15] = -28,
- [1][1][RTW89_WW][17] = -28,
- [1][1][RTW89_WW][19] = -28,
- [1][1][RTW89_WW][21] = -28,
- [1][1][RTW89_WW][23] = -28,
- [1][1][RTW89_WW][25] = -28,
- [1][1][RTW89_WW][27] = -28,
- [1][1][RTW89_WW][29] = -28,
- [1][1][RTW89_WW][30] = -28,
- [1][1][RTW89_WW][32] = -28,
- [1][1][RTW89_WW][34] = -28,
- [1][1][RTW89_WW][36] = -28,
- [1][1][RTW89_WW][38] = -28,
- [1][1][RTW89_WW][40] = -28,
- [1][1][RTW89_WW][42] = -28,
- [1][1][RTW89_WW][44] = -28,
- [1][1][RTW89_WW][45] = -26,
- [1][1][RTW89_WW][47] = -28,
- [1][1][RTW89_WW][49] = -28,
- [1][1][RTW89_WW][51] = -28,
- [1][1][RTW89_WW][53] = -26,
- [1][1][RTW89_WW][55] = -28,
- [1][1][RTW89_WW][57] = -28,
- [1][1][RTW89_WW][59] = -28,
- [1][1][RTW89_WW][60] = -28,
- [1][1][RTW89_WW][62] = -28,
- [1][1][RTW89_WW][64] = -28,
- [1][1][RTW89_WW][66] = -28,
- [1][1][RTW89_WW][68] = -28,
- [1][1][RTW89_WW][70] = -26,
- [1][1][RTW89_WW][72] = -28,
- [1][1][RTW89_WW][74] = -28,
- [1][1][RTW89_WW][75] = -28,
- [1][1][RTW89_WW][77] = -28,
- [1][1][RTW89_WW][79] = -28,
- [1][1][RTW89_WW][81] = -28,
- [1][1][RTW89_WW][83] = -28,
- [1][1][RTW89_WW][85] = -28,
- [1][1][RTW89_WW][87] = -28,
- [1][1][RTW89_WW][89] = -26,
- [1][1][RTW89_WW][90] = -26,
- [1][1][RTW89_WW][92] = -26,
- [1][1][RTW89_WW][94] = -26,
- [1][1][RTW89_WW][96] = -26,
- [1][1][RTW89_WW][98] = -26,
- [1][1][RTW89_WW][100] = -26,
- [1][1][RTW89_WW][102] = -26,
- [1][1][RTW89_WW][104] = -26,
- [1][1][RTW89_WW][105] = -26,
- [1][1][RTW89_WW][107] = -22,
- [1][1][RTW89_WW][109] = -22,
- [1][1][RTW89_WW][111] = 0,
- [1][1][RTW89_WW][113] = 0,
- [1][1][RTW89_WW][115] = 0,
- [1][1][RTW89_WW][117] = 0,
- [1][1][RTW89_WW][119] = 0,
- [2][0][RTW89_WW][0] = 8,
- [2][0][RTW89_WW][2] = 8,
- [2][0][RTW89_WW][4] = 8,
- [2][0][RTW89_WW][6] = 8,
- [2][0][RTW89_WW][8] = 8,
- [2][0][RTW89_WW][10] = 8,
- [2][0][RTW89_WW][12] = 8,
- [2][0][RTW89_WW][14] = 8,
- [2][0][RTW89_WW][15] = 8,
- [2][0][RTW89_WW][17] = 8,
- [2][0][RTW89_WW][19] = 8,
- [2][0][RTW89_WW][21] = 8,
- [2][0][RTW89_WW][23] = 8,
- [2][0][RTW89_WW][25] = 8,
- [2][0][RTW89_WW][27] = 8,
- [2][0][RTW89_WW][29] = 8,
- [2][0][RTW89_WW][30] = 8,
- [2][0][RTW89_WW][32] = 8,
- [2][0][RTW89_WW][34] = 8,
- [2][0][RTW89_WW][36] = 8,
- [2][0][RTW89_WW][38] = 8,
- [2][0][RTW89_WW][40] = 8,
- [2][0][RTW89_WW][42] = 8,
- [2][0][RTW89_WW][44] = 8,
- [2][0][RTW89_WW][45] = 8,
- [2][0][RTW89_WW][47] = 8,
- [2][0][RTW89_WW][49] = 8,
- [2][0][RTW89_WW][51] = 8,
- [2][0][RTW89_WW][53] = 8,
- [2][0][RTW89_WW][55] = 8,
- [2][0][RTW89_WW][57] = 8,
- [2][0][RTW89_WW][59] = 8,
- [2][0][RTW89_WW][60] = 8,
- [2][0][RTW89_WW][62] = 8,
- [2][0][RTW89_WW][64] = 8,
- [2][0][RTW89_WW][66] = 8,
- [2][0][RTW89_WW][68] = 8,
- [2][0][RTW89_WW][70] = 8,
- [2][0][RTW89_WW][72] = 8,
- [2][0][RTW89_WW][74] = 8,
- [2][0][RTW89_WW][75] = 8,
- [2][0][RTW89_WW][77] = 8,
- [2][0][RTW89_WW][79] = 8,
- [2][0][RTW89_WW][81] = 8,
- [2][0][RTW89_WW][83] = 8,
- [2][0][RTW89_WW][85] = 8,
- [2][0][RTW89_WW][87] = 8,
- [2][0][RTW89_WW][89] = 8,
- [2][0][RTW89_WW][90] = 8,
- [2][0][RTW89_WW][92] = 8,
- [2][0][RTW89_WW][94] = 8,
- [2][0][RTW89_WW][96] = 8,
- [2][0][RTW89_WW][98] = 8,
- [2][0][RTW89_WW][100] = 8,
- [2][0][RTW89_WW][102] = 8,
- [2][0][RTW89_WW][104] = 8,
- [2][0][RTW89_WW][105] = 8,
- [2][0][RTW89_WW][107] = 10,
- [2][0][RTW89_WW][109] = 12,
- [2][0][RTW89_WW][111] = 0,
- [2][0][RTW89_WW][113] = 0,
- [2][0][RTW89_WW][115] = 0,
- [2][0][RTW89_WW][117] = 0,
- [2][0][RTW89_WW][119] = 0,
- [2][1][RTW89_WW][0] = -16,
- [2][1][RTW89_WW][2] = -16,
- [2][1][RTW89_WW][4] = -16,
- [2][1][RTW89_WW][6] = -16,
- [2][1][RTW89_WW][8] = -16,
- [2][1][RTW89_WW][10] = -16,
- [2][1][RTW89_WW][12] = -16,
- [2][1][RTW89_WW][14] = -16,
- [2][1][RTW89_WW][15] = -16,
- [2][1][RTW89_WW][17] = -16,
- [2][1][RTW89_WW][19] = -16,
- [2][1][RTW89_WW][21] = -16,
- [2][1][RTW89_WW][23] = -16,
- [2][1][RTW89_WW][25] = -16,
- [2][1][RTW89_WW][27] = -16,
- [2][1][RTW89_WW][29] = -16,
- [2][1][RTW89_WW][30] = -16,
- [2][1][RTW89_WW][32] = -16,
- [2][1][RTW89_WW][34] = -16,
- [2][1][RTW89_WW][36] = -16,
- [2][1][RTW89_WW][38] = -16,
- [2][1][RTW89_WW][40] = -16,
- [2][1][RTW89_WW][42] = -16,
- [2][1][RTW89_WW][44] = -16,
- [2][1][RTW89_WW][45] = -16,
- [2][1][RTW89_WW][47] = -16,
- [2][1][RTW89_WW][49] = -16,
- [2][1][RTW89_WW][51] = -16,
- [2][1][RTW89_WW][53] = -16,
- [2][1][RTW89_WW][55] = -16,
- [2][1][RTW89_WW][57] = -16,
- [2][1][RTW89_WW][59] = -16,
- [2][1][RTW89_WW][60] = -16,
- [2][1][RTW89_WW][62] = -16,
- [2][1][RTW89_WW][64] = -16,
- [2][1][RTW89_WW][66] = -16,
- [2][1][RTW89_WW][68] = -16,
- [2][1][RTW89_WW][70] = -16,
- [2][1][RTW89_WW][72] = -16,
- [2][1][RTW89_WW][74] = -16,
- [2][1][RTW89_WW][75] = -16,
- [2][1][RTW89_WW][77] = -16,
- [2][1][RTW89_WW][79] = -16,
- [2][1][RTW89_WW][81] = -16,
- [2][1][RTW89_WW][83] = -16,
- [2][1][RTW89_WW][85] = -18,
- [2][1][RTW89_WW][87] = -16,
- [2][1][RTW89_WW][89] = -16,
- [2][1][RTW89_WW][90] = -16,
- [2][1][RTW89_WW][92] = -16,
- [2][1][RTW89_WW][94] = -16,
- [2][1][RTW89_WW][96] = -16,
- [2][1][RTW89_WW][98] = -16,
- [2][1][RTW89_WW][100] = -16,
- [2][1][RTW89_WW][102] = -16,
- [2][1][RTW89_WW][104] = -16,
- [2][1][RTW89_WW][105] = -16,
- [2][1][RTW89_WW][107] = -12,
- [2][1][RTW89_WW][109] = -10,
- [2][1][RTW89_WW][111] = 0,
- [2][1][RTW89_WW][113] = 0,
- [2][1][RTW89_WW][115] = 0,
- [2][1][RTW89_WW][117] = 0,
- [2][1][RTW89_WW][119] = 0,
- [0][0][RTW89_FCC][0] = -16,
- [0][0][RTW89_ETSI][0] = 32,
- [0][0][RTW89_FCC][2] = -18,
- [0][0][RTW89_ETSI][2] = 32,
- [0][0][RTW89_FCC][4] = -18,
- [0][0][RTW89_ETSI][4] = 32,
- [0][0][RTW89_FCC][6] = -18,
- [0][0][RTW89_ETSI][6] = 32,
- [0][0][RTW89_FCC][8] = -18,
- [0][0][RTW89_ETSI][8] = 32,
- [0][0][RTW89_FCC][10] = -18,
- [0][0][RTW89_ETSI][10] = 32,
- [0][0][RTW89_FCC][12] = -18,
- [0][0][RTW89_ETSI][12] = 32,
- [0][0][RTW89_FCC][14] = -18,
- [0][0][RTW89_ETSI][14] = 32,
- [0][0][RTW89_FCC][15] = -18,
- [0][0][RTW89_ETSI][15] = 32,
- [0][0][RTW89_FCC][17] = -18,
- [0][0][RTW89_ETSI][17] = 32,
- [0][0][RTW89_FCC][19] = -18,
- [0][0][RTW89_ETSI][19] = 32,
- [0][0][RTW89_FCC][21] = -18,
- [0][0][RTW89_ETSI][21] = 32,
- [0][0][RTW89_FCC][23] = -18,
- [0][0][RTW89_ETSI][23] = 32,
- [0][0][RTW89_FCC][25] = -18,
- [0][0][RTW89_ETSI][25] = 32,
- [0][0][RTW89_FCC][27] = -18,
- [0][0][RTW89_ETSI][27] = 32,
- [0][0][RTW89_FCC][29] = -18,
- [0][0][RTW89_ETSI][29] = 32,
- [0][0][RTW89_FCC][30] = -18,
- [0][0][RTW89_ETSI][30] = 32,
- [0][0][RTW89_FCC][32] = -18,
- [0][0][RTW89_ETSI][32] = 32,
- [0][0][RTW89_FCC][34] = -18,
- [0][0][RTW89_ETSI][34] = 32,
- [0][0][RTW89_FCC][36] = -18,
- [0][0][RTW89_ETSI][36] = 32,
- [0][0][RTW89_FCC][38] = -18,
- [0][0][RTW89_ETSI][38] = 32,
- [0][0][RTW89_FCC][40] = -18,
- [0][0][RTW89_ETSI][40] = 32,
- [0][0][RTW89_FCC][42] = -18,
- [0][0][RTW89_ETSI][42] = 32,
- [0][0][RTW89_FCC][44] = -16,
- [0][0][RTW89_ETSI][44] = 32,
- [0][0][RTW89_FCC][45] = -16,
- [0][0][RTW89_ETSI][45] = 127,
- [0][0][RTW89_FCC][47] = -18,
- [0][0][RTW89_ETSI][47] = 127,
- [0][0][RTW89_FCC][49] = -18,
- [0][0][RTW89_ETSI][49] = 127,
- [0][0][RTW89_FCC][51] = -18,
- [0][0][RTW89_ETSI][51] = 127,
- [0][0][RTW89_FCC][53] = -16,
- [0][0][RTW89_ETSI][53] = 127,
- [0][0][RTW89_FCC][55] = -18,
- [0][0][RTW89_ETSI][55] = 127,
- [0][0][RTW89_FCC][57] = -18,
- [0][0][RTW89_ETSI][57] = 127,
- [0][0][RTW89_FCC][59] = -18,
- [0][0][RTW89_ETSI][59] = 127,
- [0][0][RTW89_FCC][60] = -18,
- [0][0][RTW89_ETSI][60] = 127,
- [0][0][RTW89_FCC][62] = -18,
- [0][0][RTW89_ETSI][62] = 127,
- [0][0][RTW89_FCC][64] = -18,
- [0][0][RTW89_ETSI][64] = 127,
- [0][0][RTW89_FCC][66] = -18,
- [0][0][RTW89_ETSI][66] = 127,
- [0][0][RTW89_FCC][68] = -18,
- [0][0][RTW89_ETSI][68] = 127,
- [0][0][RTW89_FCC][70] = -16,
- [0][0][RTW89_ETSI][70] = 127,
- [0][0][RTW89_FCC][72] = -18,
- [0][0][RTW89_ETSI][72] = 127,
- [0][0][RTW89_FCC][74] = -18,
- [0][0][RTW89_ETSI][74] = 127,
- [0][0][RTW89_FCC][75] = -18,
- [0][0][RTW89_ETSI][75] = 127,
- [0][0][RTW89_FCC][77] = -18,
- [0][0][RTW89_ETSI][77] = 127,
- [0][0][RTW89_FCC][79] = -18,
- [0][0][RTW89_ETSI][79] = 127,
- [0][0][RTW89_FCC][81] = -18,
- [0][0][RTW89_ETSI][81] = 127,
- [0][0][RTW89_FCC][83] = -18,
- [0][0][RTW89_ETSI][83] = 127,
- [0][0][RTW89_FCC][85] = -18,
- [0][0][RTW89_ETSI][85] = 127,
- [0][0][RTW89_FCC][87] = -16,
- [0][0][RTW89_ETSI][87] = 127,
- [0][0][RTW89_FCC][89] = -16,
- [0][0][RTW89_ETSI][89] = 127,
- [0][0][RTW89_FCC][90] = -16,
- [0][0][RTW89_ETSI][90] = 127,
- [0][0][RTW89_FCC][92] = -16,
- [0][0][RTW89_ETSI][92] = 127,
- [0][0][RTW89_FCC][94] = -16,
- [0][0][RTW89_ETSI][94] = 127,
- [0][0][RTW89_FCC][96] = -16,
- [0][0][RTW89_ETSI][96] = 127,
- [0][0][RTW89_FCC][98] = -16,
- [0][0][RTW89_ETSI][98] = 127,
- [0][0][RTW89_FCC][100] = -16,
- [0][0][RTW89_ETSI][100] = 127,
- [0][0][RTW89_FCC][102] = -16,
- [0][0][RTW89_ETSI][102] = 127,
- [0][0][RTW89_FCC][104] = -16,
- [0][0][RTW89_ETSI][104] = 127,
- [0][0][RTW89_FCC][105] = -16,
- [0][0][RTW89_ETSI][105] = 127,
- [0][0][RTW89_FCC][107] = -12,
- [0][0][RTW89_ETSI][107] = 127,
- [0][0][RTW89_FCC][109] = -12,
- [0][0][RTW89_ETSI][109] = 127,
- [0][0][RTW89_FCC][111] = 127,
- [0][0][RTW89_ETSI][111] = 127,
- [0][0][RTW89_FCC][113] = 127,
- [0][0][RTW89_ETSI][113] = 127,
- [0][0][RTW89_FCC][115] = 127,
- [0][0][RTW89_ETSI][115] = 127,
- [0][0][RTW89_FCC][117] = 127,
- [0][0][RTW89_ETSI][117] = 127,
- [0][0][RTW89_FCC][119] = 127,
- [0][0][RTW89_ETSI][119] = 127,
- [0][1][RTW89_FCC][0] = -40,
- [0][1][RTW89_ETSI][0] = 20,
- [0][1][RTW89_FCC][2] = -40,
- [0][1][RTW89_ETSI][2] = 20,
- [0][1][RTW89_FCC][4] = -40,
- [0][1][RTW89_ETSI][4] = 20,
- [0][1][RTW89_FCC][6] = -40,
- [0][1][RTW89_ETSI][6] = 20,
- [0][1][RTW89_FCC][8] = -40,
- [0][1][RTW89_ETSI][8] = 20,
- [0][1][RTW89_FCC][10] = -40,
- [0][1][RTW89_ETSI][10] = 20,
- [0][1][RTW89_FCC][12] = -40,
- [0][1][RTW89_ETSI][12] = 20,
- [0][1][RTW89_FCC][14] = -40,
- [0][1][RTW89_ETSI][14] = 20,
- [0][1][RTW89_FCC][15] = -40,
- [0][1][RTW89_ETSI][15] = 20,
- [0][1][RTW89_FCC][17] = -40,
- [0][1][RTW89_ETSI][17] = 20,
- [0][1][RTW89_FCC][19] = -40,
- [0][1][RTW89_ETSI][19] = 20,
- [0][1][RTW89_FCC][21] = -40,
- [0][1][RTW89_ETSI][21] = 20,
- [0][1][RTW89_FCC][23] = -40,
- [0][1][RTW89_ETSI][23] = 20,
- [0][1][RTW89_FCC][25] = -40,
- [0][1][RTW89_ETSI][25] = 20,
- [0][1][RTW89_FCC][27] = -40,
- [0][1][RTW89_ETSI][27] = 20,
- [0][1][RTW89_FCC][29] = -40,
- [0][1][RTW89_ETSI][29] = 20,
- [0][1][RTW89_FCC][30] = -40,
- [0][1][RTW89_ETSI][30] = 20,
- [0][1][RTW89_FCC][32] = -40,
- [0][1][RTW89_ETSI][32] = 20,
- [0][1][RTW89_FCC][34] = -40,
- [0][1][RTW89_ETSI][34] = 20,
- [0][1][RTW89_FCC][36] = -40,
- [0][1][RTW89_ETSI][36] = 20,
- [0][1][RTW89_FCC][38] = -40,
- [0][1][RTW89_ETSI][38] = 20,
- [0][1][RTW89_FCC][40] = -40,
- [0][1][RTW89_ETSI][40] = 20,
- [0][1][RTW89_FCC][42] = -40,
- [0][1][RTW89_ETSI][42] = 20,
- [0][1][RTW89_FCC][44] = -40,
- [0][1][RTW89_ETSI][44] = 20,
- [0][1][RTW89_FCC][45] = -40,
- [0][1][RTW89_ETSI][45] = 127,
- [0][1][RTW89_FCC][47] = -40,
- [0][1][RTW89_ETSI][47] = 127,
- [0][1][RTW89_FCC][49] = -40,
- [0][1][RTW89_ETSI][49] = 127,
- [0][1][RTW89_FCC][51] = -40,
- [0][1][RTW89_ETSI][51] = 127,
- [0][1][RTW89_FCC][53] = -40,
- [0][1][RTW89_ETSI][53] = 127,
- [0][1][RTW89_FCC][55] = -40,
- [0][1][RTW89_ETSI][55] = 127,
- [0][1][RTW89_FCC][57] = -40,
- [0][1][RTW89_ETSI][57] = 127,
- [0][1][RTW89_FCC][59] = -40,
- [0][1][RTW89_ETSI][59] = 127,
- [0][1][RTW89_FCC][60] = -40,
- [0][1][RTW89_ETSI][60] = 127,
- [0][1][RTW89_FCC][62] = -40,
- [0][1][RTW89_ETSI][62] = 127,
- [0][1][RTW89_FCC][64] = -40,
- [0][1][RTW89_ETSI][64] = 127,
- [0][1][RTW89_FCC][66] = -40,
- [0][1][RTW89_ETSI][66] = 127,
- [0][1][RTW89_FCC][68] = -40,
- [0][1][RTW89_ETSI][68] = 127,
- [0][1][RTW89_FCC][70] = -38,
- [0][1][RTW89_ETSI][70] = 127,
- [0][1][RTW89_FCC][72] = -38,
- [0][1][RTW89_ETSI][72] = 127,
- [0][1][RTW89_FCC][74] = -38,
- [0][1][RTW89_ETSI][74] = 127,
- [0][1][RTW89_FCC][75] = -38,
- [0][1][RTW89_ETSI][75] = 127,
- [0][1][RTW89_FCC][77] = -38,
- [0][1][RTW89_ETSI][77] = 127,
- [0][1][RTW89_FCC][79] = -38,
- [0][1][RTW89_ETSI][79] = 127,
- [0][1][RTW89_FCC][81] = -38,
- [0][1][RTW89_ETSI][81] = 127,
- [0][1][RTW89_FCC][83] = -38,
- [0][1][RTW89_ETSI][83] = 127,
- [0][1][RTW89_FCC][85] = -38,
- [0][1][RTW89_ETSI][85] = 127,
- [0][1][RTW89_FCC][87] = -40,
- [0][1][RTW89_ETSI][87] = 127,
- [0][1][RTW89_FCC][89] = -38,
- [0][1][RTW89_ETSI][89] = 127,
- [0][1][RTW89_FCC][90] = -38,
- [0][1][RTW89_ETSI][90] = 127,
- [0][1][RTW89_FCC][92] = -38,
- [0][1][RTW89_ETSI][92] = 127,
- [0][1][RTW89_FCC][94] = -38,
- [0][1][RTW89_ETSI][94] = 127,
- [0][1][RTW89_FCC][96] = -38,
- [0][1][RTW89_ETSI][96] = 127,
- [0][1][RTW89_FCC][98] = -38,
- [0][1][RTW89_ETSI][98] = 127,
- [0][1][RTW89_FCC][100] = -38,
- [0][1][RTW89_ETSI][100] = 127,
- [0][1][RTW89_FCC][102] = -38,
- [0][1][RTW89_ETSI][102] = 127,
- [0][1][RTW89_FCC][104] = -38,
- [0][1][RTW89_ETSI][104] = 127,
- [0][1][RTW89_FCC][105] = -38,
- [0][1][RTW89_ETSI][105] = 127,
- [0][1][RTW89_FCC][107] = -34,
- [0][1][RTW89_ETSI][107] = 127,
- [0][1][RTW89_FCC][109] = -34,
- [0][1][RTW89_ETSI][109] = 127,
- [0][1][RTW89_FCC][111] = 127,
- [0][1][RTW89_ETSI][111] = 127,
- [0][1][RTW89_FCC][113] = 127,
- [0][1][RTW89_ETSI][113] = 127,
- [0][1][RTW89_FCC][115] = 127,
- [0][1][RTW89_ETSI][115] = 127,
- [0][1][RTW89_FCC][117] = 127,
- [0][1][RTW89_ETSI][117] = 127,
- [0][1][RTW89_FCC][119] = 127,
- [0][1][RTW89_ETSI][119] = 127,
- [1][0][RTW89_FCC][0] = -4,
- [1][0][RTW89_ETSI][0] = 46,
- [1][0][RTW89_FCC][2] = -4,
- [1][0][RTW89_ETSI][2] = 46,
- [1][0][RTW89_FCC][4] = -4,
- [1][0][RTW89_ETSI][4] = 46,
- [1][0][RTW89_FCC][6] = -4,
- [1][0][RTW89_ETSI][6] = 46,
- [1][0][RTW89_FCC][8] = -4,
- [1][0][RTW89_ETSI][8] = 46,
- [1][0][RTW89_FCC][10] = -4,
- [1][0][RTW89_ETSI][10] = 46,
- [1][0][RTW89_FCC][12] = -4,
- [1][0][RTW89_ETSI][12] = 46,
- [1][0][RTW89_FCC][14] = -4,
- [1][0][RTW89_ETSI][14] = 46,
- [1][0][RTW89_FCC][15] = -4,
- [1][0][RTW89_ETSI][15] = 46,
- [1][0][RTW89_FCC][17] = -4,
- [1][0][RTW89_ETSI][17] = 46,
- [1][0][RTW89_FCC][19] = -4,
- [1][0][RTW89_ETSI][19] = 46,
- [1][0][RTW89_FCC][21] = -4,
- [1][0][RTW89_ETSI][21] = 46,
- [1][0][RTW89_FCC][23] = -4,
- [1][0][RTW89_ETSI][23] = 46,
- [1][0][RTW89_FCC][25] = -4,
- [1][0][RTW89_ETSI][25] = 46,
- [1][0][RTW89_FCC][27] = -4,
- [1][0][RTW89_ETSI][27] = 46,
- [1][0][RTW89_FCC][29] = -4,
- [1][0][RTW89_ETSI][29] = 46,
- [1][0][RTW89_FCC][30] = -4,
- [1][0][RTW89_ETSI][30] = 46,
- [1][0][RTW89_FCC][32] = -4,
- [1][0][RTW89_ETSI][32] = 46,
- [1][0][RTW89_FCC][34] = -4,
- [1][0][RTW89_ETSI][34] = 46,
- [1][0][RTW89_FCC][36] = -4,
- [1][0][RTW89_ETSI][36] = 46,
- [1][0][RTW89_FCC][38] = -4,
- [1][0][RTW89_ETSI][38] = 46,
- [1][0][RTW89_FCC][40] = -4,
- [1][0][RTW89_ETSI][40] = 46,
- [1][0][RTW89_FCC][42] = -4,
- [1][0][RTW89_ETSI][42] = 46,
- [1][0][RTW89_FCC][44] = -4,
- [1][0][RTW89_ETSI][44] = 46,
- [1][0][RTW89_FCC][45] = -4,
- [1][0][RTW89_ETSI][45] = 127,
- [1][0][RTW89_FCC][47] = -4,
- [1][0][RTW89_ETSI][47] = 127,
- [1][0][RTW89_FCC][49] = -4,
- [1][0][RTW89_ETSI][49] = 127,
- [1][0][RTW89_FCC][51] = -4,
- [1][0][RTW89_ETSI][51] = 127,
- [1][0][RTW89_FCC][53] = -4,
- [1][0][RTW89_ETSI][53] = 127,
- [1][0][RTW89_FCC][55] = -4,
- [1][0][RTW89_ETSI][55] = 127,
- [1][0][RTW89_FCC][57] = -4,
- [1][0][RTW89_ETSI][57] = 127,
- [1][0][RTW89_FCC][59] = -4,
- [1][0][RTW89_ETSI][59] = 127,
- [1][0][RTW89_FCC][60] = -4,
- [1][0][RTW89_ETSI][60] = 127,
- [1][0][RTW89_FCC][62] = -4,
- [1][0][RTW89_ETSI][62] = 127,
- [1][0][RTW89_FCC][64] = -4,
- [1][0][RTW89_ETSI][64] = 127,
- [1][0][RTW89_FCC][66] = -4,
- [1][0][RTW89_ETSI][66] = 127,
- [1][0][RTW89_FCC][68] = -4,
- [1][0][RTW89_ETSI][68] = 127,
- [1][0][RTW89_FCC][70] = -4,
- [1][0][RTW89_ETSI][70] = 127,
- [1][0][RTW89_FCC][72] = -4,
- [1][0][RTW89_ETSI][72] = 127,
- [1][0][RTW89_FCC][74] = -4,
- [1][0][RTW89_ETSI][74] = 127,
- [1][0][RTW89_FCC][75] = -4,
- [1][0][RTW89_ETSI][75] = 127,
- [1][0][RTW89_FCC][77] = -4,
- [1][0][RTW89_ETSI][77] = 127,
- [1][0][RTW89_FCC][79] = -4,
- [1][0][RTW89_ETSI][79] = 127,
- [1][0][RTW89_FCC][81] = -4,
- [1][0][RTW89_ETSI][81] = 127,
- [1][0][RTW89_FCC][83] = -4,
- [1][0][RTW89_ETSI][83] = 127,
- [1][0][RTW89_FCC][85] = -4,
- [1][0][RTW89_ETSI][85] = 127,
- [1][0][RTW89_FCC][87] = -4,
- [1][0][RTW89_ETSI][87] = 127,
- [1][0][RTW89_FCC][89] = -4,
- [1][0][RTW89_ETSI][89] = 127,
- [1][0][RTW89_FCC][90] = -4,
- [1][0][RTW89_ETSI][90] = 127,
- [1][0][RTW89_FCC][92] = -4,
- [1][0][RTW89_ETSI][92] = 127,
- [1][0][RTW89_FCC][94] = -4,
- [1][0][RTW89_ETSI][94] = 127,
- [1][0][RTW89_FCC][96] = -4,
- [1][0][RTW89_ETSI][96] = 127,
- [1][0][RTW89_FCC][98] = -4,
- [1][0][RTW89_ETSI][98] = 127,
- [1][0][RTW89_FCC][100] = -4,
- [1][0][RTW89_ETSI][100] = 127,
- [1][0][RTW89_FCC][102] = -4,
- [1][0][RTW89_ETSI][102] = 127,
- [1][0][RTW89_FCC][104] = -4,
- [1][0][RTW89_ETSI][104] = 127,
- [1][0][RTW89_FCC][105] = -4,
- [1][0][RTW89_ETSI][105] = 127,
- [1][0][RTW89_FCC][107] = 0,
- [1][0][RTW89_ETSI][107] = 127,
- [1][0][RTW89_FCC][109] = 2,
- [1][0][RTW89_ETSI][109] = 127,
- [1][0][RTW89_FCC][111] = 127,
- [1][0][RTW89_ETSI][111] = 127,
- [1][0][RTW89_FCC][113] = 127,
- [1][0][RTW89_ETSI][113] = 127,
- [1][0][RTW89_FCC][115] = 127,
- [1][0][RTW89_ETSI][115] = 127,
- [1][0][RTW89_FCC][117] = 127,
- [1][0][RTW89_ETSI][117] = 127,
- [1][0][RTW89_FCC][119] = 127,
- [1][0][RTW89_ETSI][119] = 127,
- [1][1][RTW89_FCC][0] = -26,
- [1][1][RTW89_ETSI][0] = 32,
- [1][1][RTW89_FCC][2] = -28,
- [1][1][RTW89_ETSI][2] = 32,
- [1][1][RTW89_FCC][4] = -28,
- [1][1][RTW89_ETSI][4] = 32,
- [1][1][RTW89_FCC][6] = -28,
- [1][1][RTW89_ETSI][6] = 32,
- [1][1][RTW89_FCC][8] = -28,
- [1][1][RTW89_ETSI][8] = 32,
- [1][1][RTW89_FCC][10] = -28,
- [1][1][RTW89_ETSI][10] = 32,
- [1][1][RTW89_FCC][12] = -28,
- [1][1][RTW89_ETSI][12] = 32,
- [1][1][RTW89_FCC][14] = -28,
- [1][1][RTW89_ETSI][14] = 32,
- [1][1][RTW89_FCC][15] = -28,
- [1][1][RTW89_ETSI][15] = 32,
- [1][1][RTW89_FCC][17] = -28,
- [1][1][RTW89_ETSI][17] = 32,
- [1][1][RTW89_FCC][19] = -28,
- [1][1][RTW89_ETSI][19] = 32,
- [1][1][RTW89_FCC][21] = -28,
- [1][1][RTW89_ETSI][21] = 32,
- [1][1][RTW89_FCC][23] = -28,
- [1][1][RTW89_ETSI][23] = 32,
- [1][1][RTW89_FCC][25] = -28,
- [1][1][RTW89_ETSI][25] = 32,
- [1][1][RTW89_FCC][27] = -28,
- [1][1][RTW89_ETSI][27] = 32,
- [1][1][RTW89_FCC][29] = -28,
- [1][1][RTW89_ETSI][29] = 32,
- [1][1][RTW89_FCC][30] = -28,
- [1][1][RTW89_ETSI][30] = 32,
- [1][1][RTW89_FCC][32] = -28,
- [1][1][RTW89_ETSI][32] = 32,
- [1][1][RTW89_FCC][34] = -28,
- [1][1][RTW89_ETSI][34] = 32,
- [1][1][RTW89_FCC][36] = -28,
- [1][1][RTW89_ETSI][36] = 32,
- [1][1][RTW89_FCC][38] = -28,
- [1][1][RTW89_ETSI][38] = 32,
- [1][1][RTW89_FCC][40] = -28,
- [1][1][RTW89_ETSI][40] = 32,
- [1][1][RTW89_FCC][42] = -28,
- [1][1][RTW89_ETSI][42] = 32,
- [1][1][RTW89_FCC][44] = -28,
- [1][1][RTW89_ETSI][44] = 34,
- [1][1][RTW89_FCC][45] = -26,
- [1][1][RTW89_ETSI][45] = 127,
- [1][1][RTW89_FCC][47] = -28,
- [1][1][RTW89_ETSI][47] = 127,
- [1][1][RTW89_FCC][49] = -28,
- [1][1][RTW89_ETSI][49] = 127,
- [1][1][RTW89_FCC][51] = -28,
- [1][1][RTW89_ETSI][51] = 127,
- [1][1][RTW89_FCC][53] = -26,
- [1][1][RTW89_ETSI][53] = 127,
- [1][1][RTW89_FCC][55] = -28,
- [1][1][RTW89_ETSI][55] = 127,
- [1][1][RTW89_FCC][57] = -28,
- [1][1][RTW89_ETSI][57] = 127,
- [1][1][RTW89_FCC][59] = -28,
- [1][1][RTW89_ETSI][59] = 127,
- [1][1][RTW89_FCC][60] = -28,
- [1][1][RTW89_ETSI][60] = 127,
- [1][1][RTW89_FCC][62] = -28,
- [1][1][RTW89_ETSI][62] = 127,
- [1][1][RTW89_FCC][64] = -28,
- [1][1][RTW89_ETSI][64] = 127,
- [1][1][RTW89_FCC][66] = -28,
- [1][1][RTW89_ETSI][66] = 127,
- [1][1][RTW89_FCC][68] = -28,
- [1][1][RTW89_ETSI][68] = 127,
- [1][1][RTW89_FCC][70] = -26,
- [1][1][RTW89_ETSI][70] = 127,
- [1][1][RTW89_FCC][72] = -28,
- [1][1][RTW89_ETSI][72] = 127,
- [1][1][RTW89_FCC][74] = -28,
- [1][1][RTW89_ETSI][74] = 127,
- [1][1][RTW89_FCC][75] = -28,
- [1][1][RTW89_ETSI][75] = 127,
- [1][1][RTW89_FCC][77] = -28,
- [1][1][RTW89_ETSI][77] = 127,
- [1][1][RTW89_FCC][79] = -28,
- [1][1][RTW89_ETSI][79] = 127,
- [1][1][RTW89_FCC][81] = -28,
- [1][1][RTW89_ETSI][81] = 127,
- [1][1][RTW89_FCC][83] = -28,
- [1][1][RTW89_ETSI][83] = 127,
- [1][1][RTW89_FCC][85] = -28,
- [1][1][RTW89_ETSI][85] = 127,
- [1][1][RTW89_FCC][87] = -28,
- [1][1][RTW89_ETSI][87] = 127,
- [1][1][RTW89_FCC][89] = -26,
- [1][1][RTW89_ETSI][89] = 127,
- [1][1][RTW89_FCC][90] = -26,
- [1][1][RTW89_ETSI][90] = 127,
- [1][1][RTW89_FCC][92] = -26,
- [1][1][RTW89_ETSI][92] = 127,
- [1][1][RTW89_FCC][94] = -26,
- [1][1][RTW89_ETSI][94] = 127,
- [1][1][RTW89_FCC][96] = -26,
- [1][1][RTW89_ETSI][96] = 127,
- [1][1][RTW89_FCC][98] = -26,
- [1][1][RTW89_ETSI][98] = 127,
- [1][1][RTW89_FCC][100] = -26,
- [1][1][RTW89_ETSI][100] = 127,
- [1][1][RTW89_FCC][102] = -26,
- [1][1][RTW89_ETSI][102] = 127,
- [1][1][RTW89_FCC][104] = -26,
- [1][1][RTW89_ETSI][104] = 127,
- [1][1][RTW89_FCC][105] = -26,
- [1][1][RTW89_ETSI][105] = 127,
- [1][1][RTW89_FCC][107] = -22,
- [1][1][RTW89_ETSI][107] = 127,
- [1][1][RTW89_FCC][109] = -22,
- [1][1][RTW89_ETSI][109] = 127,
- [1][1][RTW89_FCC][111] = 127,
- [1][1][RTW89_ETSI][111] = 127,
- [1][1][RTW89_FCC][113] = 127,
- [1][1][RTW89_ETSI][113] = 127,
- [1][1][RTW89_FCC][115] = 127,
- [1][1][RTW89_ETSI][115] = 127,
- [1][1][RTW89_FCC][117] = 127,
- [1][1][RTW89_ETSI][117] = 127,
- [1][1][RTW89_FCC][119] = 127,
- [1][1][RTW89_ETSI][119] = 127,
- [2][0][RTW89_FCC][0] = 8,
- [2][0][RTW89_ETSI][0] = 56,
- [2][0][RTW89_FCC][2] = 8,
- [2][0][RTW89_ETSI][2] = 56,
- [2][0][RTW89_FCC][4] = 8,
- [2][0][RTW89_ETSI][4] = 56,
- [2][0][RTW89_FCC][6] = 8,
- [2][0][RTW89_ETSI][6] = 56,
- [2][0][RTW89_FCC][8] = 8,
- [2][0][RTW89_ETSI][8] = 56,
- [2][0][RTW89_FCC][10] = 8,
- [2][0][RTW89_ETSI][10] = 56,
- [2][0][RTW89_FCC][12] = 8,
- [2][0][RTW89_ETSI][12] = 56,
- [2][0][RTW89_FCC][14] = 8,
- [2][0][RTW89_ETSI][14] = 56,
- [2][0][RTW89_FCC][15] = 8,
- [2][0][RTW89_ETSI][15] = 56,
- [2][0][RTW89_FCC][17] = 8,
- [2][0][RTW89_ETSI][17] = 56,
- [2][0][RTW89_FCC][19] = 8,
- [2][0][RTW89_ETSI][19] = 56,
- [2][0][RTW89_FCC][21] = 8,
- [2][0][RTW89_ETSI][21] = 56,
- [2][0][RTW89_FCC][23] = 8,
- [2][0][RTW89_ETSI][23] = 56,
- [2][0][RTW89_FCC][25] = 8,
- [2][0][RTW89_ETSI][25] = 56,
- [2][0][RTW89_FCC][27] = 8,
- [2][0][RTW89_ETSI][27] = 56,
- [2][0][RTW89_FCC][29] = 8,
- [2][0][RTW89_ETSI][29] = 56,
- [2][0][RTW89_FCC][30] = 8,
- [2][0][RTW89_ETSI][30] = 56,
- [2][0][RTW89_FCC][32] = 8,
- [2][0][RTW89_ETSI][32] = 56,
- [2][0][RTW89_FCC][34] = 8,
- [2][0][RTW89_ETSI][34] = 56,
- [2][0][RTW89_FCC][36] = 8,
- [2][0][RTW89_ETSI][36] = 56,
- [2][0][RTW89_FCC][38] = 8,
- [2][0][RTW89_ETSI][38] = 56,
- [2][0][RTW89_FCC][40] = 8,
- [2][0][RTW89_ETSI][40] = 56,
- [2][0][RTW89_FCC][42] = 8,
- [2][0][RTW89_ETSI][42] = 56,
- [2][0][RTW89_FCC][44] = 8,
- [2][0][RTW89_ETSI][44] = 56,
- [2][0][RTW89_FCC][45] = 8,
- [2][0][RTW89_ETSI][45] = 127,
- [2][0][RTW89_FCC][47] = 8,
- [2][0][RTW89_ETSI][47] = 127,
- [2][0][RTW89_FCC][49] = 8,
- [2][0][RTW89_ETSI][49] = 127,
- [2][0][RTW89_FCC][51] = 8,
- [2][0][RTW89_ETSI][51] = 127,
- [2][0][RTW89_FCC][53] = 8,
- [2][0][RTW89_ETSI][53] = 127,
- [2][0][RTW89_FCC][55] = 8,
- [2][0][RTW89_ETSI][55] = 127,
- [2][0][RTW89_FCC][57] = 8,
- [2][0][RTW89_ETSI][57] = 127,
- [2][0][RTW89_FCC][59] = 8,
- [2][0][RTW89_ETSI][59] = 127,
- [2][0][RTW89_FCC][60] = 8,
- [2][0][RTW89_ETSI][60] = 127,
- [2][0][RTW89_FCC][62] = 8,
- [2][0][RTW89_ETSI][62] = 127,
- [2][0][RTW89_FCC][64] = 8,
- [2][0][RTW89_ETSI][64] = 127,
- [2][0][RTW89_FCC][66] = 8,
- [2][0][RTW89_ETSI][66] = 127,
- [2][0][RTW89_FCC][68] = 8,
- [2][0][RTW89_ETSI][68] = 127,
- [2][0][RTW89_FCC][70] = 8,
- [2][0][RTW89_ETSI][70] = 127,
- [2][0][RTW89_FCC][72] = 8,
- [2][0][RTW89_ETSI][72] = 127,
- [2][0][RTW89_FCC][74] = 8,
- [2][0][RTW89_ETSI][74] = 127,
- [2][0][RTW89_FCC][75] = 8,
- [2][0][RTW89_ETSI][75] = 127,
- [2][0][RTW89_FCC][77] = 8,
- [2][0][RTW89_ETSI][77] = 127,
- [2][0][RTW89_FCC][79] = 8,
- [2][0][RTW89_ETSI][79] = 127,
- [2][0][RTW89_FCC][81] = 8,
- [2][0][RTW89_ETSI][81] = 127,
- [2][0][RTW89_FCC][83] = 8,
- [2][0][RTW89_ETSI][83] = 127,
- [2][0][RTW89_FCC][85] = 8,
- [2][0][RTW89_ETSI][85] = 127,
- [2][0][RTW89_FCC][87] = 8,
- [2][0][RTW89_ETSI][87] = 127,
- [2][0][RTW89_FCC][89] = 8,
- [2][0][RTW89_ETSI][89] = 127,
- [2][0][RTW89_FCC][90] = 8,
- [2][0][RTW89_ETSI][90] = 127,
- [2][0][RTW89_FCC][92] = 8,
- [2][0][RTW89_ETSI][92] = 127,
- [2][0][RTW89_FCC][94] = 8,
- [2][0][RTW89_ETSI][94] = 127,
- [2][0][RTW89_FCC][96] = 8,
- [2][0][RTW89_ETSI][96] = 127,
- [2][0][RTW89_FCC][98] = 8,
- [2][0][RTW89_ETSI][98] = 127,
- [2][0][RTW89_FCC][100] = 8,
- [2][0][RTW89_ETSI][100] = 127,
- [2][0][RTW89_FCC][102] = 8,
- [2][0][RTW89_ETSI][102] = 127,
- [2][0][RTW89_FCC][104] = 8,
- [2][0][RTW89_ETSI][104] = 127,
- [2][0][RTW89_FCC][105] = 8,
- [2][0][RTW89_ETSI][105] = 127,
- [2][0][RTW89_FCC][107] = 10,
- [2][0][RTW89_ETSI][107] = 127,
- [2][0][RTW89_FCC][109] = 12,
- [2][0][RTW89_ETSI][109] = 127,
- [2][0][RTW89_FCC][111] = 127,
- [2][0][RTW89_ETSI][111] = 127,
- [2][0][RTW89_FCC][113] = 127,
- [2][0][RTW89_ETSI][113] = 127,
- [2][0][RTW89_FCC][115] = 127,
- [2][0][RTW89_ETSI][115] = 127,
- [2][0][RTW89_FCC][117] = 127,
- [2][0][RTW89_ETSI][117] = 127,
- [2][0][RTW89_FCC][119] = 127,
- [2][0][RTW89_ETSI][119] = 127,
- [2][1][RTW89_FCC][0] = -16,
- [2][1][RTW89_ETSI][0] = 44,
- [2][1][RTW89_FCC][2] = -16,
- [2][1][RTW89_ETSI][2] = 44,
- [2][1][RTW89_FCC][4] = -16,
- [2][1][RTW89_ETSI][4] = 44,
- [2][1][RTW89_FCC][6] = -16,
- [2][1][RTW89_ETSI][6] = 44,
- [2][1][RTW89_FCC][8] = -16,
- [2][1][RTW89_ETSI][8] = 44,
- [2][1][RTW89_FCC][10] = -16,
- [2][1][RTW89_ETSI][10] = 44,
- [2][1][RTW89_FCC][12] = -16,
- [2][1][RTW89_ETSI][12] = 44,
- [2][1][RTW89_FCC][14] = -16,
- [2][1][RTW89_ETSI][14] = 44,
- [2][1][RTW89_FCC][15] = -16,
- [2][1][RTW89_ETSI][15] = 44,
- [2][1][RTW89_FCC][17] = -16,
- [2][1][RTW89_ETSI][17] = 44,
- [2][1][RTW89_FCC][19] = -16,
- [2][1][RTW89_ETSI][19] = 44,
- [2][1][RTW89_FCC][21] = -16,
- [2][1][RTW89_ETSI][21] = 44,
- [2][1][RTW89_FCC][23] = -16,
- [2][1][RTW89_ETSI][23] = 44,
- [2][1][RTW89_FCC][25] = -16,
- [2][1][RTW89_ETSI][25] = 44,
- [2][1][RTW89_FCC][27] = -16,
- [2][1][RTW89_ETSI][27] = 44,
- [2][1][RTW89_FCC][29] = -16,
- [2][1][RTW89_ETSI][29] = 44,
- [2][1][RTW89_FCC][30] = -16,
- [2][1][RTW89_ETSI][30] = 44,
- [2][1][RTW89_FCC][32] = -16,
- [2][1][RTW89_ETSI][32] = 44,
- [2][1][RTW89_FCC][34] = -16,
- [2][1][RTW89_ETSI][34] = 44,
- [2][1][RTW89_FCC][36] = -16,
- [2][1][RTW89_ETSI][36] = 44,
- [2][1][RTW89_FCC][38] = -16,
- [2][1][RTW89_ETSI][38] = 44,
- [2][1][RTW89_FCC][40] = -16,
- [2][1][RTW89_ETSI][40] = 44,
- [2][1][RTW89_FCC][42] = -16,
- [2][1][RTW89_ETSI][42] = 44,
- [2][1][RTW89_FCC][44] = -16,
- [2][1][RTW89_ETSI][44] = 44,
- [2][1][RTW89_FCC][45] = -16,
- [2][1][RTW89_ETSI][45] = 127,
- [2][1][RTW89_FCC][47] = -16,
- [2][1][RTW89_ETSI][47] = 127,
- [2][1][RTW89_FCC][49] = -16,
- [2][1][RTW89_ETSI][49] = 127,
- [2][1][RTW89_FCC][51] = -16,
- [2][1][RTW89_ETSI][51] = 127,
- [2][1][RTW89_FCC][53] = -16,
- [2][1][RTW89_ETSI][53] = 127,
- [2][1][RTW89_FCC][55] = -16,
- [2][1][RTW89_ETSI][55] = 127,
- [2][1][RTW89_FCC][57] = -16,
- [2][1][RTW89_ETSI][57] = 127,
- [2][1][RTW89_FCC][59] = -16,
- [2][1][RTW89_ETSI][59] = 127,
- [2][1][RTW89_FCC][60] = -16,
- [2][1][RTW89_ETSI][60] = 127,
- [2][1][RTW89_FCC][62] = -16,
- [2][1][RTW89_ETSI][62] = 127,
- [2][1][RTW89_FCC][64] = -16,
- [2][1][RTW89_ETSI][64] = 127,
- [2][1][RTW89_FCC][66] = -16,
- [2][1][RTW89_ETSI][66] = 127,
- [2][1][RTW89_FCC][68] = -16,
- [2][1][RTW89_ETSI][68] = 127,
- [2][1][RTW89_FCC][70] = -16,
- [2][1][RTW89_ETSI][70] = 127,
- [2][1][RTW89_FCC][72] = -16,
- [2][1][RTW89_ETSI][72] = 127,
- [2][1][RTW89_FCC][74] = -16,
- [2][1][RTW89_ETSI][74] = 127,
- [2][1][RTW89_FCC][75] = -16,
- [2][1][RTW89_ETSI][75] = 127,
- [2][1][RTW89_FCC][77] = -16,
- [2][1][RTW89_ETSI][77] = 127,
- [2][1][RTW89_FCC][79] = -16,
- [2][1][RTW89_ETSI][79] = 127,
- [2][1][RTW89_FCC][81] = -16,
- [2][1][RTW89_ETSI][81] = 127,
- [2][1][RTW89_FCC][83] = -16,
- [2][1][RTW89_ETSI][83] = 127,
- [2][1][RTW89_FCC][85] = -18,
- [2][1][RTW89_ETSI][85] = 127,
- [2][1][RTW89_FCC][87] = -16,
- [2][1][RTW89_ETSI][87] = 127,
- [2][1][RTW89_FCC][89] = -16,
- [2][1][RTW89_ETSI][89] = 127,
- [2][1][RTW89_FCC][90] = -16,
- [2][1][RTW89_ETSI][90] = 127,
- [2][1][RTW89_FCC][92] = -16,
- [2][1][RTW89_ETSI][92] = 127,
- [2][1][RTW89_FCC][94] = -16,
- [2][1][RTW89_ETSI][94] = 127,
- [2][1][RTW89_FCC][96] = -16,
- [2][1][RTW89_ETSI][96] = 127,
- [2][1][RTW89_FCC][98] = -16,
- [2][1][RTW89_ETSI][98] = 127,
- [2][1][RTW89_FCC][100] = -16,
- [2][1][RTW89_ETSI][100] = 127,
- [2][1][RTW89_FCC][102] = -16,
- [2][1][RTW89_ETSI][102] = 127,
- [2][1][RTW89_FCC][104] = -16,
- [2][1][RTW89_ETSI][104] = 127,
- [2][1][RTW89_FCC][105] = -16,
- [2][1][RTW89_ETSI][105] = 127,
- [2][1][RTW89_FCC][107] = -12,
- [2][1][RTW89_ETSI][107] = 127,
- [2][1][RTW89_FCC][109] = -10,
- [2][1][RTW89_ETSI][109] = 127,
- [2][1][RTW89_FCC][111] = 127,
- [2][1][RTW89_ETSI][111] = 127,
- [2][1][RTW89_FCC][113] = 127,
- [2][1][RTW89_ETSI][113] = 127,
- [2][1][RTW89_FCC][115] = 127,
- [2][1][RTW89_ETSI][115] = 127,
- [2][1][RTW89_FCC][117] = 127,
- [2][1][RTW89_ETSI][117] = 127,
- [2][1][RTW89_FCC][119] = 127,
- [2][1][RTW89_ETSI][119] = 127,
+ [RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER]
+ [RTW89_6G_CH_NUM] = {
+ [0][0][RTW89_WW][0][0] = -16,
+ [0][0][RTW89_WW][1][0] = -16,
+ [0][0][RTW89_WW][2][0] = 44,
+ [0][0][RTW89_WW][0][2] = -18,
+ [0][0][RTW89_WW][1][2] = -18,
+ [0][0][RTW89_WW][2][2] = 44,
+ [0][0][RTW89_WW][0][4] = -18,
+ [0][0][RTW89_WW][1][4] = -18,
+ [0][0][RTW89_WW][2][4] = 44,
+ [0][0][RTW89_WW][0][6] = -18,
+ [0][0][RTW89_WW][1][6] = -18,
+ [0][0][RTW89_WW][2][6] = 44,
+ [0][0][RTW89_WW][0][8] = -18,
+ [0][0][RTW89_WW][1][8] = -18,
+ [0][0][RTW89_WW][2][8] = 44,
+ [0][0][RTW89_WW][0][10] = -18,
+ [0][0][RTW89_WW][1][10] = -18,
+ [0][0][RTW89_WW][2][10] = 44,
+ [0][0][RTW89_WW][0][12] = -18,
+ [0][0][RTW89_WW][1][12] = -18,
+ [0][0][RTW89_WW][2][12] = 44,
+ [0][0][RTW89_WW][0][14] = -18,
+ [0][0][RTW89_WW][1][14] = -18,
+ [0][0][RTW89_WW][2][14] = 44,
+ [0][0][RTW89_WW][0][15] = -18,
+ [0][0][RTW89_WW][1][15] = -18,
+ [0][0][RTW89_WW][2][15] = 44,
+ [0][0][RTW89_WW][0][17] = -18,
+ [0][0][RTW89_WW][1][17] = -18,
+ [0][0][RTW89_WW][2][17] = 44,
+ [0][0][RTW89_WW][0][19] = -18,
+ [0][0][RTW89_WW][1][19] = -18,
+ [0][0][RTW89_WW][2][19] = 44,
+ [0][0][RTW89_WW][0][21] = -18,
+ [0][0][RTW89_WW][1][21] = -18,
+ [0][0][RTW89_WW][2][21] = 44,
+ [0][0][RTW89_WW][0][23] = -18,
+ [0][0][RTW89_WW][1][23] = -18,
+ [0][0][RTW89_WW][2][23] = 54,
+ [0][0][RTW89_WW][0][25] = -18,
+ [0][0][RTW89_WW][1][25] = -18,
+ [0][0][RTW89_WW][2][25] = 54,
+ [0][0][RTW89_WW][0][27] = -18,
+ [0][0][RTW89_WW][1][27] = -18,
+ [0][0][RTW89_WW][2][27] = 54,
+ [0][0][RTW89_WW][0][29] = -18,
+ [0][0][RTW89_WW][1][29] = -18,
+ [0][0][RTW89_WW][2][29] = 54,
+ [0][0][RTW89_WW][0][30] = -18,
+ [0][0][RTW89_WW][1][30] = -18,
+ [0][0][RTW89_WW][2][30] = 54,
+ [0][0][RTW89_WW][0][32] = -18,
+ [0][0][RTW89_WW][1][32] = -18,
+ [0][0][RTW89_WW][2][32] = 54,
+ [0][0][RTW89_WW][0][34] = -18,
+ [0][0][RTW89_WW][1][34] = -18,
+ [0][0][RTW89_WW][2][34] = 54,
+ [0][0][RTW89_WW][0][36] = -18,
+ [0][0][RTW89_WW][1][36] = -18,
+ [0][0][RTW89_WW][2][36] = 54,
+ [0][0][RTW89_WW][0][38] = -18,
+ [0][0][RTW89_WW][1][38] = -18,
+ [0][0][RTW89_WW][2][38] = 54,
+ [0][0][RTW89_WW][0][40] = -18,
+ [0][0][RTW89_WW][1][40] = -18,
+ [0][0][RTW89_WW][2][40] = 54,
+ [0][0][RTW89_WW][0][42] = -18,
+ [0][0][RTW89_WW][1][42] = -18,
+ [0][0][RTW89_WW][2][42] = 54,
+ [0][0][RTW89_WW][0][44] = -16,
+ [0][0][RTW89_WW][1][44] = -16,
+ [0][0][RTW89_WW][2][44] = 56,
+ [0][0][RTW89_WW][0][45] = -16,
+ [0][0][RTW89_WW][1][45] = -16,
+ [0][0][RTW89_WW][2][45] = 0,
+ [0][0][RTW89_WW][0][47] = -18,
+ [0][0][RTW89_WW][1][47] = -18,
+ [0][0][RTW89_WW][2][47] = 0,
+ [0][0][RTW89_WW][0][49] = -18,
+ [0][0][RTW89_WW][1][49] = -18,
+ [0][0][RTW89_WW][2][49] = 0,
+ [0][0][RTW89_WW][0][51] = -18,
+ [0][0][RTW89_WW][1][51] = -18,
+ [0][0][RTW89_WW][2][51] = 0,
+ [0][0][RTW89_WW][0][53] = -16,
+ [0][0][RTW89_WW][1][53] = -16,
+ [0][0][RTW89_WW][2][53] = 0,
+ [0][0][RTW89_WW][0][55] = -18,
+ [0][0][RTW89_WW][1][55] = -18,
+ [0][0][RTW89_WW][2][55] = 56,
+ [0][0][RTW89_WW][0][57] = -18,
+ [0][0][RTW89_WW][1][57] = -18,
+ [0][0][RTW89_WW][2][57] = 56,
+ [0][0][RTW89_WW][0][59] = -18,
+ [0][0][RTW89_WW][1][59] = -18,
+ [0][0][RTW89_WW][2][59] = 56,
+ [0][0][RTW89_WW][0][60] = -18,
+ [0][0][RTW89_WW][1][60] = -18,
+ [0][0][RTW89_WW][2][60] = 56,
+ [0][0][RTW89_WW][0][62] = -18,
+ [0][0][RTW89_WW][1][62] = -18,
+ [0][0][RTW89_WW][2][62] = 56,
+ [0][0][RTW89_WW][0][64] = -18,
+ [0][0][RTW89_WW][1][64] = -18,
+ [0][0][RTW89_WW][2][64] = 56,
+ [0][0][RTW89_WW][0][66] = -18,
+ [0][0][RTW89_WW][1][66] = -18,
+ [0][0][RTW89_WW][2][66] = 56,
+ [0][0][RTW89_WW][0][68] = -18,
+ [0][0][RTW89_WW][1][68] = -18,
+ [0][0][RTW89_WW][2][68] = 56,
+ [0][0][RTW89_WW][0][70] = -16,
+ [0][0][RTW89_WW][1][70] = -16,
+ [0][0][RTW89_WW][2][70] = 56,
+ [0][0][RTW89_WW][0][72] = -18,
+ [0][0][RTW89_WW][1][72] = -18,
+ [0][0][RTW89_WW][2][72] = 56,
+ [0][0][RTW89_WW][0][74] = -18,
+ [0][0][RTW89_WW][1][74] = -18,
+ [0][0][RTW89_WW][2][74] = 56,
+ [0][0][RTW89_WW][0][75] = -18,
+ [0][0][RTW89_WW][1][75] = -18,
+ [0][0][RTW89_WW][2][75] = 56,
+ [0][0][RTW89_WW][0][77] = -18,
+ [0][0][RTW89_WW][1][77] = -18,
+ [0][0][RTW89_WW][2][77] = 56,
+ [0][0][RTW89_WW][0][79] = -18,
+ [0][0][RTW89_WW][1][79] = -18,
+ [0][0][RTW89_WW][2][79] = 56,
+ [0][0][RTW89_WW][0][81] = -18,
+ [0][0][RTW89_WW][1][81] = -18,
+ [0][0][RTW89_WW][2][81] = 56,
+ [0][0][RTW89_WW][0][83] = -18,
+ [0][0][RTW89_WW][1][83] = -18,
+ [0][0][RTW89_WW][2][83] = 56,
+ [0][0][RTW89_WW][0][85] = -18,
+ [0][0][RTW89_WW][1][85] = -18,
+ [0][0][RTW89_WW][2][85] = 56,
+ [0][0][RTW89_WW][0][87] = -16,
+ [0][0][RTW89_WW][1][87] = -16,
+ [0][0][RTW89_WW][2][87] = 0,
+ [0][0][RTW89_WW][0][89] = -16,
+ [0][0][RTW89_WW][1][89] = -16,
+ [0][0][RTW89_WW][2][89] = 0,
+ [0][0][RTW89_WW][0][90] = -16,
+ [0][0][RTW89_WW][1][90] = -16,
+ [0][0][RTW89_WW][2][90] = 0,
+ [0][0][RTW89_WW][0][92] = -16,
+ [0][0][RTW89_WW][1][92] = -16,
+ [0][0][RTW89_WW][2][92] = 0,
+ [0][0][RTW89_WW][0][94] = -16,
+ [0][0][RTW89_WW][1][94] = -16,
+ [0][0][RTW89_WW][2][94] = 0,
+ [0][0][RTW89_WW][0][96] = -16,
+ [0][0][RTW89_WW][1][96] = -16,
+ [0][0][RTW89_WW][2][96] = 0,
+ [0][0][RTW89_WW][0][98] = -16,
+ [0][0][RTW89_WW][1][98] = -16,
+ [0][0][RTW89_WW][2][98] = 0,
+ [0][0][RTW89_WW][0][100] = -16,
+ [0][0][RTW89_WW][1][100] = -16,
+ [0][0][RTW89_WW][2][100] = 0,
+ [0][0][RTW89_WW][0][102] = -16,
+ [0][0][RTW89_WW][1][102] = -16,
+ [0][0][RTW89_WW][2][102] = 0,
+ [0][0][RTW89_WW][0][104] = -16,
+ [0][0][RTW89_WW][1][104] = -16,
+ [0][0][RTW89_WW][2][104] = 0,
+ [0][0][RTW89_WW][0][105] = -16,
+ [0][0][RTW89_WW][1][105] = -16,
+ [0][0][RTW89_WW][2][105] = 0,
+ [0][0][RTW89_WW][0][107] = -12,
+ [0][0][RTW89_WW][1][107] = -12,
+ [0][0][RTW89_WW][2][107] = 0,
+ [0][0][RTW89_WW][0][109] = -12,
+ [0][0][RTW89_WW][1][109] = -12,
+ [0][0][RTW89_WW][2][109] = 0,
+ [0][0][RTW89_WW][0][111] = 0,
+ [0][0][RTW89_WW][1][111] = 0,
+ [0][0][RTW89_WW][2][111] = 0,
+ [0][0][RTW89_WW][0][113] = 0,
+ [0][0][RTW89_WW][1][113] = 0,
+ [0][0][RTW89_WW][2][113] = 0,
+ [0][0][RTW89_WW][0][115] = 0,
+ [0][0][RTW89_WW][1][115] = 0,
+ [0][0][RTW89_WW][2][115] = 0,
+ [0][0][RTW89_WW][0][117] = 0,
+ [0][0][RTW89_WW][1][117] = 0,
+ [0][0][RTW89_WW][2][117] = 0,
+ [0][0][RTW89_WW][0][119] = 0,
+ [0][0][RTW89_WW][1][119] = 0,
+ [0][0][RTW89_WW][2][119] = 0,
+ [0][1][RTW89_WW][0][0] = -40,
+ [0][1][RTW89_WW][1][0] = -40,
+ [0][1][RTW89_WW][2][0] = 32,
+ [0][1][RTW89_WW][0][2] = -40,
+ [0][1][RTW89_WW][1][2] = -40,
+ [0][1][RTW89_WW][2][2] = 32,
+ [0][1][RTW89_WW][0][4] = -40,
+ [0][1][RTW89_WW][1][4] = -40,
+ [0][1][RTW89_WW][2][4] = 32,
+ [0][1][RTW89_WW][0][6] = -40,
+ [0][1][RTW89_WW][1][6] = -40,
+ [0][1][RTW89_WW][2][6] = 32,
+ [0][1][RTW89_WW][0][8] = -40,
+ [0][1][RTW89_WW][1][8] = -40,
+ [0][1][RTW89_WW][2][8] = 32,
+ [0][1][RTW89_WW][0][10] = -40,
+ [0][1][RTW89_WW][1][10] = -40,
+ [0][1][RTW89_WW][2][10] = 32,
+ [0][1][RTW89_WW][0][12] = -40,
+ [0][1][RTW89_WW][1][12] = -40,
+ [0][1][RTW89_WW][2][12] = 32,
+ [0][1][RTW89_WW][0][14] = -40,
+ [0][1][RTW89_WW][1][14] = -40,
+ [0][1][RTW89_WW][2][14] = 32,
+ [0][1][RTW89_WW][0][15] = -40,
+ [0][1][RTW89_WW][1][15] = -40,
+ [0][1][RTW89_WW][2][15] = 32,
+ [0][1][RTW89_WW][0][17] = -40,
+ [0][1][RTW89_WW][1][17] = -40,
+ [0][1][RTW89_WW][2][17] = 32,
+ [0][1][RTW89_WW][0][19] = -40,
+ [0][1][RTW89_WW][1][19] = -40,
+ [0][1][RTW89_WW][2][19] = 32,
+ [0][1][RTW89_WW][0][21] = -40,
+ [0][1][RTW89_WW][1][21] = -40,
+ [0][1][RTW89_WW][2][21] = 32,
+ [0][1][RTW89_WW][0][23] = -40,
+ [0][1][RTW89_WW][1][23] = -40,
+ [0][1][RTW89_WW][2][23] = 32,
+ [0][1][RTW89_WW][0][25] = -40,
+ [0][1][RTW89_WW][1][25] = -40,
+ [0][1][RTW89_WW][2][25] = 32,
+ [0][1][RTW89_WW][0][27] = -40,
+ [0][1][RTW89_WW][1][27] = -40,
+ [0][1][RTW89_WW][2][27] = 32,
+ [0][1][RTW89_WW][0][29] = -40,
+ [0][1][RTW89_WW][1][29] = -40,
+ [0][1][RTW89_WW][2][29] = 32,
+ [0][1][RTW89_WW][0][30] = -40,
+ [0][1][RTW89_WW][1][30] = -40,
+ [0][1][RTW89_WW][2][30] = 32,
+ [0][1][RTW89_WW][0][32] = -40,
+ [0][1][RTW89_WW][1][32] = -40,
+ [0][1][RTW89_WW][2][32] = 32,
+ [0][1][RTW89_WW][0][34] = -40,
+ [0][1][RTW89_WW][1][34] = -40,
+ [0][1][RTW89_WW][2][34] = 32,
+ [0][1][RTW89_WW][0][36] = -40,
+ [0][1][RTW89_WW][1][36] = -40,
+ [0][1][RTW89_WW][2][36] = 32,
+ [0][1][RTW89_WW][0][38] = -40,
+ [0][1][RTW89_WW][1][38] = -40,
+ [0][1][RTW89_WW][2][38] = 32,
+ [0][1][RTW89_WW][0][40] = -40,
+ [0][1][RTW89_WW][1][40] = -40,
+ [0][1][RTW89_WW][2][40] = 32,
+ [0][1][RTW89_WW][0][42] = -40,
+ [0][1][RTW89_WW][1][42] = -40,
+ [0][1][RTW89_WW][2][42] = 32,
+ [0][1][RTW89_WW][0][44] = -40,
+ [0][1][RTW89_WW][1][44] = -40,
+ [0][1][RTW89_WW][2][44] = 32,
+ [0][1][RTW89_WW][0][45] = -40,
+ [0][1][RTW89_WW][1][45] = -40,
+ [0][1][RTW89_WW][2][45] = 0,
+ [0][1][RTW89_WW][0][47] = -40,
+ [0][1][RTW89_WW][1][47] = -40,
+ [0][1][RTW89_WW][2][47] = 0,
+ [0][1][RTW89_WW][0][49] = -40,
+ [0][1][RTW89_WW][1][49] = -40,
+ [0][1][RTW89_WW][2][49] = 0,
+ [0][1][RTW89_WW][0][51] = -40,
+ [0][1][RTW89_WW][1][51] = -40,
+ [0][1][RTW89_WW][2][51] = 0,
+ [0][1][RTW89_WW][0][53] = -40,
+ [0][1][RTW89_WW][1][53] = -40,
+ [0][1][RTW89_WW][2][53] = 0,
+ [0][1][RTW89_WW][0][55] = -40,
+ [0][1][RTW89_WW][1][55] = -40,
+ [0][1][RTW89_WW][2][55] = 30,
+ [0][1][RTW89_WW][0][57] = -40,
+ [0][1][RTW89_WW][1][57] = -40,
+ [0][1][RTW89_WW][2][57] = 30,
+ [0][1][RTW89_WW][0][59] = -40,
+ [0][1][RTW89_WW][1][59] = -40,
+ [0][1][RTW89_WW][2][59] = 30,
+ [0][1][RTW89_WW][0][60] = -40,
+ [0][1][RTW89_WW][1][60] = -40,
+ [0][1][RTW89_WW][2][60] = 30,
+ [0][1][RTW89_WW][0][62] = -40,
+ [0][1][RTW89_WW][1][62] = -40,
+ [0][1][RTW89_WW][2][62] = 30,
+ [0][1][RTW89_WW][0][64] = -40,
+ [0][1][RTW89_WW][1][64] = -40,
+ [0][1][RTW89_WW][2][64] = 30,
+ [0][1][RTW89_WW][0][66] = -40,
+ [0][1][RTW89_WW][1][66] = -40,
+ [0][1][RTW89_WW][2][66] = 30,
+ [0][1][RTW89_WW][0][68] = -40,
+ [0][1][RTW89_WW][1][68] = -40,
+ [0][1][RTW89_WW][2][68] = 30,
+ [0][1][RTW89_WW][0][70] = -38,
+ [0][1][RTW89_WW][1][70] = -38,
+ [0][1][RTW89_WW][2][70] = 30,
+ [0][1][RTW89_WW][0][72] = -38,
+ [0][1][RTW89_WW][1][72] = -38,
+ [0][1][RTW89_WW][2][72] = 30,
+ [0][1][RTW89_WW][0][74] = -38,
+ [0][1][RTW89_WW][1][74] = -38,
+ [0][1][RTW89_WW][2][74] = 30,
+ [0][1][RTW89_WW][0][75] = -38,
+ [0][1][RTW89_WW][1][75] = -38,
+ [0][1][RTW89_WW][2][75] = 30,
+ [0][1][RTW89_WW][0][77] = -38,
+ [0][1][RTW89_WW][1][77] = -38,
+ [0][1][RTW89_WW][2][77] = 30,
+ [0][1][RTW89_WW][0][79] = -38,
+ [0][1][RTW89_WW][1][79] = -38,
+ [0][1][RTW89_WW][2][79] = 30,
+ [0][1][RTW89_WW][0][81] = -38,
+ [0][1][RTW89_WW][1][81] = -38,
+ [0][1][RTW89_WW][2][81] = 30,
+ [0][1][RTW89_WW][0][83] = -38,
+ [0][1][RTW89_WW][1][83] = -38,
+ [0][1][RTW89_WW][2][83] = 30,
+ [0][1][RTW89_WW][0][85] = -38,
+ [0][1][RTW89_WW][1][85] = -38,
+ [0][1][RTW89_WW][2][85] = 30,
+ [0][1][RTW89_WW][0][87] = -40,
+ [0][1][RTW89_WW][1][87] = -40,
+ [0][1][RTW89_WW][2][87] = 0,
+ [0][1][RTW89_WW][0][89] = -38,
+ [0][1][RTW89_WW][1][89] = -38,
+ [0][1][RTW89_WW][2][89] = 0,
+ [0][1][RTW89_WW][0][90] = -38,
+ [0][1][RTW89_WW][1][90] = -38,
+ [0][1][RTW89_WW][2][90] = 0,
+ [0][1][RTW89_WW][0][92] = -38,
+ [0][1][RTW89_WW][1][92] = -38,
+ [0][1][RTW89_WW][2][92] = 0,
+ [0][1][RTW89_WW][0][94] = -38,
+ [0][1][RTW89_WW][1][94] = -38,
+ [0][1][RTW89_WW][2][94] = 0,
+ [0][1][RTW89_WW][0][96] = -38,
+ [0][1][RTW89_WW][1][96] = -38,
+ [0][1][RTW89_WW][2][96] = 0,
+ [0][1][RTW89_WW][0][98] = -38,
+ [0][1][RTW89_WW][1][98] = -38,
+ [0][1][RTW89_WW][2][98] = 0,
+ [0][1][RTW89_WW][0][100] = -38,
+ [0][1][RTW89_WW][1][100] = -38,
+ [0][1][RTW89_WW][2][100] = 0,
+ [0][1][RTW89_WW][0][102] = -38,
+ [0][1][RTW89_WW][1][102] = -38,
+ [0][1][RTW89_WW][2][102] = 0,
+ [0][1][RTW89_WW][0][104] = -38,
+ [0][1][RTW89_WW][1][104] = -38,
+ [0][1][RTW89_WW][2][104] = 0,
+ [0][1][RTW89_WW][0][105] = -38,
+ [0][1][RTW89_WW][1][105] = -38,
+ [0][1][RTW89_WW][2][105] = 0,
+ [0][1][RTW89_WW][0][107] = -34,
+ [0][1][RTW89_WW][1][107] = -34,
+ [0][1][RTW89_WW][2][107] = 0,
+ [0][1][RTW89_WW][0][109] = -34,
+ [0][1][RTW89_WW][1][109] = -34,
+ [0][1][RTW89_WW][2][109] = 0,
+ [0][1][RTW89_WW][0][111] = 0,
+ [0][1][RTW89_WW][1][111] = 0,
+ [0][1][RTW89_WW][2][111] = 0,
+ [0][1][RTW89_WW][0][113] = 0,
+ [0][1][RTW89_WW][1][113] = 0,
+ [0][1][RTW89_WW][2][113] = 0,
+ [0][1][RTW89_WW][0][115] = 0,
+ [0][1][RTW89_WW][1][115] = 0,
+ [0][1][RTW89_WW][2][115] = 0,
+ [0][1][RTW89_WW][0][117] = 0,
+ [0][1][RTW89_WW][1][117] = 0,
+ [0][1][RTW89_WW][2][117] = 0,
+ [0][1][RTW89_WW][0][119] = 0,
+ [0][1][RTW89_WW][1][119] = 0,
+ [0][1][RTW89_WW][2][119] = 0,
+ [1][0][RTW89_WW][0][0] = -4,
+ [1][0][RTW89_WW][1][0] = -4,
+ [1][0][RTW89_WW][2][0] = 52,
+ [1][0][RTW89_WW][0][2] = -4,
+ [1][0][RTW89_WW][1][2] = -4,
+ [1][0][RTW89_WW][2][2] = 52,
+ [1][0][RTW89_WW][0][4] = -4,
+ [1][0][RTW89_WW][1][4] = -4,
+ [1][0][RTW89_WW][2][4] = 52,
+ [1][0][RTW89_WW][0][6] = -4,
+ [1][0][RTW89_WW][1][6] = -4,
+ [1][0][RTW89_WW][2][6] = 52,
+ [1][0][RTW89_WW][0][8] = -4,
+ [1][0][RTW89_WW][1][8] = -4,
+ [1][0][RTW89_WW][2][8] = 52,
+ [1][0][RTW89_WW][0][10] = -4,
+ [1][0][RTW89_WW][1][10] = -4,
+ [1][0][RTW89_WW][2][10] = 52,
+ [1][0][RTW89_WW][0][12] = -4,
+ [1][0][RTW89_WW][1][12] = -4,
+ [1][0][RTW89_WW][2][12] = 52,
+ [1][0][RTW89_WW][0][14] = -4,
+ [1][0][RTW89_WW][1][14] = -4,
+ [1][0][RTW89_WW][2][14] = 52,
+ [1][0][RTW89_WW][0][15] = -4,
+ [1][0][RTW89_WW][1][15] = -4,
+ [1][0][RTW89_WW][2][15] = 52,
+ [1][0][RTW89_WW][0][17] = -4,
+ [1][0][RTW89_WW][1][17] = -4,
+ [1][0][RTW89_WW][2][17] = 52,
+ [1][0][RTW89_WW][0][19] = -4,
+ [1][0][RTW89_WW][1][19] = -4,
+ [1][0][RTW89_WW][2][19] = 52,
+ [1][0][RTW89_WW][0][21] = -4,
+ [1][0][RTW89_WW][1][21] = -4,
+ [1][0][RTW89_WW][2][21] = 52,
+ [1][0][RTW89_WW][0][23] = -4,
+ [1][0][RTW89_WW][1][23] = -4,
+ [1][0][RTW89_WW][2][23] = 66,
+ [1][0][RTW89_WW][0][25] = -4,
+ [1][0][RTW89_WW][1][25] = -4,
+ [1][0][RTW89_WW][2][25] = 66,
+ [1][0][RTW89_WW][0][27] = -4,
+ [1][0][RTW89_WW][1][27] = -4,
+ [1][0][RTW89_WW][2][27] = 66,
+ [1][0][RTW89_WW][0][29] = -4,
+ [1][0][RTW89_WW][1][29] = -4,
+ [1][0][RTW89_WW][2][29] = 66,
+ [1][0][RTW89_WW][0][30] = -4,
+ [1][0][RTW89_WW][1][30] = -4,
+ [1][0][RTW89_WW][2][30] = 66,
+ [1][0][RTW89_WW][0][32] = -4,
+ [1][0][RTW89_WW][1][32] = -4,
+ [1][0][RTW89_WW][2][32] = 66,
+ [1][0][RTW89_WW][0][34] = -4,
+ [1][0][RTW89_WW][1][34] = -4,
+ [1][0][RTW89_WW][2][34] = 66,
+ [1][0][RTW89_WW][0][36] = -4,
+ [1][0][RTW89_WW][1][36] = -4,
+ [1][0][RTW89_WW][2][36] = 66,
+ [1][0][RTW89_WW][0][38] = -4,
+ [1][0][RTW89_WW][1][38] = -4,
+ [1][0][RTW89_WW][2][38] = 66,
+ [1][0][RTW89_WW][0][40] = -4,
+ [1][0][RTW89_WW][1][40] = -4,
+ [1][0][RTW89_WW][2][40] = 66,
+ [1][0][RTW89_WW][0][42] = -4,
+ [1][0][RTW89_WW][1][42] = -4,
+ [1][0][RTW89_WW][2][42] = 66,
+ [1][0][RTW89_WW][0][44] = -4,
+ [1][0][RTW89_WW][1][44] = -4,
+ [1][0][RTW89_WW][2][44] = 66,
+ [1][0][RTW89_WW][0][45] = -4,
+ [1][0][RTW89_WW][1][45] = -4,
+ [1][0][RTW89_WW][2][45] = 0,
+ [1][0][RTW89_WW][0][47] = -4,
+ [1][0][RTW89_WW][1][47] = -4,
+ [1][0][RTW89_WW][2][47] = 0,
+ [1][0][RTW89_WW][0][49] = -4,
+ [1][0][RTW89_WW][1][49] = -4,
+ [1][0][RTW89_WW][2][49] = 0,
+ [1][0][RTW89_WW][0][51] = -4,
+ [1][0][RTW89_WW][1][51] = -4,
+ [1][0][RTW89_WW][2][51] = 0,
+ [1][0][RTW89_WW][0][53] = -4,
+ [1][0][RTW89_WW][1][53] = -4,
+ [1][0][RTW89_WW][2][53] = 0,
+ [1][0][RTW89_WW][0][55] = -4,
+ [1][0][RTW89_WW][1][55] = -4,
+ [1][0][RTW89_WW][2][55] = 68,
+ [1][0][RTW89_WW][0][57] = -4,
+ [1][0][RTW89_WW][1][57] = -4,
+ [1][0][RTW89_WW][2][57] = 68,
+ [1][0][RTW89_WW][0][59] = -4,
+ [1][0][RTW89_WW][1][59] = -4,
+ [1][0][RTW89_WW][2][59] = 68,
+ [1][0][RTW89_WW][0][60] = -4,
+ [1][0][RTW89_WW][1][60] = -4,
+ [1][0][RTW89_WW][2][60] = 68,
+ [1][0][RTW89_WW][0][62] = -4,
+ [1][0][RTW89_WW][1][62] = -4,
+ [1][0][RTW89_WW][2][62] = 68,
+ [1][0][RTW89_WW][0][64] = -4,
+ [1][0][RTW89_WW][1][64] = -4,
+ [1][0][RTW89_WW][2][64] = 68,
+ [1][0][RTW89_WW][0][66] = -4,
+ [1][0][RTW89_WW][1][66] = -4,
+ [1][0][RTW89_WW][2][66] = 68,
+ [1][0][RTW89_WW][0][68] = -4,
+ [1][0][RTW89_WW][1][68] = -4,
+ [1][0][RTW89_WW][2][68] = 68,
+ [1][0][RTW89_WW][0][70] = -4,
+ [1][0][RTW89_WW][1][70] = -4,
+ [1][0][RTW89_WW][2][70] = 68,
+ [1][0][RTW89_WW][0][72] = -4,
+ [1][0][RTW89_WW][1][72] = -4,
+ [1][0][RTW89_WW][2][72] = 68,
+ [1][0][RTW89_WW][0][74] = -4,
+ [1][0][RTW89_WW][1][74] = -4,
+ [1][0][RTW89_WW][2][74] = 68,
+ [1][0][RTW89_WW][0][75] = -4,
+ [1][0][RTW89_WW][1][75] = -4,
+ [1][0][RTW89_WW][2][75] = 68,
+ [1][0][RTW89_WW][0][77] = -4,
+ [1][0][RTW89_WW][1][77] = -4,
+ [1][0][RTW89_WW][2][77] = 68,
+ [1][0][RTW89_WW][0][79] = -4,
+ [1][0][RTW89_WW][1][79] = -4,
+ [1][0][RTW89_WW][2][79] = 68,
+ [1][0][RTW89_WW][0][81] = -4,
+ [1][0][RTW89_WW][1][81] = -4,
+ [1][0][RTW89_WW][2][81] = 68,
+ [1][0][RTW89_WW][0][83] = -4,
+ [1][0][RTW89_WW][1][83] = -4,
+ [1][0][RTW89_WW][2][83] = 68,
+ [1][0][RTW89_WW][0][85] = -4,
+ [1][0][RTW89_WW][1][85] = -4,
+ [1][0][RTW89_WW][2][85] = 68,
+ [1][0][RTW89_WW][0][87] = -4,
+ [1][0][RTW89_WW][1][87] = -4,
+ [1][0][RTW89_WW][2][87] = 0,
+ [1][0][RTW89_WW][0][89] = -4,
+ [1][0][RTW89_WW][1][89] = -4,
+ [1][0][RTW89_WW][2][89] = 0,
+ [1][0][RTW89_WW][0][90] = -4,
+ [1][0][RTW89_WW][1][90] = -4,
+ [1][0][RTW89_WW][2][90] = 0,
+ [1][0][RTW89_WW][0][92] = -4,
+ [1][0][RTW89_WW][1][92] = -4,
+ [1][0][RTW89_WW][2][92] = 0,
+ [1][0][RTW89_WW][0][94] = -4,
+ [1][0][RTW89_WW][1][94] = -4,
+ [1][0][RTW89_WW][2][94] = 0,
+ [1][0][RTW89_WW][0][96] = -4,
+ [1][0][RTW89_WW][1][96] = -4,
+ [1][0][RTW89_WW][2][96] = 0,
+ [1][0][RTW89_WW][0][98] = -4,
+ [1][0][RTW89_WW][1][98] = -4,
+ [1][0][RTW89_WW][2][98] = 0,
+ [1][0][RTW89_WW][0][100] = -4,
+ [1][0][RTW89_WW][1][100] = -4,
+ [1][0][RTW89_WW][2][100] = 0,
+ [1][0][RTW89_WW][0][102] = -4,
+ [1][0][RTW89_WW][1][102] = -4,
+ [1][0][RTW89_WW][2][102] = 0,
+ [1][0][RTW89_WW][0][104] = -4,
+ [1][0][RTW89_WW][1][104] = -4,
+ [1][0][RTW89_WW][2][104] = 0,
+ [1][0][RTW89_WW][0][105] = -4,
+ [1][0][RTW89_WW][1][105] = -4,
+ [1][0][RTW89_WW][2][105] = 0,
+ [1][0][RTW89_WW][0][107] = -2,
+ [1][0][RTW89_WW][1][107] = -2,
+ [1][0][RTW89_WW][2][107] = 0,
+ [1][0][RTW89_WW][0][109] = 2,
+ [1][0][RTW89_WW][1][109] = 2,
+ [1][0][RTW89_WW][2][109] = 0,
+ [1][0][RTW89_WW][0][111] = 0,
+ [1][0][RTW89_WW][1][111] = 0,
+ [1][0][RTW89_WW][2][111] = 0,
+ [1][0][RTW89_WW][0][113] = 0,
+ [1][0][RTW89_WW][1][113] = 0,
+ [1][0][RTW89_WW][2][113] = 0,
+ [1][0][RTW89_WW][0][115] = 0,
+ [1][0][RTW89_WW][1][115] = 0,
+ [1][0][RTW89_WW][2][115] = 0,
+ [1][0][RTW89_WW][0][117] = 0,
+ [1][0][RTW89_WW][1][117] = 0,
+ [1][0][RTW89_WW][2][117] = 0,
+ [1][0][RTW89_WW][0][119] = 0,
+ [1][0][RTW89_WW][1][119] = 0,
+ [1][0][RTW89_WW][2][119] = 0,
+ [1][1][RTW89_WW][0][0] = -26,
+ [1][1][RTW89_WW][1][0] = -26,
+ [1][1][RTW89_WW][2][0] = 44,
+ [1][1][RTW89_WW][0][2] = -28,
+ [1][1][RTW89_WW][1][2] = -28,
+ [1][1][RTW89_WW][2][2] = 44,
+ [1][1][RTW89_WW][0][4] = -28,
+ [1][1][RTW89_WW][1][4] = -28,
+ [1][1][RTW89_WW][2][4] = 44,
+ [1][1][RTW89_WW][0][6] = -28,
+ [1][1][RTW89_WW][1][6] = -28,
+ [1][1][RTW89_WW][2][6] = 44,
+ [1][1][RTW89_WW][0][8] = -28,
+ [1][1][RTW89_WW][1][8] = -28,
+ [1][1][RTW89_WW][2][8] = 44,
+ [1][1][RTW89_WW][0][10] = -28,
+ [1][1][RTW89_WW][1][10] = -28,
+ [1][1][RTW89_WW][2][10] = 44,
+ [1][1][RTW89_WW][0][12] = -28,
+ [1][1][RTW89_WW][1][12] = -28,
+ [1][1][RTW89_WW][2][12] = 44,
+ [1][1][RTW89_WW][0][14] = -28,
+ [1][1][RTW89_WW][1][14] = -28,
+ [1][1][RTW89_WW][2][14] = 44,
+ [1][1][RTW89_WW][0][15] = -28,
+ [1][1][RTW89_WW][1][15] = -28,
+ [1][1][RTW89_WW][2][15] = 44,
+ [1][1][RTW89_WW][0][17] = -28,
+ [1][1][RTW89_WW][1][17] = -28,
+ [1][1][RTW89_WW][2][17] = 44,
+ [1][1][RTW89_WW][0][19] = -28,
+ [1][1][RTW89_WW][1][19] = -28,
+ [1][1][RTW89_WW][2][19] = 44,
+ [1][1][RTW89_WW][0][21] = -28,
+ [1][1][RTW89_WW][1][21] = -28,
+ [1][1][RTW89_WW][2][21] = 44,
+ [1][1][RTW89_WW][0][23] = -28,
+ [1][1][RTW89_WW][1][23] = -28,
+ [1][1][RTW89_WW][2][23] = 44,
+ [1][1][RTW89_WW][0][25] = -28,
+ [1][1][RTW89_WW][1][25] = -28,
+ [1][1][RTW89_WW][2][25] = 44,
+ [1][1][RTW89_WW][0][27] = -28,
+ [1][1][RTW89_WW][1][27] = -28,
+ [1][1][RTW89_WW][2][27] = 44,
+ [1][1][RTW89_WW][0][29] = -28,
+ [1][1][RTW89_WW][1][29] = -28,
+ [1][1][RTW89_WW][2][29] = 44,
+ [1][1][RTW89_WW][0][30] = -28,
+ [1][1][RTW89_WW][1][30] = -28,
+ [1][1][RTW89_WW][2][30] = 44,
+ [1][1][RTW89_WW][0][32] = -28,
+ [1][1][RTW89_WW][1][32] = -28,
+ [1][1][RTW89_WW][2][32] = 44,
+ [1][1][RTW89_WW][0][34] = -28,
+ [1][1][RTW89_WW][1][34] = -28,
+ [1][1][RTW89_WW][2][34] = 44,
+ [1][1][RTW89_WW][0][36] = -28,
+ [1][1][RTW89_WW][1][36] = -28,
+ [1][1][RTW89_WW][2][36] = 44,
+ [1][1][RTW89_WW][0][38] = -28,
+ [1][1][RTW89_WW][1][38] = -28,
+ [1][1][RTW89_WW][2][38] = 44,
+ [1][1][RTW89_WW][0][40] = -28,
+ [1][1][RTW89_WW][1][40] = -28,
+ [1][1][RTW89_WW][2][40] = 44,
+ [1][1][RTW89_WW][0][42] = -28,
+ [1][1][RTW89_WW][1][42] = -28,
+ [1][1][RTW89_WW][2][42] = 44,
+ [1][1][RTW89_WW][0][44] = -28,
+ [1][1][RTW89_WW][1][44] = -28,
+ [1][1][RTW89_WW][2][44] = 44,
+ [1][1][RTW89_WW][0][45] = -26,
+ [1][1][RTW89_WW][1][45] = -26,
+ [1][1][RTW89_WW][2][45] = 0,
+ [1][1][RTW89_WW][0][47] = -28,
+ [1][1][RTW89_WW][1][47] = -28,
+ [1][1][RTW89_WW][2][47] = 0,
+ [1][1][RTW89_WW][0][49] = -28,
+ [1][1][RTW89_WW][1][49] = -28,
+ [1][1][RTW89_WW][2][49] = 0,
+ [1][1][RTW89_WW][0][51] = -28,
+ [1][1][RTW89_WW][1][51] = -28,
+ [1][1][RTW89_WW][2][51] = 0,
+ [1][1][RTW89_WW][0][53] = -26,
+ [1][1][RTW89_WW][1][53] = -26,
+ [1][1][RTW89_WW][2][53] = 0,
+ [1][1][RTW89_WW][0][55] = -28,
+ [1][1][RTW89_WW][1][55] = -28,
+ [1][1][RTW89_WW][2][55] = 44,
+ [1][1][RTW89_WW][0][57] = -28,
+ [1][1][RTW89_WW][1][57] = -28,
+ [1][1][RTW89_WW][2][57] = 44,
+ [1][1][RTW89_WW][0][59] = -28,
+ [1][1][RTW89_WW][1][59] = -28,
+ [1][1][RTW89_WW][2][59] = 44,
+ [1][1][RTW89_WW][0][60] = -28,
+ [1][1][RTW89_WW][1][60] = -28,
+ [1][1][RTW89_WW][2][60] = 44,
+ [1][1][RTW89_WW][0][62] = -28,
+ [1][1][RTW89_WW][1][62] = -28,
+ [1][1][RTW89_WW][2][62] = 44,
+ [1][1][RTW89_WW][0][64] = -28,
+ [1][1][RTW89_WW][1][64] = -28,
+ [1][1][RTW89_WW][2][64] = 44,
+ [1][1][RTW89_WW][0][66] = -28,
+ [1][1][RTW89_WW][1][66] = -28,
+ [1][1][RTW89_WW][2][66] = 44,
+ [1][1][RTW89_WW][0][68] = -28,
+ [1][1][RTW89_WW][1][68] = -28,
+ [1][1][RTW89_WW][2][68] = 44,
+ [1][1][RTW89_WW][0][70] = -26,
+ [1][1][RTW89_WW][1][70] = -26,
+ [1][1][RTW89_WW][2][70] = 44,
+ [1][1][RTW89_WW][0][72] = -28,
+ [1][1][RTW89_WW][1][72] = -28,
+ [1][1][RTW89_WW][2][72] = 44,
+ [1][1][RTW89_WW][0][74] = -28,
+ [1][1][RTW89_WW][1][74] = -28,
+ [1][1][RTW89_WW][2][74] = 44,
+ [1][1][RTW89_WW][0][75] = -28,
+ [1][1][RTW89_WW][1][75] = -28,
+ [1][1][RTW89_WW][2][75] = 44,
+ [1][1][RTW89_WW][0][77] = -28,
+ [1][1][RTW89_WW][1][77] = -28,
+ [1][1][RTW89_WW][2][77] = 44,
+ [1][1][RTW89_WW][0][79] = -28,
+ [1][1][RTW89_WW][1][79] = -28,
+ [1][1][RTW89_WW][2][79] = 44,
+ [1][1][RTW89_WW][0][81] = -28,
+ [1][1][RTW89_WW][1][81] = -28,
+ [1][1][RTW89_WW][2][81] = 44,
+ [1][1][RTW89_WW][0][83] = -28,
+ [1][1][RTW89_WW][1][83] = -28,
+ [1][1][RTW89_WW][2][83] = 44,
+ [1][1][RTW89_WW][0][85] = -28,
+ [1][1][RTW89_WW][1][85] = -28,
+ [1][1][RTW89_WW][2][85] = 44,
+ [1][1][RTW89_WW][0][87] = -28,
+ [1][1][RTW89_WW][1][87] = -28,
+ [1][1][RTW89_WW][2][87] = 0,
+ [1][1][RTW89_WW][0][89] = -26,
+ [1][1][RTW89_WW][1][89] = -26,
+ [1][1][RTW89_WW][2][89] = 0,
+ [1][1][RTW89_WW][0][90] = -26,
+ [1][1][RTW89_WW][1][90] = -26,
+ [1][1][RTW89_WW][2][90] = 0,
+ [1][1][RTW89_WW][0][92] = -26,
+ [1][1][RTW89_WW][1][92] = -26,
+ [1][1][RTW89_WW][2][92] = 0,
+ [1][1][RTW89_WW][0][94] = -26,
+ [1][1][RTW89_WW][1][94] = -26,
+ [1][1][RTW89_WW][2][94] = 0,
+ [1][1][RTW89_WW][0][96] = -26,
+ [1][1][RTW89_WW][1][96] = -26,
+ [1][1][RTW89_WW][2][96] = 0,
+ [1][1][RTW89_WW][0][98] = -26,
+ [1][1][RTW89_WW][1][98] = -26,
+ [1][1][RTW89_WW][2][98] = 0,
+ [1][1][RTW89_WW][0][100] = -26,
+ [1][1][RTW89_WW][1][100] = -26,
+ [1][1][RTW89_WW][2][100] = 0,
+ [1][1][RTW89_WW][0][102] = -26,
+ [1][1][RTW89_WW][1][102] = -26,
+ [1][1][RTW89_WW][2][102] = 0,
+ [1][1][RTW89_WW][0][104] = -26,
+ [1][1][RTW89_WW][1][104] = -26,
+ [1][1][RTW89_WW][2][104] = 0,
+ [1][1][RTW89_WW][0][105] = -26,
+ [1][1][RTW89_WW][1][105] = -26,
+ [1][1][RTW89_WW][2][105] = 0,
+ [1][1][RTW89_WW][0][107] = -22,
+ [1][1][RTW89_WW][1][107] = -22,
+ [1][1][RTW89_WW][2][107] = 0,
+ [1][1][RTW89_WW][0][109] = -22,
+ [1][1][RTW89_WW][1][109] = -22,
+ [1][1][RTW89_WW][2][109] = 0,
+ [1][1][RTW89_WW][0][111] = 0,
+ [1][1][RTW89_WW][1][111] = 0,
+ [1][1][RTW89_WW][2][111] = 0,
+ [1][1][RTW89_WW][0][113] = 0,
+ [1][1][RTW89_WW][1][113] = 0,
+ [1][1][RTW89_WW][2][113] = 0,
+ [1][1][RTW89_WW][0][115] = 0,
+ [1][1][RTW89_WW][1][115] = 0,
+ [1][1][RTW89_WW][2][115] = 0,
+ [1][1][RTW89_WW][0][117] = 0,
+ [1][1][RTW89_WW][1][117] = 0,
+ [1][1][RTW89_WW][2][117] = 0,
+ [1][1][RTW89_WW][0][119] = 0,
+ [1][1][RTW89_WW][1][119] = 0,
+ [1][1][RTW89_WW][2][119] = 0,
+ [2][0][RTW89_WW][0][0] = -2,
+ [2][0][RTW89_WW][1][0] = -2,
+ [2][0][RTW89_WW][2][0] = 60,
+ [2][0][RTW89_WW][0][2] = -2,
+ [2][0][RTW89_WW][1][2] = -2,
+ [2][0][RTW89_WW][2][2] = 60,
+ [2][0][RTW89_WW][0][4] = -2,
+ [2][0][RTW89_WW][1][4] = -2,
+ [2][0][RTW89_WW][2][4] = 60,
+ [2][0][RTW89_WW][0][6] = -2,
+ [2][0][RTW89_WW][1][6] = -2,
+ [2][0][RTW89_WW][2][6] = 60,
+ [2][0][RTW89_WW][0][8] = -2,
+ [2][0][RTW89_WW][1][8] = -2,
+ [2][0][RTW89_WW][2][8] = 60,
+ [2][0][RTW89_WW][0][10] = -2,
+ [2][0][RTW89_WW][1][10] = -2,
+ [2][0][RTW89_WW][2][10] = 60,
+ [2][0][RTW89_WW][0][12] = -2,
+ [2][0][RTW89_WW][1][12] = -2,
+ [2][0][RTW89_WW][2][12] = 60,
+ [2][0][RTW89_WW][0][14] = -2,
+ [2][0][RTW89_WW][1][14] = -2,
+ [2][0][RTW89_WW][2][14] = 60,
+ [2][0][RTW89_WW][0][15] = -2,
+ [2][0][RTW89_WW][1][15] = -2,
+ [2][0][RTW89_WW][2][15] = 60,
+ [2][0][RTW89_WW][0][17] = -2,
+ [2][0][RTW89_WW][1][17] = -2,
+ [2][0][RTW89_WW][2][17] = 60,
+ [2][0][RTW89_WW][0][19] = -2,
+ [2][0][RTW89_WW][1][19] = -2,
+ [2][0][RTW89_WW][2][19] = 60,
+ [2][0][RTW89_WW][0][21] = -2,
+ [2][0][RTW89_WW][1][21] = -2,
+ [2][0][RTW89_WW][2][21] = 60,
+ [2][0][RTW89_WW][0][23] = -2,
+ [2][0][RTW89_WW][1][23] = -2,
+ [2][0][RTW89_WW][2][23] = 78,
+ [2][0][RTW89_WW][0][25] = -2,
+ [2][0][RTW89_WW][1][25] = -2,
+ [2][0][RTW89_WW][2][25] = 78,
+ [2][0][RTW89_WW][0][27] = -2,
+ [2][0][RTW89_WW][1][27] = -2,
+ [2][0][RTW89_WW][2][27] = 78,
+ [2][0][RTW89_WW][0][29] = -2,
+ [2][0][RTW89_WW][1][29] = -2,
+ [2][0][RTW89_WW][2][29] = 78,
+ [2][0][RTW89_WW][0][30] = -2,
+ [2][0][RTW89_WW][1][30] = -2,
+ [2][0][RTW89_WW][2][30] = 78,
+ [2][0][RTW89_WW][0][32] = -2,
+ [2][0][RTW89_WW][1][32] = -2,
+ [2][0][RTW89_WW][2][32] = 78,
+ [2][0][RTW89_WW][0][34] = -2,
+ [2][0][RTW89_WW][1][34] = -2,
+ [2][0][RTW89_WW][2][34] = 78,
+ [2][0][RTW89_WW][0][36] = -2,
+ [2][0][RTW89_WW][1][36] = -2,
+ [2][0][RTW89_WW][2][36] = 78,
+ [2][0][RTW89_WW][0][38] = -2,
+ [2][0][RTW89_WW][1][38] = -2,
+ [2][0][RTW89_WW][2][38] = 78,
+ [2][0][RTW89_WW][0][40] = -2,
+ [2][0][RTW89_WW][1][40] = -2,
+ [2][0][RTW89_WW][2][40] = 78,
+ [2][0][RTW89_WW][0][42] = -2,
+ [2][0][RTW89_WW][1][42] = -2,
+ [2][0][RTW89_WW][2][42] = 78,
+ [2][0][RTW89_WW][0][44] = -2,
+ [2][0][RTW89_WW][1][44] = -2,
+ [2][0][RTW89_WW][2][44] = 78,
+ [2][0][RTW89_WW][0][45] = -2,
+ [2][0][RTW89_WW][1][45] = -2,
+ [2][0][RTW89_WW][2][45] = 0,
+ [2][0][RTW89_WW][0][47] = -2,
+ [2][0][RTW89_WW][1][47] = -2,
+ [2][0][RTW89_WW][2][47] = 0,
+ [2][0][RTW89_WW][0][49] = -2,
+ [2][0][RTW89_WW][1][49] = -2,
+ [2][0][RTW89_WW][2][49] = 0,
+ [2][0][RTW89_WW][0][51] = -2,
+ [2][0][RTW89_WW][1][51] = -2,
+ [2][0][RTW89_WW][2][51] = 0,
+ [2][0][RTW89_WW][0][53] = -2,
+ [2][0][RTW89_WW][1][53] = -2,
+ [2][0][RTW89_WW][2][53] = 0,
+ [2][0][RTW89_WW][0][55] = -2,
+ [2][0][RTW89_WW][1][55] = -2,
+ [2][0][RTW89_WW][2][55] = 78,
+ [2][0][RTW89_WW][0][57] = -2,
+ [2][0][RTW89_WW][1][57] = -2,
+ [2][0][RTW89_WW][2][57] = 78,
+ [2][0][RTW89_WW][0][59] = -2,
+ [2][0][RTW89_WW][1][59] = -2,
+ [2][0][RTW89_WW][2][59] = 78,
+ [2][0][RTW89_WW][0][60] = -2,
+ [2][0][RTW89_WW][1][60] = -2,
+ [2][0][RTW89_WW][2][60] = 78,
+ [2][0][RTW89_WW][0][62] = -2,
+ [2][0][RTW89_WW][1][62] = -2,
+ [2][0][RTW89_WW][2][62] = 78,
+ [2][0][RTW89_WW][0][64] = -2,
+ [2][0][RTW89_WW][1][64] = -2,
+ [2][0][RTW89_WW][2][64] = 78,
+ [2][0][RTW89_WW][0][66] = -2,
+ [2][0][RTW89_WW][1][66] = -2,
+ [2][0][RTW89_WW][2][66] = 78,
+ [2][0][RTW89_WW][0][68] = -2,
+ [2][0][RTW89_WW][1][68] = -2,
+ [2][0][RTW89_WW][2][68] = 78,
+ [2][0][RTW89_WW][0][70] = -2,
+ [2][0][RTW89_WW][1][70] = -2,
+ [2][0][RTW89_WW][2][70] = 78,
+ [2][0][RTW89_WW][0][72] = -2,
+ [2][0][RTW89_WW][1][72] = -2,
+ [2][0][RTW89_WW][2][72] = 78,
+ [2][0][RTW89_WW][0][74] = -2,
+ [2][0][RTW89_WW][1][74] = -2,
+ [2][0][RTW89_WW][2][74] = 78,
+ [2][0][RTW89_WW][0][75] = -2,
+ [2][0][RTW89_WW][1][75] = -2,
+ [2][0][RTW89_WW][2][75] = 78,
+ [2][0][RTW89_WW][0][77] = -2,
+ [2][0][RTW89_WW][1][77] = -2,
+ [2][0][RTW89_WW][2][77] = 78,
+ [2][0][RTW89_WW][0][79] = -2,
+ [2][0][RTW89_WW][1][79] = -2,
+ [2][0][RTW89_WW][2][79] = 78,
+ [2][0][RTW89_WW][0][81] = -2,
+ [2][0][RTW89_WW][1][81] = -2,
+ [2][0][RTW89_WW][2][81] = 78,
+ [2][0][RTW89_WW][0][83] = -2,
+ [2][0][RTW89_WW][1][83] = -2,
+ [2][0][RTW89_WW][2][83] = 78,
+ [2][0][RTW89_WW][0][85] = -2,
+ [2][0][RTW89_WW][1][85] = -2,
+ [2][0][RTW89_WW][2][85] = 78,
+ [2][0][RTW89_WW][0][87] = -2,
+ [2][0][RTW89_WW][1][87] = -2,
+ [2][0][RTW89_WW][2][87] = 0,
+ [2][0][RTW89_WW][0][89] = -2,
+ [2][0][RTW89_WW][1][89] = -2,
+ [2][0][RTW89_WW][2][89] = 0,
+ [2][0][RTW89_WW][0][90] = -2,
+ [2][0][RTW89_WW][1][90] = -2,
+ [2][0][RTW89_WW][2][90] = 0,
+ [2][0][RTW89_WW][0][92] = -2,
+ [2][0][RTW89_WW][1][92] = -2,
+ [2][0][RTW89_WW][2][92] = 0,
+ [2][0][RTW89_WW][0][94] = -2,
+ [2][0][RTW89_WW][1][94] = -2,
+ [2][0][RTW89_WW][2][94] = 0,
+ [2][0][RTW89_WW][0][96] = -2,
+ [2][0][RTW89_WW][1][96] = -2,
+ [2][0][RTW89_WW][2][96] = 0,
+ [2][0][RTW89_WW][0][98] = -2,
+ [2][0][RTW89_WW][1][98] = -2,
+ [2][0][RTW89_WW][2][98] = 0,
+ [2][0][RTW89_WW][0][100] = -2,
+ [2][0][RTW89_WW][1][100] = -2,
+ [2][0][RTW89_WW][2][100] = 0,
+ [2][0][RTW89_WW][0][102] = -2,
+ [2][0][RTW89_WW][1][102] = -2,
+ [2][0][RTW89_WW][2][102] = 0,
+ [2][0][RTW89_WW][0][104] = -2,
+ [2][0][RTW89_WW][1][104] = -2,
+ [2][0][RTW89_WW][2][104] = 0,
+ [2][0][RTW89_WW][0][105] = -2,
+ [2][0][RTW89_WW][1][105] = -2,
+ [2][0][RTW89_WW][2][105] = 0,
+ [2][0][RTW89_WW][0][107] = -2,
+ [2][0][RTW89_WW][1][107] = -2,
+ [2][0][RTW89_WW][2][107] = 0,
+ [2][0][RTW89_WW][0][109] = 12,
+ [2][0][RTW89_WW][1][109] = 12,
+ [2][0][RTW89_WW][2][109] = 0,
+ [2][0][RTW89_WW][0][111] = 0,
+ [2][0][RTW89_WW][1][111] = 0,
+ [2][0][RTW89_WW][2][111] = 0,
+ [2][0][RTW89_WW][0][113] = 0,
+ [2][0][RTW89_WW][1][113] = 0,
+ [2][0][RTW89_WW][2][113] = 0,
+ [2][0][RTW89_WW][0][115] = 0,
+ [2][0][RTW89_WW][1][115] = 0,
+ [2][0][RTW89_WW][2][115] = 0,
+ [2][0][RTW89_WW][0][117] = 0,
+ [2][0][RTW89_WW][1][117] = 0,
+ [2][0][RTW89_WW][2][117] = 0,
+ [2][0][RTW89_WW][0][119] = 0,
+ [2][0][RTW89_WW][1][119] = 0,
+ [2][0][RTW89_WW][2][119] = 0,
+ [2][1][RTW89_WW][0][0] = -16,
+ [2][1][RTW89_WW][1][0] = -16,
+ [2][1][RTW89_WW][2][0] = 54,
+ [2][1][RTW89_WW][0][2] = -16,
+ [2][1][RTW89_WW][1][2] = -16,
+ [2][1][RTW89_WW][2][2] = 54,
+ [2][1][RTW89_WW][0][4] = -16,
+ [2][1][RTW89_WW][1][4] = -16,
+ [2][1][RTW89_WW][2][4] = 54,
+ [2][1][RTW89_WW][0][6] = -16,
+ [2][1][RTW89_WW][1][6] = -16,
+ [2][1][RTW89_WW][2][6] = 54,
+ [2][1][RTW89_WW][0][8] = -16,
+ [2][1][RTW89_WW][1][8] = -16,
+ [2][1][RTW89_WW][2][8] = 54,
+ [2][1][RTW89_WW][0][10] = -16,
+ [2][1][RTW89_WW][1][10] = -16,
+ [2][1][RTW89_WW][2][10] = 54,
+ [2][1][RTW89_WW][0][12] = -16,
+ [2][1][RTW89_WW][1][12] = -16,
+ [2][1][RTW89_WW][2][12] = 54,
+ [2][1][RTW89_WW][0][14] = -16,
+ [2][1][RTW89_WW][1][14] = -16,
+ [2][1][RTW89_WW][2][14] = 54,
+ [2][1][RTW89_WW][0][15] = -16,
+ [2][1][RTW89_WW][1][15] = -16,
+ [2][1][RTW89_WW][2][15] = 54,
+ [2][1][RTW89_WW][0][17] = -16,
+ [2][1][RTW89_WW][1][17] = -16,
+ [2][1][RTW89_WW][2][17] = 54,
+ [2][1][RTW89_WW][0][19] = -16,
+ [2][1][RTW89_WW][1][19] = -16,
+ [2][1][RTW89_WW][2][19] = 54,
+ [2][1][RTW89_WW][0][21] = -16,
+ [2][1][RTW89_WW][1][21] = -16,
+ [2][1][RTW89_WW][2][21] = 54,
+ [2][1][RTW89_WW][0][23] = -16,
+ [2][1][RTW89_WW][1][23] = -16,
+ [2][1][RTW89_WW][2][23] = 54,
+ [2][1][RTW89_WW][0][25] = -16,
+ [2][1][RTW89_WW][1][25] = -16,
+ [2][1][RTW89_WW][2][25] = 54,
+ [2][1][RTW89_WW][0][27] = -16,
+ [2][1][RTW89_WW][1][27] = -16,
+ [2][1][RTW89_WW][2][27] = 54,
+ [2][1][RTW89_WW][0][29] = -16,
+ [2][1][RTW89_WW][1][29] = -16,
+ [2][1][RTW89_WW][2][29] = 54,
+ [2][1][RTW89_WW][0][30] = -16,
+ [2][1][RTW89_WW][1][30] = -16,
+ [2][1][RTW89_WW][2][30] = 54,
+ [2][1][RTW89_WW][0][32] = -16,
+ [2][1][RTW89_WW][1][32] = -16,
+ [2][1][RTW89_WW][2][32] = 54,
+ [2][1][RTW89_WW][0][34] = -16,
+ [2][1][RTW89_WW][1][34] = -16,
+ [2][1][RTW89_WW][2][34] = 54,
+ [2][1][RTW89_WW][0][36] = -16,
+ [2][1][RTW89_WW][1][36] = -16,
+ [2][1][RTW89_WW][2][36] = 54,
+ [2][1][RTW89_WW][0][38] = -16,
+ [2][1][RTW89_WW][1][38] = -16,
+ [2][1][RTW89_WW][2][38] = 54,
+ [2][1][RTW89_WW][0][40] = -16,
+ [2][1][RTW89_WW][1][40] = -16,
+ [2][1][RTW89_WW][2][40] = 54,
+ [2][1][RTW89_WW][0][42] = -16,
+ [2][1][RTW89_WW][1][42] = -16,
+ [2][1][RTW89_WW][2][42] = 54,
+ [2][1][RTW89_WW][0][44] = -16,
+ [2][1][RTW89_WW][1][44] = -16,
+ [2][1][RTW89_WW][2][44] = 54,
+ [2][1][RTW89_WW][0][45] = -16,
+ [2][1][RTW89_WW][1][45] = -16,
+ [2][1][RTW89_WW][2][45] = 0,
+ [2][1][RTW89_WW][0][47] = -16,
+ [2][1][RTW89_WW][1][47] = -16,
+ [2][1][RTW89_WW][2][47] = 0,
+ [2][1][RTW89_WW][0][49] = -16,
+ [2][1][RTW89_WW][1][49] = -16,
+ [2][1][RTW89_WW][2][49] = 0,
+ [2][1][RTW89_WW][0][51] = -16,
+ [2][1][RTW89_WW][1][51] = -16,
+ [2][1][RTW89_WW][2][51] = 0,
+ [2][1][RTW89_WW][0][53] = -16,
+ [2][1][RTW89_WW][1][53] = -16,
+ [2][1][RTW89_WW][2][53] = 0,
+ [2][1][RTW89_WW][0][55] = -16,
+ [2][1][RTW89_WW][1][55] = -16,
+ [2][1][RTW89_WW][2][55] = 54,
+ [2][1][RTW89_WW][0][57] = -16,
+ [2][1][RTW89_WW][1][57] = -16,
+ [2][1][RTW89_WW][2][57] = 54,
+ [2][1][RTW89_WW][0][59] = -16,
+ [2][1][RTW89_WW][1][59] = -16,
+ [2][1][RTW89_WW][2][59] = 54,
+ [2][1][RTW89_WW][0][60] = -16,
+ [2][1][RTW89_WW][1][60] = -16,
+ [2][1][RTW89_WW][2][60] = 54,
+ [2][1][RTW89_WW][0][62] = -16,
+ [2][1][RTW89_WW][1][62] = -16,
+ [2][1][RTW89_WW][2][62] = 54,
+ [2][1][RTW89_WW][0][64] = -16,
+ [2][1][RTW89_WW][1][64] = -16,
+ [2][1][RTW89_WW][2][64] = 54,
+ [2][1][RTW89_WW][0][66] = -16,
+ [2][1][RTW89_WW][1][66] = -16,
+ [2][1][RTW89_WW][2][66] = 54,
+ [2][1][RTW89_WW][0][68] = -16,
+ [2][1][RTW89_WW][1][68] = -16,
+ [2][1][RTW89_WW][2][68] = 54,
+ [2][1][RTW89_WW][0][70] = -16,
+ [2][1][RTW89_WW][1][70] = -16,
+ [2][1][RTW89_WW][2][70] = 56,
+ [2][1][RTW89_WW][0][72] = -16,
+ [2][1][RTW89_WW][1][72] = -16,
+ [2][1][RTW89_WW][2][72] = 56,
+ [2][1][RTW89_WW][0][74] = -16,
+ [2][1][RTW89_WW][1][74] = -16,
+ [2][1][RTW89_WW][2][74] = 56,
+ [2][1][RTW89_WW][0][75] = -16,
+ [2][1][RTW89_WW][1][75] = -16,
+ [2][1][RTW89_WW][2][75] = 56,
+ [2][1][RTW89_WW][0][77] = -16,
+ [2][1][RTW89_WW][1][77] = -16,
+ [2][1][RTW89_WW][2][77] = 56,
+ [2][1][RTW89_WW][0][79] = -16,
+ [2][1][RTW89_WW][1][79] = -16,
+ [2][1][RTW89_WW][2][79] = 56,
+ [2][1][RTW89_WW][0][81] = -16,
+ [2][1][RTW89_WW][1][81] = -16,
+ [2][1][RTW89_WW][2][81] = 56,
+ [2][1][RTW89_WW][0][83] = -16,
+ [2][1][RTW89_WW][1][83] = -16,
+ [2][1][RTW89_WW][2][83] = 56,
+ [2][1][RTW89_WW][0][85] = -18,
+ [2][1][RTW89_WW][1][85] = -18,
+ [2][1][RTW89_WW][2][85] = 56,
+ [2][1][RTW89_WW][0][87] = -16,
+ [2][1][RTW89_WW][1][87] = -16,
+ [2][1][RTW89_WW][2][87] = 0,
+ [2][1][RTW89_WW][0][89] = -16,
+ [2][1][RTW89_WW][1][89] = -16,
+ [2][1][RTW89_WW][2][89] = 0,
+ [2][1][RTW89_WW][0][90] = -16,
+ [2][1][RTW89_WW][1][90] = -16,
+ [2][1][RTW89_WW][2][90] = 0,
+ [2][1][RTW89_WW][0][92] = -16,
+ [2][1][RTW89_WW][1][92] = -16,
+ [2][1][RTW89_WW][2][92] = 0,
+ [2][1][RTW89_WW][0][94] = -16,
+ [2][1][RTW89_WW][1][94] = -16,
+ [2][1][RTW89_WW][2][94] = 0,
+ [2][1][RTW89_WW][0][96] = -16,
+ [2][1][RTW89_WW][1][96] = -16,
+ [2][1][RTW89_WW][2][96] = 0,
+ [2][1][RTW89_WW][0][98] = -16,
+ [2][1][RTW89_WW][1][98] = -16,
+ [2][1][RTW89_WW][2][98] = 0,
+ [2][1][RTW89_WW][0][100] = -16,
+ [2][1][RTW89_WW][1][100] = -16,
+ [2][1][RTW89_WW][2][100] = 0,
+ [2][1][RTW89_WW][0][102] = -16,
+ [2][1][RTW89_WW][1][102] = -16,
+ [2][1][RTW89_WW][2][102] = 0,
+ [2][1][RTW89_WW][0][104] = -16,
+ [2][1][RTW89_WW][1][104] = -16,
+ [2][1][RTW89_WW][2][104] = 0,
+ [2][1][RTW89_WW][0][105] = -16,
+ [2][1][RTW89_WW][1][105] = -16,
+ [2][1][RTW89_WW][2][105] = 0,
+ [2][1][RTW89_WW][0][107] = -14,
+ [2][1][RTW89_WW][1][107] = -14,
+ [2][1][RTW89_WW][2][107] = 0,
+ [2][1][RTW89_WW][0][109] = -10,
+ [2][1][RTW89_WW][1][109] = -10,
+ [2][1][RTW89_WW][2][109] = 0,
+ [2][1][RTW89_WW][0][111] = 0,
+ [2][1][RTW89_WW][1][111] = 0,
+ [2][1][RTW89_WW][2][111] = 0,
+ [2][1][RTW89_WW][0][113] = 0,
+ [2][1][RTW89_WW][1][113] = 0,
+ [2][1][RTW89_WW][2][113] = 0,
+ [2][1][RTW89_WW][0][115] = 0,
+ [2][1][RTW89_WW][1][115] = 0,
+ [2][1][RTW89_WW][2][115] = 0,
+ [2][1][RTW89_WW][0][117] = 0,
+ [2][1][RTW89_WW][1][117] = 0,
+ [2][1][RTW89_WW][2][117] = 0,
+ [2][1][RTW89_WW][0][119] = 0,
+ [2][1][RTW89_WW][1][119] = 0,
+ [2][1][RTW89_WW][2][119] = 0,
+ [0][0][RTW89_FCC][1][0] = -16,
+ [0][0][RTW89_FCC][2][0] = 44,
+ [0][0][RTW89_ETSI][1][0] = 32,
+ [0][0][RTW89_ETSI][0][0] = -8,
+ [0][0][RTW89_MKK][1][0] = 30,
+ [0][0][RTW89_MKK][0][0] = -8,
+ [0][0][RTW89_IC][1][0] = -16,
+ [0][0][RTW89_KCC][1][0] = -2,
+ [0][0][RTW89_KCC][0][0] = -2,
+ [0][0][RTW89_ACMA][1][0] = 32,
+ [0][0][RTW89_ACMA][0][0] = -8,
+ [0][0][RTW89_CHILE][1][0] = -16,
+ [0][0][RTW89_QATAR][1][0] = 32,
+ [0][0][RTW89_QATAR][0][0] = -8,
+ [0][0][RTW89_UK][1][0] = 32,
+ [0][0][RTW89_UK][0][0] = -8,
+ [0][0][RTW89_FCC][1][2] = -18,
+ [0][0][RTW89_FCC][2][2] = 44,
+ [0][0][RTW89_ETSI][1][2] = 32,
+ [0][0][RTW89_ETSI][0][2] = -8,
+ [0][0][RTW89_MKK][1][2] = 30,
+ [0][0][RTW89_MKK][0][2] = -8,
+ [0][0][RTW89_IC][1][2] = -18,
+ [0][0][RTW89_KCC][1][2] = -2,
+ [0][0][RTW89_KCC][0][2] = -2,
+ [0][0][RTW89_ACMA][1][2] = 32,
+ [0][0][RTW89_ACMA][0][2] = -8,
+ [0][0][RTW89_CHILE][1][2] = -18,
+ [0][0][RTW89_QATAR][1][2] = 32,
+ [0][0][RTW89_QATAR][0][2] = -8,
+ [0][0][RTW89_UK][1][2] = 32,
+ [0][0][RTW89_UK][0][2] = -8,
+ [0][0][RTW89_FCC][1][4] = -18,
+ [0][0][RTW89_FCC][2][4] = 44,
+ [0][0][RTW89_ETSI][1][4] = 32,
+ [0][0][RTW89_ETSI][0][4] = -8,
+ [0][0][RTW89_MKK][1][4] = 30,
+ [0][0][RTW89_MKK][0][4] = -8,
+ [0][0][RTW89_IC][1][4] = -18,
+ [0][0][RTW89_KCC][1][4] = -2,
+ [0][0][RTW89_KCC][0][4] = -2,
+ [0][0][RTW89_ACMA][1][4] = 32,
+ [0][0][RTW89_ACMA][0][4] = -8,
+ [0][0][RTW89_CHILE][1][4] = -18,
+ [0][0][RTW89_QATAR][1][4] = 32,
+ [0][0][RTW89_QATAR][0][4] = -8,
+ [0][0][RTW89_UK][1][4] = 32,
+ [0][0][RTW89_UK][0][4] = -8,
+ [0][0][RTW89_FCC][1][6] = -18,
+ [0][0][RTW89_FCC][2][6] = 44,
+ [0][0][RTW89_ETSI][1][6] = 32,
+ [0][0][RTW89_ETSI][0][6] = -8,
+ [0][0][RTW89_MKK][1][6] = 30,
+ [0][0][RTW89_MKK][0][6] = -8,
+ [0][0][RTW89_IC][1][6] = -18,
+ [0][0][RTW89_KCC][1][6] = -2,
+ [0][0][RTW89_KCC][0][6] = -2,
+ [0][0][RTW89_ACMA][1][6] = 32,
+ [0][0][RTW89_ACMA][0][6] = -8,
+ [0][0][RTW89_CHILE][1][6] = -18,
+ [0][0][RTW89_QATAR][1][6] = 32,
+ [0][0][RTW89_QATAR][0][6] = -8,
+ [0][0][RTW89_UK][1][6] = 32,
+ [0][0][RTW89_UK][0][6] = -8,
+ [0][0][RTW89_FCC][1][8] = -18,
+ [0][0][RTW89_FCC][2][8] = 44,
+ [0][0][RTW89_ETSI][1][8] = 32,
+ [0][0][RTW89_ETSI][0][8] = -8,
+ [0][0][RTW89_MKK][1][8] = 30,
+ [0][0][RTW89_MKK][0][8] = -8,
+ [0][0][RTW89_IC][1][8] = -18,
+ [0][0][RTW89_KCC][1][8] = -2,
+ [0][0][RTW89_KCC][0][8] = -2,
+ [0][0][RTW89_ACMA][1][8] = 32,
+ [0][0][RTW89_ACMA][0][8] = -8,
+ [0][0][RTW89_CHILE][1][8] = -18,
+ [0][0][RTW89_QATAR][1][8] = 32,
+ [0][0][RTW89_QATAR][0][8] = -8,
+ [0][0][RTW89_UK][1][8] = 32,
+ [0][0][RTW89_UK][0][8] = -8,
+ [0][0][RTW89_FCC][1][10] = -18,
+ [0][0][RTW89_FCC][2][10] = 44,
+ [0][0][RTW89_ETSI][1][10] = 32,
+ [0][0][RTW89_ETSI][0][10] = -8,
+ [0][0][RTW89_MKK][1][10] = 30,
+ [0][0][RTW89_MKK][0][10] = -8,
+ [0][0][RTW89_IC][1][10] = -18,
+ [0][0][RTW89_KCC][1][10] = -2,
+ [0][0][RTW89_KCC][0][10] = -2,
+ [0][0][RTW89_ACMA][1][10] = 32,
+ [0][0][RTW89_ACMA][0][10] = -8,
+ [0][0][RTW89_CHILE][1][10] = -18,
+ [0][0][RTW89_QATAR][1][10] = 32,
+ [0][0][RTW89_QATAR][0][10] = -8,
+ [0][0][RTW89_UK][1][10] = 32,
+ [0][0][RTW89_UK][0][10] = -8,
+ [0][0][RTW89_FCC][1][12] = -18,
+ [0][0][RTW89_FCC][2][12] = 44,
+ [0][0][RTW89_ETSI][1][12] = 32,
+ [0][0][RTW89_ETSI][0][12] = -8,
+ [0][0][RTW89_MKK][1][12] = 30,
+ [0][0][RTW89_MKK][0][12] = -8,
+ [0][0][RTW89_IC][1][12] = -18,
+ [0][0][RTW89_KCC][1][12] = -2,
+ [0][0][RTW89_KCC][0][12] = -2,
+ [0][0][RTW89_ACMA][1][12] = 32,
+ [0][0][RTW89_ACMA][0][12] = -8,
+ [0][0][RTW89_CHILE][1][12] = -18,
+ [0][0][RTW89_QATAR][1][12] = 32,
+ [0][0][RTW89_QATAR][0][12] = -8,
+ [0][0][RTW89_UK][1][12] = 32,
+ [0][0][RTW89_UK][0][12] = -8,
+ [0][0][RTW89_FCC][1][14] = -18,
+ [0][0][RTW89_FCC][2][14] = 44,
+ [0][0][RTW89_ETSI][1][14] = 32,
+ [0][0][RTW89_ETSI][0][14] = -8,
+ [0][0][RTW89_MKK][1][14] = 30,
+ [0][0][RTW89_MKK][0][14] = -8,
+ [0][0][RTW89_IC][1][14] = -18,
+ [0][0][RTW89_KCC][1][14] = -2,
+ [0][0][RTW89_KCC][0][14] = -2,
+ [0][0][RTW89_ACMA][1][14] = 32,
+ [0][0][RTW89_ACMA][0][14] = -8,
+ [0][0][RTW89_CHILE][1][14] = -18,
+ [0][0][RTW89_QATAR][1][14] = 32,
+ [0][0][RTW89_QATAR][0][14] = -8,
+ [0][0][RTW89_UK][1][14] = 32,
+ [0][0][RTW89_UK][0][14] = -8,
+ [0][0][RTW89_FCC][1][15] = -18,
+ [0][0][RTW89_FCC][2][15] = 44,
+ [0][0][RTW89_ETSI][1][15] = 32,
+ [0][0][RTW89_ETSI][0][15] = -8,
+ [0][0][RTW89_MKK][1][15] = 30,
+ [0][0][RTW89_MKK][0][15] = -8,
+ [0][0][RTW89_IC][1][15] = -18,
+ [0][0][RTW89_KCC][1][15] = -2,
+ [0][0][RTW89_KCC][0][15] = -2,
+ [0][0][RTW89_ACMA][1][15] = 32,
+ [0][0][RTW89_ACMA][0][15] = -8,
+ [0][0][RTW89_CHILE][1][15] = -18,
+ [0][0][RTW89_QATAR][1][15] = 32,
+ [0][0][RTW89_QATAR][0][15] = -8,
+ [0][0][RTW89_UK][1][15] = 32,
+ [0][0][RTW89_UK][0][15] = -8,
+ [0][0][RTW89_FCC][1][17] = -18,
+ [0][0][RTW89_FCC][2][17] = 44,
+ [0][0][RTW89_ETSI][1][17] = 32,
+ [0][0][RTW89_ETSI][0][17] = -8,
+ [0][0][RTW89_MKK][1][17] = 30,
+ [0][0][RTW89_MKK][0][17] = -8,
+ [0][0][RTW89_IC][1][17] = -18,
+ [0][0][RTW89_KCC][1][17] = -2,
+ [0][0][RTW89_KCC][0][17] = -2,
+ [0][0][RTW89_ACMA][1][17] = 32,
+ [0][0][RTW89_ACMA][0][17] = -8,
+ [0][0][RTW89_CHILE][1][17] = -18,
+ [0][0][RTW89_QATAR][1][17] = 32,
+ [0][0][RTW89_QATAR][0][17] = -8,
+ [0][0][RTW89_UK][1][17] = 32,
+ [0][0][RTW89_UK][0][17] = -8,
+ [0][0][RTW89_FCC][1][19] = -18,
+ [0][0][RTW89_FCC][2][19] = 44,
+ [0][0][RTW89_ETSI][1][19] = 32,
+ [0][0][RTW89_ETSI][0][19] = -8,
+ [0][0][RTW89_MKK][1][19] = 30,
+ [0][0][RTW89_MKK][0][19] = -8,
+ [0][0][RTW89_IC][1][19] = -18,
+ [0][0][RTW89_KCC][1][19] = -2,
+ [0][0][RTW89_KCC][0][19] = -2,
+ [0][0][RTW89_ACMA][1][19] = 32,
+ [0][0][RTW89_ACMA][0][19] = -8,
+ [0][0][RTW89_CHILE][1][19] = -18,
+ [0][0][RTW89_QATAR][1][19] = 32,
+ [0][0][RTW89_QATAR][0][19] = -8,
+ [0][0][RTW89_UK][1][19] = 32,
+ [0][0][RTW89_UK][0][19] = -8,
+ [0][0][RTW89_FCC][1][21] = -18,
+ [0][0][RTW89_FCC][2][21] = 44,
+ [0][0][RTW89_ETSI][1][21] = 32,
+ [0][0][RTW89_ETSI][0][21] = -8,
+ [0][0][RTW89_MKK][1][21] = 30,
+ [0][0][RTW89_MKK][0][21] = -8,
+ [0][0][RTW89_IC][1][21] = -18,
+ [0][0][RTW89_KCC][1][21] = -2,
+ [0][0][RTW89_KCC][0][21] = -2,
+ [0][0][RTW89_ACMA][1][21] = 32,
+ [0][0][RTW89_ACMA][0][21] = -8,
+ [0][0][RTW89_CHILE][1][21] = -18,
+ [0][0][RTW89_QATAR][1][21] = 32,
+ [0][0][RTW89_QATAR][0][21] = -8,
+ [0][0][RTW89_UK][1][21] = 32,
+ [0][0][RTW89_UK][0][21] = -8,
+ [0][0][RTW89_FCC][1][23] = -18,
+ [0][0][RTW89_FCC][2][23] = 54,
+ [0][0][RTW89_ETSI][1][23] = 32,
+ [0][0][RTW89_ETSI][0][23] = -8,
+ [0][0][RTW89_MKK][1][23] = 30,
+ [0][0][RTW89_MKK][0][23] = -8,
+ [0][0][RTW89_IC][1][23] = -18,
+ [0][0][RTW89_KCC][1][23] = -2,
+ [0][0][RTW89_KCC][0][23] = -2,
+ [0][0][RTW89_ACMA][1][23] = 32,
+ [0][0][RTW89_ACMA][0][23] = -8,
+ [0][0][RTW89_CHILE][1][23] = -18,
+ [0][0][RTW89_QATAR][1][23] = 32,
+ [0][0][RTW89_QATAR][0][23] = -8,
+ [0][0][RTW89_UK][1][23] = 32,
+ [0][0][RTW89_UK][0][23] = -8,
+ [0][0][RTW89_FCC][1][25] = -18,
+ [0][0][RTW89_FCC][2][25] = 54,
+ [0][0][RTW89_ETSI][1][25] = 32,
+ [0][0][RTW89_ETSI][0][25] = -8,
+ [0][0][RTW89_MKK][1][25] = 30,
+ [0][0][RTW89_MKK][0][25] = -8,
+ [0][0][RTW89_IC][1][25] = -18,
+ [0][0][RTW89_KCC][1][25] = -2,
+ [0][0][RTW89_KCC][0][25] = -2,
+ [0][0][RTW89_ACMA][1][25] = 32,
+ [0][0][RTW89_ACMA][0][25] = -8,
+ [0][0][RTW89_CHILE][1][25] = -18,
+ [0][0][RTW89_QATAR][1][25] = 32,
+ [0][0][RTW89_QATAR][0][25] = -8,
+ [0][0][RTW89_UK][1][25] = 32,
+ [0][0][RTW89_UK][0][25] = -8,
+ [0][0][RTW89_FCC][1][27] = -18,
+ [0][0][RTW89_FCC][2][27] = 54,
+ [0][0][RTW89_ETSI][1][27] = 32,
+ [0][0][RTW89_ETSI][0][27] = -8,
+ [0][0][RTW89_MKK][1][27] = 30,
+ [0][0][RTW89_MKK][0][27] = -8,
+ [0][0][RTW89_IC][1][27] = -18,
+ [0][0][RTW89_KCC][1][27] = -2,
+ [0][0][RTW89_KCC][0][27] = -2,
+ [0][0][RTW89_ACMA][1][27] = 32,
+ [0][0][RTW89_ACMA][0][27] = -8,
+ [0][0][RTW89_CHILE][1][27] = -18,
+ [0][0][RTW89_QATAR][1][27] = 32,
+ [0][0][RTW89_QATAR][0][27] = -8,
+ [0][0][RTW89_UK][1][27] = 32,
+ [0][0][RTW89_UK][0][27] = -8,
+ [0][0][RTW89_FCC][1][29] = -18,
+ [0][0][RTW89_FCC][2][29] = 54,
+ [0][0][RTW89_ETSI][1][29] = 32,
+ [0][0][RTW89_ETSI][0][29] = -8,
+ [0][0][RTW89_MKK][1][29] = 30,
+ [0][0][RTW89_MKK][0][29] = -8,
+ [0][0][RTW89_IC][1][29] = -18,
+ [0][0][RTW89_KCC][1][29] = -2,
+ [0][0][RTW89_KCC][0][29] = -2,
+ [0][0][RTW89_ACMA][1][29] = 32,
+ [0][0][RTW89_ACMA][0][29] = -8,
+ [0][0][RTW89_CHILE][1][29] = -18,
+ [0][0][RTW89_QATAR][1][29] = 32,
+ [0][0][RTW89_QATAR][0][29] = -8,
+ [0][0][RTW89_UK][1][29] = 32,
+ [0][0][RTW89_UK][0][29] = -8,
+ [0][0][RTW89_FCC][1][30] = -18,
+ [0][0][RTW89_FCC][2][30] = 54,
+ [0][0][RTW89_ETSI][1][30] = 32,
+ [0][0][RTW89_ETSI][0][30] = -8,
+ [0][0][RTW89_MKK][1][30] = 30,
+ [0][0][RTW89_MKK][0][30] = -8,
+ [0][0][RTW89_IC][1][30] = -18,
+ [0][0][RTW89_KCC][1][30] = -2,
+ [0][0][RTW89_KCC][0][30] = -2,
+ [0][0][RTW89_ACMA][1][30] = 32,
+ [0][0][RTW89_ACMA][0][30] = -8,
+ [0][0][RTW89_CHILE][1][30] = -18,
+ [0][0][RTW89_QATAR][1][30] = 32,
+ [0][0][RTW89_QATAR][0][30] = -8,
+ [0][0][RTW89_UK][1][30] = 32,
+ [0][0][RTW89_UK][0][30] = -8,
+ [0][0][RTW89_FCC][1][32] = -18,
+ [0][0][RTW89_FCC][2][32] = 54,
+ [0][0][RTW89_ETSI][1][32] = 32,
+ [0][0][RTW89_ETSI][0][32] = -8,
+ [0][0][RTW89_MKK][1][32] = 30,
+ [0][0][RTW89_MKK][0][32] = -8,
+ [0][0][RTW89_IC][1][32] = -18,
+ [0][0][RTW89_KCC][1][32] = -2,
+ [0][0][RTW89_KCC][0][32] = -2,
+ [0][0][RTW89_ACMA][1][32] = 32,
+ [0][0][RTW89_ACMA][0][32] = -8,
+ [0][0][RTW89_CHILE][1][32] = -18,
+ [0][0][RTW89_QATAR][1][32] = 32,
+ [0][0][RTW89_QATAR][0][32] = -8,
+ [0][0][RTW89_UK][1][32] = 32,
+ [0][0][RTW89_UK][0][32] = -8,
+ [0][0][RTW89_FCC][1][34] = -18,
+ [0][0][RTW89_FCC][2][34] = 54,
+ [0][0][RTW89_ETSI][1][34] = 32,
+ [0][0][RTW89_ETSI][0][34] = -8,
+ [0][0][RTW89_MKK][1][34] = 30,
+ [0][0][RTW89_MKK][0][34] = -8,
+ [0][0][RTW89_IC][1][34] = -18,
+ [0][0][RTW89_KCC][1][34] = -2,
+ [0][0][RTW89_KCC][0][34] = -2,
+ [0][0][RTW89_ACMA][1][34] = 32,
+ [0][0][RTW89_ACMA][0][34] = -8,
+ [0][0][RTW89_CHILE][1][34] = -18,
+ [0][0][RTW89_QATAR][1][34] = 32,
+ [0][0][RTW89_QATAR][0][34] = -8,
+ [0][0][RTW89_UK][1][34] = 32,
+ [0][0][RTW89_UK][0][34] = -8,
+ [0][0][RTW89_FCC][1][36] = -18,
+ [0][0][RTW89_FCC][2][36] = 54,
+ [0][0][RTW89_ETSI][1][36] = 32,
+ [0][0][RTW89_ETSI][0][36] = -8,
+ [0][0][RTW89_MKK][1][36] = 30,
+ [0][0][RTW89_MKK][0][36] = -8,
+ [0][0][RTW89_IC][1][36] = -18,
+ [0][0][RTW89_KCC][1][36] = -2,
+ [0][0][RTW89_KCC][0][36] = -2,
+ [0][0][RTW89_ACMA][1][36] = 32,
+ [0][0][RTW89_ACMA][0][36] = -8,
+ [0][0][RTW89_CHILE][1][36] = -18,
+ [0][0][RTW89_QATAR][1][36] = 32,
+ [0][0][RTW89_QATAR][0][36] = -8,
+ [0][0][RTW89_UK][1][36] = 32,
+ [0][0][RTW89_UK][0][36] = -8,
+ [0][0][RTW89_FCC][1][38] = -18,
+ [0][0][RTW89_FCC][2][38] = 54,
+ [0][0][RTW89_ETSI][1][38] = 32,
+ [0][0][RTW89_ETSI][0][38] = -8,
+ [0][0][RTW89_MKK][1][38] = 30,
+ [0][0][RTW89_MKK][0][38] = -8,
+ [0][0][RTW89_IC][1][38] = -18,
+ [0][0][RTW89_KCC][1][38] = -2,
+ [0][0][RTW89_KCC][0][38] = -2,
+ [0][0][RTW89_ACMA][1][38] = 32,
+ [0][0][RTW89_ACMA][0][38] = -8,
+ [0][0][RTW89_CHILE][1][38] = -18,
+ [0][0][RTW89_QATAR][1][38] = 32,
+ [0][0][RTW89_QATAR][0][38] = -8,
+ [0][0][RTW89_UK][1][38] = 32,
+ [0][0][RTW89_UK][0][38] = -8,
+ [0][0][RTW89_FCC][1][40] = -18,
+ [0][0][RTW89_FCC][2][40] = 54,
+ [0][0][RTW89_ETSI][1][40] = 32,
+ [0][0][RTW89_ETSI][0][40] = -8,
+ [0][0][RTW89_MKK][1][40] = 30,
+ [0][0][RTW89_MKK][0][40] = -8,
+ [0][0][RTW89_IC][1][40] = -18,
+ [0][0][RTW89_KCC][1][40] = -2,
+ [0][0][RTW89_KCC][0][40] = -2,
+ [0][0][RTW89_ACMA][1][40] = 32,
+ [0][0][RTW89_ACMA][0][40] = -8,
+ [0][0][RTW89_CHILE][1][40] = -18,
+ [0][0][RTW89_QATAR][1][40] = 32,
+ [0][0][RTW89_QATAR][0][40] = -8,
+ [0][0][RTW89_UK][1][40] = 32,
+ [0][0][RTW89_UK][0][40] = -8,
+ [0][0][RTW89_FCC][1][42] = -18,
+ [0][0][RTW89_FCC][2][42] = 54,
+ [0][0][RTW89_ETSI][1][42] = 32,
+ [0][0][RTW89_ETSI][0][42] = -8,
+ [0][0][RTW89_MKK][1][42] = 30,
+ [0][0][RTW89_MKK][0][42] = -8,
+ [0][0][RTW89_IC][1][42] = -18,
+ [0][0][RTW89_KCC][1][42] = -2,
+ [0][0][RTW89_KCC][0][42] = -2,
+ [0][0][RTW89_ACMA][1][42] = 32,
+ [0][0][RTW89_ACMA][0][42] = -8,
+ [0][0][RTW89_CHILE][1][42] = -18,
+ [0][0][RTW89_QATAR][1][42] = 32,
+ [0][0][RTW89_QATAR][0][42] = -8,
+ [0][0][RTW89_UK][1][42] = 32,
+ [0][0][RTW89_UK][0][42] = -8,
+ [0][0][RTW89_FCC][1][44] = -16,
+ [0][0][RTW89_FCC][2][44] = 56,
+ [0][0][RTW89_ETSI][1][44] = 32,
+ [0][0][RTW89_ETSI][0][44] = -6,
+ [0][0][RTW89_MKK][1][44] = 8,
+ [0][0][RTW89_MKK][0][44] = -10,
+ [0][0][RTW89_IC][1][44] = -16,
+ [0][0][RTW89_KCC][1][44] = -2,
+ [0][0][RTW89_KCC][0][44] = -2,
+ [0][0][RTW89_ACMA][1][44] = 32,
+ [0][0][RTW89_ACMA][0][44] = -6,
+ [0][0][RTW89_CHILE][1][44] = -16,
+ [0][0][RTW89_QATAR][1][44] = 32,
+ [0][0][RTW89_QATAR][0][44] = -6,
+ [0][0][RTW89_UK][1][44] = 32,
+ [0][0][RTW89_UK][0][44] = -6,
+ [0][0][RTW89_FCC][1][45] = -16,
+ [0][0][RTW89_FCC][2][45] = 127,
+ [0][0][RTW89_ETSI][1][45] = 127,
+ [0][0][RTW89_ETSI][0][45] = 127,
+ [0][0][RTW89_MKK][1][45] = 127,
+ [0][0][RTW89_MKK][0][45] = 127,
+ [0][0][RTW89_IC][1][45] = -16,
+ [0][0][RTW89_KCC][1][45] = -2,
+ [0][0][RTW89_KCC][0][45] = 127,
+ [0][0][RTW89_ACMA][1][45] = 127,
+ [0][0][RTW89_ACMA][0][45] = 127,
+ [0][0][RTW89_CHILE][1][45] = 127,
+ [0][0][RTW89_QATAR][1][45] = 127,
+ [0][0][RTW89_QATAR][0][45] = 127,
+ [0][0][RTW89_UK][1][45] = 127,
+ [0][0][RTW89_UK][0][45] = 127,
+ [0][0][RTW89_FCC][1][47] = -18,
+ [0][0][RTW89_FCC][2][47] = 127,
+ [0][0][RTW89_ETSI][1][47] = 127,
+ [0][0][RTW89_ETSI][0][47] = 127,
+ [0][0][RTW89_MKK][1][47] = 127,
+ [0][0][RTW89_MKK][0][47] = 127,
+ [0][0][RTW89_IC][1][47] = -18,
+ [0][0][RTW89_KCC][1][47] = -2,
+ [0][0][RTW89_KCC][0][47] = 127,
+ [0][0][RTW89_ACMA][1][47] = 127,
+ [0][0][RTW89_ACMA][0][47] = 127,
+ [0][0][RTW89_CHILE][1][47] = 127,
+ [0][0][RTW89_QATAR][1][47] = 127,
+ [0][0][RTW89_QATAR][0][47] = 127,
+ [0][0][RTW89_UK][1][47] = 127,
+ [0][0][RTW89_UK][0][47] = 127,
+ [0][0][RTW89_FCC][1][49] = -18,
+ [0][0][RTW89_FCC][2][49] = 127,
+ [0][0][RTW89_ETSI][1][49] = 127,
+ [0][0][RTW89_ETSI][0][49] = 127,
+ [0][0][RTW89_MKK][1][49] = 127,
+ [0][0][RTW89_MKK][0][49] = 127,
+ [0][0][RTW89_IC][1][49] = -18,
+ [0][0][RTW89_KCC][1][49] = -2,
+ [0][0][RTW89_KCC][0][49] = 127,
+ [0][0][RTW89_ACMA][1][49] = 127,
+ [0][0][RTW89_ACMA][0][49] = 127,
+ [0][0][RTW89_CHILE][1][49] = 127,
+ [0][0][RTW89_QATAR][1][49] = 127,
+ [0][0][RTW89_QATAR][0][49] = 127,
+ [0][0][RTW89_UK][1][49] = 127,
+ [0][0][RTW89_UK][0][49] = 127,
+ [0][0][RTW89_FCC][1][51] = -18,
+ [0][0][RTW89_FCC][2][51] = 127,
+ [0][0][RTW89_ETSI][1][51] = 127,
+ [0][0][RTW89_ETSI][0][51] = 127,
+ [0][0][RTW89_MKK][1][51] = 127,
+ [0][0][RTW89_MKK][0][51] = 127,
+ [0][0][RTW89_IC][1][51] = -18,
+ [0][0][RTW89_KCC][1][51] = -2,
+ [0][0][RTW89_KCC][0][51] = 127,
+ [0][0][RTW89_ACMA][1][51] = 127,
+ [0][0][RTW89_ACMA][0][51] = 127,
+ [0][0][RTW89_CHILE][1][51] = 127,
+ [0][0][RTW89_QATAR][1][51] = 127,
+ [0][0][RTW89_QATAR][0][51] = 127,
+ [0][0][RTW89_UK][1][51] = 127,
+ [0][0][RTW89_UK][0][51] = 127,
+ [0][0][RTW89_FCC][1][53] = -16,
+ [0][0][RTW89_FCC][2][53] = 127,
+ [0][0][RTW89_ETSI][1][53] = 127,
+ [0][0][RTW89_ETSI][0][53] = 127,
+ [0][0][RTW89_MKK][1][53] = 127,
+ [0][0][RTW89_MKK][0][53] = 127,
+ [0][0][RTW89_IC][1][53] = -16,
+ [0][0][RTW89_KCC][1][53] = -2,
+ [0][0][RTW89_KCC][0][53] = 127,
+ [0][0][RTW89_ACMA][1][53] = 127,
+ [0][0][RTW89_ACMA][0][53] = 127,
+ [0][0][RTW89_CHILE][1][53] = 127,
+ [0][0][RTW89_QATAR][1][53] = 127,
+ [0][0][RTW89_QATAR][0][53] = 127,
+ [0][0][RTW89_UK][1][53] = 127,
+ [0][0][RTW89_UK][0][53] = 127,
+ [0][0][RTW89_FCC][1][55] = -18,
+ [0][0][RTW89_FCC][2][55] = 56,
+ [0][0][RTW89_ETSI][1][55] = 127,
+ [0][0][RTW89_ETSI][0][55] = 127,
+ [0][0][RTW89_MKK][1][55] = 127,
+ [0][0][RTW89_MKK][0][55] = 127,
+ [0][0][RTW89_IC][1][55] = -18,
+ [0][0][RTW89_KCC][1][55] = -2,
+ [0][0][RTW89_KCC][0][55] = 127,
+ [0][0][RTW89_ACMA][1][55] = 127,
+ [0][0][RTW89_ACMA][0][55] = 127,
+ [0][0][RTW89_CHILE][1][55] = 127,
+ [0][0][RTW89_QATAR][1][55] = 127,
+ [0][0][RTW89_QATAR][0][55] = 127,
+ [0][0][RTW89_UK][1][55] = 127,
+ [0][0][RTW89_UK][0][55] = 127,
+ [0][0][RTW89_FCC][1][57] = -18,
+ [0][0][RTW89_FCC][2][57] = 56,
+ [0][0][RTW89_ETSI][1][57] = 127,
+ [0][0][RTW89_ETSI][0][57] = 127,
+ [0][0][RTW89_MKK][1][57] = 127,
+ [0][0][RTW89_MKK][0][57] = 127,
+ [0][0][RTW89_IC][1][57] = -18,
+ [0][0][RTW89_KCC][1][57] = -2,
+ [0][0][RTW89_KCC][0][57] = 127,
+ [0][0][RTW89_ACMA][1][57] = 127,
+ [0][0][RTW89_ACMA][0][57] = 127,
+ [0][0][RTW89_CHILE][1][57] = 127,
+ [0][0][RTW89_QATAR][1][57] = 127,
+ [0][0][RTW89_QATAR][0][57] = 127,
+ [0][0][RTW89_UK][1][57] = 127,
+ [0][0][RTW89_UK][0][57] = 127,
+ [0][0][RTW89_FCC][1][59] = -18,
+ [0][0][RTW89_FCC][2][59] = 56,
+ [0][0][RTW89_ETSI][1][59] = 127,
+ [0][0][RTW89_ETSI][0][59] = 127,
+ [0][0][RTW89_MKK][1][59] = 127,
+ [0][0][RTW89_MKK][0][59] = 127,
+ [0][0][RTW89_IC][1][59] = -18,
+ [0][0][RTW89_KCC][1][59] = -2,
+ [0][0][RTW89_KCC][0][59] = 127,
+ [0][0][RTW89_ACMA][1][59] = 127,
+ [0][0][RTW89_ACMA][0][59] = 127,
+ [0][0][RTW89_CHILE][1][59] = 127,
+ [0][0][RTW89_QATAR][1][59] = 127,
+ [0][0][RTW89_QATAR][0][59] = 127,
+ [0][0][RTW89_UK][1][59] = 127,
+ [0][0][RTW89_UK][0][59] = 127,
+ [0][0][RTW89_FCC][1][60] = -18,
+ [0][0][RTW89_FCC][2][60] = 56,
+ [0][0][RTW89_ETSI][1][60] = 127,
+ [0][0][RTW89_ETSI][0][60] = 127,
+ [0][0][RTW89_MKK][1][60] = 127,
+ [0][0][RTW89_MKK][0][60] = 127,
+ [0][0][RTW89_IC][1][60] = -18,
+ [0][0][RTW89_KCC][1][60] = -2,
+ [0][0][RTW89_KCC][0][60] = 127,
+ [0][0][RTW89_ACMA][1][60] = 127,
+ [0][0][RTW89_ACMA][0][60] = 127,
+ [0][0][RTW89_CHILE][1][60] = 127,
+ [0][0][RTW89_QATAR][1][60] = 127,
+ [0][0][RTW89_QATAR][0][60] = 127,
+ [0][0][RTW89_UK][1][60] = 127,
+ [0][0][RTW89_UK][0][60] = 127,
+ [0][0][RTW89_FCC][1][62] = -18,
+ [0][0][RTW89_FCC][2][62] = 56,
+ [0][0][RTW89_ETSI][1][62] = 127,
+ [0][0][RTW89_ETSI][0][62] = 127,
+ [0][0][RTW89_MKK][1][62] = 127,
+ [0][0][RTW89_MKK][0][62] = 127,
+ [0][0][RTW89_IC][1][62] = -18,
+ [0][0][RTW89_KCC][1][62] = -2,
+ [0][0][RTW89_KCC][0][62] = 127,
+ [0][0][RTW89_ACMA][1][62] = 127,
+ [0][0][RTW89_ACMA][0][62] = 127,
+ [0][0][RTW89_CHILE][1][62] = 127,
+ [0][0][RTW89_QATAR][1][62] = 127,
+ [0][0][RTW89_QATAR][0][62] = 127,
+ [0][0][RTW89_UK][1][62] = 127,
+ [0][0][RTW89_UK][0][62] = 127,
+ [0][0][RTW89_FCC][1][64] = -18,
+ [0][0][RTW89_FCC][2][64] = 56,
+ [0][0][RTW89_ETSI][1][64] = 127,
+ [0][0][RTW89_ETSI][0][64] = 127,
+ [0][0][RTW89_MKK][1][64] = 127,
+ [0][0][RTW89_MKK][0][64] = 127,
+ [0][0][RTW89_IC][1][64] = -18,
+ [0][0][RTW89_KCC][1][64] = -2,
+ [0][0][RTW89_KCC][0][64] = 127,
+ [0][0][RTW89_ACMA][1][64] = 127,
+ [0][0][RTW89_ACMA][0][64] = 127,
+ [0][0][RTW89_CHILE][1][64] = 127,
+ [0][0][RTW89_QATAR][1][64] = 127,
+ [0][0][RTW89_QATAR][0][64] = 127,
+ [0][0][RTW89_UK][1][64] = 127,
+ [0][0][RTW89_UK][0][64] = 127,
+ [0][0][RTW89_FCC][1][66] = -18,
+ [0][0][RTW89_FCC][2][66] = 56,
+ [0][0][RTW89_ETSI][1][66] = 127,
+ [0][0][RTW89_ETSI][0][66] = 127,
+ [0][0][RTW89_MKK][1][66] = 127,
+ [0][0][RTW89_MKK][0][66] = 127,
+ [0][0][RTW89_IC][1][66] = -18,
+ [0][0][RTW89_KCC][1][66] = -2,
+ [0][0][RTW89_KCC][0][66] = 127,
+ [0][0][RTW89_ACMA][1][66] = 127,
+ [0][0][RTW89_ACMA][0][66] = 127,
+ [0][0][RTW89_CHILE][1][66] = 127,
+ [0][0][RTW89_QATAR][1][66] = 127,
+ [0][0][RTW89_QATAR][0][66] = 127,
+ [0][0][RTW89_UK][1][66] = 127,
+ [0][0][RTW89_UK][0][66] = 127,
+ [0][0][RTW89_FCC][1][68] = -18,
+ [0][0][RTW89_FCC][2][68] = 56,
+ [0][0][RTW89_ETSI][1][68] = 127,
+ [0][0][RTW89_ETSI][0][68] = 127,
+ [0][0][RTW89_MKK][1][68] = 127,
+ [0][0][RTW89_MKK][0][68] = 127,
+ [0][0][RTW89_IC][1][68] = -18,
+ [0][0][RTW89_KCC][1][68] = -2,
+ [0][0][RTW89_KCC][0][68] = 127,
+ [0][0][RTW89_ACMA][1][68] = 127,
+ [0][0][RTW89_ACMA][0][68] = 127,
+ [0][0][RTW89_CHILE][1][68] = 127,
+ [0][0][RTW89_QATAR][1][68] = 127,
+ [0][0][RTW89_QATAR][0][68] = 127,
+ [0][0][RTW89_UK][1][68] = 127,
+ [0][0][RTW89_UK][0][68] = 127,
+ [0][0][RTW89_FCC][1][70] = -16,
+ [0][0][RTW89_FCC][2][70] = 56,
+ [0][0][RTW89_ETSI][1][70] = 127,
+ [0][0][RTW89_ETSI][0][70] = 127,
+ [0][0][RTW89_MKK][1][70] = 127,
+ [0][0][RTW89_MKK][0][70] = 127,
+ [0][0][RTW89_IC][1][70] = -16,
+ [0][0][RTW89_KCC][1][70] = -2,
+ [0][0][RTW89_KCC][0][70] = 127,
+ [0][0][RTW89_ACMA][1][70] = 127,
+ [0][0][RTW89_ACMA][0][70] = 127,
+ [0][0][RTW89_CHILE][1][70] = 127,
+ [0][0][RTW89_QATAR][1][70] = 127,
+ [0][0][RTW89_QATAR][0][70] = 127,
+ [0][0][RTW89_UK][1][70] = 127,
+ [0][0][RTW89_UK][0][70] = 127,
+ [0][0][RTW89_FCC][1][72] = -18,
+ [0][0][RTW89_FCC][2][72] = 56,
+ [0][0][RTW89_ETSI][1][72] = 127,
+ [0][0][RTW89_ETSI][0][72] = 127,
+ [0][0][RTW89_MKK][1][72] = 127,
+ [0][0][RTW89_MKK][0][72] = 127,
+ [0][0][RTW89_IC][1][72] = -18,
+ [0][0][RTW89_KCC][1][72] = -2,
+ [0][0][RTW89_KCC][0][72] = 127,
+ [0][0][RTW89_ACMA][1][72] = 127,
+ [0][0][RTW89_ACMA][0][72] = 127,
+ [0][0][RTW89_CHILE][1][72] = 127,
+ [0][0][RTW89_QATAR][1][72] = 127,
+ [0][0][RTW89_QATAR][0][72] = 127,
+ [0][0][RTW89_UK][1][72] = 127,
+ [0][0][RTW89_UK][0][72] = 127,
+ [0][0][RTW89_FCC][1][74] = -18,
+ [0][0][RTW89_FCC][2][74] = 56,
+ [0][0][RTW89_ETSI][1][74] = 127,
+ [0][0][RTW89_ETSI][0][74] = 127,
+ [0][0][RTW89_MKK][1][74] = 127,
+ [0][0][RTW89_MKK][0][74] = 127,
+ [0][0][RTW89_IC][1][74] = -18,
+ [0][0][RTW89_KCC][1][74] = -2,
+ [0][0][RTW89_KCC][0][74] = 127,
+ [0][0][RTW89_ACMA][1][74] = 127,
+ [0][0][RTW89_ACMA][0][74] = 127,
+ [0][0][RTW89_CHILE][1][74] = 127,
+ [0][0][RTW89_QATAR][1][74] = 127,
+ [0][0][RTW89_QATAR][0][74] = 127,
+ [0][0][RTW89_UK][1][74] = 127,
+ [0][0][RTW89_UK][0][74] = 127,
+ [0][0][RTW89_FCC][1][75] = -18,
+ [0][0][RTW89_FCC][2][75] = 56,
+ [0][0][RTW89_ETSI][1][75] = 127,
+ [0][0][RTW89_ETSI][0][75] = 127,
+ [0][0][RTW89_MKK][1][75] = 127,
+ [0][0][RTW89_MKK][0][75] = 127,
+ [0][0][RTW89_IC][1][75] = -18,
+ [0][0][RTW89_KCC][1][75] = -2,
+ [0][0][RTW89_KCC][0][75] = 127,
+ [0][0][RTW89_ACMA][1][75] = 127,
+ [0][0][RTW89_ACMA][0][75] = 127,
+ [0][0][RTW89_CHILE][1][75] = 127,
+ [0][0][RTW89_QATAR][1][75] = 127,
+ [0][0][RTW89_QATAR][0][75] = 127,
+ [0][0][RTW89_UK][1][75] = 127,
+ [0][0][RTW89_UK][0][75] = 127,
+ [0][0][RTW89_FCC][1][77] = -18,
+ [0][0][RTW89_FCC][2][77] = 56,
+ [0][0][RTW89_ETSI][1][77] = 127,
+ [0][0][RTW89_ETSI][0][77] = 127,
+ [0][0][RTW89_MKK][1][77] = 127,
+ [0][0][RTW89_MKK][0][77] = 127,
+ [0][0][RTW89_IC][1][77] = -18,
+ [0][0][RTW89_KCC][1][77] = -2,
+ [0][0][RTW89_KCC][0][77] = 127,
+ [0][0][RTW89_ACMA][1][77] = 127,
+ [0][0][RTW89_ACMA][0][77] = 127,
+ [0][0][RTW89_CHILE][1][77] = 127,
+ [0][0][RTW89_QATAR][1][77] = 127,
+ [0][0][RTW89_QATAR][0][77] = 127,
+ [0][0][RTW89_UK][1][77] = 127,
+ [0][0][RTW89_UK][0][77] = 127,
+ [0][0][RTW89_FCC][1][79] = -18,
+ [0][0][RTW89_FCC][2][79] = 56,
+ [0][0][RTW89_ETSI][1][79] = 127,
+ [0][0][RTW89_ETSI][0][79] = 127,
+ [0][0][RTW89_MKK][1][79] = 127,
+ [0][0][RTW89_MKK][0][79] = 127,
+ [0][0][RTW89_IC][1][79] = -18,
+ [0][0][RTW89_KCC][1][79] = -2,
+ [0][0][RTW89_KCC][0][79] = 127,
+ [0][0][RTW89_ACMA][1][79] = 127,
+ [0][0][RTW89_ACMA][0][79] = 127,
+ [0][0][RTW89_CHILE][1][79] = 127,
+ [0][0][RTW89_QATAR][1][79] = 127,
+ [0][0][RTW89_QATAR][0][79] = 127,
+ [0][0][RTW89_UK][1][79] = 127,
+ [0][0][RTW89_UK][0][79] = 127,
+ [0][0][RTW89_FCC][1][81] = -18,
+ [0][0][RTW89_FCC][2][81] = 56,
+ [0][0][RTW89_ETSI][1][81] = 127,
+ [0][0][RTW89_ETSI][0][81] = 127,
+ [0][0][RTW89_MKK][1][81] = 127,
+ [0][0][RTW89_MKK][0][81] = 127,
+ [0][0][RTW89_IC][1][81] = -18,
+ [0][0][RTW89_KCC][1][81] = -2,
+ [0][0][RTW89_KCC][0][81] = 127,
+ [0][0][RTW89_ACMA][1][81] = 127,
+ [0][0][RTW89_ACMA][0][81] = 127,
+ [0][0][RTW89_CHILE][1][81] = 127,
+ [0][0][RTW89_QATAR][1][81] = 127,
+ [0][0][RTW89_QATAR][0][81] = 127,
+ [0][0][RTW89_UK][1][81] = 127,
+ [0][0][RTW89_UK][0][81] = 127,
+ [0][0][RTW89_FCC][1][83] = -18,
+ [0][0][RTW89_FCC][2][83] = 56,
+ [0][0][RTW89_ETSI][1][83] = 127,
+ [0][0][RTW89_ETSI][0][83] = 127,
+ [0][0][RTW89_MKK][1][83] = 127,
+ [0][0][RTW89_MKK][0][83] = 127,
+ [0][0][RTW89_IC][1][83] = -18,
+ [0][0][RTW89_KCC][1][83] = -2,
+ [0][0][RTW89_KCC][0][83] = 127,
+ [0][0][RTW89_ACMA][1][83] = 127,
+ [0][0][RTW89_ACMA][0][83] = 127,
+ [0][0][RTW89_CHILE][1][83] = 127,
+ [0][0][RTW89_QATAR][1][83] = 127,
+ [0][0][RTW89_QATAR][0][83] = 127,
+ [0][0][RTW89_UK][1][83] = 127,
+ [0][0][RTW89_UK][0][83] = 127,
+ [0][0][RTW89_FCC][1][85] = -18,
+ [0][0][RTW89_FCC][2][85] = 56,
+ [0][0][RTW89_ETSI][1][85] = 127,
+ [0][0][RTW89_ETSI][0][85] = 127,
+ [0][0][RTW89_MKK][1][85] = 127,
+ [0][0][RTW89_MKK][0][85] = 127,
+ [0][0][RTW89_IC][1][85] = -18,
+ [0][0][RTW89_KCC][1][85] = -2,
+ [0][0][RTW89_KCC][0][85] = 127,
+ [0][0][RTW89_ACMA][1][85] = 127,
+ [0][0][RTW89_ACMA][0][85] = 127,
+ [0][0][RTW89_CHILE][1][85] = 127,
+ [0][0][RTW89_QATAR][1][85] = 127,
+ [0][0][RTW89_QATAR][0][85] = 127,
+ [0][0][RTW89_UK][1][85] = 127,
+ [0][0][RTW89_UK][0][85] = 127,
+ [0][0][RTW89_FCC][1][87] = -16,
+ [0][0][RTW89_FCC][2][87] = 127,
+ [0][0][RTW89_ETSI][1][87] = 127,
+ [0][0][RTW89_ETSI][0][87] = 127,
+ [0][0][RTW89_MKK][1][87] = 127,
+ [0][0][RTW89_MKK][0][87] = 127,
+ [0][0][RTW89_IC][1][87] = -16,
+ [0][0][RTW89_KCC][1][87] = -2,
+ [0][0][RTW89_KCC][0][87] = 127,
+ [0][0][RTW89_ACMA][1][87] = 127,
+ [0][0][RTW89_ACMA][0][87] = 127,
+ [0][0][RTW89_CHILE][1][87] = 127,
+ [0][0][RTW89_QATAR][1][87] = 127,
+ [0][0][RTW89_QATAR][0][87] = 127,
+ [0][0][RTW89_UK][1][87] = 127,
+ [0][0][RTW89_UK][0][87] = 127,
+ [0][0][RTW89_FCC][1][89] = -16,
+ [0][0][RTW89_FCC][2][89] = 127,
+ [0][0][RTW89_ETSI][1][89] = 127,
+ [0][0][RTW89_ETSI][0][89] = 127,
+ [0][0][RTW89_MKK][1][89] = 127,
+ [0][0][RTW89_MKK][0][89] = 127,
+ [0][0][RTW89_IC][1][89] = -16,
+ [0][0][RTW89_KCC][1][89] = -2,
+ [0][0][RTW89_KCC][0][89] = 127,
+ [0][0][RTW89_ACMA][1][89] = 127,
+ [0][0][RTW89_ACMA][0][89] = 127,
+ [0][0][RTW89_CHILE][1][89] = 127,
+ [0][0][RTW89_QATAR][1][89] = 127,
+ [0][0][RTW89_QATAR][0][89] = 127,
+ [0][0][RTW89_UK][1][89] = 127,
+ [0][0][RTW89_UK][0][89] = 127,
+ [0][0][RTW89_FCC][1][90] = -16,
+ [0][0][RTW89_FCC][2][90] = 127,
+ [0][0][RTW89_ETSI][1][90] = 127,
+ [0][0][RTW89_ETSI][0][90] = 127,
+ [0][0][RTW89_MKK][1][90] = 127,
+ [0][0][RTW89_MKK][0][90] = 127,
+ [0][0][RTW89_IC][1][90] = -16,
+ [0][0][RTW89_KCC][1][90] = -2,
+ [0][0][RTW89_KCC][0][90] = 127,
+ [0][0][RTW89_ACMA][1][90] = 127,
+ [0][0][RTW89_ACMA][0][90] = 127,
+ [0][0][RTW89_CHILE][1][90] = 127,
+ [0][0][RTW89_QATAR][1][90] = 127,
+ [0][0][RTW89_QATAR][0][90] = 127,
+ [0][0][RTW89_UK][1][90] = 127,
+ [0][0][RTW89_UK][0][90] = 127,
+ [0][0][RTW89_FCC][1][92] = -16,
+ [0][0][RTW89_FCC][2][92] = 127,
+ [0][0][RTW89_ETSI][1][92] = 127,
+ [0][0][RTW89_ETSI][0][92] = 127,
+ [0][0][RTW89_MKK][1][92] = 127,
+ [0][0][RTW89_MKK][0][92] = 127,
+ [0][0][RTW89_IC][1][92] = -16,
+ [0][0][RTW89_KCC][1][92] = -2,
+ [0][0][RTW89_KCC][0][92] = 127,
+ [0][0][RTW89_ACMA][1][92] = 127,
+ [0][0][RTW89_ACMA][0][92] = 127,
+ [0][0][RTW89_CHILE][1][92] = 127,
+ [0][0][RTW89_QATAR][1][92] = 127,
+ [0][0][RTW89_QATAR][0][92] = 127,
+ [0][0][RTW89_UK][1][92] = 127,
+ [0][0][RTW89_UK][0][92] = 127,
+ [0][0][RTW89_FCC][1][94] = -16,
+ [0][0][RTW89_FCC][2][94] = 127,
+ [0][0][RTW89_ETSI][1][94] = 127,
+ [0][0][RTW89_ETSI][0][94] = 127,
+ [0][0][RTW89_MKK][1][94] = 127,
+ [0][0][RTW89_MKK][0][94] = 127,
+ [0][0][RTW89_IC][1][94] = -16,
+ [0][0][RTW89_KCC][1][94] = -2,
+ [0][0][RTW89_KCC][0][94] = 127,
+ [0][0][RTW89_ACMA][1][94] = 127,
+ [0][0][RTW89_ACMA][0][94] = 127,
+ [0][0][RTW89_CHILE][1][94] = 127,
+ [0][0][RTW89_QATAR][1][94] = 127,
+ [0][0][RTW89_QATAR][0][94] = 127,
+ [0][0][RTW89_UK][1][94] = 127,
+ [0][0][RTW89_UK][0][94] = 127,
+ [0][0][RTW89_FCC][1][96] = -16,
+ [0][0][RTW89_FCC][2][96] = 127,
+ [0][0][RTW89_ETSI][1][96] = 127,
+ [0][0][RTW89_ETSI][0][96] = 127,
+ [0][0][RTW89_MKK][1][96] = 127,
+ [0][0][RTW89_MKK][0][96] = 127,
+ [0][0][RTW89_IC][1][96] = -16,
+ [0][0][RTW89_KCC][1][96] = -2,
+ [0][0][RTW89_KCC][0][96] = 127,
+ [0][0][RTW89_ACMA][1][96] = 127,
+ [0][0][RTW89_ACMA][0][96] = 127,
+ [0][0][RTW89_CHILE][1][96] = 127,
+ [0][0][RTW89_QATAR][1][96] = 127,
+ [0][0][RTW89_QATAR][0][96] = 127,
+ [0][0][RTW89_UK][1][96] = 127,
+ [0][0][RTW89_UK][0][96] = 127,
+ [0][0][RTW89_FCC][1][98] = -16,
+ [0][0][RTW89_FCC][2][98] = 127,
+ [0][0][RTW89_ETSI][1][98] = 127,
+ [0][0][RTW89_ETSI][0][98] = 127,
+ [0][0][RTW89_MKK][1][98] = 127,
+ [0][0][RTW89_MKK][0][98] = 127,
+ [0][0][RTW89_IC][1][98] = -16,
+ [0][0][RTW89_KCC][1][98] = -2,
+ [0][0][RTW89_KCC][0][98] = 127,
+ [0][0][RTW89_ACMA][1][98] = 127,
+ [0][0][RTW89_ACMA][0][98] = 127,
+ [0][0][RTW89_CHILE][1][98] = 127,
+ [0][0][RTW89_QATAR][1][98] = 127,
+ [0][0][RTW89_QATAR][0][98] = 127,
+ [0][0][RTW89_UK][1][98] = 127,
+ [0][0][RTW89_UK][0][98] = 127,
+ [0][0][RTW89_FCC][1][100] = -16,
+ [0][0][RTW89_FCC][2][100] = 127,
+ [0][0][RTW89_ETSI][1][100] = 127,
+ [0][0][RTW89_ETSI][0][100] = 127,
+ [0][0][RTW89_MKK][1][100] = 127,
+ [0][0][RTW89_MKK][0][100] = 127,
+ [0][0][RTW89_IC][1][100] = -16,
+ [0][0][RTW89_KCC][1][100] = -2,
+ [0][0][RTW89_KCC][0][100] = 127,
+ [0][0][RTW89_ACMA][1][100] = 127,
+ [0][0][RTW89_ACMA][0][100] = 127,
+ [0][0][RTW89_CHILE][1][100] = 127,
+ [0][0][RTW89_QATAR][1][100] = 127,
+ [0][0][RTW89_QATAR][0][100] = 127,
+ [0][0][RTW89_UK][1][100] = 127,
+ [0][0][RTW89_UK][0][100] = 127,
+ [0][0][RTW89_FCC][1][102] = -16,
+ [0][0][RTW89_FCC][2][102] = 127,
+ [0][0][RTW89_ETSI][1][102] = 127,
+ [0][0][RTW89_ETSI][0][102] = 127,
+ [0][0][RTW89_MKK][1][102] = 127,
+ [0][0][RTW89_MKK][0][102] = 127,
+ [0][0][RTW89_IC][1][102] = -16,
+ [0][0][RTW89_KCC][1][102] = -2,
+ [0][0][RTW89_KCC][0][102] = 127,
+ [0][0][RTW89_ACMA][1][102] = 127,
+ [0][0][RTW89_ACMA][0][102] = 127,
+ [0][0][RTW89_CHILE][1][102] = 127,
+ [0][0][RTW89_QATAR][1][102] = 127,
+ [0][0][RTW89_QATAR][0][102] = 127,
+ [0][0][RTW89_UK][1][102] = 127,
+ [0][0][RTW89_UK][0][102] = 127,
+ [0][0][RTW89_FCC][1][104] = -16,
+ [0][0][RTW89_FCC][2][104] = 127,
+ [0][0][RTW89_ETSI][1][104] = 127,
+ [0][0][RTW89_ETSI][0][104] = 127,
+ [0][0][RTW89_MKK][1][104] = 127,
+ [0][0][RTW89_MKK][0][104] = 127,
+ [0][0][RTW89_IC][1][104] = -16,
+ [0][0][RTW89_KCC][1][104] = -2,
+ [0][0][RTW89_KCC][0][104] = 127,
+ [0][0][RTW89_ACMA][1][104] = 127,
+ [0][0][RTW89_ACMA][0][104] = 127,
+ [0][0][RTW89_CHILE][1][104] = 127,
+ [0][0][RTW89_QATAR][1][104] = 127,
+ [0][0][RTW89_QATAR][0][104] = 127,
+ [0][0][RTW89_UK][1][104] = 127,
+ [0][0][RTW89_UK][0][104] = 127,
+ [0][0][RTW89_FCC][1][105] = -16,
+ [0][0][RTW89_FCC][2][105] = 127,
+ [0][0][RTW89_ETSI][1][105] = 127,
+ [0][0][RTW89_ETSI][0][105] = 127,
+ [0][0][RTW89_MKK][1][105] = 127,
+ [0][0][RTW89_MKK][0][105] = 127,
+ [0][0][RTW89_IC][1][105] = -16,
+ [0][0][RTW89_KCC][1][105] = -2,
+ [0][0][RTW89_KCC][0][105] = 127,
+ [0][0][RTW89_ACMA][1][105] = 127,
+ [0][0][RTW89_ACMA][0][105] = 127,
+ [0][0][RTW89_CHILE][1][105] = 127,
+ [0][0][RTW89_QATAR][1][105] = 127,
+ [0][0][RTW89_QATAR][0][105] = 127,
+ [0][0][RTW89_UK][1][105] = 127,
+ [0][0][RTW89_UK][0][105] = 127,
+ [0][0][RTW89_FCC][1][107] = -12,
+ [0][0][RTW89_FCC][2][107] = 127,
+ [0][0][RTW89_ETSI][1][107] = 127,
+ [0][0][RTW89_ETSI][0][107] = 127,
+ [0][0][RTW89_MKK][1][107] = 127,
+ [0][0][RTW89_MKK][0][107] = 127,
+ [0][0][RTW89_IC][1][107] = -12,
+ [0][0][RTW89_KCC][1][107] = -2,
+ [0][0][RTW89_KCC][0][107] = 127,
+ [0][0][RTW89_ACMA][1][107] = 127,
+ [0][0][RTW89_ACMA][0][107] = 127,
+ [0][0][RTW89_CHILE][1][107] = 127,
+ [0][0][RTW89_QATAR][1][107] = 127,
+ [0][0][RTW89_QATAR][0][107] = 127,
+ [0][0][RTW89_UK][1][107] = 127,
+ [0][0][RTW89_UK][0][107] = 127,
+ [0][0][RTW89_FCC][1][109] = -12,
+ [0][0][RTW89_FCC][2][109] = 127,
+ [0][0][RTW89_ETSI][1][109] = 127,
+ [0][0][RTW89_ETSI][0][109] = 127,
+ [0][0][RTW89_MKK][1][109] = 127,
+ [0][0][RTW89_MKK][0][109] = 127,
+ [0][0][RTW89_IC][1][109] = -12,
+ [0][0][RTW89_KCC][1][109] = 127,
+ [0][0][RTW89_KCC][0][109] = 127,
+ [0][0][RTW89_ACMA][1][109] = 127,
+ [0][0][RTW89_ACMA][0][109] = 127,
+ [0][0][RTW89_CHILE][1][109] = 127,
+ [0][0][RTW89_QATAR][1][109] = 127,
+ [0][0][RTW89_QATAR][0][109] = 127,
+ [0][0][RTW89_UK][1][109] = 127,
+ [0][0][RTW89_UK][0][109] = 127,
+ [0][0][RTW89_FCC][1][111] = 127,
+ [0][0][RTW89_FCC][2][111] = 127,
+ [0][0][RTW89_ETSI][1][111] = 127,
+ [0][0][RTW89_ETSI][0][111] = 127,
+ [0][0][RTW89_MKK][1][111] = 127,
+ [0][0][RTW89_MKK][0][111] = 127,
+ [0][0][RTW89_IC][1][111] = 127,
+ [0][0][RTW89_KCC][1][111] = 127,
+ [0][0][RTW89_KCC][0][111] = 127,
+ [0][0][RTW89_ACMA][1][111] = 127,
+ [0][0][RTW89_ACMA][0][111] = 127,
+ [0][0][RTW89_CHILE][1][111] = 127,
+ [0][0][RTW89_QATAR][1][111] = 127,
+ [0][0][RTW89_QATAR][0][111] = 127,
+ [0][0][RTW89_UK][1][111] = 127,
+ [0][0][RTW89_UK][0][111] = 127,
+ [0][0][RTW89_FCC][1][113] = 127,
+ [0][0][RTW89_FCC][2][113] = 127,
+ [0][0][RTW89_ETSI][1][113] = 127,
+ [0][0][RTW89_ETSI][0][113] = 127,
+ [0][0][RTW89_MKK][1][113] = 127,
+ [0][0][RTW89_MKK][0][113] = 127,
+ [0][0][RTW89_IC][1][113] = 127,
+ [0][0][RTW89_KCC][1][113] = 127,
+ [0][0][RTW89_KCC][0][113] = 127,
+ [0][0][RTW89_ACMA][1][113] = 127,
+ [0][0][RTW89_ACMA][0][113] = 127,
+ [0][0][RTW89_CHILE][1][113] = 127,
+ [0][0][RTW89_QATAR][1][113] = 127,
+ [0][0][RTW89_QATAR][0][113] = 127,
+ [0][0][RTW89_UK][1][113] = 127,
+ [0][0][RTW89_UK][0][113] = 127,
+ [0][0][RTW89_FCC][1][115] = 127,
+ [0][0][RTW89_FCC][2][115] = 127,
+ [0][0][RTW89_ETSI][1][115] = 127,
+ [0][0][RTW89_ETSI][0][115] = 127,
+ [0][0][RTW89_MKK][1][115] = 127,
+ [0][0][RTW89_MKK][0][115] = 127,
+ [0][0][RTW89_IC][1][115] = 127,
+ [0][0][RTW89_KCC][1][115] = 127,
+ [0][0][RTW89_KCC][0][115] = 127,
+ [0][0][RTW89_ACMA][1][115] = 127,
+ [0][0][RTW89_ACMA][0][115] = 127,
+ [0][0][RTW89_CHILE][1][115] = 127,
+ [0][0][RTW89_QATAR][1][115] = 127,
+ [0][0][RTW89_QATAR][0][115] = 127,
+ [0][0][RTW89_UK][1][115] = 127,
+ [0][0][RTW89_UK][0][115] = 127,
+ [0][0][RTW89_FCC][1][117] = 127,
+ [0][0][RTW89_FCC][2][117] = 127,
+ [0][0][RTW89_ETSI][1][117] = 127,
+ [0][0][RTW89_ETSI][0][117] = 127,
+ [0][0][RTW89_MKK][1][117] = 127,
+ [0][0][RTW89_MKK][0][117] = 127,
+ [0][0][RTW89_IC][1][117] = 127,
+ [0][0][RTW89_KCC][1][117] = 127,
+ [0][0][RTW89_KCC][0][117] = 127,
+ [0][0][RTW89_ACMA][1][117] = 127,
+ [0][0][RTW89_ACMA][0][117] = 127,
+ [0][0][RTW89_CHILE][1][117] = 127,
+ [0][0][RTW89_QATAR][1][117] = 127,
+ [0][0][RTW89_QATAR][0][117] = 127,
+ [0][0][RTW89_UK][1][117] = 127,
+ [0][0][RTW89_UK][0][117] = 127,
+ [0][0][RTW89_FCC][1][119] = 127,
+ [0][0][RTW89_FCC][2][119] = 127,
+ [0][0][RTW89_ETSI][1][119] = 127,
+ [0][0][RTW89_ETSI][0][119] = 127,
+ [0][0][RTW89_MKK][1][119] = 127,
+ [0][0][RTW89_MKK][0][119] = 127,
+ [0][0][RTW89_IC][1][119] = 127,
+ [0][0][RTW89_KCC][1][119] = 127,
+ [0][0][RTW89_KCC][0][119] = 127,
+ [0][0][RTW89_ACMA][1][119] = 127,
+ [0][0][RTW89_ACMA][0][119] = 127,
+ [0][0][RTW89_CHILE][1][119] = 127,
+ [0][0][RTW89_QATAR][1][119] = 127,
+ [0][0][RTW89_QATAR][0][119] = 127,
+ [0][0][RTW89_UK][1][119] = 127,
+ [0][0][RTW89_UK][0][119] = 127,
+ [0][1][RTW89_FCC][1][0] = -40,
+ [0][1][RTW89_FCC][2][0] = 32,
+ [0][1][RTW89_ETSI][1][0] = 20,
+ [0][1][RTW89_ETSI][0][0] = -18,
+ [0][1][RTW89_MKK][1][0] = 18,
+ [0][1][RTW89_MKK][0][0] = -20,
+ [0][1][RTW89_IC][1][0] = -40,
+ [0][1][RTW89_KCC][1][0] = -14,
+ [0][1][RTW89_KCC][0][0] = -14,
+ [0][1][RTW89_ACMA][1][0] = 20,
+ [0][1][RTW89_ACMA][0][0] = -18,
+ [0][1][RTW89_CHILE][1][0] = -40,
+ [0][1][RTW89_QATAR][1][0] = 20,
+ [0][1][RTW89_QATAR][0][0] = -18,
+ [0][1][RTW89_UK][1][0] = 20,
+ [0][1][RTW89_UK][0][0] = -18,
+ [0][1][RTW89_FCC][1][2] = -40,
+ [0][1][RTW89_FCC][2][2] = 32,
+ [0][1][RTW89_ETSI][1][2] = 20,
+ [0][1][RTW89_ETSI][0][2] = -18,
+ [0][1][RTW89_MKK][1][2] = 18,
+ [0][1][RTW89_MKK][0][2] = -22,
+ [0][1][RTW89_IC][1][2] = -40,
+ [0][1][RTW89_KCC][1][2] = -14,
+ [0][1][RTW89_KCC][0][2] = -14,
+ [0][1][RTW89_ACMA][1][2] = 20,
+ [0][1][RTW89_ACMA][0][2] = -18,
+ [0][1][RTW89_CHILE][1][2] = -40,
+ [0][1][RTW89_QATAR][1][2] = 20,
+ [0][1][RTW89_QATAR][0][2] = -18,
+ [0][1][RTW89_UK][1][2] = 20,
+ [0][1][RTW89_UK][0][2] = -18,
+ [0][1][RTW89_FCC][1][4] = -40,
+ [0][1][RTW89_FCC][2][4] = 32,
+ [0][1][RTW89_ETSI][1][4] = 20,
+ [0][1][RTW89_ETSI][0][4] = -18,
+ [0][1][RTW89_MKK][1][4] = 18,
+ [0][1][RTW89_MKK][0][4] = -22,
+ [0][1][RTW89_IC][1][4] = -40,
+ [0][1][RTW89_KCC][1][4] = -14,
+ [0][1][RTW89_KCC][0][4] = -14,
+ [0][1][RTW89_ACMA][1][4] = 20,
+ [0][1][RTW89_ACMA][0][4] = -18,
+ [0][1][RTW89_CHILE][1][4] = -40,
+ [0][1][RTW89_QATAR][1][4] = 20,
+ [0][1][RTW89_QATAR][0][4] = -18,
+ [0][1][RTW89_UK][1][4] = 20,
+ [0][1][RTW89_UK][0][4] = -18,
+ [0][1][RTW89_FCC][1][6] = -40,
+ [0][1][RTW89_FCC][2][6] = 32,
+ [0][1][RTW89_ETSI][1][6] = 20,
+ [0][1][RTW89_ETSI][0][6] = -18,
+ [0][1][RTW89_MKK][1][6] = 18,
+ [0][1][RTW89_MKK][0][6] = -22,
+ [0][1][RTW89_IC][1][6] = -40,
+ [0][1][RTW89_KCC][1][6] = -14,
+ [0][1][RTW89_KCC][0][6] = -14,
+ [0][1][RTW89_ACMA][1][6] = 20,
+ [0][1][RTW89_ACMA][0][6] = -18,
+ [0][1][RTW89_CHILE][1][6] = -40,
+ [0][1][RTW89_QATAR][1][6] = 20,
+ [0][1][RTW89_QATAR][0][6] = -18,
+ [0][1][RTW89_UK][1][6] = 20,
+ [0][1][RTW89_UK][0][6] = -18,
+ [0][1][RTW89_FCC][1][8] = -40,
+ [0][1][RTW89_FCC][2][8] = 32,
+ [0][1][RTW89_ETSI][1][8] = 20,
+ [0][1][RTW89_ETSI][0][8] = -18,
+ [0][1][RTW89_MKK][1][8] = 18,
+ [0][1][RTW89_MKK][0][8] = -22,
+ [0][1][RTW89_IC][1][8] = -40,
+ [0][1][RTW89_KCC][1][8] = -14,
+ [0][1][RTW89_KCC][0][8] = -14,
+ [0][1][RTW89_ACMA][1][8] = 20,
+ [0][1][RTW89_ACMA][0][8] = -18,
+ [0][1][RTW89_CHILE][1][8] = -40,
+ [0][1][RTW89_QATAR][1][8] = 20,
+ [0][1][RTW89_QATAR][0][8] = -18,
+ [0][1][RTW89_UK][1][8] = 20,
+ [0][1][RTW89_UK][0][8] = -18,
+ [0][1][RTW89_FCC][1][10] = -40,
+ [0][1][RTW89_FCC][2][10] = 32,
+ [0][1][RTW89_ETSI][1][10] = 20,
+ [0][1][RTW89_ETSI][0][10] = -18,
+ [0][1][RTW89_MKK][1][10] = 18,
+ [0][1][RTW89_MKK][0][10] = -22,
+ [0][1][RTW89_IC][1][10] = -40,
+ [0][1][RTW89_KCC][1][10] = -14,
+ [0][1][RTW89_KCC][0][10] = -14,
+ [0][1][RTW89_ACMA][1][10] = 20,
+ [0][1][RTW89_ACMA][0][10] = -18,
+ [0][1][RTW89_CHILE][1][10] = -40,
+ [0][1][RTW89_QATAR][1][10] = 20,
+ [0][1][RTW89_QATAR][0][10] = -18,
+ [0][1][RTW89_UK][1][10] = 20,
+ [0][1][RTW89_UK][0][10] = -18,
+ [0][1][RTW89_FCC][1][12] = -40,
+ [0][1][RTW89_FCC][2][12] = 32,
+ [0][1][RTW89_ETSI][1][12] = 20,
+ [0][1][RTW89_ETSI][0][12] = -18,
+ [0][1][RTW89_MKK][1][12] = 18,
+ [0][1][RTW89_MKK][0][12] = -22,
+ [0][1][RTW89_IC][1][12] = -40,
+ [0][1][RTW89_KCC][1][12] = -14,
+ [0][1][RTW89_KCC][0][12] = -14,
+ [0][1][RTW89_ACMA][1][12] = 20,
+ [0][1][RTW89_ACMA][0][12] = -18,
+ [0][1][RTW89_CHILE][1][12] = -40,
+ [0][1][RTW89_QATAR][1][12] = 20,
+ [0][1][RTW89_QATAR][0][12] = -18,
+ [0][1][RTW89_UK][1][12] = 20,
+ [0][1][RTW89_UK][0][12] = -18,
+ [0][1][RTW89_FCC][1][14] = -40,
+ [0][1][RTW89_FCC][2][14] = 32,
+ [0][1][RTW89_ETSI][1][14] = 20,
+ [0][1][RTW89_ETSI][0][14] = -18,
+ [0][1][RTW89_MKK][1][14] = 18,
+ [0][1][RTW89_MKK][0][14] = -22,
+ [0][1][RTW89_IC][1][14] = -40,
+ [0][1][RTW89_KCC][1][14] = -14,
+ [0][1][RTW89_KCC][0][14] = -14,
+ [0][1][RTW89_ACMA][1][14] = 20,
+ [0][1][RTW89_ACMA][0][14] = -18,
+ [0][1][RTW89_CHILE][1][14] = -40,
+ [0][1][RTW89_QATAR][1][14] = 20,
+ [0][1][RTW89_QATAR][0][14] = -18,
+ [0][1][RTW89_UK][1][14] = 20,
+ [0][1][RTW89_UK][0][14] = -18,
+ [0][1][RTW89_FCC][1][15] = -40,
+ [0][1][RTW89_FCC][2][15] = 32,
+ [0][1][RTW89_ETSI][1][15] = 20,
+ [0][1][RTW89_ETSI][0][15] = -18,
+ [0][1][RTW89_MKK][1][15] = 18,
+ [0][1][RTW89_MKK][0][15] = -22,
+ [0][1][RTW89_IC][1][15] = -40,
+ [0][1][RTW89_KCC][1][15] = -14,
+ [0][1][RTW89_KCC][0][15] = -14,
+ [0][1][RTW89_ACMA][1][15] = 20,
+ [0][1][RTW89_ACMA][0][15] = -18,
+ [0][1][RTW89_CHILE][1][15] = -40,
+ [0][1][RTW89_QATAR][1][15] = 20,
+ [0][1][RTW89_QATAR][0][15] = -18,
+ [0][1][RTW89_UK][1][15] = 20,
+ [0][1][RTW89_UK][0][15] = -18,
+ [0][1][RTW89_FCC][1][17] = -40,
+ [0][1][RTW89_FCC][2][17] = 32,
+ [0][1][RTW89_ETSI][1][17] = 20,
+ [0][1][RTW89_ETSI][0][17] = -18,
+ [0][1][RTW89_MKK][1][17] = 18,
+ [0][1][RTW89_MKK][0][17] = -22,
+ [0][1][RTW89_IC][1][17] = -40,
+ [0][1][RTW89_KCC][1][17] = -14,
+ [0][1][RTW89_KCC][0][17] = -14,
+ [0][1][RTW89_ACMA][1][17] = 20,
+ [0][1][RTW89_ACMA][0][17] = -18,
+ [0][1][RTW89_CHILE][1][17] = -40,
+ [0][1][RTW89_QATAR][1][17] = 20,
+ [0][1][RTW89_QATAR][0][17] = -18,
+ [0][1][RTW89_UK][1][17] = 20,
+ [0][1][RTW89_UK][0][17] = -18,
+ [0][1][RTW89_FCC][1][19] = -40,
+ [0][1][RTW89_FCC][2][19] = 32,
+ [0][1][RTW89_ETSI][1][19] = 20,
+ [0][1][RTW89_ETSI][0][19] = -18,
+ [0][1][RTW89_MKK][1][19] = 18,
+ [0][1][RTW89_MKK][0][19] = -22,
+ [0][1][RTW89_IC][1][19] = -40,
+ [0][1][RTW89_KCC][1][19] = -14,
+ [0][1][RTW89_KCC][0][19] = -14,
+ [0][1][RTW89_ACMA][1][19] = 20,
+ [0][1][RTW89_ACMA][0][19] = -18,
+ [0][1][RTW89_CHILE][1][19] = -40,
+ [0][1][RTW89_QATAR][1][19] = 20,
+ [0][1][RTW89_QATAR][0][19] = -18,
+ [0][1][RTW89_UK][1][19] = 20,
+ [0][1][RTW89_UK][0][19] = -18,
+ [0][1][RTW89_FCC][1][21] = -40,
+ [0][1][RTW89_FCC][2][21] = 32,
+ [0][1][RTW89_ETSI][1][21] = 20,
+ [0][1][RTW89_ETSI][0][21] = -18,
+ [0][1][RTW89_MKK][1][21] = 18,
+ [0][1][RTW89_MKK][0][21] = -22,
+ [0][1][RTW89_IC][1][21] = -40,
+ [0][1][RTW89_KCC][1][21] = -14,
+ [0][1][RTW89_KCC][0][21] = -14,
+ [0][1][RTW89_ACMA][1][21] = 20,
+ [0][1][RTW89_ACMA][0][21] = -18,
+ [0][1][RTW89_CHILE][1][21] = -40,
+ [0][1][RTW89_QATAR][1][21] = 20,
+ [0][1][RTW89_QATAR][0][21] = -18,
+ [0][1][RTW89_UK][1][21] = 20,
+ [0][1][RTW89_UK][0][21] = -18,
+ [0][1][RTW89_FCC][1][23] = -40,
+ [0][1][RTW89_FCC][2][23] = 32,
+ [0][1][RTW89_ETSI][1][23] = 20,
+ [0][1][RTW89_ETSI][0][23] = -18,
+ [0][1][RTW89_MKK][1][23] = 18,
+ [0][1][RTW89_MKK][0][23] = -22,
+ [0][1][RTW89_IC][1][23] = -40,
+ [0][1][RTW89_KCC][1][23] = -14,
+ [0][1][RTW89_KCC][0][23] = -14,
+ [0][1][RTW89_ACMA][1][23] = 20,
+ [0][1][RTW89_ACMA][0][23] = -18,
+ [0][1][RTW89_CHILE][1][23] = -40,
+ [0][1][RTW89_QATAR][1][23] = 20,
+ [0][1][RTW89_QATAR][0][23] = -18,
+ [0][1][RTW89_UK][1][23] = 20,
+ [0][1][RTW89_UK][0][23] = -18,
+ [0][1][RTW89_FCC][1][25] = -40,
+ [0][1][RTW89_FCC][2][25] = 32,
+ [0][1][RTW89_ETSI][1][25] = 20,
+ [0][1][RTW89_ETSI][0][25] = -18,
+ [0][1][RTW89_MKK][1][25] = -4,
+ [0][1][RTW89_MKK][0][25] = -22,
+ [0][1][RTW89_IC][1][25] = -40,
+ [0][1][RTW89_KCC][1][25] = -14,
+ [0][1][RTW89_KCC][0][25] = -14,
+ [0][1][RTW89_ACMA][1][25] = 20,
+ [0][1][RTW89_ACMA][0][25] = -18,
+ [0][1][RTW89_CHILE][1][25] = -40,
+ [0][1][RTW89_QATAR][1][25] = 20,
+ [0][1][RTW89_QATAR][0][25] = -18,
+ [0][1][RTW89_UK][1][25] = 20,
+ [0][1][RTW89_UK][0][25] = -18,
+ [0][1][RTW89_FCC][1][27] = -40,
+ [0][1][RTW89_FCC][2][27] = 32,
+ [0][1][RTW89_ETSI][1][27] = 20,
+ [0][1][RTW89_ETSI][0][27] = -18,
+ [0][1][RTW89_MKK][1][27] = -4,
+ [0][1][RTW89_MKK][0][27] = -22,
+ [0][1][RTW89_IC][1][27] = -40,
+ [0][1][RTW89_KCC][1][27] = -14,
+ [0][1][RTW89_KCC][0][27] = -14,
+ [0][1][RTW89_ACMA][1][27] = 20,
+ [0][1][RTW89_ACMA][0][27] = -18,
+ [0][1][RTW89_CHILE][1][27] = -40,
+ [0][1][RTW89_QATAR][1][27] = 20,
+ [0][1][RTW89_QATAR][0][27] = -18,
+ [0][1][RTW89_UK][1][27] = 20,
+ [0][1][RTW89_UK][0][27] = -18,
+ [0][1][RTW89_FCC][1][29] = -40,
+ [0][1][RTW89_FCC][2][29] = 32,
+ [0][1][RTW89_ETSI][1][29] = 20,
+ [0][1][RTW89_ETSI][0][29] = -18,
+ [0][1][RTW89_MKK][1][29] = -4,
+ [0][1][RTW89_MKK][0][29] = -22,
+ [0][1][RTW89_IC][1][29] = -40,
+ [0][1][RTW89_KCC][1][29] = -14,
+ [0][1][RTW89_KCC][0][29] = -14,
+ [0][1][RTW89_ACMA][1][29] = 20,
+ [0][1][RTW89_ACMA][0][29] = -18,
+ [0][1][RTW89_CHILE][1][29] = -40,
+ [0][1][RTW89_QATAR][1][29] = 20,
+ [0][1][RTW89_QATAR][0][29] = -18,
+ [0][1][RTW89_UK][1][29] = 20,
+ [0][1][RTW89_UK][0][29] = -18,
+ [0][1][RTW89_FCC][1][30] = -40,
+ [0][1][RTW89_FCC][2][30] = 32,
+ [0][1][RTW89_ETSI][1][30] = 20,
+ [0][1][RTW89_ETSI][0][30] = -18,
+ [0][1][RTW89_MKK][1][30] = -4,
+ [0][1][RTW89_MKK][0][30] = -22,
+ [0][1][RTW89_IC][1][30] = -40,
+ [0][1][RTW89_KCC][1][30] = -14,
+ [0][1][RTW89_KCC][0][30] = -14,
+ [0][1][RTW89_ACMA][1][30] = 20,
+ [0][1][RTW89_ACMA][0][30] = -18,
+ [0][1][RTW89_CHILE][1][30] = -40,
+ [0][1][RTW89_QATAR][1][30] = 20,
+ [0][1][RTW89_QATAR][0][30] = -18,
+ [0][1][RTW89_UK][1][30] = 20,
+ [0][1][RTW89_UK][0][30] = -18,
+ [0][1][RTW89_FCC][1][32] = -40,
+ [0][1][RTW89_FCC][2][32] = 32,
+ [0][1][RTW89_ETSI][1][32] = 20,
+ [0][1][RTW89_ETSI][0][32] = -18,
+ [0][1][RTW89_MKK][1][32] = -4,
+ [0][1][RTW89_MKK][0][32] = -22,
+ [0][1][RTW89_IC][1][32] = -40,
+ [0][1][RTW89_KCC][1][32] = -14,
+ [0][1][RTW89_KCC][0][32] = -14,
+ [0][1][RTW89_ACMA][1][32] = 20,
+ [0][1][RTW89_ACMA][0][32] = -18,
+ [0][1][RTW89_CHILE][1][32] = -40,
+ [0][1][RTW89_QATAR][1][32] = 20,
+ [0][1][RTW89_QATAR][0][32] = -18,
+ [0][1][RTW89_UK][1][32] = 20,
+ [0][1][RTW89_UK][0][32] = -18,
+ [0][1][RTW89_FCC][1][34] = -40,
+ [0][1][RTW89_FCC][2][34] = 32,
+ [0][1][RTW89_ETSI][1][34] = 20,
+ [0][1][RTW89_ETSI][0][34] = -18,
+ [0][1][RTW89_MKK][1][34] = -4,
+ [0][1][RTW89_MKK][0][34] = -22,
+ [0][1][RTW89_IC][1][34] = -40,
+ [0][1][RTW89_KCC][1][34] = -14,
+ [0][1][RTW89_KCC][0][34] = -14,
+ [0][1][RTW89_ACMA][1][34] = 20,
+ [0][1][RTW89_ACMA][0][34] = -18,
+ [0][1][RTW89_CHILE][1][34] = -40,
+ [0][1][RTW89_QATAR][1][34] = 20,
+ [0][1][RTW89_QATAR][0][34] = -18,
+ [0][1][RTW89_UK][1][34] = 20,
+ [0][1][RTW89_UK][0][34] = -18,
+ [0][1][RTW89_FCC][1][36] = -40,
+ [0][1][RTW89_FCC][2][36] = 32,
+ [0][1][RTW89_ETSI][1][36] = 20,
+ [0][1][RTW89_ETSI][0][36] = -18,
+ [0][1][RTW89_MKK][1][36] = -4,
+ [0][1][RTW89_MKK][0][36] = -22,
+ [0][1][RTW89_IC][1][36] = -40,
+ [0][1][RTW89_KCC][1][36] = -14,
+ [0][1][RTW89_KCC][0][36] = -14,
+ [0][1][RTW89_ACMA][1][36] = 20,
+ [0][1][RTW89_ACMA][0][36] = -18,
+ [0][1][RTW89_CHILE][1][36] = -40,
+ [0][1][RTW89_QATAR][1][36] = 20,
+ [0][1][RTW89_QATAR][0][36] = -18,
+ [0][1][RTW89_UK][1][36] = 20,
+ [0][1][RTW89_UK][0][36] = -18,
+ [0][1][RTW89_FCC][1][38] = -40,
+ [0][1][RTW89_FCC][2][38] = 32,
+ [0][1][RTW89_ETSI][1][38] = 20,
+ [0][1][RTW89_ETSI][0][38] = -18,
+ [0][1][RTW89_MKK][1][38] = -4,
+ [0][1][RTW89_MKK][0][38] = -22,
+ [0][1][RTW89_IC][1][38] = -40,
+ [0][1][RTW89_KCC][1][38] = -14,
+ [0][1][RTW89_KCC][0][38] = -14,
+ [0][1][RTW89_ACMA][1][38] = 20,
+ [0][1][RTW89_ACMA][0][38] = -18,
+ [0][1][RTW89_CHILE][1][38] = -40,
+ [0][1][RTW89_QATAR][1][38] = 20,
+ [0][1][RTW89_QATAR][0][38] = -18,
+ [0][1][RTW89_UK][1][38] = 20,
+ [0][1][RTW89_UK][0][38] = -18,
+ [0][1][RTW89_FCC][1][40] = -40,
+ [0][1][RTW89_FCC][2][40] = 32,
+ [0][1][RTW89_ETSI][1][40] = 20,
+ [0][1][RTW89_ETSI][0][40] = -18,
+ [0][1][RTW89_MKK][1][40] = -4,
+ [0][1][RTW89_MKK][0][40] = -22,
+ [0][1][RTW89_IC][1][40] = -40,
+ [0][1][RTW89_KCC][1][40] = -14,
+ [0][1][RTW89_KCC][0][40] = -14,
+ [0][1][RTW89_ACMA][1][40] = 20,
+ [0][1][RTW89_ACMA][0][40] = -18,
+ [0][1][RTW89_CHILE][1][40] = -40,
+ [0][1][RTW89_QATAR][1][40] = 20,
+ [0][1][RTW89_QATAR][0][40] = -18,
+ [0][1][RTW89_UK][1][40] = 20,
+ [0][1][RTW89_UK][0][40] = -18,
+ [0][1][RTW89_FCC][1][42] = -40,
+ [0][1][RTW89_FCC][2][42] = 32,
+ [0][1][RTW89_ETSI][1][42] = 20,
+ [0][1][RTW89_ETSI][0][42] = -18,
+ [0][1][RTW89_MKK][1][42] = -4,
+ [0][1][RTW89_MKK][0][42] = -22,
+ [0][1][RTW89_IC][1][42] = -40,
+ [0][1][RTW89_KCC][1][42] = -14,
+ [0][1][RTW89_KCC][0][42] = -14,
+ [0][1][RTW89_ACMA][1][42] = 20,
+ [0][1][RTW89_ACMA][0][42] = -18,
+ [0][1][RTW89_CHILE][1][42] = -40,
+ [0][1][RTW89_QATAR][1][42] = 20,
+ [0][1][RTW89_QATAR][0][42] = -18,
+ [0][1][RTW89_UK][1][42] = 20,
+ [0][1][RTW89_UK][0][42] = -18,
+ [0][1][RTW89_FCC][1][44] = -40,
+ [0][1][RTW89_FCC][2][44] = 32,
+ [0][1][RTW89_ETSI][1][44] = 20,
+ [0][1][RTW89_ETSI][0][44] = -18,
+ [0][1][RTW89_MKK][1][44] = -4,
+ [0][1][RTW89_MKK][0][44] = -22,
+ [0][1][RTW89_IC][1][44] = -40,
+ [0][1][RTW89_KCC][1][44] = -14,
+ [0][1][RTW89_KCC][0][44] = -14,
+ [0][1][RTW89_ACMA][1][44] = 20,
+ [0][1][RTW89_ACMA][0][44] = -18,
+ [0][1][RTW89_CHILE][1][44] = -40,
+ [0][1][RTW89_QATAR][1][44] = 20,
+ [0][1][RTW89_QATAR][0][44] = -18,
+ [0][1][RTW89_UK][1][44] = 20,
+ [0][1][RTW89_UK][0][44] = -18,
+ [0][1][RTW89_FCC][1][45] = -40,
+ [0][1][RTW89_FCC][2][45] = 127,
+ [0][1][RTW89_ETSI][1][45] = 127,
+ [0][1][RTW89_ETSI][0][45] = 127,
+ [0][1][RTW89_MKK][1][45] = 127,
+ [0][1][RTW89_MKK][0][45] = 127,
+ [0][1][RTW89_IC][1][45] = -40,
+ [0][1][RTW89_KCC][1][45] = -14,
+ [0][1][RTW89_KCC][0][45] = 127,
+ [0][1][RTW89_ACMA][1][45] = 127,
+ [0][1][RTW89_ACMA][0][45] = 127,
+ [0][1][RTW89_CHILE][1][45] = 127,
+ [0][1][RTW89_QATAR][1][45] = 127,
+ [0][1][RTW89_QATAR][0][45] = 127,
+ [0][1][RTW89_UK][1][45] = 127,
+ [0][1][RTW89_UK][0][45] = 127,
+ [0][1][RTW89_FCC][1][47] = -40,
+ [0][1][RTW89_FCC][2][47] = 127,
+ [0][1][RTW89_ETSI][1][47] = 127,
+ [0][1][RTW89_ETSI][0][47] = 127,
+ [0][1][RTW89_MKK][1][47] = 127,
+ [0][1][RTW89_MKK][0][47] = 127,
+ [0][1][RTW89_IC][1][47] = -40,
+ [0][1][RTW89_KCC][1][47] = -14,
+ [0][1][RTW89_KCC][0][47] = 127,
+ [0][1][RTW89_ACMA][1][47] = 127,
+ [0][1][RTW89_ACMA][0][47] = 127,
+ [0][1][RTW89_CHILE][1][47] = 127,
+ [0][1][RTW89_QATAR][1][47] = 127,
+ [0][1][RTW89_QATAR][0][47] = 127,
+ [0][1][RTW89_UK][1][47] = 127,
+ [0][1][RTW89_UK][0][47] = 127,
+ [0][1][RTW89_FCC][1][49] = -40,
+ [0][1][RTW89_FCC][2][49] = 127,
+ [0][1][RTW89_ETSI][1][49] = 127,
+ [0][1][RTW89_ETSI][0][49] = 127,
+ [0][1][RTW89_MKK][1][49] = 127,
+ [0][1][RTW89_MKK][0][49] = 127,
+ [0][1][RTW89_IC][1][49] = -40,
+ [0][1][RTW89_KCC][1][49] = -14,
+ [0][1][RTW89_KCC][0][49] = 127,
+ [0][1][RTW89_ACMA][1][49] = 127,
+ [0][1][RTW89_ACMA][0][49] = 127,
+ [0][1][RTW89_CHILE][1][49] = 127,
+ [0][1][RTW89_QATAR][1][49] = 127,
+ [0][1][RTW89_QATAR][0][49] = 127,
+ [0][1][RTW89_UK][1][49] = 127,
+ [0][1][RTW89_UK][0][49] = 127,
+ [0][1][RTW89_FCC][1][51] = -40,
+ [0][1][RTW89_FCC][2][51] = 127,
+ [0][1][RTW89_ETSI][1][51] = 127,
+ [0][1][RTW89_ETSI][0][51] = 127,
+ [0][1][RTW89_MKK][1][51] = 127,
+ [0][1][RTW89_MKK][0][51] = 127,
+ [0][1][RTW89_IC][1][51] = -40,
+ [0][1][RTW89_KCC][1][51] = -14,
+ [0][1][RTW89_KCC][0][51] = 127,
+ [0][1][RTW89_ACMA][1][51] = 127,
+ [0][1][RTW89_ACMA][0][51] = 127,
+ [0][1][RTW89_CHILE][1][51] = 127,
+ [0][1][RTW89_QATAR][1][51] = 127,
+ [0][1][RTW89_QATAR][0][51] = 127,
+ [0][1][RTW89_UK][1][51] = 127,
+ [0][1][RTW89_UK][0][51] = 127,
+ [0][1][RTW89_FCC][1][53] = -40,
+ [0][1][RTW89_FCC][2][53] = 127,
+ [0][1][RTW89_ETSI][1][53] = 127,
+ [0][1][RTW89_ETSI][0][53] = 127,
+ [0][1][RTW89_MKK][1][53] = 127,
+ [0][1][RTW89_MKK][0][53] = 127,
+ [0][1][RTW89_IC][1][53] = -40,
+ [0][1][RTW89_KCC][1][53] = -14,
+ [0][1][RTW89_KCC][0][53] = 127,
+ [0][1][RTW89_ACMA][1][53] = 127,
+ [0][1][RTW89_ACMA][0][53] = 127,
+ [0][1][RTW89_CHILE][1][53] = 127,
+ [0][1][RTW89_QATAR][1][53] = 127,
+ [0][1][RTW89_QATAR][0][53] = 127,
+ [0][1][RTW89_UK][1][53] = 127,
+ [0][1][RTW89_UK][0][53] = 127,
+ [0][1][RTW89_FCC][1][55] = -40,
+ [0][1][RTW89_FCC][2][55] = 30,
+ [0][1][RTW89_ETSI][1][55] = 127,
+ [0][1][RTW89_ETSI][0][55] = 127,
+ [0][1][RTW89_MKK][1][55] = 127,
+ [0][1][RTW89_MKK][0][55] = 127,
+ [0][1][RTW89_IC][1][55] = -40,
+ [0][1][RTW89_KCC][1][55] = -14,
+ [0][1][RTW89_KCC][0][55] = 127,
+ [0][1][RTW89_ACMA][1][55] = 127,
+ [0][1][RTW89_ACMA][0][55] = 127,
+ [0][1][RTW89_CHILE][1][55] = 127,
+ [0][1][RTW89_QATAR][1][55] = 127,
+ [0][1][RTW89_QATAR][0][55] = 127,
+ [0][1][RTW89_UK][1][55] = 127,
+ [0][1][RTW89_UK][0][55] = 127,
+ [0][1][RTW89_FCC][1][57] = -40,
+ [0][1][RTW89_FCC][2][57] = 30,
+ [0][1][RTW89_ETSI][1][57] = 127,
+ [0][1][RTW89_ETSI][0][57] = 127,
+ [0][1][RTW89_MKK][1][57] = 127,
+ [0][1][RTW89_MKK][0][57] = 127,
+ [0][1][RTW89_IC][1][57] = -40,
+ [0][1][RTW89_KCC][1][57] = -14,
+ [0][1][RTW89_KCC][0][57] = 127,
+ [0][1][RTW89_ACMA][1][57] = 127,
+ [0][1][RTW89_ACMA][0][57] = 127,
+ [0][1][RTW89_CHILE][1][57] = 127,
+ [0][1][RTW89_QATAR][1][57] = 127,
+ [0][1][RTW89_QATAR][0][57] = 127,
+ [0][1][RTW89_UK][1][57] = 127,
+ [0][1][RTW89_UK][0][57] = 127,
+ [0][1][RTW89_FCC][1][59] = -40,
+ [0][1][RTW89_FCC][2][59] = 30,
+ [0][1][RTW89_ETSI][1][59] = 127,
+ [0][1][RTW89_ETSI][0][59] = 127,
+ [0][1][RTW89_MKK][1][59] = 127,
+ [0][1][RTW89_MKK][0][59] = 127,
+ [0][1][RTW89_IC][1][59] = -40,
+ [0][1][RTW89_KCC][1][59] = -14,
+ [0][1][RTW89_KCC][0][59] = 127,
+ [0][1][RTW89_ACMA][1][59] = 127,
+ [0][1][RTW89_ACMA][0][59] = 127,
+ [0][1][RTW89_CHILE][1][59] = 127,
+ [0][1][RTW89_QATAR][1][59] = 127,
+ [0][1][RTW89_QATAR][0][59] = 127,
+ [0][1][RTW89_UK][1][59] = 127,
+ [0][1][RTW89_UK][0][59] = 127,
+ [0][1][RTW89_FCC][1][60] = -40,
+ [0][1][RTW89_FCC][2][60] = 30,
+ [0][1][RTW89_ETSI][1][60] = 127,
+ [0][1][RTW89_ETSI][0][60] = 127,
+ [0][1][RTW89_MKK][1][60] = 127,
+ [0][1][RTW89_MKK][0][60] = 127,
+ [0][1][RTW89_IC][1][60] = -40,
+ [0][1][RTW89_KCC][1][60] = -14,
+ [0][1][RTW89_KCC][0][60] = 127,
+ [0][1][RTW89_ACMA][1][60] = 127,
+ [0][1][RTW89_ACMA][0][60] = 127,
+ [0][1][RTW89_CHILE][1][60] = 127,
+ [0][1][RTW89_QATAR][1][60] = 127,
+ [0][1][RTW89_QATAR][0][60] = 127,
+ [0][1][RTW89_UK][1][60] = 127,
+ [0][1][RTW89_UK][0][60] = 127,
+ [0][1][RTW89_FCC][1][62] = -40,
+ [0][1][RTW89_FCC][2][62] = 30,
+ [0][1][RTW89_ETSI][1][62] = 127,
+ [0][1][RTW89_ETSI][0][62] = 127,
+ [0][1][RTW89_MKK][1][62] = 127,
+ [0][1][RTW89_MKK][0][62] = 127,
+ [0][1][RTW89_IC][1][62] = -40,
+ [0][1][RTW89_KCC][1][62] = -14,
+ [0][1][RTW89_KCC][0][62] = 127,
+ [0][1][RTW89_ACMA][1][62] = 127,
+ [0][1][RTW89_ACMA][0][62] = 127,
+ [0][1][RTW89_CHILE][1][62] = 127,
+ [0][1][RTW89_QATAR][1][62] = 127,
+ [0][1][RTW89_QATAR][0][62] = 127,
+ [0][1][RTW89_UK][1][62] = 127,
+ [0][1][RTW89_UK][0][62] = 127,
+ [0][1][RTW89_FCC][1][64] = -40,
+ [0][1][RTW89_FCC][2][64] = 30,
+ [0][1][RTW89_ETSI][1][64] = 127,
+ [0][1][RTW89_ETSI][0][64] = 127,
+ [0][1][RTW89_MKK][1][64] = 127,
+ [0][1][RTW89_MKK][0][64] = 127,
+ [0][1][RTW89_IC][1][64] = -40,
+ [0][1][RTW89_KCC][1][64] = -14,
+ [0][1][RTW89_KCC][0][64] = 127,
+ [0][1][RTW89_ACMA][1][64] = 127,
+ [0][1][RTW89_ACMA][0][64] = 127,
+ [0][1][RTW89_CHILE][1][64] = 127,
+ [0][1][RTW89_QATAR][1][64] = 127,
+ [0][1][RTW89_QATAR][0][64] = 127,
+ [0][1][RTW89_UK][1][64] = 127,
+ [0][1][RTW89_UK][0][64] = 127,
+ [0][1][RTW89_FCC][1][66] = -40,
+ [0][1][RTW89_FCC][2][66] = 30,
+ [0][1][RTW89_ETSI][1][66] = 127,
+ [0][1][RTW89_ETSI][0][66] = 127,
+ [0][1][RTW89_MKK][1][66] = 127,
+ [0][1][RTW89_MKK][0][66] = 127,
+ [0][1][RTW89_IC][1][66] = -40,
+ [0][1][RTW89_KCC][1][66] = -14,
+ [0][1][RTW89_KCC][0][66] = 127,
+ [0][1][RTW89_ACMA][1][66] = 127,
+ [0][1][RTW89_ACMA][0][66] = 127,
+ [0][1][RTW89_CHILE][1][66] = 127,
+ [0][1][RTW89_QATAR][1][66] = 127,
+ [0][1][RTW89_QATAR][0][66] = 127,
+ [0][1][RTW89_UK][1][66] = 127,
+ [0][1][RTW89_UK][0][66] = 127,
+ [0][1][RTW89_FCC][1][68] = -40,
+ [0][1][RTW89_FCC][2][68] = 30,
+ [0][1][RTW89_ETSI][1][68] = 127,
+ [0][1][RTW89_ETSI][0][68] = 127,
+ [0][1][RTW89_MKK][1][68] = 127,
+ [0][1][RTW89_MKK][0][68] = 127,
+ [0][1][RTW89_IC][1][68] = -40,
+ [0][1][RTW89_KCC][1][68] = -14,
+ [0][1][RTW89_KCC][0][68] = 127,
+ [0][1][RTW89_ACMA][1][68] = 127,
+ [0][1][RTW89_ACMA][0][68] = 127,
+ [0][1][RTW89_CHILE][1][68] = 127,
+ [0][1][RTW89_QATAR][1][68] = 127,
+ [0][1][RTW89_QATAR][0][68] = 127,
+ [0][1][RTW89_UK][1][68] = 127,
+ [0][1][RTW89_UK][0][68] = 127,
+ [0][1][RTW89_FCC][1][70] = -38,
+ [0][1][RTW89_FCC][2][70] = 30,
+ [0][1][RTW89_ETSI][1][70] = 127,
+ [0][1][RTW89_ETSI][0][70] = 127,
+ [0][1][RTW89_MKK][1][70] = 127,
+ [0][1][RTW89_MKK][0][70] = 127,
+ [0][1][RTW89_IC][1][70] = -38,
+ [0][1][RTW89_KCC][1][70] = -14,
+ [0][1][RTW89_KCC][0][70] = 127,
+ [0][1][RTW89_ACMA][1][70] = 127,
+ [0][1][RTW89_ACMA][0][70] = 127,
+ [0][1][RTW89_CHILE][1][70] = 127,
+ [0][1][RTW89_QATAR][1][70] = 127,
+ [0][1][RTW89_QATAR][0][70] = 127,
+ [0][1][RTW89_UK][1][70] = 127,
+ [0][1][RTW89_UK][0][70] = 127,
+ [0][1][RTW89_FCC][1][72] = -38,
+ [0][1][RTW89_FCC][2][72] = 30,
+ [0][1][RTW89_ETSI][1][72] = 127,
+ [0][1][RTW89_ETSI][0][72] = 127,
+ [0][1][RTW89_MKK][1][72] = 127,
+ [0][1][RTW89_MKK][0][72] = 127,
+ [0][1][RTW89_IC][1][72] = -38,
+ [0][1][RTW89_KCC][1][72] = -14,
+ [0][1][RTW89_KCC][0][72] = 127,
+ [0][1][RTW89_ACMA][1][72] = 127,
+ [0][1][RTW89_ACMA][0][72] = 127,
+ [0][1][RTW89_CHILE][1][72] = 127,
+ [0][1][RTW89_QATAR][1][72] = 127,
+ [0][1][RTW89_QATAR][0][72] = 127,
+ [0][1][RTW89_UK][1][72] = 127,
+ [0][1][RTW89_UK][0][72] = 127,
+ [0][1][RTW89_FCC][1][74] = -38,
+ [0][1][RTW89_FCC][2][74] = 30,
+ [0][1][RTW89_ETSI][1][74] = 127,
+ [0][1][RTW89_ETSI][0][74] = 127,
+ [0][1][RTW89_MKK][1][74] = 127,
+ [0][1][RTW89_MKK][0][74] = 127,
+ [0][1][RTW89_IC][1][74] = -38,
+ [0][1][RTW89_KCC][1][74] = -14,
+ [0][1][RTW89_KCC][0][74] = 127,
+ [0][1][RTW89_ACMA][1][74] = 127,
+ [0][1][RTW89_ACMA][0][74] = 127,
+ [0][1][RTW89_CHILE][1][74] = 127,
+ [0][1][RTW89_QATAR][1][74] = 127,
+ [0][1][RTW89_QATAR][0][74] = 127,
+ [0][1][RTW89_UK][1][74] = 127,
+ [0][1][RTW89_UK][0][74] = 127,
+ [0][1][RTW89_FCC][1][75] = -38,
+ [0][1][RTW89_FCC][2][75] = 30,
+ [0][1][RTW89_ETSI][1][75] = 127,
+ [0][1][RTW89_ETSI][0][75] = 127,
+ [0][1][RTW89_MKK][1][75] = 127,
+ [0][1][RTW89_MKK][0][75] = 127,
+ [0][1][RTW89_IC][1][75] = -38,
+ [0][1][RTW89_KCC][1][75] = -14,
+ [0][1][RTW89_KCC][0][75] = 127,
+ [0][1][RTW89_ACMA][1][75] = 127,
+ [0][1][RTW89_ACMA][0][75] = 127,
+ [0][1][RTW89_CHILE][1][75] = 127,
+ [0][1][RTW89_QATAR][1][75] = 127,
+ [0][1][RTW89_QATAR][0][75] = 127,
+ [0][1][RTW89_UK][1][75] = 127,
+ [0][1][RTW89_UK][0][75] = 127,
+ [0][1][RTW89_FCC][1][77] = -38,
+ [0][1][RTW89_FCC][2][77] = 30,
+ [0][1][RTW89_ETSI][1][77] = 127,
+ [0][1][RTW89_ETSI][0][77] = 127,
+ [0][1][RTW89_MKK][1][77] = 127,
+ [0][1][RTW89_MKK][0][77] = 127,
+ [0][1][RTW89_IC][1][77] = -38,
+ [0][1][RTW89_KCC][1][77] = -14,
+ [0][1][RTW89_KCC][0][77] = 127,
+ [0][1][RTW89_ACMA][1][77] = 127,
+ [0][1][RTW89_ACMA][0][77] = 127,
+ [0][1][RTW89_CHILE][1][77] = 127,
+ [0][1][RTW89_QATAR][1][77] = 127,
+ [0][1][RTW89_QATAR][0][77] = 127,
+ [0][1][RTW89_UK][1][77] = 127,
+ [0][1][RTW89_UK][0][77] = 127,
+ [0][1][RTW89_FCC][1][79] = -38,
+ [0][1][RTW89_FCC][2][79] = 30,
+ [0][1][RTW89_ETSI][1][79] = 127,
+ [0][1][RTW89_ETSI][0][79] = 127,
+ [0][1][RTW89_MKK][1][79] = 127,
+ [0][1][RTW89_MKK][0][79] = 127,
+ [0][1][RTW89_IC][1][79] = -38,
+ [0][1][RTW89_KCC][1][79] = -14,
+ [0][1][RTW89_KCC][0][79] = 127,
+ [0][1][RTW89_ACMA][1][79] = 127,
+ [0][1][RTW89_ACMA][0][79] = 127,
+ [0][1][RTW89_CHILE][1][79] = 127,
+ [0][1][RTW89_QATAR][1][79] = 127,
+ [0][1][RTW89_QATAR][0][79] = 127,
+ [0][1][RTW89_UK][1][79] = 127,
+ [0][1][RTW89_UK][0][79] = 127,
+ [0][1][RTW89_FCC][1][81] = -38,
+ [0][1][RTW89_FCC][2][81] = 30,
+ [0][1][RTW89_ETSI][1][81] = 127,
+ [0][1][RTW89_ETSI][0][81] = 127,
+ [0][1][RTW89_MKK][1][81] = 127,
+ [0][1][RTW89_MKK][0][81] = 127,
+ [0][1][RTW89_IC][1][81] = -38,
+ [0][1][RTW89_KCC][1][81] = -14,
+ [0][1][RTW89_KCC][0][81] = 127,
+ [0][1][RTW89_ACMA][1][81] = 127,
+ [0][1][RTW89_ACMA][0][81] = 127,
+ [0][1][RTW89_CHILE][1][81] = 127,
+ [0][1][RTW89_QATAR][1][81] = 127,
+ [0][1][RTW89_QATAR][0][81] = 127,
+ [0][1][RTW89_UK][1][81] = 127,
+ [0][1][RTW89_UK][0][81] = 127,
+ [0][1][RTW89_FCC][1][83] = -38,
+ [0][1][RTW89_FCC][2][83] = 30,
+ [0][1][RTW89_ETSI][1][83] = 127,
+ [0][1][RTW89_ETSI][0][83] = 127,
+ [0][1][RTW89_MKK][1][83] = 127,
+ [0][1][RTW89_MKK][0][83] = 127,
+ [0][1][RTW89_IC][1][83] = -38,
+ [0][1][RTW89_KCC][1][83] = -14,
+ [0][1][RTW89_KCC][0][83] = 127,
+ [0][1][RTW89_ACMA][1][83] = 127,
+ [0][1][RTW89_ACMA][0][83] = 127,
+ [0][1][RTW89_CHILE][1][83] = 127,
+ [0][1][RTW89_QATAR][1][83] = 127,
+ [0][1][RTW89_QATAR][0][83] = 127,
+ [0][1][RTW89_UK][1][83] = 127,
+ [0][1][RTW89_UK][0][83] = 127,
+ [0][1][RTW89_FCC][1][85] = -38,
+ [0][1][RTW89_FCC][2][85] = 30,
+ [0][1][RTW89_ETSI][1][85] = 127,
+ [0][1][RTW89_ETSI][0][85] = 127,
+ [0][1][RTW89_MKK][1][85] = 127,
+ [0][1][RTW89_MKK][0][85] = 127,
+ [0][1][RTW89_IC][1][85] = -38,
+ [0][1][RTW89_KCC][1][85] = -14,
+ [0][1][RTW89_KCC][0][85] = 127,
+ [0][1][RTW89_ACMA][1][85] = 127,
+ [0][1][RTW89_ACMA][0][85] = 127,
+ [0][1][RTW89_CHILE][1][85] = 127,
+ [0][1][RTW89_QATAR][1][85] = 127,
+ [0][1][RTW89_QATAR][0][85] = 127,
+ [0][1][RTW89_UK][1][85] = 127,
+ [0][1][RTW89_UK][0][85] = 127,
+ [0][1][RTW89_FCC][1][87] = -40,
+ [0][1][RTW89_FCC][2][87] = 127,
+ [0][1][RTW89_ETSI][1][87] = 127,
+ [0][1][RTW89_ETSI][0][87] = 127,
+ [0][1][RTW89_MKK][1][87] = 127,
+ [0][1][RTW89_MKK][0][87] = 127,
+ [0][1][RTW89_IC][1][87] = -40,
+ [0][1][RTW89_KCC][1][87] = -14,
+ [0][1][RTW89_KCC][0][87] = 127,
+ [0][1][RTW89_ACMA][1][87] = 127,
+ [0][1][RTW89_ACMA][0][87] = 127,
+ [0][1][RTW89_CHILE][1][87] = 127,
+ [0][1][RTW89_QATAR][1][87] = 127,
+ [0][1][RTW89_QATAR][0][87] = 127,
+ [0][1][RTW89_UK][1][87] = 127,
+ [0][1][RTW89_UK][0][87] = 127,
+ [0][1][RTW89_FCC][1][89] = -38,
+ [0][1][RTW89_FCC][2][89] = 127,
+ [0][1][RTW89_ETSI][1][89] = 127,
+ [0][1][RTW89_ETSI][0][89] = 127,
+ [0][1][RTW89_MKK][1][89] = 127,
+ [0][1][RTW89_MKK][0][89] = 127,
+ [0][1][RTW89_IC][1][89] = -38,
+ [0][1][RTW89_KCC][1][89] = -14,
+ [0][1][RTW89_KCC][0][89] = 127,
+ [0][1][RTW89_ACMA][1][89] = 127,
+ [0][1][RTW89_ACMA][0][89] = 127,
+ [0][1][RTW89_CHILE][1][89] = 127,
+ [0][1][RTW89_QATAR][1][89] = 127,
+ [0][1][RTW89_QATAR][0][89] = 127,
+ [0][1][RTW89_UK][1][89] = 127,
+ [0][1][RTW89_UK][0][89] = 127,
+ [0][1][RTW89_FCC][1][90] = -38,
+ [0][1][RTW89_FCC][2][90] = 127,
+ [0][1][RTW89_ETSI][1][90] = 127,
+ [0][1][RTW89_ETSI][0][90] = 127,
+ [0][1][RTW89_MKK][1][90] = 127,
+ [0][1][RTW89_MKK][0][90] = 127,
+ [0][1][RTW89_IC][1][90] = -38,
+ [0][1][RTW89_KCC][1][90] = -14,
+ [0][1][RTW89_KCC][0][90] = 127,
+ [0][1][RTW89_ACMA][1][90] = 127,
+ [0][1][RTW89_ACMA][0][90] = 127,
+ [0][1][RTW89_CHILE][1][90] = 127,
+ [0][1][RTW89_QATAR][1][90] = 127,
+ [0][1][RTW89_QATAR][0][90] = 127,
+ [0][1][RTW89_UK][1][90] = 127,
+ [0][1][RTW89_UK][0][90] = 127,
+ [0][1][RTW89_FCC][1][92] = -38,
+ [0][1][RTW89_FCC][2][92] = 127,
+ [0][1][RTW89_ETSI][1][92] = 127,
+ [0][1][RTW89_ETSI][0][92] = 127,
+ [0][1][RTW89_MKK][1][92] = 127,
+ [0][1][RTW89_MKK][0][92] = 127,
+ [0][1][RTW89_IC][1][92] = -38,
+ [0][1][RTW89_KCC][1][92] = -14,
+ [0][1][RTW89_KCC][0][92] = 127,
+ [0][1][RTW89_ACMA][1][92] = 127,
+ [0][1][RTW89_ACMA][0][92] = 127,
+ [0][1][RTW89_CHILE][1][92] = 127,
+ [0][1][RTW89_QATAR][1][92] = 127,
+ [0][1][RTW89_QATAR][0][92] = 127,
+ [0][1][RTW89_UK][1][92] = 127,
+ [0][1][RTW89_UK][0][92] = 127,
+ [0][1][RTW89_FCC][1][94] = -38,
+ [0][1][RTW89_FCC][2][94] = 127,
+ [0][1][RTW89_ETSI][1][94] = 127,
+ [0][1][RTW89_ETSI][0][94] = 127,
+ [0][1][RTW89_MKK][1][94] = 127,
+ [0][1][RTW89_MKK][0][94] = 127,
+ [0][1][RTW89_IC][1][94] = -38,
+ [0][1][RTW89_KCC][1][94] = -14,
+ [0][1][RTW89_KCC][0][94] = 127,
+ [0][1][RTW89_ACMA][1][94] = 127,
+ [0][1][RTW89_ACMA][0][94] = 127,
+ [0][1][RTW89_CHILE][1][94] = 127,
+ [0][1][RTW89_QATAR][1][94] = 127,
+ [0][1][RTW89_QATAR][0][94] = 127,
+ [0][1][RTW89_UK][1][94] = 127,
+ [0][1][RTW89_UK][0][94] = 127,
+ [0][1][RTW89_FCC][1][96] = -38,
+ [0][1][RTW89_FCC][2][96] = 127,
+ [0][1][RTW89_ETSI][1][96] = 127,
+ [0][1][RTW89_ETSI][0][96] = 127,
+ [0][1][RTW89_MKK][1][96] = 127,
+ [0][1][RTW89_MKK][0][96] = 127,
+ [0][1][RTW89_IC][1][96] = -38,
+ [0][1][RTW89_KCC][1][96] = -14,
+ [0][1][RTW89_KCC][0][96] = 127,
+ [0][1][RTW89_ACMA][1][96] = 127,
+ [0][1][RTW89_ACMA][0][96] = 127,
+ [0][1][RTW89_CHILE][1][96] = 127,
+ [0][1][RTW89_QATAR][1][96] = 127,
+ [0][1][RTW89_QATAR][0][96] = 127,
+ [0][1][RTW89_UK][1][96] = 127,
+ [0][1][RTW89_UK][0][96] = 127,
+ [0][1][RTW89_FCC][1][98] = -38,
+ [0][1][RTW89_FCC][2][98] = 127,
+ [0][1][RTW89_ETSI][1][98] = 127,
+ [0][1][RTW89_ETSI][0][98] = 127,
+ [0][1][RTW89_MKK][1][98] = 127,
+ [0][1][RTW89_MKK][0][98] = 127,
+ [0][1][RTW89_IC][1][98] = -38,
+ [0][1][RTW89_KCC][1][98] = -14,
+ [0][1][RTW89_KCC][0][98] = 127,
+ [0][1][RTW89_ACMA][1][98] = 127,
+ [0][1][RTW89_ACMA][0][98] = 127,
+ [0][1][RTW89_CHILE][1][98] = 127,
+ [0][1][RTW89_QATAR][1][98] = 127,
+ [0][1][RTW89_QATAR][0][98] = 127,
+ [0][1][RTW89_UK][1][98] = 127,
+ [0][1][RTW89_UK][0][98] = 127,
+ [0][1][RTW89_FCC][1][100] = -38,
+ [0][1][RTW89_FCC][2][100] = 127,
+ [0][1][RTW89_ETSI][1][100] = 127,
+ [0][1][RTW89_ETSI][0][100] = 127,
+ [0][1][RTW89_MKK][1][100] = 127,
+ [0][1][RTW89_MKK][0][100] = 127,
+ [0][1][RTW89_IC][1][100] = -38,
+ [0][1][RTW89_KCC][1][100] = -14,
+ [0][1][RTW89_KCC][0][100] = 127,
+ [0][1][RTW89_ACMA][1][100] = 127,
+ [0][1][RTW89_ACMA][0][100] = 127,
+ [0][1][RTW89_CHILE][1][100] = 127,
+ [0][1][RTW89_QATAR][1][100] = 127,
+ [0][1][RTW89_QATAR][0][100] = 127,
+ [0][1][RTW89_UK][1][100] = 127,
+ [0][1][RTW89_UK][0][100] = 127,
+ [0][1][RTW89_FCC][1][102] = -38,
+ [0][1][RTW89_FCC][2][102] = 127,
+ [0][1][RTW89_ETSI][1][102] = 127,
+ [0][1][RTW89_ETSI][0][102] = 127,
+ [0][1][RTW89_MKK][1][102] = 127,
+ [0][1][RTW89_MKK][0][102] = 127,
+ [0][1][RTW89_IC][1][102] = -38,
+ [0][1][RTW89_KCC][1][102] = -14,
+ [0][1][RTW89_KCC][0][102] = 127,
+ [0][1][RTW89_ACMA][1][102] = 127,
+ [0][1][RTW89_ACMA][0][102] = 127,
+ [0][1][RTW89_CHILE][1][102] = 127,
+ [0][1][RTW89_QATAR][1][102] = 127,
+ [0][1][RTW89_QATAR][0][102] = 127,
+ [0][1][RTW89_UK][1][102] = 127,
+ [0][1][RTW89_UK][0][102] = 127,
+ [0][1][RTW89_FCC][1][104] = -38,
+ [0][1][RTW89_FCC][2][104] = 127,
+ [0][1][RTW89_ETSI][1][104] = 127,
+ [0][1][RTW89_ETSI][0][104] = 127,
+ [0][1][RTW89_MKK][1][104] = 127,
+ [0][1][RTW89_MKK][0][104] = 127,
+ [0][1][RTW89_IC][1][104] = -38,
+ [0][1][RTW89_KCC][1][104] = -14,
+ [0][1][RTW89_KCC][0][104] = 127,
+ [0][1][RTW89_ACMA][1][104] = 127,
+ [0][1][RTW89_ACMA][0][104] = 127,
+ [0][1][RTW89_CHILE][1][104] = 127,
+ [0][1][RTW89_QATAR][1][104] = 127,
+ [0][1][RTW89_QATAR][0][104] = 127,
+ [0][1][RTW89_UK][1][104] = 127,
+ [0][1][RTW89_UK][0][104] = 127,
+ [0][1][RTW89_FCC][1][105] = -38,
+ [0][1][RTW89_FCC][2][105] = 127,
+ [0][1][RTW89_ETSI][1][105] = 127,
+ [0][1][RTW89_ETSI][0][105] = 127,
+ [0][1][RTW89_MKK][1][105] = 127,
+ [0][1][RTW89_MKK][0][105] = 127,
+ [0][1][RTW89_IC][1][105] = -38,
+ [0][1][RTW89_KCC][1][105] = -14,
+ [0][1][RTW89_KCC][0][105] = 127,
+ [0][1][RTW89_ACMA][1][105] = 127,
+ [0][1][RTW89_ACMA][0][105] = 127,
+ [0][1][RTW89_CHILE][1][105] = 127,
+ [0][1][RTW89_QATAR][1][105] = 127,
+ [0][1][RTW89_QATAR][0][105] = 127,
+ [0][1][RTW89_UK][1][105] = 127,
+ [0][1][RTW89_UK][0][105] = 127,
+ [0][1][RTW89_FCC][1][107] = -34,
+ [0][1][RTW89_FCC][2][107] = 127,
+ [0][1][RTW89_ETSI][1][107] = 127,
+ [0][1][RTW89_ETSI][0][107] = 127,
+ [0][1][RTW89_MKK][1][107] = 127,
+ [0][1][RTW89_MKK][0][107] = 127,
+ [0][1][RTW89_IC][1][107] = -34,
+ [0][1][RTW89_KCC][1][107] = -14,
+ [0][1][RTW89_KCC][0][107] = 127,
+ [0][1][RTW89_ACMA][1][107] = 127,
+ [0][1][RTW89_ACMA][0][107] = 127,
+ [0][1][RTW89_CHILE][1][107] = 127,
+ [0][1][RTW89_QATAR][1][107] = 127,
+ [0][1][RTW89_QATAR][0][107] = 127,
+ [0][1][RTW89_UK][1][107] = 127,
+ [0][1][RTW89_UK][0][107] = 127,
+ [0][1][RTW89_FCC][1][109] = -34,
+ [0][1][RTW89_FCC][2][109] = 127,
+ [0][1][RTW89_ETSI][1][109] = 127,
+ [0][1][RTW89_ETSI][0][109] = 127,
+ [0][1][RTW89_MKK][1][109] = 127,
+ [0][1][RTW89_MKK][0][109] = 127,
+ [0][1][RTW89_IC][1][109] = -34,
+ [0][1][RTW89_KCC][1][109] = 127,
+ [0][1][RTW89_KCC][0][109] = 127,
+ [0][1][RTW89_ACMA][1][109] = 127,
+ [0][1][RTW89_ACMA][0][109] = 127,
+ [0][1][RTW89_CHILE][1][109] = 127,
+ [0][1][RTW89_QATAR][1][109] = 127,
+ [0][1][RTW89_QATAR][0][109] = 127,
+ [0][1][RTW89_UK][1][109] = 127,
+ [0][1][RTW89_UK][0][109] = 127,
+ [0][1][RTW89_FCC][1][111] = 127,
+ [0][1][RTW89_FCC][2][111] = 127,
+ [0][1][RTW89_ETSI][1][111] = 127,
+ [0][1][RTW89_ETSI][0][111] = 127,
+ [0][1][RTW89_MKK][1][111] = 127,
+ [0][1][RTW89_MKK][0][111] = 127,
+ [0][1][RTW89_IC][1][111] = 127,
+ [0][1][RTW89_KCC][1][111] = 127,
+ [0][1][RTW89_KCC][0][111] = 127,
+ [0][1][RTW89_ACMA][1][111] = 127,
+ [0][1][RTW89_ACMA][0][111] = 127,
+ [0][1][RTW89_CHILE][1][111] = 127,
+ [0][1][RTW89_QATAR][1][111] = 127,
+ [0][1][RTW89_QATAR][0][111] = 127,
+ [0][1][RTW89_UK][1][111] = 127,
+ [0][1][RTW89_UK][0][111] = 127,
+ [0][1][RTW89_FCC][1][113] = 127,
+ [0][1][RTW89_FCC][2][113] = 127,
+ [0][1][RTW89_ETSI][1][113] = 127,
+ [0][1][RTW89_ETSI][0][113] = 127,
+ [0][1][RTW89_MKK][1][113] = 127,
+ [0][1][RTW89_MKK][0][113] = 127,
+ [0][1][RTW89_IC][1][113] = 127,
+ [0][1][RTW89_KCC][1][113] = 127,
+ [0][1][RTW89_KCC][0][113] = 127,
+ [0][1][RTW89_ACMA][1][113] = 127,
+ [0][1][RTW89_ACMA][0][113] = 127,
+ [0][1][RTW89_CHILE][1][113] = 127,
+ [0][1][RTW89_QATAR][1][113] = 127,
+ [0][1][RTW89_QATAR][0][113] = 127,
+ [0][1][RTW89_UK][1][113] = 127,
+ [0][1][RTW89_UK][0][113] = 127,
+ [0][1][RTW89_FCC][1][115] = 127,
+ [0][1][RTW89_FCC][2][115] = 127,
+ [0][1][RTW89_ETSI][1][115] = 127,
+ [0][1][RTW89_ETSI][0][115] = 127,
+ [0][1][RTW89_MKK][1][115] = 127,
+ [0][1][RTW89_MKK][0][115] = 127,
+ [0][1][RTW89_IC][1][115] = 127,
+ [0][1][RTW89_KCC][1][115] = 127,
+ [0][1][RTW89_KCC][0][115] = 127,
+ [0][1][RTW89_ACMA][1][115] = 127,
+ [0][1][RTW89_ACMA][0][115] = 127,
+ [0][1][RTW89_CHILE][1][115] = 127,
+ [0][1][RTW89_QATAR][1][115] = 127,
+ [0][1][RTW89_QATAR][0][115] = 127,
+ [0][1][RTW89_UK][1][115] = 127,
+ [0][1][RTW89_UK][0][115] = 127,
+ [0][1][RTW89_FCC][1][117] = 127,
+ [0][1][RTW89_FCC][2][117] = 127,
+ [0][1][RTW89_ETSI][1][117] = 127,
+ [0][1][RTW89_ETSI][0][117] = 127,
+ [0][1][RTW89_MKK][1][117] = 127,
+ [0][1][RTW89_MKK][0][117] = 127,
+ [0][1][RTW89_IC][1][117] = 127,
+ [0][1][RTW89_KCC][1][117] = 127,
+ [0][1][RTW89_KCC][0][117] = 127,
+ [0][1][RTW89_ACMA][1][117] = 127,
+ [0][1][RTW89_ACMA][0][117] = 127,
+ [0][1][RTW89_CHILE][1][117] = 127,
+ [0][1][RTW89_QATAR][1][117] = 127,
+ [0][1][RTW89_QATAR][0][117] = 127,
+ [0][1][RTW89_UK][1][117] = 127,
+ [0][1][RTW89_UK][0][117] = 127,
+ [0][1][RTW89_FCC][1][119] = 127,
+ [0][1][RTW89_FCC][2][119] = 127,
+ [0][1][RTW89_ETSI][1][119] = 127,
+ [0][1][RTW89_ETSI][0][119] = 127,
+ [0][1][RTW89_MKK][1][119] = 127,
+ [0][1][RTW89_MKK][0][119] = 127,
+ [0][1][RTW89_IC][1][119] = 127,
+ [0][1][RTW89_KCC][1][119] = 127,
+ [0][1][RTW89_KCC][0][119] = 127,
+ [0][1][RTW89_ACMA][1][119] = 127,
+ [0][1][RTW89_ACMA][0][119] = 127,
+ [0][1][RTW89_CHILE][1][119] = 127,
+ [0][1][RTW89_QATAR][1][119] = 127,
+ [0][1][RTW89_QATAR][0][119] = 127,
+ [0][1][RTW89_UK][1][119] = 127,
+ [0][1][RTW89_UK][0][119] = 127,
+ [1][0][RTW89_FCC][1][0] = -4,
+ [1][0][RTW89_FCC][2][0] = 52,
+ [1][0][RTW89_ETSI][1][0] = 46,
+ [1][0][RTW89_ETSI][0][0] = 6,
+ [1][0][RTW89_MKK][1][0] = 42,
+ [1][0][RTW89_MKK][0][0] = 2,
+ [1][0][RTW89_IC][1][0] = -4,
+ [1][0][RTW89_KCC][1][0] = -2,
+ [1][0][RTW89_KCC][0][0] = -2,
+ [1][0][RTW89_ACMA][1][0] = 46,
+ [1][0][RTW89_ACMA][0][0] = 6,
+ [1][0][RTW89_CHILE][1][0] = -4,
+ [1][0][RTW89_QATAR][1][0] = 46,
+ [1][0][RTW89_QATAR][0][0] = 6,
+ [1][0][RTW89_UK][1][0] = 46,
+ [1][0][RTW89_UK][0][0] = 6,
+ [1][0][RTW89_FCC][1][2] = -4,
+ [1][0][RTW89_FCC][2][2] = 52,
+ [1][0][RTW89_ETSI][1][2] = 46,
+ [1][0][RTW89_ETSI][0][2] = 6,
+ [1][0][RTW89_MKK][1][2] = 42,
+ [1][0][RTW89_MKK][0][2] = 2,
+ [1][0][RTW89_IC][1][2] = -4,
+ [1][0][RTW89_KCC][1][2] = -2,
+ [1][0][RTW89_KCC][0][2] = -2,
+ [1][0][RTW89_ACMA][1][2] = 46,
+ [1][0][RTW89_ACMA][0][2] = 6,
+ [1][0][RTW89_CHILE][1][2] = -4,
+ [1][0][RTW89_QATAR][1][2] = 46,
+ [1][0][RTW89_QATAR][0][2] = 6,
+ [1][0][RTW89_UK][1][2] = 46,
+ [1][0][RTW89_UK][0][2] = 6,
+ [1][0][RTW89_FCC][1][4] = -4,
+ [1][0][RTW89_FCC][2][4] = 52,
+ [1][0][RTW89_ETSI][1][4] = 46,
+ [1][0][RTW89_ETSI][0][4] = 6,
+ [1][0][RTW89_MKK][1][4] = 42,
+ [1][0][RTW89_MKK][0][4] = 2,
+ [1][0][RTW89_IC][1][4] = -4,
+ [1][0][RTW89_KCC][1][4] = -2,
+ [1][0][RTW89_KCC][0][4] = -2,
+ [1][0][RTW89_ACMA][1][4] = 46,
+ [1][0][RTW89_ACMA][0][4] = 6,
+ [1][0][RTW89_CHILE][1][4] = -4,
+ [1][0][RTW89_QATAR][1][4] = 46,
+ [1][0][RTW89_QATAR][0][4] = 6,
+ [1][0][RTW89_UK][1][4] = 46,
+ [1][0][RTW89_UK][0][4] = 6,
+ [1][0][RTW89_FCC][1][6] = -4,
+ [1][0][RTW89_FCC][2][6] = 52,
+ [1][0][RTW89_ETSI][1][6] = 46,
+ [1][0][RTW89_ETSI][0][6] = 6,
+ [1][0][RTW89_MKK][1][6] = 42,
+ [1][0][RTW89_MKK][0][6] = 2,
+ [1][0][RTW89_IC][1][6] = -4,
+ [1][0][RTW89_KCC][1][6] = -2,
+ [1][0][RTW89_KCC][0][6] = -2,
+ [1][0][RTW89_ACMA][1][6] = 46,
+ [1][0][RTW89_ACMA][0][6] = 6,
+ [1][0][RTW89_CHILE][1][6] = -4,
+ [1][0][RTW89_QATAR][1][6] = 46,
+ [1][0][RTW89_QATAR][0][6] = 6,
+ [1][0][RTW89_UK][1][6] = 46,
+ [1][0][RTW89_UK][0][6] = 6,
+ [1][0][RTW89_FCC][1][8] = -4,
+ [1][0][RTW89_FCC][2][8] = 52,
+ [1][0][RTW89_ETSI][1][8] = 46,
+ [1][0][RTW89_ETSI][0][8] = 6,
+ [1][0][RTW89_MKK][1][8] = 42,
+ [1][0][RTW89_MKK][0][8] = 2,
+ [1][0][RTW89_IC][1][8] = -4,
+ [1][0][RTW89_KCC][1][8] = -2,
+ [1][0][RTW89_KCC][0][8] = -2,
+ [1][0][RTW89_ACMA][1][8] = 46,
+ [1][0][RTW89_ACMA][0][8] = 6,
+ [1][0][RTW89_CHILE][1][8] = -4,
+ [1][0][RTW89_QATAR][1][8] = 46,
+ [1][0][RTW89_QATAR][0][8] = 6,
+ [1][0][RTW89_UK][1][8] = 46,
+ [1][0][RTW89_UK][0][8] = 6,
+ [1][0][RTW89_FCC][1][10] = -4,
+ [1][0][RTW89_FCC][2][10] = 52,
+ [1][0][RTW89_ETSI][1][10] = 46,
+ [1][0][RTW89_ETSI][0][10] = 6,
+ [1][0][RTW89_MKK][1][10] = 42,
+ [1][0][RTW89_MKK][0][10] = 2,
+ [1][0][RTW89_IC][1][10] = -4,
+ [1][0][RTW89_KCC][1][10] = -2,
+ [1][0][RTW89_KCC][0][10] = -2,
+ [1][0][RTW89_ACMA][1][10] = 46,
+ [1][0][RTW89_ACMA][0][10] = 6,
+ [1][0][RTW89_CHILE][1][10] = -4,
+ [1][0][RTW89_QATAR][1][10] = 46,
+ [1][0][RTW89_QATAR][0][10] = 6,
+ [1][0][RTW89_UK][1][10] = 46,
+ [1][0][RTW89_UK][0][10] = 6,
+ [1][0][RTW89_FCC][1][12] = -4,
+ [1][0][RTW89_FCC][2][12] = 52,
+ [1][0][RTW89_ETSI][1][12] = 46,
+ [1][0][RTW89_ETSI][0][12] = 6,
+ [1][0][RTW89_MKK][1][12] = 42,
+ [1][0][RTW89_MKK][0][12] = 2,
+ [1][0][RTW89_IC][1][12] = -4,
+ [1][0][RTW89_KCC][1][12] = -2,
+ [1][0][RTW89_KCC][0][12] = -2,
+ [1][0][RTW89_ACMA][1][12] = 46,
+ [1][0][RTW89_ACMA][0][12] = 6,
+ [1][0][RTW89_CHILE][1][12] = -4,
+ [1][0][RTW89_QATAR][1][12] = 46,
+ [1][0][RTW89_QATAR][0][12] = 6,
+ [1][0][RTW89_UK][1][12] = 46,
+ [1][0][RTW89_UK][0][12] = 6,
+ [1][0][RTW89_FCC][1][14] = -4,
+ [1][0][RTW89_FCC][2][14] = 52,
+ [1][0][RTW89_ETSI][1][14] = 46,
+ [1][0][RTW89_ETSI][0][14] = 6,
+ [1][0][RTW89_MKK][1][14] = 42,
+ [1][0][RTW89_MKK][0][14] = 2,
+ [1][0][RTW89_IC][1][14] = -4,
+ [1][0][RTW89_KCC][1][14] = -2,
+ [1][0][RTW89_KCC][0][14] = -2,
+ [1][0][RTW89_ACMA][1][14] = 46,
+ [1][0][RTW89_ACMA][0][14] = 6,
+ [1][0][RTW89_CHILE][1][14] = -4,
+ [1][0][RTW89_QATAR][1][14] = 46,
+ [1][0][RTW89_QATAR][0][14] = 6,
+ [1][0][RTW89_UK][1][14] = 46,
+ [1][0][RTW89_UK][0][14] = 6,
+ [1][0][RTW89_FCC][1][15] = -4,
+ [1][0][RTW89_FCC][2][15] = 52,
+ [1][0][RTW89_ETSI][1][15] = 46,
+ [1][0][RTW89_ETSI][0][15] = 6,
+ [1][0][RTW89_MKK][1][15] = 42,
+ [1][0][RTW89_MKK][0][15] = 2,
+ [1][0][RTW89_IC][1][15] = -4,
+ [1][0][RTW89_KCC][1][15] = -2,
+ [1][0][RTW89_KCC][0][15] = -2,
+ [1][0][RTW89_ACMA][1][15] = 46,
+ [1][0][RTW89_ACMA][0][15] = 6,
+ [1][0][RTW89_CHILE][1][15] = -4,
+ [1][0][RTW89_QATAR][1][15] = 46,
+ [1][0][RTW89_QATAR][0][15] = 6,
+ [1][0][RTW89_UK][1][15] = 46,
+ [1][0][RTW89_UK][0][15] = 6,
+ [1][0][RTW89_FCC][1][17] = -4,
+ [1][0][RTW89_FCC][2][17] = 52,
+ [1][0][RTW89_ETSI][1][17] = 46,
+ [1][0][RTW89_ETSI][0][17] = 6,
+ [1][0][RTW89_MKK][1][17] = 42,
+ [1][0][RTW89_MKK][0][17] = 2,
+ [1][0][RTW89_IC][1][17] = -4,
+ [1][0][RTW89_KCC][1][17] = -2,
+ [1][0][RTW89_KCC][0][17] = -2,
+ [1][0][RTW89_ACMA][1][17] = 46,
+ [1][0][RTW89_ACMA][0][17] = 6,
+ [1][0][RTW89_CHILE][1][17] = -4,
+ [1][0][RTW89_QATAR][1][17] = 46,
+ [1][0][RTW89_QATAR][0][17] = 6,
+ [1][0][RTW89_UK][1][17] = 46,
+ [1][0][RTW89_UK][0][17] = 6,
+ [1][0][RTW89_FCC][1][19] = -4,
+ [1][0][RTW89_FCC][2][19] = 52,
+ [1][0][RTW89_ETSI][1][19] = 46,
+ [1][0][RTW89_ETSI][0][19] = 6,
+ [1][0][RTW89_MKK][1][19] = 42,
+ [1][0][RTW89_MKK][0][19] = 2,
+ [1][0][RTW89_IC][1][19] = -4,
+ [1][0][RTW89_KCC][1][19] = -2,
+ [1][0][RTW89_KCC][0][19] = -2,
+ [1][0][RTW89_ACMA][1][19] = 46,
+ [1][0][RTW89_ACMA][0][19] = 6,
+ [1][0][RTW89_CHILE][1][19] = -4,
+ [1][0][RTW89_QATAR][1][19] = 46,
+ [1][0][RTW89_QATAR][0][19] = 6,
+ [1][0][RTW89_UK][1][19] = 46,
+ [1][0][RTW89_UK][0][19] = 6,
+ [1][0][RTW89_FCC][1][21] = -4,
+ [1][0][RTW89_FCC][2][21] = 52,
+ [1][0][RTW89_ETSI][1][21] = 46,
+ [1][0][RTW89_ETSI][0][21] = 6,
+ [1][0][RTW89_MKK][1][21] = 42,
+ [1][0][RTW89_MKK][0][21] = 2,
+ [1][0][RTW89_IC][1][21] = -4,
+ [1][0][RTW89_KCC][1][21] = -2,
+ [1][0][RTW89_KCC][0][21] = -2,
+ [1][0][RTW89_ACMA][1][21] = 46,
+ [1][0][RTW89_ACMA][0][21] = 6,
+ [1][0][RTW89_CHILE][1][21] = -4,
+ [1][0][RTW89_QATAR][1][21] = 46,
+ [1][0][RTW89_QATAR][0][21] = 6,
+ [1][0][RTW89_UK][1][21] = 46,
+ [1][0][RTW89_UK][0][21] = 6,
+ [1][0][RTW89_FCC][1][23] = -4,
+ [1][0][RTW89_FCC][2][23] = 66,
+ [1][0][RTW89_ETSI][1][23] = 46,
+ [1][0][RTW89_ETSI][0][23] = 6,
+ [1][0][RTW89_MKK][1][23] = 42,
+ [1][0][RTW89_MKK][0][23] = 2,
+ [1][0][RTW89_IC][1][23] = -4,
+ [1][0][RTW89_KCC][1][23] = -2,
+ [1][0][RTW89_KCC][0][23] = -2,
+ [1][0][RTW89_ACMA][1][23] = 46,
+ [1][0][RTW89_ACMA][0][23] = 6,
+ [1][0][RTW89_CHILE][1][23] = -4,
+ [1][0][RTW89_QATAR][1][23] = 46,
+ [1][0][RTW89_QATAR][0][23] = 6,
+ [1][0][RTW89_UK][1][23] = 46,
+ [1][0][RTW89_UK][0][23] = 6,
+ [1][0][RTW89_FCC][1][25] = -4,
+ [1][0][RTW89_FCC][2][25] = 66,
+ [1][0][RTW89_ETSI][1][25] = 46,
+ [1][0][RTW89_ETSI][0][25] = 6,
+ [1][0][RTW89_MKK][1][25] = 42,
+ [1][0][RTW89_MKK][0][25] = 2,
+ [1][0][RTW89_IC][1][25] = -4,
+ [1][0][RTW89_KCC][1][25] = -2,
+ [1][0][RTW89_KCC][0][25] = -2,
+ [1][0][RTW89_ACMA][1][25] = 46,
+ [1][0][RTW89_ACMA][0][25] = 6,
+ [1][0][RTW89_CHILE][1][25] = -4,
+ [1][0][RTW89_QATAR][1][25] = 46,
+ [1][0][RTW89_QATAR][0][25] = 6,
+ [1][0][RTW89_UK][1][25] = 46,
+ [1][0][RTW89_UK][0][25] = 6,
+ [1][0][RTW89_FCC][1][27] = -4,
+ [1][0][RTW89_FCC][2][27] = 66,
+ [1][0][RTW89_ETSI][1][27] = 46,
+ [1][0][RTW89_ETSI][0][27] = 6,
+ [1][0][RTW89_MKK][1][27] = 42,
+ [1][0][RTW89_MKK][0][27] = 2,
+ [1][0][RTW89_IC][1][27] = -4,
+ [1][0][RTW89_KCC][1][27] = -2,
+ [1][0][RTW89_KCC][0][27] = -2,
+ [1][0][RTW89_ACMA][1][27] = 46,
+ [1][0][RTW89_ACMA][0][27] = 6,
+ [1][0][RTW89_CHILE][1][27] = -4,
+ [1][0][RTW89_QATAR][1][27] = 46,
+ [1][0][RTW89_QATAR][0][27] = 6,
+ [1][0][RTW89_UK][1][27] = 46,
+ [1][0][RTW89_UK][0][27] = 6,
+ [1][0][RTW89_FCC][1][29] = -4,
+ [1][0][RTW89_FCC][2][29] = 66,
+ [1][0][RTW89_ETSI][1][29] = 46,
+ [1][0][RTW89_ETSI][0][29] = 6,
+ [1][0][RTW89_MKK][1][29] = 42,
+ [1][0][RTW89_MKK][0][29] = 2,
+ [1][0][RTW89_IC][1][29] = -4,
+ [1][0][RTW89_KCC][1][29] = -2,
+ [1][0][RTW89_KCC][0][29] = -2,
+ [1][0][RTW89_ACMA][1][29] = 46,
+ [1][0][RTW89_ACMA][0][29] = 6,
+ [1][0][RTW89_CHILE][1][29] = -4,
+ [1][0][RTW89_QATAR][1][29] = 46,
+ [1][0][RTW89_QATAR][0][29] = 6,
+ [1][0][RTW89_UK][1][29] = 46,
+ [1][0][RTW89_UK][0][29] = 6,
+ [1][0][RTW89_FCC][1][30] = -4,
+ [1][0][RTW89_FCC][2][30] = 66,
+ [1][0][RTW89_ETSI][1][30] = 46,
+ [1][0][RTW89_ETSI][0][30] = 6,
+ [1][0][RTW89_MKK][1][30] = 42,
+ [1][0][RTW89_MKK][0][30] = 2,
+ [1][0][RTW89_IC][1][30] = -4,
+ [1][0][RTW89_KCC][1][30] = -2,
+ [1][0][RTW89_KCC][0][30] = -2,
+ [1][0][RTW89_ACMA][1][30] = 46,
+ [1][0][RTW89_ACMA][0][30] = 6,
+ [1][0][RTW89_CHILE][1][30] = -4,
+ [1][0][RTW89_QATAR][1][30] = 46,
+ [1][0][RTW89_QATAR][0][30] = 6,
+ [1][0][RTW89_UK][1][30] = 46,
+ [1][0][RTW89_UK][0][30] = 6,
+ [1][0][RTW89_FCC][1][32] = -4,
+ [1][0][RTW89_FCC][2][32] = 66,
+ [1][0][RTW89_ETSI][1][32] = 46,
+ [1][0][RTW89_ETSI][0][32] = 6,
+ [1][0][RTW89_MKK][1][32] = 42,
+ [1][0][RTW89_MKK][0][32] = 2,
+ [1][0][RTW89_IC][1][32] = -4,
+ [1][0][RTW89_KCC][1][32] = -2,
+ [1][0][RTW89_KCC][0][32] = -2,
+ [1][0][RTW89_ACMA][1][32] = 46,
+ [1][0][RTW89_ACMA][0][32] = 6,
+ [1][0][RTW89_CHILE][1][32] = -4,
+ [1][0][RTW89_QATAR][1][32] = 46,
+ [1][0][RTW89_QATAR][0][32] = 6,
+ [1][0][RTW89_UK][1][32] = 46,
+ [1][0][RTW89_UK][0][32] = 6,
+ [1][0][RTW89_FCC][1][34] = -4,
+ [1][0][RTW89_FCC][2][34] = 66,
+ [1][0][RTW89_ETSI][1][34] = 46,
+ [1][0][RTW89_ETSI][0][34] = 6,
+ [1][0][RTW89_MKK][1][34] = 42,
+ [1][0][RTW89_MKK][0][34] = 2,
+ [1][0][RTW89_IC][1][34] = -4,
+ [1][0][RTW89_KCC][1][34] = -2,
+ [1][0][RTW89_KCC][0][34] = -2,
+ [1][0][RTW89_ACMA][1][34] = 46,
+ [1][0][RTW89_ACMA][0][34] = 6,
+ [1][0][RTW89_CHILE][1][34] = -4,
+ [1][0][RTW89_QATAR][1][34] = 46,
+ [1][0][RTW89_QATAR][0][34] = 6,
+ [1][0][RTW89_UK][1][34] = 46,
+ [1][0][RTW89_UK][0][34] = 6,
+ [1][0][RTW89_FCC][1][36] = -4,
+ [1][0][RTW89_FCC][2][36] = 66,
+ [1][0][RTW89_ETSI][1][36] = 46,
+ [1][0][RTW89_ETSI][0][36] = 6,
+ [1][0][RTW89_MKK][1][36] = 42,
+ [1][0][RTW89_MKK][0][36] = 2,
+ [1][0][RTW89_IC][1][36] = -4,
+ [1][0][RTW89_KCC][1][36] = -2,
+ [1][0][RTW89_KCC][0][36] = -2,
+ [1][0][RTW89_ACMA][1][36] = 46,
+ [1][0][RTW89_ACMA][0][36] = 6,
+ [1][0][RTW89_CHILE][1][36] = -4,
+ [1][0][RTW89_QATAR][1][36] = 46,
+ [1][0][RTW89_QATAR][0][36] = 6,
+ [1][0][RTW89_UK][1][36] = 46,
+ [1][0][RTW89_UK][0][36] = 6,
+ [1][0][RTW89_FCC][1][38] = -4,
+ [1][0][RTW89_FCC][2][38] = 66,
+ [1][0][RTW89_ETSI][1][38] = 46,
+ [1][0][RTW89_ETSI][0][38] = 6,
+ [1][0][RTW89_MKK][1][38] = 42,
+ [1][0][RTW89_MKK][0][38] = 2,
+ [1][0][RTW89_IC][1][38] = -4,
+ [1][0][RTW89_KCC][1][38] = -2,
+ [1][0][RTW89_KCC][0][38] = -2,
+ [1][0][RTW89_ACMA][1][38] = 46,
+ [1][0][RTW89_ACMA][0][38] = 6,
+ [1][0][RTW89_CHILE][1][38] = -4,
+ [1][0][RTW89_QATAR][1][38] = 46,
+ [1][0][RTW89_QATAR][0][38] = 6,
+ [1][0][RTW89_UK][1][38] = 46,
+ [1][0][RTW89_UK][0][38] = 6,
+ [1][0][RTW89_FCC][1][40] = -4,
+ [1][0][RTW89_FCC][2][40] = 66,
+ [1][0][RTW89_ETSI][1][40] = 46,
+ [1][0][RTW89_ETSI][0][40] = 6,
+ [1][0][RTW89_MKK][1][40] = 42,
+ [1][0][RTW89_MKK][0][40] = 2,
+ [1][0][RTW89_IC][1][40] = -4,
+ [1][0][RTW89_KCC][1][40] = -2,
+ [1][0][RTW89_KCC][0][40] = -2,
+ [1][0][RTW89_ACMA][1][40] = 46,
+ [1][0][RTW89_ACMA][0][40] = 6,
+ [1][0][RTW89_CHILE][1][40] = -4,
+ [1][0][RTW89_QATAR][1][40] = 46,
+ [1][0][RTW89_QATAR][0][40] = 6,
+ [1][0][RTW89_UK][1][40] = 46,
+ [1][0][RTW89_UK][0][40] = 6,
+ [1][0][RTW89_FCC][1][42] = -4,
+ [1][0][RTW89_FCC][2][42] = 66,
+ [1][0][RTW89_ETSI][1][42] = 46,
+ [1][0][RTW89_ETSI][0][42] = 6,
+ [1][0][RTW89_MKK][1][42] = 42,
+ [1][0][RTW89_MKK][0][42] = 2,
+ [1][0][RTW89_IC][1][42] = -4,
+ [1][0][RTW89_KCC][1][42] = -2,
+ [1][0][RTW89_KCC][0][42] = -2,
+ [1][0][RTW89_ACMA][1][42] = 46,
+ [1][0][RTW89_ACMA][0][42] = 6,
+ [1][0][RTW89_CHILE][1][42] = -4,
+ [1][0][RTW89_QATAR][1][42] = 46,
+ [1][0][RTW89_QATAR][0][42] = 6,
+ [1][0][RTW89_UK][1][42] = 46,
+ [1][0][RTW89_UK][0][42] = 6,
+ [1][0][RTW89_FCC][1][44] = -4,
+ [1][0][RTW89_FCC][2][44] = 66,
+ [1][0][RTW89_ETSI][1][44] = 46,
+ [1][0][RTW89_ETSI][0][44] = 8,
+ [1][0][RTW89_MKK][1][44] = 22,
+ [1][0][RTW89_MKK][0][44] = 4,
+ [1][0][RTW89_IC][1][44] = -4,
+ [1][0][RTW89_KCC][1][44] = -2,
+ [1][0][RTW89_KCC][0][44] = -2,
+ [1][0][RTW89_ACMA][1][44] = 46,
+ [1][0][RTW89_ACMA][0][44] = 8,
+ [1][0][RTW89_CHILE][1][44] = -4,
+ [1][0][RTW89_QATAR][1][44] = 46,
+ [1][0][RTW89_QATAR][0][44] = 8,
+ [1][0][RTW89_UK][1][44] = 46,
+ [1][0][RTW89_UK][0][44] = 8,
+ [1][0][RTW89_FCC][1][45] = -4,
+ [1][0][RTW89_FCC][2][45] = 127,
+ [1][0][RTW89_ETSI][1][45] = 127,
+ [1][0][RTW89_ETSI][0][45] = 127,
+ [1][0][RTW89_MKK][1][45] = 127,
+ [1][0][RTW89_MKK][0][45] = 127,
+ [1][0][RTW89_IC][1][45] = -4,
+ [1][0][RTW89_KCC][1][45] = -2,
+ [1][0][RTW89_KCC][0][45] = 127,
+ [1][0][RTW89_ACMA][1][45] = 127,
+ [1][0][RTW89_ACMA][0][45] = 127,
+ [1][0][RTW89_CHILE][1][45] = 127,
+ [1][0][RTW89_QATAR][1][45] = 127,
+ [1][0][RTW89_QATAR][0][45] = 127,
+ [1][0][RTW89_UK][1][45] = 127,
+ [1][0][RTW89_UK][0][45] = 127,
+ [1][0][RTW89_FCC][1][47] = -4,
+ [1][0][RTW89_FCC][2][47] = 127,
+ [1][0][RTW89_ETSI][1][47] = 127,
+ [1][0][RTW89_ETSI][0][47] = 127,
+ [1][0][RTW89_MKK][1][47] = 127,
+ [1][0][RTW89_MKK][0][47] = 127,
+ [1][0][RTW89_IC][1][47] = -4,
+ [1][0][RTW89_KCC][1][47] = -2,
+ [1][0][RTW89_KCC][0][47] = 127,
+ [1][0][RTW89_ACMA][1][47] = 127,
+ [1][0][RTW89_ACMA][0][47] = 127,
+ [1][0][RTW89_CHILE][1][47] = 127,
+ [1][0][RTW89_QATAR][1][47] = 127,
+ [1][0][RTW89_QATAR][0][47] = 127,
+ [1][0][RTW89_UK][1][47] = 127,
+ [1][0][RTW89_UK][0][47] = 127,
+ [1][0][RTW89_FCC][1][49] = -4,
+ [1][0][RTW89_FCC][2][49] = 127,
+ [1][0][RTW89_ETSI][1][49] = 127,
+ [1][0][RTW89_ETSI][0][49] = 127,
+ [1][0][RTW89_MKK][1][49] = 127,
+ [1][0][RTW89_MKK][0][49] = 127,
+ [1][0][RTW89_IC][1][49] = -4,
+ [1][0][RTW89_KCC][1][49] = -2,
+ [1][0][RTW89_KCC][0][49] = 127,
+ [1][0][RTW89_ACMA][1][49] = 127,
+ [1][0][RTW89_ACMA][0][49] = 127,
+ [1][0][RTW89_CHILE][1][49] = 127,
+ [1][0][RTW89_QATAR][1][49] = 127,
+ [1][0][RTW89_QATAR][0][49] = 127,
+ [1][0][RTW89_UK][1][49] = 127,
+ [1][0][RTW89_UK][0][49] = 127,
+ [1][0][RTW89_FCC][1][51] = -4,
+ [1][0][RTW89_FCC][2][51] = 127,
+ [1][0][RTW89_ETSI][1][51] = 127,
+ [1][0][RTW89_ETSI][0][51] = 127,
+ [1][0][RTW89_MKK][1][51] = 127,
+ [1][0][RTW89_MKK][0][51] = 127,
+ [1][0][RTW89_IC][1][51] = -4,
+ [1][0][RTW89_KCC][1][51] = -2,
+ [1][0][RTW89_KCC][0][51] = 127,
+ [1][0][RTW89_ACMA][1][51] = 127,
+ [1][0][RTW89_ACMA][0][51] = 127,
+ [1][0][RTW89_CHILE][1][51] = 127,
+ [1][0][RTW89_QATAR][1][51] = 127,
+ [1][0][RTW89_QATAR][0][51] = 127,
+ [1][0][RTW89_UK][1][51] = 127,
+ [1][0][RTW89_UK][0][51] = 127,
+ [1][0][RTW89_FCC][1][53] = -4,
+ [1][0][RTW89_FCC][2][53] = 127,
+ [1][0][RTW89_ETSI][1][53] = 127,
+ [1][0][RTW89_ETSI][0][53] = 127,
+ [1][0][RTW89_MKK][1][53] = 127,
+ [1][0][RTW89_MKK][0][53] = 127,
+ [1][0][RTW89_IC][1][53] = -4,
+ [1][0][RTW89_KCC][1][53] = -2,
+ [1][0][RTW89_KCC][0][53] = 127,
+ [1][0][RTW89_ACMA][1][53] = 127,
+ [1][0][RTW89_ACMA][0][53] = 127,
+ [1][0][RTW89_CHILE][1][53] = 127,
+ [1][0][RTW89_QATAR][1][53] = 127,
+ [1][0][RTW89_QATAR][0][53] = 127,
+ [1][0][RTW89_UK][1][53] = 127,
+ [1][0][RTW89_UK][0][53] = 127,
+ [1][0][RTW89_FCC][1][55] = -4,
+ [1][0][RTW89_FCC][2][55] = 68,
+ [1][0][RTW89_ETSI][1][55] = 127,
+ [1][0][RTW89_ETSI][0][55] = 127,
+ [1][0][RTW89_MKK][1][55] = 127,
+ [1][0][RTW89_MKK][0][55] = 127,
+ [1][0][RTW89_IC][1][55] = -4,
+ [1][0][RTW89_KCC][1][55] = -2,
+ [1][0][RTW89_KCC][0][55] = 127,
+ [1][0][RTW89_ACMA][1][55] = 127,
+ [1][0][RTW89_ACMA][0][55] = 127,
+ [1][0][RTW89_CHILE][1][55] = 127,
+ [1][0][RTW89_QATAR][1][55] = 127,
+ [1][0][RTW89_QATAR][0][55] = 127,
+ [1][0][RTW89_UK][1][55] = 127,
+ [1][0][RTW89_UK][0][55] = 127,
+ [1][0][RTW89_FCC][1][57] = -4,
+ [1][0][RTW89_FCC][2][57] = 68,
+ [1][0][RTW89_ETSI][1][57] = 127,
+ [1][0][RTW89_ETSI][0][57] = 127,
+ [1][0][RTW89_MKK][1][57] = 127,
+ [1][0][RTW89_MKK][0][57] = 127,
+ [1][0][RTW89_IC][1][57] = -4,
+ [1][0][RTW89_KCC][1][57] = -2,
+ [1][0][RTW89_KCC][0][57] = 127,
+ [1][0][RTW89_ACMA][1][57] = 127,
+ [1][0][RTW89_ACMA][0][57] = 127,
+ [1][0][RTW89_CHILE][1][57] = 127,
+ [1][0][RTW89_QATAR][1][57] = 127,
+ [1][0][RTW89_QATAR][0][57] = 127,
+ [1][0][RTW89_UK][1][57] = 127,
+ [1][0][RTW89_UK][0][57] = 127,
+ [1][0][RTW89_FCC][1][59] = -4,
+ [1][0][RTW89_FCC][2][59] = 68,
+ [1][0][RTW89_ETSI][1][59] = 127,
+ [1][0][RTW89_ETSI][0][59] = 127,
+ [1][0][RTW89_MKK][1][59] = 127,
+ [1][0][RTW89_MKK][0][59] = 127,
+ [1][0][RTW89_IC][1][59] = -4,
+ [1][0][RTW89_KCC][1][59] = -2,
+ [1][0][RTW89_KCC][0][59] = 127,
+ [1][0][RTW89_ACMA][1][59] = 127,
+ [1][0][RTW89_ACMA][0][59] = 127,
+ [1][0][RTW89_CHILE][1][59] = 127,
+ [1][0][RTW89_QATAR][1][59] = 127,
+ [1][0][RTW89_QATAR][0][59] = 127,
+ [1][0][RTW89_UK][1][59] = 127,
+ [1][0][RTW89_UK][0][59] = 127,
+ [1][0][RTW89_FCC][1][60] = -4,
+ [1][0][RTW89_FCC][2][60] = 68,
+ [1][0][RTW89_ETSI][1][60] = 127,
+ [1][0][RTW89_ETSI][0][60] = 127,
+ [1][0][RTW89_MKK][1][60] = 127,
+ [1][0][RTW89_MKK][0][60] = 127,
+ [1][0][RTW89_IC][1][60] = -4,
+ [1][0][RTW89_KCC][1][60] = -2,
+ [1][0][RTW89_KCC][0][60] = 127,
+ [1][0][RTW89_ACMA][1][60] = 127,
+ [1][0][RTW89_ACMA][0][60] = 127,
+ [1][0][RTW89_CHILE][1][60] = 127,
+ [1][0][RTW89_QATAR][1][60] = 127,
+ [1][0][RTW89_QATAR][0][60] = 127,
+ [1][0][RTW89_UK][1][60] = 127,
+ [1][0][RTW89_UK][0][60] = 127,
+ [1][0][RTW89_FCC][1][62] = -4,
+ [1][0][RTW89_FCC][2][62] = 68,
+ [1][0][RTW89_ETSI][1][62] = 127,
+ [1][0][RTW89_ETSI][0][62] = 127,
+ [1][0][RTW89_MKK][1][62] = 127,
+ [1][0][RTW89_MKK][0][62] = 127,
+ [1][0][RTW89_IC][1][62] = -4,
+ [1][0][RTW89_KCC][1][62] = -2,
+ [1][0][RTW89_KCC][0][62] = 127,
+ [1][0][RTW89_ACMA][1][62] = 127,
+ [1][0][RTW89_ACMA][0][62] = 127,
+ [1][0][RTW89_CHILE][1][62] = 127,
+ [1][0][RTW89_QATAR][1][62] = 127,
+ [1][0][RTW89_QATAR][0][62] = 127,
+ [1][0][RTW89_UK][1][62] = 127,
+ [1][0][RTW89_UK][0][62] = 127,
+ [1][0][RTW89_FCC][1][64] = -4,
+ [1][0][RTW89_FCC][2][64] = 68,
+ [1][0][RTW89_ETSI][1][64] = 127,
+ [1][0][RTW89_ETSI][0][64] = 127,
+ [1][0][RTW89_MKK][1][64] = 127,
+ [1][0][RTW89_MKK][0][64] = 127,
+ [1][0][RTW89_IC][1][64] = -4,
+ [1][0][RTW89_KCC][1][64] = -2,
+ [1][0][RTW89_KCC][0][64] = 127,
+ [1][0][RTW89_ACMA][1][64] = 127,
+ [1][0][RTW89_ACMA][0][64] = 127,
+ [1][0][RTW89_CHILE][1][64] = 127,
+ [1][0][RTW89_QATAR][1][64] = 127,
+ [1][0][RTW89_QATAR][0][64] = 127,
+ [1][0][RTW89_UK][1][64] = 127,
+ [1][0][RTW89_UK][0][64] = 127,
+ [1][0][RTW89_FCC][1][66] = -4,
+ [1][0][RTW89_FCC][2][66] = 68,
+ [1][0][RTW89_ETSI][1][66] = 127,
+ [1][0][RTW89_ETSI][0][66] = 127,
+ [1][0][RTW89_MKK][1][66] = 127,
+ [1][0][RTW89_MKK][0][66] = 127,
+ [1][0][RTW89_IC][1][66] = -4,
+ [1][0][RTW89_KCC][1][66] = -2,
+ [1][0][RTW89_KCC][0][66] = 127,
+ [1][0][RTW89_ACMA][1][66] = 127,
+ [1][0][RTW89_ACMA][0][66] = 127,
+ [1][0][RTW89_CHILE][1][66] = 127,
+ [1][0][RTW89_QATAR][1][66] = 127,
+ [1][0][RTW89_QATAR][0][66] = 127,
+ [1][0][RTW89_UK][1][66] = 127,
+ [1][0][RTW89_UK][0][66] = 127,
+ [1][0][RTW89_FCC][1][68] = -4,
+ [1][0][RTW89_FCC][2][68] = 68,
+ [1][0][RTW89_ETSI][1][68] = 127,
+ [1][0][RTW89_ETSI][0][68] = 127,
+ [1][0][RTW89_MKK][1][68] = 127,
+ [1][0][RTW89_MKK][0][68] = 127,
+ [1][0][RTW89_IC][1][68] = -4,
+ [1][0][RTW89_KCC][1][68] = -2,
+ [1][0][RTW89_KCC][0][68] = 127,
+ [1][0][RTW89_ACMA][1][68] = 127,
+ [1][0][RTW89_ACMA][0][68] = 127,
+ [1][0][RTW89_CHILE][1][68] = 127,
+ [1][0][RTW89_QATAR][1][68] = 127,
+ [1][0][RTW89_QATAR][0][68] = 127,
+ [1][0][RTW89_UK][1][68] = 127,
+ [1][0][RTW89_UK][0][68] = 127,
+ [1][0][RTW89_FCC][1][70] = -4,
+ [1][0][RTW89_FCC][2][70] = 68,
+ [1][0][RTW89_ETSI][1][70] = 127,
+ [1][0][RTW89_ETSI][0][70] = 127,
+ [1][0][RTW89_MKK][1][70] = 127,
+ [1][0][RTW89_MKK][0][70] = 127,
+ [1][0][RTW89_IC][1][70] = -4,
+ [1][0][RTW89_KCC][1][70] = -2,
+ [1][0][RTW89_KCC][0][70] = 127,
+ [1][0][RTW89_ACMA][1][70] = 127,
+ [1][0][RTW89_ACMA][0][70] = 127,
+ [1][0][RTW89_CHILE][1][70] = 127,
+ [1][0][RTW89_QATAR][1][70] = 127,
+ [1][0][RTW89_QATAR][0][70] = 127,
+ [1][0][RTW89_UK][1][70] = 127,
+ [1][0][RTW89_UK][0][70] = 127,
+ [1][0][RTW89_FCC][1][72] = -4,
+ [1][0][RTW89_FCC][2][72] = 68,
+ [1][0][RTW89_ETSI][1][72] = 127,
+ [1][0][RTW89_ETSI][0][72] = 127,
+ [1][0][RTW89_MKK][1][72] = 127,
+ [1][0][RTW89_MKK][0][72] = 127,
+ [1][0][RTW89_IC][1][72] = -4,
+ [1][0][RTW89_KCC][1][72] = -2,
+ [1][0][RTW89_KCC][0][72] = 127,
+ [1][0][RTW89_ACMA][1][72] = 127,
+ [1][0][RTW89_ACMA][0][72] = 127,
+ [1][0][RTW89_CHILE][1][72] = 127,
+ [1][0][RTW89_QATAR][1][72] = 127,
+ [1][0][RTW89_QATAR][0][72] = 127,
+ [1][0][RTW89_UK][1][72] = 127,
+ [1][0][RTW89_UK][0][72] = 127,
+ [1][0][RTW89_FCC][1][74] = -4,
+ [1][0][RTW89_FCC][2][74] = 68,
+ [1][0][RTW89_ETSI][1][74] = 127,
+ [1][0][RTW89_ETSI][0][74] = 127,
+ [1][0][RTW89_MKK][1][74] = 127,
+ [1][0][RTW89_MKK][0][74] = 127,
+ [1][0][RTW89_IC][1][74] = -4,
+ [1][0][RTW89_KCC][1][74] = -2,
+ [1][0][RTW89_KCC][0][74] = 127,
+ [1][0][RTW89_ACMA][1][74] = 127,
+ [1][0][RTW89_ACMA][0][74] = 127,
+ [1][0][RTW89_CHILE][1][74] = 127,
+ [1][0][RTW89_QATAR][1][74] = 127,
+ [1][0][RTW89_QATAR][0][74] = 127,
+ [1][0][RTW89_UK][1][74] = 127,
+ [1][0][RTW89_UK][0][74] = 127,
+ [1][0][RTW89_FCC][1][75] = -4,
+ [1][0][RTW89_FCC][2][75] = 68,
+ [1][0][RTW89_ETSI][1][75] = 127,
+ [1][0][RTW89_ETSI][0][75] = 127,
+ [1][0][RTW89_MKK][1][75] = 127,
+ [1][0][RTW89_MKK][0][75] = 127,
+ [1][0][RTW89_IC][1][75] = -4,
+ [1][0][RTW89_KCC][1][75] = -2,
+ [1][0][RTW89_KCC][0][75] = 127,
+ [1][0][RTW89_ACMA][1][75] = 127,
+ [1][0][RTW89_ACMA][0][75] = 127,
+ [1][0][RTW89_CHILE][1][75] = 127,
+ [1][0][RTW89_QATAR][1][75] = 127,
+ [1][0][RTW89_QATAR][0][75] = 127,
+ [1][0][RTW89_UK][1][75] = 127,
+ [1][0][RTW89_UK][0][75] = 127,
+ [1][0][RTW89_FCC][1][77] = -4,
+ [1][0][RTW89_FCC][2][77] = 68,
+ [1][0][RTW89_ETSI][1][77] = 127,
+ [1][0][RTW89_ETSI][0][77] = 127,
+ [1][0][RTW89_MKK][1][77] = 127,
+ [1][0][RTW89_MKK][0][77] = 127,
+ [1][0][RTW89_IC][1][77] = -4,
+ [1][0][RTW89_KCC][1][77] = -2,
+ [1][0][RTW89_KCC][0][77] = 127,
+ [1][0][RTW89_ACMA][1][77] = 127,
+ [1][0][RTW89_ACMA][0][77] = 127,
+ [1][0][RTW89_CHILE][1][77] = 127,
+ [1][0][RTW89_QATAR][1][77] = 127,
+ [1][0][RTW89_QATAR][0][77] = 127,
+ [1][0][RTW89_UK][1][77] = 127,
+ [1][0][RTW89_UK][0][77] = 127,
+ [1][0][RTW89_FCC][1][79] = -4,
+ [1][0][RTW89_FCC][2][79] = 68,
+ [1][0][RTW89_ETSI][1][79] = 127,
+ [1][0][RTW89_ETSI][0][79] = 127,
+ [1][0][RTW89_MKK][1][79] = 127,
+ [1][0][RTW89_MKK][0][79] = 127,
+ [1][0][RTW89_IC][1][79] = -4,
+ [1][0][RTW89_KCC][1][79] = -2,
+ [1][0][RTW89_KCC][0][79] = 127,
+ [1][0][RTW89_ACMA][1][79] = 127,
+ [1][0][RTW89_ACMA][0][79] = 127,
+ [1][0][RTW89_CHILE][1][79] = 127,
+ [1][0][RTW89_QATAR][1][79] = 127,
+ [1][0][RTW89_QATAR][0][79] = 127,
+ [1][0][RTW89_UK][1][79] = 127,
+ [1][0][RTW89_UK][0][79] = 127,
+ [1][0][RTW89_FCC][1][81] = -4,
+ [1][0][RTW89_FCC][2][81] = 68,
+ [1][0][RTW89_ETSI][1][81] = 127,
+ [1][0][RTW89_ETSI][0][81] = 127,
+ [1][0][RTW89_MKK][1][81] = 127,
+ [1][0][RTW89_MKK][0][81] = 127,
+ [1][0][RTW89_IC][1][81] = -4,
+ [1][0][RTW89_KCC][1][81] = -2,
+ [1][0][RTW89_KCC][0][81] = 127,
+ [1][0][RTW89_ACMA][1][81] = 127,
+ [1][0][RTW89_ACMA][0][81] = 127,
+ [1][0][RTW89_CHILE][1][81] = 127,
+ [1][0][RTW89_QATAR][1][81] = 127,
+ [1][0][RTW89_QATAR][0][81] = 127,
+ [1][0][RTW89_UK][1][81] = 127,
+ [1][0][RTW89_UK][0][81] = 127,
+ [1][0][RTW89_FCC][1][83] = -4,
+ [1][0][RTW89_FCC][2][83] = 68,
+ [1][0][RTW89_ETSI][1][83] = 127,
+ [1][0][RTW89_ETSI][0][83] = 127,
+ [1][0][RTW89_MKK][1][83] = 127,
+ [1][0][RTW89_MKK][0][83] = 127,
+ [1][0][RTW89_IC][1][83] = -4,
+ [1][0][RTW89_KCC][1][83] = -2,
+ [1][0][RTW89_KCC][0][83] = 127,
+ [1][0][RTW89_ACMA][1][83] = 127,
+ [1][0][RTW89_ACMA][0][83] = 127,
+ [1][0][RTW89_CHILE][1][83] = 127,
+ [1][0][RTW89_QATAR][1][83] = 127,
+ [1][0][RTW89_QATAR][0][83] = 127,
+ [1][0][RTW89_UK][1][83] = 127,
+ [1][0][RTW89_UK][0][83] = 127,
+ [1][0][RTW89_FCC][1][85] = -4,
+ [1][0][RTW89_FCC][2][85] = 68,
+ [1][0][RTW89_ETSI][1][85] = 127,
+ [1][0][RTW89_ETSI][0][85] = 127,
+ [1][0][RTW89_MKK][1][85] = 127,
+ [1][0][RTW89_MKK][0][85] = 127,
+ [1][0][RTW89_IC][1][85] = -4,
+ [1][0][RTW89_KCC][1][85] = -2,
+ [1][0][RTW89_KCC][0][85] = 127,
+ [1][0][RTW89_ACMA][1][85] = 127,
+ [1][0][RTW89_ACMA][0][85] = 127,
+ [1][0][RTW89_CHILE][1][85] = 127,
+ [1][0][RTW89_QATAR][1][85] = 127,
+ [1][0][RTW89_QATAR][0][85] = 127,
+ [1][0][RTW89_UK][1][85] = 127,
+ [1][0][RTW89_UK][0][85] = 127,
+ [1][0][RTW89_FCC][1][87] = -4,
+ [1][0][RTW89_FCC][2][87] = 127,
+ [1][0][RTW89_ETSI][1][87] = 127,
+ [1][0][RTW89_ETSI][0][87] = 127,
+ [1][0][RTW89_MKK][1][87] = 127,
+ [1][0][RTW89_MKK][0][87] = 127,
+ [1][0][RTW89_IC][1][87] = -4,
+ [1][0][RTW89_KCC][1][87] = -2,
+ [1][0][RTW89_KCC][0][87] = 127,
+ [1][0][RTW89_ACMA][1][87] = 127,
+ [1][0][RTW89_ACMA][0][87] = 127,
+ [1][0][RTW89_CHILE][1][87] = 127,
+ [1][0][RTW89_QATAR][1][87] = 127,
+ [1][0][RTW89_QATAR][0][87] = 127,
+ [1][0][RTW89_UK][1][87] = 127,
+ [1][0][RTW89_UK][0][87] = 127,
+ [1][0][RTW89_FCC][1][89] = -4,
+ [1][0][RTW89_FCC][2][89] = 127,
+ [1][0][RTW89_ETSI][1][89] = 127,
+ [1][0][RTW89_ETSI][0][89] = 127,
+ [1][0][RTW89_MKK][1][89] = 127,
+ [1][0][RTW89_MKK][0][89] = 127,
+ [1][0][RTW89_IC][1][89] = -4,
+ [1][0][RTW89_KCC][1][89] = -2,
+ [1][0][RTW89_KCC][0][89] = 127,
+ [1][0][RTW89_ACMA][1][89] = 127,
+ [1][0][RTW89_ACMA][0][89] = 127,
+ [1][0][RTW89_CHILE][1][89] = 127,
+ [1][0][RTW89_QATAR][1][89] = 127,
+ [1][0][RTW89_QATAR][0][89] = 127,
+ [1][0][RTW89_UK][1][89] = 127,
+ [1][0][RTW89_UK][0][89] = 127,
+ [1][0][RTW89_FCC][1][90] = -4,
+ [1][0][RTW89_FCC][2][90] = 127,
+ [1][0][RTW89_ETSI][1][90] = 127,
+ [1][0][RTW89_ETSI][0][90] = 127,
+ [1][0][RTW89_MKK][1][90] = 127,
+ [1][0][RTW89_MKK][0][90] = 127,
+ [1][0][RTW89_IC][1][90] = -4,
+ [1][0][RTW89_KCC][1][90] = -2,
+ [1][0][RTW89_KCC][0][90] = 127,
+ [1][0][RTW89_ACMA][1][90] = 127,
+ [1][0][RTW89_ACMA][0][90] = 127,
+ [1][0][RTW89_CHILE][1][90] = 127,
+ [1][0][RTW89_QATAR][1][90] = 127,
+ [1][0][RTW89_QATAR][0][90] = 127,
+ [1][0][RTW89_UK][1][90] = 127,
+ [1][0][RTW89_UK][0][90] = 127,
+ [1][0][RTW89_FCC][1][92] = -4,
+ [1][0][RTW89_FCC][2][92] = 127,
+ [1][0][RTW89_ETSI][1][92] = 127,
+ [1][0][RTW89_ETSI][0][92] = 127,
+ [1][0][RTW89_MKK][1][92] = 127,
+ [1][0][RTW89_MKK][0][92] = 127,
+ [1][0][RTW89_IC][1][92] = -4,
+ [1][0][RTW89_KCC][1][92] = -2,
+ [1][0][RTW89_KCC][0][92] = 127,
+ [1][0][RTW89_ACMA][1][92] = 127,
+ [1][0][RTW89_ACMA][0][92] = 127,
+ [1][0][RTW89_CHILE][1][92] = 127,
+ [1][0][RTW89_QATAR][1][92] = 127,
+ [1][0][RTW89_QATAR][0][92] = 127,
+ [1][0][RTW89_UK][1][92] = 127,
+ [1][0][RTW89_UK][0][92] = 127,
+ [1][0][RTW89_FCC][1][94] = -4,
+ [1][0][RTW89_FCC][2][94] = 127,
+ [1][0][RTW89_ETSI][1][94] = 127,
+ [1][0][RTW89_ETSI][0][94] = 127,
+ [1][0][RTW89_MKK][1][94] = 127,
+ [1][0][RTW89_MKK][0][94] = 127,
+ [1][0][RTW89_IC][1][94] = -4,
+ [1][0][RTW89_KCC][1][94] = -2,
+ [1][0][RTW89_KCC][0][94] = 127,
+ [1][0][RTW89_ACMA][1][94] = 127,
+ [1][0][RTW89_ACMA][0][94] = 127,
+ [1][0][RTW89_CHILE][1][94] = 127,
+ [1][0][RTW89_QATAR][1][94] = 127,
+ [1][0][RTW89_QATAR][0][94] = 127,
+ [1][0][RTW89_UK][1][94] = 127,
+ [1][0][RTW89_UK][0][94] = 127,
+ [1][0][RTW89_FCC][1][96] = -4,
+ [1][0][RTW89_FCC][2][96] = 127,
+ [1][0][RTW89_ETSI][1][96] = 127,
+ [1][0][RTW89_ETSI][0][96] = 127,
+ [1][0][RTW89_MKK][1][96] = 127,
+ [1][0][RTW89_MKK][0][96] = 127,
+ [1][0][RTW89_IC][1][96] = -4,
+ [1][0][RTW89_KCC][1][96] = -2,
+ [1][0][RTW89_KCC][0][96] = 127,
+ [1][0][RTW89_ACMA][1][96] = 127,
+ [1][0][RTW89_ACMA][0][96] = 127,
+ [1][0][RTW89_CHILE][1][96] = 127,
+ [1][0][RTW89_QATAR][1][96] = 127,
+ [1][0][RTW89_QATAR][0][96] = 127,
+ [1][0][RTW89_UK][1][96] = 127,
+ [1][0][RTW89_UK][0][96] = 127,
+ [1][0][RTW89_FCC][1][98] = -4,
+ [1][0][RTW89_FCC][2][98] = 127,
+ [1][0][RTW89_ETSI][1][98] = 127,
+ [1][0][RTW89_ETSI][0][98] = 127,
+ [1][0][RTW89_MKK][1][98] = 127,
+ [1][0][RTW89_MKK][0][98] = 127,
+ [1][0][RTW89_IC][1][98] = -4,
+ [1][0][RTW89_KCC][1][98] = -2,
+ [1][0][RTW89_KCC][0][98] = 127,
+ [1][0][RTW89_ACMA][1][98] = 127,
+ [1][0][RTW89_ACMA][0][98] = 127,
+ [1][0][RTW89_CHILE][1][98] = 127,
+ [1][0][RTW89_QATAR][1][98] = 127,
+ [1][0][RTW89_QATAR][0][98] = 127,
+ [1][0][RTW89_UK][1][98] = 127,
+ [1][0][RTW89_UK][0][98] = 127,
+ [1][0][RTW89_FCC][1][100] = -4,
+ [1][0][RTW89_FCC][2][100] = 127,
+ [1][0][RTW89_ETSI][1][100] = 127,
+ [1][0][RTW89_ETSI][0][100] = 127,
+ [1][0][RTW89_MKK][1][100] = 127,
+ [1][0][RTW89_MKK][0][100] = 127,
+ [1][0][RTW89_IC][1][100] = -4,
+ [1][0][RTW89_KCC][1][100] = -2,
+ [1][0][RTW89_KCC][0][100] = 127,
+ [1][0][RTW89_ACMA][1][100] = 127,
+ [1][0][RTW89_ACMA][0][100] = 127,
+ [1][0][RTW89_CHILE][1][100] = 127,
+ [1][0][RTW89_QATAR][1][100] = 127,
+ [1][0][RTW89_QATAR][0][100] = 127,
+ [1][0][RTW89_UK][1][100] = 127,
+ [1][0][RTW89_UK][0][100] = 127,
+ [1][0][RTW89_FCC][1][102] = -4,
+ [1][0][RTW89_FCC][2][102] = 127,
+ [1][0][RTW89_ETSI][1][102] = 127,
+ [1][0][RTW89_ETSI][0][102] = 127,
+ [1][0][RTW89_MKK][1][102] = 127,
+ [1][0][RTW89_MKK][0][102] = 127,
+ [1][0][RTW89_IC][1][102] = -4,
+ [1][0][RTW89_KCC][1][102] = -2,
+ [1][0][RTW89_KCC][0][102] = 127,
+ [1][0][RTW89_ACMA][1][102] = 127,
+ [1][0][RTW89_ACMA][0][102] = 127,
+ [1][0][RTW89_CHILE][1][102] = 127,
+ [1][0][RTW89_QATAR][1][102] = 127,
+ [1][0][RTW89_QATAR][0][102] = 127,
+ [1][0][RTW89_UK][1][102] = 127,
+ [1][0][RTW89_UK][0][102] = 127,
+ [1][0][RTW89_FCC][1][104] = -4,
+ [1][0][RTW89_FCC][2][104] = 127,
+ [1][0][RTW89_ETSI][1][104] = 127,
+ [1][0][RTW89_ETSI][0][104] = 127,
+ [1][0][RTW89_MKK][1][104] = 127,
+ [1][0][RTW89_MKK][0][104] = 127,
+ [1][0][RTW89_IC][1][104] = -4,
+ [1][0][RTW89_KCC][1][104] = -2,
+ [1][0][RTW89_KCC][0][104] = 127,
+ [1][0][RTW89_ACMA][1][104] = 127,
+ [1][0][RTW89_ACMA][0][104] = 127,
+ [1][0][RTW89_CHILE][1][104] = 127,
+ [1][0][RTW89_QATAR][1][104] = 127,
+ [1][0][RTW89_QATAR][0][104] = 127,
+ [1][0][RTW89_UK][1][104] = 127,
+ [1][0][RTW89_UK][0][104] = 127,
+ [1][0][RTW89_FCC][1][105] = -4,
+ [1][0][RTW89_FCC][2][105] = 127,
+ [1][0][RTW89_ETSI][1][105] = 127,
+ [1][0][RTW89_ETSI][0][105] = 127,
+ [1][0][RTW89_MKK][1][105] = 127,
+ [1][0][RTW89_MKK][0][105] = 127,
+ [1][0][RTW89_IC][1][105] = -4,
+ [1][0][RTW89_KCC][1][105] = -2,
+ [1][0][RTW89_KCC][0][105] = 127,
+ [1][0][RTW89_ACMA][1][105] = 127,
+ [1][0][RTW89_ACMA][0][105] = 127,
+ [1][0][RTW89_CHILE][1][105] = 127,
+ [1][0][RTW89_QATAR][1][105] = 127,
+ [1][0][RTW89_QATAR][0][105] = 127,
+ [1][0][RTW89_UK][1][105] = 127,
+ [1][0][RTW89_UK][0][105] = 127,
+ [1][0][RTW89_FCC][1][107] = 1,
+ [1][0][RTW89_FCC][2][107] = 127,
+ [1][0][RTW89_ETSI][1][107] = 127,
+ [1][0][RTW89_ETSI][0][107] = 127,
+ [1][0][RTW89_MKK][1][107] = 127,
+ [1][0][RTW89_MKK][0][107] = 127,
+ [1][0][RTW89_IC][1][107] = 1,
+ [1][0][RTW89_KCC][1][107] = -2,
+ [1][0][RTW89_KCC][0][107] = 127,
+ [1][0][RTW89_ACMA][1][107] = 127,
+ [1][0][RTW89_ACMA][0][107] = 127,
+ [1][0][RTW89_CHILE][1][107] = 127,
+ [1][0][RTW89_QATAR][1][107] = 127,
+ [1][0][RTW89_QATAR][0][107] = 127,
+ [1][0][RTW89_UK][1][107] = 127,
+ [1][0][RTW89_UK][0][107] = 127,
+ [1][0][RTW89_FCC][1][109] = 2,
+ [1][0][RTW89_FCC][2][109] = 127,
+ [1][0][RTW89_ETSI][1][109] = 127,
+ [1][0][RTW89_ETSI][0][109] = 127,
+ [1][0][RTW89_MKK][1][109] = 127,
+ [1][0][RTW89_MKK][0][109] = 127,
+ [1][0][RTW89_IC][1][109] = 2,
+ [1][0][RTW89_KCC][1][109] = 127,
+ [1][0][RTW89_KCC][0][109] = 127,
+ [1][0][RTW89_ACMA][1][109] = 127,
+ [1][0][RTW89_ACMA][0][109] = 127,
+ [1][0][RTW89_CHILE][1][109] = 127,
+ [1][0][RTW89_QATAR][1][109] = 127,
+ [1][0][RTW89_QATAR][0][109] = 127,
+ [1][0][RTW89_UK][1][109] = 127,
+ [1][0][RTW89_UK][0][109] = 127,
+ [1][0][RTW89_FCC][1][111] = 127,
+ [1][0][RTW89_FCC][2][111] = 127,
+ [1][0][RTW89_ETSI][1][111] = 127,
+ [1][0][RTW89_ETSI][0][111] = 127,
+ [1][0][RTW89_MKK][1][111] = 127,
+ [1][0][RTW89_MKK][0][111] = 127,
+ [1][0][RTW89_IC][1][111] = 127,
+ [1][0][RTW89_KCC][1][111] = 127,
+ [1][0][RTW89_KCC][0][111] = 127,
+ [1][0][RTW89_ACMA][1][111] = 127,
+ [1][0][RTW89_ACMA][0][111] = 127,
+ [1][0][RTW89_CHILE][1][111] = 127,
+ [1][0][RTW89_QATAR][1][111] = 127,
+ [1][0][RTW89_QATAR][0][111] = 127,
+ [1][0][RTW89_UK][1][111] = 127,
+ [1][0][RTW89_UK][0][111] = 127,
+ [1][0][RTW89_FCC][1][113] = 127,
+ [1][0][RTW89_FCC][2][113] = 127,
+ [1][0][RTW89_ETSI][1][113] = 127,
+ [1][0][RTW89_ETSI][0][113] = 127,
+ [1][0][RTW89_MKK][1][113] = 127,
+ [1][0][RTW89_MKK][0][113] = 127,
+ [1][0][RTW89_IC][1][113] = 127,
+ [1][0][RTW89_KCC][1][113] = 127,
+ [1][0][RTW89_KCC][0][113] = 127,
+ [1][0][RTW89_ACMA][1][113] = 127,
+ [1][0][RTW89_ACMA][0][113] = 127,
+ [1][0][RTW89_CHILE][1][113] = 127,
+ [1][0][RTW89_QATAR][1][113] = 127,
+ [1][0][RTW89_QATAR][0][113] = 127,
+ [1][0][RTW89_UK][1][113] = 127,
+ [1][0][RTW89_UK][0][113] = 127,
+ [1][0][RTW89_FCC][1][115] = 127,
+ [1][0][RTW89_FCC][2][115] = 127,
+ [1][0][RTW89_ETSI][1][115] = 127,
+ [1][0][RTW89_ETSI][0][115] = 127,
+ [1][0][RTW89_MKK][1][115] = 127,
+ [1][0][RTW89_MKK][0][115] = 127,
+ [1][0][RTW89_IC][1][115] = 127,
+ [1][0][RTW89_KCC][1][115] = 127,
+ [1][0][RTW89_KCC][0][115] = 127,
+ [1][0][RTW89_ACMA][1][115] = 127,
+ [1][0][RTW89_ACMA][0][115] = 127,
+ [1][0][RTW89_CHILE][1][115] = 127,
+ [1][0][RTW89_QATAR][1][115] = 127,
+ [1][0][RTW89_QATAR][0][115] = 127,
+ [1][0][RTW89_UK][1][115] = 127,
+ [1][0][RTW89_UK][0][115] = 127,
+ [1][0][RTW89_FCC][1][117] = 127,
+ [1][0][RTW89_FCC][2][117] = 127,
+ [1][0][RTW89_ETSI][1][117] = 127,
+ [1][0][RTW89_ETSI][0][117] = 127,
+ [1][0][RTW89_MKK][1][117] = 127,
+ [1][0][RTW89_MKK][0][117] = 127,
+ [1][0][RTW89_IC][1][117] = 127,
+ [1][0][RTW89_KCC][1][117] = 127,
+ [1][0][RTW89_KCC][0][117] = 127,
+ [1][0][RTW89_ACMA][1][117] = 127,
+ [1][0][RTW89_ACMA][0][117] = 127,
+ [1][0][RTW89_CHILE][1][117] = 127,
+ [1][0][RTW89_QATAR][1][117] = 127,
+ [1][0][RTW89_QATAR][0][117] = 127,
+ [1][0][RTW89_UK][1][117] = 127,
+ [1][0][RTW89_UK][0][117] = 127,
+ [1][0][RTW89_FCC][1][119] = 127,
+ [1][0][RTW89_FCC][2][119] = 127,
+ [1][0][RTW89_ETSI][1][119] = 127,
+ [1][0][RTW89_ETSI][0][119] = 127,
+ [1][0][RTW89_MKK][1][119] = 127,
+ [1][0][RTW89_MKK][0][119] = 127,
+ [1][0][RTW89_IC][1][119] = 127,
+ [1][0][RTW89_KCC][1][119] = 127,
+ [1][0][RTW89_KCC][0][119] = 127,
+ [1][0][RTW89_ACMA][1][119] = 127,
+ [1][0][RTW89_ACMA][0][119] = 127,
+ [1][0][RTW89_CHILE][1][119] = 127,
+ [1][0][RTW89_QATAR][1][119] = 127,
+ [1][0][RTW89_QATAR][0][119] = 127,
+ [1][0][RTW89_UK][1][119] = 127,
+ [1][0][RTW89_UK][0][119] = 127,
+ [1][1][RTW89_FCC][1][0] = -26,
+ [1][1][RTW89_FCC][2][0] = 44,
+ [1][1][RTW89_ETSI][1][0] = 32,
+ [1][1][RTW89_ETSI][0][0] = -6,
+ [1][1][RTW89_MKK][1][0] = 30,
+ [1][1][RTW89_MKK][0][0] = -10,
+ [1][1][RTW89_IC][1][0] = -26,
+ [1][1][RTW89_KCC][1][0] = -14,
+ [1][1][RTW89_KCC][0][0] = -14,
+ [1][1][RTW89_ACMA][1][0] = 32,
+ [1][1][RTW89_ACMA][0][0] = -6,
+ [1][1][RTW89_CHILE][1][0] = -26,
+ [1][1][RTW89_QATAR][1][0] = 32,
+ [1][1][RTW89_QATAR][0][0] = -6,
+ [1][1][RTW89_UK][1][0] = 32,
+ [1][1][RTW89_UK][0][0] = -6,
+ [1][1][RTW89_FCC][1][2] = -28,
+ [1][1][RTW89_FCC][2][2] = 44,
+ [1][1][RTW89_ETSI][1][2] = 32,
+ [1][1][RTW89_ETSI][0][2] = -6,
+ [1][1][RTW89_MKK][1][2] = 30,
+ [1][1][RTW89_MKK][0][2] = -10,
+ [1][1][RTW89_IC][1][2] = -28,
+ [1][1][RTW89_KCC][1][2] = -14,
+ [1][1][RTW89_KCC][0][2] = -14,
+ [1][1][RTW89_ACMA][1][2] = 32,
+ [1][1][RTW89_ACMA][0][2] = -6,
+ [1][1][RTW89_CHILE][1][2] = -28,
+ [1][1][RTW89_QATAR][1][2] = 32,
+ [1][1][RTW89_QATAR][0][2] = -6,
+ [1][1][RTW89_UK][1][2] = 32,
+ [1][1][RTW89_UK][0][2] = -6,
+ [1][1][RTW89_FCC][1][4] = -28,
+ [1][1][RTW89_FCC][2][4] = 44,
+ [1][1][RTW89_ETSI][1][4] = 32,
+ [1][1][RTW89_ETSI][0][4] = -6,
+ [1][1][RTW89_MKK][1][4] = 30,
+ [1][1][RTW89_MKK][0][4] = -10,
+ [1][1][RTW89_IC][1][4] = -28,
+ [1][1][RTW89_KCC][1][4] = -14,
+ [1][1][RTW89_KCC][0][4] = -14,
+ [1][1][RTW89_ACMA][1][4] = 32,
+ [1][1][RTW89_ACMA][0][4] = -6,
+ [1][1][RTW89_CHILE][1][4] = -28,
+ [1][1][RTW89_QATAR][1][4] = 32,
+ [1][1][RTW89_QATAR][0][4] = -6,
+ [1][1][RTW89_UK][1][4] = 32,
+ [1][1][RTW89_UK][0][4] = -6,
+ [1][1][RTW89_FCC][1][6] = -28,
+ [1][1][RTW89_FCC][2][6] = 44,
+ [1][1][RTW89_ETSI][1][6] = 32,
+ [1][1][RTW89_ETSI][0][6] = -6,
+ [1][1][RTW89_MKK][1][6] = 30,
+ [1][1][RTW89_MKK][0][6] = -10,
+ [1][1][RTW89_IC][1][6] = -28,
+ [1][1][RTW89_KCC][1][6] = -14,
+ [1][1][RTW89_KCC][0][6] = -14,
+ [1][1][RTW89_ACMA][1][6] = 32,
+ [1][1][RTW89_ACMA][0][6] = -6,
+ [1][1][RTW89_CHILE][1][6] = -28,
+ [1][1][RTW89_QATAR][1][6] = 32,
+ [1][1][RTW89_QATAR][0][6] = -6,
+ [1][1][RTW89_UK][1][6] = 32,
+ [1][1][RTW89_UK][0][6] = -6,
+ [1][1][RTW89_FCC][1][8] = -28,
+ [1][1][RTW89_FCC][2][8] = 44,
+ [1][1][RTW89_ETSI][1][8] = 32,
+ [1][1][RTW89_ETSI][0][8] = -6,
+ [1][1][RTW89_MKK][1][8] = 30,
+ [1][1][RTW89_MKK][0][8] = -10,
+ [1][1][RTW89_IC][1][8] = -28,
+ [1][1][RTW89_KCC][1][8] = -14,
+ [1][1][RTW89_KCC][0][8] = -14,
+ [1][1][RTW89_ACMA][1][8] = 32,
+ [1][1][RTW89_ACMA][0][8] = -6,
+ [1][1][RTW89_CHILE][1][8] = -28,
+ [1][1][RTW89_QATAR][1][8] = 32,
+ [1][1][RTW89_QATAR][0][8] = -6,
+ [1][1][RTW89_UK][1][8] = 32,
+ [1][1][RTW89_UK][0][8] = -6,
+ [1][1][RTW89_FCC][1][10] = -28,
+ [1][1][RTW89_FCC][2][10] = 44,
+ [1][1][RTW89_ETSI][1][10] = 32,
+ [1][1][RTW89_ETSI][0][10] = -6,
+ [1][1][RTW89_MKK][1][10] = 30,
+ [1][1][RTW89_MKK][0][10] = -10,
+ [1][1][RTW89_IC][1][10] = -28,
+ [1][1][RTW89_KCC][1][10] = -14,
+ [1][1][RTW89_KCC][0][10] = -14,
+ [1][1][RTW89_ACMA][1][10] = 32,
+ [1][1][RTW89_ACMA][0][10] = -6,
+ [1][1][RTW89_CHILE][1][10] = -28,
+ [1][1][RTW89_QATAR][1][10] = 32,
+ [1][1][RTW89_QATAR][0][10] = -6,
+ [1][1][RTW89_UK][1][10] = 32,
+ [1][1][RTW89_UK][0][10] = -6,
+ [1][1][RTW89_FCC][1][12] = -28,
+ [1][1][RTW89_FCC][2][12] = 44,
+ [1][1][RTW89_ETSI][1][12] = 32,
+ [1][1][RTW89_ETSI][0][12] = -6,
+ [1][1][RTW89_MKK][1][12] = 30,
+ [1][1][RTW89_MKK][0][12] = -10,
+ [1][1][RTW89_IC][1][12] = -28,
+ [1][1][RTW89_KCC][1][12] = -14,
+ [1][1][RTW89_KCC][0][12] = -14,
+ [1][1][RTW89_ACMA][1][12] = 32,
+ [1][1][RTW89_ACMA][0][12] = -6,
+ [1][1][RTW89_CHILE][1][12] = -28,
+ [1][1][RTW89_QATAR][1][12] = 32,
+ [1][1][RTW89_QATAR][0][12] = -6,
+ [1][1][RTW89_UK][1][12] = 32,
+ [1][1][RTW89_UK][0][12] = -6,
+ [1][1][RTW89_FCC][1][14] = -28,
+ [1][1][RTW89_FCC][2][14] = 44,
+ [1][1][RTW89_ETSI][1][14] = 32,
+ [1][1][RTW89_ETSI][0][14] = -6,
+ [1][1][RTW89_MKK][1][14] = 30,
+ [1][1][RTW89_MKK][0][14] = -10,
+ [1][1][RTW89_IC][1][14] = -28,
+ [1][1][RTW89_KCC][1][14] = -14,
+ [1][1][RTW89_KCC][0][14] = -14,
+ [1][1][RTW89_ACMA][1][14] = 32,
+ [1][1][RTW89_ACMA][0][14] = -6,
+ [1][1][RTW89_CHILE][1][14] = -28,
+ [1][1][RTW89_QATAR][1][14] = 32,
+ [1][1][RTW89_QATAR][0][14] = -6,
+ [1][1][RTW89_UK][1][14] = 32,
+ [1][1][RTW89_UK][0][14] = -6,
+ [1][1][RTW89_FCC][1][15] = -28,
+ [1][1][RTW89_FCC][2][15] = 44,
+ [1][1][RTW89_ETSI][1][15] = 32,
+ [1][1][RTW89_ETSI][0][15] = -6,
+ [1][1][RTW89_MKK][1][15] = 30,
+ [1][1][RTW89_MKK][0][15] = -10,
+ [1][1][RTW89_IC][1][15] = -28,
+ [1][1][RTW89_KCC][1][15] = -14,
+ [1][1][RTW89_KCC][0][15] = -14,
+ [1][1][RTW89_ACMA][1][15] = 32,
+ [1][1][RTW89_ACMA][0][15] = -6,
+ [1][1][RTW89_CHILE][1][15] = -28,
+ [1][1][RTW89_QATAR][1][15] = 32,
+ [1][1][RTW89_QATAR][0][15] = -6,
+ [1][1][RTW89_UK][1][15] = 32,
+ [1][1][RTW89_UK][0][15] = -6,
+ [1][1][RTW89_FCC][1][17] = -28,
+ [1][1][RTW89_FCC][2][17] = 44,
+ [1][1][RTW89_ETSI][1][17] = 32,
+ [1][1][RTW89_ETSI][0][17] = -6,
+ [1][1][RTW89_MKK][1][17] = 30,
+ [1][1][RTW89_MKK][0][17] = -10,
+ [1][1][RTW89_IC][1][17] = -28,
+ [1][1][RTW89_KCC][1][17] = -14,
+ [1][1][RTW89_KCC][0][17] = -14,
+ [1][1][RTW89_ACMA][1][17] = 32,
+ [1][1][RTW89_ACMA][0][17] = -6,
+ [1][1][RTW89_CHILE][1][17] = -28,
+ [1][1][RTW89_QATAR][1][17] = 32,
+ [1][1][RTW89_QATAR][0][17] = -6,
+ [1][1][RTW89_UK][1][17] = 32,
+ [1][1][RTW89_UK][0][17] = -6,
+ [1][1][RTW89_FCC][1][19] = -28,
+ [1][1][RTW89_FCC][2][19] = 44,
+ [1][1][RTW89_ETSI][1][19] = 32,
+ [1][1][RTW89_ETSI][0][19] = -6,
+ [1][1][RTW89_MKK][1][19] = 30,
+ [1][1][RTW89_MKK][0][19] = -10,
+ [1][1][RTW89_IC][1][19] = -28,
+ [1][1][RTW89_KCC][1][19] = -14,
+ [1][1][RTW89_KCC][0][19] = -14,
+ [1][1][RTW89_ACMA][1][19] = 32,
+ [1][1][RTW89_ACMA][0][19] = -6,
+ [1][1][RTW89_CHILE][1][19] = -28,
+ [1][1][RTW89_QATAR][1][19] = 32,
+ [1][1][RTW89_QATAR][0][19] = -6,
+ [1][1][RTW89_UK][1][19] = 32,
+ [1][1][RTW89_UK][0][19] = -6,
+ [1][1][RTW89_FCC][1][21] = -28,
+ [1][1][RTW89_FCC][2][21] = 44,
+ [1][1][RTW89_ETSI][1][21] = 32,
+ [1][1][RTW89_ETSI][0][21] = -6,
+ [1][1][RTW89_MKK][1][21] = 30,
+ [1][1][RTW89_MKK][0][21] = -10,
+ [1][1][RTW89_IC][1][21] = -28,
+ [1][1][RTW89_KCC][1][21] = -14,
+ [1][1][RTW89_KCC][0][21] = -14,
+ [1][1][RTW89_ACMA][1][21] = 32,
+ [1][1][RTW89_ACMA][0][21] = -6,
+ [1][1][RTW89_CHILE][1][21] = -28,
+ [1][1][RTW89_QATAR][1][21] = 32,
+ [1][1][RTW89_QATAR][0][21] = -6,
+ [1][1][RTW89_UK][1][21] = 32,
+ [1][1][RTW89_UK][0][21] = -6,
+ [1][1][RTW89_FCC][1][23] = -28,
+ [1][1][RTW89_FCC][2][23] = 44,
+ [1][1][RTW89_ETSI][1][23] = 32,
+ [1][1][RTW89_ETSI][0][23] = -6,
+ [1][1][RTW89_MKK][1][23] = 32,
+ [1][1][RTW89_MKK][0][23] = -10,
+ [1][1][RTW89_IC][1][23] = -28,
+ [1][1][RTW89_KCC][1][23] = -14,
+ [1][1][RTW89_KCC][0][23] = -14,
+ [1][1][RTW89_ACMA][1][23] = 32,
+ [1][1][RTW89_ACMA][0][23] = -6,
+ [1][1][RTW89_CHILE][1][23] = -28,
+ [1][1][RTW89_QATAR][1][23] = 32,
+ [1][1][RTW89_QATAR][0][23] = -6,
+ [1][1][RTW89_UK][1][23] = 32,
+ [1][1][RTW89_UK][0][23] = -6,
+ [1][1][RTW89_FCC][1][25] = -28,
+ [1][1][RTW89_FCC][2][25] = 44,
+ [1][1][RTW89_ETSI][1][25] = 32,
+ [1][1][RTW89_ETSI][0][25] = -6,
+ [1][1][RTW89_MKK][1][25] = 32,
+ [1][1][RTW89_MKK][0][25] = -10,
+ [1][1][RTW89_IC][1][25] = -28,
+ [1][1][RTW89_KCC][1][25] = -14,
+ [1][1][RTW89_KCC][0][25] = -14,
+ [1][1][RTW89_ACMA][1][25] = 32,
+ [1][1][RTW89_ACMA][0][25] = -6,
+ [1][1][RTW89_CHILE][1][25] = -28,
+ [1][1][RTW89_QATAR][1][25] = 32,
+ [1][1][RTW89_QATAR][0][25] = -6,
+ [1][1][RTW89_UK][1][25] = 32,
+ [1][1][RTW89_UK][0][25] = -6,
+ [1][1][RTW89_FCC][1][27] = -28,
+ [1][1][RTW89_FCC][2][27] = 44,
+ [1][1][RTW89_ETSI][1][27] = 32,
+ [1][1][RTW89_ETSI][0][27] = -6,
+ [1][1][RTW89_MKK][1][27] = 32,
+ [1][1][RTW89_MKK][0][27] = -10,
+ [1][1][RTW89_IC][1][27] = -28,
+ [1][1][RTW89_KCC][1][27] = -14,
+ [1][1][RTW89_KCC][0][27] = -14,
+ [1][1][RTW89_ACMA][1][27] = 32,
+ [1][1][RTW89_ACMA][0][27] = -6,
+ [1][1][RTW89_CHILE][1][27] = -28,
+ [1][1][RTW89_QATAR][1][27] = 32,
+ [1][1][RTW89_QATAR][0][27] = -6,
+ [1][1][RTW89_UK][1][27] = 32,
+ [1][1][RTW89_UK][0][27] = -6,
+ [1][1][RTW89_FCC][1][29] = -28,
+ [1][1][RTW89_FCC][2][29] = 44,
+ [1][1][RTW89_ETSI][1][29] = 32,
+ [1][1][RTW89_ETSI][0][29] = -6,
+ [1][1][RTW89_MKK][1][29] = 32,
+ [1][1][RTW89_MKK][0][29] = -10,
+ [1][1][RTW89_IC][1][29] = -28,
+ [1][1][RTW89_KCC][1][29] = -14,
+ [1][1][RTW89_KCC][0][29] = -14,
+ [1][1][RTW89_ACMA][1][29] = 32,
+ [1][1][RTW89_ACMA][0][29] = -6,
+ [1][1][RTW89_CHILE][1][29] = -28,
+ [1][1][RTW89_QATAR][1][29] = 32,
+ [1][1][RTW89_QATAR][0][29] = -6,
+ [1][1][RTW89_UK][1][29] = 32,
+ [1][1][RTW89_UK][0][29] = -6,
+ [1][1][RTW89_FCC][1][30] = -28,
+ [1][1][RTW89_FCC][2][30] = 44,
+ [1][1][RTW89_ETSI][1][30] = 32,
+ [1][1][RTW89_ETSI][0][30] = -6,
+ [1][1][RTW89_MKK][1][30] = 32,
+ [1][1][RTW89_MKK][0][30] = -10,
+ [1][1][RTW89_IC][1][30] = -28,
+ [1][1][RTW89_KCC][1][30] = -14,
+ [1][1][RTW89_KCC][0][30] = -14,
+ [1][1][RTW89_ACMA][1][30] = 32,
+ [1][1][RTW89_ACMA][0][30] = -6,
+ [1][1][RTW89_CHILE][1][30] = -28,
+ [1][1][RTW89_QATAR][1][30] = 32,
+ [1][1][RTW89_QATAR][0][30] = -6,
+ [1][1][RTW89_UK][1][30] = 32,
+ [1][1][RTW89_UK][0][30] = -6,
+ [1][1][RTW89_FCC][1][32] = -28,
+ [1][1][RTW89_FCC][2][32] = 44,
+ [1][1][RTW89_ETSI][1][32] = 32,
+ [1][1][RTW89_ETSI][0][32] = -6,
+ [1][1][RTW89_MKK][1][32] = 32,
+ [1][1][RTW89_MKK][0][32] = -10,
+ [1][1][RTW89_IC][1][32] = -28,
+ [1][1][RTW89_KCC][1][32] = -14,
+ [1][1][RTW89_KCC][0][32] = -14,
+ [1][1][RTW89_ACMA][1][32] = 32,
+ [1][1][RTW89_ACMA][0][32] = -6,
+ [1][1][RTW89_CHILE][1][32] = -28,
+ [1][1][RTW89_QATAR][1][32] = 32,
+ [1][1][RTW89_QATAR][0][32] = -6,
+ [1][1][RTW89_UK][1][32] = 32,
+ [1][1][RTW89_UK][0][32] = -6,
+ [1][1][RTW89_FCC][1][34] = -28,
+ [1][1][RTW89_FCC][2][34] = 44,
+ [1][1][RTW89_ETSI][1][34] = 32,
+ [1][1][RTW89_ETSI][0][34] = -6,
+ [1][1][RTW89_MKK][1][34] = 32,
+ [1][1][RTW89_MKK][0][34] = -10,
+ [1][1][RTW89_IC][1][34] = -28,
+ [1][1][RTW89_KCC][1][34] = -14,
+ [1][1][RTW89_KCC][0][34] = -14,
+ [1][1][RTW89_ACMA][1][34] = 32,
+ [1][1][RTW89_ACMA][0][34] = -6,
+ [1][1][RTW89_CHILE][1][34] = -28,
+ [1][1][RTW89_QATAR][1][34] = 32,
+ [1][1][RTW89_QATAR][0][34] = -6,
+ [1][1][RTW89_UK][1][34] = 32,
+ [1][1][RTW89_UK][0][34] = -6,
+ [1][1][RTW89_FCC][1][36] = -28,
+ [1][1][RTW89_FCC][2][36] = 44,
+ [1][1][RTW89_ETSI][1][36] = 32,
+ [1][1][RTW89_ETSI][0][36] = -6,
+ [1][1][RTW89_MKK][1][36] = 32,
+ [1][1][RTW89_MKK][0][36] = -10,
+ [1][1][RTW89_IC][1][36] = -28,
+ [1][1][RTW89_KCC][1][36] = -14,
+ [1][1][RTW89_KCC][0][36] = -14,
+ [1][1][RTW89_ACMA][1][36] = 32,
+ [1][1][RTW89_ACMA][0][36] = -6,
+ [1][1][RTW89_CHILE][1][36] = -28,
+ [1][1][RTW89_QATAR][1][36] = 32,
+ [1][1][RTW89_QATAR][0][36] = -6,
+ [1][1][RTW89_UK][1][36] = 32,
+ [1][1][RTW89_UK][0][36] = -6,
+ [1][1][RTW89_FCC][1][38] = -28,
+ [1][1][RTW89_FCC][2][38] = 44,
+ [1][1][RTW89_ETSI][1][38] = 32,
+ [1][1][RTW89_ETSI][0][38] = -6,
+ [1][1][RTW89_MKK][1][38] = 32,
+ [1][1][RTW89_MKK][0][38] = -10,
+ [1][1][RTW89_IC][1][38] = -28,
+ [1][1][RTW89_KCC][1][38] = -14,
+ [1][1][RTW89_KCC][0][38] = -14,
+ [1][1][RTW89_ACMA][1][38] = 32,
+ [1][1][RTW89_ACMA][0][38] = -6,
+ [1][1][RTW89_CHILE][1][38] = -28,
+ [1][1][RTW89_QATAR][1][38] = 32,
+ [1][1][RTW89_QATAR][0][38] = -6,
+ [1][1][RTW89_UK][1][38] = 32,
+ [1][1][RTW89_UK][0][38] = -6,
+ [1][1][RTW89_FCC][1][40] = -28,
+ [1][1][RTW89_FCC][2][40] = 44,
+ [1][1][RTW89_ETSI][1][40] = 32,
+ [1][1][RTW89_ETSI][0][40] = -6,
+ [1][1][RTW89_MKK][1][40] = 32,
+ [1][1][RTW89_MKK][0][40] = -10,
+ [1][1][RTW89_IC][1][40] = -28,
+ [1][1][RTW89_KCC][1][40] = -14,
+ [1][1][RTW89_KCC][0][40] = -14,
+ [1][1][RTW89_ACMA][1][40] = 32,
+ [1][1][RTW89_ACMA][0][40] = -6,
+ [1][1][RTW89_CHILE][1][40] = -28,
+ [1][1][RTW89_QATAR][1][40] = 32,
+ [1][1][RTW89_QATAR][0][40] = -6,
+ [1][1][RTW89_UK][1][40] = 32,
+ [1][1][RTW89_UK][0][40] = -6,
+ [1][1][RTW89_FCC][1][42] = -28,
+ [1][1][RTW89_FCC][2][42] = 44,
+ [1][1][RTW89_ETSI][1][42] = 32,
+ [1][1][RTW89_ETSI][0][42] = -6,
+ [1][1][RTW89_MKK][1][42] = 32,
+ [1][1][RTW89_MKK][0][42] = -10,
+ [1][1][RTW89_IC][1][42] = -28,
+ [1][1][RTW89_KCC][1][42] = -14,
+ [1][1][RTW89_KCC][0][42] = -14,
+ [1][1][RTW89_ACMA][1][42] = 32,
+ [1][1][RTW89_ACMA][0][42] = -6,
+ [1][1][RTW89_CHILE][1][42] = -28,
+ [1][1][RTW89_QATAR][1][42] = 32,
+ [1][1][RTW89_QATAR][0][42] = -6,
+ [1][1][RTW89_UK][1][42] = 32,
+ [1][1][RTW89_UK][0][42] = -6,
+ [1][1][RTW89_FCC][1][44] = -28,
+ [1][1][RTW89_FCC][2][44] = 44,
+ [1][1][RTW89_ETSI][1][44] = 34,
+ [1][1][RTW89_ETSI][0][44] = -4,
+ [1][1][RTW89_MKK][1][44] = 4,
+ [1][1][RTW89_MKK][0][44] = -8,
+ [1][1][RTW89_IC][1][44] = -28,
+ [1][1][RTW89_KCC][1][44] = -14,
+ [1][1][RTW89_KCC][0][44] = -14,
+ [1][1][RTW89_ACMA][1][44] = 34,
+ [1][1][RTW89_ACMA][0][44] = -4,
+ [1][1][RTW89_CHILE][1][44] = -28,
+ [1][1][RTW89_QATAR][1][44] = 34,
+ [1][1][RTW89_QATAR][0][44] = -4,
+ [1][1][RTW89_UK][1][44] = 34,
+ [1][1][RTW89_UK][0][44] = -4,
+ [1][1][RTW89_FCC][1][45] = -26,
+ [1][1][RTW89_FCC][2][45] = 127,
+ [1][1][RTW89_ETSI][1][45] = 127,
+ [1][1][RTW89_ETSI][0][45] = 127,
+ [1][1][RTW89_MKK][1][45] = 127,
+ [1][1][RTW89_MKK][0][45] = 127,
+ [1][1][RTW89_IC][1][45] = -26,
+ [1][1][RTW89_KCC][1][45] = -14,
+ [1][1][RTW89_KCC][0][45] = 127,
+ [1][1][RTW89_ACMA][1][45] = 127,
+ [1][1][RTW89_ACMA][0][45] = 127,
+ [1][1][RTW89_CHILE][1][45] = 127,
+ [1][1][RTW89_QATAR][1][45] = 127,
+ [1][1][RTW89_QATAR][0][45] = 127,
+ [1][1][RTW89_UK][1][45] = 127,
+ [1][1][RTW89_UK][0][45] = 127,
+ [1][1][RTW89_FCC][1][47] = -28,
+ [1][1][RTW89_FCC][2][47] = 127,
+ [1][1][RTW89_ETSI][1][47] = 127,
+ [1][1][RTW89_ETSI][0][47] = 127,
+ [1][1][RTW89_MKK][1][47] = 127,
+ [1][1][RTW89_MKK][0][47] = 127,
+ [1][1][RTW89_IC][1][47] = -28,
+ [1][1][RTW89_KCC][1][47] = -14,
+ [1][1][RTW89_KCC][0][47] = 127,
+ [1][1][RTW89_ACMA][1][47] = 127,
+ [1][1][RTW89_ACMA][0][47] = 127,
+ [1][1][RTW89_CHILE][1][47] = 127,
+ [1][1][RTW89_QATAR][1][47] = 127,
+ [1][1][RTW89_QATAR][0][47] = 127,
+ [1][1][RTW89_UK][1][47] = 127,
+ [1][1][RTW89_UK][0][47] = 127,
+ [1][1][RTW89_FCC][1][49] = -28,
+ [1][1][RTW89_FCC][2][49] = 127,
+ [1][1][RTW89_ETSI][1][49] = 127,
+ [1][1][RTW89_ETSI][0][49] = 127,
+ [1][1][RTW89_MKK][1][49] = 127,
+ [1][1][RTW89_MKK][0][49] = 127,
+ [1][1][RTW89_IC][1][49] = -28,
+ [1][1][RTW89_KCC][1][49] = -14,
+ [1][1][RTW89_KCC][0][49] = 127,
+ [1][1][RTW89_ACMA][1][49] = 127,
+ [1][1][RTW89_ACMA][0][49] = 127,
+ [1][1][RTW89_CHILE][1][49] = 127,
+ [1][1][RTW89_QATAR][1][49] = 127,
+ [1][1][RTW89_QATAR][0][49] = 127,
+ [1][1][RTW89_UK][1][49] = 127,
+ [1][1][RTW89_UK][0][49] = 127,
+ [1][1][RTW89_FCC][1][51] = -28,
+ [1][1][RTW89_FCC][2][51] = 127,
+ [1][1][RTW89_ETSI][1][51] = 127,
+ [1][1][RTW89_ETSI][0][51] = 127,
+ [1][1][RTW89_MKK][1][51] = 127,
+ [1][1][RTW89_MKK][0][51] = 127,
+ [1][1][RTW89_IC][1][51] = -28,
+ [1][1][RTW89_KCC][1][51] = -14,
+ [1][1][RTW89_KCC][0][51] = 127,
+ [1][1][RTW89_ACMA][1][51] = 127,
+ [1][1][RTW89_ACMA][0][51] = 127,
+ [1][1][RTW89_CHILE][1][51] = 127,
+ [1][1][RTW89_QATAR][1][51] = 127,
+ [1][1][RTW89_QATAR][0][51] = 127,
+ [1][1][RTW89_UK][1][51] = 127,
+ [1][1][RTW89_UK][0][51] = 127,
+ [1][1][RTW89_FCC][1][53] = -26,
+ [1][1][RTW89_FCC][2][53] = 127,
+ [1][1][RTW89_ETSI][1][53] = 127,
+ [1][1][RTW89_ETSI][0][53] = 127,
+ [1][1][RTW89_MKK][1][53] = 127,
+ [1][1][RTW89_MKK][0][53] = 127,
+ [1][1][RTW89_IC][1][53] = -26,
+ [1][1][RTW89_KCC][1][53] = -14,
+ [1][1][RTW89_KCC][0][53] = 127,
+ [1][1][RTW89_ACMA][1][53] = 127,
+ [1][1][RTW89_ACMA][0][53] = 127,
+ [1][1][RTW89_CHILE][1][53] = 127,
+ [1][1][RTW89_QATAR][1][53] = 127,
+ [1][1][RTW89_QATAR][0][53] = 127,
+ [1][1][RTW89_UK][1][53] = 127,
+ [1][1][RTW89_UK][0][53] = 127,
+ [1][1][RTW89_FCC][1][55] = -28,
+ [1][1][RTW89_FCC][2][55] = 44,
+ [1][1][RTW89_ETSI][1][55] = 127,
+ [1][1][RTW89_ETSI][0][55] = 127,
+ [1][1][RTW89_MKK][1][55] = 127,
+ [1][1][RTW89_MKK][0][55] = 127,
+ [1][1][RTW89_IC][1][55] = -28,
+ [1][1][RTW89_KCC][1][55] = -14,
+ [1][1][RTW89_KCC][0][55] = 127,
+ [1][1][RTW89_ACMA][1][55] = 127,
+ [1][1][RTW89_ACMA][0][55] = 127,
+ [1][1][RTW89_CHILE][1][55] = 127,
+ [1][1][RTW89_QATAR][1][55] = 127,
+ [1][1][RTW89_QATAR][0][55] = 127,
+ [1][1][RTW89_UK][1][55] = 127,
+ [1][1][RTW89_UK][0][55] = 127,
+ [1][1][RTW89_FCC][1][57] = -28,
+ [1][1][RTW89_FCC][2][57] = 44,
+ [1][1][RTW89_ETSI][1][57] = 127,
+ [1][1][RTW89_ETSI][0][57] = 127,
+ [1][1][RTW89_MKK][1][57] = 127,
+ [1][1][RTW89_MKK][0][57] = 127,
+ [1][1][RTW89_IC][1][57] = -28,
+ [1][1][RTW89_KCC][1][57] = -14,
+ [1][1][RTW89_KCC][0][57] = 127,
+ [1][1][RTW89_ACMA][1][57] = 127,
+ [1][1][RTW89_ACMA][0][57] = 127,
+ [1][1][RTW89_CHILE][1][57] = 127,
+ [1][1][RTW89_QATAR][1][57] = 127,
+ [1][1][RTW89_QATAR][0][57] = 127,
+ [1][1][RTW89_UK][1][57] = 127,
+ [1][1][RTW89_UK][0][57] = 127,
+ [1][1][RTW89_FCC][1][59] = -28,
+ [1][1][RTW89_FCC][2][59] = 44,
+ [1][1][RTW89_ETSI][1][59] = 127,
+ [1][1][RTW89_ETSI][0][59] = 127,
+ [1][1][RTW89_MKK][1][59] = 127,
+ [1][1][RTW89_MKK][0][59] = 127,
+ [1][1][RTW89_IC][1][59] = -28,
+ [1][1][RTW89_KCC][1][59] = -14,
+ [1][1][RTW89_KCC][0][59] = 127,
+ [1][1][RTW89_ACMA][1][59] = 127,
+ [1][1][RTW89_ACMA][0][59] = 127,
+ [1][1][RTW89_CHILE][1][59] = 127,
+ [1][1][RTW89_QATAR][1][59] = 127,
+ [1][1][RTW89_QATAR][0][59] = 127,
+ [1][1][RTW89_UK][1][59] = 127,
+ [1][1][RTW89_UK][0][59] = 127,
+ [1][1][RTW89_FCC][1][60] = -28,
+ [1][1][RTW89_FCC][2][60] = 44,
+ [1][1][RTW89_ETSI][1][60] = 127,
+ [1][1][RTW89_ETSI][0][60] = 127,
+ [1][1][RTW89_MKK][1][60] = 127,
+ [1][1][RTW89_MKK][0][60] = 127,
+ [1][1][RTW89_IC][1][60] = -28,
+ [1][1][RTW89_KCC][1][60] = -14,
+ [1][1][RTW89_KCC][0][60] = 127,
+ [1][1][RTW89_ACMA][1][60] = 127,
+ [1][1][RTW89_ACMA][0][60] = 127,
+ [1][1][RTW89_CHILE][1][60] = 127,
+ [1][1][RTW89_QATAR][1][60] = 127,
+ [1][1][RTW89_QATAR][0][60] = 127,
+ [1][1][RTW89_UK][1][60] = 127,
+ [1][1][RTW89_UK][0][60] = 127,
+ [1][1][RTW89_FCC][1][62] = -28,
+ [1][1][RTW89_FCC][2][62] = 44,
+ [1][1][RTW89_ETSI][1][62] = 127,
+ [1][1][RTW89_ETSI][0][62] = 127,
+ [1][1][RTW89_MKK][1][62] = 127,
+ [1][1][RTW89_MKK][0][62] = 127,
+ [1][1][RTW89_IC][1][62] = -28,
+ [1][1][RTW89_KCC][1][62] = -14,
+ [1][1][RTW89_KCC][0][62] = 127,
+ [1][1][RTW89_ACMA][1][62] = 127,
+ [1][1][RTW89_ACMA][0][62] = 127,
+ [1][1][RTW89_CHILE][1][62] = 127,
+ [1][1][RTW89_QATAR][1][62] = 127,
+ [1][1][RTW89_QATAR][0][62] = 127,
+ [1][1][RTW89_UK][1][62] = 127,
+ [1][1][RTW89_UK][0][62] = 127,
+ [1][1][RTW89_FCC][1][64] = -28,
+ [1][1][RTW89_FCC][2][64] = 44,
+ [1][1][RTW89_ETSI][1][64] = 127,
+ [1][1][RTW89_ETSI][0][64] = 127,
+ [1][1][RTW89_MKK][1][64] = 127,
+ [1][1][RTW89_MKK][0][64] = 127,
+ [1][1][RTW89_IC][1][64] = -28,
+ [1][1][RTW89_KCC][1][64] = -14,
+ [1][1][RTW89_KCC][0][64] = 127,
+ [1][1][RTW89_ACMA][1][64] = 127,
+ [1][1][RTW89_ACMA][0][64] = 127,
+ [1][1][RTW89_CHILE][1][64] = 127,
+ [1][1][RTW89_QATAR][1][64] = 127,
+ [1][1][RTW89_QATAR][0][64] = 127,
+ [1][1][RTW89_UK][1][64] = 127,
+ [1][1][RTW89_UK][0][64] = 127,
+ [1][1][RTW89_FCC][1][66] = -28,
+ [1][1][RTW89_FCC][2][66] = 44,
+ [1][1][RTW89_ETSI][1][66] = 127,
+ [1][1][RTW89_ETSI][0][66] = 127,
+ [1][1][RTW89_MKK][1][66] = 127,
+ [1][1][RTW89_MKK][0][66] = 127,
+ [1][1][RTW89_IC][1][66] = -28,
+ [1][1][RTW89_KCC][1][66] = -14,
+ [1][1][RTW89_KCC][0][66] = 127,
+ [1][1][RTW89_ACMA][1][66] = 127,
+ [1][1][RTW89_ACMA][0][66] = 127,
+ [1][1][RTW89_CHILE][1][66] = 127,
+ [1][1][RTW89_QATAR][1][66] = 127,
+ [1][1][RTW89_QATAR][0][66] = 127,
+ [1][1][RTW89_UK][1][66] = 127,
+ [1][1][RTW89_UK][0][66] = 127,
+ [1][1][RTW89_FCC][1][68] = -28,
+ [1][1][RTW89_FCC][2][68] = 44,
+ [1][1][RTW89_ETSI][1][68] = 127,
+ [1][1][RTW89_ETSI][0][68] = 127,
+ [1][1][RTW89_MKK][1][68] = 127,
+ [1][1][RTW89_MKK][0][68] = 127,
+ [1][1][RTW89_IC][1][68] = -28,
+ [1][1][RTW89_KCC][1][68] = -14,
+ [1][1][RTW89_KCC][0][68] = 127,
+ [1][1][RTW89_ACMA][1][68] = 127,
+ [1][1][RTW89_ACMA][0][68] = 127,
+ [1][1][RTW89_CHILE][1][68] = 127,
+ [1][1][RTW89_QATAR][1][68] = 127,
+ [1][1][RTW89_QATAR][0][68] = 127,
+ [1][1][RTW89_UK][1][68] = 127,
+ [1][1][RTW89_UK][0][68] = 127,
+ [1][1][RTW89_FCC][1][70] = -26,
+ [1][1][RTW89_FCC][2][70] = 44,
+ [1][1][RTW89_ETSI][1][70] = 127,
+ [1][1][RTW89_ETSI][0][70] = 127,
+ [1][1][RTW89_MKK][1][70] = 127,
+ [1][1][RTW89_MKK][0][70] = 127,
+ [1][1][RTW89_IC][1][70] = -26,
+ [1][1][RTW89_KCC][1][70] = -14,
+ [1][1][RTW89_KCC][0][70] = 127,
+ [1][1][RTW89_ACMA][1][70] = 127,
+ [1][1][RTW89_ACMA][0][70] = 127,
+ [1][1][RTW89_CHILE][1][70] = 127,
+ [1][1][RTW89_QATAR][1][70] = 127,
+ [1][1][RTW89_QATAR][0][70] = 127,
+ [1][1][RTW89_UK][1][70] = 127,
+ [1][1][RTW89_UK][0][70] = 127,
+ [1][1][RTW89_FCC][1][72] = -28,
+ [1][1][RTW89_FCC][2][72] = 44,
+ [1][1][RTW89_ETSI][1][72] = 127,
+ [1][1][RTW89_ETSI][0][72] = 127,
+ [1][1][RTW89_MKK][1][72] = 127,
+ [1][1][RTW89_MKK][0][72] = 127,
+ [1][1][RTW89_IC][1][72] = -28,
+ [1][1][RTW89_KCC][1][72] = -14,
+ [1][1][RTW89_KCC][0][72] = 127,
+ [1][1][RTW89_ACMA][1][72] = 127,
+ [1][1][RTW89_ACMA][0][72] = 127,
+ [1][1][RTW89_CHILE][1][72] = 127,
+ [1][1][RTW89_QATAR][1][72] = 127,
+ [1][1][RTW89_QATAR][0][72] = 127,
+ [1][1][RTW89_UK][1][72] = 127,
+ [1][1][RTW89_UK][0][72] = 127,
+ [1][1][RTW89_FCC][1][74] = -28,
+ [1][1][RTW89_FCC][2][74] = 44,
+ [1][1][RTW89_ETSI][1][74] = 127,
+ [1][1][RTW89_ETSI][0][74] = 127,
+ [1][1][RTW89_MKK][1][74] = 127,
+ [1][1][RTW89_MKK][0][74] = 127,
+ [1][1][RTW89_IC][1][74] = -28,
+ [1][1][RTW89_KCC][1][74] = -14,
+ [1][1][RTW89_KCC][0][74] = 127,
+ [1][1][RTW89_ACMA][1][74] = 127,
+ [1][1][RTW89_ACMA][0][74] = 127,
+ [1][1][RTW89_CHILE][1][74] = 127,
+ [1][1][RTW89_QATAR][1][74] = 127,
+ [1][1][RTW89_QATAR][0][74] = 127,
+ [1][1][RTW89_UK][1][74] = 127,
+ [1][1][RTW89_UK][0][74] = 127,
+ [1][1][RTW89_FCC][1][75] = -28,
+ [1][1][RTW89_FCC][2][75] = 44,
+ [1][1][RTW89_ETSI][1][75] = 127,
+ [1][1][RTW89_ETSI][0][75] = 127,
+ [1][1][RTW89_MKK][1][75] = 127,
+ [1][1][RTW89_MKK][0][75] = 127,
+ [1][1][RTW89_IC][1][75] = -28,
+ [1][1][RTW89_KCC][1][75] = -14,
+ [1][1][RTW89_KCC][0][75] = 127,
+ [1][1][RTW89_ACMA][1][75] = 127,
+ [1][1][RTW89_ACMA][0][75] = 127,
+ [1][1][RTW89_CHILE][1][75] = 127,
+ [1][1][RTW89_QATAR][1][75] = 127,
+ [1][1][RTW89_QATAR][0][75] = 127,
+ [1][1][RTW89_UK][1][75] = 127,
+ [1][1][RTW89_UK][0][75] = 127,
+ [1][1][RTW89_FCC][1][77] = -28,
+ [1][1][RTW89_FCC][2][77] = 44,
+ [1][1][RTW89_ETSI][1][77] = 127,
+ [1][1][RTW89_ETSI][0][77] = 127,
+ [1][1][RTW89_MKK][1][77] = 127,
+ [1][1][RTW89_MKK][0][77] = 127,
+ [1][1][RTW89_IC][1][77] = -28,
+ [1][1][RTW89_KCC][1][77] = -14,
+ [1][1][RTW89_KCC][0][77] = 127,
+ [1][1][RTW89_ACMA][1][77] = 127,
+ [1][1][RTW89_ACMA][0][77] = 127,
+ [1][1][RTW89_CHILE][1][77] = 127,
+ [1][1][RTW89_QATAR][1][77] = 127,
+ [1][1][RTW89_QATAR][0][77] = 127,
+ [1][1][RTW89_UK][1][77] = 127,
+ [1][1][RTW89_UK][0][77] = 127,
+ [1][1][RTW89_FCC][1][79] = -28,
+ [1][1][RTW89_FCC][2][79] = 44,
+ [1][1][RTW89_ETSI][1][79] = 127,
+ [1][1][RTW89_ETSI][0][79] = 127,
+ [1][1][RTW89_MKK][1][79] = 127,
+ [1][1][RTW89_MKK][0][79] = 127,
+ [1][1][RTW89_IC][1][79] = -28,
+ [1][1][RTW89_KCC][1][79] = -14,
+ [1][1][RTW89_KCC][0][79] = 127,
+ [1][1][RTW89_ACMA][1][79] = 127,
+ [1][1][RTW89_ACMA][0][79] = 127,
+ [1][1][RTW89_CHILE][1][79] = 127,
+ [1][1][RTW89_QATAR][1][79] = 127,
+ [1][1][RTW89_QATAR][0][79] = 127,
+ [1][1][RTW89_UK][1][79] = 127,
+ [1][1][RTW89_UK][0][79] = 127,
+ [1][1][RTW89_FCC][1][81] = -28,
+ [1][1][RTW89_FCC][2][81] = 44,
+ [1][1][RTW89_ETSI][1][81] = 127,
+ [1][1][RTW89_ETSI][0][81] = 127,
+ [1][1][RTW89_MKK][1][81] = 127,
+ [1][1][RTW89_MKK][0][81] = 127,
+ [1][1][RTW89_IC][1][81] = -28,
+ [1][1][RTW89_KCC][1][81] = -14,
+ [1][1][RTW89_KCC][0][81] = 127,
+ [1][1][RTW89_ACMA][1][81] = 127,
+ [1][1][RTW89_ACMA][0][81] = 127,
+ [1][1][RTW89_CHILE][1][81] = 127,
+ [1][1][RTW89_QATAR][1][81] = 127,
+ [1][1][RTW89_QATAR][0][81] = 127,
+ [1][1][RTW89_UK][1][81] = 127,
+ [1][1][RTW89_UK][0][81] = 127,
+ [1][1][RTW89_FCC][1][83] = -28,
+ [1][1][RTW89_FCC][2][83] = 44,
+ [1][1][RTW89_ETSI][1][83] = 127,
+ [1][1][RTW89_ETSI][0][83] = 127,
+ [1][1][RTW89_MKK][1][83] = 127,
+ [1][1][RTW89_MKK][0][83] = 127,
+ [1][1][RTW89_IC][1][83] = -28,
+ [1][1][RTW89_KCC][1][83] = -14,
+ [1][1][RTW89_KCC][0][83] = 127,
+ [1][1][RTW89_ACMA][1][83] = 127,
+ [1][1][RTW89_ACMA][0][83] = 127,
+ [1][1][RTW89_CHILE][1][83] = 127,
+ [1][1][RTW89_QATAR][1][83] = 127,
+ [1][1][RTW89_QATAR][0][83] = 127,
+ [1][1][RTW89_UK][1][83] = 127,
+ [1][1][RTW89_UK][0][83] = 127,
+ [1][1][RTW89_FCC][1][85] = -28,
+ [1][1][RTW89_FCC][2][85] = 44,
+ [1][1][RTW89_ETSI][1][85] = 127,
+ [1][1][RTW89_ETSI][0][85] = 127,
+ [1][1][RTW89_MKK][1][85] = 127,
+ [1][1][RTW89_MKK][0][85] = 127,
+ [1][1][RTW89_IC][1][85] = -28,
+ [1][1][RTW89_KCC][1][85] = -14,
+ [1][1][RTW89_KCC][0][85] = 127,
+ [1][1][RTW89_ACMA][1][85] = 127,
+ [1][1][RTW89_ACMA][0][85] = 127,
+ [1][1][RTW89_CHILE][1][85] = 127,
+ [1][1][RTW89_QATAR][1][85] = 127,
+ [1][1][RTW89_QATAR][0][85] = 127,
+ [1][1][RTW89_UK][1][85] = 127,
+ [1][1][RTW89_UK][0][85] = 127,
+ [1][1][RTW89_FCC][1][87] = -28,
+ [1][1][RTW89_FCC][2][87] = 127,
+ [1][1][RTW89_ETSI][1][87] = 127,
+ [1][1][RTW89_ETSI][0][87] = 127,
+ [1][1][RTW89_MKK][1][87] = 127,
+ [1][1][RTW89_MKK][0][87] = 127,
+ [1][1][RTW89_IC][1][87] = -28,
+ [1][1][RTW89_KCC][1][87] = -14,
+ [1][1][RTW89_KCC][0][87] = 127,
+ [1][1][RTW89_ACMA][1][87] = 127,
+ [1][1][RTW89_ACMA][0][87] = 127,
+ [1][1][RTW89_CHILE][1][87] = 127,
+ [1][1][RTW89_QATAR][1][87] = 127,
+ [1][1][RTW89_QATAR][0][87] = 127,
+ [1][1][RTW89_UK][1][87] = 127,
+ [1][1][RTW89_UK][0][87] = 127,
+ [1][1][RTW89_FCC][1][89] = -26,
+ [1][1][RTW89_FCC][2][89] = 127,
+ [1][1][RTW89_ETSI][1][89] = 127,
+ [1][1][RTW89_ETSI][0][89] = 127,
+ [1][1][RTW89_MKK][1][89] = 127,
+ [1][1][RTW89_MKK][0][89] = 127,
+ [1][1][RTW89_IC][1][89] = -26,
+ [1][1][RTW89_KCC][1][89] = -14,
+ [1][1][RTW89_KCC][0][89] = 127,
+ [1][1][RTW89_ACMA][1][89] = 127,
+ [1][1][RTW89_ACMA][0][89] = 127,
+ [1][1][RTW89_CHILE][1][89] = 127,
+ [1][1][RTW89_QATAR][1][89] = 127,
+ [1][1][RTW89_QATAR][0][89] = 127,
+ [1][1][RTW89_UK][1][89] = 127,
+ [1][1][RTW89_UK][0][89] = 127,
+ [1][1][RTW89_FCC][1][90] = -26,
+ [1][1][RTW89_FCC][2][90] = 127,
+ [1][1][RTW89_ETSI][1][90] = 127,
+ [1][1][RTW89_ETSI][0][90] = 127,
+ [1][1][RTW89_MKK][1][90] = 127,
+ [1][1][RTW89_MKK][0][90] = 127,
+ [1][1][RTW89_IC][1][90] = -26,
+ [1][1][RTW89_KCC][1][90] = -14,
+ [1][1][RTW89_KCC][0][90] = 127,
+ [1][1][RTW89_ACMA][1][90] = 127,
+ [1][1][RTW89_ACMA][0][90] = 127,
+ [1][1][RTW89_CHILE][1][90] = 127,
+ [1][1][RTW89_QATAR][1][90] = 127,
+ [1][1][RTW89_QATAR][0][90] = 127,
+ [1][1][RTW89_UK][1][90] = 127,
+ [1][1][RTW89_UK][0][90] = 127,
+ [1][1][RTW89_FCC][1][92] = -26,
+ [1][1][RTW89_FCC][2][92] = 127,
+ [1][1][RTW89_ETSI][1][92] = 127,
+ [1][1][RTW89_ETSI][0][92] = 127,
+ [1][1][RTW89_MKK][1][92] = 127,
+ [1][1][RTW89_MKK][0][92] = 127,
+ [1][1][RTW89_IC][1][92] = -26,
+ [1][1][RTW89_KCC][1][92] = -14,
+ [1][1][RTW89_KCC][0][92] = 127,
+ [1][1][RTW89_ACMA][1][92] = 127,
+ [1][1][RTW89_ACMA][0][92] = 127,
+ [1][1][RTW89_CHILE][1][92] = 127,
+ [1][1][RTW89_QATAR][1][92] = 127,
+ [1][1][RTW89_QATAR][0][92] = 127,
+ [1][1][RTW89_UK][1][92] = 127,
+ [1][1][RTW89_UK][0][92] = 127,
+ [1][1][RTW89_FCC][1][94] = -26,
+ [1][1][RTW89_FCC][2][94] = 127,
+ [1][1][RTW89_ETSI][1][94] = 127,
+ [1][1][RTW89_ETSI][0][94] = 127,
+ [1][1][RTW89_MKK][1][94] = 127,
+ [1][1][RTW89_MKK][0][94] = 127,
+ [1][1][RTW89_IC][1][94] = -26,
+ [1][1][RTW89_KCC][1][94] = -14,
+ [1][1][RTW89_KCC][0][94] = 127,
+ [1][1][RTW89_ACMA][1][94] = 127,
+ [1][1][RTW89_ACMA][0][94] = 127,
+ [1][1][RTW89_CHILE][1][94] = 127,
+ [1][1][RTW89_QATAR][1][94] = 127,
+ [1][1][RTW89_QATAR][0][94] = 127,
+ [1][1][RTW89_UK][1][94] = 127,
+ [1][1][RTW89_UK][0][94] = 127,
+ [1][1][RTW89_FCC][1][96] = -26,
+ [1][1][RTW89_FCC][2][96] = 127,
+ [1][1][RTW89_ETSI][1][96] = 127,
+ [1][1][RTW89_ETSI][0][96] = 127,
+ [1][1][RTW89_MKK][1][96] = 127,
+ [1][1][RTW89_MKK][0][96] = 127,
+ [1][1][RTW89_IC][1][96] = -26,
+ [1][1][RTW89_KCC][1][96] = -14,
+ [1][1][RTW89_KCC][0][96] = 127,
+ [1][1][RTW89_ACMA][1][96] = 127,
+ [1][1][RTW89_ACMA][0][96] = 127,
+ [1][1][RTW89_CHILE][1][96] = 127,
+ [1][1][RTW89_QATAR][1][96] = 127,
+ [1][1][RTW89_QATAR][0][96] = 127,
+ [1][1][RTW89_UK][1][96] = 127,
+ [1][1][RTW89_UK][0][96] = 127,
+ [1][1][RTW89_FCC][1][98] = -26,
+ [1][1][RTW89_FCC][2][98] = 127,
+ [1][1][RTW89_ETSI][1][98] = 127,
+ [1][1][RTW89_ETSI][0][98] = 127,
+ [1][1][RTW89_MKK][1][98] = 127,
+ [1][1][RTW89_MKK][0][98] = 127,
+ [1][1][RTW89_IC][1][98] = -26,
+ [1][1][RTW89_KCC][1][98] = -14,
+ [1][1][RTW89_KCC][0][98] = 127,
+ [1][1][RTW89_ACMA][1][98] = 127,
+ [1][1][RTW89_ACMA][0][98] = 127,
+ [1][1][RTW89_CHILE][1][98] = 127,
+ [1][1][RTW89_QATAR][1][98] = 127,
+ [1][1][RTW89_QATAR][0][98] = 127,
+ [1][1][RTW89_UK][1][98] = 127,
+ [1][1][RTW89_UK][0][98] = 127,
+ [1][1][RTW89_FCC][1][100] = -26,
+ [1][1][RTW89_FCC][2][100] = 127,
+ [1][1][RTW89_ETSI][1][100] = 127,
+ [1][1][RTW89_ETSI][0][100] = 127,
+ [1][1][RTW89_MKK][1][100] = 127,
+ [1][1][RTW89_MKK][0][100] = 127,
+ [1][1][RTW89_IC][1][100] = -26,
+ [1][1][RTW89_KCC][1][100] = -14,
+ [1][1][RTW89_KCC][0][100] = 127,
+ [1][1][RTW89_ACMA][1][100] = 127,
+ [1][1][RTW89_ACMA][0][100] = 127,
+ [1][1][RTW89_CHILE][1][100] = 127,
+ [1][1][RTW89_QATAR][1][100] = 127,
+ [1][1][RTW89_QATAR][0][100] = 127,
+ [1][1][RTW89_UK][1][100] = 127,
+ [1][1][RTW89_UK][0][100] = 127,
+ [1][1][RTW89_FCC][1][102] = -26,
+ [1][1][RTW89_FCC][2][102] = 127,
+ [1][1][RTW89_ETSI][1][102] = 127,
+ [1][1][RTW89_ETSI][0][102] = 127,
+ [1][1][RTW89_MKK][1][102] = 127,
+ [1][1][RTW89_MKK][0][102] = 127,
+ [1][1][RTW89_IC][1][102] = -26,
+ [1][1][RTW89_KCC][1][102] = -14,
+ [1][1][RTW89_KCC][0][102] = 127,
+ [1][1][RTW89_ACMA][1][102] = 127,
+ [1][1][RTW89_ACMA][0][102] = 127,
+ [1][1][RTW89_CHILE][1][102] = 127,
+ [1][1][RTW89_QATAR][1][102] = 127,
+ [1][1][RTW89_QATAR][0][102] = 127,
+ [1][1][RTW89_UK][1][102] = 127,
+ [1][1][RTW89_UK][0][102] = 127,
+ [1][1][RTW89_FCC][1][104] = -26,
+ [1][1][RTW89_FCC][2][104] = 127,
+ [1][1][RTW89_ETSI][1][104] = 127,
+ [1][1][RTW89_ETSI][0][104] = 127,
+ [1][1][RTW89_MKK][1][104] = 127,
+ [1][1][RTW89_MKK][0][104] = 127,
+ [1][1][RTW89_IC][1][104] = -26,
+ [1][1][RTW89_KCC][1][104] = -14,
+ [1][1][RTW89_KCC][0][104] = 127,
+ [1][1][RTW89_ACMA][1][104] = 127,
+ [1][1][RTW89_ACMA][0][104] = 127,
+ [1][1][RTW89_CHILE][1][104] = 127,
+ [1][1][RTW89_QATAR][1][104] = 127,
+ [1][1][RTW89_QATAR][0][104] = 127,
+ [1][1][RTW89_UK][1][104] = 127,
+ [1][1][RTW89_UK][0][104] = 127,
+ [1][1][RTW89_FCC][1][105] = -26,
+ [1][1][RTW89_FCC][2][105] = 127,
+ [1][1][RTW89_ETSI][1][105] = 127,
+ [1][1][RTW89_ETSI][0][105] = 127,
+ [1][1][RTW89_MKK][1][105] = 127,
+ [1][1][RTW89_MKK][0][105] = 127,
+ [1][1][RTW89_IC][1][105] = -26,
+ [1][1][RTW89_KCC][1][105] = -14,
+ [1][1][RTW89_KCC][0][105] = 127,
+ [1][1][RTW89_ACMA][1][105] = 127,
+ [1][1][RTW89_ACMA][0][105] = 127,
+ [1][1][RTW89_CHILE][1][105] = 127,
+ [1][1][RTW89_QATAR][1][105] = 127,
+ [1][1][RTW89_QATAR][0][105] = 127,
+ [1][1][RTW89_UK][1][105] = 127,
+ [1][1][RTW89_UK][0][105] = 127,
+ [1][1][RTW89_FCC][1][107] = -22,
+ [1][1][RTW89_FCC][2][107] = 127,
+ [1][1][RTW89_ETSI][1][107] = 127,
+ [1][1][RTW89_ETSI][0][107] = 127,
+ [1][1][RTW89_MKK][1][107] = 127,
+ [1][1][RTW89_MKK][0][107] = 127,
+ [1][1][RTW89_IC][1][107] = -22,
+ [1][1][RTW89_KCC][1][107] = -14,
+ [1][1][RTW89_KCC][0][107] = 127,
+ [1][1][RTW89_ACMA][1][107] = 127,
+ [1][1][RTW89_ACMA][0][107] = 127,
+ [1][1][RTW89_CHILE][1][107] = 127,
+ [1][1][RTW89_QATAR][1][107] = 127,
+ [1][1][RTW89_QATAR][0][107] = 127,
+ [1][1][RTW89_UK][1][107] = 127,
+ [1][1][RTW89_UK][0][107] = 127,
+ [1][1][RTW89_FCC][1][109] = -22,
+ [1][1][RTW89_FCC][2][109] = 127,
+ [1][1][RTW89_ETSI][1][109] = 127,
+ [1][1][RTW89_ETSI][0][109] = 127,
+ [1][1][RTW89_MKK][1][109] = 127,
+ [1][1][RTW89_MKK][0][109] = 127,
+ [1][1][RTW89_IC][1][109] = -22,
+ [1][1][RTW89_KCC][1][109] = 127,
+ [1][1][RTW89_KCC][0][109] = 127,
+ [1][1][RTW89_ACMA][1][109] = 127,
+ [1][1][RTW89_ACMA][0][109] = 127,
+ [1][1][RTW89_CHILE][1][109] = 127,
+ [1][1][RTW89_QATAR][1][109] = 127,
+ [1][1][RTW89_QATAR][0][109] = 127,
+ [1][1][RTW89_UK][1][109] = 127,
+ [1][1][RTW89_UK][0][109] = 127,
+ [1][1][RTW89_FCC][1][111] = 127,
+ [1][1][RTW89_FCC][2][111] = 127,
+ [1][1][RTW89_ETSI][1][111] = 127,
+ [1][1][RTW89_ETSI][0][111] = 127,
+ [1][1][RTW89_MKK][1][111] = 127,
+ [1][1][RTW89_MKK][0][111] = 127,
+ [1][1][RTW89_IC][1][111] = 127,
+ [1][1][RTW89_KCC][1][111] = 127,
+ [1][1][RTW89_KCC][0][111] = 127,
+ [1][1][RTW89_ACMA][1][111] = 127,
+ [1][1][RTW89_ACMA][0][111] = 127,
+ [1][1][RTW89_CHILE][1][111] = 127,
+ [1][1][RTW89_QATAR][1][111] = 127,
+ [1][1][RTW89_QATAR][0][111] = 127,
+ [1][1][RTW89_UK][1][111] = 127,
+ [1][1][RTW89_UK][0][111] = 127,
+ [1][1][RTW89_FCC][1][113] = 127,
+ [1][1][RTW89_FCC][2][113] = 127,
+ [1][1][RTW89_ETSI][1][113] = 127,
+ [1][1][RTW89_ETSI][0][113] = 127,
+ [1][1][RTW89_MKK][1][113] = 127,
+ [1][1][RTW89_MKK][0][113] = 127,
+ [1][1][RTW89_IC][1][113] = 127,
+ [1][1][RTW89_KCC][1][113] = 127,
+ [1][1][RTW89_KCC][0][113] = 127,
+ [1][1][RTW89_ACMA][1][113] = 127,
+ [1][1][RTW89_ACMA][0][113] = 127,
+ [1][1][RTW89_CHILE][1][113] = 127,
+ [1][1][RTW89_QATAR][1][113] = 127,
+ [1][1][RTW89_QATAR][0][113] = 127,
+ [1][1][RTW89_UK][1][113] = 127,
+ [1][1][RTW89_UK][0][113] = 127,
+ [1][1][RTW89_FCC][1][115] = 127,
+ [1][1][RTW89_FCC][2][115] = 127,
+ [1][1][RTW89_ETSI][1][115] = 127,
+ [1][1][RTW89_ETSI][0][115] = 127,
+ [1][1][RTW89_MKK][1][115] = 127,
+ [1][1][RTW89_MKK][0][115] = 127,
+ [1][1][RTW89_IC][1][115] = 127,
+ [1][1][RTW89_KCC][1][115] = 127,
+ [1][1][RTW89_KCC][0][115] = 127,
+ [1][1][RTW89_ACMA][1][115] = 127,
+ [1][1][RTW89_ACMA][0][115] = 127,
+ [1][1][RTW89_CHILE][1][115] = 127,
+ [1][1][RTW89_QATAR][1][115] = 127,
+ [1][1][RTW89_QATAR][0][115] = 127,
+ [1][1][RTW89_UK][1][115] = 127,
+ [1][1][RTW89_UK][0][115] = 127,
+ [1][1][RTW89_FCC][1][117] = 127,
+ [1][1][RTW89_FCC][2][117] = 127,
+ [1][1][RTW89_ETSI][1][117] = 127,
+ [1][1][RTW89_ETSI][0][117] = 127,
+ [1][1][RTW89_MKK][1][117] = 127,
+ [1][1][RTW89_MKK][0][117] = 127,
+ [1][1][RTW89_IC][1][117] = 127,
+ [1][1][RTW89_KCC][1][117] = 127,
+ [1][1][RTW89_KCC][0][117] = 127,
+ [1][1][RTW89_ACMA][1][117] = 127,
+ [1][1][RTW89_ACMA][0][117] = 127,
+ [1][1][RTW89_CHILE][1][117] = 127,
+ [1][1][RTW89_QATAR][1][117] = 127,
+ [1][1][RTW89_QATAR][0][117] = 127,
+ [1][1][RTW89_UK][1][117] = 127,
+ [1][1][RTW89_UK][0][117] = 127,
+ [1][1][RTW89_FCC][1][119] = 127,
+ [1][1][RTW89_FCC][2][119] = 127,
+ [1][1][RTW89_ETSI][1][119] = 127,
+ [1][1][RTW89_ETSI][0][119] = 127,
+ [1][1][RTW89_MKK][1][119] = 127,
+ [1][1][RTW89_MKK][0][119] = 127,
+ [1][1][RTW89_IC][1][119] = 127,
+ [1][1][RTW89_KCC][1][119] = 127,
+ [1][1][RTW89_KCC][0][119] = 127,
+ [1][1][RTW89_ACMA][1][119] = 127,
+ [1][1][RTW89_ACMA][0][119] = 127,
+ [1][1][RTW89_CHILE][1][119] = 127,
+ [1][1][RTW89_QATAR][1][119] = 127,
+ [1][1][RTW89_QATAR][0][119] = 127,
+ [1][1][RTW89_UK][1][119] = 127,
+ [1][1][RTW89_UK][0][119] = 127,
+ [2][0][RTW89_FCC][1][0] = 8,
+ [2][0][RTW89_FCC][2][0] = 60,
+ [2][0][RTW89_ETSI][1][0] = 56,
+ [2][0][RTW89_ETSI][0][0] = 18,
+ [2][0][RTW89_MKK][1][0] = 54,
+ [2][0][RTW89_MKK][0][0] = 14,
+ [2][0][RTW89_IC][1][0] = 8,
+ [2][0][RTW89_KCC][1][0] = -2,
+ [2][0][RTW89_KCC][0][0] = -2,
+ [2][0][RTW89_ACMA][1][0] = 56,
+ [2][0][RTW89_ACMA][0][0] = 18,
+ [2][0][RTW89_CHILE][1][0] = 8,
+ [2][0][RTW89_QATAR][1][0] = 56,
+ [2][0][RTW89_QATAR][0][0] = 18,
+ [2][0][RTW89_UK][1][0] = 56,
+ [2][0][RTW89_UK][0][0] = 18,
+ [2][0][RTW89_FCC][1][2] = 8,
+ [2][0][RTW89_FCC][2][2] = 60,
+ [2][0][RTW89_ETSI][1][2] = 56,
+ [2][0][RTW89_ETSI][0][2] = 18,
+ [2][0][RTW89_MKK][1][2] = 54,
+ [2][0][RTW89_MKK][0][2] = 14,
+ [2][0][RTW89_IC][1][2] = 8,
+ [2][0][RTW89_KCC][1][2] = -2,
+ [2][0][RTW89_KCC][0][2] = -2,
+ [2][0][RTW89_ACMA][1][2] = 56,
+ [2][0][RTW89_ACMA][0][2] = 18,
+ [2][0][RTW89_CHILE][1][2] = 8,
+ [2][0][RTW89_QATAR][1][2] = 56,
+ [2][0][RTW89_QATAR][0][2] = 18,
+ [2][0][RTW89_UK][1][2] = 56,
+ [2][0][RTW89_UK][0][2] = 18,
+ [2][0][RTW89_FCC][1][4] = 8,
+ [2][0][RTW89_FCC][2][4] = 60,
+ [2][0][RTW89_ETSI][1][4] = 56,
+ [2][0][RTW89_ETSI][0][4] = 18,
+ [2][0][RTW89_MKK][1][4] = 54,
+ [2][0][RTW89_MKK][0][4] = 14,
+ [2][0][RTW89_IC][1][4] = 8,
+ [2][0][RTW89_KCC][1][4] = -2,
+ [2][0][RTW89_KCC][0][4] = -2,
+ [2][0][RTW89_ACMA][1][4] = 56,
+ [2][0][RTW89_ACMA][0][4] = 18,
+ [2][0][RTW89_CHILE][1][4] = 8,
+ [2][0][RTW89_QATAR][1][4] = 56,
+ [2][0][RTW89_QATAR][0][4] = 18,
+ [2][0][RTW89_UK][1][4] = 56,
+ [2][0][RTW89_UK][0][4] = 18,
+ [2][0][RTW89_FCC][1][6] = 8,
+ [2][0][RTW89_FCC][2][6] = 60,
+ [2][0][RTW89_ETSI][1][6] = 56,
+ [2][0][RTW89_ETSI][0][6] = 18,
+ [2][0][RTW89_MKK][1][6] = 54,
+ [2][0][RTW89_MKK][0][6] = 14,
+ [2][0][RTW89_IC][1][6] = 8,
+ [2][0][RTW89_KCC][1][6] = -2,
+ [2][0][RTW89_KCC][0][6] = -2,
+ [2][0][RTW89_ACMA][1][6] = 56,
+ [2][0][RTW89_ACMA][0][6] = 18,
+ [2][0][RTW89_CHILE][1][6] = 8,
+ [2][0][RTW89_QATAR][1][6] = 56,
+ [2][0][RTW89_QATAR][0][6] = 18,
+ [2][0][RTW89_UK][1][6] = 56,
+ [2][0][RTW89_UK][0][6] = 18,
+ [2][0][RTW89_FCC][1][8] = 8,
+ [2][0][RTW89_FCC][2][8] = 60,
+ [2][0][RTW89_ETSI][1][8] = 56,
+ [2][0][RTW89_ETSI][0][8] = 18,
+ [2][0][RTW89_MKK][1][8] = 54,
+ [2][0][RTW89_MKK][0][8] = 14,
+ [2][0][RTW89_IC][1][8] = 8,
+ [2][0][RTW89_KCC][1][8] = -2,
+ [2][0][RTW89_KCC][0][8] = -2,
+ [2][0][RTW89_ACMA][1][8] = 56,
+ [2][0][RTW89_ACMA][0][8] = 18,
+ [2][0][RTW89_CHILE][1][8] = 8,
+ [2][0][RTW89_QATAR][1][8] = 56,
+ [2][0][RTW89_QATAR][0][8] = 18,
+ [2][0][RTW89_UK][1][8] = 56,
+ [2][0][RTW89_UK][0][8] = 18,
+ [2][0][RTW89_FCC][1][10] = 8,
+ [2][0][RTW89_FCC][2][10] = 60,
+ [2][0][RTW89_ETSI][1][10] = 56,
+ [2][0][RTW89_ETSI][0][10] = 18,
+ [2][0][RTW89_MKK][1][10] = 54,
+ [2][0][RTW89_MKK][0][10] = 14,
+ [2][0][RTW89_IC][1][10] = 8,
+ [2][0][RTW89_KCC][1][10] = -2,
+ [2][0][RTW89_KCC][0][10] = -2,
+ [2][0][RTW89_ACMA][1][10] = 56,
+ [2][0][RTW89_ACMA][0][10] = 18,
+ [2][0][RTW89_CHILE][1][10] = 8,
+ [2][0][RTW89_QATAR][1][10] = 56,
+ [2][0][RTW89_QATAR][0][10] = 18,
+ [2][0][RTW89_UK][1][10] = 56,
+ [2][0][RTW89_UK][0][10] = 18,
+ [2][0][RTW89_FCC][1][12] = 8,
+ [2][0][RTW89_FCC][2][12] = 60,
+ [2][0][RTW89_ETSI][1][12] = 56,
+ [2][0][RTW89_ETSI][0][12] = 18,
+ [2][0][RTW89_MKK][1][12] = 54,
+ [2][0][RTW89_MKK][0][12] = 14,
+ [2][0][RTW89_IC][1][12] = 8,
+ [2][0][RTW89_KCC][1][12] = -2,
+ [2][0][RTW89_KCC][0][12] = -2,
+ [2][0][RTW89_ACMA][1][12] = 56,
+ [2][0][RTW89_ACMA][0][12] = 18,
+ [2][0][RTW89_CHILE][1][12] = 8,
+ [2][0][RTW89_QATAR][1][12] = 56,
+ [2][0][RTW89_QATAR][0][12] = 18,
+ [2][0][RTW89_UK][1][12] = 56,
+ [2][0][RTW89_UK][0][12] = 18,
+ [2][0][RTW89_FCC][1][14] = 8,
+ [2][0][RTW89_FCC][2][14] = 60,
+ [2][0][RTW89_ETSI][1][14] = 56,
+ [2][0][RTW89_ETSI][0][14] = 18,
+ [2][0][RTW89_MKK][1][14] = 54,
+ [2][0][RTW89_MKK][0][14] = 14,
+ [2][0][RTW89_IC][1][14] = 8,
+ [2][0][RTW89_KCC][1][14] = -2,
+ [2][0][RTW89_KCC][0][14] = -2,
+ [2][0][RTW89_ACMA][1][14] = 56,
+ [2][0][RTW89_ACMA][0][14] = 18,
+ [2][0][RTW89_CHILE][1][14] = 8,
+ [2][0][RTW89_QATAR][1][14] = 56,
+ [2][0][RTW89_QATAR][0][14] = 18,
+ [2][0][RTW89_UK][1][14] = 56,
+ [2][0][RTW89_UK][0][14] = 18,
+ [2][0][RTW89_FCC][1][15] = 8,
+ [2][0][RTW89_FCC][2][15] = 60,
+ [2][0][RTW89_ETSI][1][15] = 56,
+ [2][0][RTW89_ETSI][0][15] = 18,
+ [2][0][RTW89_MKK][1][15] = 54,
+ [2][0][RTW89_MKK][0][15] = 14,
+ [2][0][RTW89_IC][1][15] = 8,
+ [2][0][RTW89_KCC][1][15] = -2,
+ [2][0][RTW89_KCC][0][15] = -2,
+ [2][0][RTW89_ACMA][1][15] = 56,
+ [2][0][RTW89_ACMA][0][15] = 18,
+ [2][0][RTW89_CHILE][1][15] = 8,
+ [2][0][RTW89_QATAR][1][15] = 56,
+ [2][0][RTW89_QATAR][0][15] = 18,
+ [2][0][RTW89_UK][1][15] = 56,
+ [2][0][RTW89_UK][0][15] = 18,
+ [2][0][RTW89_FCC][1][17] = 8,
+ [2][0][RTW89_FCC][2][17] = 60,
+ [2][0][RTW89_ETSI][1][17] = 56,
+ [2][0][RTW89_ETSI][0][17] = 18,
+ [2][0][RTW89_MKK][1][17] = 54,
+ [2][0][RTW89_MKK][0][17] = 14,
+ [2][0][RTW89_IC][1][17] = 8,
+ [2][0][RTW89_KCC][1][17] = -2,
+ [2][0][RTW89_KCC][0][17] = -2,
+ [2][0][RTW89_ACMA][1][17] = 56,
+ [2][0][RTW89_ACMA][0][17] = 18,
+ [2][0][RTW89_CHILE][1][17] = 8,
+ [2][0][RTW89_QATAR][1][17] = 56,
+ [2][0][RTW89_QATAR][0][17] = 18,
+ [2][0][RTW89_UK][1][17] = 56,
+ [2][0][RTW89_UK][0][17] = 18,
+ [2][0][RTW89_FCC][1][19] = 8,
+ [2][0][RTW89_FCC][2][19] = 60,
+ [2][0][RTW89_ETSI][1][19] = 56,
+ [2][0][RTW89_ETSI][0][19] = 18,
+ [2][0][RTW89_MKK][1][19] = 54,
+ [2][0][RTW89_MKK][0][19] = 14,
+ [2][0][RTW89_IC][1][19] = 8,
+ [2][0][RTW89_KCC][1][19] = -2,
+ [2][0][RTW89_KCC][0][19] = -2,
+ [2][0][RTW89_ACMA][1][19] = 56,
+ [2][0][RTW89_ACMA][0][19] = 18,
+ [2][0][RTW89_CHILE][1][19] = 8,
+ [2][0][RTW89_QATAR][1][19] = 56,
+ [2][0][RTW89_QATAR][0][19] = 18,
+ [2][0][RTW89_UK][1][19] = 56,
+ [2][0][RTW89_UK][0][19] = 18,
+ [2][0][RTW89_FCC][1][21] = 8,
+ [2][0][RTW89_FCC][2][21] = 60,
+ [2][0][RTW89_ETSI][1][21] = 56,
+ [2][0][RTW89_ETSI][0][21] = 18,
+ [2][0][RTW89_MKK][1][21] = 54,
+ [2][0][RTW89_MKK][0][21] = 14,
+ [2][0][RTW89_IC][1][21] = 8,
+ [2][0][RTW89_KCC][1][21] = -2,
+ [2][0][RTW89_KCC][0][21] = -2,
+ [2][0][RTW89_ACMA][1][21] = 56,
+ [2][0][RTW89_ACMA][0][21] = 18,
+ [2][0][RTW89_CHILE][1][21] = 8,
+ [2][0][RTW89_QATAR][1][21] = 56,
+ [2][0][RTW89_QATAR][0][21] = 18,
+ [2][0][RTW89_UK][1][21] = 56,
+ [2][0][RTW89_UK][0][21] = 18,
+ [2][0][RTW89_FCC][1][23] = 8,
+ [2][0][RTW89_FCC][2][23] = 78,
+ [2][0][RTW89_ETSI][1][23] = 56,
+ [2][0][RTW89_ETSI][0][23] = 18,
+ [2][0][RTW89_MKK][1][23] = 56,
+ [2][0][RTW89_MKK][0][23] = 14,
+ [2][0][RTW89_IC][1][23] = 8,
+ [2][0][RTW89_KCC][1][23] = -2,
+ [2][0][RTW89_KCC][0][23] = -2,
+ [2][0][RTW89_ACMA][1][23] = 56,
+ [2][0][RTW89_ACMA][0][23] = 18,
+ [2][0][RTW89_CHILE][1][23] = 8,
+ [2][0][RTW89_QATAR][1][23] = 56,
+ [2][0][RTW89_QATAR][0][23] = 18,
+ [2][0][RTW89_UK][1][23] = 56,
+ [2][0][RTW89_UK][0][23] = 18,
+ [2][0][RTW89_FCC][1][25] = 8,
+ [2][0][RTW89_FCC][2][25] = 78,
+ [2][0][RTW89_ETSI][1][25] = 56,
+ [2][0][RTW89_ETSI][0][25] = 18,
+ [2][0][RTW89_MKK][1][25] = 56,
+ [2][0][RTW89_MKK][0][25] = 14,
+ [2][0][RTW89_IC][1][25] = 8,
+ [2][0][RTW89_KCC][1][25] = -2,
+ [2][0][RTW89_KCC][0][25] = -2,
+ [2][0][RTW89_ACMA][1][25] = 56,
+ [2][0][RTW89_ACMA][0][25] = 18,
+ [2][0][RTW89_CHILE][1][25] = 8,
+ [2][0][RTW89_QATAR][1][25] = 56,
+ [2][0][RTW89_QATAR][0][25] = 18,
+ [2][0][RTW89_UK][1][25] = 56,
+ [2][0][RTW89_UK][0][25] = 18,
+ [2][0][RTW89_FCC][1][27] = 8,
+ [2][0][RTW89_FCC][2][27] = 78,
+ [2][0][RTW89_ETSI][1][27] = 56,
+ [2][0][RTW89_ETSI][0][27] = 18,
+ [2][0][RTW89_MKK][1][27] = 56,
+ [2][0][RTW89_MKK][0][27] = 14,
+ [2][0][RTW89_IC][1][27] = 8,
+ [2][0][RTW89_KCC][1][27] = -2,
+ [2][0][RTW89_KCC][0][27] = -2,
+ [2][0][RTW89_ACMA][1][27] = 56,
+ [2][0][RTW89_ACMA][0][27] = 18,
+ [2][0][RTW89_CHILE][1][27] = 8,
+ [2][0][RTW89_QATAR][1][27] = 56,
+ [2][0][RTW89_QATAR][0][27] = 18,
+ [2][0][RTW89_UK][1][27] = 56,
+ [2][0][RTW89_UK][0][27] = 18,
+ [2][0][RTW89_FCC][1][29] = 8,
+ [2][0][RTW89_FCC][2][29] = 78,
+ [2][0][RTW89_ETSI][1][29] = 56,
+ [2][0][RTW89_ETSI][0][29] = 18,
+ [2][0][RTW89_MKK][1][29] = 56,
+ [2][0][RTW89_MKK][0][29] = 14,
+ [2][0][RTW89_IC][1][29] = 8,
+ [2][0][RTW89_KCC][1][29] = -2,
+ [2][0][RTW89_KCC][0][29] = -2,
+ [2][0][RTW89_ACMA][1][29] = 56,
+ [2][0][RTW89_ACMA][0][29] = 18,
+ [2][0][RTW89_CHILE][1][29] = 8,
+ [2][0][RTW89_QATAR][1][29] = 56,
+ [2][0][RTW89_QATAR][0][29] = 18,
+ [2][0][RTW89_UK][1][29] = 56,
+ [2][0][RTW89_UK][0][29] = 18,
+ [2][0][RTW89_FCC][1][30] = 8,
+ [2][0][RTW89_FCC][2][30] = 78,
+ [2][0][RTW89_ETSI][1][30] = 56,
+ [2][0][RTW89_ETSI][0][30] = 18,
+ [2][0][RTW89_MKK][1][30] = 56,
+ [2][0][RTW89_MKK][0][30] = 14,
+ [2][0][RTW89_IC][1][30] = 8,
+ [2][0][RTW89_KCC][1][30] = -2,
+ [2][0][RTW89_KCC][0][30] = -2,
+ [2][0][RTW89_ACMA][1][30] = 56,
+ [2][0][RTW89_ACMA][0][30] = 18,
+ [2][0][RTW89_CHILE][1][30] = 8,
+ [2][0][RTW89_QATAR][1][30] = 56,
+ [2][0][RTW89_QATAR][0][30] = 18,
+ [2][0][RTW89_UK][1][30] = 56,
+ [2][0][RTW89_UK][0][30] = 18,
+ [2][0][RTW89_FCC][1][32] = 8,
+ [2][0][RTW89_FCC][2][32] = 78,
+ [2][0][RTW89_ETSI][1][32] = 56,
+ [2][0][RTW89_ETSI][0][32] = 18,
+ [2][0][RTW89_MKK][1][32] = 56,
+ [2][0][RTW89_MKK][0][32] = 14,
+ [2][0][RTW89_IC][1][32] = 8,
+ [2][0][RTW89_KCC][1][32] = -2,
+ [2][0][RTW89_KCC][0][32] = -2,
+ [2][0][RTW89_ACMA][1][32] = 56,
+ [2][0][RTW89_ACMA][0][32] = 18,
+ [2][0][RTW89_CHILE][1][32] = 8,
+ [2][0][RTW89_QATAR][1][32] = 56,
+ [2][0][RTW89_QATAR][0][32] = 18,
+ [2][0][RTW89_UK][1][32] = 56,
+ [2][0][RTW89_UK][0][32] = 18,
+ [2][0][RTW89_FCC][1][34] = 8,
+ [2][0][RTW89_FCC][2][34] = 78,
+ [2][0][RTW89_ETSI][1][34] = 56,
+ [2][0][RTW89_ETSI][0][34] = 18,
+ [2][0][RTW89_MKK][1][34] = 56,
+ [2][0][RTW89_MKK][0][34] = 14,
+ [2][0][RTW89_IC][1][34] = 8,
+ [2][0][RTW89_KCC][1][34] = -2,
+ [2][0][RTW89_KCC][0][34] = -2,
+ [2][0][RTW89_ACMA][1][34] = 56,
+ [2][0][RTW89_ACMA][0][34] = 18,
+ [2][0][RTW89_CHILE][1][34] = 8,
+ [2][0][RTW89_QATAR][1][34] = 56,
+ [2][0][RTW89_QATAR][0][34] = 18,
+ [2][0][RTW89_UK][1][34] = 56,
+ [2][0][RTW89_UK][0][34] = 18,
+ [2][0][RTW89_FCC][1][36] = 8,
+ [2][0][RTW89_FCC][2][36] = 78,
+ [2][0][RTW89_ETSI][1][36] = 56,
+ [2][0][RTW89_ETSI][0][36] = 18,
+ [2][0][RTW89_MKK][1][36] = 56,
+ [2][0][RTW89_MKK][0][36] = 14,
+ [2][0][RTW89_IC][1][36] = 8,
+ [2][0][RTW89_KCC][1][36] = -2,
+ [2][0][RTW89_KCC][0][36] = -2,
+ [2][0][RTW89_ACMA][1][36] = 56,
+ [2][0][RTW89_ACMA][0][36] = 18,
+ [2][0][RTW89_CHILE][1][36] = 8,
+ [2][0][RTW89_QATAR][1][36] = 56,
+ [2][0][RTW89_QATAR][0][36] = 18,
+ [2][0][RTW89_UK][1][36] = 56,
+ [2][0][RTW89_UK][0][36] = 18,
+ [2][0][RTW89_FCC][1][38] = 8,
+ [2][0][RTW89_FCC][2][38] = 78,
+ [2][0][RTW89_ETSI][1][38] = 56,
+ [2][0][RTW89_ETSI][0][38] = 18,
+ [2][0][RTW89_MKK][1][38] = 56,
+ [2][0][RTW89_MKK][0][38] = 14,
+ [2][0][RTW89_IC][1][38] = 8,
+ [2][0][RTW89_KCC][1][38] = -2,
+ [2][0][RTW89_KCC][0][38] = -2,
+ [2][0][RTW89_ACMA][1][38] = 56,
+ [2][0][RTW89_ACMA][0][38] = 18,
+ [2][0][RTW89_CHILE][1][38] = 8,
+ [2][0][RTW89_QATAR][1][38] = 56,
+ [2][0][RTW89_QATAR][0][38] = 18,
+ [2][0][RTW89_UK][1][38] = 56,
+ [2][0][RTW89_UK][0][38] = 18,
+ [2][0][RTW89_FCC][1][40] = 8,
+ [2][0][RTW89_FCC][2][40] = 78,
+ [2][0][RTW89_ETSI][1][40] = 56,
+ [2][0][RTW89_ETSI][0][40] = 18,
+ [2][0][RTW89_MKK][1][40] = 56,
+ [2][0][RTW89_MKK][0][40] = 14,
+ [2][0][RTW89_IC][1][40] = 8,
+ [2][0][RTW89_KCC][1][40] = -2,
+ [2][0][RTW89_KCC][0][40] = -2,
+ [2][0][RTW89_ACMA][1][40] = 56,
+ [2][0][RTW89_ACMA][0][40] = 18,
+ [2][0][RTW89_CHILE][1][40] = 8,
+ [2][0][RTW89_QATAR][1][40] = 56,
+ [2][0][RTW89_QATAR][0][40] = 18,
+ [2][0][RTW89_UK][1][40] = 56,
+ [2][0][RTW89_UK][0][40] = 18,
+ [2][0][RTW89_FCC][1][42] = 8,
+ [2][0][RTW89_FCC][2][42] = 78,
+ [2][0][RTW89_ETSI][1][42] = 56,
+ [2][0][RTW89_ETSI][0][42] = 18,
+ [2][0][RTW89_MKK][1][42] = 56,
+ [2][0][RTW89_MKK][0][42] = 14,
+ [2][0][RTW89_IC][1][42] = 8,
+ [2][0][RTW89_KCC][1][42] = -2,
+ [2][0][RTW89_KCC][0][42] = -2,
+ [2][0][RTW89_ACMA][1][42] = 56,
+ [2][0][RTW89_ACMA][0][42] = 18,
+ [2][0][RTW89_CHILE][1][42] = 8,
+ [2][0][RTW89_QATAR][1][42] = 56,
+ [2][0][RTW89_QATAR][0][42] = 18,
+ [2][0][RTW89_UK][1][42] = 56,
+ [2][0][RTW89_UK][0][42] = 18,
+ [2][0][RTW89_FCC][1][44] = 8,
+ [2][0][RTW89_FCC][2][44] = 78,
+ [2][0][RTW89_ETSI][1][44] = 56,
+ [2][0][RTW89_ETSI][0][44] = 18,
+ [2][0][RTW89_MKK][1][44] = 32,
+ [2][0][RTW89_MKK][0][44] = 14,
+ [2][0][RTW89_IC][1][44] = 8,
+ [2][0][RTW89_KCC][1][44] = -2,
+ [2][0][RTW89_KCC][0][44] = -2,
+ [2][0][RTW89_ACMA][1][44] = 56,
+ [2][0][RTW89_ACMA][0][44] = 18,
+ [2][0][RTW89_CHILE][1][44] = 8,
+ [2][0][RTW89_QATAR][1][44] = 56,
+ [2][0][RTW89_QATAR][0][44] = 18,
+ [2][0][RTW89_UK][1][44] = 56,
+ [2][0][RTW89_UK][0][44] = 18,
+ [2][0][RTW89_FCC][1][45] = 8,
+ [2][0][RTW89_FCC][2][45] = 127,
+ [2][0][RTW89_ETSI][1][45] = 127,
+ [2][0][RTW89_ETSI][0][45] = 127,
+ [2][0][RTW89_MKK][1][45] = 127,
+ [2][0][RTW89_MKK][0][45] = 127,
+ [2][0][RTW89_IC][1][45] = 8,
+ [2][0][RTW89_KCC][1][45] = -2,
+ [2][0][RTW89_KCC][0][45] = 127,
+ [2][0][RTW89_ACMA][1][45] = 127,
+ [2][0][RTW89_ACMA][0][45] = 127,
+ [2][0][RTW89_CHILE][1][45] = 127,
+ [2][0][RTW89_QATAR][1][45] = 127,
+ [2][0][RTW89_QATAR][0][45] = 127,
+ [2][0][RTW89_UK][1][45] = 127,
+ [2][0][RTW89_UK][0][45] = 127,
+ [2][0][RTW89_FCC][1][47] = 8,
+ [2][0][RTW89_FCC][2][47] = 127,
+ [2][0][RTW89_ETSI][1][47] = 127,
+ [2][0][RTW89_ETSI][0][47] = 127,
+ [2][0][RTW89_MKK][1][47] = 127,
+ [2][0][RTW89_MKK][0][47] = 127,
+ [2][0][RTW89_IC][1][47] = 8,
+ [2][0][RTW89_KCC][1][47] = -2,
+ [2][0][RTW89_KCC][0][47] = 127,
+ [2][0][RTW89_ACMA][1][47] = 127,
+ [2][0][RTW89_ACMA][0][47] = 127,
+ [2][0][RTW89_CHILE][1][47] = 127,
+ [2][0][RTW89_QATAR][1][47] = 127,
+ [2][0][RTW89_QATAR][0][47] = 127,
+ [2][0][RTW89_UK][1][47] = 127,
+ [2][0][RTW89_UK][0][47] = 127,
+ [2][0][RTW89_FCC][1][49] = 8,
+ [2][0][RTW89_FCC][2][49] = 127,
+ [2][0][RTW89_ETSI][1][49] = 127,
+ [2][0][RTW89_ETSI][0][49] = 127,
+ [2][0][RTW89_MKK][1][49] = 127,
+ [2][0][RTW89_MKK][0][49] = 127,
+ [2][0][RTW89_IC][1][49] = 8,
+ [2][0][RTW89_KCC][1][49] = -2,
+ [2][0][RTW89_KCC][0][49] = 127,
+ [2][0][RTW89_ACMA][1][49] = 127,
+ [2][0][RTW89_ACMA][0][49] = 127,
+ [2][0][RTW89_CHILE][1][49] = 127,
+ [2][0][RTW89_QATAR][1][49] = 127,
+ [2][0][RTW89_QATAR][0][49] = 127,
+ [2][0][RTW89_UK][1][49] = 127,
+ [2][0][RTW89_UK][0][49] = 127,
+ [2][0][RTW89_FCC][1][51] = 8,
+ [2][0][RTW89_FCC][2][51] = 127,
+ [2][0][RTW89_ETSI][1][51] = 127,
+ [2][0][RTW89_ETSI][0][51] = 127,
+ [2][0][RTW89_MKK][1][51] = 127,
+ [2][0][RTW89_MKK][0][51] = 127,
+ [2][0][RTW89_IC][1][51] = 8,
+ [2][0][RTW89_KCC][1][51] = -2,
+ [2][0][RTW89_KCC][0][51] = 127,
+ [2][0][RTW89_ACMA][1][51] = 127,
+ [2][0][RTW89_ACMA][0][51] = 127,
+ [2][0][RTW89_CHILE][1][51] = 127,
+ [2][0][RTW89_QATAR][1][51] = 127,
+ [2][0][RTW89_QATAR][0][51] = 127,
+ [2][0][RTW89_UK][1][51] = 127,
+ [2][0][RTW89_UK][0][51] = 127,
+ [2][0][RTW89_FCC][1][53] = 8,
+ [2][0][RTW89_FCC][2][53] = 127,
+ [2][0][RTW89_ETSI][1][53] = 127,
+ [2][0][RTW89_ETSI][0][53] = 127,
+ [2][0][RTW89_MKK][1][53] = 127,
+ [2][0][RTW89_MKK][0][53] = 127,
+ [2][0][RTW89_IC][1][53] = 8,
+ [2][0][RTW89_KCC][1][53] = -2,
+ [2][0][RTW89_KCC][0][53] = 127,
+ [2][0][RTW89_ACMA][1][53] = 127,
+ [2][0][RTW89_ACMA][0][53] = 127,
+ [2][0][RTW89_CHILE][1][53] = 127,
+ [2][0][RTW89_QATAR][1][53] = 127,
+ [2][0][RTW89_QATAR][0][53] = 127,
+ [2][0][RTW89_UK][1][53] = 127,
+ [2][0][RTW89_UK][0][53] = 127,
+ [2][0][RTW89_FCC][1][55] = 8,
+ [2][0][RTW89_FCC][2][55] = 78,
+ [2][0][RTW89_ETSI][1][55] = 127,
+ [2][0][RTW89_ETSI][0][55] = 127,
+ [2][0][RTW89_MKK][1][55] = 127,
+ [2][0][RTW89_MKK][0][55] = 127,
+ [2][0][RTW89_IC][1][55] = 8,
+ [2][0][RTW89_KCC][1][55] = -2,
+ [2][0][RTW89_KCC][0][55] = 127,
+ [2][0][RTW89_ACMA][1][55] = 127,
+ [2][0][RTW89_ACMA][0][55] = 127,
+ [2][0][RTW89_CHILE][1][55] = 127,
+ [2][0][RTW89_QATAR][1][55] = 127,
+ [2][0][RTW89_QATAR][0][55] = 127,
+ [2][0][RTW89_UK][1][55] = 127,
+ [2][0][RTW89_UK][0][55] = 127,
+ [2][0][RTW89_FCC][1][57] = 8,
+ [2][0][RTW89_FCC][2][57] = 78,
+ [2][0][RTW89_ETSI][1][57] = 127,
+ [2][0][RTW89_ETSI][0][57] = 127,
+ [2][0][RTW89_MKK][1][57] = 127,
+ [2][0][RTW89_MKK][0][57] = 127,
+ [2][0][RTW89_IC][1][57] = 8,
+ [2][0][RTW89_KCC][1][57] = -2,
+ [2][0][RTW89_KCC][0][57] = 127,
+ [2][0][RTW89_ACMA][1][57] = 127,
+ [2][0][RTW89_ACMA][0][57] = 127,
+ [2][0][RTW89_CHILE][1][57] = 127,
+ [2][0][RTW89_QATAR][1][57] = 127,
+ [2][0][RTW89_QATAR][0][57] = 127,
+ [2][0][RTW89_UK][1][57] = 127,
+ [2][0][RTW89_UK][0][57] = 127,
+ [2][0][RTW89_FCC][1][59] = 8,
+ [2][0][RTW89_FCC][2][59] = 78,
+ [2][0][RTW89_ETSI][1][59] = 127,
+ [2][0][RTW89_ETSI][0][59] = 127,
+ [2][0][RTW89_MKK][1][59] = 127,
+ [2][0][RTW89_MKK][0][59] = 127,
+ [2][0][RTW89_IC][1][59] = 8,
+ [2][0][RTW89_KCC][1][59] = -2,
+ [2][0][RTW89_KCC][0][59] = 127,
+ [2][0][RTW89_ACMA][1][59] = 127,
+ [2][0][RTW89_ACMA][0][59] = 127,
+ [2][0][RTW89_CHILE][1][59] = 127,
+ [2][0][RTW89_QATAR][1][59] = 127,
+ [2][0][RTW89_QATAR][0][59] = 127,
+ [2][0][RTW89_UK][1][59] = 127,
+ [2][0][RTW89_UK][0][59] = 127,
+ [2][0][RTW89_FCC][1][60] = 8,
+ [2][0][RTW89_FCC][2][60] = 78,
+ [2][0][RTW89_ETSI][1][60] = 127,
+ [2][0][RTW89_ETSI][0][60] = 127,
+ [2][0][RTW89_MKK][1][60] = 127,
+ [2][0][RTW89_MKK][0][60] = 127,
+ [2][0][RTW89_IC][1][60] = 8,
+ [2][0][RTW89_KCC][1][60] = -2,
+ [2][0][RTW89_KCC][0][60] = 127,
+ [2][0][RTW89_ACMA][1][60] = 127,
+ [2][0][RTW89_ACMA][0][60] = 127,
+ [2][0][RTW89_CHILE][1][60] = 127,
+ [2][0][RTW89_QATAR][1][60] = 127,
+ [2][0][RTW89_QATAR][0][60] = 127,
+ [2][0][RTW89_UK][1][60] = 127,
+ [2][0][RTW89_UK][0][60] = 127,
+ [2][0][RTW89_FCC][1][62] = 8,
+ [2][0][RTW89_FCC][2][62] = 78,
+ [2][0][RTW89_ETSI][1][62] = 127,
+ [2][0][RTW89_ETSI][0][62] = 127,
+ [2][0][RTW89_MKK][1][62] = 127,
+ [2][0][RTW89_MKK][0][62] = 127,
+ [2][0][RTW89_IC][1][62] = 8,
+ [2][0][RTW89_KCC][1][62] = -2,
+ [2][0][RTW89_KCC][0][62] = 127,
+ [2][0][RTW89_ACMA][1][62] = 127,
+ [2][0][RTW89_ACMA][0][62] = 127,
+ [2][0][RTW89_CHILE][1][62] = 127,
+ [2][0][RTW89_QATAR][1][62] = 127,
+ [2][0][RTW89_QATAR][0][62] = 127,
+ [2][0][RTW89_UK][1][62] = 127,
+ [2][0][RTW89_UK][0][62] = 127,
+ [2][0][RTW89_FCC][1][64] = 8,
+ [2][0][RTW89_FCC][2][64] = 78,
+ [2][0][RTW89_ETSI][1][64] = 127,
+ [2][0][RTW89_ETSI][0][64] = 127,
+ [2][0][RTW89_MKK][1][64] = 127,
+ [2][0][RTW89_MKK][0][64] = 127,
+ [2][0][RTW89_IC][1][64] = 8,
+ [2][0][RTW89_KCC][1][64] = -2,
+ [2][0][RTW89_KCC][0][64] = 127,
+ [2][0][RTW89_ACMA][1][64] = 127,
+ [2][0][RTW89_ACMA][0][64] = 127,
+ [2][0][RTW89_CHILE][1][64] = 127,
+ [2][0][RTW89_QATAR][1][64] = 127,
+ [2][0][RTW89_QATAR][0][64] = 127,
+ [2][0][RTW89_UK][1][64] = 127,
+ [2][0][RTW89_UK][0][64] = 127,
+ [2][0][RTW89_FCC][1][66] = 8,
+ [2][0][RTW89_FCC][2][66] = 78,
+ [2][0][RTW89_ETSI][1][66] = 127,
+ [2][0][RTW89_ETSI][0][66] = 127,
+ [2][0][RTW89_MKK][1][66] = 127,
+ [2][0][RTW89_MKK][0][66] = 127,
+ [2][0][RTW89_IC][1][66] = 8,
+ [2][0][RTW89_KCC][1][66] = -2,
+ [2][0][RTW89_KCC][0][66] = 127,
+ [2][0][RTW89_ACMA][1][66] = 127,
+ [2][0][RTW89_ACMA][0][66] = 127,
+ [2][0][RTW89_CHILE][1][66] = 127,
+ [2][0][RTW89_QATAR][1][66] = 127,
+ [2][0][RTW89_QATAR][0][66] = 127,
+ [2][0][RTW89_UK][1][66] = 127,
+ [2][0][RTW89_UK][0][66] = 127,
+ [2][0][RTW89_FCC][1][68] = 8,
+ [2][0][RTW89_FCC][2][68] = 78,
+ [2][0][RTW89_ETSI][1][68] = 127,
+ [2][0][RTW89_ETSI][0][68] = 127,
+ [2][0][RTW89_MKK][1][68] = 127,
+ [2][0][RTW89_MKK][0][68] = 127,
+ [2][0][RTW89_IC][1][68] = 8,
+ [2][0][RTW89_KCC][1][68] = -2,
+ [2][0][RTW89_KCC][0][68] = 127,
+ [2][0][RTW89_ACMA][1][68] = 127,
+ [2][0][RTW89_ACMA][0][68] = 127,
+ [2][0][RTW89_CHILE][1][68] = 127,
+ [2][0][RTW89_QATAR][1][68] = 127,
+ [2][0][RTW89_QATAR][0][68] = 127,
+ [2][0][RTW89_UK][1][68] = 127,
+ [2][0][RTW89_UK][0][68] = 127,
+ [2][0][RTW89_FCC][1][70] = 8,
+ [2][0][RTW89_FCC][2][70] = 78,
+ [2][0][RTW89_ETSI][1][70] = 127,
+ [2][0][RTW89_ETSI][0][70] = 127,
+ [2][0][RTW89_MKK][1][70] = 127,
+ [2][0][RTW89_MKK][0][70] = 127,
+ [2][0][RTW89_IC][1][70] = 8,
+ [2][0][RTW89_KCC][1][70] = -2,
+ [2][0][RTW89_KCC][0][70] = 127,
+ [2][0][RTW89_ACMA][1][70] = 127,
+ [2][0][RTW89_ACMA][0][70] = 127,
+ [2][0][RTW89_CHILE][1][70] = 127,
+ [2][0][RTW89_QATAR][1][70] = 127,
+ [2][0][RTW89_QATAR][0][70] = 127,
+ [2][0][RTW89_UK][1][70] = 127,
+ [2][0][RTW89_UK][0][70] = 127,
+ [2][0][RTW89_FCC][1][72] = 8,
+ [2][0][RTW89_FCC][2][72] = 78,
+ [2][0][RTW89_ETSI][1][72] = 127,
+ [2][0][RTW89_ETSI][0][72] = 127,
+ [2][0][RTW89_MKK][1][72] = 127,
+ [2][0][RTW89_MKK][0][72] = 127,
+ [2][0][RTW89_IC][1][72] = 8,
+ [2][0][RTW89_KCC][1][72] = -2,
+ [2][0][RTW89_KCC][0][72] = 127,
+ [2][0][RTW89_ACMA][1][72] = 127,
+ [2][0][RTW89_ACMA][0][72] = 127,
+ [2][0][RTW89_CHILE][1][72] = 127,
+ [2][0][RTW89_QATAR][1][72] = 127,
+ [2][0][RTW89_QATAR][0][72] = 127,
+ [2][0][RTW89_UK][1][72] = 127,
+ [2][0][RTW89_UK][0][72] = 127,
+ [2][0][RTW89_FCC][1][74] = 8,
+ [2][0][RTW89_FCC][2][74] = 78,
+ [2][0][RTW89_ETSI][1][74] = 127,
+ [2][0][RTW89_ETSI][0][74] = 127,
+ [2][0][RTW89_MKK][1][74] = 127,
+ [2][0][RTW89_MKK][0][74] = 127,
+ [2][0][RTW89_IC][1][74] = 8,
+ [2][0][RTW89_KCC][1][74] = -2,
+ [2][0][RTW89_KCC][0][74] = 127,
+ [2][0][RTW89_ACMA][1][74] = 127,
+ [2][0][RTW89_ACMA][0][74] = 127,
+ [2][0][RTW89_CHILE][1][74] = 127,
+ [2][0][RTW89_QATAR][1][74] = 127,
+ [2][0][RTW89_QATAR][0][74] = 127,
+ [2][0][RTW89_UK][1][74] = 127,
+ [2][0][RTW89_UK][0][74] = 127,
+ [2][0][RTW89_FCC][1][75] = 8,
+ [2][0][RTW89_FCC][2][75] = 78,
+ [2][0][RTW89_ETSI][1][75] = 127,
+ [2][0][RTW89_ETSI][0][75] = 127,
+ [2][0][RTW89_MKK][1][75] = 127,
+ [2][0][RTW89_MKK][0][75] = 127,
+ [2][0][RTW89_IC][1][75] = 8,
+ [2][0][RTW89_KCC][1][75] = -2,
+ [2][0][RTW89_KCC][0][75] = 127,
+ [2][0][RTW89_ACMA][1][75] = 127,
+ [2][0][RTW89_ACMA][0][75] = 127,
+ [2][0][RTW89_CHILE][1][75] = 127,
+ [2][0][RTW89_QATAR][1][75] = 127,
+ [2][0][RTW89_QATAR][0][75] = 127,
+ [2][0][RTW89_UK][1][75] = 127,
+ [2][0][RTW89_UK][0][75] = 127,
+ [2][0][RTW89_FCC][1][77] = 8,
+ [2][0][RTW89_FCC][2][77] = 78,
+ [2][0][RTW89_ETSI][1][77] = 127,
+ [2][0][RTW89_ETSI][0][77] = 127,
+ [2][0][RTW89_MKK][1][77] = 127,
+ [2][0][RTW89_MKK][0][77] = 127,
+ [2][0][RTW89_IC][1][77] = 8,
+ [2][0][RTW89_KCC][1][77] = -2,
+ [2][0][RTW89_KCC][0][77] = 127,
+ [2][0][RTW89_ACMA][1][77] = 127,
+ [2][0][RTW89_ACMA][0][77] = 127,
+ [2][0][RTW89_CHILE][1][77] = 127,
+ [2][0][RTW89_QATAR][1][77] = 127,
+ [2][0][RTW89_QATAR][0][77] = 127,
+ [2][0][RTW89_UK][1][77] = 127,
+ [2][0][RTW89_UK][0][77] = 127,
+ [2][0][RTW89_FCC][1][79] = 8,
+ [2][0][RTW89_FCC][2][79] = 78,
+ [2][0][RTW89_ETSI][1][79] = 127,
+ [2][0][RTW89_ETSI][0][79] = 127,
+ [2][0][RTW89_MKK][1][79] = 127,
+ [2][0][RTW89_MKK][0][79] = 127,
+ [2][0][RTW89_IC][1][79] = 8,
+ [2][0][RTW89_KCC][1][79] = -2,
+ [2][0][RTW89_KCC][0][79] = 127,
+ [2][0][RTW89_ACMA][1][79] = 127,
+ [2][0][RTW89_ACMA][0][79] = 127,
+ [2][0][RTW89_CHILE][1][79] = 127,
+ [2][0][RTW89_QATAR][1][79] = 127,
+ [2][0][RTW89_QATAR][0][79] = 127,
+ [2][0][RTW89_UK][1][79] = 127,
+ [2][0][RTW89_UK][0][79] = 127,
+ [2][0][RTW89_FCC][1][81] = 8,
+ [2][0][RTW89_FCC][2][81] = 78,
+ [2][0][RTW89_ETSI][1][81] = 127,
+ [2][0][RTW89_ETSI][0][81] = 127,
+ [2][0][RTW89_MKK][1][81] = 127,
+ [2][0][RTW89_MKK][0][81] = 127,
+ [2][0][RTW89_IC][1][81] = 8,
+ [2][0][RTW89_KCC][1][81] = -2,
+ [2][0][RTW89_KCC][0][81] = 127,
+ [2][0][RTW89_ACMA][1][81] = 127,
+ [2][0][RTW89_ACMA][0][81] = 127,
+ [2][0][RTW89_CHILE][1][81] = 127,
+ [2][0][RTW89_QATAR][1][81] = 127,
+ [2][0][RTW89_QATAR][0][81] = 127,
+ [2][0][RTW89_UK][1][81] = 127,
+ [2][0][RTW89_UK][0][81] = 127,
+ [2][0][RTW89_FCC][1][83] = 8,
+ [2][0][RTW89_FCC][2][83] = 78,
+ [2][0][RTW89_ETSI][1][83] = 127,
+ [2][0][RTW89_ETSI][0][83] = 127,
+ [2][0][RTW89_MKK][1][83] = 127,
+ [2][0][RTW89_MKK][0][83] = 127,
+ [2][0][RTW89_IC][1][83] = 8,
+ [2][0][RTW89_KCC][1][83] = -2,
+ [2][0][RTW89_KCC][0][83] = 127,
+ [2][0][RTW89_ACMA][1][83] = 127,
+ [2][0][RTW89_ACMA][0][83] = 127,
+ [2][0][RTW89_CHILE][1][83] = 127,
+ [2][0][RTW89_QATAR][1][83] = 127,
+ [2][0][RTW89_QATAR][0][83] = 127,
+ [2][0][RTW89_UK][1][83] = 127,
+ [2][0][RTW89_UK][0][83] = 127,
+ [2][0][RTW89_FCC][1][85] = 8,
+ [2][0][RTW89_FCC][2][85] = 78,
+ [2][0][RTW89_ETSI][1][85] = 127,
+ [2][0][RTW89_ETSI][0][85] = 127,
+ [2][0][RTW89_MKK][1][85] = 127,
+ [2][0][RTW89_MKK][0][85] = 127,
+ [2][0][RTW89_IC][1][85] = 8,
+ [2][0][RTW89_KCC][1][85] = -2,
+ [2][0][RTW89_KCC][0][85] = 127,
+ [2][0][RTW89_ACMA][1][85] = 127,
+ [2][0][RTW89_ACMA][0][85] = 127,
+ [2][0][RTW89_CHILE][1][85] = 127,
+ [2][0][RTW89_QATAR][1][85] = 127,
+ [2][0][RTW89_QATAR][0][85] = 127,
+ [2][0][RTW89_UK][1][85] = 127,
+ [2][0][RTW89_UK][0][85] = 127,
+ [2][0][RTW89_FCC][1][87] = 8,
+ [2][0][RTW89_FCC][2][87] = 127,
+ [2][0][RTW89_ETSI][1][87] = 127,
+ [2][0][RTW89_ETSI][0][87] = 127,
+ [2][0][RTW89_MKK][1][87] = 127,
+ [2][0][RTW89_MKK][0][87] = 127,
+ [2][0][RTW89_IC][1][87] = 8,
+ [2][0][RTW89_KCC][1][87] = -2,
+ [2][0][RTW89_KCC][0][87] = 127,
+ [2][0][RTW89_ACMA][1][87] = 127,
+ [2][0][RTW89_ACMA][0][87] = 127,
+ [2][0][RTW89_CHILE][1][87] = 127,
+ [2][0][RTW89_QATAR][1][87] = 127,
+ [2][0][RTW89_QATAR][0][87] = 127,
+ [2][0][RTW89_UK][1][87] = 127,
+ [2][0][RTW89_UK][0][87] = 127,
+ [2][0][RTW89_FCC][1][89] = 8,
+ [2][0][RTW89_FCC][2][89] = 127,
+ [2][0][RTW89_ETSI][1][89] = 127,
+ [2][0][RTW89_ETSI][0][89] = 127,
+ [2][0][RTW89_MKK][1][89] = 127,
+ [2][0][RTW89_MKK][0][89] = 127,
+ [2][0][RTW89_IC][1][89] = 8,
+ [2][0][RTW89_KCC][1][89] = -2,
+ [2][0][RTW89_KCC][0][89] = 127,
+ [2][0][RTW89_ACMA][1][89] = 127,
+ [2][0][RTW89_ACMA][0][89] = 127,
+ [2][0][RTW89_CHILE][1][89] = 127,
+ [2][0][RTW89_QATAR][1][89] = 127,
+ [2][0][RTW89_QATAR][0][89] = 127,
+ [2][0][RTW89_UK][1][89] = 127,
+ [2][0][RTW89_UK][0][89] = 127,
+ [2][0][RTW89_FCC][1][90] = 8,
+ [2][0][RTW89_FCC][2][90] = 127,
+ [2][0][RTW89_ETSI][1][90] = 127,
+ [2][0][RTW89_ETSI][0][90] = 127,
+ [2][0][RTW89_MKK][1][90] = 127,
+ [2][0][RTW89_MKK][0][90] = 127,
+ [2][0][RTW89_IC][1][90] = 8,
+ [2][0][RTW89_KCC][1][90] = -2,
+ [2][0][RTW89_KCC][0][90] = 127,
+ [2][0][RTW89_ACMA][1][90] = 127,
+ [2][0][RTW89_ACMA][0][90] = 127,
+ [2][0][RTW89_CHILE][1][90] = 127,
+ [2][0][RTW89_QATAR][1][90] = 127,
+ [2][0][RTW89_QATAR][0][90] = 127,
+ [2][0][RTW89_UK][1][90] = 127,
+ [2][0][RTW89_UK][0][90] = 127,
+ [2][0][RTW89_FCC][1][92] = 8,
+ [2][0][RTW89_FCC][2][92] = 127,
+ [2][0][RTW89_ETSI][1][92] = 127,
+ [2][0][RTW89_ETSI][0][92] = 127,
+ [2][0][RTW89_MKK][1][92] = 127,
+ [2][0][RTW89_MKK][0][92] = 127,
+ [2][0][RTW89_IC][1][92] = 8,
+ [2][0][RTW89_KCC][1][92] = -2,
+ [2][0][RTW89_KCC][0][92] = 127,
+ [2][0][RTW89_ACMA][1][92] = 127,
+ [2][0][RTW89_ACMA][0][92] = 127,
+ [2][0][RTW89_CHILE][1][92] = 127,
+ [2][0][RTW89_QATAR][1][92] = 127,
+ [2][0][RTW89_QATAR][0][92] = 127,
+ [2][0][RTW89_UK][1][92] = 127,
+ [2][0][RTW89_UK][0][92] = 127,
+ [2][0][RTW89_FCC][1][94] = 8,
+ [2][0][RTW89_FCC][2][94] = 127,
+ [2][0][RTW89_ETSI][1][94] = 127,
+ [2][0][RTW89_ETSI][0][94] = 127,
+ [2][0][RTW89_MKK][1][94] = 127,
+ [2][0][RTW89_MKK][0][94] = 127,
+ [2][0][RTW89_IC][1][94] = 8,
+ [2][0][RTW89_KCC][1][94] = -2,
+ [2][0][RTW89_KCC][0][94] = 127,
+ [2][0][RTW89_ACMA][1][94] = 127,
+ [2][0][RTW89_ACMA][0][94] = 127,
+ [2][0][RTW89_CHILE][1][94] = 127,
+ [2][0][RTW89_QATAR][1][94] = 127,
+ [2][0][RTW89_QATAR][0][94] = 127,
+ [2][0][RTW89_UK][1][94] = 127,
+ [2][0][RTW89_UK][0][94] = 127,
+ [2][0][RTW89_FCC][1][96] = 8,
+ [2][0][RTW89_FCC][2][96] = 127,
+ [2][0][RTW89_ETSI][1][96] = 127,
+ [2][0][RTW89_ETSI][0][96] = 127,
+ [2][0][RTW89_MKK][1][96] = 127,
+ [2][0][RTW89_MKK][0][96] = 127,
+ [2][0][RTW89_IC][1][96] = 8,
+ [2][0][RTW89_KCC][1][96] = -2,
+ [2][0][RTW89_KCC][0][96] = 127,
+ [2][0][RTW89_ACMA][1][96] = 127,
+ [2][0][RTW89_ACMA][0][96] = 127,
+ [2][0][RTW89_CHILE][1][96] = 127,
+ [2][0][RTW89_QATAR][1][96] = 127,
+ [2][0][RTW89_QATAR][0][96] = 127,
+ [2][0][RTW89_UK][1][96] = 127,
+ [2][0][RTW89_UK][0][96] = 127,
+ [2][0][RTW89_FCC][1][98] = 8,
+ [2][0][RTW89_FCC][2][98] = 127,
+ [2][0][RTW89_ETSI][1][98] = 127,
+ [2][0][RTW89_ETSI][0][98] = 127,
+ [2][0][RTW89_MKK][1][98] = 127,
+ [2][0][RTW89_MKK][0][98] = 127,
+ [2][0][RTW89_IC][1][98] = 8,
+ [2][0][RTW89_KCC][1][98] = -2,
+ [2][0][RTW89_KCC][0][98] = 127,
+ [2][0][RTW89_ACMA][1][98] = 127,
+ [2][0][RTW89_ACMA][0][98] = 127,
+ [2][0][RTW89_CHILE][1][98] = 127,
+ [2][0][RTW89_QATAR][1][98] = 127,
+ [2][0][RTW89_QATAR][0][98] = 127,
+ [2][0][RTW89_UK][1][98] = 127,
+ [2][0][RTW89_UK][0][98] = 127,
+ [2][0][RTW89_FCC][1][100] = 8,
+ [2][0][RTW89_FCC][2][100] = 127,
+ [2][0][RTW89_ETSI][1][100] = 127,
+ [2][0][RTW89_ETSI][0][100] = 127,
+ [2][0][RTW89_MKK][1][100] = 127,
+ [2][0][RTW89_MKK][0][100] = 127,
+ [2][0][RTW89_IC][1][100] = 8,
+ [2][0][RTW89_KCC][1][100] = -2,
+ [2][0][RTW89_KCC][0][100] = 127,
+ [2][0][RTW89_ACMA][1][100] = 127,
+ [2][0][RTW89_ACMA][0][100] = 127,
+ [2][0][RTW89_CHILE][1][100] = 127,
+ [2][0][RTW89_QATAR][1][100] = 127,
+ [2][0][RTW89_QATAR][0][100] = 127,
+ [2][0][RTW89_UK][1][100] = 127,
+ [2][0][RTW89_UK][0][100] = 127,
+ [2][0][RTW89_FCC][1][102] = 8,
+ [2][0][RTW89_FCC][2][102] = 127,
+ [2][0][RTW89_ETSI][1][102] = 127,
+ [2][0][RTW89_ETSI][0][102] = 127,
+ [2][0][RTW89_MKK][1][102] = 127,
+ [2][0][RTW89_MKK][0][102] = 127,
+ [2][0][RTW89_IC][1][102] = 8,
+ [2][0][RTW89_KCC][1][102] = -2,
+ [2][0][RTW89_KCC][0][102] = 127,
+ [2][0][RTW89_ACMA][1][102] = 127,
+ [2][0][RTW89_ACMA][0][102] = 127,
+ [2][0][RTW89_CHILE][1][102] = 127,
+ [2][0][RTW89_QATAR][1][102] = 127,
+ [2][0][RTW89_QATAR][0][102] = 127,
+ [2][0][RTW89_UK][1][102] = 127,
+ [2][0][RTW89_UK][0][102] = 127,
+ [2][0][RTW89_FCC][1][104] = 8,
+ [2][0][RTW89_FCC][2][104] = 127,
+ [2][0][RTW89_ETSI][1][104] = 127,
+ [2][0][RTW89_ETSI][0][104] = 127,
+ [2][0][RTW89_MKK][1][104] = 127,
+ [2][0][RTW89_MKK][0][104] = 127,
+ [2][0][RTW89_IC][1][104] = 8,
+ [2][0][RTW89_KCC][1][104] = -2,
+ [2][0][RTW89_KCC][0][104] = 127,
+ [2][0][RTW89_ACMA][1][104] = 127,
+ [2][0][RTW89_ACMA][0][104] = 127,
+ [2][0][RTW89_CHILE][1][104] = 127,
+ [2][0][RTW89_QATAR][1][104] = 127,
+ [2][0][RTW89_QATAR][0][104] = 127,
+ [2][0][RTW89_UK][1][104] = 127,
+ [2][0][RTW89_UK][0][104] = 127,
+ [2][0][RTW89_FCC][1][105] = 8,
+ [2][0][RTW89_FCC][2][105] = 127,
+ [2][0][RTW89_ETSI][1][105] = 127,
+ [2][0][RTW89_ETSI][0][105] = 127,
+ [2][0][RTW89_MKK][1][105] = 127,
+ [2][0][RTW89_MKK][0][105] = 127,
+ [2][0][RTW89_IC][1][105] = 8,
+ [2][0][RTW89_KCC][1][105] = -2,
+ [2][0][RTW89_KCC][0][105] = 127,
+ [2][0][RTW89_ACMA][1][105] = 127,
+ [2][0][RTW89_ACMA][0][105] = 127,
+ [2][0][RTW89_CHILE][1][105] = 127,
+ [2][0][RTW89_QATAR][1][105] = 127,
+ [2][0][RTW89_QATAR][0][105] = 127,
+ [2][0][RTW89_UK][1][105] = 127,
+ [2][0][RTW89_UK][0][105] = 127,
+ [2][0][RTW89_FCC][1][107] = 10,
+ [2][0][RTW89_FCC][2][107] = 127,
+ [2][0][RTW89_ETSI][1][107] = 127,
+ [2][0][RTW89_ETSI][0][107] = 127,
+ [2][0][RTW89_MKK][1][107] = 127,
+ [2][0][RTW89_MKK][0][107] = 127,
+ [2][0][RTW89_IC][1][107] = 10,
+ [2][0][RTW89_KCC][1][107] = -2,
+ [2][0][RTW89_KCC][0][107] = 127,
+ [2][0][RTW89_ACMA][1][107] = 127,
+ [2][0][RTW89_ACMA][0][107] = 127,
+ [2][0][RTW89_CHILE][1][107] = 127,
+ [2][0][RTW89_QATAR][1][107] = 127,
+ [2][0][RTW89_QATAR][0][107] = 127,
+ [2][0][RTW89_UK][1][107] = 127,
+ [2][0][RTW89_UK][0][107] = 127,
+ [2][0][RTW89_FCC][1][109] = 12,
+ [2][0][RTW89_FCC][2][109] = 127,
+ [2][0][RTW89_ETSI][1][109] = 127,
+ [2][0][RTW89_ETSI][0][109] = 127,
+ [2][0][RTW89_MKK][1][109] = 127,
+ [2][0][RTW89_MKK][0][109] = 127,
+ [2][0][RTW89_IC][1][109] = 12,
+ [2][0][RTW89_KCC][1][109] = 127,
+ [2][0][RTW89_KCC][0][109] = 127,
+ [2][0][RTW89_ACMA][1][109] = 127,
+ [2][0][RTW89_ACMA][0][109] = 127,
+ [2][0][RTW89_CHILE][1][109] = 127,
+ [2][0][RTW89_QATAR][1][109] = 127,
+ [2][0][RTW89_QATAR][0][109] = 127,
+ [2][0][RTW89_UK][1][109] = 127,
+ [2][0][RTW89_UK][0][109] = 127,
+ [2][0][RTW89_FCC][1][111] = 127,
+ [2][0][RTW89_FCC][2][111] = 127,
+ [2][0][RTW89_ETSI][1][111] = 127,
+ [2][0][RTW89_ETSI][0][111] = 127,
+ [2][0][RTW89_MKK][1][111] = 127,
+ [2][0][RTW89_MKK][0][111] = 127,
+ [2][0][RTW89_IC][1][111] = 127,
+ [2][0][RTW89_KCC][1][111] = 127,
+ [2][0][RTW89_KCC][0][111] = 127,
+ [2][0][RTW89_ACMA][1][111] = 127,
+ [2][0][RTW89_ACMA][0][111] = 127,
+ [2][0][RTW89_CHILE][1][111] = 127,
+ [2][0][RTW89_QATAR][1][111] = 127,
+ [2][0][RTW89_QATAR][0][111] = 127,
+ [2][0][RTW89_UK][1][111] = 127,
+ [2][0][RTW89_UK][0][111] = 127,
+ [2][0][RTW89_FCC][1][113] = 127,
+ [2][0][RTW89_FCC][2][113] = 127,
+ [2][0][RTW89_ETSI][1][113] = 127,
+ [2][0][RTW89_ETSI][0][113] = 127,
+ [2][0][RTW89_MKK][1][113] = 127,
+ [2][0][RTW89_MKK][0][113] = 127,
+ [2][0][RTW89_IC][1][113] = 127,
+ [2][0][RTW89_KCC][1][113] = 127,
+ [2][0][RTW89_KCC][0][113] = 127,
+ [2][0][RTW89_ACMA][1][113] = 127,
+ [2][0][RTW89_ACMA][0][113] = 127,
+ [2][0][RTW89_CHILE][1][113] = 127,
+ [2][0][RTW89_QATAR][1][113] = 127,
+ [2][0][RTW89_QATAR][0][113] = 127,
+ [2][0][RTW89_UK][1][113] = 127,
+ [2][0][RTW89_UK][0][113] = 127,
+ [2][0][RTW89_FCC][1][115] = 127,
+ [2][0][RTW89_FCC][2][115] = 127,
+ [2][0][RTW89_ETSI][1][115] = 127,
+ [2][0][RTW89_ETSI][0][115] = 127,
+ [2][0][RTW89_MKK][1][115] = 127,
+ [2][0][RTW89_MKK][0][115] = 127,
+ [2][0][RTW89_IC][1][115] = 127,
+ [2][0][RTW89_KCC][1][115] = 127,
+ [2][0][RTW89_KCC][0][115] = 127,
+ [2][0][RTW89_ACMA][1][115] = 127,
+ [2][0][RTW89_ACMA][0][115] = 127,
+ [2][0][RTW89_CHILE][1][115] = 127,
+ [2][0][RTW89_QATAR][1][115] = 127,
+ [2][0][RTW89_QATAR][0][115] = 127,
+ [2][0][RTW89_UK][1][115] = 127,
+ [2][0][RTW89_UK][0][115] = 127,
+ [2][0][RTW89_FCC][1][117] = 127,
+ [2][0][RTW89_FCC][2][117] = 127,
+ [2][0][RTW89_ETSI][1][117] = 127,
+ [2][0][RTW89_ETSI][0][117] = 127,
+ [2][0][RTW89_MKK][1][117] = 127,
+ [2][0][RTW89_MKK][0][117] = 127,
+ [2][0][RTW89_IC][1][117] = 127,
+ [2][0][RTW89_KCC][1][117] = 127,
+ [2][0][RTW89_KCC][0][117] = 127,
+ [2][0][RTW89_ACMA][1][117] = 127,
+ [2][0][RTW89_ACMA][0][117] = 127,
+ [2][0][RTW89_CHILE][1][117] = 127,
+ [2][0][RTW89_QATAR][1][117] = 127,
+ [2][0][RTW89_QATAR][0][117] = 127,
+ [2][0][RTW89_UK][1][117] = 127,
+ [2][0][RTW89_UK][0][117] = 127,
+ [2][0][RTW89_FCC][1][119] = 127,
+ [2][0][RTW89_FCC][2][119] = 127,
+ [2][0][RTW89_ETSI][1][119] = 127,
+ [2][0][RTW89_ETSI][0][119] = 127,
+ [2][0][RTW89_MKK][1][119] = 127,
+ [2][0][RTW89_MKK][0][119] = 127,
+ [2][0][RTW89_IC][1][119] = 127,
+ [2][0][RTW89_KCC][1][119] = 127,
+ [2][0][RTW89_KCC][0][119] = 127,
+ [2][0][RTW89_ACMA][1][119] = 127,
+ [2][0][RTW89_ACMA][0][119] = 127,
+ [2][0][RTW89_CHILE][1][119] = 127,
+ [2][0][RTW89_QATAR][1][119] = 127,
+ [2][0][RTW89_QATAR][0][119] = 127,
+ [2][0][RTW89_UK][1][119] = 127,
+ [2][0][RTW89_UK][0][119] = 127,
+ [2][1][RTW89_FCC][1][0] = -16,
+ [2][1][RTW89_FCC][2][0] = 54,
+ [2][1][RTW89_ETSI][1][0] = 44,
+ [2][1][RTW89_ETSI][0][0] = 6,
+ [2][1][RTW89_MKK][1][0] = 42,
+ [2][1][RTW89_MKK][0][0] = 2,
+ [2][1][RTW89_IC][1][0] = -16,
+ [2][1][RTW89_KCC][1][0] = -14,
+ [2][1][RTW89_KCC][0][0] = -14,
+ [2][1][RTW89_ACMA][1][0] = 44,
+ [2][1][RTW89_ACMA][0][0] = 6,
+ [2][1][RTW89_CHILE][1][0] = -16,
+ [2][1][RTW89_QATAR][1][0] = 44,
+ [2][1][RTW89_QATAR][0][0] = 6,
+ [2][1][RTW89_UK][1][0] = 44,
+ [2][1][RTW89_UK][0][0] = 6,
+ [2][1][RTW89_FCC][1][2] = -16,
+ [2][1][RTW89_FCC][2][2] = 54,
+ [2][1][RTW89_ETSI][1][2] = 44,
+ [2][1][RTW89_ETSI][0][2] = 6,
+ [2][1][RTW89_MKK][1][2] = 40,
+ [2][1][RTW89_MKK][0][2] = 2,
+ [2][1][RTW89_IC][1][2] = -16,
+ [2][1][RTW89_KCC][1][2] = -14,
+ [2][1][RTW89_KCC][0][2] = -14,
+ [2][1][RTW89_ACMA][1][2] = 44,
+ [2][1][RTW89_ACMA][0][2] = 6,
+ [2][1][RTW89_CHILE][1][2] = -16,
+ [2][1][RTW89_QATAR][1][2] = 44,
+ [2][1][RTW89_QATAR][0][2] = 6,
+ [2][1][RTW89_UK][1][2] = 44,
+ [2][1][RTW89_UK][0][2] = 6,
+ [2][1][RTW89_FCC][1][4] = -16,
+ [2][1][RTW89_FCC][2][4] = 54,
+ [2][1][RTW89_ETSI][1][4] = 44,
+ [2][1][RTW89_ETSI][0][4] = 6,
+ [2][1][RTW89_MKK][1][4] = 40,
+ [2][1][RTW89_MKK][0][4] = 2,
+ [2][1][RTW89_IC][1][4] = -16,
+ [2][1][RTW89_KCC][1][4] = -14,
+ [2][1][RTW89_KCC][0][4] = -14,
+ [2][1][RTW89_ACMA][1][4] = 44,
+ [2][1][RTW89_ACMA][0][4] = 6,
+ [2][1][RTW89_CHILE][1][4] = -16,
+ [2][1][RTW89_QATAR][1][4] = 44,
+ [2][1][RTW89_QATAR][0][4] = 6,
+ [2][1][RTW89_UK][1][4] = 44,
+ [2][1][RTW89_UK][0][4] = 6,
+ [2][1][RTW89_FCC][1][6] = -16,
+ [2][1][RTW89_FCC][2][6] = 54,
+ [2][1][RTW89_ETSI][1][6] = 44,
+ [2][1][RTW89_ETSI][0][6] = 6,
+ [2][1][RTW89_MKK][1][6] = 40,
+ [2][1][RTW89_MKK][0][6] = 2,
+ [2][1][RTW89_IC][1][6] = -16,
+ [2][1][RTW89_KCC][1][6] = -14,
+ [2][1][RTW89_KCC][0][6] = -14,
+ [2][1][RTW89_ACMA][1][6] = 44,
+ [2][1][RTW89_ACMA][0][6] = 6,
+ [2][1][RTW89_CHILE][1][6] = -16,
+ [2][1][RTW89_QATAR][1][6] = 44,
+ [2][1][RTW89_QATAR][0][6] = 6,
+ [2][1][RTW89_UK][1][6] = 44,
+ [2][1][RTW89_UK][0][6] = 6,
+ [2][1][RTW89_FCC][1][8] = -16,
+ [2][1][RTW89_FCC][2][8] = 54,
+ [2][1][RTW89_ETSI][1][8] = 44,
+ [2][1][RTW89_ETSI][0][8] = 6,
+ [2][1][RTW89_MKK][1][8] = 40,
+ [2][1][RTW89_MKK][0][8] = 2,
+ [2][1][RTW89_IC][1][8] = -16,
+ [2][1][RTW89_KCC][1][8] = -14,
+ [2][1][RTW89_KCC][0][8] = -14,
+ [2][1][RTW89_ACMA][1][8] = 44,
+ [2][1][RTW89_ACMA][0][8] = 6,
+ [2][1][RTW89_CHILE][1][8] = -16,
+ [2][1][RTW89_QATAR][1][8] = 44,
+ [2][1][RTW89_QATAR][0][8] = 6,
+ [2][1][RTW89_UK][1][8] = 44,
+ [2][1][RTW89_UK][0][8] = 6,
+ [2][1][RTW89_FCC][1][10] = -16,
+ [2][1][RTW89_FCC][2][10] = 54,
+ [2][1][RTW89_ETSI][1][10] = 44,
+ [2][1][RTW89_ETSI][0][10] = 6,
+ [2][1][RTW89_MKK][1][10] = 40,
+ [2][1][RTW89_MKK][0][10] = 2,
+ [2][1][RTW89_IC][1][10] = -16,
+ [2][1][RTW89_KCC][1][10] = -14,
+ [2][1][RTW89_KCC][0][10] = -14,
+ [2][1][RTW89_ACMA][1][10] = 44,
+ [2][1][RTW89_ACMA][0][10] = 6,
+ [2][1][RTW89_CHILE][1][10] = -16,
+ [2][1][RTW89_QATAR][1][10] = 44,
+ [2][1][RTW89_QATAR][0][10] = 6,
+ [2][1][RTW89_UK][1][10] = 44,
+ [2][1][RTW89_UK][0][10] = 6,
+ [2][1][RTW89_FCC][1][12] = -16,
+ [2][1][RTW89_FCC][2][12] = 54,
+ [2][1][RTW89_ETSI][1][12] = 44,
+ [2][1][RTW89_ETSI][0][12] = 6,
+ [2][1][RTW89_MKK][1][12] = 40,
+ [2][1][RTW89_MKK][0][12] = 2,
+ [2][1][RTW89_IC][1][12] = -16,
+ [2][1][RTW89_KCC][1][12] = -14,
+ [2][1][RTW89_KCC][0][12] = -14,
+ [2][1][RTW89_ACMA][1][12] = 44,
+ [2][1][RTW89_ACMA][0][12] = 6,
+ [2][1][RTW89_CHILE][1][12] = -16,
+ [2][1][RTW89_QATAR][1][12] = 44,
+ [2][1][RTW89_QATAR][0][12] = 6,
+ [2][1][RTW89_UK][1][12] = 44,
+ [2][1][RTW89_UK][0][12] = 6,
+ [2][1][RTW89_FCC][1][14] = -16,
+ [2][1][RTW89_FCC][2][14] = 54,
+ [2][1][RTW89_ETSI][1][14] = 44,
+ [2][1][RTW89_ETSI][0][14] = 6,
+ [2][1][RTW89_MKK][1][14] = 40,
+ [2][1][RTW89_MKK][0][14] = 2,
+ [2][1][RTW89_IC][1][14] = -16,
+ [2][1][RTW89_KCC][1][14] = -14,
+ [2][1][RTW89_KCC][0][14] = -14,
+ [2][1][RTW89_ACMA][1][14] = 44,
+ [2][1][RTW89_ACMA][0][14] = 6,
+ [2][1][RTW89_CHILE][1][14] = -16,
+ [2][1][RTW89_QATAR][1][14] = 44,
+ [2][1][RTW89_QATAR][0][14] = 6,
+ [2][1][RTW89_UK][1][14] = 44,
+ [2][1][RTW89_UK][0][14] = 6,
+ [2][1][RTW89_FCC][1][15] = -16,
+ [2][1][RTW89_FCC][2][15] = 54,
+ [2][1][RTW89_ETSI][1][15] = 44,
+ [2][1][RTW89_ETSI][0][15] = 6,
+ [2][1][RTW89_MKK][1][15] = 40,
+ [2][1][RTW89_MKK][0][15] = 2,
+ [2][1][RTW89_IC][1][15] = -16,
+ [2][1][RTW89_KCC][1][15] = -14,
+ [2][1][RTW89_KCC][0][15] = -14,
+ [2][1][RTW89_ACMA][1][15] = 44,
+ [2][1][RTW89_ACMA][0][15] = 6,
+ [2][1][RTW89_CHILE][1][15] = -16,
+ [2][1][RTW89_QATAR][1][15] = 44,
+ [2][1][RTW89_QATAR][0][15] = 6,
+ [2][1][RTW89_UK][1][15] = 44,
+ [2][1][RTW89_UK][0][15] = 6,
+ [2][1][RTW89_FCC][1][17] = -16,
+ [2][1][RTW89_FCC][2][17] = 54,
+ [2][1][RTW89_ETSI][1][17] = 44,
+ [2][1][RTW89_ETSI][0][17] = 6,
+ [2][1][RTW89_MKK][1][17] = 40,
+ [2][1][RTW89_MKK][0][17] = 2,
+ [2][1][RTW89_IC][1][17] = -16,
+ [2][1][RTW89_KCC][1][17] = -14,
+ [2][1][RTW89_KCC][0][17] = -14,
+ [2][1][RTW89_ACMA][1][17] = 44,
+ [2][1][RTW89_ACMA][0][17] = 6,
+ [2][1][RTW89_CHILE][1][17] = -16,
+ [2][1][RTW89_QATAR][1][17] = 44,
+ [2][1][RTW89_QATAR][0][17] = 6,
+ [2][1][RTW89_UK][1][17] = 44,
+ [2][1][RTW89_UK][0][17] = 6,
+ [2][1][RTW89_FCC][1][19] = -16,
+ [2][1][RTW89_FCC][2][19] = 54,
+ [2][1][RTW89_ETSI][1][19] = 44,
+ [2][1][RTW89_ETSI][0][19] = 6,
+ [2][1][RTW89_MKK][1][19] = 40,
+ [2][1][RTW89_MKK][0][19] = 2,
+ [2][1][RTW89_IC][1][19] = -16,
+ [2][1][RTW89_KCC][1][19] = -14,
+ [2][1][RTW89_KCC][0][19] = -14,
+ [2][1][RTW89_ACMA][1][19] = 44,
+ [2][1][RTW89_ACMA][0][19] = 6,
+ [2][1][RTW89_CHILE][1][19] = -16,
+ [2][1][RTW89_QATAR][1][19] = 44,
+ [2][1][RTW89_QATAR][0][19] = 6,
+ [2][1][RTW89_UK][1][19] = 44,
+ [2][1][RTW89_UK][0][19] = 6,
+ [2][1][RTW89_FCC][1][21] = -16,
+ [2][1][RTW89_FCC][2][21] = 54,
+ [2][1][RTW89_ETSI][1][21] = 44,
+ [2][1][RTW89_ETSI][0][21] = 6,
+ [2][1][RTW89_MKK][1][21] = 40,
+ [2][1][RTW89_MKK][0][21] = 2,
+ [2][1][RTW89_IC][1][21] = -16,
+ [2][1][RTW89_KCC][1][21] = -14,
+ [2][1][RTW89_KCC][0][21] = -14,
+ [2][1][RTW89_ACMA][1][21] = 44,
+ [2][1][RTW89_ACMA][0][21] = 6,
+ [2][1][RTW89_CHILE][1][21] = -16,
+ [2][1][RTW89_QATAR][1][21] = 44,
+ [2][1][RTW89_QATAR][0][21] = 6,
+ [2][1][RTW89_UK][1][21] = 44,
+ [2][1][RTW89_UK][0][21] = 6,
+ [2][1][RTW89_FCC][1][23] = -16,
+ [2][1][RTW89_FCC][2][23] = 54,
+ [2][1][RTW89_ETSI][1][23] = 44,
+ [2][1][RTW89_ETSI][0][23] = 6,
+ [2][1][RTW89_MKK][1][23] = 40,
+ [2][1][RTW89_MKK][0][23] = 2,
+ [2][1][RTW89_IC][1][23] = -16,
+ [2][1][RTW89_KCC][1][23] = -14,
+ [2][1][RTW89_KCC][0][23] = -14,
+ [2][1][RTW89_ACMA][1][23] = 44,
+ [2][1][RTW89_ACMA][0][23] = 6,
+ [2][1][RTW89_CHILE][1][23] = -16,
+ [2][1][RTW89_QATAR][1][23] = 44,
+ [2][1][RTW89_QATAR][0][23] = 6,
+ [2][1][RTW89_UK][1][23] = 44,
+ [2][1][RTW89_UK][0][23] = 6,
+ [2][1][RTW89_FCC][1][25] = -16,
+ [2][1][RTW89_FCC][2][25] = 54,
+ [2][1][RTW89_ETSI][1][25] = 44,
+ [2][1][RTW89_ETSI][0][25] = 6,
+ [2][1][RTW89_MKK][1][25] = 40,
+ [2][1][RTW89_MKK][0][25] = 2,
+ [2][1][RTW89_IC][1][25] = -16,
+ [2][1][RTW89_KCC][1][25] = -14,
+ [2][1][RTW89_KCC][0][25] = -14,
+ [2][1][RTW89_ACMA][1][25] = 44,
+ [2][1][RTW89_ACMA][0][25] = 6,
+ [2][1][RTW89_CHILE][1][25] = -16,
+ [2][1][RTW89_QATAR][1][25] = 44,
+ [2][1][RTW89_QATAR][0][25] = 6,
+ [2][1][RTW89_UK][1][25] = 44,
+ [2][1][RTW89_UK][0][25] = 6,
+ [2][1][RTW89_FCC][1][27] = -16,
+ [2][1][RTW89_FCC][2][27] = 54,
+ [2][1][RTW89_ETSI][1][27] = 44,
+ [2][1][RTW89_ETSI][0][27] = 6,
+ [2][1][RTW89_MKK][1][27] = 40,
+ [2][1][RTW89_MKK][0][27] = 2,
+ [2][1][RTW89_IC][1][27] = -16,
+ [2][1][RTW89_KCC][1][27] = -14,
+ [2][1][RTW89_KCC][0][27] = -14,
+ [2][1][RTW89_ACMA][1][27] = 44,
+ [2][1][RTW89_ACMA][0][27] = 6,
+ [2][1][RTW89_CHILE][1][27] = -16,
+ [2][1][RTW89_QATAR][1][27] = 44,
+ [2][1][RTW89_QATAR][0][27] = 6,
+ [2][1][RTW89_UK][1][27] = 44,
+ [2][1][RTW89_UK][0][27] = 6,
+ [2][1][RTW89_FCC][1][29] = -16,
+ [2][1][RTW89_FCC][2][29] = 54,
+ [2][1][RTW89_ETSI][1][29] = 44,
+ [2][1][RTW89_ETSI][0][29] = 6,
+ [2][1][RTW89_MKK][1][29] = 40,
+ [2][1][RTW89_MKK][0][29] = 2,
+ [2][1][RTW89_IC][1][29] = -16,
+ [2][1][RTW89_KCC][1][29] = -14,
+ [2][1][RTW89_KCC][0][29] = -14,
+ [2][1][RTW89_ACMA][1][29] = 44,
+ [2][1][RTW89_ACMA][0][29] = 6,
+ [2][1][RTW89_CHILE][1][29] = -16,
+ [2][1][RTW89_QATAR][1][29] = 44,
+ [2][1][RTW89_QATAR][0][29] = 6,
+ [2][1][RTW89_UK][1][29] = 44,
+ [2][1][RTW89_UK][0][29] = 6,
+ [2][1][RTW89_FCC][1][30] = -16,
+ [2][1][RTW89_FCC][2][30] = 54,
+ [2][1][RTW89_ETSI][1][30] = 44,
+ [2][1][RTW89_ETSI][0][30] = 6,
+ [2][1][RTW89_MKK][1][30] = 40,
+ [2][1][RTW89_MKK][0][30] = 2,
+ [2][1][RTW89_IC][1][30] = -16,
+ [2][1][RTW89_KCC][1][30] = -14,
+ [2][1][RTW89_KCC][0][30] = -14,
+ [2][1][RTW89_ACMA][1][30] = 44,
+ [2][1][RTW89_ACMA][0][30] = 6,
+ [2][1][RTW89_CHILE][1][30] = -16,
+ [2][1][RTW89_QATAR][1][30] = 44,
+ [2][1][RTW89_QATAR][0][30] = 6,
+ [2][1][RTW89_UK][1][30] = 44,
+ [2][1][RTW89_UK][0][30] = 6,
+ [2][1][RTW89_FCC][1][32] = -16,
+ [2][1][RTW89_FCC][2][32] = 54,
+ [2][1][RTW89_ETSI][1][32] = 44,
+ [2][1][RTW89_ETSI][0][32] = 6,
+ [2][1][RTW89_MKK][1][32] = 40,
+ [2][1][RTW89_MKK][0][32] = 2,
+ [2][1][RTW89_IC][1][32] = -16,
+ [2][1][RTW89_KCC][1][32] = -14,
+ [2][1][RTW89_KCC][0][32] = -14,
+ [2][1][RTW89_ACMA][1][32] = 44,
+ [2][1][RTW89_ACMA][0][32] = 6,
+ [2][1][RTW89_CHILE][1][32] = -16,
+ [2][1][RTW89_QATAR][1][32] = 44,
+ [2][1][RTW89_QATAR][0][32] = 6,
+ [2][1][RTW89_UK][1][32] = 44,
+ [2][1][RTW89_UK][0][32] = 6,
+ [2][1][RTW89_FCC][1][34] = -16,
+ [2][1][RTW89_FCC][2][34] = 54,
+ [2][1][RTW89_ETSI][1][34] = 44,
+ [2][1][RTW89_ETSI][0][34] = 6,
+ [2][1][RTW89_MKK][1][34] = 40,
+ [2][1][RTW89_MKK][0][34] = 2,
+ [2][1][RTW89_IC][1][34] = -16,
+ [2][1][RTW89_KCC][1][34] = -14,
+ [2][1][RTW89_KCC][0][34] = -14,
+ [2][1][RTW89_ACMA][1][34] = 44,
+ [2][1][RTW89_ACMA][0][34] = 6,
+ [2][1][RTW89_CHILE][1][34] = -16,
+ [2][1][RTW89_QATAR][1][34] = 44,
+ [2][1][RTW89_QATAR][0][34] = 6,
+ [2][1][RTW89_UK][1][34] = 44,
+ [2][1][RTW89_UK][0][34] = 6,
+ [2][1][RTW89_FCC][1][36] = -16,
+ [2][1][RTW89_FCC][2][36] = 54,
+ [2][1][RTW89_ETSI][1][36] = 44,
+ [2][1][RTW89_ETSI][0][36] = 6,
+ [2][1][RTW89_MKK][1][36] = 40,
+ [2][1][RTW89_MKK][0][36] = 2,
+ [2][1][RTW89_IC][1][36] = -16,
+ [2][1][RTW89_KCC][1][36] = -14,
+ [2][1][RTW89_KCC][0][36] = -14,
+ [2][1][RTW89_ACMA][1][36] = 44,
+ [2][1][RTW89_ACMA][0][36] = 6,
+ [2][1][RTW89_CHILE][1][36] = -16,
+ [2][1][RTW89_QATAR][1][36] = 44,
+ [2][1][RTW89_QATAR][0][36] = 6,
+ [2][1][RTW89_UK][1][36] = 44,
+ [2][1][RTW89_UK][0][36] = 6,
+ [2][1][RTW89_FCC][1][38] = -16,
+ [2][1][RTW89_FCC][2][38] = 54,
+ [2][1][RTW89_ETSI][1][38] = 44,
+ [2][1][RTW89_ETSI][0][38] = 6,
+ [2][1][RTW89_MKK][1][38] = 40,
+ [2][1][RTW89_MKK][0][38] = 2,
+ [2][1][RTW89_IC][1][38] = -16,
+ [2][1][RTW89_KCC][1][38] = -14,
+ [2][1][RTW89_KCC][0][38] = -14,
+ [2][1][RTW89_ACMA][1][38] = 44,
+ [2][1][RTW89_ACMA][0][38] = 6,
+ [2][1][RTW89_CHILE][1][38] = -16,
+ [2][1][RTW89_QATAR][1][38] = 44,
+ [2][1][RTW89_QATAR][0][38] = 6,
+ [2][1][RTW89_UK][1][38] = 44,
+ [2][1][RTW89_UK][0][38] = 6,
+ [2][1][RTW89_FCC][1][40] = -16,
+ [2][1][RTW89_FCC][2][40] = 54,
+ [2][1][RTW89_ETSI][1][40] = 44,
+ [2][1][RTW89_ETSI][0][40] = 6,
+ [2][1][RTW89_MKK][1][40] = 40,
+ [2][1][RTW89_MKK][0][40] = 2,
+ [2][1][RTW89_IC][1][40] = -16,
+ [2][1][RTW89_KCC][1][40] = -14,
+ [2][1][RTW89_KCC][0][40] = -14,
+ [2][1][RTW89_ACMA][1][40] = 44,
+ [2][1][RTW89_ACMA][0][40] = 6,
+ [2][1][RTW89_CHILE][1][40] = -16,
+ [2][1][RTW89_QATAR][1][40] = 44,
+ [2][1][RTW89_QATAR][0][40] = 6,
+ [2][1][RTW89_UK][1][40] = 44,
+ [2][1][RTW89_UK][0][40] = 6,
+ [2][1][RTW89_FCC][1][42] = -16,
+ [2][1][RTW89_FCC][2][42] = 54,
+ [2][1][RTW89_ETSI][1][42] = 44,
+ [2][1][RTW89_ETSI][0][42] = 6,
+ [2][1][RTW89_MKK][1][42] = 40,
+ [2][1][RTW89_MKK][0][42] = 2,
+ [2][1][RTW89_IC][1][42] = -16,
+ [2][1][RTW89_KCC][1][42] = -14,
+ [2][1][RTW89_KCC][0][42] = -14,
+ [2][1][RTW89_ACMA][1][42] = 44,
+ [2][1][RTW89_ACMA][0][42] = 6,
+ [2][1][RTW89_CHILE][1][42] = -16,
+ [2][1][RTW89_QATAR][1][42] = 44,
+ [2][1][RTW89_QATAR][0][42] = 6,
+ [2][1][RTW89_UK][1][42] = 44,
+ [2][1][RTW89_UK][0][42] = 6,
+ [2][1][RTW89_FCC][1][44] = -16,
+ [2][1][RTW89_FCC][2][44] = 54,
+ [2][1][RTW89_ETSI][1][44] = 44,
+ [2][1][RTW89_ETSI][0][44] = 6,
+ [2][1][RTW89_MKK][1][44] = 16,
+ [2][1][RTW89_MKK][0][44] = 2,
+ [2][1][RTW89_IC][1][44] = -16,
+ [2][1][RTW89_KCC][1][44] = -14,
+ [2][1][RTW89_KCC][0][44] = -14,
+ [2][1][RTW89_ACMA][1][44] = 44,
+ [2][1][RTW89_ACMA][0][44] = 6,
+ [2][1][RTW89_CHILE][1][44] = -16,
+ [2][1][RTW89_QATAR][1][44] = 44,
+ [2][1][RTW89_QATAR][0][44] = 6,
+ [2][1][RTW89_UK][1][44] = 44,
+ [2][1][RTW89_UK][0][44] = 6,
+ [2][1][RTW89_FCC][1][45] = -16,
+ [2][1][RTW89_FCC][2][45] = 127,
+ [2][1][RTW89_ETSI][1][45] = 127,
+ [2][1][RTW89_ETSI][0][45] = 127,
+ [2][1][RTW89_MKK][1][45] = 127,
+ [2][1][RTW89_MKK][0][45] = 127,
+ [2][1][RTW89_IC][1][45] = -16,
+ [2][1][RTW89_KCC][1][45] = -14,
+ [2][1][RTW89_KCC][0][45] = 127,
+ [2][1][RTW89_ACMA][1][45] = 127,
+ [2][1][RTW89_ACMA][0][45] = 127,
+ [2][1][RTW89_CHILE][1][45] = 127,
+ [2][1][RTW89_QATAR][1][45] = 127,
+ [2][1][RTW89_QATAR][0][45] = 127,
+ [2][1][RTW89_UK][1][45] = 127,
+ [2][1][RTW89_UK][0][45] = 127,
+ [2][1][RTW89_FCC][1][47] = -16,
+ [2][1][RTW89_FCC][2][47] = 127,
+ [2][1][RTW89_ETSI][1][47] = 127,
+ [2][1][RTW89_ETSI][0][47] = 127,
+ [2][1][RTW89_MKK][1][47] = 127,
+ [2][1][RTW89_MKK][0][47] = 127,
+ [2][1][RTW89_IC][1][47] = -16,
+ [2][1][RTW89_KCC][1][47] = -14,
+ [2][1][RTW89_KCC][0][47] = 127,
+ [2][1][RTW89_ACMA][1][47] = 127,
+ [2][1][RTW89_ACMA][0][47] = 127,
+ [2][1][RTW89_CHILE][1][47] = 127,
+ [2][1][RTW89_QATAR][1][47] = 127,
+ [2][1][RTW89_QATAR][0][47] = 127,
+ [2][1][RTW89_UK][1][47] = 127,
+ [2][1][RTW89_UK][0][47] = 127,
+ [2][1][RTW89_FCC][1][49] = -16,
+ [2][1][RTW89_FCC][2][49] = 127,
+ [2][1][RTW89_ETSI][1][49] = 127,
+ [2][1][RTW89_ETSI][0][49] = 127,
+ [2][1][RTW89_MKK][1][49] = 127,
+ [2][1][RTW89_MKK][0][49] = 127,
+ [2][1][RTW89_IC][1][49] = -16,
+ [2][1][RTW89_KCC][1][49] = -14,
+ [2][1][RTW89_KCC][0][49] = 127,
+ [2][1][RTW89_ACMA][1][49] = 127,
+ [2][1][RTW89_ACMA][0][49] = 127,
+ [2][1][RTW89_CHILE][1][49] = 127,
+ [2][1][RTW89_QATAR][1][49] = 127,
+ [2][1][RTW89_QATAR][0][49] = 127,
+ [2][1][RTW89_UK][1][49] = 127,
+ [2][1][RTW89_UK][0][49] = 127,
+ [2][1][RTW89_FCC][1][51] = -16,
+ [2][1][RTW89_FCC][2][51] = 127,
+ [2][1][RTW89_ETSI][1][51] = 127,
+ [2][1][RTW89_ETSI][0][51] = 127,
+ [2][1][RTW89_MKK][1][51] = 127,
+ [2][1][RTW89_MKK][0][51] = 127,
+ [2][1][RTW89_IC][1][51] = -16,
+ [2][1][RTW89_KCC][1][51] = -14,
+ [2][1][RTW89_KCC][0][51] = 127,
+ [2][1][RTW89_ACMA][1][51] = 127,
+ [2][1][RTW89_ACMA][0][51] = 127,
+ [2][1][RTW89_CHILE][1][51] = 127,
+ [2][1][RTW89_QATAR][1][51] = 127,
+ [2][1][RTW89_QATAR][0][51] = 127,
+ [2][1][RTW89_UK][1][51] = 127,
+ [2][1][RTW89_UK][0][51] = 127,
+ [2][1][RTW89_FCC][1][53] = -16,
+ [2][1][RTW89_FCC][2][53] = 127,
+ [2][1][RTW89_ETSI][1][53] = 127,
+ [2][1][RTW89_ETSI][0][53] = 127,
+ [2][1][RTW89_MKK][1][53] = 127,
+ [2][1][RTW89_MKK][0][53] = 127,
+ [2][1][RTW89_IC][1][53] = -16,
+ [2][1][RTW89_KCC][1][53] = -14,
+ [2][1][RTW89_KCC][0][53] = 127,
+ [2][1][RTW89_ACMA][1][53] = 127,
+ [2][1][RTW89_ACMA][0][53] = 127,
+ [2][1][RTW89_CHILE][1][53] = 127,
+ [2][1][RTW89_QATAR][1][53] = 127,
+ [2][1][RTW89_QATAR][0][53] = 127,
+ [2][1][RTW89_UK][1][53] = 127,
+ [2][1][RTW89_UK][0][53] = 127,
+ [2][1][RTW89_FCC][1][55] = -16,
+ [2][1][RTW89_FCC][2][55] = 54,
+ [2][1][RTW89_ETSI][1][55] = 127,
+ [2][1][RTW89_ETSI][0][55] = 127,
+ [2][1][RTW89_MKK][1][55] = 127,
+ [2][1][RTW89_MKK][0][55] = 127,
+ [2][1][RTW89_IC][1][55] = -16,
+ [2][1][RTW89_KCC][1][55] = -14,
+ [2][1][RTW89_KCC][0][55] = 127,
+ [2][1][RTW89_ACMA][1][55] = 127,
+ [2][1][RTW89_ACMA][0][55] = 127,
+ [2][1][RTW89_CHILE][1][55] = 127,
+ [2][1][RTW89_QATAR][1][55] = 127,
+ [2][1][RTW89_QATAR][0][55] = 127,
+ [2][1][RTW89_UK][1][55] = 127,
+ [2][1][RTW89_UK][0][55] = 127,
+ [2][1][RTW89_FCC][1][57] = -16,
+ [2][1][RTW89_FCC][2][57] = 54,
+ [2][1][RTW89_ETSI][1][57] = 127,
+ [2][1][RTW89_ETSI][0][57] = 127,
+ [2][1][RTW89_MKK][1][57] = 127,
+ [2][1][RTW89_MKK][0][57] = 127,
+ [2][1][RTW89_IC][1][57] = -16,
+ [2][1][RTW89_KCC][1][57] = -14,
+ [2][1][RTW89_KCC][0][57] = 127,
+ [2][1][RTW89_ACMA][1][57] = 127,
+ [2][1][RTW89_ACMA][0][57] = 127,
+ [2][1][RTW89_CHILE][1][57] = 127,
+ [2][1][RTW89_QATAR][1][57] = 127,
+ [2][1][RTW89_QATAR][0][57] = 127,
+ [2][1][RTW89_UK][1][57] = 127,
+ [2][1][RTW89_UK][0][57] = 127,
+ [2][1][RTW89_FCC][1][59] = -16,
+ [2][1][RTW89_FCC][2][59] = 54,
+ [2][1][RTW89_ETSI][1][59] = 127,
+ [2][1][RTW89_ETSI][0][59] = 127,
+ [2][1][RTW89_MKK][1][59] = 127,
+ [2][1][RTW89_MKK][0][59] = 127,
+ [2][1][RTW89_IC][1][59] = -16,
+ [2][1][RTW89_KCC][1][59] = -14,
+ [2][1][RTW89_KCC][0][59] = 127,
+ [2][1][RTW89_ACMA][1][59] = 127,
+ [2][1][RTW89_ACMA][0][59] = 127,
+ [2][1][RTW89_CHILE][1][59] = 127,
+ [2][1][RTW89_QATAR][1][59] = 127,
+ [2][1][RTW89_QATAR][0][59] = 127,
+ [2][1][RTW89_UK][1][59] = 127,
+ [2][1][RTW89_UK][0][59] = 127,
+ [2][1][RTW89_FCC][1][60] = -16,
+ [2][1][RTW89_FCC][2][60] = 54,
+ [2][1][RTW89_ETSI][1][60] = 127,
+ [2][1][RTW89_ETSI][0][60] = 127,
+ [2][1][RTW89_MKK][1][60] = 127,
+ [2][1][RTW89_MKK][0][60] = 127,
+ [2][1][RTW89_IC][1][60] = -16,
+ [2][1][RTW89_KCC][1][60] = -14,
+ [2][1][RTW89_KCC][0][60] = 127,
+ [2][1][RTW89_ACMA][1][60] = 127,
+ [2][1][RTW89_ACMA][0][60] = 127,
+ [2][1][RTW89_CHILE][1][60] = 127,
+ [2][1][RTW89_QATAR][1][60] = 127,
+ [2][1][RTW89_QATAR][0][60] = 127,
+ [2][1][RTW89_UK][1][60] = 127,
+ [2][1][RTW89_UK][0][60] = 127,
+ [2][1][RTW89_FCC][1][62] = -16,
+ [2][1][RTW89_FCC][2][62] = 54,
+ [2][1][RTW89_ETSI][1][62] = 127,
+ [2][1][RTW89_ETSI][0][62] = 127,
+ [2][1][RTW89_MKK][1][62] = 127,
+ [2][1][RTW89_MKK][0][62] = 127,
+ [2][1][RTW89_IC][1][62] = -16,
+ [2][1][RTW89_KCC][1][62] = -14,
+ [2][1][RTW89_KCC][0][62] = 127,
+ [2][1][RTW89_ACMA][1][62] = 127,
+ [2][1][RTW89_ACMA][0][62] = 127,
+ [2][1][RTW89_CHILE][1][62] = 127,
+ [2][1][RTW89_QATAR][1][62] = 127,
+ [2][1][RTW89_QATAR][0][62] = 127,
+ [2][1][RTW89_UK][1][62] = 127,
+ [2][1][RTW89_UK][0][62] = 127,
+ [2][1][RTW89_FCC][1][64] = -16,
+ [2][1][RTW89_FCC][2][64] = 54,
+ [2][1][RTW89_ETSI][1][64] = 127,
+ [2][1][RTW89_ETSI][0][64] = 127,
+ [2][1][RTW89_MKK][1][64] = 127,
+ [2][1][RTW89_MKK][0][64] = 127,
+ [2][1][RTW89_IC][1][64] = -16,
+ [2][1][RTW89_KCC][1][64] = -14,
+ [2][1][RTW89_KCC][0][64] = 127,
+ [2][1][RTW89_ACMA][1][64] = 127,
+ [2][1][RTW89_ACMA][0][64] = 127,
+ [2][1][RTW89_CHILE][1][64] = 127,
+ [2][1][RTW89_QATAR][1][64] = 127,
+ [2][1][RTW89_QATAR][0][64] = 127,
+ [2][1][RTW89_UK][1][64] = 127,
+ [2][1][RTW89_UK][0][64] = 127,
+ [2][1][RTW89_FCC][1][66] = -16,
+ [2][1][RTW89_FCC][2][66] = 54,
+ [2][1][RTW89_ETSI][1][66] = 127,
+ [2][1][RTW89_ETSI][0][66] = 127,
+ [2][1][RTW89_MKK][1][66] = 127,
+ [2][1][RTW89_MKK][0][66] = 127,
+ [2][1][RTW89_IC][1][66] = -16,
+ [2][1][RTW89_KCC][1][66] = -14,
+ [2][1][RTW89_KCC][0][66] = 127,
+ [2][1][RTW89_ACMA][1][66] = 127,
+ [2][1][RTW89_ACMA][0][66] = 127,
+ [2][1][RTW89_CHILE][1][66] = 127,
+ [2][1][RTW89_QATAR][1][66] = 127,
+ [2][1][RTW89_QATAR][0][66] = 127,
+ [2][1][RTW89_UK][1][66] = 127,
+ [2][1][RTW89_UK][0][66] = 127,
+ [2][1][RTW89_FCC][1][68] = -16,
+ [2][1][RTW89_FCC][2][68] = 54,
+ [2][1][RTW89_ETSI][1][68] = 127,
+ [2][1][RTW89_ETSI][0][68] = 127,
+ [2][1][RTW89_MKK][1][68] = 127,
+ [2][1][RTW89_MKK][0][68] = 127,
+ [2][1][RTW89_IC][1][68] = -16,
+ [2][1][RTW89_KCC][1][68] = -14,
+ [2][1][RTW89_KCC][0][68] = 127,
+ [2][1][RTW89_ACMA][1][68] = 127,
+ [2][1][RTW89_ACMA][0][68] = 127,
+ [2][1][RTW89_CHILE][1][68] = 127,
+ [2][1][RTW89_QATAR][1][68] = 127,
+ [2][1][RTW89_QATAR][0][68] = 127,
+ [2][1][RTW89_UK][1][68] = 127,
+ [2][1][RTW89_UK][0][68] = 127,
+ [2][1][RTW89_FCC][1][70] = -16,
+ [2][1][RTW89_FCC][2][70] = 56,
+ [2][1][RTW89_ETSI][1][70] = 127,
+ [2][1][RTW89_ETSI][0][70] = 127,
+ [2][1][RTW89_MKK][1][70] = 127,
+ [2][1][RTW89_MKK][0][70] = 127,
+ [2][1][RTW89_IC][1][70] = -16,
+ [2][1][RTW89_KCC][1][70] = -14,
+ [2][1][RTW89_KCC][0][70] = 127,
+ [2][1][RTW89_ACMA][1][70] = 127,
+ [2][1][RTW89_ACMA][0][70] = 127,
+ [2][1][RTW89_CHILE][1][70] = 127,
+ [2][1][RTW89_QATAR][1][70] = 127,
+ [2][1][RTW89_QATAR][0][70] = 127,
+ [2][1][RTW89_UK][1][70] = 127,
+ [2][1][RTW89_UK][0][70] = 127,
+ [2][1][RTW89_FCC][1][72] = -16,
+ [2][1][RTW89_FCC][2][72] = 56,
+ [2][1][RTW89_ETSI][1][72] = 127,
+ [2][1][RTW89_ETSI][0][72] = 127,
+ [2][1][RTW89_MKK][1][72] = 127,
+ [2][1][RTW89_MKK][0][72] = 127,
+ [2][1][RTW89_IC][1][72] = -16,
+ [2][1][RTW89_KCC][1][72] = -14,
+ [2][1][RTW89_KCC][0][72] = 127,
+ [2][1][RTW89_ACMA][1][72] = 127,
+ [2][1][RTW89_ACMA][0][72] = 127,
+ [2][1][RTW89_CHILE][1][72] = 127,
+ [2][1][RTW89_QATAR][1][72] = 127,
+ [2][1][RTW89_QATAR][0][72] = 127,
+ [2][1][RTW89_UK][1][72] = 127,
+ [2][1][RTW89_UK][0][72] = 127,
+ [2][1][RTW89_FCC][1][74] = -16,
+ [2][1][RTW89_FCC][2][74] = 56,
+ [2][1][RTW89_ETSI][1][74] = 127,
+ [2][1][RTW89_ETSI][0][74] = 127,
+ [2][1][RTW89_MKK][1][74] = 127,
+ [2][1][RTW89_MKK][0][74] = 127,
+ [2][1][RTW89_IC][1][74] = -16,
+ [2][1][RTW89_KCC][1][74] = -14,
+ [2][1][RTW89_KCC][0][74] = 127,
+ [2][1][RTW89_ACMA][1][74] = 127,
+ [2][1][RTW89_ACMA][0][74] = 127,
+ [2][1][RTW89_CHILE][1][74] = 127,
+ [2][1][RTW89_QATAR][1][74] = 127,
+ [2][1][RTW89_QATAR][0][74] = 127,
+ [2][1][RTW89_UK][1][74] = 127,
+ [2][1][RTW89_UK][0][74] = 127,
+ [2][1][RTW89_FCC][1][75] = -16,
+ [2][1][RTW89_FCC][2][75] = 56,
+ [2][1][RTW89_ETSI][1][75] = 127,
+ [2][1][RTW89_ETSI][0][75] = 127,
+ [2][1][RTW89_MKK][1][75] = 127,
+ [2][1][RTW89_MKK][0][75] = 127,
+ [2][1][RTW89_IC][1][75] = -16,
+ [2][1][RTW89_KCC][1][75] = -14,
+ [2][1][RTW89_KCC][0][75] = 127,
+ [2][1][RTW89_ACMA][1][75] = 127,
+ [2][1][RTW89_ACMA][0][75] = 127,
+ [2][1][RTW89_CHILE][1][75] = 127,
+ [2][1][RTW89_QATAR][1][75] = 127,
+ [2][1][RTW89_QATAR][0][75] = 127,
+ [2][1][RTW89_UK][1][75] = 127,
+ [2][1][RTW89_UK][0][75] = 127,
+ [2][1][RTW89_FCC][1][77] = -16,
+ [2][1][RTW89_FCC][2][77] = 56,
+ [2][1][RTW89_ETSI][1][77] = 127,
+ [2][1][RTW89_ETSI][0][77] = 127,
+ [2][1][RTW89_MKK][1][77] = 127,
+ [2][1][RTW89_MKK][0][77] = 127,
+ [2][1][RTW89_IC][1][77] = -16,
+ [2][1][RTW89_KCC][1][77] = -14,
+ [2][1][RTW89_KCC][0][77] = 127,
+ [2][1][RTW89_ACMA][1][77] = 127,
+ [2][1][RTW89_ACMA][0][77] = 127,
+ [2][1][RTW89_CHILE][1][77] = 127,
+ [2][1][RTW89_QATAR][1][77] = 127,
+ [2][1][RTW89_QATAR][0][77] = 127,
+ [2][1][RTW89_UK][1][77] = 127,
+ [2][1][RTW89_UK][0][77] = 127,
+ [2][1][RTW89_FCC][1][79] = -16,
+ [2][1][RTW89_FCC][2][79] = 56,
+ [2][1][RTW89_ETSI][1][79] = 127,
+ [2][1][RTW89_ETSI][0][79] = 127,
+ [2][1][RTW89_MKK][1][79] = 127,
+ [2][1][RTW89_MKK][0][79] = 127,
+ [2][1][RTW89_IC][1][79] = -16,
+ [2][1][RTW89_KCC][1][79] = -14,
+ [2][1][RTW89_KCC][0][79] = 127,
+ [2][1][RTW89_ACMA][1][79] = 127,
+ [2][1][RTW89_ACMA][0][79] = 127,
+ [2][1][RTW89_CHILE][1][79] = 127,
+ [2][1][RTW89_QATAR][1][79] = 127,
+ [2][1][RTW89_QATAR][0][79] = 127,
+ [2][1][RTW89_UK][1][79] = 127,
+ [2][1][RTW89_UK][0][79] = 127,
+ [2][1][RTW89_FCC][1][81] = -16,
+ [2][1][RTW89_FCC][2][81] = 56,
+ [2][1][RTW89_ETSI][1][81] = 127,
+ [2][1][RTW89_ETSI][0][81] = 127,
+ [2][1][RTW89_MKK][1][81] = 127,
+ [2][1][RTW89_MKK][0][81] = 127,
+ [2][1][RTW89_IC][1][81] = -16,
+ [2][1][RTW89_KCC][1][81] = -14,
+ [2][1][RTW89_KCC][0][81] = 127,
+ [2][1][RTW89_ACMA][1][81] = 127,
+ [2][1][RTW89_ACMA][0][81] = 127,
+ [2][1][RTW89_CHILE][1][81] = 127,
+ [2][1][RTW89_QATAR][1][81] = 127,
+ [2][1][RTW89_QATAR][0][81] = 127,
+ [2][1][RTW89_UK][1][81] = 127,
+ [2][1][RTW89_UK][0][81] = 127,
+ [2][1][RTW89_FCC][1][83] = -16,
+ [2][1][RTW89_FCC][2][83] = 56,
+ [2][1][RTW89_ETSI][1][83] = 127,
+ [2][1][RTW89_ETSI][0][83] = 127,
+ [2][1][RTW89_MKK][1][83] = 127,
+ [2][1][RTW89_MKK][0][83] = 127,
+ [2][1][RTW89_IC][1][83] = -16,
+ [2][1][RTW89_KCC][1][83] = -14,
+ [2][1][RTW89_KCC][0][83] = 127,
+ [2][1][RTW89_ACMA][1][83] = 127,
+ [2][1][RTW89_ACMA][0][83] = 127,
+ [2][1][RTW89_CHILE][1][83] = 127,
+ [2][1][RTW89_QATAR][1][83] = 127,
+ [2][1][RTW89_QATAR][0][83] = 127,
+ [2][1][RTW89_UK][1][83] = 127,
+ [2][1][RTW89_UK][0][83] = 127,
+ [2][1][RTW89_FCC][1][85] = -18,
+ [2][1][RTW89_FCC][2][85] = 56,
+ [2][1][RTW89_ETSI][1][85] = 127,
+ [2][1][RTW89_ETSI][0][85] = 127,
+ [2][1][RTW89_MKK][1][85] = 127,
+ [2][1][RTW89_MKK][0][85] = 127,
+ [2][1][RTW89_IC][1][85] = -18,
+ [2][1][RTW89_KCC][1][85] = -14,
+ [2][1][RTW89_KCC][0][85] = 127,
+ [2][1][RTW89_ACMA][1][85] = 127,
+ [2][1][RTW89_ACMA][0][85] = 127,
+ [2][1][RTW89_CHILE][1][85] = 127,
+ [2][1][RTW89_QATAR][1][85] = 127,
+ [2][1][RTW89_QATAR][0][85] = 127,
+ [2][1][RTW89_UK][1][85] = 127,
+ [2][1][RTW89_UK][0][85] = 127,
+ [2][1][RTW89_FCC][1][87] = -16,
+ [2][1][RTW89_FCC][2][87] = 127,
+ [2][1][RTW89_ETSI][1][87] = 127,
+ [2][1][RTW89_ETSI][0][87] = 127,
+ [2][1][RTW89_MKK][1][87] = 127,
+ [2][1][RTW89_MKK][0][87] = 127,
+ [2][1][RTW89_IC][1][87] = -16,
+ [2][1][RTW89_KCC][1][87] = -14,
+ [2][1][RTW89_KCC][0][87] = 127,
+ [2][1][RTW89_ACMA][1][87] = 127,
+ [2][1][RTW89_ACMA][0][87] = 127,
+ [2][1][RTW89_CHILE][1][87] = 127,
+ [2][1][RTW89_QATAR][1][87] = 127,
+ [2][1][RTW89_QATAR][0][87] = 127,
+ [2][1][RTW89_UK][1][87] = 127,
+ [2][1][RTW89_UK][0][87] = 127,
+ [2][1][RTW89_FCC][1][89] = -16,
+ [2][1][RTW89_FCC][2][89] = 127,
+ [2][1][RTW89_ETSI][1][89] = 127,
+ [2][1][RTW89_ETSI][0][89] = 127,
+ [2][1][RTW89_MKK][1][89] = 127,
+ [2][1][RTW89_MKK][0][89] = 127,
+ [2][1][RTW89_IC][1][89] = -16,
+ [2][1][RTW89_KCC][1][89] = -14,
+ [2][1][RTW89_KCC][0][89] = 127,
+ [2][1][RTW89_ACMA][1][89] = 127,
+ [2][1][RTW89_ACMA][0][89] = 127,
+ [2][1][RTW89_CHILE][1][89] = 127,
+ [2][1][RTW89_QATAR][1][89] = 127,
+ [2][1][RTW89_QATAR][0][89] = 127,
+ [2][1][RTW89_UK][1][89] = 127,
+ [2][1][RTW89_UK][0][89] = 127,
+ [2][1][RTW89_FCC][1][90] = -16,
+ [2][1][RTW89_FCC][2][90] = 127,
+ [2][1][RTW89_ETSI][1][90] = 127,
+ [2][1][RTW89_ETSI][0][90] = 127,
+ [2][1][RTW89_MKK][1][90] = 127,
+ [2][1][RTW89_MKK][0][90] = 127,
+ [2][1][RTW89_IC][1][90] = -16,
+ [2][1][RTW89_KCC][1][90] = -14,
+ [2][1][RTW89_KCC][0][90] = 127,
+ [2][1][RTW89_ACMA][1][90] = 127,
+ [2][1][RTW89_ACMA][0][90] = 127,
+ [2][1][RTW89_CHILE][1][90] = 127,
+ [2][1][RTW89_QATAR][1][90] = 127,
+ [2][1][RTW89_QATAR][0][90] = 127,
+ [2][1][RTW89_UK][1][90] = 127,
+ [2][1][RTW89_UK][0][90] = 127,
+ [2][1][RTW89_FCC][1][92] = -16,
+ [2][1][RTW89_FCC][2][92] = 127,
+ [2][1][RTW89_ETSI][1][92] = 127,
+ [2][1][RTW89_ETSI][0][92] = 127,
+ [2][1][RTW89_MKK][1][92] = 127,
+ [2][1][RTW89_MKK][0][92] = 127,
+ [2][1][RTW89_IC][1][92] = -16,
+ [2][1][RTW89_KCC][1][92] = -14,
+ [2][1][RTW89_KCC][0][92] = 127,
+ [2][1][RTW89_ACMA][1][92] = 127,
+ [2][1][RTW89_ACMA][0][92] = 127,
+ [2][1][RTW89_CHILE][1][92] = 127,
+ [2][1][RTW89_QATAR][1][92] = 127,
+ [2][1][RTW89_QATAR][0][92] = 127,
+ [2][1][RTW89_UK][1][92] = 127,
+ [2][1][RTW89_UK][0][92] = 127,
+ [2][1][RTW89_FCC][1][94] = -16,
+ [2][1][RTW89_FCC][2][94] = 127,
+ [2][1][RTW89_ETSI][1][94] = 127,
+ [2][1][RTW89_ETSI][0][94] = 127,
+ [2][1][RTW89_MKK][1][94] = 127,
+ [2][1][RTW89_MKK][0][94] = 127,
+ [2][1][RTW89_IC][1][94] = -16,
+ [2][1][RTW89_KCC][1][94] = -14,
+ [2][1][RTW89_KCC][0][94] = 127,
+ [2][1][RTW89_ACMA][1][94] = 127,
+ [2][1][RTW89_ACMA][0][94] = 127,
+ [2][1][RTW89_CHILE][1][94] = 127,
+ [2][1][RTW89_QATAR][1][94] = 127,
+ [2][1][RTW89_QATAR][0][94] = 127,
+ [2][1][RTW89_UK][1][94] = 127,
+ [2][1][RTW89_UK][0][94] = 127,
+ [2][1][RTW89_FCC][1][96] = -16,
+ [2][1][RTW89_FCC][2][96] = 127,
+ [2][1][RTW89_ETSI][1][96] = 127,
+ [2][1][RTW89_ETSI][0][96] = 127,
+ [2][1][RTW89_MKK][1][96] = 127,
+ [2][1][RTW89_MKK][0][96] = 127,
+ [2][1][RTW89_IC][1][96] = -16,
+ [2][1][RTW89_KCC][1][96] = -14,
+ [2][1][RTW89_KCC][0][96] = 127,
+ [2][1][RTW89_ACMA][1][96] = 127,
+ [2][1][RTW89_ACMA][0][96] = 127,
+ [2][1][RTW89_CHILE][1][96] = 127,
+ [2][1][RTW89_QATAR][1][96] = 127,
+ [2][1][RTW89_QATAR][0][96] = 127,
+ [2][1][RTW89_UK][1][96] = 127,
+ [2][1][RTW89_UK][0][96] = 127,
+ [2][1][RTW89_FCC][1][98] = -16,
+ [2][1][RTW89_FCC][2][98] = 127,
+ [2][1][RTW89_ETSI][1][98] = 127,
+ [2][1][RTW89_ETSI][0][98] = 127,
+ [2][1][RTW89_MKK][1][98] = 127,
+ [2][1][RTW89_MKK][0][98] = 127,
+ [2][1][RTW89_IC][1][98] = -16,
+ [2][1][RTW89_KCC][1][98] = -14,
+ [2][1][RTW89_KCC][0][98] = 127,
+ [2][1][RTW89_ACMA][1][98] = 127,
+ [2][1][RTW89_ACMA][0][98] = 127,
+ [2][1][RTW89_CHILE][1][98] = 127,
+ [2][1][RTW89_QATAR][1][98] = 127,
+ [2][1][RTW89_QATAR][0][98] = 127,
+ [2][1][RTW89_UK][1][98] = 127,
+ [2][1][RTW89_UK][0][98] = 127,
+ [2][1][RTW89_FCC][1][100] = -16,
+ [2][1][RTW89_FCC][2][100] = 127,
+ [2][1][RTW89_ETSI][1][100] = 127,
+ [2][1][RTW89_ETSI][0][100] = 127,
+ [2][1][RTW89_MKK][1][100] = 127,
+ [2][1][RTW89_MKK][0][100] = 127,
+ [2][1][RTW89_IC][1][100] = -16,
+ [2][1][RTW89_KCC][1][100] = -14,
+ [2][1][RTW89_KCC][0][100] = 127,
+ [2][1][RTW89_ACMA][1][100] = 127,
+ [2][1][RTW89_ACMA][0][100] = 127,
+ [2][1][RTW89_CHILE][1][100] = 127,
+ [2][1][RTW89_QATAR][1][100] = 127,
+ [2][1][RTW89_QATAR][0][100] = 127,
+ [2][1][RTW89_UK][1][100] = 127,
+ [2][1][RTW89_UK][0][100] = 127,
+ [2][1][RTW89_FCC][1][102] = -16,
+ [2][1][RTW89_FCC][2][102] = 127,
+ [2][1][RTW89_ETSI][1][102] = 127,
+ [2][1][RTW89_ETSI][0][102] = 127,
+ [2][1][RTW89_MKK][1][102] = 127,
+ [2][1][RTW89_MKK][0][102] = 127,
+ [2][1][RTW89_IC][1][102] = -16,
+ [2][1][RTW89_KCC][1][102] = -14,
+ [2][1][RTW89_KCC][0][102] = 127,
+ [2][1][RTW89_ACMA][1][102] = 127,
+ [2][1][RTW89_ACMA][0][102] = 127,
+ [2][1][RTW89_CHILE][1][102] = 127,
+ [2][1][RTW89_QATAR][1][102] = 127,
+ [2][1][RTW89_QATAR][0][102] = 127,
+ [2][1][RTW89_UK][1][102] = 127,
+ [2][1][RTW89_UK][0][102] = 127,
+ [2][1][RTW89_FCC][1][104] = -16,
+ [2][1][RTW89_FCC][2][104] = 127,
+ [2][1][RTW89_ETSI][1][104] = 127,
+ [2][1][RTW89_ETSI][0][104] = 127,
+ [2][1][RTW89_MKK][1][104] = 127,
+ [2][1][RTW89_MKK][0][104] = 127,
+ [2][1][RTW89_IC][1][104] = -16,
+ [2][1][RTW89_KCC][1][104] = -14,
+ [2][1][RTW89_KCC][0][104] = 127,
+ [2][1][RTW89_ACMA][1][104] = 127,
+ [2][1][RTW89_ACMA][0][104] = 127,
+ [2][1][RTW89_CHILE][1][104] = 127,
+ [2][1][RTW89_QATAR][1][104] = 127,
+ [2][1][RTW89_QATAR][0][104] = 127,
+ [2][1][RTW89_UK][1][104] = 127,
+ [2][1][RTW89_UK][0][104] = 127,
+ [2][1][RTW89_FCC][1][105] = -16,
+ [2][1][RTW89_FCC][2][105] = 127,
+ [2][1][RTW89_ETSI][1][105] = 127,
+ [2][1][RTW89_ETSI][0][105] = 127,
+ [2][1][RTW89_MKK][1][105] = 127,
+ [2][1][RTW89_MKK][0][105] = 127,
+ [2][1][RTW89_IC][1][105] = -16,
+ [2][1][RTW89_KCC][1][105] = -14,
+ [2][1][RTW89_KCC][0][105] = 127,
+ [2][1][RTW89_ACMA][1][105] = 127,
+ [2][1][RTW89_ACMA][0][105] = 127,
+ [2][1][RTW89_CHILE][1][105] = 127,
+ [2][1][RTW89_QATAR][1][105] = 127,
+ [2][1][RTW89_QATAR][0][105] = 127,
+ [2][1][RTW89_UK][1][105] = 127,
+ [2][1][RTW89_UK][0][105] = 127,
+ [2][1][RTW89_FCC][1][107] = -12,
+ [2][1][RTW89_FCC][2][107] = 127,
+ [2][1][RTW89_ETSI][1][107] = 127,
+ [2][1][RTW89_ETSI][0][107] = 127,
+ [2][1][RTW89_MKK][1][107] = 127,
+ [2][1][RTW89_MKK][0][107] = 127,
+ [2][1][RTW89_IC][1][107] = -12,
+ [2][1][RTW89_KCC][1][107] = -14,
+ [2][1][RTW89_KCC][0][107] = 127,
+ [2][1][RTW89_ACMA][1][107] = 127,
+ [2][1][RTW89_ACMA][0][107] = 127,
+ [2][1][RTW89_CHILE][1][107] = 127,
+ [2][1][RTW89_QATAR][1][107] = 127,
+ [2][1][RTW89_QATAR][0][107] = 127,
+ [2][1][RTW89_UK][1][107] = 127,
+ [2][1][RTW89_UK][0][107] = 127,
+ [2][1][RTW89_FCC][1][109] = -10,
+ [2][1][RTW89_FCC][2][109] = 127,
+ [2][1][RTW89_ETSI][1][109] = 127,
+ [2][1][RTW89_ETSI][0][109] = 127,
+ [2][1][RTW89_MKK][1][109] = 127,
+ [2][1][RTW89_MKK][0][109] = 127,
+ [2][1][RTW89_IC][1][109] = -10,
+ [2][1][RTW89_KCC][1][109] = 127,
+ [2][1][RTW89_KCC][0][109] = 127,
+ [2][1][RTW89_ACMA][1][109] = 127,
+ [2][1][RTW89_ACMA][0][109] = 127,
+ [2][1][RTW89_CHILE][1][109] = 127,
+ [2][1][RTW89_QATAR][1][109] = 127,
+ [2][1][RTW89_QATAR][0][109] = 127,
+ [2][1][RTW89_UK][1][109] = 127,
+ [2][1][RTW89_UK][0][109] = 127,
+ [2][1][RTW89_FCC][1][111] = 127,
+ [2][1][RTW89_FCC][2][111] = 127,
+ [2][1][RTW89_ETSI][1][111] = 127,
+ [2][1][RTW89_ETSI][0][111] = 127,
+ [2][1][RTW89_MKK][1][111] = 127,
+ [2][1][RTW89_MKK][0][111] = 127,
+ [2][1][RTW89_IC][1][111] = 127,
+ [2][1][RTW89_KCC][1][111] = 127,
+ [2][1][RTW89_KCC][0][111] = 127,
+ [2][1][RTW89_ACMA][1][111] = 127,
+ [2][1][RTW89_ACMA][0][111] = 127,
+ [2][1][RTW89_CHILE][1][111] = 127,
+ [2][1][RTW89_QATAR][1][111] = 127,
+ [2][1][RTW89_QATAR][0][111] = 127,
+ [2][1][RTW89_UK][1][111] = 127,
+ [2][1][RTW89_UK][0][111] = 127,
+ [2][1][RTW89_FCC][1][113] = 127,
+ [2][1][RTW89_FCC][2][113] = 127,
+ [2][1][RTW89_ETSI][1][113] = 127,
+ [2][1][RTW89_ETSI][0][113] = 127,
+ [2][1][RTW89_MKK][1][113] = 127,
+ [2][1][RTW89_MKK][0][113] = 127,
+ [2][1][RTW89_IC][1][113] = 127,
+ [2][1][RTW89_KCC][1][113] = 127,
+ [2][1][RTW89_KCC][0][113] = 127,
+ [2][1][RTW89_ACMA][1][113] = 127,
+ [2][1][RTW89_ACMA][0][113] = 127,
+ [2][1][RTW89_CHILE][1][113] = 127,
+ [2][1][RTW89_QATAR][1][113] = 127,
+ [2][1][RTW89_QATAR][0][113] = 127,
+ [2][1][RTW89_UK][1][113] = 127,
+ [2][1][RTW89_UK][0][113] = 127,
+ [2][1][RTW89_FCC][1][115] = 127,
+ [2][1][RTW89_FCC][2][115] = 127,
+ [2][1][RTW89_ETSI][1][115] = 127,
+ [2][1][RTW89_ETSI][0][115] = 127,
+ [2][1][RTW89_MKK][1][115] = 127,
+ [2][1][RTW89_MKK][0][115] = 127,
+ [2][1][RTW89_IC][1][115] = 127,
+ [2][1][RTW89_KCC][1][115] = 127,
+ [2][1][RTW89_KCC][0][115] = 127,
+ [2][1][RTW89_ACMA][1][115] = 127,
+ [2][1][RTW89_ACMA][0][115] = 127,
+ [2][1][RTW89_CHILE][1][115] = 127,
+ [2][1][RTW89_QATAR][1][115] = 127,
+ [2][1][RTW89_QATAR][0][115] = 127,
+ [2][1][RTW89_UK][1][115] = 127,
+ [2][1][RTW89_UK][0][115] = 127,
+ [2][1][RTW89_FCC][1][117] = 127,
+ [2][1][RTW89_FCC][2][117] = 127,
+ [2][1][RTW89_ETSI][1][117] = 127,
+ [2][1][RTW89_ETSI][0][117] = 127,
+ [2][1][RTW89_MKK][1][117] = 127,
+ [2][1][RTW89_MKK][0][117] = 127,
+ [2][1][RTW89_IC][1][117] = 127,
+ [2][1][RTW89_KCC][1][117] = 127,
+ [2][1][RTW89_KCC][0][117] = 127,
+ [2][1][RTW89_ACMA][1][117] = 127,
+ [2][1][RTW89_ACMA][0][117] = 127,
+ [2][1][RTW89_CHILE][1][117] = 127,
+ [2][1][RTW89_QATAR][1][117] = 127,
+ [2][1][RTW89_QATAR][0][117] = 127,
+ [2][1][RTW89_UK][1][117] = 127,
+ [2][1][RTW89_UK][0][117] = 127,
+ [2][1][RTW89_FCC][1][119] = 127,
+ [2][1][RTW89_FCC][2][119] = 127,
+ [2][1][RTW89_ETSI][1][119] = 127,
+ [2][1][RTW89_ETSI][0][119] = 127,
+ [2][1][RTW89_MKK][1][119] = 127,
+ [2][1][RTW89_MKK][0][119] = 127,
+ [2][1][RTW89_IC][1][119] = 127,
+ [2][1][RTW89_KCC][1][119] = 127,
+ [2][1][RTW89_KCC][0][119] = 127,
+ [2][1][RTW89_ACMA][1][119] = 127,
+ [2][1][RTW89_ACMA][0][119] = 127,
+ [2][1][RTW89_CHILE][1][119] = 127,
+ [2][1][RTW89_QATAR][1][119] = 127,
+ [2][1][RTW89_QATAR][0][119] = 127,
+ [2][1][RTW89_UK][1][119] = 127,
+ [2][1][RTW89_UK][0][119] = 127,
};
const struct rtw89_phy_table rtw89_8852c_phy_bb_table = {
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h
index 6da1849fb1fa..3eb0c4995174 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h
@@ -15,7 +15,7 @@ extern const struct rtw89_phy_table rtw89_8852c_phy_nctl_table;
extern const struct rtw89_txpwr_table rtw89_8852c_byr_table;
extern const struct rtw89_phy_tssi_dbw_table rtw89_8852c_tssi_dbw_table;
extern const struct rtw89_txpwr_track_cfg rtw89_8852c_trk_cfg;
-extern const u8 rtw89_8852c_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
+extern const u8 rtw89_8852c_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM]
[RTW89_REGD_NUM];
extern const struct rtw89_rfe_parms rtw89_8852c_dflt_parms;
diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c
index 9e9f6947e7f1..0462ba693f6f 100644
--- a/drivers/net/wireless/realtek/rtw89/ser.c
+++ b/drivers/net/wireless/realtek/rtw89/ser.c
@@ -20,12 +20,14 @@ enum ser_evt {
SER_EV_NONE,
SER_EV_STATE_IN,
SER_EV_STATE_OUT,
+ SER_EV_L1_RESET_PREPARE, /* pre-M0 */
SER_EV_L1_RESET, /* M1 */
SER_EV_DO_RECOVERY, /* M3 */
SER_EV_MAC_RESET_DONE, /* M5 */
SER_EV_L2_RESET,
SER_EV_L2_RECFG_DONE,
SER_EV_L2_RECFG_TIMEOUT,
+ SER_EV_M1_TIMEOUT,
SER_EV_M3_TIMEOUT,
SER_EV_FW_M5_TIMEOUT,
SER_EV_L0_RESET,
@@ -34,6 +36,7 @@ enum ser_evt {
enum ser_state {
SER_IDLE_ST,
+ SER_L1_RESET_PRE_ST,
SER_RESET_TRX_ST,
SER_DO_HCI_ST,
SER_L2_RESET_ST,
@@ -300,6 +303,7 @@ static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port);
rtwvif->net_type = RTW89_NET_TYPE_NO_LINK;
rtwvif->trigger = false;
+ rtwvif->tdls_peer = 0;
}
static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta)
@@ -338,6 +342,8 @@ static void ser_reset_mac_binding(struct rtw89_dev *rtwdev)
rtw89_core_release_all_bits_map(rtwdev->mac_id_map, RTW89_MAX_MAC_ID_NUM);
rtw89_for_each_rtwvif(rtwdev, rtwvif)
ser_reset_vif(rtwdev, rtwvif);
+
+ rtwdev->total_sta_assoc = 0;
}
/* hal function */
@@ -374,6 +380,13 @@ static int hal_stop_dma(struct rtw89_ser *ser)
return ret;
}
+static void hal_send_post_m0_event(struct rtw89_ser *ser)
+{
+ struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser);
+
+ rtw89_mac_set_err_status(rtwdev, MAC_AX_ERR_L1_RESET_START_DMAC);
+}
+
static void hal_send_m2_event(struct rtw89_ser *ser)
{
struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser);
@@ -396,8 +409,12 @@ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt)
switch (evt) {
case SER_EV_STATE_IN:
rtw89_hci_recovery_complete(rtwdev);
+ clear_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags);
clear_bit(RTW89_FLAG_CRASH_SIMULATING, rtwdev->flags);
break;
+ case SER_EV_L1_RESET_PREPARE:
+ ser_state_goto(ser, SER_L1_RESET_PRE_ST);
+ break;
case SER_EV_L1_RESET:
ser_state_goto(ser, SER_RESET_TRX_ST);
break;
@@ -405,6 +422,7 @@ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt)
ser_state_goto(ser, SER_L2_RESET_ST);
break;
case SER_EV_STATE_OUT:
+ set_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags);
rtw89_hci_recovery_start(rtwdev);
break;
default:
@@ -412,6 +430,28 @@ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt)
}
}
+static void ser_l1_reset_pre_st_hdl(struct rtw89_ser *ser, u8 evt)
+{
+ switch (evt) {
+ case SER_EV_STATE_IN:
+ ser->prehandle_l1 = true;
+ hal_send_post_m0_event(ser);
+ ser_set_alarm(ser, 1000, SER_EV_M1_TIMEOUT);
+ break;
+ case SER_EV_L1_RESET:
+ ser_state_goto(ser, SER_RESET_TRX_ST);
+ break;
+ case SER_EV_M1_TIMEOUT:
+ ser_state_goto(ser, SER_L2_RESET_ST);
+ break;
+ case SER_EV_STATE_OUT:
+ ser_del_alarm(ser);
+ break;
+ default:
+ break;
+ }
+}
+
static void ser_reset_trx_st_hdl(struct rtw89_ser *ser, u8 evt)
{
struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser);
@@ -654,12 +694,14 @@ static const struct event_ent ser_ev_tbl[] = {
{SER_EV_NONE, "SER_EV_NONE"},
{SER_EV_STATE_IN, "SER_EV_STATE_IN"},
{SER_EV_STATE_OUT, "SER_EV_STATE_OUT"},
- {SER_EV_L1_RESET, "SER_EV_L1_RESET"},
+ {SER_EV_L1_RESET_PREPARE, "SER_EV_L1_RESET_PREPARE pre-m0"},
+ {SER_EV_L1_RESET, "SER_EV_L1_RESET m1"},
{SER_EV_DO_RECOVERY, "SER_EV_DO_RECOVERY m3"},
{SER_EV_MAC_RESET_DONE, "SER_EV_MAC_RESET_DONE m5"},
{SER_EV_L2_RESET, "SER_EV_L2_RESET"},
{SER_EV_L2_RECFG_DONE, "SER_EV_L2_RECFG_DONE"},
{SER_EV_L2_RECFG_TIMEOUT, "SER_EV_L2_RECFG_TIMEOUT"},
+ {SER_EV_M1_TIMEOUT, "SER_EV_M1_TIMEOUT"},
{SER_EV_M3_TIMEOUT, "SER_EV_M3_TIMEOUT"},
{SER_EV_FW_M5_TIMEOUT, "SER_EV_FW_M5_TIMEOUT"},
{SER_EV_L0_RESET, "SER_EV_L0_RESET"},
@@ -668,6 +710,7 @@ static const struct event_ent ser_ev_tbl[] = {
static const struct state_ent ser_st_tbl[] = {
{SER_IDLE_ST, "SER_IDLE_ST", ser_idle_st_hdl},
+ {SER_L1_RESET_PRE_ST, "SER_L1_RESET_PRE_ST", ser_l1_reset_pre_st_hdl},
{SER_RESET_TRX_ST, "SER_RESET_TRX_ST", ser_reset_trx_st_hdl},
{SER_DO_HCI_ST, "SER_DO_HCI_ST", ser_do_hci_st_hdl},
{SER_L2_RESET_ST, "SER_L2_RESET_ST", ser_l2_reset_st_hdl}
@@ -713,6 +756,9 @@ int rtw89_ser_notify(struct rtw89_dev *rtwdev, u32 err)
rtw89_info(rtwdev, "SER catches error: 0x%x\n", err);
switch (err) {
+ case MAC_AX_ERR_L1_PREERR_DMAC: /* pre-M0 */
+ event = SER_EV_L1_RESET_PREPARE;
+ break;
case MAC_AX_ERR_L1_ERR_DMAC:
case MAC_AX_ERR_L0_PROMOTE_TO_L1:
event = SER_EV_L1_RESET; /* M1 */
diff --git a/drivers/net/wireless/realtek/rtw89/txrx.h b/drivers/net/wireless/realtek/rtw89/txrx.h
index 98eb9607cd21..ec96da36eacc 100644
--- a/drivers/net/wireless/realtek/rtw89/txrx.h
+++ b/drivers/net/wireless/realtek/rtw89/txrx.h
@@ -186,124 +186,64 @@
#define AX_RXD_BIP_KEYID BIT(27)
#define AX_RXD_BIP_ENC BIT(28)
-/* RX DESC helpers */
-/* Short Descriptor */
-#define RTW89_GET_RXWD_LONG_RXD(rxdesc) \
- le32_get_bits((rxdesc)->dword0, BIT(31))
-#define RTW89_GET_RXWD_DRV_INFO_SIZE(rxdesc) \
- le32_get_bits((rxdesc)->dword0, GENMASK(30, 28))
-#define RTW89_GET_RXWD_RPKT_TYPE(rxdesc) \
- le32_get_bits((rxdesc)->dword0, GENMASK(27, 24))
-#define RTW89_GET_RXWD_MAC_INFO_VALID(rxdesc) \
- le32_get_bits((rxdesc)->dword0, BIT(23))
-#define RTW89_GET_RXWD_BB_SEL(rxdesc) \
- le32_get_bits((rxdesc)->dword0, BIT(22))
-#define RTW89_GET_RXWD_HD_IV_LEN(rxdesc) \
- le32_get_bits((rxdesc)->dword0, GENMASK(21, 16))
-#define RTW89_GET_RXWD_SHIFT(rxdesc) \
- le32_get_bits((rxdesc)->dword0, GENMASK(15, 14))
-#define RTW89_GET_RXWD_PKT_SIZE(rxdesc) \
- le32_get_bits((rxdesc)->dword0, GENMASK(13, 0))
-#define RTW89_GET_RXWD_BW(rxdesc) \
- le32_get_bits((rxdesc)->dword1, GENMASK(31, 30))
-#define RTW89_GET_RXWD_BW_V1(rxdesc) \
- le32_get_bits((rxdesc)->dword1, GENMASK(31, 29))
-#define RTW89_GET_RXWD_GI_LTF(rxdesc) \
- le32_get_bits((rxdesc)->dword1, GENMASK(27, 25))
-#define RTW89_GET_RXWD_DATA_RATE(rxdesc) \
- le32_get_bits((rxdesc)->dword1, GENMASK(24, 16))
-#define RTW89_GET_RXWD_USER_ID(rxdesc) \
- le32_get_bits((rxdesc)->dword1, GENMASK(15, 8))
-#define RTW89_GET_RXWD_SR_EN(rxdesc) \
- le32_get_bits((rxdesc)->dword1, BIT(7))
-#define RTW89_GET_RXWD_PPDU_CNT(rxdesc) \
- le32_get_bits((rxdesc)->dword1, GENMASK(6, 4))
-#define RTW89_GET_RXWD_PPDU_TYPE(rxdesc) \
- le32_get_bits((rxdesc)->dword1, GENMASK(3, 0))
-#define RTW89_GET_RXWD_FREE_RUN_CNT(rxdesc) \
- le32_get_bits((rxdesc)->dword2, GENMASK(31, 0))
-#define RTW89_GET_RXWD_ICV_ERR(rxdesc) \
- le32_get_bits((rxdesc)->dword3, BIT(10))
-#define RTW89_GET_RXWD_CRC32_ERR(rxdesc) \
- le32_get_bits((rxdesc)->dword3, BIT(9))
-#define RTW89_GET_RXWD_HW_DEC(rxdesc) \
- le32_get_bits((rxdesc)->dword3, BIT(2))
-#define RTW89_GET_RXWD_SW_DEC(rxdesc) \
- le32_get_bits((rxdesc)->dword3, BIT(1))
-#define RTW89_GET_RXWD_A1_MATCH(rxdesc) \
- le32_get_bits((rxdesc)->dword3, BIT(0))
-
-/* Long Descriptor */
-#define RTW89_GET_RXWD_FRAG(rxdesc) \
- le32_get_bits((rxdesc)->dword4, GENMASK(31, 28))
-#define RTW89_GET_RXWD_SEQ(rxdesc) \
- le32_get_bits((rxdesc)->dword4, GENMASK(27, 16))
-#define RTW89_GET_RXWD_TYPE(rxdesc) \
- le32_get_bits((rxdesc)->dword4, GENMASK(1, 0))
-#define RTW89_GET_RXWD_ADDR_CAM_VLD(rxdesc) \
- le32_get_bits((rxdesc)->dword5, BIT(28))
-#define RTW89_GET_RXWD_RX_PL_ID(rxdesc) \
- le32_get_bits((rxdesc)->dword5, GENMASK(27, 24))
-#define RTW89_GET_RXWD_MAC_ID(rxdesc) \
- le32_get_bits((rxdesc)->dword5, GENMASK(23, 16))
-#define RTW89_GET_RXWD_ADDR_CAM_ID(rxdesc) \
- le32_get_bits((rxdesc)->dword5, GENMASK(15, 8))
-#define RTW89_GET_RXWD_SEC_CAM_ID(rxdesc) \
- le32_get_bits((rxdesc)->dword5, GENMASK(7, 0))
-
-#define RTW89_GET_RXINFO_USR_NUM(rpt) \
- le32_get_bits(*((const __le32 *)rpt), GENMASK(3, 0))
-#define RTW89_GET_RXINFO_FW_DEFINE(rpt) \
- le32_get_bits(*((const __le32 *)rpt), GENMASK(15, 8))
-#define RTW89_GET_RXINFO_LSIG_LEN(rpt) \
- le32_get_bits(*((const __le32 *)rpt), GENMASK(27, 16))
-#define RTW89_GET_RXINFO_IS_TO_SELF(rpt) \
- le32_get_bits(*((const __le32 *)rpt), BIT(28))
-#define RTW89_GET_RXINFO_RX_CNT_VLD(rpt) \
- le32_get_bits(*((const __le32 *)rpt), BIT(29))
-#define RTW89_GET_RXINFO_LONG_RXD(rpt) \
- le32_get_bits(*((const __le32 *)rpt), GENMASK(31, 30))
-#define RTW89_GET_RXINFO_SERVICE(rpt) \
- le32_get_bits(*((const __le32 *)(rpt) + 1), GENMASK(15, 0))
-#define RTW89_GET_RXINFO_PLCP_LEN(rpt) \
- le32_get_bits(*((const __le32 *)(rpt) + 1), GENMASK(23, 16))
-#define RTW89_GET_RXINFO_MAC_ID_VALID(rpt, usr) \
- le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(0))
-#define RTW89_GET_RXINFO_DATA(rpt, usr) \
- le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(1))
-#define RTW89_GET_RXINFO_CTRL(rpt, usr) \
- le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(2))
-#define RTW89_GET_RXINFO_MGMT(rpt, usr) \
- le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(3))
-#define RTW89_GET_RXINFO_BCM(rpt, usr) \
- le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(4))
-#define RTW89_GET_RXINFO_MACID(rpt, usr) \
- le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), GENMASK(15, 8))
-
-#define RTW89_GET_PHY_STS_IE_MAP(sts) \
- le32_get_bits(*((const __le32 *)(sts)), GENMASK(4, 0))
-#define RTW89_GET_PHY_STS_RSSI_A(sts) \
- le32_get_bits(*((const __le32 *)(sts) + 1), GENMASK(7, 0))
-#define RTW89_GET_PHY_STS_RSSI_B(sts) \
- le32_get_bits(*((const __le32 *)(sts) + 1), GENMASK(15, 8))
-#define RTW89_GET_PHY_STS_RSSI_C(sts) \
- le32_get_bits(*((const __le32 *)(sts) + 1), GENMASK(23, 16))
-#define RTW89_GET_PHY_STS_RSSI_D(sts) \
- le32_get_bits(*((const __le32 *)(sts) + 1), GENMASK(31, 24))
-#define RTW89_GET_PHY_STS_LEN(sts) \
- le32_get_bits(*((const __le32 *)sts), GENMASK(15, 8))
-#define RTW89_GET_PHY_STS_RSSI_AVG(sts) \
- le32_get_bits(*((const __le32 *)sts), GENMASK(31, 24))
-#define RTW89_GET_PHY_STS_IE_TYPE(ie) \
- le32_get_bits(*((const __le32 *)ie), GENMASK(4, 0))
-#define RTW89_GET_PHY_STS_IE_LEN(ie) \
- le32_get_bits(*((const __le32 *)ie), GENMASK(11, 5))
-#define RTW89_GET_PHY_STS_IE01_CH_IDX(ie) \
- le32_get_bits(*((const __le32 *)ie), GENMASK(23, 16))
-#define RTW89_GET_PHY_STS_IE01_FD_CFO(ie) \
- le32_get_bits(*((const __le32 *)(ie) + 1), GENMASK(19, 8))
-#define RTW89_GET_PHY_STS_IE01_PREMB_CFO(ie) \
- le32_get_bits(*((const __le32 *)(ie) + 1), GENMASK(31, 20))
+struct rtw89_rxinfo_user {
+ __le32 w0;
+};
+
+#define RTW89_RXINFO_USER_MAC_ID_VALID BIT(0)
+#define RTW89_RXINFO_USER_DATA BIT(1)
+#define RTW89_RXINFO_USER_CTRL BIT(2)
+#define RTW89_RXINFO_USER_MGMT BIT(3)
+#define RTW89_RXINFO_USER_BCM BIT(4)
+#define RTW89_RXINFO_USER_MACID GENMASK(15, 8)
+
+struct rtw89_rxinfo {
+ __le32 w0;
+ __le32 w1;
+ struct rtw89_rxinfo_user user[];
+} __packed;
+
+#define RTW89_RXINFO_W0_USR_NUM GENMASK(3, 0)
+#define RTW89_RXINFO_W0_FW_DEFINE GENMASK(15, 8)
+#define RTW89_RXINFO_W0_LSIG_LEN GENMASK(27, 16)
+#define RTW89_RXINFO_W0_IS_TO_SELF BIT(28)
+#define RTW89_RXINFO_W0_RX_CNT_VLD BIT(29)
+#define RTW89_RXINFO_W0_LONG_RXD GENMASK(31, 30)
+#define RTW89_RXINFO_W1_SERVICE GENMASK(15, 0)
+#define RTW89_RXINFO_W1_PLCP_LEN GENMASK(23, 16)
+
+struct rtw89_phy_sts_hdr {
+ __le32 w0;
+ __le32 w1;
+} __packed;
+
+#define RTW89_PHY_STS_HDR_W0_IE_MAP GENMASK(4, 0)
+#define RTW89_PHY_STS_HDR_W0_LEN GENMASK(15, 8)
+#define RTW89_PHY_STS_HDR_W0_RSSI_AVG GENMASK(31, 24)
+#define RTW89_PHY_STS_HDR_W1_RSSI_A GENMASK(7, 0)
+#define RTW89_PHY_STS_HDR_W1_RSSI_B GENMASK(15, 8)
+#define RTW89_PHY_STS_HDR_W1_RSSI_C GENMASK(23, 16)
+#define RTW89_PHY_STS_HDR_W1_RSSI_D GENMASK(31, 24)
+
+struct rtw89_phy_sts_iehdr {
+ __le32 w0;
+};
+
+#define RTW89_PHY_STS_IEHDR_TYPE GENMASK(4, 0)
+#define RTW89_PHY_STS_IEHDR_LEN GENMASK(11, 5)
+
+struct rtw89_phy_sts_ie0 {
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+} __packed;
+
+#define RTW89_PHY_STS_IE01_W0_CH_IDX GENMASK(23, 16)
+#define RTW89_PHY_STS_IE01_W1_FD_CFO GENMASK(19, 8)
+#define RTW89_PHY_STS_IE01_W1_PREMB_CFO GENMASK(31, 20)
+#define RTW89_PHY_STS_IE01_W2_AVG_SNR GENMASK(5, 0)
+#define RTW89_PHY_STS_IE01_W2_EVM_MAX GENMASK(15, 8)
+#define RTW89_PHY_STS_IE01_W2_EVM_MIN GENMASK(23, 16)
enum rtw89_tx_channel {
RTW89_TXCH_ACH0 = 0,
diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c
index 2ca8abb70f11..364e54622150 100644
--- a/drivers/net/wireless/realtek/rtw89/wow.c
+++ b/drivers/net/wireless/realtek/rtw89/wow.c
@@ -91,7 +91,7 @@ static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev)
u32 wow_reason_reg;
u8 reason;
- if (chip_id == RTL8852A || chip_id == RTL8852B)
+ if (chip_id == RTL8852A || chip_id == RTL8852B || chip_id == RTL8851B)
wow_reason_reg = R_AX_C2HREG_DATA3 + 3;
else
wow_reason_reg = R_AX_C2HREG_DATA3_V1 + 3;
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index d09998796ac0..1911fef3bbad 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -1463,10 +1463,8 @@ static void rsi_shutdown(struct device *dev)
rsi_dbg(ERR_ZONE, "SDIO Bus shutdown =====>\n");
- if (hw) {
- struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config;
-
- if (rsi_config_wowlan(adapter, wowlan))
+ if (hw && hw->wiphy && hw->wiphy->wowlan_config) {
+ if (rsi_config_wowlan(adapter, hw->wiphy->wowlan_config))
rsi_dbg(ERR_ZONE, "Failed to configure WoWLAN\n");
}
@@ -1481,9 +1479,6 @@ static void rsi_shutdown(struct device *dev)
if (sdev->write_fail)
rsi_dbg(INFO_ZONE, "###### Device is not ready #######\n");
- if (rsi_set_sdio_pm_caps(adapter))
- rsi_dbg(INFO_ZONE, "Setting power management caps failed\n");
-
rsi_dbg(INFO_ZONE, "***** RSI module shut down *****\n");
}
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index 89c7a1420381..f446fd0e8cd0 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -4,7 +4,7 @@
* Copyright (c) 2008, Jouni Malinen <j@w1.fi>
* Copyright (c) 2011, Javier Lopez <jlopex@gmail.com>
* Copyright (c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 - 2022 Intel Corporation
+ * Copyright (C) 2018 - 2023 Intel Corporation
*/
/*
@@ -582,8 +582,9 @@ static int mac80211_hwsim_vendor_cmd_test(struct wiphy *wiphy,
*/
/* Add vendor data */
- nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_TEST, val + 1);
-
+ err = nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_TEST, val + 1);
+ if (err)
+ return err;
/* Send the event - this will call nla_nest_end() */
cfg80211_vendor_event(skb, GFP_KERNEL);
}
@@ -1859,12 +1860,12 @@ mac80211_hwsim_select_tx_link(struct mac80211_hwsim_data *data,
struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
int i;
- if (!vif->valid_links)
+ if (!ieee80211_vif_is_mld(vif))
return &vif->bss_conf;
WARN_ON(is_multicast_ether_addr(hdr->addr1));
- if (WARN_ON_ONCE(!sta->valid_links))
+ if (WARN_ON_ONCE(!sta || !sta->valid_links))
return &vif->bss_conf;
for (i = 0; i < ARRAY_SIZE(vif->link_conf); i++) {
@@ -1940,7 +1941,14 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
hdr, &link_sta);
}
- if (WARN_ON(!bss_conf)) {
+ if (unlikely(!bss_conf)) {
+ /* if it's an MLO STA, it might have deactivated all
+ * links temporarily - but we don't handle real PS in
+ * this code yet, so just drop the frame in that case
+ */
+ WARN(link != IEEE80211_LINK_UNSPECIFIED || !sta || !sta->mlo,
+ "link:%d, sta:%pM, sta->mlo:%d\n",
+ link, sta ? sta->addr : NULL, sta ? sta->mlo : -1);
ieee80211_free_txskb(hw, skb);
return;
}
@@ -2628,7 +2636,8 @@ static int mac80211_hwsim_sta_state(struct ieee80211_hw *hw,
*/
if (vif->type == NL80211_IFTYPE_STATION &&
new_state == IEEE80211_STA_AUTHORIZED && !sta->tdls)
- ieee80211_set_active_links_async(vif, vif->valid_links);
+ ieee80211_set_active_links_async(vif,
+ ieee80211_vif_usable_links(vif));
return 0;
}
diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.c b/drivers/net/wwan/iosm/iosm_ipc_imem.c
index 829515a601b3..635301d677e1 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_imem.c
+++ b/drivers/net/wwan/iosm/iosm_ipc_imem.c
@@ -4,6 +4,7 @@
*/
#include <linux/delay.h>
+#include <linux/pm_runtime.h>
#include "iosm_ipc_chnl_cfg.h"
#include "iosm_ipc_devlink.h"
@@ -631,6 +632,11 @@ static void ipc_imem_run_state_worker(struct work_struct *instance)
/* Complete all memory stores after setting bit */
smp_mb__after_atomic();
+ if (ipc_imem->pcie->pci->device == INTEL_CP_DEVICE_7560_ID) {
+ pm_runtime_mark_last_busy(ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_imem->dev);
+ }
+
return;
err_ipc_mux_deinit:
@@ -1234,6 +1240,7 @@ void ipc_imem_cleanup(struct iosm_imem *ipc_imem)
/* forward MDM_NOT_READY to listeners */
ipc_uevent_send(ipc_imem->dev, UEVENT_MDM_NOT_READY);
+ pm_runtime_get_sync(ipc_imem->dev);
hrtimer_cancel(&ipc_imem->td_alloc_timer);
hrtimer_cancel(&ipc_imem->tdupdate_timer);
@@ -1419,6 +1426,16 @@ struct iosm_imem *ipc_imem_init(struct iosm_pcie *pcie, unsigned int device_id,
set_bit(IOSM_DEVLINK_INIT, &ipc_imem->flag);
}
+
+ if (!pm_runtime_enabled(ipc_imem->dev))
+ pm_runtime_enable(ipc_imem->dev);
+
+ pm_runtime_set_autosuspend_delay(ipc_imem->dev,
+ IPC_MEM_AUTO_SUSPEND_DELAY_MS);
+ pm_runtime_use_autosuspend(ipc_imem->dev);
+ pm_runtime_allow(ipc_imem->dev);
+ pm_runtime_mark_last_busy(ipc_imem->dev);
+
return ipc_imem;
devlink_channel_fail:
ipc_devlink_deinit(ipc_imem->ipc_devlink);
diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.h b/drivers/net/wwan/iosm/iosm_ipc_imem.h
index e700dc8bfe0a..0144b45e2afb 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_imem.h
+++ b/drivers/net/wwan/iosm/iosm_ipc_imem.h
@@ -103,6 +103,8 @@ struct ipc_chnl_cfg;
#define FULLY_FUNCTIONAL 0
#define IOSM_DEVLINK_INIT 1
+#define IPC_MEM_AUTO_SUSPEND_DELAY_MS 5000
+
/* List of the supported UL/DL pipes. */
enum ipc_mem_pipes {
IPC_MEM_PIPE_0 = 0,
@@ -140,17 +142,6 @@ enum ipc_channel_state {
IMEM_CHANNEL_CLOSING,
};
-/* Time Unit */
-enum ipc_time_unit {
- IPC_SEC = 0,
- IPC_MILLI_SEC = 1,
- IPC_MICRO_SEC = 2,
- IPC_NANO_SEC = 3,
- IPC_PICO_SEC = 4,
- IPC_FEMTO_SEC = 5,
- IPC_ATTO_SEC = 6,
-};
-
/**
* enum ipc_ctype - Enum defining supported channel type needed for control
* /IP traffic.
@@ -204,7 +195,6 @@ enum ipc_hp_identifier {
* @pipe_nr: Pipe identification number
* @irq: Interrupt vector
* @dir: Direction of data stream in pipe
- * @td_tag: Unique tag of the buffer queued
* @buf_size: Buffer size (in bytes) for preallocated
* buffers (for DL pipes)
* @nr_of_queued_entries: Aueued number of entries
@@ -224,7 +214,6 @@ struct ipc_pipe {
u32 pipe_nr;
u32 irq;
enum ipc_mem_pipe_dir dir;
- u32 td_tag;
u32 buf_size;
u16 nr_of_queued_entries;
u8 is_open:1;
diff --git a/drivers/net/wwan/iosm/iosm_ipc_mux.h b/drivers/net/wwan/iosm/iosm_ipc_mux.h
index 9968bb885c1f..17ca8d1f9397 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_mux.h
+++ b/drivers/net/wwan/iosm/iosm_ipc_mux.h
@@ -333,9 +333,7 @@ struct mux_acb {
* @wwan_q_offset: This will hold the offset of the given instance
* Useful while passing or receiving packets from
* wwan/imem layer.
- * @adb_finish_timer: Timer for forcefully finishing the ADB
* @acb_tx_sequence_nr: Sequence number for the ACB header.
- * @params: user configurable parameters
* @adb_tx_sequence_nr: Sequence number for ADB header
* @acc_adb_size: Statistic data for logging
* @acc_payload_size: Statistic data for logging
@@ -367,9 +365,7 @@ struct iosm_mux {
long long ul_data_pend_bytes;
struct mux_acb acb;
int wwan_q_offset;
- struct hrtimer adb_finish_timer;
u16 acb_tx_sequence_nr;
- struct ipc_params *params;
u16 adb_tx_sequence_nr;
unsigned long long acc_adb_size;
unsigned long long acc_payload_size;
diff --git a/drivers/net/wwan/iosm/iosm_ipc_pcie.c b/drivers/net/wwan/iosm/iosm_ipc_pcie.c
index 04517bd3325a..3a259c9abefd 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_pcie.c
+++ b/drivers/net/wwan/iosm/iosm_ipc_pcie.c
@@ -6,6 +6,7 @@
#include <linux/acpi.h>
#include <linux/bitfield.h>
#include <linux/module.h>
+#include <linux/pm_runtime.h>
#include <net/rtnetlink.h>
#include "iosm_ipc_imem.h"
@@ -437,7 +438,8 @@ static int __maybe_unused ipc_pcie_resume_cb(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(iosm_ipc_pm, ipc_pcie_suspend_cb, ipc_pcie_resume_cb);
+static DEFINE_RUNTIME_DEV_PM_OPS(iosm_ipc_pm, ipc_pcie_suspend_cb,
+ ipc_pcie_resume_cb, NULL);
static struct pci_driver iosm_ipc_driver = {
.name = KBUILD_MODNAME,
diff --git a/drivers/net/wwan/iosm/iosm_ipc_port.c b/drivers/net/wwan/iosm/iosm_ipc_port.c
index 5d5b4183e14a..2ba1ddca3945 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_port.c
+++ b/drivers/net/wwan/iosm/iosm_ipc_port.c
@@ -3,6 +3,8 @@
* Copyright (C) 2020-21 Intel Corporation.
*/
+#include <linux/pm_runtime.h>
+
#include "iosm_ipc_chnl_cfg.h"
#include "iosm_ipc_imem_ops.h"
#include "iosm_ipc_port.h"
@@ -13,12 +15,16 @@ static int ipc_port_ctrl_start(struct wwan_port *port)
struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port);
int ret = 0;
+ pm_runtime_get_sync(ipc_port->ipc_imem->dev);
ipc_port->channel = ipc_imem_sys_port_open(ipc_port->ipc_imem,
ipc_port->chl_id,
IPC_HP_CDEV_OPEN);
if (!ipc_port->channel)
ret = -EIO;
+ pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev);
+
return ret;
}
@@ -27,15 +33,24 @@ static void ipc_port_ctrl_stop(struct wwan_port *port)
{
struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port);
+ pm_runtime_get_sync(ipc_port->ipc_imem->dev);
ipc_imem_sys_port_close(ipc_port->ipc_imem, ipc_port->channel);
+ pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev);
}
/* transfer control data to modem */
static int ipc_port_ctrl_tx(struct wwan_port *port, struct sk_buff *skb)
{
struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port);
+ int ret;
- return ipc_imem_sys_cdev_write(ipc_port, skb);
+ pm_runtime_get_sync(ipc_port->ipc_imem->dev);
+ ret = ipc_imem_sys_cdev_write(ipc_port, skb);
+ pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev);
+
+ return ret;
}
static const struct wwan_port_ops ipc_wwan_ctrl_ops = {
diff --git a/drivers/net/wwan/iosm/iosm_ipc_trace.c b/drivers/net/wwan/iosm/iosm_ipc_trace.c
index eeecfa3d10c5..4368373797b6 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_trace.c
+++ b/drivers/net/wwan/iosm/iosm_ipc_trace.c
@@ -3,7 +3,9 @@
* Copyright (C) 2020-2021 Intel Corporation.
*/
+#include <linux/pm_runtime.h>
#include <linux/wwan.h>
+
#include "iosm_ipc_trace.h"
/* sub buffer size and number of sub buffer */
@@ -97,6 +99,8 @@ static ssize_t ipc_trace_ctrl_file_write(struct file *filp,
if (ret)
return ret;
+ pm_runtime_get_sync(ipc_trace->ipc_imem->dev);
+
mutex_lock(&ipc_trace->trc_mutex);
if (val == TRACE_ENABLE && ipc_trace->mode != TRACE_ENABLE) {
ipc_trace->channel = ipc_imem_sys_port_open(ipc_trace->ipc_imem,
@@ -117,6 +121,10 @@ static ssize_t ipc_trace_ctrl_file_write(struct file *filp,
ret = count;
unlock:
mutex_unlock(&ipc_trace->trc_mutex);
+
+ pm_runtime_mark_last_busy(ipc_trace->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_trace->ipc_imem->dev);
+
return ret;
}
diff --git a/drivers/net/wwan/iosm/iosm_ipc_wwan.c b/drivers/net/wwan/iosm/iosm_ipc_wwan.c
index 4c9022a93e01..93d17de08786 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_wwan.c
+++ b/drivers/net/wwan/iosm/iosm_ipc_wwan.c
@@ -6,6 +6,7 @@
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
#include <linux/if_link.h>
+#include <linux/pm_runtime.h>
#include <linux/rtnetlink.h>
#include <linux/wwan.h>
#include <net/pkt_sched.h>
@@ -18,8 +19,6 @@
#define IOSM_IP_TYPE_IPV4 0x40
#define IOSM_IP_TYPE_IPV6 0x60
-#define IOSM_IF_ID_PAYLOAD 2
-
/**
* struct iosm_netdev_priv - netdev WWAN driver specific private data
* @ipc_wwan: Pointer to iosm_wwan struct
@@ -53,11 +52,13 @@ static int ipc_wwan_link_open(struct net_device *netdev)
struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev);
struct iosm_wwan *ipc_wwan = priv->ipc_wwan;
int if_id = priv->if_id;
+ int ret = 0;
if (if_id < IP_MUX_SESSION_START ||
if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist))
return -EINVAL;
+ pm_runtime_get_sync(ipc_wwan->ipc_imem->dev);
/* get channel id */
priv->ch_id = ipc_imem_sys_wwan_open(ipc_wwan->ipc_imem, if_id);
@@ -65,7 +66,8 @@ static int ipc_wwan_link_open(struct net_device *netdev)
dev_err(ipc_wwan->dev,
"cannot connect wwan0 & id %d to the IPC mem layer",
if_id);
- return -ENODEV;
+ ret = -ENODEV;
+ goto err_out;
}
/* enable tx path, DL data may follow */
@@ -74,7 +76,11 @@ static int ipc_wwan_link_open(struct net_device *netdev)
dev_dbg(ipc_wwan->dev, "Channel id %d allocated to if_id %d",
priv->ch_id, priv->if_id);
- return 0;
+err_out:
+ pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev);
+
+ return ret;
}
/* Bring-down the wwan net link */
@@ -84,9 +90,12 @@ static int ipc_wwan_link_stop(struct net_device *netdev)
netif_stop_queue(netdev);
+ pm_runtime_get_sync(priv->ipc_wwan->ipc_imem->dev);
ipc_imem_sys_wwan_close(priv->ipc_wwan->ipc_imem, priv->if_id,
priv->ch_id);
priv->ch_id = -1;
+ pm_runtime_mark_last_busy(priv->ipc_wwan->ipc_imem->dev);
+ pm_runtime_put_autosuspend(priv->ipc_wwan->ipc_imem->dev);
return 0;
}
@@ -108,6 +117,7 @@ static netdev_tx_t ipc_wwan_link_transmit(struct sk_buff *skb,
if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist))
return -EINVAL;
+ pm_runtime_get(ipc_wwan->ipc_imem->dev);
/* Send the SKB to device for transmission */
ret = ipc_imem_sys_wwan_transmit(ipc_wwan->ipc_imem,
if_id, priv->ch_id, skb);
@@ -121,9 +131,14 @@ static netdev_tx_t ipc_wwan_link_transmit(struct sk_buff *skb,
ret = NETDEV_TX_BUSY;
dev_err(ipc_wwan->dev, "unable to push packets");
} else {
+ pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev);
goto exit;
}
+ pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev);
+
return ret;
exit:
diff --git a/drivers/net/wwan/t7xx/t7xx_hif_cldma.c b/drivers/net/wwan/t7xx/t7xx_hif_cldma.c
index aec3a18d44bd..7162bf38a8c9 100644
--- a/drivers/net/wwan/t7xx/t7xx_hif_cldma.c
+++ b/drivers/net/wwan/t7xx/t7xx_hif_cldma.c
@@ -1293,9 +1293,9 @@ int t7xx_cldma_init(struct cldma_ctrl *md_ctrl)
for (i = 0; i < CLDMA_TXQ_NUM; i++) {
md_cd_queue_struct_init(&md_ctrl->txq[i], md_ctrl, MTK_TX, i);
md_ctrl->txq[i].worker =
- alloc_workqueue("md_hif%d_tx%d_worker",
- WQ_UNBOUND | WQ_MEM_RECLAIM | (i ? 0 : WQ_HIGHPRI),
- 1, md_ctrl->hif_id, i);
+ alloc_ordered_workqueue("md_hif%d_tx%d_worker",
+ WQ_MEM_RECLAIM | (i ? 0 : WQ_HIGHPRI),
+ md_ctrl->hif_id, i);
if (!md_ctrl->txq[i].worker)
goto err_workqueue;
@@ -1306,9 +1306,10 @@ int t7xx_cldma_init(struct cldma_ctrl *md_ctrl)
md_cd_queue_struct_init(&md_ctrl->rxq[i], md_ctrl, MTK_RX, i);
INIT_WORK(&md_ctrl->rxq[i].cldma_work, t7xx_cldma_rx_done);
- md_ctrl->rxq[i].worker = alloc_workqueue("md_hif%d_rx%d_worker",
- WQ_UNBOUND | WQ_MEM_RECLAIM,
- 1, md_ctrl->hif_id, i);
+ md_ctrl->rxq[i].worker =
+ alloc_ordered_workqueue("md_hif%d_rx%d_worker",
+ WQ_MEM_RECLAIM,
+ md_ctrl->hif_id, i);
if (!md_ctrl->rxq[i].worker)
goto err_workqueue;
}
diff --git a/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c b/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c
index 46514208d4f9..8dab025a088a 100644
--- a/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c
+++ b/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c
@@ -618,8 +618,9 @@ int t7xx_dpmaif_txq_init(struct dpmaif_tx_queue *txq)
return ret;
}
- txq->worker = alloc_workqueue("md_dpmaif_tx%d_worker", WQ_UNBOUND | WQ_MEM_RECLAIM |
- (txq->index ? 0 : WQ_HIGHPRI), 1, txq->index);
+ txq->worker = alloc_ordered_workqueue("md_dpmaif_tx%d_worker",
+ WQ_MEM_RECLAIM | (txq->index ? 0 : WQ_HIGHPRI),
+ txq->index);
if (!txq->worker)
return -ENOMEM;
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index c1501f41e2d8..88f760a7cbc3 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -396,7 +396,7 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
struct gnttab_map_grant_ref *gop = queue->tx_map_ops + *map_ops;
struct xen_netif_tx_request *txp = first;
- nr_slots = shinfo->nr_frags + 1;
+ nr_slots = shinfo->nr_frags + frag_overflow + 1;
copy_count(skb) = 0;
XENVIF_TX_CB(skb)->split_mask = 0;
@@ -462,8 +462,8 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
}
}
- for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots;
- shinfo->nr_frags++, gop++) {
+ for (shinfo->nr_frags = 0; nr_slots > 0 && shinfo->nr_frags < MAX_SKB_FRAGS;
+ shinfo->nr_frags++, gop++, nr_slots--) {
index = pending_index(queue->pending_cons++);
pending_idx = queue->pending_ring[index];
xenvif_tx_create_map_op(queue, pending_idx, txp,
@@ -476,12 +476,12 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
txp++;
}
- if (frag_overflow) {
+ if (nr_slots > 0) {
shinfo = skb_shinfo(nskb);
frags = shinfo->frags;
- for (shinfo->nr_frags = 0; shinfo->nr_frags < frag_overflow;
+ for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots;
shinfo->nr_frags++, txp++, gop++) {
index = pending_index(queue->pending_cons++);
pending_idx = queue->pending_ring[index];
@@ -492,6 +492,11 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
}
skb_shinfo(skb)->frag_list = nskb;
+ } else if (nskb) {
+ /* A frag_list skb was allocated but it is no longer needed
+ * because enough slots were converted to copy ops above.
+ */
+ kfree_skb(nskb);
}
(*copy_ops) = cop - queue->tx_copy_ops;
@@ -689,7 +694,7 @@ static void xenvif_fill_frags(struct xenvif_queue *queue, struct sk_buff *skb)
prev_pending_idx = pending_idx;
txp = &queue->pending_tx_info[pending_idx].req;
- page = virt_to_page(idx_to_kaddr(queue, pending_idx));
+ page = virt_to_page((void *)idx_to_kaddr(queue, pending_idx));
__skb_fill_page_desc(skb, i, page, txp->offset, txp->size);
skb->len += txp->size;
skb->data_len += txp->size;
@@ -1128,9 +1133,7 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s
BUG();
offset += len;
- __skb_frag_set_page(&frags[i], page);
- skb_frag_off_set(&frags[i], 0);
- skb_frag_size_set(&frags[i], len);
+ skb_frag_fill_page_desc(&frags[i], page, 0, len);
}
/* Release all the original (foreign) frags. */
diff --git a/drivers/nfc/fdp/i2c.c b/drivers/nfc/fdp/i2c.c
index 1e0f2297f9c6..c1896a1d978c 100644
--- a/drivers/nfc/fdp/i2c.c
+++ b/drivers/nfc/fdp/i2c.c
@@ -359,7 +359,7 @@ static struct i2c_driver fdp_nci_i2c_driver = {
.name = FDP_I2C_DRIVER_NAME,
.acpi_match_table = fdp_nci_i2c_acpi_match,
},
- .probe_new = fdp_nci_i2c_probe,
+ .probe = fdp_nci_i2c_probe,
.remove = fdp_nci_i2c_remove,
};
module_i2c_driver(fdp_nci_i2c_driver);
diff --git a/drivers/nfc/microread/i2c.c b/drivers/nfc/microread/i2c.c
index e72b358a2a12..642df4e0ce24 100644
--- a/drivers/nfc/microread/i2c.c
+++ b/drivers/nfc/microread/i2c.c
@@ -286,7 +286,7 @@ static struct i2c_driver microread_i2c_driver = {
.driver = {
.name = MICROREAD_I2C_DRIVER_NAME,
},
- .probe_new = microread_i2c_probe,
+ .probe = microread_i2c_probe,
.remove = microread_i2c_remove,
.id_table = microread_i2c_id,
};
diff --git a/drivers/nfc/nfcmrvl/i2c.c b/drivers/nfc/nfcmrvl/i2c.c
index 164e2ab859fd..74553134c1b1 100644
--- a/drivers/nfc/nfcmrvl/i2c.c
+++ b/drivers/nfc/nfcmrvl/i2c.c
@@ -258,7 +258,7 @@ static const struct i2c_device_id nfcmrvl_i2c_id_table[] = {
MODULE_DEVICE_TABLE(i2c, nfcmrvl_i2c_id_table);
static struct i2c_driver nfcmrvl_i2c_driver = {
- .probe_new = nfcmrvl_i2c_probe,
+ .probe = nfcmrvl_i2c_probe,
.id_table = nfcmrvl_i2c_id_table,
.remove = nfcmrvl_i2c_remove,
.driver = {
diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c
index d4c299be7949..dca25a0c2f33 100644
--- a/drivers/nfc/nxp-nci/i2c.c
+++ b/drivers/nfc/nxp-nci/i2c.c
@@ -97,8 +97,8 @@ static int nxp_nci_i2c_fw_read(struct nxp_nci_i2c_phy *phy,
struct sk_buff **skb)
{
struct i2c_client *client = phy->i2c_dev;
- u16 header;
size_t frame_len;
+ __be16 header;
int r;
r = i2c_master_recv(client, (u8 *) &header, NXP_NCI_FW_HDR_LEN);
@@ -348,7 +348,7 @@ static struct i2c_driver nxp_nci_i2c_driver = {
.acpi_match_table = ACPI_PTR(acpi_id),
.of_match_table = of_nxp_nci_i2c_match,
},
- .probe_new = nxp_nci_i2c_probe,
+ .probe = nxp_nci_i2c_probe,
.id_table = nxp_nci_i2c_id_table,
.remove = nxp_nci_i2c_remove,
};
diff --git a/drivers/nfc/pn533/i2c.c b/drivers/nfc/pn533/i2c.c
index 1503a98f0405..438ab9553f7a 100644
--- a/drivers/nfc/pn533/i2c.c
+++ b/drivers/nfc/pn533/i2c.c
@@ -259,7 +259,7 @@ static struct i2c_driver pn533_i2c_driver = {
.name = PN533_I2C_DRIVER_NAME,
.of_match_table = of_match_ptr(of_pn533_i2c_match),
},
- .probe_new = pn533_i2c_probe,
+ .probe = pn533_i2c_probe,
.id_table = pn533_i2c_id_table,
.remove = pn533_i2c_remove,
};
diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c
index 8b0d910bee06..3f6d74832bac 100644
--- a/drivers/nfc/pn544/i2c.c
+++ b/drivers/nfc/pn544/i2c.c
@@ -953,7 +953,7 @@ static struct i2c_driver pn544_hci_i2c_driver = {
.of_match_table = of_match_ptr(of_pn544_i2c_match),
.acpi_match_table = ACPI_PTR(pn544_hci_i2c_acpi_match),
},
- .probe_new = pn544_hci_i2c_probe,
+ .probe = pn544_hci_i2c_probe,
.id_table = pn544_hci_i2c_id_table,
.remove = pn544_hci_i2c_remove,
};
diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c
index 2517ae71f9a4..720d4a72493c 100644
--- a/drivers/nfc/s3fwrn5/i2c.c
+++ b/drivers/nfc/s3fwrn5/i2c.c
@@ -261,7 +261,7 @@ static struct i2c_driver s3fwrn5_i2c_driver = {
.name = S3FWRN5_I2C_DRIVER_NAME,
.of_match_table = of_match_ptr(of_s3fwrn5_i2c_match),
},
- .probe_new = s3fwrn5_i2c_probe,
+ .probe = s3fwrn5_i2c_probe,
.remove = s3fwrn5_i2c_remove,
.id_table = s3fwrn5_i2c_id_table,
};
diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c
index 6b5eed8a1fbe..d20a337e90b4 100644
--- a/drivers/nfc/st-nci/i2c.c
+++ b/drivers/nfc/st-nci/i2c.c
@@ -283,7 +283,7 @@ static struct i2c_driver st_nci_i2c_driver = {
.of_match_table = of_match_ptr(of_st_nci_i2c_match),
.acpi_match_table = ACPI_PTR(st_nci_i2c_acpi_match),
},
- .probe_new = st_nci_i2c_probe,
+ .probe = st_nci_i2c_probe,
.id_table = st_nci_i2c_id_table,
.remove = st_nci_i2c_remove,
};
diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c
index 55f7a2391bb1..064a63db288b 100644
--- a/drivers/nfc/st21nfca/i2c.c
+++ b/drivers/nfc/st21nfca/i2c.c
@@ -597,7 +597,7 @@ static struct i2c_driver st21nfca_hci_i2c_driver = {
.of_match_table = of_match_ptr(of_st21nfca_i2c_match),
.acpi_match_table = ACPI_PTR(st21nfca_hci_i2c_acpi_match),
},
- .probe_new = st21nfca_hci_i2c_probe,
+ .probe = st21nfca_hci_i2c_probe,
.id_table = st21nfca_hci_i2c_id_table,
.remove = st21nfca_hci_i2c_remove,
};
diff --git a/drivers/ntb/hw/amd/ntb_hw_amd.c b/drivers/ntb/hw/amd/ntb_hw_amd.c
index 04550b1f984c..4940b6301d83 100644
--- a/drivers/ntb/hw/amd/ntb_hw_amd.c
+++ b/drivers/ntb/hw/amd/ntb_hw_amd.c
@@ -941,7 +941,7 @@ static void ndev_init_debugfs(struct amd_ntb_dev *ndev)
ndev->debugfs_dir =
debugfs_create_dir(pci_name(ndev->ntb.pdev),
debugfs_dir);
- if (!ndev->debugfs_dir)
+ if (IS_ERR(ndev->debugfs_dir))
ndev->debugfs_info = NULL;
else
ndev->debugfs_info =
@@ -1194,7 +1194,6 @@ static int amd_ntb_init_pci(struct amd_ntb_dev *ndev,
return 0;
err_dma_mask:
- pci_clear_master(pdev);
pci_release_regions(pdev);
err_pci_regions:
pci_disable_device(pdev);
@@ -1209,7 +1208,6 @@ static void amd_ntb_deinit_pci(struct amd_ntb_dev *ndev)
pci_iounmap(pdev, ndev->self_mmio);
- pci_clear_master(pdev);
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
@@ -1338,12 +1336,17 @@ static struct pci_driver amd_ntb_pci_driver = {
static int __init amd_ntb_pci_driver_init(void)
{
+ int ret;
pr_info("%s %s\n", NTB_DESC, NTB_VER);
if (debugfs_initialized())
debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
- return pci_register_driver(&amd_ntb_pci_driver);
+ ret = pci_register_driver(&amd_ntb_pci_driver);
+ if (ret)
+ debugfs_remove_recursive(debugfs_dir);
+
+ return ret;
}
module_init(amd_ntb_pci_driver_init);
diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
index 3ece49cb18ff..b640aa0bf45e 100644
--- a/drivers/ntb/hw/epf/ntb_hw_epf.c
+++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
@@ -591,7 +591,7 @@ static int ntb_epf_init_pci(struct ntb_epf_dev *ndev,
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (ret) {
dev_err(dev, "Cannot set DMA mask\n");
- goto err_dma_mask;
+ goto err_pci_regions;
}
dev_warn(&pdev->dev, "Cannot DMA highmem\n");
}
@@ -599,14 +599,14 @@ static int ntb_epf_init_pci(struct ntb_epf_dev *ndev,
ndev->ctrl_reg = pci_iomap(pdev, ndev->ctrl_reg_bar, 0);
if (!ndev->ctrl_reg) {
ret = -EIO;
- goto err_dma_mask;
+ goto err_pci_regions;
}
if (ndev->peer_spad_reg_bar) {
ndev->peer_spad_reg = pci_iomap(pdev, ndev->peer_spad_reg_bar, 0);
if (!ndev->peer_spad_reg) {
ret = -EIO;
- goto err_dma_mask;
+ goto err_pci_regions;
}
} else {
spad_sz = 4 * readl(ndev->ctrl_reg + NTB_EPF_SPAD_COUNT);
@@ -617,14 +617,11 @@ static int ntb_epf_init_pci(struct ntb_epf_dev *ndev,
ndev->db_reg = pci_iomap(pdev, ndev->db_reg_bar, 0);
if (!ndev->db_reg) {
ret = -EIO;
- goto err_dma_mask;
+ goto err_pci_regions;
}
return 0;
-err_dma_mask:
- pci_clear_master(pdev);
-
err_pci_regions:
pci_disable_device(pdev);
@@ -642,7 +639,6 @@ static void ntb_epf_deinit_pci(struct ntb_epf_dev *ndev)
pci_iounmap(pdev, ndev->peer_spad_reg);
pci_iounmap(pdev, ndev->db_reg);
- pci_clear_master(pdev);
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
diff --git a/drivers/ntb/hw/idt/ntb_hw_idt.c b/drivers/ntb/hw/idt/ntb_hw_idt.c
index 0ed6f809ff2e..48823b53ede3 100644
--- a/drivers/ntb/hw/idt/ntb_hw_idt.c
+++ b/drivers/ntb/hw/idt/ntb_hw_idt.c
@@ -2651,20 +2651,18 @@ static int idt_init_pci(struct idt_ntb_dev *ndev)
}
/*
- * Enable the device advanced error reporting. It's not critical to
+ * The PCI core enables device error reporting. It's not critical to
* have AER disabled in the kernel.
+ *
+ * Cleanup nonfatal error status before getting to init.
*/
- ret = pci_enable_pcie_error_reporting(pdev);
- if (ret != 0)
- dev_warn(&pdev->dev, "PCIe AER capability disabled\n");
- else /* Cleanup nonfatal error status before getting to init */
- pci_aer_clear_nonfatal_status(pdev);
+ pci_aer_clear_nonfatal_status(pdev);
/* First enable the PCI device */
ret = pcim_enable_device(pdev);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to enable PCIe device\n");
- goto err_disable_aer;
+ return ret;
}
/*
@@ -2692,8 +2690,6 @@ static int idt_init_pci(struct idt_ntb_dev *ndev)
err_clear_master:
pci_clear_master(pdev);
-err_disable_aer:
- (void)pci_disable_pcie_error_reporting(pdev);
return ret;
}
@@ -2714,9 +2710,6 @@ static void idt_deinit_pci(struct idt_ntb_dev *ndev)
/* Clear the bus master disabling the Request TLPs translation */
pci_clear_master(pdev);
- /* Disable the AER capability */
- (void)pci_disable_pcie_error_reporting(pdev);
-
dev_dbg(&pdev->dev, "NT-function PCIe interface cleared");
}
@@ -2891,6 +2884,7 @@ static struct pci_driver idt_pci_driver = {
static int __init idt_pci_driver_init(void)
{
+ int ret;
pr_info("%s %s\n", NTB_DESC, NTB_VER);
/* Create the top DebugFS directory if the FS is initialized */
@@ -2898,7 +2892,11 @@ static int __init idt_pci_driver_init(void)
dbgfs_topdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
/* Register the NTB hardware driver to handle the PCI device */
- return pci_register_driver(&idt_pci_driver);
+ ret = pci_register_driver(&idt_pci_driver);
+ if (ret)
+ debugfs_remove_recursive(dbgfs_topdir);
+
+ return ret;
}
module_init(idt_pci_driver_init);
diff --git a/drivers/ntb/hw/intel/ntb_hw_gen1.c b/drivers/ntb/hw/intel/ntb_hw_gen1.c
index 84772013812b..9ab836d0d4f1 100644
--- a/drivers/ntb/hw/intel/ntb_hw_gen1.c
+++ b/drivers/ntb/hw/intel/ntb_hw_gen1.c
@@ -1791,7 +1791,6 @@ static int intel_ntb_init_pci(struct intel_ntb_dev *ndev, struct pci_dev *pdev)
err_mmio:
err_dma_mask:
- pci_clear_master(pdev);
pci_release_regions(pdev);
err_pci_regions:
pci_disable_device(pdev);
@@ -1808,7 +1807,6 @@ static void intel_ntb_deinit_pci(struct intel_ntb_dev *ndev)
pci_iounmap(pdev, ndev->peer_mmio);
pci_iounmap(pdev, ndev->self_mmio);
- pci_clear_master(pdev);
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
@@ -2064,12 +2062,17 @@ static struct pci_driver intel_ntb_pci_driver = {
static int __init intel_ntb_pci_driver_init(void)
{
+ int ret;
pr_info("%s %s\n", NTB_DESC, NTB_VER);
if (debugfs_initialized())
debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
- return pci_register_driver(&intel_ntb_pci_driver);
+ ret = pci_register_driver(&intel_ntb_pci_driver);
+ if (ret)
+ debugfs_remove_recursive(debugfs_dir);
+
+ return ret;
}
module_init(intel_ntb_pci_driver_init);
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index a9b97ebc71ac..2abd2235bbca 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -410,7 +410,7 @@ int ntb_transport_register_client_dev(char *device_name)
rc = device_register(dev);
if (rc) {
- kfree(client_dev);
+ put_device(dev);
goto err;
}
diff --git a/drivers/ntb/test/ntb_tool.c b/drivers/ntb/test/ntb_tool.c
index 5ee0afa621a9..eeeb4b1c97d2 100644
--- a/drivers/ntb/test/ntb_tool.c
+++ b/drivers/ntb/test/ntb_tool.c
@@ -998,6 +998,8 @@ static int tool_init_mws(struct tool_ctx *tc)
tc->peers[pidx].outmws =
devm_kcalloc(&tc->ntb->dev, tc->peers[pidx].outmw_cnt,
sizeof(*tc->peers[pidx].outmws), GFP_KERNEL);
+ if (tc->peers[pidx].outmws == NULL)
+ return -ENOMEM;
for (widx = 0; widx < tc->peers[pidx].outmw_cnt; widx++) {
tc->peers[pidx].outmws[widx].pidx = pidx;
diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index f70ba58dbc55..ab0f32b901c8 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -32,6 +32,13 @@
/* Globals */
+/* The "nubus.populate_procfs" parameter makes slot resources available in
+ * procfs. It's deprecated and disabled by default because procfs is no longer
+ * thought to be suitable for that and some board ROMs make it too expensive.
+ */
+bool nubus_populate_procfs;
+module_param_named(populate_procfs, nubus_populate_procfs, bool, 0);
+
LIST_HEAD(nubus_func_rsrcs);
/* Meaning of "bytelanes":
@@ -572,9 +579,9 @@ nubus_get_functional_resource(struct nubus_board *board, int slot,
nubus_proc_add_rsrc(dir.procdir, &ent);
break;
default:
- /* Local/Private resources have their own
- function */
- nubus_get_private_resource(fres, dir.procdir, &ent);
+ if (nubus_populate_procfs)
+ nubus_get_private_resource(fres, dir.procdir,
+ &ent);
}
}
diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c
index 1fd667852271..e7a347db708c 100644
--- a/drivers/nubus/proc.c
+++ b/drivers/nubus/proc.c
@@ -55,7 +55,7 @@ struct proc_dir_entry *nubus_proc_add_board(struct nubus_board *board)
{
char name[2];
- if (!proc_bus_nubus_dir)
+ if (!proc_bus_nubus_dir || !nubus_populate_procfs)
return NULL;
snprintf(name, sizeof(name), "%x", board->slot);
return proc_mkdir(name, proc_bus_nubus_dir);
@@ -72,9 +72,10 @@ struct proc_dir_entry *nubus_proc_add_rsrc_dir(struct proc_dir_entry *procdir,
char name[9];
int lanes = board->lanes;
- if (!procdir)
+ if (!procdir || !nubus_populate_procfs)
return NULL;
snprintf(name, sizeof(name), "%x", ent->type);
+ remove_proc_subtree(name, procdir);
return proc_mkdir_data(name, 0555, procdir, (void *)lanes);
}
@@ -137,6 +138,18 @@ static int nubus_proc_rsrc_show(struct seq_file *m, void *v)
return 0;
}
+static int nubus_rsrc_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, nubus_proc_rsrc_show, inode);
+}
+
+static const struct proc_ops nubus_rsrc_proc_ops = {
+ .proc_open = nubus_rsrc_proc_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = single_release,
+};
+
void nubus_proc_add_rsrc_mem(struct proc_dir_entry *procdir,
const struct nubus_dirent *ent,
unsigned int size)
@@ -144,7 +157,7 @@ void nubus_proc_add_rsrc_mem(struct proc_dir_entry *procdir,
char name[9];
struct nubus_proc_pde_data *pded;
- if (!procdir)
+ if (!procdir || !nubus_populate_procfs)
return;
snprintf(name, sizeof(name), "%x", ent->type);
@@ -152,8 +165,9 @@ void nubus_proc_add_rsrc_mem(struct proc_dir_entry *procdir,
pded = nubus_proc_alloc_pde_data(nubus_dirptr(ent), size);
else
pded = NULL;
- proc_create_single_data(name, S_IFREG | 0444, procdir,
- nubus_proc_rsrc_show, pded);
+ remove_proc_subtree(name, procdir);
+ proc_create_data(name, S_IFREG | 0444, procdir,
+ &nubus_rsrc_proc_ops, pded);
}
void nubus_proc_add_rsrc(struct proc_dir_entry *procdir,
@@ -162,13 +176,14 @@ void nubus_proc_add_rsrc(struct proc_dir_entry *procdir,
char name[9];
unsigned char *data = (unsigned char *)ent->data;
- if (!procdir)
+ if (!procdir || !nubus_populate_procfs)
return;
snprintf(name, sizeof(name), "%x", ent->type);
- proc_create_single_data(name, S_IFREG | 0444, procdir,
- nubus_proc_rsrc_show,
- nubus_proc_alloc_pde_data(data, 0));
+ remove_proc_subtree(name, procdir);
+ proc_create_data(name, S_IFREG | 0444, procdir,
+ &nubus_rsrc_proc_ops,
+ nubus_proc_alloc_pde_data(data, 0));
}
/*
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 e27202d22c7d..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
+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/auth.c b/drivers/nvme/host/auth.c
index ea16a0aba679..daf5d144a8ea 100644
--- a/drivers/nvme/host/auth.c
+++ b/drivers/nvme/host/auth.c
@@ -30,18 +30,18 @@ struct nvme_dhchap_queue_context {
u32 s2;
u16 transaction;
u8 status;
+ u8 dhgroup_id;
u8 hash_id;
size_t hash_len;
- u8 dhgroup_id;
u8 c1[64];
u8 c2[64];
u8 response[64];
u8 *host_response;
u8 *ctrl_key;
- int ctrl_key_len;
u8 *host_key;
- int host_key_len;
u8 *sess_key;
+ int ctrl_key_len;
+ int host_key_len;
int sess_key_len;
};
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 3ec38e2b9173..f3a01b79148c 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -237,7 +237,7 @@ int nvme_delete_ctrl(struct nvme_ctrl *ctrl)
}
EXPORT_SYMBOL_GPL(nvme_delete_ctrl);
-static void nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl)
+void nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl)
{
/*
* Keep a reference until nvme_do_delete_ctrl() complete,
@@ -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);
@@ -1635,12 +1638,12 @@ static void nvme_ns_release(struct nvme_ns *ns)
nvme_put_ns(ns);
}
-static int nvme_open(struct block_device *bdev, fmode_t mode)
+static int nvme_open(struct gendisk *disk, blk_mode_t mode)
{
- return nvme_ns_open(bdev->bd_disk->private_data);
+ return nvme_ns_open(disk->private_data);
}
-static void nvme_release(struct gendisk *disk, fmode_t mode)
+static void nvme_release(struct gendisk *disk)
{
nvme_ns_release(disk->private_data);
}
@@ -1879,7 +1882,7 @@ static void nvme_update_disk_info(struct gendisk *disk,
struct nvme_ns *ns, struct nvme_id_ns *id)
{
sector_t capacity = nvme_lba_to_sect(ns, le64_to_cpu(id->nsze));
- unsigned short bs = 1 << ns->lba_shift;
+ u32 bs = 1U << ns->lba_shift;
u32 atomic_bs, phys_bs, io_opt = 0;
/*
@@ -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)
@@ -2300,7 +2156,7 @@ static int nvme_report_zones(struct gendisk *disk, sector_t sector,
#define nvme_report_zones NULL
#endif /* CONFIG_BLK_DEV_ZONED */
-static const struct block_device_operations nvme_bdev_ops = {
+const struct block_device_operations nvme_bdev_ops = {
.owner = THIS_MODULE,
.ioctl = nvme_ioctl,
.compat_ioctl = blkdev_compat_ptr_ioctl,
@@ -2835,75 +2691,6 @@ static struct nvme_subsystem *__nvme_find_get_subsystem(const char *subsysnqn)
return NULL;
}
-#define SUBSYS_ATTR_RO(_name, _mode, _show) \
- struct device_attribute subsys_attr_##_name = \
- __ATTR(_name, _mode, _show, NULL)
-
-static ssize_t nvme_subsys_show_nqn(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct nvme_subsystem *subsys =
- container_of(dev, struct nvme_subsystem, dev);
-
- return sysfs_emit(buf, "%s\n", subsys->subnqn);
-}
-static SUBSYS_ATTR_RO(subsysnqn, S_IRUGO, nvme_subsys_show_nqn);
-
-static ssize_t nvme_subsys_show_type(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct nvme_subsystem *subsys =
- container_of(dev, struct nvme_subsystem, dev);
-
- switch (subsys->subtype) {
- case NVME_NQN_DISC:
- return sysfs_emit(buf, "discovery\n");
- case NVME_NQN_NVME:
- return sysfs_emit(buf, "nvm\n");
- default:
- return sysfs_emit(buf, "reserved\n");
- }
-}
-static SUBSYS_ATTR_RO(subsystype, S_IRUGO, nvme_subsys_show_type);
-
-#define nvme_subsys_show_str_function(field) \
-static ssize_t subsys_##field##_show(struct device *dev, \
- struct device_attribute *attr, char *buf) \
-{ \
- struct nvme_subsystem *subsys = \
- container_of(dev, struct nvme_subsystem, dev); \
- return sysfs_emit(buf, "%.*s\n", \
- (int)sizeof(subsys->field), subsys->field); \
-} \
-static SUBSYS_ATTR_RO(field, S_IRUGO, subsys_##field##_show);
-
-nvme_subsys_show_str_function(model);
-nvme_subsys_show_str_function(serial);
-nvme_subsys_show_str_function(firmware_rev);
-
-static struct attribute *nvme_subsys_attrs[] = {
- &subsys_attr_model.attr,
- &subsys_attr_serial.attr,
- &subsys_attr_firmware_rev.attr,
- &subsys_attr_subsysnqn.attr,
- &subsys_attr_subsystype.attr,
-#ifdef CONFIG_NVME_MULTIPATH
- &subsys_attr_iopolicy.attr,
-#endif
- NULL,
-};
-
-static const struct attribute_group nvme_subsys_attrs_group = {
- .attrs = nvme_subsys_attrs,
-};
-
-static const struct attribute_group *nvme_subsys_attrs_groups[] = {
- &nvme_subsys_attrs_group,
- NULL,
-};
-
static inline bool nvme_discovery_ctrl(struct nvme_ctrl *ctrl)
{
return ctrl->opts && ctrl->opts->discovery_nqn;
@@ -3108,7 +2895,8 @@ static int nvme_init_non_mdts_limits(struct nvme_ctrl *ctrl)
ctrl->max_zeroes_sectors = 0;
if (ctrl->subsys->subtype != NVME_NQN_NVME ||
- nvme_ctrl_limited_cns(ctrl))
+ nvme_ctrl_limited_cns(ctrl) ||
+ test_bit(NVME_CTRL_SKIP_ID_CNS_CS, &ctrl->flags))
return 0;
id = kzalloc(sizeof(*id), GFP_KERNEL);
@@ -3130,6 +2918,8 @@ static int nvme_init_non_mdts_limits(struct nvme_ctrl *ctrl)
ctrl->max_zeroes_sectors = nvme_mps_to_sectors(ctrl, id->wzsl);
free_data:
+ if (ret > 0)
+ set_bit(NVME_CTRL_SKIP_ID_CNS_CS, &ctrl->flags);
kfree(id);
return ret;
}
@@ -3390,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;
@@ -3437,586 +3228,6 @@ static const struct file_operations nvme_dev_fops = {
.uring_cmd = nvme_dev_uring_cmd,
};
-static ssize_t nvme_sysfs_reset(struct device *dev,
- struct device_attribute *attr, const char *buf,
- size_t count)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
- int ret;
-
- ret = nvme_reset_ctrl_sync(ctrl);
- if (ret < 0)
- return ret;
- return count;
-}
-static DEVICE_ATTR(reset_controller, S_IWUSR, NULL, nvme_sysfs_reset);
-
-static ssize_t nvme_sysfs_rescan(struct device *dev,
- struct device_attribute *attr, const char *buf,
- size_t count)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
-
- nvme_queue_scan(ctrl);
- return count;
-}
-static DEVICE_ATTR(rescan_controller, S_IWUSR, NULL, nvme_sysfs_rescan);
-
-static inline struct nvme_ns_head *dev_to_ns_head(struct device *dev)
-{
- struct gendisk *disk = dev_to_disk(dev);
-
- if (disk->fops == &nvme_bdev_ops)
- return nvme_get_ns_from_dev(dev)->head;
- else
- return disk->private_data;
-}
-
-static ssize_t wwid_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct nvme_ns_head *head = dev_to_ns_head(dev);
- struct nvme_ns_ids *ids = &head->ids;
- struct nvme_subsystem *subsys = head->subsys;
- int serial_len = sizeof(subsys->serial);
- int model_len = sizeof(subsys->model);
-
- if (!uuid_is_null(&ids->uuid))
- return sysfs_emit(buf, "uuid.%pU\n", &ids->uuid);
-
- if (memchr_inv(ids->nguid, 0, sizeof(ids->nguid)))
- return sysfs_emit(buf, "eui.%16phN\n", ids->nguid);
-
- if (memchr_inv(ids->eui64, 0, sizeof(ids->eui64)))
- return sysfs_emit(buf, "eui.%8phN\n", ids->eui64);
-
- while (serial_len > 0 && (subsys->serial[serial_len - 1] == ' ' ||
- subsys->serial[serial_len - 1] == '\0'))
- serial_len--;
- while (model_len > 0 && (subsys->model[model_len - 1] == ' ' ||
- subsys->model[model_len - 1] == '\0'))
- model_len--;
-
- return sysfs_emit(buf, "nvme.%04x-%*phN-%*phN-%08x\n", subsys->vendor_id,
- serial_len, subsys->serial, model_len, subsys->model,
- head->ns_id);
-}
-static DEVICE_ATTR_RO(wwid);
-
-static ssize_t nguid_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- return sysfs_emit(buf, "%pU\n", dev_to_ns_head(dev)->ids.nguid);
-}
-static DEVICE_ATTR_RO(nguid);
-
-static ssize_t uuid_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct nvme_ns_ids *ids = &dev_to_ns_head(dev)->ids;
-
- /* For backward compatibility expose the NGUID to userspace if
- * we have no UUID set
- */
- if (uuid_is_null(&ids->uuid)) {
- dev_warn_ratelimited(dev,
- "No UUID available providing old NGUID\n");
- return sysfs_emit(buf, "%pU\n", ids->nguid);
- }
- return sysfs_emit(buf, "%pU\n", &ids->uuid);
-}
-static DEVICE_ATTR_RO(uuid);
-
-static ssize_t eui_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- return sysfs_emit(buf, "%8ph\n", dev_to_ns_head(dev)->ids.eui64);
-}
-static DEVICE_ATTR_RO(eui);
-
-static ssize_t nsid_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- return sysfs_emit(buf, "%d\n", dev_to_ns_head(dev)->ns_id);
-}
-static DEVICE_ATTR_RO(nsid);
-
-static struct attribute *nvme_ns_id_attrs[] = {
- &dev_attr_wwid.attr,
- &dev_attr_uuid.attr,
- &dev_attr_nguid.attr,
- &dev_attr_eui.attr,
- &dev_attr_nsid.attr,
-#ifdef CONFIG_NVME_MULTIPATH
- &dev_attr_ana_grpid.attr,
- &dev_attr_ana_state.attr,
-#endif
- NULL,
-};
-
-static umode_t nvme_ns_id_attrs_are_visible(struct kobject *kobj,
- struct attribute *a, int n)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct nvme_ns_ids *ids = &dev_to_ns_head(dev)->ids;
-
- if (a == &dev_attr_uuid.attr) {
- if (uuid_is_null(&ids->uuid) &&
- !memchr_inv(ids->nguid, 0, sizeof(ids->nguid)))
- return 0;
- }
- if (a == &dev_attr_nguid.attr) {
- if (!memchr_inv(ids->nguid, 0, sizeof(ids->nguid)))
- return 0;
- }
- if (a == &dev_attr_eui.attr) {
- if (!memchr_inv(ids->eui64, 0, sizeof(ids->eui64)))
- return 0;
- }
-#ifdef CONFIG_NVME_MULTIPATH
- if (a == &dev_attr_ana_grpid.attr || a == &dev_attr_ana_state.attr) {
- if (dev_to_disk(dev)->fops != &nvme_bdev_ops) /* per-path attr */
- return 0;
- if (!nvme_ctrl_use_ana(nvme_get_ns_from_dev(dev)->ctrl))
- return 0;
- }
-#endif
- return a->mode;
-}
-
-static const struct attribute_group nvme_ns_id_attr_group = {
- .attrs = nvme_ns_id_attrs,
- .is_visible = nvme_ns_id_attrs_are_visible,
-};
-
-const struct attribute_group *nvme_ns_id_attr_groups[] = {
- &nvme_ns_id_attr_group,
- NULL,
-};
-
-#define nvme_show_str_function(field) \
-static ssize_t field##_show(struct device *dev, \
- struct device_attribute *attr, char *buf) \
-{ \
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev); \
- return sysfs_emit(buf, "%.*s\n", \
- (int)sizeof(ctrl->subsys->field), ctrl->subsys->field); \
-} \
-static DEVICE_ATTR(field, S_IRUGO, field##_show, NULL);
-
-nvme_show_str_function(model);
-nvme_show_str_function(serial);
-nvme_show_str_function(firmware_rev);
-
-#define nvme_show_int_function(field) \
-static ssize_t field##_show(struct device *dev, \
- struct device_attribute *attr, char *buf) \
-{ \
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev); \
- return sysfs_emit(buf, "%d\n", ctrl->field); \
-} \
-static DEVICE_ATTR(field, S_IRUGO, field##_show, NULL);
-
-nvme_show_int_function(cntlid);
-nvme_show_int_function(numa_node);
-nvme_show_int_function(queue_count);
-nvme_show_int_function(sqsize);
-nvme_show_int_function(kato);
-
-static ssize_t nvme_sysfs_delete(struct device *dev,
- struct device_attribute *attr, const char *buf,
- size_t count)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
-
- if (!test_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags))
- return -EBUSY;
-
- if (device_remove_file_self(dev, attr))
- nvme_delete_ctrl_sync(ctrl);
- return count;
-}
-static DEVICE_ATTR(delete_controller, S_IWUSR, NULL, nvme_sysfs_delete);
-
-static ssize_t nvme_sysfs_show_transport(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
-
- return sysfs_emit(buf, "%s\n", ctrl->ops->name);
-}
-static DEVICE_ATTR(transport, S_IRUGO, nvme_sysfs_show_transport, NULL);
-
-static ssize_t nvme_sysfs_show_state(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
- static const char *const state_name[] = {
- [NVME_CTRL_NEW] = "new",
- [NVME_CTRL_LIVE] = "live",
- [NVME_CTRL_RESETTING] = "resetting",
- [NVME_CTRL_CONNECTING] = "connecting",
- [NVME_CTRL_DELETING] = "deleting",
- [NVME_CTRL_DELETING_NOIO]= "deleting (no IO)",
- [NVME_CTRL_DEAD] = "dead",
- };
-
- if ((unsigned)ctrl->state < ARRAY_SIZE(state_name) &&
- state_name[ctrl->state])
- return sysfs_emit(buf, "%s\n", state_name[ctrl->state]);
-
- return sysfs_emit(buf, "unknown state\n");
-}
-
-static DEVICE_ATTR(state, S_IRUGO, nvme_sysfs_show_state, NULL);
-
-static ssize_t nvme_sysfs_show_subsysnqn(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
-
- return sysfs_emit(buf, "%s\n", ctrl->subsys->subnqn);
-}
-static DEVICE_ATTR(subsysnqn, S_IRUGO, nvme_sysfs_show_subsysnqn, NULL);
-
-static ssize_t nvme_sysfs_show_hostnqn(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
-
- return sysfs_emit(buf, "%s\n", ctrl->opts->host->nqn);
-}
-static DEVICE_ATTR(hostnqn, S_IRUGO, nvme_sysfs_show_hostnqn, NULL);
-
-static ssize_t nvme_sysfs_show_hostid(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
-
- return sysfs_emit(buf, "%pU\n", &ctrl->opts->host->id);
-}
-static DEVICE_ATTR(hostid, S_IRUGO, nvme_sysfs_show_hostid, NULL);
-
-static ssize_t nvme_sysfs_show_address(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
-
- return ctrl->ops->get_address(ctrl, buf, PAGE_SIZE);
-}
-static DEVICE_ATTR(address, S_IRUGO, nvme_sysfs_show_address, NULL);
-
-static ssize_t nvme_ctrl_loss_tmo_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
- struct nvmf_ctrl_options *opts = ctrl->opts;
-
- if (ctrl->opts->max_reconnects == -1)
- return sysfs_emit(buf, "off\n");
- return sysfs_emit(buf, "%d\n",
- opts->max_reconnects * opts->reconnect_delay);
-}
-
-static ssize_t nvme_ctrl_loss_tmo_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
- struct nvmf_ctrl_options *opts = ctrl->opts;
- int ctrl_loss_tmo, err;
-
- err = kstrtoint(buf, 10, &ctrl_loss_tmo);
- if (err)
- return -EINVAL;
-
- if (ctrl_loss_tmo < 0)
- opts->max_reconnects = -1;
- else
- opts->max_reconnects = DIV_ROUND_UP(ctrl_loss_tmo,
- opts->reconnect_delay);
- return count;
-}
-static DEVICE_ATTR(ctrl_loss_tmo, S_IRUGO | S_IWUSR,
- nvme_ctrl_loss_tmo_show, nvme_ctrl_loss_tmo_store);
-
-static ssize_t nvme_ctrl_reconnect_delay_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
-
- if (ctrl->opts->reconnect_delay == -1)
- return sysfs_emit(buf, "off\n");
- return sysfs_emit(buf, "%d\n", ctrl->opts->reconnect_delay);
-}
-
-static ssize_t nvme_ctrl_reconnect_delay_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
- unsigned int v;
- int err;
-
- err = kstrtou32(buf, 10, &v);
- if (err)
- return err;
-
- ctrl->opts->reconnect_delay = v;
- return count;
-}
-static DEVICE_ATTR(reconnect_delay, S_IRUGO | S_IWUSR,
- nvme_ctrl_reconnect_delay_show, nvme_ctrl_reconnect_delay_store);
-
-static ssize_t nvme_ctrl_fast_io_fail_tmo_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
-
- if (ctrl->opts->fast_io_fail_tmo == -1)
- return sysfs_emit(buf, "off\n");
- return sysfs_emit(buf, "%d\n", ctrl->opts->fast_io_fail_tmo);
-}
-
-static ssize_t nvme_ctrl_fast_io_fail_tmo_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
- struct nvmf_ctrl_options *opts = ctrl->opts;
- int fast_io_fail_tmo, err;
-
- err = kstrtoint(buf, 10, &fast_io_fail_tmo);
- if (err)
- return -EINVAL;
-
- if (fast_io_fail_tmo < 0)
- opts->fast_io_fail_tmo = -1;
- else
- opts->fast_io_fail_tmo = fast_io_fail_tmo;
- return count;
-}
-static DEVICE_ATTR(fast_io_fail_tmo, S_IRUGO | S_IWUSR,
- nvme_ctrl_fast_io_fail_tmo_show, nvme_ctrl_fast_io_fail_tmo_store);
-
-static ssize_t cntrltype_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- static const char * const type[] = {
- [NVME_CTRL_IO] = "io\n",
- [NVME_CTRL_DISC] = "discovery\n",
- [NVME_CTRL_ADMIN] = "admin\n",
- };
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
-
- if (ctrl->cntrltype > NVME_CTRL_ADMIN || !type[ctrl->cntrltype])
- return sysfs_emit(buf, "reserved\n");
-
- return sysfs_emit(buf, type[ctrl->cntrltype]);
-}
-static DEVICE_ATTR_RO(cntrltype);
-
-static ssize_t dctype_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- static const char * const type[] = {
- [NVME_DCTYPE_NOT_REPORTED] = "none\n",
- [NVME_DCTYPE_DDC] = "ddc\n",
- [NVME_DCTYPE_CDC] = "cdc\n",
- };
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
-
- if (ctrl->dctype > NVME_DCTYPE_CDC || !type[ctrl->dctype])
- return sysfs_emit(buf, "reserved\n");
-
- return sysfs_emit(buf, type[ctrl->dctype]);
-}
-static DEVICE_ATTR_RO(dctype);
-
-#ifdef CONFIG_NVME_AUTH
-static ssize_t nvme_ctrl_dhchap_secret_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
- struct nvmf_ctrl_options *opts = ctrl->opts;
-
- if (!opts->dhchap_secret)
- return sysfs_emit(buf, "none\n");
- return sysfs_emit(buf, "%s\n", opts->dhchap_secret);
-}
-
-static ssize_t nvme_ctrl_dhchap_secret_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
- struct nvmf_ctrl_options *opts = ctrl->opts;
- char *dhchap_secret;
-
- if (!ctrl->opts->dhchap_secret)
- return -EINVAL;
- if (count < 7)
- return -EINVAL;
- if (memcmp(buf, "DHHC-1:", 7))
- return -EINVAL;
-
- dhchap_secret = kzalloc(count + 1, GFP_KERNEL);
- if (!dhchap_secret)
- return -ENOMEM;
- memcpy(dhchap_secret, buf, count);
- nvme_auth_stop(ctrl);
- if (strcmp(dhchap_secret, opts->dhchap_secret)) {
- struct nvme_dhchap_key *key, *host_key;
- int ret;
-
- ret = nvme_auth_generate_key(dhchap_secret, &key);
- if (ret)
- return ret;
- kfree(opts->dhchap_secret);
- opts->dhchap_secret = dhchap_secret;
- host_key = ctrl->host_key;
- mutex_lock(&ctrl->dhchap_auth_mutex);
- ctrl->host_key = key;
- mutex_unlock(&ctrl->dhchap_auth_mutex);
- nvme_auth_free_key(host_key);
- }
- /* Start re-authentication */
- dev_info(ctrl->device, "re-authenticating controller\n");
- queue_work(nvme_wq, &ctrl->dhchap_auth_work);
-
- return count;
-}
-static DEVICE_ATTR(dhchap_secret, S_IRUGO | S_IWUSR,
- nvme_ctrl_dhchap_secret_show, nvme_ctrl_dhchap_secret_store);
-
-static ssize_t nvme_ctrl_dhchap_ctrl_secret_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
- struct nvmf_ctrl_options *opts = ctrl->opts;
-
- if (!opts->dhchap_ctrl_secret)
- return sysfs_emit(buf, "none\n");
- return sysfs_emit(buf, "%s\n", opts->dhchap_ctrl_secret);
-}
-
-static ssize_t nvme_ctrl_dhchap_ctrl_secret_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
- struct nvmf_ctrl_options *opts = ctrl->opts;
- char *dhchap_secret;
-
- if (!ctrl->opts->dhchap_ctrl_secret)
- return -EINVAL;
- if (count < 7)
- return -EINVAL;
- if (memcmp(buf, "DHHC-1:", 7))
- return -EINVAL;
-
- dhchap_secret = kzalloc(count + 1, GFP_KERNEL);
- if (!dhchap_secret)
- return -ENOMEM;
- memcpy(dhchap_secret, buf, count);
- nvme_auth_stop(ctrl);
- if (strcmp(dhchap_secret, opts->dhchap_ctrl_secret)) {
- struct nvme_dhchap_key *key, *ctrl_key;
- int ret;
-
- ret = nvme_auth_generate_key(dhchap_secret, &key);
- if (ret)
- return ret;
- kfree(opts->dhchap_ctrl_secret);
- opts->dhchap_ctrl_secret = dhchap_secret;
- ctrl_key = ctrl->ctrl_key;
- mutex_lock(&ctrl->dhchap_auth_mutex);
- ctrl->ctrl_key = key;
- mutex_unlock(&ctrl->dhchap_auth_mutex);
- nvme_auth_free_key(ctrl_key);
- }
- /* Start re-authentication */
- dev_info(ctrl->device, "re-authenticating controller\n");
- queue_work(nvme_wq, &ctrl->dhchap_auth_work);
-
- return count;
-}
-static DEVICE_ATTR(dhchap_ctrl_secret, S_IRUGO | S_IWUSR,
- nvme_ctrl_dhchap_ctrl_secret_show, nvme_ctrl_dhchap_ctrl_secret_store);
-#endif
-
-static struct attribute *nvme_dev_attrs[] = {
- &dev_attr_reset_controller.attr,
- &dev_attr_rescan_controller.attr,
- &dev_attr_model.attr,
- &dev_attr_serial.attr,
- &dev_attr_firmware_rev.attr,
- &dev_attr_cntlid.attr,
- &dev_attr_delete_controller.attr,
- &dev_attr_transport.attr,
- &dev_attr_subsysnqn.attr,
- &dev_attr_address.attr,
- &dev_attr_state.attr,
- &dev_attr_numa_node.attr,
- &dev_attr_queue_count.attr,
- &dev_attr_sqsize.attr,
- &dev_attr_hostnqn.attr,
- &dev_attr_hostid.attr,
- &dev_attr_ctrl_loss_tmo.attr,
- &dev_attr_reconnect_delay.attr,
- &dev_attr_fast_io_fail_tmo.attr,
- &dev_attr_kato.attr,
- &dev_attr_cntrltype.attr,
- &dev_attr_dctype.attr,
-#ifdef CONFIG_NVME_AUTH
- &dev_attr_dhchap_secret.attr,
- &dev_attr_dhchap_ctrl_secret.attr,
-#endif
- NULL
-};
-
-static umode_t nvme_dev_attrs_are_visible(struct kobject *kobj,
- struct attribute *a, int n)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
-
- if (a == &dev_attr_delete_controller.attr && !ctrl->ops->delete_ctrl)
- return 0;
- if (a == &dev_attr_address.attr && !ctrl->ops->get_address)
- return 0;
- if (a == &dev_attr_hostnqn.attr && !ctrl->opts)
- return 0;
- if (a == &dev_attr_hostid.attr && !ctrl->opts)
- return 0;
- if (a == &dev_attr_ctrl_loss_tmo.attr && !ctrl->opts)
- return 0;
- if (a == &dev_attr_reconnect_delay.attr && !ctrl->opts)
- return 0;
- if (a == &dev_attr_fast_io_fail_tmo.attr && !ctrl->opts)
- return 0;
-#ifdef CONFIG_NVME_AUTH
- if (a == &dev_attr_dhchap_secret.attr && !ctrl->opts)
- return 0;
- if (a == &dev_attr_dhchap_ctrl_secret.attr && !ctrl->opts)
- return 0;
-#endif
-
- return a->mode;
-}
-
-const struct attribute_group nvme_dev_attrs_group = {
- .attrs = nvme_dev_attrs,
- .is_visible = nvme_dev_attrs_are_visible,
-};
-EXPORT_SYMBOL_GPL(nvme_dev_attrs_group);
-
-static const struct attribute_group *nvme_dev_attr_groups[] = {
- &nvme_dev_attrs_group,
- NULL,
-};
-
static struct nvme_ns_head *nvme_find_ns_head(struct nvme_ctrl *ctrl,
unsigned nsid)
{
@@ -4220,10 +3431,40 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
ret = nvme_global_check_duplicate_ids(ctrl->subsys, &info->ids);
if (ret) {
- dev_err(ctrl->device,
- "globally duplicate IDs for nsid %d\n", info->nsid);
+ /*
+ * We've found two different namespaces on two different
+ * subsystems that report the same ID. This is pretty nasty
+ * for anything that actually requires unique device
+ * identification. In the kernel we need this for multipathing,
+ * and in user space the /dev/disk/by-id/ links rely on it.
+ *
+ * If the device also claims to be multi-path capable back off
+ * here now and refuse the probe the second device as this is a
+ * recipe for data corruption. If not this is probably a
+ * cheap consumer device if on the PCIe bus, so let the user
+ * proceed and use the shiny toy, but warn that with changing
+ * probing order (which due to our async probing could just be
+ * device taking longer to startup) the other device could show
+ * up at any time.
+ */
nvme_print_device_info(ctrl);
- return ret;
+ if ((ns->ctrl->ops->flags & NVME_F_FABRICS) || /* !PCIe */
+ ((ns->ctrl->subsys->cmic & NVME_CTRL_CMIC_MULTI_CTRL) &&
+ info->is_shared)) {
+ dev_err(ctrl->device,
+ "ignoring nsid %d because of duplicate IDs\n",
+ info->nsid);
+ return ret;
+ }
+
+ dev_err(ctrl->device,
+ "clearing duplicate IDs for nsid %d\n", info->nsid);
+ dev_err(ctrl->device,
+ "use of /dev/disk/by-id/ may cause data corruption\n");
+ memset(&info->ids.nguid, 0, sizeof(info->ids.nguid));
+ memset(&info->ids.uuid, 0, sizeof(info->ids.uuid));
+ memset(&info->ids.eui64, 0, sizeof(info->ids.eui64));
+ ctrl->quirks |= NVME_QUIRK_BOGUS_NID;
}
mutex_lock(&ctrl->subsys->lock);
@@ -4256,7 +3497,7 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
goto out_put_ns_head;
}
- if (!multipath && !list_empty(&head->list)) {
+ if (!multipath) {
dev_warn(ctrl->device,
"Found shared namespace %d, but multipathing not supported.\n",
info->nsid);
@@ -4357,7 +3598,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info)
* instance as shared namespaces will show up as multiple block
* devices.
*/
- if (ns->head->disk) {
+ if (nvme_ns_head_multipath(ns->head)) {
sprintf(disk->disk_name, "nvme%dc%dn%d", ctrl->subsys->instance,
ctrl->instance, ns->head->instance);
disk->flags |= GENHD_FL_HIDDEN;
@@ -4692,6 +3933,12 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl)
*/
nvme_mpath_clear_ctrl_paths(ctrl);
+ /*
+ * Unquiesce io queues so any pending IO won't hang, especially
+ * those submitted from scan work
+ */
+ nvme_unquiesce_io_queues(ctrl);
+
/* prevent racing with ns scanning */
flush_work(&ctrl->scan_work);
@@ -4701,10 +3948,8 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl)
* removing the namespaces' disks; fail all the queues now to avoid
* potentially having to clean up the failed sync later.
*/
- if (ctrl->state == NVME_CTRL_DEAD) {
+ if (ctrl->state == NVME_CTRL_DEAD)
nvme_mark_namespaces_dead(ctrl);
- nvme_unquiesce_io_queues(ctrl);
- }
/* this is a no-op when called from the controller reset handler */
nvme_change_ctrl_state(ctrl, NVME_CTRL_DELETING_NOIO);
@@ -5243,6 +4488,8 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
return 0;
out_free_cdev:
+ nvme_fault_inject_fini(&ctrl->fault_inject);
+ dev_pm_qos_hide_latency_tolerance(ctrl->device);
cdev_device_del(&ctrl->cdev, ctrl->device);
out_free_name:
nvme_put_ctrl(ctrl);
diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c
index 0069ebff85df..8175d49f2909 100644
--- a/drivers/nvme/host/fabrics.c
+++ b/drivers/nvme/host/fabrics.c
@@ -21,35 +21,60 @@ static DEFINE_MUTEX(nvmf_hosts_mutex);
static struct nvmf_host *nvmf_default_host;
-static struct nvmf_host *__nvmf_host_find(const char *hostnqn)
+static struct nvmf_host *nvmf_host_alloc(const char *hostnqn, uuid_t *id)
{
struct nvmf_host *host;
- list_for_each_entry(host, &nvmf_hosts, list) {
- if (!strcmp(host->nqn, hostnqn))
- return host;
- }
+ host = kmalloc(sizeof(*host), GFP_KERNEL);
+ if (!host)
+ return NULL;
- return NULL;
+ kref_init(&host->ref);
+ uuid_copy(&host->id, id);
+ strscpy(host->nqn, hostnqn, NVMF_NQN_SIZE);
+
+ return host;
}
-static struct nvmf_host *nvmf_host_add(const char *hostnqn)
+static struct nvmf_host *nvmf_host_add(const char *hostnqn, uuid_t *id)
{
struct nvmf_host *host;
mutex_lock(&nvmf_hosts_mutex);
- host = __nvmf_host_find(hostnqn);
- if (host) {
- kref_get(&host->ref);
- goto out_unlock;
+
+ /*
+ * We have defined a host as how it is perceived by the target.
+ * Therefore, we don't allow different Host NQNs with the same Host ID.
+ * Similarly, we do not allow the usage of the same Host NQN with
+ * different Host IDs. This'll maintain unambiguous host identification.
+ */
+ list_for_each_entry(host, &nvmf_hosts, list) {
+ bool same_hostnqn = !strcmp(host->nqn, hostnqn);
+ bool same_hostid = uuid_equal(&host->id, id);
+
+ if (same_hostnqn && same_hostid) {
+ kref_get(&host->ref);
+ goto out_unlock;
+ }
+ if (same_hostnqn) {
+ pr_err("found same hostnqn %s but different hostid %pUb\n",
+ hostnqn, id);
+ host = ERR_PTR(-EINVAL);
+ goto out_unlock;
+ }
+ if (same_hostid) {
+ pr_err("found same hostid %pUb but different hostnqn %s\n",
+ id, hostnqn);
+ host = ERR_PTR(-EINVAL);
+ goto out_unlock;
+ }
}
- host = kmalloc(sizeof(*host), GFP_KERNEL);
- if (!host)
+ host = nvmf_host_alloc(hostnqn, id);
+ if (!host) {
+ host = ERR_PTR(-ENOMEM);
goto out_unlock;
-
- kref_init(&host->ref);
- strscpy(host->nqn, hostnqn, NVMF_NQN_SIZE);
+ }
list_add_tail(&host->list, &nvmf_hosts);
out_unlock:
@@ -60,16 +85,17 @@ out_unlock:
static struct nvmf_host *nvmf_host_default(void)
{
struct nvmf_host *host;
+ char nqn[NVMF_NQN_SIZE];
+ uuid_t id;
- host = kmalloc(sizeof(*host), GFP_KERNEL);
+ uuid_gen(&id);
+ snprintf(nqn, NVMF_NQN_SIZE,
+ "nqn.2014-08.org.nvmexpress:uuid:%pUb", &id);
+
+ host = nvmf_host_alloc(nqn, &id);
if (!host)
return NULL;
- kref_init(&host->ref);
- uuid_gen(&host->id);
- snprintf(host->nqn, NVMF_NQN_SIZE,
- "nqn.2014-08.org.nvmexpress:uuid:%pUb", &host->id);
-
mutex_lock(&nvmf_hosts_mutex);
list_add_tail(&host->list, &nvmf_hosts);
mutex_unlock(&nvmf_hosts_mutex);
@@ -349,6 +375,45 @@ static void nvmf_log_connect_error(struct nvme_ctrl *ctrl,
}
}
+static struct nvmf_connect_data *nvmf_connect_data_prep(struct nvme_ctrl *ctrl,
+ u16 cntlid)
+{
+ struct nvmf_connect_data *data;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return NULL;
+
+ uuid_copy(&data->hostid, &ctrl->opts->host->id);
+ data->cntlid = cpu_to_le16(cntlid);
+ strncpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE);
+ strncpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE);
+
+ return data;
+}
+
+static void nvmf_connect_cmd_prep(struct nvme_ctrl *ctrl, u16 qid,
+ struct nvme_command *cmd)
+{
+ cmd->connect.opcode = nvme_fabrics_command;
+ cmd->connect.fctype = nvme_fabrics_type_connect;
+ cmd->connect.qid = cpu_to_le16(qid);
+
+ if (qid) {
+ cmd->connect.sqsize = cpu_to_le16(ctrl->sqsize);
+ } else {
+ cmd->connect.sqsize = cpu_to_le16(NVME_AQ_DEPTH - 1);
+
+ /*
+ * set keep-alive timeout in seconds granularity (ms * 1000)
+ */
+ cmd->connect.kato = cpu_to_le32(ctrl->kato * 1000);
+ }
+
+ if (ctrl->opts->disable_sqflow)
+ cmd->connect.cattr |= NVME_CONNECT_DISABLE_SQFLOW;
+}
+
/**
* nvmf_connect_admin_queue() - NVMe Fabrics Admin Queue "Connect"
* API function.
@@ -377,28 +442,12 @@ int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl)
int ret;
u32 result;
- cmd.connect.opcode = nvme_fabrics_command;
- cmd.connect.fctype = nvme_fabrics_type_connect;
- cmd.connect.qid = 0;
- cmd.connect.sqsize = cpu_to_le16(NVME_AQ_DEPTH - 1);
-
- /*
- * Set keep-alive timeout in seconds granularity (ms * 1000)
- */
- cmd.connect.kato = cpu_to_le32(ctrl->kato * 1000);
-
- if (ctrl->opts->disable_sqflow)
- cmd.connect.cattr |= NVME_CONNECT_DISABLE_SQFLOW;
+ nvmf_connect_cmd_prep(ctrl, 0, &cmd);
- data = kzalloc(sizeof(*data), GFP_KERNEL);
+ data = nvmf_connect_data_prep(ctrl, 0xffff);
if (!data)
return -ENOMEM;
- uuid_copy(&data->hostid, &ctrl->opts->host->id);
- data->cntlid = cpu_to_le16(0xffff);
- strncpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE);
- strncpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE);
-
ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res,
data, sizeof(*data), NVME_QID_ANY, 1,
BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT);
@@ -468,23 +517,12 @@ int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid)
int ret;
u32 result;
- cmd.connect.opcode = nvme_fabrics_command;
- cmd.connect.fctype = nvme_fabrics_type_connect;
- cmd.connect.qid = cpu_to_le16(qid);
- cmd.connect.sqsize = cpu_to_le16(ctrl->sqsize);
+ nvmf_connect_cmd_prep(ctrl, qid, &cmd);
- if (ctrl->opts->disable_sqflow)
- cmd.connect.cattr |= NVME_CONNECT_DISABLE_SQFLOW;
-
- data = kzalloc(sizeof(*data), GFP_KERNEL);
+ data = nvmf_connect_data_prep(ctrl, ctrl->cntlid);
if (!data)
return -ENOMEM;
- uuid_copy(&data->hostid, &ctrl->opts->host->id);
- data->cntlid = cpu_to_le16(ctrl->cntlid);
- strncpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE);
- strncpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE);
-
ret = __nvme_submit_sync_cmd(ctrl->connect_q, &cmd, &res,
data, sizeof(*data), qid, 1,
BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT);
@@ -621,6 +659,7 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
size_t nqnlen = 0;
int ctrl_loss_tmo = NVMF_DEF_CTRL_LOSS_TMO;
uuid_t hostid;
+ char hostnqn[NVMF_NQN_SIZE];
/* Set defaults */
opts->queue_size = NVMF_DEF_QUEUE_SIZE;
@@ -637,7 +676,9 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
if (!options)
return -ENOMEM;
- uuid_gen(&hostid);
+ /* use default host if not given by user space */
+ uuid_copy(&hostid, &nvmf_default_host->id);
+ strscpy(hostnqn, nvmf_default_host->nqn, NVMF_NQN_SIZE);
while ((p = strsep(&o, ",\n")) != NULL) {
if (!*p)
@@ -783,12 +824,8 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
ret = -EINVAL;
goto out;
}
- opts->host = nvmf_host_add(p);
+ strscpy(hostnqn, p, NVMF_NQN_SIZE);
kfree(p);
- if (!opts->host) {
- ret = -ENOMEM;
- goto out;
- }
break;
case NVMF_OPT_RECONNECT_DELAY:
if (match_int(args, &token)) {
@@ -945,18 +982,94 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
opts->fast_io_fail_tmo, ctrl_loss_tmo);
}
- if (!opts->host) {
- kref_get(&nvmf_default_host->ref);
- opts->host = nvmf_default_host;
+ opts->host = nvmf_host_add(hostnqn, &hostid);
+ if (IS_ERR(opts->host)) {
+ ret = PTR_ERR(opts->host);
+ opts->host = NULL;
+ goto out;
}
- uuid_copy(&opts->host->id, &hostid);
-
out:
kfree(options);
return ret;
}
+void nvmf_set_io_queues(struct nvmf_ctrl_options *opts, u32 nr_io_queues,
+ u32 io_queues[HCTX_MAX_TYPES])
+{
+ if (opts->nr_write_queues && opts->nr_io_queues < nr_io_queues) {
+ /*
+ * separate read/write queues
+ * hand out dedicated default queues only after we have
+ * sufficient read queues.
+ */
+ io_queues[HCTX_TYPE_READ] = opts->nr_io_queues;
+ nr_io_queues -= io_queues[HCTX_TYPE_READ];
+ io_queues[HCTX_TYPE_DEFAULT] =
+ min(opts->nr_write_queues, nr_io_queues);
+ nr_io_queues -= io_queues[HCTX_TYPE_DEFAULT];
+ } else {
+ /*
+ * shared read/write queues
+ * either no write queues were requested, or we don't have
+ * sufficient queue count to have dedicated default queues.
+ */
+ io_queues[HCTX_TYPE_DEFAULT] =
+ min(opts->nr_io_queues, nr_io_queues);
+ nr_io_queues -= io_queues[HCTX_TYPE_DEFAULT];
+ }
+
+ if (opts->nr_poll_queues && nr_io_queues) {
+ /* map dedicated poll queues only if we have queues left */
+ io_queues[HCTX_TYPE_POLL] =
+ min(opts->nr_poll_queues, nr_io_queues);
+ }
+}
+EXPORT_SYMBOL_GPL(nvmf_set_io_queues);
+
+void nvmf_map_queues(struct blk_mq_tag_set *set, struct nvme_ctrl *ctrl,
+ u32 io_queues[HCTX_MAX_TYPES])
+{
+ struct nvmf_ctrl_options *opts = ctrl->opts;
+
+ if (opts->nr_write_queues && io_queues[HCTX_TYPE_READ]) {
+ /* separate read/write queues */
+ set->map[HCTX_TYPE_DEFAULT].nr_queues =
+ io_queues[HCTX_TYPE_DEFAULT];
+ set->map[HCTX_TYPE_DEFAULT].queue_offset = 0;
+ set->map[HCTX_TYPE_READ].nr_queues =
+ io_queues[HCTX_TYPE_READ];
+ set->map[HCTX_TYPE_READ].queue_offset =
+ io_queues[HCTX_TYPE_DEFAULT];
+ } else {
+ /* shared read/write queues */
+ set->map[HCTX_TYPE_DEFAULT].nr_queues =
+ io_queues[HCTX_TYPE_DEFAULT];
+ set->map[HCTX_TYPE_DEFAULT].queue_offset = 0;
+ set->map[HCTX_TYPE_READ].nr_queues =
+ io_queues[HCTX_TYPE_DEFAULT];
+ set->map[HCTX_TYPE_READ].queue_offset = 0;
+ }
+
+ blk_mq_map_queues(&set->map[HCTX_TYPE_DEFAULT]);
+ blk_mq_map_queues(&set->map[HCTX_TYPE_READ]);
+ if (opts->nr_poll_queues && io_queues[HCTX_TYPE_POLL]) {
+ /* map dedicated poll queues only if we have queues left */
+ set->map[HCTX_TYPE_POLL].nr_queues = io_queues[HCTX_TYPE_POLL];
+ set->map[HCTX_TYPE_POLL].queue_offset =
+ io_queues[HCTX_TYPE_DEFAULT] +
+ io_queues[HCTX_TYPE_READ];
+ blk_mq_map_queues(&set->map[HCTX_TYPE_POLL]);
+ }
+
+ dev_info(ctrl->device,
+ "mapped %d/%d/%d default/read/poll queues.\n",
+ io_queues[HCTX_TYPE_DEFAULT],
+ io_queues[HCTX_TYPE_READ],
+ io_queues[HCTX_TYPE_POLL]);
+}
+EXPORT_SYMBOL_GPL(nvmf_map_queues);
+
static int nvmf_check_required_opts(struct nvmf_ctrl_options *opts,
unsigned int required_opts)
{
diff --git a/drivers/nvme/host/fabrics.h b/drivers/nvme/host/fabrics.h
index dcac3df8a5f7..82e7a27ffbde 100644
--- a/drivers/nvme/host/fabrics.h
+++ b/drivers/nvme/host/fabrics.h
@@ -77,6 +77,9 @@ enum {
* with the parsing opts enum.
* @mask: Used by the fabrics library to parse through sysfs options
* on adding a NVMe controller.
+ * @max_reconnects: maximum number of allowed reconnect attempts before removing
+ * the controller, (-1) means reconnect forever, zero means remove
+ * immediately;
* @transport: Holds the fabric transport "technology name" (for a lack of
* better description) that will be used by an NVMe controller
* being added.
@@ -96,9 +99,6 @@ enum {
* @discovery_nqn: indicates if the subsysnqn is the well-known discovery NQN.
* @kato: Keep-alive timeout.
* @host: Virtual NVMe host, contains the NQN and Host ID.
- * @max_reconnects: maximum number of allowed reconnect attempts before removing
- * the controller, (-1) means reconnect forever, zero means remove
- * immediately;
* @dhchap_secret: DH-HMAC-CHAP secret
* @dhchap_ctrl_secret: DH-HMAC-CHAP controller secret for bi-directional
* authentication
@@ -112,6 +112,7 @@ enum {
*/
struct nvmf_ctrl_options {
unsigned mask;
+ int max_reconnects;
char *transport;
char *subsysnqn;
char *traddr;
@@ -125,7 +126,6 @@ struct nvmf_ctrl_options {
bool duplicate_connect;
unsigned int kato;
struct nvmf_host *host;
- int max_reconnects;
char *dhchap_secret;
char *dhchap_ctrl_secret;
bool disable_sqflow;
@@ -181,7 +181,7 @@ nvmf_ctlr_matches_baseopts(struct nvme_ctrl *ctrl,
ctrl->state == NVME_CTRL_DEAD ||
strcmp(opts->subsysnqn, ctrl->opts->subsysnqn) ||
strcmp(opts->host->nqn, ctrl->opts->host->nqn) ||
- memcmp(&opts->host->id, &ctrl->opts->host->id, sizeof(uuid_t)))
+ !uuid_equal(&opts->host->id, &ctrl->opts->host->id))
return false;
return true;
@@ -203,6 +203,13 @@ static inline void nvmf_complete_timed_out_request(struct request *rq)
}
}
+static inline unsigned int nvmf_nr_io_queues(struct nvmf_ctrl_options *opts)
+{
+ return min(opts->nr_io_queues, num_online_cpus()) +
+ min(opts->nr_write_queues, num_online_cpus()) +
+ min(opts->nr_poll_queues, num_online_cpus());
+}
+
int nvmf_reg_read32(struct nvme_ctrl *ctrl, u32 off, u32 *val);
int nvmf_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val);
int nvmf_reg_write32(struct nvme_ctrl *ctrl, u32 off, u32 val);
@@ -215,5 +222,9 @@ int nvmf_get_address(struct nvme_ctrl *ctrl, char *buf, int size);
bool nvmf_should_reconnect(struct nvme_ctrl *ctrl);
bool nvmf_ip_options_match(struct nvme_ctrl *ctrl,
struct nvmf_ctrl_options *opts);
+void nvmf_set_io_queues(struct nvmf_ctrl_options *opts, u32 nr_io_queues,
+ u32 io_queues[HCTX_MAX_TYPES]);
+void nvmf_map_queues(struct blk_mq_tag_set *set, struct nvme_ctrl *ctrl,
+ u32 io_queues[HCTX_MAX_TYPES]);
#endif /* _NVME_FABRICS_H */
diff --git a/drivers/nvme/host/fault_inject.c b/drivers/nvme/host/fault_inject.c
index 83d2e6860d38..1ba10a5c656d 100644
--- a/drivers/nvme/host/fault_inject.c
+++ b/drivers/nvme/host/fault_inject.c
@@ -27,7 +27,7 @@ void nvme_fault_inject_init(struct nvme_fault_inject *fault_inj,
/* create debugfs directory and attribute */
parent = debugfs_create_dir(dev_name, NULL);
- if (!parent) {
+ if (IS_ERR(parent)) {
pr_warn("%s: failed to create debugfs directory\n", dev_name);
return;
}
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index 2ed75923507d..1cd2bf82319a 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -2548,14 +2548,24 @@ nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg)
* the controller. Abort any ios on the association and let the
* create_association error path resolve things.
*/
- if (ctrl->ctrl.state == NVME_CTRL_CONNECTING) {
- __nvme_fc_abort_outstanding_ios(ctrl, true);
+ enum nvme_ctrl_state state;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ctrl->lock, flags);
+ state = ctrl->ctrl.state;
+ if (state == NVME_CTRL_CONNECTING) {
set_bit(ASSOC_FAILED, &ctrl->flags);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
+ __nvme_fc_abort_outstanding_ios(ctrl, true);
+ dev_warn(ctrl->ctrl.device,
+ "NVME-FC{%d}: transport error during (re)connect\n",
+ ctrl->cnum);
return;
}
+ spin_unlock_irqrestore(&ctrl->lock, flags);
/* Otherwise, only proceed if in LIVE state - e.g. on first error */
- if (ctrl->ctrl.state != NVME_CTRL_LIVE)
+ if (state != NVME_CTRL_LIVE)
return;
dev_warn(ctrl->ctrl.device,
@@ -2917,8 +2927,8 @@ nvme_fc_create_io_queues(struct nvme_fc_ctrl *ctrl)
ret = nvme_alloc_io_tag_set(&ctrl->ctrl, &ctrl->tag_set,
&nvme_fc_mq_ops, 1,
- struct_size((struct nvme_fcp_op_w_sgl *)NULL, priv,
- ctrl->lport->ops->fcprqst_priv_sz));
+ struct_size_t(struct nvme_fcp_op_w_sgl, priv,
+ ctrl->lport->ops->fcprqst_priv_sz));
if (ret)
return ret;
@@ -3110,7 +3120,9 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
*/
ret = nvme_enable_ctrl(&ctrl->ctrl);
- if (ret || test_bit(ASSOC_FAILED, &ctrl->flags))
+ if (!ret && test_bit(ASSOC_FAILED, &ctrl->flags))
+ ret = -EIO;
+ if (ret)
goto out_disconnect_admin_queue;
ctrl->ctrl.max_segments = ctrl->lport->ops->max_sgl_segments;
@@ -3120,7 +3132,9 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
nvme_unquiesce_admin_queue(&ctrl->ctrl);
ret = nvme_init_ctrl_finish(&ctrl->ctrl, false);
- if (ret || test_bit(ASSOC_FAILED, &ctrl->flags))
+ if (!ret && test_bit(ASSOC_FAILED, &ctrl->flags))
+ ret = -EIO;
+ if (ret)
goto out_disconnect_admin_queue;
/* sanity checks */
@@ -3165,10 +3179,16 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
else
ret = nvme_fc_recreate_io_queues(ctrl);
}
- if (ret || test_bit(ASSOC_FAILED, &ctrl->flags))
- goto out_term_aen_ops;
+ spin_lock_irqsave(&ctrl->lock, flags);
+ if (!ret && test_bit(ASSOC_FAILED, &ctrl->flags))
+ ret = -EIO;
+ if (ret) {
+ spin_unlock_irqrestore(&ctrl->lock, flags);
+ goto out_term_aen_ops;
+ }
changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
ctrl->ctrl.nr_reconnects = 0;
@@ -3180,6 +3200,9 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
out_term_aen_ops:
nvme_fc_term_aen_ops(ctrl);
out_disconnect_admin_queue:
+ dev_warn(ctrl->ctrl.device,
+ "NVME-FC{%d}: create_assoc failed, assoc_id %llx ret %d\n",
+ ctrl->cnum, ctrl->association_id, ret);
/* send a Disconnect(association) LS to fc-nvme target */
nvme_fc_xmt_disconnect_assoc(ctrl);
spin_lock_irqsave(&ctrl->lock, flags);
@@ -3536,8 +3559,8 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
ret = nvme_alloc_admin_tag_set(&ctrl->ctrl, &ctrl->admin_tag_set,
&nvme_fc_admin_mq_ops,
- struct_size((struct nvme_fcp_op_w_sgl *)NULL, priv,
- ctrl->lport->ops->fcprqst_priv_sz));
+ struct_size_t(struct nvme_fcp_op_w_sgl, priv,
+ ctrl->lport->ops->fcprqst_priv_sz));
if (ret)
goto fail_ctrl;
diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
index f15e7330b75a..d39f3219358b 100644
--- a/drivers/nvme/host/ioctl.c
+++ b/drivers/nvme/host/ioctl.c
@@ -14,7 +14,7 @@ enum {
};
static bool nvme_cmd_allowed(struct nvme_ns *ns, struct nvme_command *c,
- unsigned int flags, fmode_t mode)
+ unsigned int flags, bool open_for_write)
{
u32 effects;
@@ -80,7 +80,7 @@ static bool nvme_cmd_allowed(struct nvme_ns *ns, struct nvme_command *c,
* writing.
*/
if (nvme_is_write(c) || (effects & NVME_CMD_EFFECTS_LBCC))
- return mode & FMODE_WRITE;
+ return open_for_write;
return true;
}
@@ -337,7 +337,7 @@ static bool nvme_validate_passthru_nsid(struct nvme_ctrl *ctrl,
static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
struct nvme_passthru_cmd __user *ucmd, unsigned int flags,
- fmode_t mode)
+ bool open_for_write)
{
struct nvme_passthru_cmd cmd;
struct nvme_command c;
@@ -365,7 +365,7 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
c.common.cdw14 = cpu_to_le32(cmd.cdw14);
c.common.cdw15 = cpu_to_le32(cmd.cdw15);
- if (!nvme_cmd_allowed(ns, &c, 0, mode))
+ if (!nvme_cmd_allowed(ns, &c, 0, open_for_write))
return -EACCES;
if (cmd.timeout_ms)
@@ -385,7 +385,7 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
static int nvme_user_cmd64(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
struct nvme_passthru_cmd64 __user *ucmd, unsigned int flags,
- fmode_t mode)
+ bool open_for_write)
{
struct nvme_passthru_cmd64 cmd;
struct nvme_command c;
@@ -412,7 +412,7 @@ static int nvme_user_cmd64(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
c.common.cdw14 = cpu_to_le32(cmd.cdw14);
c.common.cdw15 = cpu_to_le32(cmd.cdw15);
- if (!nvme_cmd_allowed(ns, &c, flags, mode))
+ if (!nvme_cmd_allowed(ns, &c, flags, open_for_write))
return -EACCES;
if (cmd.timeout_ms)
@@ -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
- io_uring_cmd_complete_in_task(ioucmd, nvme_uring_task_cb);
+ } 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
- io_uring_cmd_complete_in_task(ioucmd, nvme_uring_task_meta_cb);
+ } else {
+ io_uring_cmd_do_in_task_lazy(ioucmd, nvme_uring_task_meta_cb);
+ }
return RQ_END_IO_NONE;
}
@@ -583,7 +585,7 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
c.common.cdw14 = cpu_to_le32(READ_ONCE(cmd->cdw14));
c.common.cdw15 = cpu_to_le32(READ_ONCE(cmd->cdw15));
- if (!nvme_cmd_allowed(ns, &c, 0, ioucmd->file->f_mode))
+ if (!nvme_cmd_allowed(ns, &c, 0, ioucmd->file->f_mode & FMODE_WRITE))
return -EACCES;
d.metadata = READ_ONCE(cmd->metadata);
@@ -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;
@@ -649,13 +644,13 @@ static bool is_ctrl_ioctl(unsigned int cmd)
}
static int nvme_ctrl_ioctl(struct nvme_ctrl *ctrl, unsigned int cmd,
- void __user *argp, fmode_t mode)
+ void __user *argp, bool open_for_write)
{
switch (cmd) {
case NVME_IOCTL_ADMIN_CMD:
- return nvme_user_cmd(ctrl, NULL, argp, 0, mode);
+ return nvme_user_cmd(ctrl, NULL, argp, 0, open_for_write);
case NVME_IOCTL_ADMIN64_CMD:
- return nvme_user_cmd64(ctrl, NULL, argp, 0, mode);
+ return nvme_user_cmd64(ctrl, NULL, argp, 0, open_for_write);
default:
return sed_ioctl(ctrl->opal_dev, cmd, argp);
}
@@ -680,14 +675,14 @@ struct nvme_user_io32 {
#endif /* COMPAT_FOR_U64_ALIGNMENT */
static int nvme_ns_ioctl(struct nvme_ns *ns, unsigned int cmd,
- void __user *argp, unsigned int flags, fmode_t mode)
+ void __user *argp, unsigned int flags, bool open_for_write)
{
switch (cmd) {
case NVME_IOCTL_ID:
force_successful_syscall_return();
return ns->head->ns_id;
case NVME_IOCTL_IO_CMD:
- return nvme_user_cmd(ns->ctrl, ns, argp, flags, mode);
+ return nvme_user_cmd(ns->ctrl, ns, argp, flags, open_for_write);
/*
* struct nvme_user_io can have different padding on some 32-bit ABIs.
* Just accept the compat version as all fields that are used are the
@@ -702,16 +697,18 @@ static int nvme_ns_ioctl(struct nvme_ns *ns, unsigned int cmd,
flags |= NVME_IOCTL_VEC;
fallthrough;
case NVME_IOCTL_IO64_CMD:
- return nvme_user_cmd64(ns->ctrl, ns, argp, flags, mode);
+ return nvme_user_cmd64(ns->ctrl, ns, argp, flags,
+ open_for_write);
default:
return -ENOTTY;
}
}
-int nvme_ioctl(struct block_device *bdev, fmode_t mode,
+int nvme_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long arg)
{
struct nvme_ns *ns = bdev->bd_disk->private_data;
+ bool open_for_write = mode & BLK_OPEN_WRITE;
void __user *argp = (void __user *)arg;
unsigned int flags = 0;
@@ -719,19 +716,20 @@ int nvme_ioctl(struct block_device *bdev, fmode_t mode,
flags |= NVME_IOCTL_PARTITION;
if (is_ctrl_ioctl(cmd))
- return nvme_ctrl_ioctl(ns->ctrl, cmd, argp, mode);
- return nvme_ns_ioctl(ns, cmd, argp, flags, mode);
+ return nvme_ctrl_ioctl(ns->ctrl, cmd, argp, open_for_write);
+ return nvme_ns_ioctl(ns, cmd, argp, flags, open_for_write);
}
long nvme_ns_chr_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct nvme_ns *ns =
container_of(file_inode(file)->i_cdev, struct nvme_ns, cdev);
+ bool open_for_write = file->f_mode & FMODE_WRITE;
void __user *argp = (void __user *)arg;
if (is_ctrl_ioctl(cmd))
- return nvme_ctrl_ioctl(ns->ctrl, cmd, argp, file->f_mode);
- return nvme_ns_ioctl(ns, cmd, argp, 0, file->f_mode);
+ return nvme_ctrl_ioctl(ns->ctrl, cmd, argp, open_for_write);
+ return nvme_ns_ioctl(ns, cmd, argp, 0, open_for_write);
}
static int nvme_uring_cmd_checks(unsigned int issue_flags)
@@ -782,25 +780,21 @@ 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;
- 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);
- rcu_read_unlock();
+ if (!(ioucmd->flags & IORING_URING_CMD_POLLED))
+ return 0;
+
+ req = READ_ONCE(ioucmd->cookie);
+ if (req && blk_rq_is_poll(req))
+ ret = blk_rq_poll(req, iob, poll_flags);
return ret;
}
#ifdef CONFIG_NVME_MULTIPATH
static int nvme_ns_head_ctrl_ioctl(struct nvme_ns *ns, unsigned int cmd,
void __user *argp, struct nvme_ns_head *head, int srcu_idx,
- fmode_t mode)
+ bool open_for_write)
__releases(&head->srcu)
{
struct nvme_ctrl *ctrl = ns->ctrl;
@@ -808,16 +802,17 @@ static int nvme_ns_head_ctrl_ioctl(struct nvme_ns *ns, unsigned int cmd,
nvme_get_ctrl(ns->ctrl);
srcu_read_unlock(&head->srcu, srcu_idx);
- ret = nvme_ctrl_ioctl(ns->ctrl, cmd, argp, mode);
+ ret = nvme_ctrl_ioctl(ns->ctrl, cmd, argp, open_for_write);
nvme_put_ctrl(ctrl);
return ret;
}
-int nvme_ns_head_ioctl(struct block_device *bdev, fmode_t mode,
+int nvme_ns_head_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long arg)
{
struct nvme_ns_head *head = bdev->bd_disk->private_data;
+ bool open_for_write = mode & BLK_OPEN_WRITE;
void __user *argp = (void __user *)arg;
struct nvme_ns *ns;
int srcu_idx, ret = -EWOULDBLOCK;
@@ -838,9 +833,9 @@ int nvme_ns_head_ioctl(struct block_device *bdev, fmode_t mode,
*/
if (is_ctrl_ioctl(cmd))
return nvme_ns_head_ctrl_ioctl(ns, cmd, argp, head, srcu_idx,
- mode);
+ open_for_write);
- ret = nvme_ns_ioctl(ns, cmd, argp, flags, mode);
+ ret = nvme_ns_ioctl(ns, cmd, argp, flags, open_for_write);
out_unlock:
srcu_read_unlock(&head->srcu, srcu_idx);
return ret;
@@ -849,6 +844,7 @@ out_unlock:
long nvme_ns_head_chr_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
+ bool open_for_write = file->f_mode & FMODE_WRITE;
struct cdev *cdev = file_inode(file)->i_cdev;
struct nvme_ns_head *head =
container_of(cdev, struct nvme_ns_head, cdev);
@@ -863,9 +859,9 @@ long nvme_ns_head_chr_ioctl(struct file *file, unsigned int cmd,
if (is_ctrl_ioctl(cmd))
return nvme_ns_head_ctrl_ioctl(ns, cmd, argp, head, srcu_idx,
- file->f_mode);
+ open_for_write);
- ret = nvme_ns_ioctl(ns, cmd, argp, 0, file->f_mode);
+ ret = nvme_ns_ioctl(ns, cmd, argp, 0, open_for_write);
out_unlock:
srcu_read_unlock(&head->srcu, srcu_idx);
return ret;
@@ -885,31 +881,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)
@@ -940,7 +911,7 @@ int nvme_dev_uring_cmd(struct io_uring_cmd *ioucmd, unsigned int issue_flags)
}
static int nvme_dev_user_cmd(struct nvme_ctrl *ctrl, void __user *argp,
- fmode_t mode)
+ bool open_for_write)
{
struct nvme_ns *ns;
int ret;
@@ -964,7 +935,7 @@ static int nvme_dev_user_cmd(struct nvme_ctrl *ctrl, void __user *argp,
kref_get(&ns->kref);
up_read(&ctrl->namespaces_rwsem);
- ret = nvme_user_cmd(ctrl, ns, argp, 0, mode);
+ ret = nvme_user_cmd(ctrl, ns, argp, 0, open_for_write);
nvme_put_ns(ns);
return ret;
@@ -976,16 +947,17 @@ out_unlock:
long nvme_dev_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
+ bool open_for_write = file->f_mode & FMODE_WRITE;
struct nvme_ctrl *ctrl = file->private_data;
void __user *argp = (void __user *)arg;
switch (cmd) {
case NVME_IOCTL_ADMIN_CMD:
- return nvme_user_cmd(ctrl, NULL, argp, 0, file->f_mode);
+ return nvme_user_cmd(ctrl, NULL, argp, 0, open_for_write);
case NVME_IOCTL_ADMIN64_CMD:
- return nvme_user_cmd64(ctrl, NULL, argp, 0, file->f_mode);
+ return nvme_user_cmd64(ctrl, NULL, argp, 0, open_for_write);
case NVME_IOCTL_IO_CMD:
- return nvme_dev_user_cmd(ctrl, argp, file->f_mode);
+ return nvme_dev_user_cmd(ctrl, argp, open_for_write);
case NVME_IOCTL_RESET:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index 2bc159a318ff..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);
@@ -402,14 +410,14 @@ static void nvme_ns_head_submit_bio(struct bio *bio)
srcu_read_unlock(&head->srcu, srcu_idx);
}
-static int nvme_ns_head_open(struct block_device *bdev, fmode_t mode)
+static int nvme_ns_head_open(struct gendisk *disk, blk_mode_t mode)
{
- if (!nvme_tryget_ns_head(bdev->bd_disk->private_data))
+ if (!nvme_tryget_ns_head(disk->private_data))
return -ENXIO;
return 0;
}
-static void nvme_ns_head_release(struct gendisk *disk, fmode_t mode)
+static void nvme_ns_head_release(struct gendisk *disk)
{
nvme_put_ns_head(disk->private_data);
}
@@ -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 8657811f8b88..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)
@@ -247,12 +249,14 @@ enum nvme_ctrl_flags {
NVME_CTRL_ADMIN_Q_STOPPED = 1,
NVME_CTRL_STARTED_ONCE = 2,
NVME_CTRL_STOPPED = 3,
+ NVME_CTRL_SKIP_ID_CNS_CS = 4,
+ NVME_CTRL_DIRTY_CAPABILITY = 5,
};
struct nvme_ctrl {
bool comp_seen;
- enum nvme_ctrl_state state;
bool identified;
+ enum nvme_ctrl_state state;
spinlock_t lock;
struct mutex scan_lock;
const struct nvme_ctrl_ops *ops;
@@ -284,8 +288,8 @@ struct nvme_ctrl {
char name[12];
u16 cntlid;
- u32 ctrl_config;
u16 mtfa;
+ u32 ctrl_config;
u32 queue_count;
u64 cap;
@@ -359,10 +363,10 @@ struct nvme_ctrl {
bool apst_enabled;
/* PCIe only: */
+ u16 hmmaxd;
u32 hmpre;
u32 hmmin;
u32 hmminds;
- u16 hmmaxd;
/* Fabrics only */
u32 ioccsz;
@@ -842,10 +846,10 @@ void nvme_put_ns_head(struct nvme_ns_head *head);
int nvme_cdev_add(struct cdev *cdev, struct device *cdev_device,
const struct file_operations *fops, struct module *owner);
void nvme_cdev_del(struct cdev *cdev, struct device *cdev_device);
-int nvme_ioctl(struct block_device *bdev, fmode_t mode,
+int nvme_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long arg);
long nvme_ns_chr_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-int nvme_ns_head_ioctl(struct block_device *bdev, fmode_t mode,
+int nvme_ns_head_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long arg);
long nvme_ns_head_chr_ioctl(struct file *file, unsigned int cmd,
unsigned long arg);
@@ -853,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,
@@ -866,7 +868,11 @@ extern const struct attribute_group *nvme_ns_id_attr_groups[];
extern const struct pr_ops nvme_pr_ops;
extern const struct block_device_operations nvme_ns_head_ops;
extern const struct attribute_group nvme_dev_attrs_group;
+extern const struct attribute_group *nvme_subsys_attrs_groups[];
+extern const struct attribute_group *nvme_dev_attr_groups[];
+extern const struct block_device_operations nvme_bdev_ops;
+void nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl);
struct nvme_ns *nvme_find_path(struct nvme_ns_head *head);
#ifdef CONFIG_NVME_MULTIPATH
static inline bool nvme_ctrl_use_ana(struct nvme_ctrl *ctrl)
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 492f319ebdf3..2f57da12d983 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -420,10 +420,9 @@ static int nvme_pci_init_request(struct blk_mq_tag_set *set,
struct request *req, unsigned int hctx_idx,
unsigned int numa_node)
{
- struct nvme_dev *dev = to_nvme_dev(set->driver_data);
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
- nvme_req(req)->ctrl = &dev->ctrl;
+ nvme_req(req)->ctrl = set->driver_data;
nvme_req(req)->cmd = &iod->cmd;
return 0;
}
@@ -968,7 +967,7 @@ static __always_inline void nvme_pci_unmap_rq(struct request *req)
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
dma_unmap_page(dev->dev, iod->meta_dma,
- rq_integrity_vec(req)->bv_len, rq_data_dir(req));
+ rq_integrity_vec(req)->bv_len, rq_dma_dir(req));
}
if (blk_rq_nr_phys_segments(req))
@@ -1299,9 +1298,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req)
*/
if (nvme_should_reset(dev, csts)) {
nvme_warn_reset(dev, csts);
- nvme_dev_disable(dev, false);
- nvme_reset_ctrl(&dev->ctrl);
- return BLK_EH_DONE;
+ goto disable;
}
/*
@@ -1352,10 +1349,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req)
"I/O %d QID %d timeout, reset controller\n",
req->tag, nvmeq->qid);
nvme_req(req)->flags |= NVME_REQ_CANCELLED;
- nvme_dev_disable(dev, false);
- nvme_reset_ctrl(&dev->ctrl);
-
- return BLK_EH_DONE;
+ goto disable;
}
if (atomic_dec_return(&dev->ctrl.abort_limit) < 0) {
@@ -1392,6 +1386,15 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req)
* as the device then is in a faulty state.
*/
return BLK_EH_RESET_TIMER;
+
+disable:
+ if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING))
+ return BLK_EH_DONE;
+
+ nvme_dev_disable(dev, false);
+ if (nvme_try_sched_reset(&dev->ctrl))
+ nvme_unquiesce_io_queues(&dev->ctrl);
+ return BLK_EH_DONE;
}
static void nvme_free_queue(struct nvme_queue *nvmeq)
@@ -2691,7 +2694,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;
}
/*
@@ -2778,7 +2782,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);
}
@@ -3276,6 +3282,10 @@ static pci_ers_result_t nvme_error_detected(struct pci_dev *pdev,
case pci_channel_io_frozen:
dev_warn(dev->ctrl.device,
"frozen state error detected, reset controller\n");
+ if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING)) {
+ nvme_dev_disable(dev, true);
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
nvme_dev_disable(dev, false);
return PCI_ERS_RESULT_NEED_RESET;
case pci_channel_io_perm_failure:
@@ -3292,7 +3302,8 @@ static pci_ers_result_t nvme_slot_reset(struct pci_dev *pdev)
dev_info(dev->ctrl.device, "restart after slot reset\n");
pci_restore_state(pdev);
- nvme_reset_ctrl(&dev->ctrl);
+ if (!nvme_try_sched_reset(&dev->ctrl))
+ nvme_unquiesce_io_queues(&dev->ctrl);
return PCI_ERS_RESULT_RECOVERED;
}
@@ -3391,9 +3402,12 @@ static const struct pci_device_id nvme_id_table[] = {
{ PCI_DEVICE(0x1d97, 0x2263), /* SPCC */
.driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
{ PCI_DEVICE(0x144d, 0xa80b), /* Samsung PM9B1 256G and 512G */
- .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
+ .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES |
+ NVME_QUIRK_BOGUS_NID, },
{ PCI_DEVICE(0x144d, 0xa809), /* Samsung MZALQ256HBJD 256G */
.driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
+ { PCI_DEVICE(0x144d, 0xa802), /* Samsung SM953 */
+ .driver_data = NVME_QUIRK_BOGUS_NID, },
{ PCI_DEVICE(0x1cc4, 0x6303), /* UMIS RPJTJ512MGE1QDY 512G */
.driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
{ PCI_DEVICE(0x1cc4, 0x6302), /* UMIS RPJTJ256MGE1QDY 256G */
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/host/rdma.c b/drivers/nvme/host/rdma.c
index 0eb79696fb73..337a624a537c 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -501,7 +501,7 @@ static int nvme_rdma_create_queue_ib(struct nvme_rdma_queue *queue)
}
ibdev = queue->device->dev;
- /* +1 for ib_stop_cq */
+ /* +1 for ib_drain_qp */
queue->cq_size = cq_factor * queue->queue_size + 1;
ret = nvme_rdma_create_cq(ibdev, queue);
@@ -713,18 +713,10 @@ out_stop_queues:
static int nvme_rdma_alloc_io_queues(struct nvme_rdma_ctrl *ctrl)
{
struct nvmf_ctrl_options *opts = ctrl->ctrl.opts;
- struct ib_device *ibdev = ctrl->device->dev;
- unsigned int nr_io_queues, nr_default_queues;
- unsigned int nr_read_queues, nr_poll_queues;
+ unsigned int nr_io_queues;
int i, ret;
- nr_read_queues = min_t(unsigned int, ibdev->num_comp_vectors,
- min(opts->nr_io_queues, num_online_cpus()));
- nr_default_queues = min_t(unsigned int, ibdev->num_comp_vectors,
- min(opts->nr_write_queues, num_online_cpus()));
- nr_poll_queues = min(opts->nr_poll_queues, num_online_cpus());
- nr_io_queues = nr_read_queues + nr_default_queues + nr_poll_queues;
-
+ nr_io_queues = nvmf_nr_io_queues(opts);
ret = nvme_set_queue_count(&ctrl->ctrl, &nr_io_queues);
if (ret)
return ret;
@@ -739,34 +731,7 @@ static int nvme_rdma_alloc_io_queues(struct nvme_rdma_ctrl *ctrl)
dev_info(ctrl->ctrl.device,
"creating %d I/O queues.\n", nr_io_queues);
- if (opts->nr_write_queues && nr_read_queues < nr_io_queues) {
- /*
- * separate read/write queues
- * hand out dedicated default queues only after we have
- * sufficient read queues.
- */
- ctrl->io_queues[HCTX_TYPE_READ] = nr_read_queues;
- nr_io_queues -= ctrl->io_queues[HCTX_TYPE_READ];
- ctrl->io_queues[HCTX_TYPE_DEFAULT] =
- min(nr_default_queues, nr_io_queues);
- nr_io_queues -= ctrl->io_queues[HCTX_TYPE_DEFAULT];
- } else {
- /*
- * shared read/write queues
- * either no write queues were requested, or we don't have
- * sufficient queue count to have dedicated default queues.
- */
- ctrl->io_queues[HCTX_TYPE_DEFAULT] =
- min(nr_read_queues, nr_io_queues);
- nr_io_queues -= ctrl->io_queues[HCTX_TYPE_DEFAULT];
- }
-
- if (opts->nr_poll_queues && nr_io_queues) {
- /* map dedicated poll queues only if we have queues left */
- ctrl->io_queues[HCTX_TYPE_POLL] =
- min(nr_poll_queues, nr_io_queues);
- }
-
+ nvmf_set_io_queues(opts, nr_io_queues, ctrl->io_queues);
for (i = 1; i < ctrl->ctrl.queue_count; i++) {
ret = nvme_rdma_alloc_queue(ctrl, i,
ctrl->ctrl.sqsize + 1);
@@ -918,6 +883,7 @@ static int nvme_rdma_configure_io_queues(struct nvme_rdma_ctrl *ctrl, bool new)
goto out_cleanup_tagset;
if (!new) {
+ nvme_start_freeze(&ctrl->ctrl);
nvme_unquiesce_io_queues(&ctrl->ctrl);
if (!nvme_wait_freeze_timeout(&ctrl->ctrl, NVME_IO_TIMEOUT)) {
/*
@@ -926,6 +892,7 @@ static int nvme_rdma_configure_io_queues(struct nvme_rdma_ctrl *ctrl, bool new)
* to be safe.
*/
ret = -ENODEV;
+ nvme_unfreeze(&ctrl->ctrl);
goto out_wait_freeze_timed_out;
}
blk_mq_update_nr_hw_queues(ctrl->ctrl.tagset,
@@ -975,7 +942,6 @@ static void nvme_rdma_teardown_io_queues(struct nvme_rdma_ctrl *ctrl,
bool remove)
{
if (ctrl->ctrl.queue_count > 1) {
- nvme_start_freeze(&ctrl->ctrl);
nvme_quiesce_io_queues(&ctrl->ctrl);
nvme_sync_io_queues(&ctrl->ctrl);
nvme_rdma_stop_io_queues(ctrl);
@@ -2138,44 +2104,8 @@ static void nvme_rdma_complete_rq(struct request *rq)
static void nvme_rdma_map_queues(struct blk_mq_tag_set *set)
{
struct nvme_rdma_ctrl *ctrl = to_rdma_ctrl(set->driver_data);
- struct nvmf_ctrl_options *opts = ctrl->ctrl.opts;
- if (opts->nr_write_queues && ctrl->io_queues[HCTX_TYPE_READ]) {
- /* separate read/write queues */
- set->map[HCTX_TYPE_DEFAULT].nr_queues =
- ctrl->io_queues[HCTX_TYPE_DEFAULT];
- set->map[HCTX_TYPE_DEFAULT].queue_offset = 0;
- set->map[HCTX_TYPE_READ].nr_queues =
- ctrl->io_queues[HCTX_TYPE_READ];
- set->map[HCTX_TYPE_READ].queue_offset =
- ctrl->io_queues[HCTX_TYPE_DEFAULT];
- } else {
- /* shared read/write queues */
- set->map[HCTX_TYPE_DEFAULT].nr_queues =
- ctrl->io_queues[HCTX_TYPE_DEFAULT];
- set->map[HCTX_TYPE_DEFAULT].queue_offset = 0;
- set->map[HCTX_TYPE_READ].nr_queues =
- ctrl->io_queues[HCTX_TYPE_DEFAULT];
- set->map[HCTX_TYPE_READ].queue_offset = 0;
- }
- blk_mq_map_queues(&set->map[HCTX_TYPE_DEFAULT]);
- blk_mq_map_queues(&set->map[HCTX_TYPE_READ]);
-
- if (opts->nr_poll_queues && ctrl->io_queues[HCTX_TYPE_POLL]) {
- /* map dedicated poll queues only if we have queues left */
- set->map[HCTX_TYPE_POLL].nr_queues =
- ctrl->io_queues[HCTX_TYPE_POLL];
- set->map[HCTX_TYPE_POLL].queue_offset =
- ctrl->io_queues[HCTX_TYPE_DEFAULT] +
- ctrl->io_queues[HCTX_TYPE_READ];
- blk_mq_map_queues(&set->map[HCTX_TYPE_POLL]);
- }
-
- dev_info(ctrl->ctrl.device,
- "mapped %d/%d/%d default/read/poll queues.\n",
- ctrl->io_queues[HCTX_TYPE_DEFAULT],
- ctrl->io_queues[HCTX_TYPE_READ],
- ctrl->io_queues[HCTX_TYPE_POLL]);
+ nvmf_map_queues(set, &ctrl->ctrl, ctrl->io_queues);
}
static const struct blk_mq_ops nvme_rdma_mq_ops = {
diff --git a/drivers/nvme/host/sysfs.c b/drivers/nvme/host/sysfs.c
new file mode 100644
index 000000000000..212e1b05d298
--- /dev/null
+++ b/drivers/nvme/host/sysfs.c
@@ -0,0 +1,668 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sysfs interface for the NVMe core driver.
+ *
+ * Copyright (c) 2011-2014, Intel Corporation.
+ */
+
+#include <linux/nvme-auth.h>
+
+#include "nvme.h"
+#include "fabrics.h"
+
+static ssize_t nvme_sysfs_reset(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+ int ret;
+
+ ret = nvme_reset_ctrl_sync(ctrl);
+ if (ret < 0)
+ return ret;
+ return count;
+}
+static DEVICE_ATTR(reset_controller, S_IWUSR, NULL, nvme_sysfs_reset);
+
+static ssize_t nvme_sysfs_rescan(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+
+ nvme_queue_scan(ctrl);
+ return count;
+}
+static DEVICE_ATTR(rescan_controller, S_IWUSR, NULL, nvme_sysfs_rescan);
+
+static inline struct nvme_ns_head *dev_to_ns_head(struct device *dev)
+{
+ struct gendisk *disk = dev_to_disk(dev);
+
+ if (disk->fops == &nvme_bdev_ops)
+ return nvme_get_ns_from_dev(dev)->head;
+ else
+ return disk->private_data;
+}
+
+static ssize_t wwid_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct nvme_ns_head *head = dev_to_ns_head(dev);
+ struct nvme_ns_ids *ids = &head->ids;
+ struct nvme_subsystem *subsys = head->subsys;
+ int serial_len = sizeof(subsys->serial);
+ int model_len = sizeof(subsys->model);
+
+ if (!uuid_is_null(&ids->uuid))
+ return sysfs_emit(buf, "uuid.%pU\n", &ids->uuid);
+
+ if (memchr_inv(ids->nguid, 0, sizeof(ids->nguid)))
+ return sysfs_emit(buf, "eui.%16phN\n", ids->nguid);
+
+ if (memchr_inv(ids->eui64, 0, sizeof(ids->eui64)))
+ return sysfs_emit(buf, "eui.%8phN\n", ids->eui64);
+
+ while (serial_len > 0 && (subsys->serial[serial_len - 1] == ' ' ||
+ subsys->serial[serial_len - 1] == '\0'))
+ serial_len--;
+ while (model_len > 0 && (subsys->model[model_len - 1] == ' ' ||
+ subsys->model[model_len - 1] == '\0'))
+ model_len--;
+
+ return sysfs_emit(buf, "nvme.%04x-%*phN-%*phN-%08x\n", subsys->vendor_id,
+ serial_len, subsys->serial, model_len, subsys->model,
+ head->ns_id);
+}
+static DEVICE_ATTR_RO(wwid);
+
+static ssize_t nguid_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "%pU\n", dev_to_ns_head(dev)->ids.nguid);
+}
+static DEVICE_ATTR_RO(nguid);
+
+static ssize_t uuid_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct nvme_ns_ids *ids = &dev_to_ns_head(dev)->ids;
+
+ /* For backward compatibility expose the NGUID to userspace if
+ * we have no UUID set
+ */
+ if (uuid_is_null(&ids->uuid)) {
+ dev_warn_once(dev,
+ "No UUID available providing old NGUID\n");
+ return sysfs_emit(buf, "%pU\n", ids->nguid);
+ }
+ return sysfs_emit(buf, "%pU\n", &ids->uuid);
+}
+static DEVICE_ATTR_RO(uuid);
+
+static ssize_t eui_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "%8ph\n", dev_to_ns_head(dev)->ids.eui64);
+}
+static DEVICE_ATTR_RO(eui);
+
+static ssize_t nsid_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "%d\n", dev_to_ns_head(dev)->ns_id);
+}
+static DEVICE_ATTR_RO(nsid);
+
+static struct attribute *nvme_ns_id_attrs[] = {
+ &dev_attr_wwid.attr,
+ &dev_attr_uuid.attr,
+ &dev_attr_nguid.attr,
+ &dev_attr_eui.attr,
+ &dev_attr_nsid.attr,
+#ifdef CONFIG_NVME_MULTIPATH
+ &dev_attr_ana_grpid.attr,
+ &dev_attr_ana_state.attr,
+#endif
+ NULL,
+};
+
+static umode_t nvme_ns_id_attrs_are_visible(struct kobject *kobj,
+ struct attribute *a, int n)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct nvme_ns_ids *ids = &dev_to_ns_head(dev)->ids;
+
+ if (a == &dev_attr_uuid.attr) {
+ if (uuid_is_null(&ids->uuid) &&
+ !memchr_inv(ids->nguid, 0, sizeof(ids->nguid)))
+ return 0;
+ }
+ if (a == &dev_attr_nguid.attr) {
+ if (!memchr_inv(ids->nguid, 0, sizeof(ids->nguid)))
+ return 0;
+ }
+ if (a == &dev_attr_eui.attr) {
+ if (!memchr_inv(ids->eui64, 0, sizeof(ids->eui64)))
+ return 0;
+ }
+#ifdef CONFIG_NVME_MULTIPATH
+ if (a == &dev_attr_ana_grpid.attr || a == &dev_attr_ana_state.attr) {
+ if (dev_to_disk(dev)->fops != &nvme_bdev_ops) /* per-path attr */
+ return 0;
+ if (!nvme_ctrl_use_ana(nvme_get_ns_from_dev(dev)->ctrl))
+ return 0;
+ }
+#endif
+ return a->mode;
+}
+
+static const struct attribute_group nvme_ns_id_attr_group = {
+ .attrs = nvme_ns_id_attrs,
+ .is_visible = nvme_ns_id_attrs_are_visible,
+};
+
+const struct attribute_group *nvme_ns_id_attr_groups[] = {
+ &nvme_ns_id_attr_group,
+ NULL,
+};
+
+#define nvme_show_str_function(field) \
+static ssize_t field##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev); \
+ return sysfs_emit(buf, "%.*s\n", \
+ (int)sizeof(ctrl->subsys->field), ctrl->subsys->field); \
+} \
+static DEVICE_ATTR(field, S_IRUGO, field##_show, NULL);
+
+nvme_show_str_function(model);
+nvme_show_str_function(serial);
+nvme_show_str_function(firmware_rev);
+
+#define nvme_show_int_function(field) \
+static ssize_t field##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev); \
+ return sysfs_emit(buf, "%d\n", ctrl->field); \
+} \
+static DEVICE_ATTR(field, S_IRUGO, field##_show, NULL);
+
+nvme_show_int_function(cntlid);
+nvme_show_int_function(numa_node);
+nvme_show_int_function(queue_count);
+nvme_show_int_function(sqsize);
+nvme_show_int_function(kato);
+
+static ssize_t nvme_sysfs_delete(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+
+ if (!test_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags))
+ return -EBUSY;
+
+ if (device_remove_file_self(dev, attr))
+ nvme_delete_ctrl_sync(ctrl);
+ return count;
+}
+static DEVICE_ATTR(delete_controller, S_IWUSR, NULL, nvme_sysfs_delete);
+
+static ssize_t nvme_sysfs_show_transport(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%s\n", ctrl->ops->name);
+}
+static DEVICE_ATTR(transport, S_IRUGO, nvme_sysfs_show_transport, NULL);
+
+static ssize_t nvme_sysfs_show_state(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+ static const char *const state_name[] = {
+ [NVME_CTRL_NEW] = "new",
+ [NVME_CTRL_LIVE] = "live",
+ [NVME_CTRL_RESETTING] = "resetting",
+ [NVME_CTRL_CONNECTING] = "connecting",
+ [NVME_CTRL_DELETING] = "deleting",
+ [NVME_CTRL_DELETING_NOIO]= "deleting (no IO)",
+ [NVME_CTRL_DEAD] = "dead",
+ };
+
+ if ((unsigned)ctrl->state < ARRAY_SIZE(state_name) &&
+ state_name[ctrl->state])
+ return sysfs_emit(buf, "%s\n", state_name[ctrl->state]);
+
+ return sysfs_emit(buf, "unknown state\n");
+}
+
+static DEVICE_ATTR(state, S_IRUGO, nvme_sysfs_show_state, NULL);
+
+static ssize_t nvme_sysfs_show_subsysnqn(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%s\n", ctrl->subsys->subnqn);
+}
+static DEVICE_ATTR(subsysnqn, S_IRUGO, nvme_sysfs_show_subsysnqn, NULL);
+
+static ssize_t nvme_sysfs_show_hostnqn(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%s\n", ctrl->opts->host->nqn);
+}
+static DEVICE_ATTR(hostnqn, S_IRUGO, nvme_sysfs_show_hostnqn, NULL);
+
+static ssize_t nvme_sysfs_show_hostid(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%pU\n", &ctrl->opts->host->id);
+}
+static DEVICE_ATTR(hostid, S_IRUGO, nvme_sysfs_show_hostid, NULL);
+
+static ssize_t nvme_sysfs_show_address(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+
+ return ctrl->ops->get_address(ctrl, buf, PAGE_SIZE);
+}
+static DEVICE_ATTR(address, S_IRUGO, nvme_sysfs_show_address, NULL);
+
+static ssize_t nvme_ctrl_loss_tmo_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+ struct nvmf_ctrl_options *opts = ctrl->opts;
+
+ if (ctrl->opts->max_reconnects == -1)
+ return sysfs_emit(buf, "off\n");
+ return sysfs_emit(buf, "%d\n",
+ opts->max_reconnects * opts->reconnect_delay);
+}
+
+static ssize_t nvme_ctrl_loss_tmo_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+ struct nvmf_ctrl_options *opts = ctrl->opts;
+ int ctrl_loss_tmo, err;
+
+ err = kstrtoint(buf, 10, &ctrl_loss_tmo);
+ if (err)
+ return -EINVAL;
+
+ if (ctrl_loss_tmo < 0)
+ opts->max_reconnects = -1;
+ else
+ opts->max_reconnects = DIV_ROUND_UP(ctrl_loss_tmo,
+ opts->reconnect_delay);
+ return count;
+}
+static DEVICE_ATTR(ctrl_loss_tmo, S_IRUGO | S_IWUSR,
+ nvme_ctrl_loss_tmo_show, nvme_ctrl_loss_tmo_store);
+
+static ssize_t nvme_ctrl_reconnect_delay_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+
+ if (ctrl->opts->reconnect_delay == -1)
+ return sysfs_emit(buf, "off\n");
+ return sysfs_emit(buf, "%d\n", ctrl->opts->reconnect_delay);
+}
+
+static ssize_t nvme_ctrl_reconnect_delay_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+ unsigned int v;
+ int err;
+
+ err = kstrtou32(buf, 10, &v);
+ if (err)
+ return err;
+
+ ctrl->opts->reconnect_delay = v;
+ return count;
+}
+static DEVICE_ATTR(reconnect_delay, S_IRUGO | S_IWUSR,
+ nvme_ctrl_reconnect_delay_show, nvme_ctrl_reconnect_delay_store);
+
+static ssize_t nvme_ctrl_fast_io_fail_tmo_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+
+ if (ctrl->opts->fast_io_fail_tmo == -1)
+ return sysfs_emit(buf, "off\n");
+ return sysfs_emit(buf, "%d\n", ctrl->opts->fast_io_fail_tmo);
+}
+
+static ssize_t nvme_ctrl_fast_io_fail_tmo_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+ struct nvmf_ctrl_options *opts = ctrl->opts;
+ int fast_io_fail_tmo, err;
+
+ err = kstrtoint(buf, 10, &fast_io_fail_tmo);
+ if (err)
+ return -EINVAL;
+
+ if (fast_io_fail_tmo < 0)
+ opts->fast_io_fail_tmo = -1;
+ else
+ opts->fast_io_fail_tmo = fast_io_fail_tmo;
+ return count;
+}
+static DEVICE_ATTR(fast_io_fail_tmo, S_IRUGO | S_IWUSR,
+ nvme_ctrl_fast_io_fail_tmo_show, nvme_ctrl_fast_io_fail_tmo_store);
+
+static ssize_t cntrltype_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ static const char * const type[] = {
+ [NVME_CTRL_IO] = "io\n",
+ [NVME_CTRL_DISC] = "discovery\n",
+ [NVME_CTRL_ADMIN] = "admin\n",
+ };
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+
+ if (ctrl->cntrltype > NVME_CTRL_ADMIN || !type[ctrl->cntrltype])
+ return sysfs_emit(buf, "reserved\n");
+
+ return sysfs_emit(buf, type[ctrl->cntrltype]);
+}
+static DEVICE_ATTR_RO(cntrltype);
+
+static ssize_t dctype_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ static const char * const type[] = {
+ [NVME_DCTYPE_NOT_REPORTED] = "none\n",
+ [NVME_DCTYPE_DDC] = "ddc\n",
+ [NVME_DCTYPE_CDC] = "cdc\n",
+ };
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+
+ if (ctrl->dctype > NVME_DCTYPE_CDC || !type[ctrl->dctype])
+ return sysfs_emit(buf, "reserved\n");
+
+ return sysfs_emit(buf, type[ctrl->dctype]);
+}
+static DEVICE_ATTR_RO(dctype);
+
+#ifdef CONFIG_NVME_AUTH
+static ssize_t nvme_ctrl_dhchap_secret_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+ struct nvmf_ctrl_options *opts = ctrl->opts;
+
+ if (!opts->dhchap_secret)
+ return sysfs_emit(buf, "none\n");
+ return sysfs_emit(buf, "%s\n", opts->dhchap_secret);
+}
+
+static ssize_t nvme_ctrl_dhchap_secret_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+ struct nvmf_ctrl_options *opts = ctrl->opts;
+ char *dhchap_secret;
+
+ if (!ctrl->opts->dhchap_secret)
+ return -EINVAL;
+ if (count < 7)
+ return -EINVAL;
+ if (memcmp(buf, "DHHC-1:", 7))
+ return -EINVAL;
+
+ dhchap_secret = kzalloc(count + 1, GFP_KERNEL);
+ if (!dhchap_secret)
+ return -ENOMEM;
+ memcpy(dhchap_secret, buf, count);
+ nvme_auth_stop(ctrl);
+ if (strcmp(dhchap_secret, opts->dhchap_secret)) {
+ struct nvme_dhchap_key *key, *host_key;
+ int ret;
+
+ ret = nvme_auth_generate_key(dhchap_secret, &key);
+ if (ret) {
+ kfree(dhchap_secret);
+ return ret;
+ }
+ kfree(opts->dhchap_secret);
+ opts->dhchap_secret = dhchap_secret;
+ host_key = ctrl->host_key;
+ mutex_lock(&ctrl->dhchap_auth_mutex);
+ ctrl->host_key = key;
+ mutex_unlock(&ctrl->dhchap_auth_mutex);
+ nvme_auth_free_key(host_key);
+ } else
+ kfree(dhchap_secret);
+ /* Start re-authentication */
+ dev_info(ctrl->device, "re-authenticating controller\n");
+ queue_work(nvme_wq, &ctrl->dhchap_auth_work);
+
+ return count;
+}
+
+static DEVICE_ATTR(dhchap_secret, S_IRUGO | S_IWUSR,
+ nvme_ctrl_dhchap_secret_show, nvme_ctrl_dhchap_secret_store);
+
+static ssize_t nvme_ctrl_dhchap_ctrl_secret_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+ struct nvmf_ctrl_options *opts = ctrl->opts;
+
+ if (!opts->dhchap_ctrl_secret)
+ return sysfs_emit(buf, "none\n");
+ return sysfs_emit(buf, "%s\n", opts->dhchap_ctrl_secret);
+}
+
+static ssize_t nvme_ctrl_dhchap_ctrl_secret_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+ struct nvmf_ctrl_options *opts = ctrl->opts;
+ char *dhchap_secret;
+
+ if (!ctrl->opts->dhchap_ctrl_secret)
+ return -EINVAL;
+ if (count < 7)
+ return -EINVAL;
+ if (memcmp(buf, "DHHC-1:", 7))
+ return -EINVAL;
+
+ dhchap_secret = kzalloc(count + 1, GFP_KERNEL);
+ if (!dhchap_secret)
+ return -ENOMEM;
+ memcpy(dhchap_secret, buf, count);
+ nvme_auth_stop(ctrl);
+ if (strcmp(dhchap_secret, opts->dhchap_ctrl_secret)) {
+ struct nvme_dhchap_key *key, *ctrl_key;
+ int ret;
+
+ ret = nvme_auth_generate_key(dhchap_secret, &key);
+ if (ret) {
+ kfree(dhchap_secret);
+ return ret;
+ }
+ kfree(opts->dhchap_ctrl_secret);
+ opts->dhchap_ctrl_secret = dhchap_secret;
+ ctrl_key = ctrl->ctrl_key;
+ mutex_lock(&ctrl->dhchap_auth_mutex);
+ ctrl->ctrl_key = key;
+ mutex_unlock(&ctrl->dhchap_auth_mutex);
+ nvme_auth_free_key(ctrl_key);
+ } else
+ kfree(dhchap_secret);
+ /* Start re-authentication */
+ dev_info(ctrl->device, "re-authenticating controller\n");
+ queue_work(nvme_wq, &ctrl->dhchap_auth_work);
+
+ return count;
+}
+
+static DEVICE_ATTR(dhchap_ctrl_secret, S_IRUGO | S_IWUSR,
+ nvme_ctrl_dhchap_ctrl_secret_show, nvme_ctrl_dhchap_ctrl_secret_store);
+#endif
+
+static struct attribute *nvme_dev_attrs[] = {
+ &dev_attr_reset_controller.attr,
+ &dev_attr_rescan_controller.attr,
+ &dev_attr_model.attr,
+ &dev_attr_serial.attr,
+ &dev_attr_firmware_rev.attr,
+ &dev_attr_cntlid.attr,
+ &dev_attr_delete_controller.attr,
+ &dev_attr_transport.attr,
+ &dev_attr_subsysnqn.attr,
+ &dev_attr_address.attr,
+ &dev_attr_state.attr,
+ &dev_attr_numa_node.attr,
+ &dev_attr_queue_count.attr,
+ &dev_attr_sqsize.attr,
+ &dev_attr_hostnqn.attr,
+ &dev_attr_hostid.attr,
+ &dev_attr_ctrl_loss_tmo.attr,
+ &dev_attr_reconnect_delay.attr,
+ &dev_attr_fast_io_fail_tmo.attr,
+ &dev_attr_kato.attr,
+ &dev_attr_cntrltype.attr,
+ &dev_attr_dctype.attr,
+#ifdef CONFIG_NVME_AUTH
+ &dev_attr_dhchap_secret.attr,
+ &dev_attr_dhchap_ctrl_secret.attr,
+#endif
+ NULL
+};
+
+static umode_t nvme_dev_attrs_are_visible(struct kobject *kobj,
+ struct attribute *a, int n)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+
+ if (a == &dev_attr_delete_controller.attr && !ctrl->ops->delete_ctrl)
+ return 0;
+ if (a == &dev_attr_address.attr && !ctrl->ops->get_address)
+ return 0;
+ if (a == &dev_attr_hostnqn.attr && !ctrl->opts)
+ return 0;
+ if (a == &dev_attr_hostid.attr && !ctrl->opts)
+ return 0;
+ if (a == &dev_attr_ctrl_loss_tmo.attr && !ctrl->opts)
+ return 0;
+ if (a == &dev_attr_reconnect_delay.attr && !ctrl->opts)
+ return 0;
+ if (a == &dev_attr_fast_io_fail_tmo.attr && !ctrl->opts)
+ return 0;
+#ifdef CONFIG_NVME_AUTH
+ if (a == &dev_attr_dhchap_secret.attr && !ctrl->opts)
+ return 0;
+ if (a == &dev_attr_dhchap_ctrl_secret.attr && !ctrl->opts)
+ return 0;
+#endif
+
+ return a->mode;
+}
+
+const struct attribute_group nvme_dev_attrs_group = {
+ .attrs = nvme_dev_attrs,
+ .is_visible = nvme_dev_attrs_are_visible,
+};
+EXPORT_SYMBOL_GPL(nvme_dev_attrs_group);
+
+const struct attribute_group *nvme_dev_attr_groups[] = {
+ &nvme_dev_attrs_group,
+ NULL,
+};
+
+#define SUBSYS_ATTR_RO(_name, _mode, _show) \
+ struct device_attribute subsys_attr_##_name = \
+ __ATTR(_name, _mode, _show, NULL)
+
+static ssize_t nvme_subsys_show_nqn(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct nvme_subsystem *subsys =
+ container_of(dev, struct nvme_subsystem, dev);
+
+ return sysfs_emit(buf, "%s\n", subsys->subnqn);
+}
+static SUBSYS_ATTR_RO(subsysnqn, S_IRUGO, nvme_subsys_show_nqn);
+
+static ssize_t nvme_subsys_show_type(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct nvme_subsystem *subsys =
+ container_of(dev, struct nvme_subsystem, dev);
+
+ switch (subsys->subtype) {
+ case NVME_NQN_DISC:
+ return sysfs_emit(buf, "discovery\n");
+ case NVME_NQN_NVME:
+ return sysfs_emit(buf, "nvm\n");
+ default:
+ return sysfs_emit(buf, "reserved\n");
+ }
+}
+static SUBSYS_ATTR_RO(subsystype, S_IRUGO, nvme_subsys_show_type);
+
+#define nvme_subsys_show_str_function(field) \
+static ssize_t subsys_##field##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct nvme_subsystem *subsys = \
+ container_of(dev, struct nvme_subsystem, dev); \
+ return sysfs_emit(buf, "%.*s\n", \
+ (int)sizeof(subsys->field), subsys->field); \
+} \
+static SUBSYS_ATTR_RO(field, S_IRUGO, subsys_##field##_show);
+
+nvme_subsys_show_str_function(model);
+nvme_subsys_show_str_function(serial);
+nvme_subsys_show_str_function(firmware_rev);
+
+static struct attribute *nvme_subsys_attrs[] = {
+ &subsys_attr_model.attr,
+ &subsys_attr_serial.attr,
+ &subsys_attr_firmware_rev.attr,
+ &subsys_attr_subsysnqn.attr,
+ &subsys_attr_subsystype.attr,
+#ifdef CONFIG_NVME_MULTIPATH
+ &subsys_attr_iopolicy.attr,
+#endif
+ NULL,
+};
+
+static const struct attribute_group nvme_subsys_attrs_group = {
+ .attrs = nvme_subsys_attrs,
+};
+
+const struct attribute_group *nvme_subsys_attrs_groups[] = {
+ &nvme_subsys_attrs_group,
+ NULL,
+};
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index bf0230442d57..5b332d9f87fc 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
@@ -997,25 +997,28 @@ static int nvme_tcp_try_send_data(struct nvme_tcp_request *req)
u32 h2cdata_left = req->h2cdata_left;
while (true) {
+ struct bio_vec bvec;
+ struct msghdr msg = {
+ .msg_flags = MSG_DONTWAIT | MSG_SPLICE_PAGES,
+ };
struct page *page = nvme_tcp_req_cur_page(req);
size_t offset = nvme_tcp_req_cur_offset(req);
size_t len = nvme_tcp_req_cur_length(req);
bool last = nvme_tcp_pdu_last_send(req, len);
int req_data_sent = req->data_sent;
- int ret, flags = MSG_DONTWAIT;
+ int ret;
if (last && !queue->data_digest && !nvme_tcp_queue_more(queue))
- flags |= MSG_EOR;
+ msg.msg_flags |= MSG_EOR;
else
- flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST;
+ msg.msg_flags |= MSG_MORE;
- if (sendpage_ok(page)) {
- ret = kernel_sendpage(queue->sock, page, offset, len,
- flags);
- } else {
- ret = sock_no_sendpage(queue->sock, page, offset, len,
- flags);
- }
+ if (!sendpage_ok(page))
+ msg.msg_flags &= ~MSG_SPLICE_PAGES;
+
+ bvec_set_page(&bvec, page, len, offset);
+ iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, len);
+ ret = sock_sendmsg(queue->sock, &msg);
if (ret <= 0)
return ret;
@@ -1054,22 +1057,24 @@ static int nvme_tcp_try_send_cmd_pdu(struct nvme_tcp_request *req)
{
struct nvme_tcp_queue *queue = req->queue;
struct nvme_tcp_cmd_pdu *pdu = nvme_tcp_req_cmd_pdu(req);
+ struct bio_vec bvec;
+ struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_SPLICE_PAGES, };
bool inline_data = nvme_tcp_has_inline_data(req);
u8 hdgst = nvme_tcp_hdgst_len(queue);
int len = sizeof(*pdu) + hdgst - req->offset;
- int flags = MSG_DONTWAIT;
int ret;
if (inline_data || nvme_tcp_queue_more(queue))
- flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST;
+ msg.msg_flags |= MSG_MORE;
else
- flags |= MSG_EOR;
+ msg.msg_flags |= MSG_EOR;
if (queue->hdr_digest && !req->offset)
nvme_tcp_hdgst(queue->snd_hash, pdu, sizeof(*pdu));
- ret = kernel_sendpage(queue->sock, virt_to_page(pdu),
- offset_in_page(pdu) + req->offset, len, flags);
+ bvec_set_virt(&bvec, (void *)pdu + req->offset, len);
+ iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, len);
+ ret = sock_sendmsg(queue->sock, &msg);
if (unlikely(ret <= 0))
return ret;
@@ -1093,6 +1098,8 @@ static int nvme_tcp_try_send_data_pdu(struct nvme_tcp_request *req)
{
struct nvme_tcp_queue *queue = req->queue;
struct nvme_tcp_data_pdu *pdu = nvme_tcp_req_data_pdu(req);
+ struct bio_vec bvec;
+ struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_MORE, };
u8 hdgst = nvme_tcp_hdgst_len(queue);
int len = sizeof(*pdu) - req->offset + hdgst;
int ret;
@@ -1101,13 +1108,11 @@ static int nvme_tcp_try_send_data_pdu(struct nvme_tcp_request *req)
nvme_tcp_hdgst(queue->snd_hash, pdu, sizeof(*pdu));
if (!req->h2cdata_left)
- ret = kernel_sendpage(queue->sock, virt_to_page(pdu),
- offset_in_page(pdu) + req->offset, len,
- MSG_DONTWAIT | MSG_MORE | MSG_SENDPAGE_NOTLAST);
- else
- ret = sock_no_sendpage(queue->sock, virt_to_page(pdu),
- offset_in_page(pdu) + req->offset, len,
- MSG_DONTWAIT | MSG_MORE);
+ msg.msg_flags |= MSG_SPLICE_PAGES;
+
+ bvec_set_virt(&bvec, (void *)pdu + req->offset, len);
+ iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, len);
+ ret = sock_sendmsg(queue->sock, &msg);
if (unlikely(ret <= 0))
return ret;
@@ -1802,58 +1807,12 @@ out_free_queues:
return ret;
}
-static unsigned int nvme_tcp_nr_io_queues(struct nvme_ctrl *ctrl)
-{
- unsigned int nr_io_queues;
-
- nr_io_queues = min(ctrl->opts->nr_io_queues, num_online_cpus());
- nr_io_queues += min(ctrl->opts->nr_write_queues, num_online_cpus());
- nr_io_queues += min(ctrl->opts->nr_poll_queues, num_online_cpus());
-
- return nr_io_queues;
-}
-
-static void nvme_tcp_set_io_queues(struct nvme_ctrl *nctrl,
- unsigned int nr_io_queues)
-{
- struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
- struct nvmf_ctrl_options *opts = nctrl->opts;
-
- if (opts->nr_write_queues && opts->nr_io_queues < nr_io_queues) {
- /*
- * separate read/write queues
- * hand out dedicated default queues only after we have
- * sufficient read queues.
- */
- ctrl->io_queues[HCTX_TYPE_READ] = opts->nr_io_queues;
- nr_io_queues -= ctrl->io_queues[HCTX_TYPE_READ];
- ctrl->io_queues[HCTX_TYPE_DEFAULT] =
- min(opts->nr_write_queues, nr_io_queues);
- nr_io_queues -= ctrl->io_queues[HCTX_TYPE_DEFAULT];
- } else {
- /*
- * shared read/write queues
- * either no write queues were requested, or we don't have
- * sufficient queue count to have dedicated default queues.
- */
- ctrl->io_queues[HCTX_TYPE_DEFAULT] =
- min(opts->nr_io_queues, nr_io_queues);
- nr_io_queues -= ctrl->io_queues[HCTX_TYPE_DEFAULT];
- }
-
- if (opts->nr_poll_queues && nr_io_queues) {
- /* map dedicated poll queues only if we have queues left */
- ctrl->io_queues[HCTX_TYPE_POLL] =
- min(opts->nr_poll_queues, nr_io_queues);
- }
-}
-
static int nvme_tcp_alloc_io_queues(struct nvme_ctrl *ctrl)
{
unsigned int nr_io_queues;
int ret;
- nr_io_queues = nvme_tcp_nr_io_queues(ctrl);
+ nr_io_queues = nvmf_nr_io_queues(ctrl->opts);
ret = nvme_set_queue_count(ctrl, &nr_io_queues);
if (ret)
return ret;
@@ -1868,8 +1827,8 @@ static int nvme_tcp_alloc_io_queues(struct nvme_ctrl *ctrl)
dev_info(ctrl->device,
"creating %d I/O queues.\n", nr_io_queues);
- nvme_tcp_set_io_queues(ctrl, nr_io_queues);
-
+ nvmf_set_io_queues(ctrl->opts, nr_io_queues,
+ to_tcp_ctrl(ctrl)->io_queues);
return __nvme_tcp_alloc_io_queues(ctrl);
}
@@ -1909,6 +1868,7 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new)
goto out_cleanup_connect_q;
if (!new) {
+ nvme_start_freeze(ctrl);
nvme_unquiesce_io_queues(ctrl);
if (!nvme_wait_freeze_timeout(ctrl, NVME_IO_TIMEOUT)) {
/*
@@ -1917,6 +1877,7 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new)
* to be safe.
*/
ret = -ENODEV;
+ nvme_unfreeze(ctrl);
goto out_wait_freeze_timed_out;
}
blk_mq_update_nr_hw_queues(ctrl->tagset,
@@ -2021,7 +1982,6 @@ static void nvme_tcp_teardown_io_queues(struct nvme_ctrl *ctrl,
if (ctrl->queue_count <= 1)
return;
nvme_quiesce_admin_queue(ctrl);
- nvme_start_freeze(ctrl);
nvme_quiesce_io_queues(ctrl);
nvme_sync_io_queues(ctrl);
nvme_tcp_stop_io_queues(ctrl);
@@ -2449,44 +2409,8 @@ static blk_status_t nvme_tcp_queue_rq(struct blk_mq_hw_ctx *hctx,
static void nvme_tcp_map_queues(struct blk_mq_tag_set *set)
{
struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(set->driver_data);
- struct nvmf_ctrl_options *opts = ctrl->ctrl.opts;
-
- if (opts->nr_write_queues && ctrl->io_queues[HCTX_TYPE_READ]) {
- /* separate read/write queues */
- set->map[HCTX_TYPE_DEFAULT].nr_queues =
- ctrl->io_queues[HCTX_TYPE_DEFAULT];
- set->map[HCTX_TYPE_DEFAULT].queue_offset = 0;
- set->map[HCTX_TYPE_READ].nr_queues =
- ctrl->io_queues[HCTX_TYPE_READ];
- set->map[HCTX_TYPE_READ].queue_offset =
- ctrl->io_queues[HCTX_TYPE_DEFAULT];
- } else {
- /* shared read/write queues */
- set->map[HCTX_TYPE_DEFAULT].nr_queues =
- ctrl->io_queues[HCTX_TYPE_DEFAULT];
- set->map[HCTX_TYPE_DEFAULT].queue_offset = 0;
- set->map[HCTX_TYPE_READ].nr_queues =
- ctrl->io_queues[HCTX_TYPE_DEFAULT];
- set->map[HCTX_TYPE_READ].queue_offset = 0;
- }
- blk_mq_map_queues(&set->map[HCTX_TYPE_DEFAULT]);
- blk_mq_map_queues(&set->map[HCTX_TYPE_READ]);
-
- if (opts->nr_poll_queues && ctrl->io_queues[HCTX_TYPE_POLL]) {
- /* map dedicated poll queues only if we have queues left */
- set->map[HCTX_TYPE_POLL].nr_queues =
- ctrl->io_queues[HCTX_TYPE_POLL];
- set->map[HCTX_TYPE_POLL].queue_offset =
- ctrl->io_queues[HCTX_TYPE_DEFAULT] +
- ctrl->io_queues[HCTX_TYPE_READ];
- blk_mq_map_queues(&set->map[HCTX_TYPE_POLL]);
- }
-
- dev_info(ctrl->ctrl.device,
- "mapped %d/%d/%d default/read/poll queues.\n",
- ctrl->io_queues[HCTX_TYPE_DEFAULT],
- ctrl->io_queues[HCTX_TYPE_READ],
- ctrl->io_queues[HCTX_TYPE_POLL]);
+
+ nvmf_map_queues(set, &ctrl->ctrl, ctrl->io_queues);
}
static int nvme_tcp_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob)
diff --git a/drivers/nvme/host/zns.c b/drivers/nvme/host/zns.c
index 12316ab51bda..ec8557810c21 100644
--- a/drivers/nvme/host/zns.c
+++ b/drivers/nvme/host/zns.c
@@ -10,12 +10,11 @@
int nvme_revalidate_zones(struct nvme_ns *ns)
{
struct request_queue *q = ns->queue;
- int ret;
- ret = blk_revalidate_disk_zones(ns->disk, NULL);
- if (!ret)
- blk_queue_max_zone_append_sectors(q, ns->ctrl->max_zone_append);
- return ret;
+ blk_queue_chunk_sectors(q, ns->zsze);
+ blk_queue_max_zone_append_sectors(q, ns->ctrl->max_zone_append);
+
+ return blk_revalidate_disk_zones(ns->disk, NULL);
}
static int nvme_set_max_append(struct nvme_ctrl *ctrl)
diff --git a/drivers/nvme/target/fabrics-cmd-auth.c b/drivers/nvme/target/fabrics-cmd-auth.c
index 7970a7640e58..586458f765f1 100644
--- a/drivers/nvme/target/fabrics-cmd-auth.c
+++ b/drivers/nvme/target/fabrics-cmd-auth.c
@@ -295,13 +295,11 @@ void nvmet_execute_auth_send(struct nvmet_req *req)
status = 0;
}
goto done_kfree;
- break;
case NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2:
req->sq->authenticated = true;
pr_debug("%s: ctrl %d qid %d ctrl authenticated\n",
__func__, ctrl->cntlid, req->sq->qid);
goto done_kfree;
- break;
case NVME_AUTH_DHCHAP_MESSAGE_FAILURE2:
status = nvmet_auth_failure2(d);
if (status) {
@@ -312,7 +310,6 @@ void nvmet_execute_auth_send(struct nvmet_req *req)
status = 0;
}
goto done_kfree;
- break;
default:
req->sq->dhchap_status =
NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE;
@@ -320,7 +317,6 @@ void nvmet_execute_auth_send(struct nvmet_req *req)
NVME_AUTH_DHCHAP_MESSAGE_FAILURE2;
req->sq->authenticated = false;
goto done_kfree;
- break;
}
done_failure1:
req->sq->dhchap_status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE;
@@ -483,15 +479,6 @@ void nvmet_execute_auth_receive(struct nvmet_req *req)
status = NVME_SC_INTERNAL;
break;
}
- if (status) {
- req->sq->dhchap_status = status;
- nvmet_auth_failure1(req, d, al);
- pr_warn("ctrl %d qid %d: challenge status (%x)\n",
- ctrl->cntlid, req->sq->qid,
- req->sq->dhchap_status);
- status = 0;
- break;
- }
req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_REPLY;
break;
case NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1:
diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c
index e940a7d37a9d..c65a73433c05 100644
--- a/drivers/nvme/target/fcloop.c
+++ b/drivers/nvme/target/fcloop.c
@@ -645,8 +645,6 @@ fcloop_fcp_recv_work(struct work_struct *work)
}
if (ret)
fcloop_call_host_done(fcpreq, tfcp_req, ret);
-
- return;
}
static void
@@ -1168,7 +1166,8 @@ __wait_localport_unreg(struct fcloop_lport *lport)
ret = nvme_fc_unregister_localport(lport->localport);
- wait_for_completion(&lport->unreg_done);
+ if (!ret)
+ wait_for_completion(&lport->unreg_done);
kfree(lport);
diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c
index c2d6cea0236b..2733e0158585 100644
--- a/drivers/nvme/target/io-cmd-bdev.c
+++ b/drivers/nvme/target/io-cmd-bdev.c
@@ -51,7 +51,7 @@ void nvmet_bdev_set_limits(struct block_device *bdev, struct nvme_id_ns *id)
void nvmet_bdev_ns_disable(struct nvmet_ns *ns)
{
if (ns->bdev) {
- blkdev_put(ns->bdev, FMODE_WRITE | FMODE_READ);
+ blkdev_put(ns->bdev, NULL);
ns->bdev = NULL;
}
}
@@ -85,7 +85,7 @@ int nvmet_bdev_ns_enable(struct nvmet_ns *ns)
return -ENOTBLK;
ns->bdev = blkdev_get_by_path(ns->device_path,
- FMODE_READ | FMODE_WRITE, NULL);
+ BLK_OPEN_READ | BLK_OPEN_WRITE, NULL, NULL);
if (IS_ERR(ns->bdev)) {
ret = PTR_ERR(ns->bdev);
if (ret != -ENOTBLK) {
diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c
index f2d24b2d992f..48d5df054cd0 100644
--- a/drivers/nvme/target/loop.c
+++ b/drivers/nvme/target/loop.c
@@ -373,7 +373,7 @@ static int nvme_loop_configure_admin_queue(struct nvme_loop_ctrl *ctrl)
goto out_cleanup_tagset;
ctrl->ctrl.max_hw_sectors =
- (NVME_LOOP_MAX_SEGMENTS - 1) << (PAGE_SHIFT - 9);
+ (NVME_LOOP_MAX_SEGMENTS - 1) << PAGE_SECTORS_SHIFT;
nvme_unquiesce_admin_queue(&ctrl->ctrl);
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index dc60a22646f7..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;
@@ -109,8 +109,8 @@ struct nvmet_sq {
u32 sqhd;
bool sqhd_disabled;
#ifdef CONFIG_NVME_TARGET_AUTH
- struct delayed_work auth_expired_work;
bool authenticated;
+ struct delayed_work auth_expired_work;
u16 dhchap_tid;
u16 dhchap_status;
int dhchap_step;
diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c
index 71a9c1cc57f5..9fe07d7efa96 100644
--- a/drivers/nvme/target/passthru.c
+++ b/drivers/nvme/target/passthru.c
@@ -102,14 +102,14 @@ static u16 nvmet_passthru_override_id_ctrl(struct nvmet_req *req)
* which depends on the host's memory fragementation. To solve this,
* ensure mdts is limited to the pages equal to the number of segments.
*/
- max_hw_sectors = min_not_zero(pctrl->max_segments << (PAGE_SHIFT - 9),
+ max_hw_sectors = min_not_zero(pctrl->max_segments << PAGE_SECTORS_SHIFT,
pctrl->max_hw_sectors);
/*
* nvmet_passthru_map_sg is limitted to using a single bio so limit
* the mdts based on BIO_MAX_VECS as well
*/
- max_hw_sectors = min_not_zero(BIO_MAX_VECS << (PAGE_SHIFT - 9),
+ max_hw_sectors = min_not_zero(BIO_MAX_VECS << PAGE_SECTORS_SHIFT,
max_hw_sectors);
page_shift = NVME_CAP_MPSMIN(ctrl->cap) + 12;
diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
index ed98df72c76b..868aa4de2e4c 100644
--- a/drivers/nvme/target/tcp.c
+++ b/drivers/nvme/target/tcp.c
@@ -576,13 +576,17 @@ static void nvmet_tcp_execute_request(struct nvmet_tcp_cmd *cmd)
static int nvmet_try_send_data_pdu(struct nvmet_tcp_cmd *cmd)
{
+ struct msghdr msg = {
+ .msg_flags = MSG_DONTWAIT | MSG_MORE | MSG_SPLICE_PAGES,
+ };
+ struct bio_vec bvec;
u8 hdgst = nvmet_tcp_hdgst_len(cmd->queue);
int left = sizeof(*cmd->data_pdu) - cmd->offset + hdgst;
int ret;
- ret = kernel_sendpage(cmd->queue->sock, virt_to_page(cmd->data_pdu),
- offset_in_page(cmd->data_pdu) + cmd->offset,
- left, MSG_DONTWAIT | MSG_MORE | MSG_SENDPAGE_NOTLAST);
+ bvec_set_virt(&bvec, (void *)cmd->data_pdu + cmd->offset, left);
+ iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, left);
+ ret = sock_sendmsg(cmd->queue->sock, &msg);
if (ret <= 0)
return ret;
@@ -603,17 +607,21 @@ static int nvmet_try_send_data(struct nvmet_tcp_cmd *cmd, bool last_in_batch)
int ret;
while (cmd->cur_sg) {
+ struct msghdr msg = {
+ .msg_flags = MSG_DONTWAIT | MSG_SPLICE_PAGES,
+ };
struct page *page = sg_page(cmd->cur_sg);
+ struct bio_vec bvec;
u32 left = cmd->cur_sg->length - cmd->offset;
- int flags = MSG_DONTWAIT;
if ((!last_in_batch && cmd->queue->send_list_len) ||
cmd->wbytes_done + left < cmd->req.transfer_len ||
queue->data_digest || !queue->nvme_sq.sqhd_disabled)
- flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST;
+ msg.msg_flags |= MSG_MORE;
- ret = kernel_sendpage(cmd->queue->sock, page, cmd->offset,
- left, flags);
+ bvec_set_page(&bvec, page, left, cmd->offset);
+ iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, left);
+ ret = sock_sendmsg(cmd->queue->sock, &msg);
if (ret <= 0)
return ret;
@@ -649,18 +657,20 @@ static int nvmet_try_send_data(struct nvmet_tcp_cmd *cmd, bool last_in_batch)
static int nvmet_try_send_response(struct nvmet_tcp_cmd *cmd,
bool last_in_batch)
{
+ struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_SPLICE_PAGES, };
+ struct bio_vec bvec;
u8 hdgst = nvmet_tcp_hdgst_len(cmd->queue);
int left = sizeof(*cmd->rsp_pdu) - cmd->offset + hdgst;
- int flags = MSG_DONTWAIT;
int ret;
if (!last_in_batch && cmd->queue->send_list_len)
- flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST;
+ msg.msg_flags |= MSG_MORE;
else
- flags |= MSG_EOR;
+ msg.msg_flags |= MSG_EOR;
- ret = kernel_sendpage(cmd->queue->sock, virt_to_page(cmd->rsp_pdu),
- offset_in_page(cmd->rsp_pdu) + cmd->offset, left, flags);
+ bvec_set_virt(&bvec, (void *)cmd->rsp_pdu + cmd->offset, left);
+ iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, left);
+ ret = sock_sendmsg(cmd->queue->sock, &msg);
if (ret <= 0)
return ret;
cmd->offset += ret;
@@ -677,18 +687,20 @@ static int nvmet_try_send_response(struct nvmet_tcp_cmd *cmd,
static int nvmet_try_send_r2t(struct nvmet_tcp_cmd *cmd, bool last_in_batch)
{
+ struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_SPLICE_PAGES, };
+ struct bio_vec bvec;
u8 hdgst = nvmet_tcp_hdgst_len(cmd->queue);
int left = sizeof(*cmd->r2t_pdu) - cmd->offset + hdgst;
- int flags = MSG_DONTWAIT;
int ret;
if (!last_in_batch && cmd->queue->send_list_len)
- flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST;
+ msg.msg_flags |= MSG_MORE;
else
- flags |= MSG_EOR;
+ msg.msg_flags |= MSG_EOR;
- ret = kernel_sendpage(cmd->queue->sock, virt_to_page(cmd->r2t_pdu),
- offset_in_page(cmd->r2t_pdu) + cmd->offset, left, flags);
+ bvec_set_virt(&bvec, (void *)cmd->r2t_pdu + cmd->offset, left);
+ iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, left);
+ ret = sock_sendmsg(cmd->queue->sock, &msg);
if (ret <= 0)
return ret;
cmd->offset += ret;
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/Kconfig b/drivers/of/Kconfig
index e40f10bf2ba4..da9826accb1b 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -55,7 +55,7 @@ config OF_FLATTREE
config OF_EARLY_FLATTREE
bool
- select DMA_DECLARE_COHERENT if HAS_DMA
+ select DMA_DECLARE_COHERENT if HAS_DMA && HAS_IOMEM
select OF_FLATTREE
config OF_PROMTREE
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
index e311d406b170..4999636eaa92 100644
--- a/drivers/of/dynamic.c
+++ b/drivers/of/dynamic.c
@@ -63,15 +63,14 @@ int of_reconfig_notifier_unregister(struct notifier_block *nb)
}
EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister);
-#ifdef DEBUG
-const char *action_names[] = {
+static const char *action_names[] = {
+ [0] = "INVALID",
[OF_RECONFIG_ATTACH_NODE] = "ATTACH_NODE",
[OF_RECONFIG_DETACH_NODE] = "DETACH_NODE",
[OF_RECONFIG_ADD_PROPERTY] = "ADD_PROPERTY",
[OF_RECONFIG_REMOVE_PROPERTY] = "REMOVE_PROPERTY",
[OF_RECONFIG_UPDATE_PROPERTY] = "UPDATE_PROPERTY",
};
-#endif
int of_reconfig_notify(unsigned long action, struct of_reconfig_data *p)
{
@@ -620,21 +619,9 @@ static int __of_changeset_entry_apply(struct of_changeset_entry *ce)
}
ret = __of_add_property(ce->np, ce->prop);
- if (ret) {
- pr_err("changeset: add_property failed @%pOF/%s\n",
- ce->np,
- ce->prop->name);
- break;
- }
break;
case OF_RECONFIG_REMOVE_PROPERTY:
ret = __of_remove_property(ce->np, ce->prop);
- if (ret) {
- pr_err("changeset: remove_property failed @%pOF/%s\n",
- ce->np,
- ce->prop->name);
- break;
- }
break;
case OF_RECONFIG_UPDATE_PROPERTY:
@@ -648,20 +635,17 @@ static int __of_changeset_entry_apply(struct of_changeset_entry *ce)
}
ret = __of_update_property(ce->np, ce->prop, &old_prop);
- if (ret) {
- pr_err("changeset: update_property failed @%pOF/%s\n",
- ce->np,
- ce->prop->name);
- break;
- }
break;
default:
ret = -EINVAL;
}
raw_spin_unlock_irqrestore(&devtree_lock, flags);
- if (ret)
+ if (ret) {
+ pr_err("changeset: apply failed: %-15s %pOF:%s\n",
+ action_names[ce->action], ce->np, ce->prop->name);
return ret;
+ }
switch (ce->action) {
case OF_RECONFIG_ATTACH_NODE:
@@ -947,6 +931,9 @@ int of_changeset_action(struct of_changeset *ocs, unsigned long action,
if (!ce)
return -ENOMEM;
+ if (WARN_ON(action >= ARRAY_SIZE(action_names)))
+ return -EINVAL;
+
/* get a reference to the node */
ce->action = action;
ce->np = of_node_get(np);
diff --git a/drivers/of/kexec.c b/drivers/of/kexec.c
index f26d2ba8a371..68278340cecf 100644
--- a/drivers/of/kexec.c
+++ b/drivers/of/kexec.c
@@ -184,7 +184,8 @@ int __init ima_free_kexec_buffer(void)
if (ret)
return ret;
- return memblock_phys_free(addr, size);
+ memblock_free_late(addr, size);
+ return 0;
}
#endif
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..6a557eb866d0 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(of_node_get(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(of_node_get(node)));
dev->dev.parent = parent ? : &platform_bus;
dev->dev.platform_data = platform_data;
if (bus_id)
@@ -553,7 +552,7 @@ static int __init of_platform_default_populate_init(void)
if (!of_get_property(node, "linux,opened", NULL) ||
!of_get_property(node, "linux,boot-display", NULL))
continue;
- dev = of_platform_device_create(node, "of-display.0", NULL);
+ dev = of_platform_device_create(node, "of-display", NULL);
of_node_put(node);
if (WARN_ON(!dev))
return -ENOMEM;
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index 2191c0136531..b545fcb22536 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -664,12 +664,12 @@ static void __init of_unittest_parse_phandle_with_args_map(void)
memset(&args, 0, sizeof(args));
EXPECT_BEGIN(KERN_INFO,
- "OF: /testcase-data/phandle-tests/consumer-b: could not find phandle");
+ "OF: /testcase-data/phandle-tests/consumer-b: could not find phandle 12345678");
rc = of_parse_phandle_with_args_map(np, "phandle-list-bad-phandle",
"phandle", 0, &args);
EXPECT_END(KERN_INFO,
- "OF: /testcase-data/phandle-tests/consumer-b: could not find phandle");
+ "OF: /testcase-data/phandle-tests/consumer-b: could not find phandle 12345678");
unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
@@ -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..8b1dcd537020 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;
@@ -123,6 +121,8 @@ module_param(sba_reserve_agpgart, int, 0444);
MODULE_PARM_DESC(sba_reserve_agpgart, "Reserve half of IO pdir as AGPGART");
#endif
+struct proc_dir_entry *proc_runway_root __ro_after_init;
+struct proc_dir_entry *proc_mckinley_root __ro_after_init;
/************************************
** SBA register read and write support
@@ -332,13 +332,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 +432,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 +492,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 +570,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 +611,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 +795,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 +875,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 +907,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 +944,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 +953,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 +992,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 +1029,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 +1237,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;
@@ -1964,11 +1970,15 @@ static int __init sba_driver_callback(struct parisc_device *dev)
#ifdef CONFIG_PROC_FS
switch (dev->id.hversion) {
case PLUTO_MCKINLEY_PORT:
+ if (!proc_mckinley_root)
+ proc_mckinley_root = proc_mkdir("bus/mckinley", NULL);
root = proc_mckinley_root;
break;
case ASTRO_RUNWAY_PORT:
case IKE_MERCED_PORT:
default:
+ if (!proc_runway_root)
+ proc_runway_root = proc_mkdir("bus/runway", NULL);
root = proc_runway_root;
break;
}
@@ -1992,7 +2002,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 +2022,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 +2064,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/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index 0dcc497b0449..5e4475254bd0 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -28,7 +28,6 @@
#include <linux/sysctl.h>
#include <asm/io.h>
-#include <asm/dma.h>
#include <linux/uaccess.h>
#include <asm/superio.h>
@@ -226,9 +225,9 @@ static int parport_PS2_supported(struct parport *pb)
/* --- Initialisation code -------------------------------- */
-struct parport *parport_gsc_probe_port(unsigned long base,
+static struct parport *parport_gsc_probe_port(unsigned long base,
unsigned long base_hi, int irq,
- int dma, struct parisc_device *padev)
+ struct parisc_device *padev)
{
struct parport_gsc_private *priv;
struct parport_operations *ops;
@@ -250,12 +249,9 @@ struct parport *parport_gsc_probe_port(unsigned long base,
}
priv->ctr = 0xc;
priv->ctr_writable = 0xff;
- priv->dma_buf = NULL;
- priv->dma_handle = 0;
p->base = base;
p->base_hi = base_hi;
p->irq = irq;
- p->dma = dma;
p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT;
p->ops = ops;
p->private_data = priv;
@@ -286,17 +282,9 @@ struct parport *parport_gsc_probe_port(unsigned long base,
if (p->irq == PARPORT_IRQ_AUTO) {
p->irq = PARPORT_IRQ_NONE;
}
- if (p->irq != PARPORT_IRQ_NONE) {
+ if (p->irq != PARPORT_IRQ_NONE)
pr_cont(", irq %d", p->irq);
- if (p->dma == PARPORT_DMA_AUTO) {
- p->dma = PARPORT_DMA_NONE;
- }
- }
- if (p->dma == PARPORT_DMA_AUTO) /* To use DMA, giving the irq
- is mandatory (see above) */
- p->dma = PARPORT_DMA_NONE;
-
pr_cont(" [");
#define printmode(x) \
do { \
@@ -321,7 +309,6 @@ do { \
pr_warn("%s: irq %d in use, resorting to polled operation\n",
p->name, p->irq);
p->irq = PARPORT_IRQ_NONE;
- p->dma = PARPORT_DMA_NONE;
}
}
@@ -369,8 +356,7 @@ static int __init parport_init_chip(struct parisc_device *dev)
pr_info("%s: enhanced parport-modes not supported\n", __func__);
}
- p = parport_gsc_probe_port(port, 0, dev->irq,
- /* PARPORT_IRQ_NONE */ PARPORT_DMA_NONE, dev);
+ p = parport_gsc_probe_port(port, 0, dev->irq, dev);
if (p)
parport_count++;
dev_set_drvdata(&dev->dev, p);
@@ -382,16 +368,10 @@ static void __exit parport_remove_chip(struct parisc_device *dev)
{
struct parport *p = dev_get_drvdata(&dev->dev);
if (p) {
- struct parport_gsc_private *priv = p->private_data;
struct parport_operations *ops = p->ops;
parport_remove_port(p);
- if (p->dma != PARPORT_DMA_NONE)
- free_dma(p->dma);
if (p->irq != PARPORT_IRQ_NONE)
free_irq(p->irq, p);
- if (priv->dma_buf)
- dma_free_coherent(&priv->dev->dev, PAGE_SIZE,
- priv->dma_buf, priv->dma_handle);
kfree (p->private_data);
parport_put_port(p);
kfree (ops); /* hope no-one cached it */
diff --git a/drivers/parport/parport_gsc.h b/drivers/parport/parport_gsc.h
index 9301217edf12..d447a568c257 100644
--- a/drivers/parport/parport_gsc.h
+++ b/drivers/parport/parport_gsc.h
@@ -63,8 +63,6 @@ struct parport_gsc_private {
int writeIntrThreshold;
/* buffer suitable for DMA, if DMA enabled */
- char *dma_buf;
- dma_addr_t dma_handle;
struct pci_dev *dev;
};
@@ -199,9 +197,4 @@ extern void parport_gsc_inc_use_count(void);
extern void parport_gsc_dec_use_count(void);
-extern struct parport *parport_gsc_probe_port(unsigned long base,
- unsigned long base_hi,
- int irq, int dma,
- struct parisc_device *padev);
-
#endif /* __DRIVERS_PARPORT_PARPORT_GSC_H */
diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c
index d740eba3c099..4e5b972c3e26 100644
--- a/drivers/parport/procfs.c
+++ b/drivers/parport/procfs.c
@@ -32,6 +32,13 @@
#define PARPORT_MAX_TIMESLICE_VALUE ((unsigned long) HZ)
#define PARPORT_MIN_SPINTIME_VALUE 1
#define PARPORT_MAX_SPINTIME_VALUE 1000
+/*
+ * PARPORT_BASE_* is the size of the known parts of the sysctl path
+ * in dev/partport/%s/devices/%s. "dev/parport/"(12), "/devices/"(9
+ * and null char(1).
+ */
+#define PARPORT_BASE_PATH_SIZE 13
+#define PARPORT_BASE_DEVICES_PATH_SIZE 22
static int do_active_device(struct ctl_table *table, int write,
void *result, size_t *lenp, loff_t *ppos)
@@ -236,13 +243,6 @@ do { \
return 0;
}
-#define PARPORT_PORT_DIR(CHILD) { .procname = NULL, .mode = 0555, .child = CHILD }
-#define PARPORT_PARPORT_DIR(CHILD) { .procname = "parport", \
- .mode = 0555, .child = CHILD }
-#define PARPORT_DEV_DIR(CHILD) { .procname = "dev", .mode = 0555, .child = CHILD }
-#define PARPORT_DEVICES_ROOT_DIR { .procname = "devices", \
- .mode = 0555, .child = NULL }
-
static const unsigned long parport_min_timeslice_value =
PARPORT_MIN_TIMESLICE_VALUE;
@@ -257,17 +257,16 @@ PARPORT_MAX_SPINTIME_VALUE;
struct parport_sysctl_table {
- struct ctl_table_header *sysctl_header;
+ struct ctl_table_header *port_header;
+ struct ctl_table_header *devices_header;
struct ctl_table vars[12];
struct ctl_table device_dir[2];
- struct ctl_table port_dir[2];
- struct ctl_table parport_dir[2];
- struct ctl_table dev_dir[2];
};
static const struct parport_sysctl_table parport_sysctl_template = {
- .sysctl_header = NULL,
- {
+ .port_header = NULL,
+ .devices_header = NULL,
+ {
{
.procname = "spintime",
.data = NULL,
@@ -305,7 +304,6 @@ static const struct parport_sysctl_table parport_sysctl_template = {
.mode = 0444,
.proc_handler = do_hardware_modes
},
- PARPORT_DEVICES_ROOT_DIR,
#ifdef CONFIG_PARPORT_1284
{
.procname = "autoprobe",
@@ -355,18 +353,6 @@ static const struct parport_sysctl_table parport_sysctl_template = {
},
{}
},
- {
- PARPORT_PORT_DIR(NULL),
- {}
- },
- {
- PARPORT_PARPORT_DIR(NULL),
- {}
- },
- {
- PARPORT_DEV_DIR(NULL),
- {}
- }
};
struct parport_device_sysctl_table
@@ -393,6 +379,7 @@ parport_device_sysctl_template = {
.extra1 = (void*) &parport_min_timeslice_value,
.extra2 = (void*) &parport_max_timeslice_value
},
+ {}
},
{
{
@@ -400,25 +387,8 @@ parport_device_sysctl_template = {
.data = NULL,
.maxlen = 0,
.mode = 0555,
- .child = NULL
},
{}
- },
- {
- PARPORT_DEVICES_ROOT_DIR,
- {}
- },
- {
- PARPORT_PORT_DIR(NULL),
- {}
- },
- {
- PARPORT_PARPORT_DIR(NULL),
- {}
- },
- {
- PARPORT_DEV_DIR(NULL),
- {}
}
};
@@ -454,30 +424,15 @@ parport_default_sysctl_table = {
.extra2 = (void*) &parport_max_spintime_value
},
{}
- },
- {
- {
- .procname = "default",
- .mode = 0555,
- .child = parport_default_sysctl_table.vars
- },
- {}
- },
- {
- PARPORT_PARPORT_DIR(parport_default_sysctl_table.default_dir),
- {}
- },
- {
- PARPORT_DEV_DIR(parport_default_sysctl_table.parport_dir),
- {}
}
};
-
int parport_proc_register(struct parport *port)
{
struct parport_sysctl_table *t;
- int i;
+ char *tmp_dir_path;
+ size_t tmp_path_len, port_name_len;
+ int bytes_written, i, err = 0;
t = kmemdup(&parport_sysctl_template, sizeof(*t), GFP_KERNEL);
if (t == NULL)
@@ -485,28 +440,64 @@ int parport_proc_register(struct parport *port)
t->device_dir[0].extra1 = port;
- for (i = 0; i < 5; i++)
+ t->vars[0].data = &port->spintime;
+ for (i = 0; i < 5; i++) {
t->vars[i].extra1 = port;
+ t->vars[5 + i].extra2 = &port->probe_info[i];
+ }
- t->vars[0].data = &port->spintime;
- t->vars[5].child = t->device_dir;
-
- for (i = 0; i < 5; i++)
- t->vars[6 + i].extra2 = &port->probe_info[i];
+ port_name_len = strnlen(port->name, PARPORT_NAME_MAX_LEN);
+ /*
+ * Allocate a buffer for two paths: dev/parport/PORT and dev/parport/PORT/devices.
+ * We calculate for the second as that will give us enough for the first.
+ */
+ tmp_path_len = PARPORT_BASE_DEVICES_PATH_SIZE + port_name_len;
+ tmp_dir_path = kzalloc(tmp_path_len, GFP_KERNEL);
+ if (!tmp_dir_path) {
+ err = -ENOMEM;
+ goto exit_free_t;
+ }
- t->port_dir[0].procname = port->name;
+ bytes_written = snprintf(tmp_dir_path, tmp_path_len,
+ "dev/parport/%s/devices", port->name);
+ if (tmp_path_len <= bytes_written) {
+ err = -ENOENT;
+ goto exit_free_tmp_dir_path;
+ }
+ t->devices_header = register_sysctl(tmp_dir_path, t->device_dir);
+ if (t->devices_header == NULL) {
+ err = -ENOENT;
+ goto exit_free_tmp_dir_path;
+ }
- t->port_dir[0].child = t->vars;
- t->parport_dir[0].child = t->port_dir;
- t->dev_dir[0].child = t->parport_dir;
+ tmp_path_len = PARPORT_BASE_PATH_SIZE + port_name_len;
+ bytes_written = snprintf(tmp_dir_path, tmp_path_len,
+ "dev/parport/%s", port->name);
+ if (tmp_path_len <= bytes_written) {
+ err = -ENOENT;
+ goto unregister_devices_h;
+ }
- t->sysctl_header = register_sysctl_table(t->dev_dir);
- if (t->sysctl_header == NULL) {
- kfree(t);
- t = NULL;
+ t->port_header = register_sysctl(tmp_dir_path, t->vars);
+ if (t->port_header == NULL) {
+ err = -ENOENT;
+ goto unregister_devices_h;
}
+
port->sysctl_table = t;
+
+ kfree(tmp_dir_path);
return 0;
+
+unregister_devices_h:
+ unregister_sysctl_table(t->devices_header);
+
+exit_free_tmp_dir_path:
+ kfree(tmp_dir_path);
+
+exit_free_t:
+ kfree(t);
+ return err;
}
int parport_proc_unregister(struct parport *port)
@@ -514,7 +505,8 @@ int parport_proc_unregister(struct parport *port)
if (port->sysctl_table) {
struct parport_sysctl_table *t = port->sysctl_table;
port->sysctl_table = NULL;
- unregister_sysctl_table(t->sysctl_header);
+ unregister_sysctl_table(t->devices_header);
+ unregister_sysctl_table(t->port_header);
kfree(t);
}
return 0;
@@ -522,30 +514,53 @@ int parport_proc_unregister(struct parport *port)
int parport_device_proc_register(struct pardevice *device)
{
+ int bytes_written, err = 0;
struct parport_device_sysctl_table *t;
struct parport * port = device->port;
+ size_t port_name_len, device_name_len, tmp_dir_path_len;
+ char *tmp_dir_path;
t = kmemdup(&parport_device_sysctl_template, sizeof(*t), GFP_KERNEL);
if (t == NULL)
return -ENOMEM;
- t->dev_dir[0].child = t->parport_dir;
- t->parport_dir[0].child = t->port_dir;
- t->port_dir[0].procname = port->name;
- t->port_dir[0].child = t->devices_root_dir;
- t->devices_root_dir[0].child = t->device_dir;
+ port_name_len = strnlen(port->name, PARPORT_NAME_MAX_LEN);
+ device_name_len = strnlen(device->name, PATH_MAX);
+
+ /* Allocate a buffer for two paths: dev/parport/PORT/devices/DEVICE. */
+ tmp_dir_path_len = PARPORT_BASE_DEVICES_PATH_SIZE + port_name_len + device_name_len;
+ tmp_dir_path = kzalloc(tmp_dir_path_len, GFP_KERNEL);
+ if (!tmp_dir_path) {
+ err = -ENOMEM;
+ goto exit_free_t;
+ }
+
+ bytes_written = snprintf(tmp_dir_path, tmp_dir_path_len, "dev/parport/%s/devices/%s",
+ port->name, device->name);
+ if (tmp_dir_path_len <= bytes_written) {
+ err = -ENOENT;
+ goto exit_free_path;
+ }
- t->device_dir[0].procname = device->name;
- t->device_dir[0].child = t->vars;
t->vars[0].data = &device->timeslice;
- t->sysctl_header = register_sysctl_table(t->dev_dir);
+ t->sysctl_header = register_sysctl(tmp_dir_path, t->vars);
if (t->sysctl_header == NULL) {
kfree(t);
t = NULL;
}
device->sysctl_table = t;
+
+ kfree(tmp_dir_path);
return 0;
+
+exit_free_path:
+ kfree(tmp_dir_path);
+
+exit_free_t:
+ kfree(t);
+
+ return err;
}
int parport_device_proc_unregister(struct pardevice *device)
@@ -564,7 +579,7 @@ static int __init parport_default_proc_register(void)
int ret;
parport_default_sysctl_table.sysctl_header =
- register_sysctl_table(parport_default_sysctl_table.dev_dir);
+ register_sysctl("dev/parport/default", parport_default_sysctl_table.vars);
if (!parport_default_sysctl_table.sysctl_header)
return -ENOMEM;
ret = parport_bus_init();
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index 62f8407923d4..2d46b1d4fd69 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -467,7 +467,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
atomic_set(&tmp->ref_count, 1);
INIT_LIST_HEAD(&tmp->full_list);
- name = kmalloc(15, GFP_KERNEL);
+ name = kmalloc(PARPORT_NAME_MAX_LEN, GFP_KERNEL);
if (!name) {
kfree(tmp);
return NULL;
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 9309f2469b41..3c07d8d214b3 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -168,6 +168,7 @@ config PCI_P2PDMA
#
depends on 64BIT
select GENERIC_ALLOCATOR
+ select NEED_SG_DMA_FLAGS
help
Enableѕ drivers to do PCI peer-to-peer transactions to and from
BARs that are exposed in other devices that are the part of
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 5bc81cc0a2de..46b252bbe500 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -11,6 +11,7 @@
#include <linux/pci.h>
#include <linux/errno.h>
#include <linux/ioport.h>
+#include <linux/of.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
@@ -332,6 +333,7 @@ void __weak pcibios_bus_add_device(struct pci_dev *pdev) { }
*/
void pci_bus_add_device(struct pci_dev *dev)
{
+ struct device_node *dn = dev->dev.of_node;
int retval;
/*
@@ -344,7 +346,7 @@ void pci_bus_add_device(struct pci_dev *dev)
pci_proc_attach_device(dev);
pci_bridge_d3_update(dev);
- dev->match_driver = true;
+ dev->match_driver = !dn || of_device_is_available(dn);
retval = device_attach(&dev->dev);
if (retval < 0 && retval != -EPROBE_DEFER)
pci_warn(dev, "device attach failed (%d)\n", retval);
diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
index 8d49bad7f847..0859be86e718 100644
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -179,7 +179,6 @@ config PCI_MVEBU
depends on MVEBU_MBUS
depends on ARM
depends on OF
- depends on BROKEN
select PCI_BRIDGE_EMUL
help
Add support for Marvell EBU PCIe controller. This PCIe controller
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.c b/drivers/pci/controller/dwc/pcie-designware.c
index 8e33e6e59e68..1f2ee71da4da 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -828,7 +828,7 @@ static int dw_pcie_edma_irq_vector(struct device *dev, unsigned int nr)
return platform_get_irq_byname_optional(pdev, name);
}
-static struct dw_edma_core_ops dw_pcie_edma_ops = {
+static struct dw_edma_plat_ops dw_pcie_edma_ops = {
.irq_vector = dw_pcie_edma_irq_vector,
};
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..c8b423c3c26e 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
@@ -1285,6 +1285,7 @@ static int pci_vntb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return 0;
err_register_dev:
+ put_device(&ndev->ntb.dev);
return -EINVAL;
}
@@ -1395,13 +1396,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..601129772b2d 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -512,12 +512,15 @@ 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);
+ if (pci_is_root_bus(bus))
+ __pci_bus_size_bridges(dev->subordinate, &add_list);
}
}
}
- __pci_bus_assign_resources(bus, &add_list, NULL);
+ if (pci_is_root_bus(bus))
+ __pci_bus_assign_resources(bus, &add_list, NULL);
+ else
+ 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..3c158b17dcb5 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -34,21 +34,14 @@ int pci_set_of_node(struct pci_dev *dev)
if (!node)
return 0;
- if (!of_device_is_available(node)) {
- of_node_put(node);
- 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 +56,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 711f82400086..f4572a5cca72 100644
--- a/drivers/perf/Kconfig
+++ b/drivers/perf/Kconfig
@@ -127,6 +127,14 @@ config FSL_IMX8_DDR_PMU
can give information about memory throughput and other related
events.
+config FSL_IMX9_DDR_PMU
+ tristate "Freescale i.MX9 DDR perf monitor"
+ depends on ARCH_MXC
+ help
+ Provides support for the DDR performance monitor in i.MX9, which
+ can give information about memory throughput and other related
+ events.
+
config QCOM_L2_PMU
bool "Qualcomm Technologies L2-cache PMU"
depends on ARCH_QCOM && ARM64 && ACPI
@@ -213,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 dabc859540ce..16b3ec4db916 100644
--- a/drivers/perf/Makefile
+++ b/drivers/perf/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_ARM_PMU_ACPI) += arm_pmu_acpi.o
obj-$(CONFIG_ARM_PMUV3) += arm_pmuv3.o
obj-$(CONFIG_ARM_SMMU_V3_PMU) += arm_smmuv3_pmu.o
obj-$(CONFIG_FSL_IMX8_DDR_PMU) += fsl_imx8_ddr_perf.o
+obj-$(CONFIG_FSL_IMX9_DDR_PMU) += fsl_imx9_ddr_perf.o
obj-$(CONFIG_HISI_PMU) += hisilicon/
obj-$(CONFIG_QCOM_L2_PMU) += qcom_l2_pmu.o
obj-$(CONFIG_QCOM_L3_PMU) += qcom_l3_pmu.o
@@ -24,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/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
index 8574c6e58c83..cd2de44b61b9 100644
--- a/drivers/perf/apple_m1_cpu_pmu.c
+++ b/drivers/perf/apple_m1_cpu_pmu.c
@@ -493,6 +493,17 @@ static int m1_pmu_map_event(struct perf_event *event)
return armpmu_map_event(event, &m1_pmu_perf_map, NULL, M1_PMU_CFG_EVENT);
}
+static int m2_pmu_map_event(struct perf_event *event)
+{
+ /*
+ * Same deal as the above, except that M2 has 64bit counters.
+ * Which, as far as we're concerned, actually means 63 bits.
+ * Yes, this is getting awkward.
+ */
+ event->hw.flags |= ARMPMU_EVT_63BIT;
+ return armpmu_map_event(event, &m1_pmu_perf_map, NULL, M1_PMU_CFG_EVENT);
+}
+
static void m1_pmu_reset(void *info)
{
int i;
@@ -525,7 +536,7 @@ static int m1_pmu_set_event_filter(struct hw_perf_event *event,
return 0;
}
-static int m1_pmu_init(struct arm_pmu *cpu_pmu)
+static int m1_pmu_init(struct arm_pmu *cpu_pmu, u32 flags)
{
cpu_pmu->handle_irq = m1_pmu_handle_irq;
cpu_pmu->enable = m1_pmu_enable_event;
@@ -536,7 +547,14 @@ static int m1_pmu_init(struct arm_pmu *cpu_pmu)
cpu_pmu->clear_event_idx = m1_pmu_clear_event_idx;
cpu_pmu->start = m1_pmu_start;
cpu_pmu->stop = m1_pmu_stop;
- cpu_pmu->map_event = m1_pmu_map_event;
+
+ if (flags & ARMPMU_EVT_47BIT)
+ cpu_pmu->map_event = m1_pmu_map_event;
+ else if (flags & ARMPMU_EVT_63BIT)
+ cpu_pmu->map_event = m2_pmu_map_event;
+ else
+ return WARN_ON(-EINVAL);
+
cpu_pmu->reset = m1_pmu_reset;
cpu_pmu->set_event_filter = m1_pmu_set_event_filter;
@@ -550,25 +568,25 @@ static int m1_pmu_init(struct arm_pmu *cpu_pmu)
static int m1_pmu_ice_init(struct arm_pmu *cpu_pmu)
{
cpu_pmu->name = "apple_icestorm_pmu";
- return m1_pmu_init(cpu_pmu);
+ return m1_pmu_init(cpu_pmu, ARMPMU_EVT_47BIT);
}
static int m1_pmu_fire_init(struct arm_pmu *cpu_pmu)
{
cpu_pmu->name = "apple_firestorm_pmu";
- return m1_pmu_init(cpu_pmu);
+ return m1_pmu_init(cpu_pmu, ARMPMU_EVT_47BIT);
}
static int m2_pmu_avalanche_init(struct arm_pmu *cpu_pmu)
{
cpu_pmu->name = "apple_avalanche_pmu";
- return m1_pmu_init(cpu_pmu);
+ return m1_pmu_init(cpu_pmu, ARMPMU_EVT_63BIT);
}
static int m2_pmu_blizzard_init(struct arm_pmu *cpu_pmu)
{
cpu_pmu->name = "apple_blizzard_pmu";
- return m1_pmu_init(cpu_pmu);
+ return m1_pmu_init(cpu_pmu, ARMPMU_EVT_63BIT);
}
static const struct of_device_id m1_pmu_of_device_ids[] = {
diff --git a/drivers/perf/arm-cci.c b/drivers/perf/arm-cci.c
index 03b1309875ae..998259f1d973 100644
--- a/drivers/perf/arm-cci.c
+++ b/drivers/perf/arm-cci.c
@@ -645,7 +645,7 @@ static void cci_pmu_sync_counters(struct cci_pmu *cci_pmu)
struct cci_pmu_hw_events *cci_hw = &cci_pmu->hw_events;
DECLARE_BITMAP(mask, HW_CNTRS_MAX);
- bitmap_zero(mask, cci_pmu->num_cntrs);
+ bitmap_zero(mask, HW_CNTRS_MAX);
for_each_set_bit(i, cci_pmu->hw_events.used_mask, cci_pmu->num_cntrs) {
struct perf_event *event = cci_hw->events[i];
@@ -656,7 +656,7 @@ static void cci_pmu_sync_counters(struct cci_pmu *cci_pmu)
if (event->hw.state & PERF_HES_STOPPED)
continue;
if (event->hw.state & PERF_HES_ARCH) {
- set_bit(i, mask);
+ __set_bit(i, mask);
event->hw.state &= ~PERF_HES_ARCH;
}
}
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index 47d359f72957..b8c15878bc86 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -44,8 +44,11 @@
#define CMN_MAX_DTMS (CMN_MAX_XPS + (CMN_MAX_DIMENSION - 1) * 4)
/* The CFG node has various info besides the discovery tree */
-#define CMN_CFGM_PERIPH_ID_2 0x0010
-#define CMN_CFGM_PID2_REVISION GENMASK(7, 4)
+#define CMN_CFGM_PERIPH_ID_01 0x0008
+#define CMN_CFGM_PID0_PART_0 GENMASK_ULL(7, 0)
+#define CMN_CFGM_PID1_PART_1 GENMASK_ULL(35, 32)
+#define CMN_CFGM_PERIPH_ID_23 0x0010
+#define CMN_CFGM_PID2_REVISION GENMASK_ULL(7, 4)
#define CMN_CFGM_INFO_GLOBAL 0x900
#define CMN_INFO_MULTIPLE_DTM_EN BIT_ULL(63)
@@ -186,6 +189,7 @@
#define CMN_WP_DOWN 2
+/* Internal values for encoding event support */
enum cmn_model {
CMN600 = 1,
CMN650 = 2,
@@ -197,26 +201,34 @@ enum cmn_model {
CMN_650ON = CMN650 | CMN700,
};
+/* Actual part numbers and revision IDs defined by the hardware */
+enum cmn_part {
+ PART_CMN600 = 0x434,
+ PART_CMN650 = 0x436,
+ PART_CMN700 = 0x43c,
+ PART_CI700 = 0x43a,
+};
+
/* CMN-600 r0px shouldn't exist in silicon, thankfully */
enum cmn_revision {
- CMN600_R1P0,
- CMN600_R1P1,
- CMN600_R1P2,
- CMN600_R1P3,
- CMN600_R2P0,
- CMN600_R3P0,
- CMN600_R3P1,
- CMN650_R0P0 = 0,
- CMN650_R1P0,
- CMN650_R1P1,
- CMN650_R2P0,
- CMN650_R1P2,
- CMN700_R0P0 = 0,
- CMN700_R1P0,
- CMN700_R2P0,
- CI700_R0P0 = 0,
- CI700_R1P0,
- CI700_R2P0,
+ REV_CMN600_R1P0,
+ REV_CMN600_R1P1,
+ REV_CMN600_R1P2,
+ REV_CMN600_R1P3,
+ REV_CMN600_R2P0,
+ REV_CMN600_R3P0,
+ REV_CMN600_R3P1,
+ REV_CMN650_R0P0 = 0,
+ REV_CMN650_R1P0,
+ REV_CMN650_R1P1,
+ REV_CMN650_R2P0,
+ REV_CMN650_R1P2,
+ REV_CMN700_R0P0 = 0,
+ REV_CMN700_R1P0,
+ REV_CMN700_R2P0,
+ REV_CI700_R0P0 = 0,
+ REV_CI700_R1P0,
+ REV_CI700_R2P0,
};
enum cmn_node_type {
@@ -306,7 +318,7 @@ struct arm_cmn {
unsigned int state;
enum cmn_revision rev;
- enum cmn_model model;
+ enum cmn_part part;
u8 mesh_x;
u8 mesh_y;
u16 num_xps;
@@ -394,19 +406,35 @@ static struct arm_cmn_node *arm_cmn_node(const struct arm_cmn *cmn,
return NULL;
}
+static enum cmn_model arm_cmn_model(const struct arm_cmn *cmn)
+{
+ switch (cmn->part) {
+ case PART_CMN600:
+ return CMN600;
+ case PART_CMN650:
+ return CMN650;
+ case PART_CMN700:
+ return CMN700;
+ case PART_CI700:
+ return CI700;
+ default:
+ return 0;
+ };
+}
+
static u32 arm_cmn_device_connect_info(const struct arm_cmn *cmn,
const struct arm_cmn_node *xp, int port)
{
int offset = CMN_MXP__CONNECT_INFO(port);
if (port >= 2) {
- if (cmn->model & (CMN600 | CMN650))
+ if (cmn->part == PART_CMN600 || cmn->part == PART_CMN650)
return 0;
/*
* CI-700 may have extra ports, but still has the
* mesh_port_connect_info registers in the way.
*/
- if (cmn->model == CI700)
+ if (cmn->part == PART_CI700)
offset += CI700_CONNECT_INFO_P2_5_OFFSET;
}
@@ -640,7 +668,7 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
eattr = container_of(attr, typeof(*eattr), attr.attr);
- if (!(eattr->model & cmn->model))
+ if (!(eattr->model & arm_cmn_model(cmn)))
return 0;
type = eattr->type;
@@ -658,7 +686,7 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
if ((intf & 4) && !(cmn->ports_used & BIT(intf & 3)))
return 0;
- if (chan == 4 && cmn->model == CMN600)
+ if (chan == 4 && cmn->part == PART_CMN600)
return 0;
if ((chan == 5 && cmn->rsp_vc_num < 2) ||
@@ -669,19 +697,19 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
}
/* Revision-specific differences */
- if (cmn->model == CMN600) {
- if (cmn->rev < CMN600_R1P3) {
+ if (cmn->part == PART_CMN600) {
+ if (cmn->rev < REV_CMN600_R1P3) {
if (type == CMN_TYPE_CXRA && eventid > 0x10)
return 0;
}
- if (cmn->rev < CMN600_R1P2) {
+ if (cmn->rev < REV_CMN600_R1P2) {
if (type == CMN_TYPE_HNF && eventid == 0x1b)
return 0;
if (type == CMN_TYPE_CXRA || type == CMN_TYPE_CXHA)
return 0;
}
- } else if (cmn->model == CMN650) {
- if (cmn->rev < CMN650_R2P0 || cmn->rev == CMN650_R1P2) {
+ } else if (cmn->part == PART_CMN650) {
+ if (cmn->rev < REV_CMN650_R2P0 || cmn->rev == REV_CMN650_R1P2) {
if (type == CMN_TYPE_HNF && eventid > 0x22)
return 0;
if (type == CMN_TYPE_SBSX && eventid == 0x17)
@@ -689,8 +717,8 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
if (type == CMN_TYPE_RNI && eventid > 0x10)
return 0;
}
- } else if (cmn->model == CMN700) {
- if (cmn->rev < CMN700_R2P0) {
+ } else if (cmn->part == PART_CMN700) {
+ if (cmn->rev < REV_CMN700_R2P0) {
if (type == CMN_TYPE_HNF && eventid > 0x2c)
return 0;
if (type == CMN_TYPE_CCHA && eventid > 0x74)
@@ -698,7 +726,7 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
if (type == CMN_TYPE_CCLA && eventid > 0x27)
return 0;
}
- if (cmn->rev < CMN700_R1P0) {
+ if (cmn->rev < REV_CMN700_R1P0) {
if (type == CMN_TYPE_HNF && eventid > 0x2b)
return 0;
}
@@ -1171,19 +1199,31 @@ static ssize_t arm_cmn_cpumask_show(struct device *dev,
static struct device_attribute arm_cmn_cpumask_attr =
__ATTR(cpumask, 0444, arm_cmn_cpumask_show, NULL);
-static struct attribute *arm_cmn_cpumask_attrs[] = {
+static ssize_t arm_cmn_identifier_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct arm_cmn *cmn = to_cmn(dev_get_drvdata(dev));
+
+ return sysfs_emit(buf, "%03x%02x\n", cmn->part, cmn->rev);
+}
+
+static struct device_attribute arm_cmn_identifier_attr =
+ __ATTR(identifier, 0444, arm_cmn_identifier_show, NULL);
+
+static struct attribute *arm_cmn_other_attrs[] = {
&arm_cmn_cpumask_attr.attr,
+ &arm_cmn_identifier_attr.attr,
NULL,
};
-static const struct attribute_group arm_cmn_cpumask_attr_group = {
- .attrs = arm_cmn_cpumask_attrs,
+static const struct attribute_group arm_cmn_other_attrs_group = {
+ .attrs = arm_cmn_other_attrs,
};
static const struct attribute_group *arm_cmn_attr_groups[] = {
&arm_cmn_event_attrs_group,
&arm_cmn_format_attrs_group,
- &arm_cmn_cpumask_attr_group,
+ &arm_cmn_other_attrs_group,
NULL
};
@@ -1200,7 +1240,7 @@ static u32 arm_cmn_wp_config(struct perf_event *event)
u32 grp = CMN_EVENT_WP_GRP(event);
u32 exc = CMN_EVENT_WP_EXCLUSIVE(event);
u32 combine = CMN_EVENT_WP_COMBINE(event);
- bool is_cmn600 = to_cmn(event->pmu)->model == CMN600;
+ bool is_cmn600 = to_cmn(event->pmu)->part == PART_CMN600;
config = FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_DEV_SEL, dev) |
FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_CHN_SEL, chn) |
@@ -1520,14 +1560,14 @@ done:
return ret;
}
-static enum cmn_filter_select arm_cmn_filter_sel(enum cmn_model model,
+static enum cmn_filter_select arm_cmn_filter_sel(const struct arm_cmn *cmn,
enum cmn_node_type type,
unsigned int eventid)
{
struct arm_cmn_event_attr *e;
- int i;
+ enum cmn_model model = arm_cmn_model(cmn);
- for (i = 0; i < ARRAY_SIZE(arm_cmn_event_attrs) - 1; i++) {
+ for (int i = 0; i < ARRAY_SIZE(arm_cmn_event_attrs) - 1; i++) {
e = container_of(arm_cmn_event_attrs[i], typeof(*e), attr.attr);
if (e->model & model && e->type == type && e->eventid == eventid)
return e->fsel;
@@ -1570,12 +1610,12 @@ static int arm_cmn_event_init(struct perf_event *event)
/* ...but the DTM may depend on which port we're watching */
if (cmn->multi_dtm)
hw->dtm_offset = CMN_EVENT_WP_DEV_SEL(event) / 2;
- } else if (type == CMN_TYPE_XP && cmn->model == CMN700) {
+ } else if (type == CMN_TYPE_XP && cmn->part == PART_CMN700) {
hw->wide_sel = true;
}
/* This is sufficiently annoying to recalculate, so cache it */
- hw->filter_sel = arm_cmn_filter_sel(cmn->model, type, eventid);
+ hw->filter_sel = arm_cmn_filter_sel(cmn, type, eventid);
bynodeid = CMN_EVENT_BYNODEID(event);
nodeid = CMN_EVENT_NODEID(event);
@@ -1899,9 +1939,10 @@ static int arm_cmn_init_dtc(struct arm_cmn *cmn, struct arm_cmn_node *dn, int id
if (dtc->irq < 0)
return dtc->irq;
- writel_relaxed(0, dtc->base + CMN_DT_PMCR);
+ writel_relaxed(CMN_DT_DTC_CTL_DT_EN, dtc->base + CMN_DT_DTC_CTL);
+ writel_relaxed(CMN_DT_PMCR_PMU_EN | CMN_DT_PMCR_OVFL_INTR_EN, dtc->base + CMN_DT_PMCR);
+ writeq_relaxed(0, dtc->base + CMN_DT_PMCCNTR);
writel_relaxed(0x1ff, dtc->base + CMN_DT_PMOVSR_CLR);
- writel_relaxed(CMN_DT_PMCR_OVFL_INTR_EN, dtc->base + CMN_DT_PMCR);
return 0;
}
@@ -1961,7 +2002,7 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
dn->type = CMN_TYPE_CCLA;
}
- writel_relaxed(CMN_DT_DTC_CTL_DT_EN, cmn->dtc[0].base + CMN_DT_DTC_CTL);
+ arm_cmn_set_state(cmn, CMN_STATE_DISABLED);
return 0;
}
@@ -2006,6 +2047,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
void __iomem *cfg_region;
struct arm_cmn_node cfg, *dn;
struct arm_cmn_dtm *dtm;
+ enum cmn_part part;
u16 child_count, child_poff;
u32 xp_offset[CMN_MAX_XPS];
u64 reg;
@@ -2017,7 +2059,19 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
return -ENODEV;
cfg_region = cmn->base + rgn_offset;
- reg = readl_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_2);
+
+ reg = readq_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_01);
+ part = FIELD_GET(CMN_CFGM_PID0_PART_0, reg);
+ part |= FIELD_GET(CMN_CFGM_PID1_PART_1, reg) << 8;
+ if (cmn->part && cmn->part != part)
+ dev_warn(cmn->dev,
+ "Firmware binding mismatch: expected part number 0x%x, found 0x%x\n",
+ cmn->part, part);
+ cmn->part = part;
+ if (!arm_cmn_model(cmn))
+ dev_warn(cmn->dev, "Unknown part number: 0x%x\n", part);
+
+ reg = readl_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_23);
cmn->rev = FIELD_GET(CMN_CFGM_PID2_REVISION, reg);
reg = readq_relaxed(cfg_region + CMN_CFGM_INFO_GLOBAL);
@@ -2081,7 +2135,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
if (xp->id == (1 << 3))
cmn->mesh_x = xp->logid;
- if (cmn->model == CMN600)
+ if (cmn->part == PART_CMN600)
xp->dtc = 0xf;
else
xp->dtc = 1 << readl_relaxed(xp_region + CMN_DTM_UNIT_INFO);
@@ -2201,7 +2255,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
if (cmn->num_xps == 1)
dev_warn(cmn->dev, "1x1 config not fully supported, translate XP events manually\n");
- dev_dbg(cmn->dev, "model %d, periph_id_2 revision %d\n", cmn->model, cmn->rev);
+ dev_dbg(cmn->dev, "periph_id part 0x%03x revision %d\n", cmn->part, cmn->rev);
reg = cmn->ports_used;
dev_dbg(cmn->dev, "mesh %dx%d, ID width %d, ports %6pbl%s\n",
cmn->mesh_x, cmn->mesh_y, arm_cmn_xyidbits(cmn), &reg,
@@ -2256,17 +2310,17 @@ static int arm_cmn_probe(struct platform_device *pdev)
return -ENOMEM;
cmn->dev = &pdev->dev;
- cmn->model = (unsigned long)device_get_match_data(cmn->dev);
+ cmn->part = (unsigned long)device_get_match_data(cmn->dev);
platform_set_drvdata(pdev, cmn);
- if (cmn->model == CMN600 && has_acpi_companion(cmn->dev)) {
+ if (cmn->part == PART_CMN600 && has_acpi_companion(cmn->dev)) {
rootnode = arm_cmn600_acpi_probe(pdev, cmn);
} else {
rootnode = 0;
cmn->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(cmn->base))
return PTR_ERR(cmn->base);
- if (cmn->model == CMN600)
+ if (cmn->part == PART_CMN600)
rootnode = arm_cmn600_of_probe(pdev->dev.of_node);
}
if (rootnode < 0)
@@ -2335,10 +2389,10 @@ static int arm_cmn_remove(struct platform_device *pdev)
#ifdef CONFIG_OF
static const struct of_device_id arm_cmn_of_match[] = {
- { .compatible = "arm,cmn-600", .data = (void *)CMN600 },
- { .compatible = "arm,cmn-650", .data = (void *)CMN650 },
- { .compatible = "arm,cmn-700", .data = (void *)CMN700 },
- { .compatible = "arm,ci-700", .data = (void *)CI700 },
+ { .compatible = "arm,cmn-600", .data = (void *)PART_CMN600 },
+ { .compatible = "arm,cmn-650" },
+ { .compatible = "arm,cmn-700" },
+ { .compatible = "arm,ci-700" },
{}
};
MODULE_DEVICE_TABLE(of, arm_cmn_of_match);
@@ -2346,9 +2400,9 @@ MODULE_DEVICE_TABLE(of, arm_cmn_of_match);
#ifdef CONFIG_ACPI
static const struct acpi_device_id arm_cmn_acpi_match[] = {
- { "ARMHC600", CMN600 },
- { "ARMHC650", CMN650 },
- { "ARMHC700", CMN700 },
+ { "ARMHC600", PART_CMN600 },
+ { "ARMHC650" },
+ { "ARMHC700" },
{}
};
MODULE_DEVICE_TABLE(acpi, arm_cmn_acpi_match);
diff --git a/drivers/perf/arm_cspmu/Kconfig b/drivers/perf/arm_cspmu/Kconfig
index 0b316fe69a45..25d25ded0983 100644
--- a/drivers/perf/arm_cspmu/Kconfig
+++ b/drivers/perf/arm_cspmu/Kconfig
@@ -4,8 +4,7 @@
config ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU
tristate "ARM Coresight Architecture PMU"
- depends on ARM64 && ACPI
- depends on ACPI_APMT || COMPILE_TEST
+ depends on ARM64 || COMPILE_TEST
help
Provides support for performance monitoring unit (PMU) devices
based on ARM CoreSight PMU architecture. Note that this PMU
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
index a3f1c410b417..e2b7827c4563 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.c
+++ b/drivers/perf/arm_cspmu/arm_cspmu.c
@@ -28,7 +28,6 @@
#include <linux/module.h>
#include <linux/perf_event.h>
#include <linux/platform_device.h>
-#include <acpi/processor.h>
#include "arm_cspmu.h"
#include "nvidia_cspmu.h"
@@ -101,10 +100,6 @@
#define ARM_CSPMU_ACTIVE_CPU_MASK 0x0
#define ARM_CSPMU_ASSOCIATED_CPU_MASK 0x1
-/* Check if field f in flags is set with value v */
-#define CHECK_APMT_FLAG(flags, f, v) \
- ((flags & (ACPI_APMT_FLAGS_ ## f)) == (ACPI_APMT_FLAGS_ ## f ## _ ## v))
-
/* Check and use default if implementer doesn't provide attribute callback */
#define CHECK_DEFAULT_IMPL_OPS(ops, callback) \
do { \
@@ -122,6 +117,11 @@
static unsigned long arm_cspmu_cpuhp_state;
+static struct acpi_apmt_node *arm_cspmu_apmt_node(struct device *dev)
+{
+ return *(struct acpi_apmt_node **)dev_get_platdata(dev);
+}
+
/*
* In CoreSight PMU architecture, all of the MMIO registers are 32-bit except
* counter register. The counter register can be implemented as 32-bit or 64-bit
@@ -156,12 +156,6 @@ static u64 read_reg64_hilohi(const void __iomem *addr, u32 max_poll_count)
return val;
}
-/* Check if PMU supports 64-bit single copy atomic. */
-static inline bool supports_64bit_atomics(const struct arm_cspmu *cspmu)
-{
- return CHECK_APMT_FLAG(cspmu->apmt_node->flags, ATOMIC, SUPP);
-}
-
/* Check if cycle counter is supported. */
static inline bool supports_cycle_counter(const struct arm_cspmu *cspmu)
{
@@ -189,10 +183,10 @@ static inline bool use_64b_counter_reg(const struct arm_cspmu *cspmu)
ssize_t arm_cspmu_sysfs_event_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct dev_ext_attribute *eattr =
- container_of(attr, struct dev_ext_attribute, attr);
- return sysfs_emit(buf, "event=0x%llx\n",
- (unsigned long long)eattr->var);
+ struct perf_pmu_events_attr *pmu_attr;
+
+ pmu_attr = container_of(attr, typeof(*pmu_attr), attr);
+ return sysfs_emit(buf, "event=0x%llx\n", pmu_attr->id);
}
EXPORT_SYMBOL_GPL(arm_cspmu_sysfs_event_show);
@@ -320,7 +314,7 @@ static const char *arm_cspmu_get_name(const struct arm_cspmu *cspmu)
static atomic_t pmu_idx[ACPI_APMT_NODE_TYPE_COUNT] = { 0 };
dev = cspmu->dev;
- apmt_node = cspmu->apmt_node;
+ apmt_node = arm_cspmu_apmt_node(dev);
pmu_type = apmt_node->type;
if (pmu_type >= ACPI_APMT_NODE_TYPE_COUNT) {
@@ -397,8 +391,8 @@ static const struct impl_match impl_match[] = {
static int arm_cspmu_init_impl_ops(struct arm_cspmu *cspmu)
{
int ret;
- struct acpi_apmt_node *apmt_node = cspmu->apmt_node;
struct arm_cspmu_impl_ops *impl_ops = &cspmu->impl.ops;
+ struct acpi_apmt_node *apmt_node = arm_cspmu_apmt_node(cspmu->dev);
const struct impl_match *match = impl_match;
/*
@@ -720,7 +714,7 @@ static u64 arm_cspmu_read_counter(struct perf_event *event)
offset = counter_offset(sizeof(u64), event->hw.idx);
counter_addr = cspmu->base1 + offset;
- return supports_64bit_atomics(cspmu) ?
+ return cspmu->has_atomic_dword ?
readq(counter_addr) :
read_reg64_hilohi(counter_addr, HILOHI_MAX_POLL);
}
@@ -911,24 +905,18 @@ static struct arm_cspmu *arm_cspmu_alloc(struct platform_device *pdev)
{
struct acpi_apmt_node *apmt_node;
struct arm_cspmu *cspmu;
- struct device *dev;
-
- dev = &pdev->dev;
- apmt_node = *(struct acpi_apmt_node **)dev_get_platdata(dev);
- if (!apmt_node) {
- dev_err(dev, "failed to get APMT node\n");
- return NULL;
- }
+ struct device *dev = &pdev->dev;
cspmu = devm_kzalloc(dev, sizeof(*cspmu), GFP_KERNEL);
if (!cspmu)
return NULL;
cspmu->dev = dev;
- cspmu->apmt_node = apmt_node;
-
platform_set_drvdata(pdev, cspmu);
+ apmt_node = arm_cspmu_apmt_node(dev);
+ cspmu->has_atomic_dword = apmt_node->flags & ACPI_APMT_FLAGS_ATOMIC;
+
return cspmu;
}
@@ -936,11 +924,9 @@ static int arm_cspmu_init_mmio(struct arm_cspmu *cspmu)
{
struct device *dev;
struct platform_device *pdev;
- struct acpi_apmt_node *apmt_node;
dev = cspmu->dev;
pdev = to_platform_device(dev);
- apmt_node = cspmu->apmt_node;
/* Base address for page 0. */
cspmu->base0 = devm_platform_ioremap_resource(pdev, 0);
@@ -951,7 +937,7 @@ static int arm_cspmu_init_mmio(struct arm_cspmu *cspmu)
/* Base address for page 1 if supported. Otherwise point to page 0. */
cspmu->base1 = cspmu->base0;
- if (CHECK_APMT_FLAG(apmt_node->flags, DUAL_PAGE, SUPP)) {
+ if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) {
cspmu->base1 = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(cspmu->base1)) {
dev_err(dev, "ioremap failed for page-1 resource\n");
@@ -1048,19 +1034,14 @@ static int arm_cspmu_request_irq(struct arm_cspmu *cspmu)
int irq, ret;
struct device *dev;
struct platform_device *pdev;
- struct acpi_apmt_node *apmt_node;
dev = cspmu->dev;
pdev = to_platform_device(dev);
- apmt_node = cspmu->apmt_node;
/* Skip IRQ request if the PMU does not support overflow interrupt. */
- if (apmt_node->ovflw_irq == 0)
- return 0;
-
- irq = platform_get_irq(pdev, 0);
+ irq = platform_get_irq_optional(pdev, 0);
if (irq < 0)
- return irq;
+ return irq == -ENXIO ? 0 : irq;
ret = devm_request_irq(dev, irq, arm_cspmu_handle_irq,
IRQF_NOBALANCING | IRQF_NO_THREAD, dev_name(dev),
@@ -1075,6 +1056,9 @@ static int arm_cspmu_request_irq(struct arm_cspmu *cspmu)
return 0;
}
+#if defined(CONFIG_ACPI) && defined(CONFIG_ARM64)
+#include <acpi/processor.h>
+
static inline int arm_cspmu_find_cpu_container(int cpu, u32 container_uid)
{
u32 acpi_uid;
@@ -1099,15 +1083,13 @@ static inline int arm_cspmu_find_cpu_container(int cpu, u32 container_uid)
return -ENODEV;
}
-static int arm_cspmu_get_cpus(struct arm_cspmu *cspmu)
+static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu)
{
- struct device *dev;
struct acpi_apmt_node *apmt_node;
int affinity_flag;
int cpu;
- dev = cspmu->pmu.dev;
- apmt_node = cspmu->apmt_node;
+ apmt_node = arm_cspmu_apmt_node(cspmu->dev);
affinity_flag = apmt_node->flags & ACPI_APMT_FLAGS_AFFINITY;
if (affinity_flag == ACPI_APMT_FLAGS_AFFINITY_PROC) {
@@ -1129,12 +1111,23 @@ static int arm_cspmu_get_cpus(struct arm_cspmu *cspmu)
}
if (cpumask_empty(&cspmu->associated_cpus)) {
- dev_dbg(dev, "No cpu associated with the PMU\n");
+ dev_dbg(cspmu->dev, "No cpu associated with the PMU\n");
return -ENODEV;
}
return 0;
}
+#else
+static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu)
+{
+ return -ENODEV;
+}
+#endif
+
+static int arm_cspmu_get_cpus(struct arm_cspmu *cspmu)
+{
+ return arm_cspmu_acpi_get_cpus(cspmu);
+}
static int arm_cspmu_register_pmu(struct arm_cspmu *cspmu)
{
@@ -1220,6 +1213,12 @@ static int arm_cspmu_device_remove(struct platform_device *pdev)
return 0;
}
+static const struct platform_device_id arm_cspmu_id[] = {
+ {DRVNAME, 0},
+ { },
+};
+MODULE_DEVICE_TABLE(platform, arm_cspmu_id);
+
static struct platform_driver arm_cspmu_driver = {
.driver = {
.name = DRVNAME,
@@ -1227,12 +1226,14 @@ static struct platform_driver arm_cspmu_driver = {
},
.probe = arm_cspmu_device_probe,
.remove = arm_cspmu_device_remove,
+ .id_table = arm_cspmu_id,
};
static void arm_cspmu_set_active_cpu(int cpu, struct arm_cspmu *cspmu)
{
cpumask_set_cpu(cpu, &cspmu->active_cpu);
- WARN_ON(irq_set_affinity(cspmu->irq, &cspmu->active_cpu));
+ if (cspmu->irq)
+ WARN_ON(irq_set_affinity(cspmu->irq, &cspmu->active_cpu));
}
static int arm_cspmu_cpu_online(unsigned int cpu, struct hlist_node *node)
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h
index 51323b175a4a..83df53d1c132 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.h
+++ b/drivers/perf/arm_cspmu/arm_cspmu.h
@@ -8,7 +8,6 @@
#ifndef __ARM_CSPMU_H__
#define __ARM_CSPMU_H__
-#include <linux/acpi.h>
#include <linux/bitfield.h>
#include <linux/cpumask.h>
#include <linux/device.h>
@@ -118,16 +117,16 @@ struct arm_cspmu_impl {
struct arm_cspmu {
struct pmu pmu;
struct device *dev;
- struct acpi_apmt_node *apmt_node;
const char *name;
const char *identifier;
void __iomem *base0;
void __iomem *base1;
- int irq;
cpumask_t associated_cpus;
cpumask_t active_cpu;
struct hlist_node cpuhp_node;
+ int irq;
+ bool has_atomic_dword;
u32 pmcfgr;
u32 num_logical_ctrs;
u32 num_set_clr_reg;
diff --git a/drivers/perf/arm_dmc620_pmu.c b/drivers/perf/arm_dmc620_pmu.c
index 5de06f9a4dd3..9d0f01c4455a 100644
--- a/drivers/perf/arm_dmc620_pmu.c
+++ b/drivers/perf/arm_dmc620_pmu.c
@@ -227,9 +227,31 @@ static const struct attribute_group dmc620_pmu_format_attr_group = {
.attrs = dmc620_pmu_formats_attrs,
};
+static ssize_t dmc620_pmu_cpumask_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dmc620_pmu *dmc620_pmu = to_dmc620_pmu(dev_get_drvdata(dev));
+
+ return cpumap_print_to_pagebuf(true, buf,
+ cpumask_of(dmc620_pmu->irq->cpu));
+}
+
+static struct device_attribute dmc620_pmu_cpumask_attr =
+ __ATTR(cpumask, 0444, dmc620_pmu_cpumask_show, NULL);
+
+static struct attribute *dmc620_pmu_cpumask_attrs[] = {
+ &dmc620_pmu_cpumask_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group dmc620_pmu_cpumask_attr_group = {
+ .attrs = dmc620_pmu_cpumask_attrs,
+};
+
static const struct attribute_group *dmc620_pmu_attr_groups[] = {
&dmc620_pmu_events_attr_group,
&dmc620_pmu_format_attr_group,
+ &dmc620_pmu_cpumask_attr_group,
NULL,
};
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 15bd1e34a88e..f6ccb2cd4dfc 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -109,6 +109,8 @@ static inline u64 arm_pmu_event_max_period(struct perf_event *event)
{
if (event->hw.flags & ARMPMU_EVT_64BIT)
return GENMASK_ULL(63, 0);
+ else if (event->hw.flags & ARMPMU_EVT_63BIT)
+ return GENMASK_ULL(62, 0);
else if (event->hw.flags & ARMPMU_EVT_47BIT)
return GENMASK_ULL(46, 0);
else
@@ -687,6 +689,11 @@ static int armpmu_get_cpu_irq(struct arm_pmu *pmu, int cpu)
return per_cpu(hw_events->irq, cpu);
}
+bool arm_pmu_irq_is_nmi(void)
+{
+ return has_nmi;
+}
+
/*
* PMU hardware loses all context when a CPU goes offline.
* When a CPU is hotplugged back in, since some hardware registers are
diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c
index 93b7edb5f1e7..08b3a1bf0ef6 100644
--- a/drivers/perf/arm_pmuv3.c
+++ b/drivers/perf/arm_pmuv3.c
@@ -22,6 +22,7 @@
#include <linux/platform_device.h>
#include <linux/sched_clock.h>
#include <linux/smp.h>
+#include <linux/nmi.h>
#include <asm/arm_pmuv3.h>
@@ -1363,10 +1364,17 @@ static struct platform_driver armv8_pmu_driver = {
static int __init armv8_pmu_driver_init(void)
{
+ int ret;
+
if (acpi_disabled)
- return platform_driver_register(&armv8_pmu_driver);
+ ret = platform_driver_register(&armv8_pmu_driver);
else
- return arm_pmu_acpi_probe(armv8_pmuv3_pmu_init);
+ ret = arm_pmu_acpi_probe(armv8_pmuv3_pmu_init);
+
+ if (!ret)
+ lockup_detector_retry_init();
+
+ return ret;
}
device_initcall(armv8_pmu_driver_init)
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/fsl_imx9_ddr_perf.c b/drivers/perf/fsl_imx9_ddr_perf.c
new file mode 100644
index 000000000000..71d5b07e3aff
--- /dev/null
+++ b/drivers/perf/fsl_imx9_ddr_perf.c
@@ -0,0 +1,711 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright 2023 NXP
+
+#include <linux/bitfield.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/perf_event.h>
+
+/* Performance monitor configuration */
+#define PMCFG1 0x00
+#define PMCFG1_RD_TRANS_FILT_EN BIT(31)
+#define PMCFG1_WR_TRANS_FILT_EN BIT(30)
+#define PMCFG1_RD_BT_FILT_EN BIT(29)
+#define PMCFG1_ID_MASK GENMASK(17, 0)
+
+#define PMCFG2 0x04
+#define PMCFG2_ID GENMASK(17, 0)
+
+/* Global control register affects all counters and takes priority over local control registers */
+#define PMGC0 0x40
+/* Global control register bits */
+#define PMGC0_FAC BIT(31)
+#define PMGC0_PMIE BIT(30)
+#define PMGC0_FCECE BIT(29)
+
+/*
+ * 64bit counter0 exclusively dedicated to counting cycles
+ * 32bit counters monitor counter-specific events in addition to counting reference events
+ */
+#define PMLCA(n) (0x40 + 0x10 + (0x10 * n))
+#define PMLCB(n) (0x40 + 0x14 + (0x10 * n))
+#define PMC(n) (0x40 + 0x18 + (0x10 * n))
+/* Local control register bits */
+#define PMLCA_FC BIT(31)
+#define PMLCA_CE BIT(26)
+#define PMLCA_EVENT GENMASK(22, 16)
+
+#define NUM_COUNTERS 11
+#define CYCLES_COUNTER 0
+
+#define to_ddr_pmu(p) container_of(p, struct ddr_pmu, pmu)
+
+#define DDR_PERF_DEV_NAME "imx9_ddr"
+#define DDR_CPUHP_CB_NAME DDR_PERF_DEV_NAME "_perf_pmu"
+
+static DEFINE_IDA(ddr_ida);
+
+struct imx_ddr_devtype_data {
+ const char *identifier; /* system PMU identifier for userspace */
+};
+
+struct ddr_pmu {
+ struct pmu pmu;
+ void __iomem *base;
+ unsigned int cpu;
+ struct hlist_node node;
+ struct device *dev;
+ struct perf_event *events[NUM_COUNTERS];
+ int active_events;
+ enum cpuhp_state cpuhp_state;
+ const struct imx_ddr_devtype_data *devtype_data;
+ int irq;
+ int id;
+};
+
+static const struct imx_ddr_devtype_data imx93_devtype_data = {
+ .identifier = "imx93",
+};
+
+static const struct of_device_id imx_ddr_pmu_dt_ids[] = {
+ {.compatible = "fsl,imx93-ddr-pmu", .data = &imx93_devtype_data},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_ddr_pmu_dt_ids);
+
+static ssize_t ddr_perf_identifier_show(struct device *dev,
+ struct device_attribute *attr,
+ char *page)
+{
+ struct ddr_pmu *pmu = dev_get_drvdata(dev);
+
+ return sysfs_emit(page, "%s\n", pmu->devtype_data->identifier);
+}
+
+static struct device_attribute ddr_perf_identifier_attr =
+ __ATTR(identifier, 0444, ddr_perf_identifier_show, NULL);
+
+static struct attribute *ddr_perf_identifier_attrs[] = {
+ &ddr_perf_identifier_attr.attr,
+ NULL,
+};
+
+static struct attribute_group ddr_perf_identifier_attr_group = {
+ .attrs = ddr_perf_identifier_attrs,
+};
+
+static ssize_t ddr_perf_cpumask_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ddr_pmu *pmu = dev_get_drvdata(dev);
+
+ return cpumap_print_to_pagebuf(true, buf, cpumask_of(pmu->cpu));
+}
+
+static struct device_attribute ddr_perf_cpumask_attr =
+ __ATTR(cpumask, 0444, ddr_perf_cpumask_show, NULL);
+
+static struct attribute *ddr_perf_cpumask_attrs[] = {
+ &ddr_perf_cpumask_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group ddr_perf_cpumask_attr_group = {
+ .attrs = ddr_perf_cpumask_attrs,
+};
+
+static ssize_t ddr_pmu_event_show(struct device *dev,
+ struct device_attribute *attr, char *page)
+{
+ struct perf_pmu_events_attr *pmu_attr;
+
+ pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
+ return sysfs_emit(page, "event=0x%02llx\n", pmu_attr->id);
+}
+
+#define IMX9_DDR_PMU_EVENT_ATTR(_name, _id) \
+ (&((struct perf_pmu_events_attr[]) { \
+ { .attr = __ATTR(_name, 0444, ddr_pmu_event_show, NULL),\
+ .id = _id, } \
+ })[0].attr.attr)
+
+static struct attribute *ddr_perf_events_attrs[] = {
+ /* counter0 cycles event */
+ IMX9_DDR_PMU_EVENT_ATTR(cycles, 0),
+
+ /* reference events for all normal counters, need assert DEBUG19[21] bit */
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ddrc1_rmw_for_ecc, 12),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_rreorder, 13),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_wreorder, 14),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_0, 15),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_1, 16),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_2, 17),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_3, 18),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_4, 19),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_5, 22),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_6, 23),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_7, 24),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_8, 25),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_9, 26),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_10, 27),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_11, 28),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_12, 31),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_13, 59),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_15, 61),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_29, 63),
+
+ /* counter1 specific events */
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_0, 64),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_1, 65),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_2, 66),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_3, 67),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_4, 68),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_5, 69),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_6, 70),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_7, 71),
+
+ /* counter2 specific events */
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_0, 64),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_1, 65),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_2, 66),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_3, 67),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_4, 68),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_5, 69),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_6, 70),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_7, 71),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_empty, 72),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_trans_filt, 73),
+
+ /* counter3 specific events */
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_0, 64),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_1, 65),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_2, 66),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_3, 67),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_4, 68),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_5, 69),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_6, 70),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_7, 71),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_full, 72),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pm_wr_trans_filt, 73),
+
+ /* counter4 specific events */
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_0, 64),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_1, 65),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_2, 66),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_3, 67),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_4, 68),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_5, 69),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_6, 70),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_7, 71),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq2_rmw, 72),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_beat_filt, 73),
+
+ /* counter5 specific events */
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_0, 64),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_1, 65),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_2, 66),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_3, 67),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_4, 68),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_5, 69),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_6, 70),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_7, 71),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq1, 72),
+
+ /* counter6 specific events */
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_end_0, 64),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq2, 72),
+
+ /* counter7 specific events */
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_1_2_full, 64),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_wrq0, 65),
+
+ /* counter8 specific events */
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_bias_switched, 64),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_1_4_full, 65),
+
+ /* counter9 specific events */
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_wrq1, 65),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_3_4_full, 66),
+
+ /* counter10 specific events */
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_misc_mrk, 65),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq0, 66),
+ NULL,
+};
+
+static const struct attribute_group ddr_perf_events_attr_group = {
+ .name = "events",
+ .attrs = ddr_perf_events_attrs,
+};
+
+PMU_FORMAT_ATTR(event, "config:0-7");
+PMU_FORMAT_ATTR(counter, "config:8-15");
+PMU_FORMAT_ATTR(axi_id, "config1:0-17");
+PMU_FORMAT_ATTR(axi_mask, "config2:0-17");
+
+static struct attribute *ddr_perf_format_attrs[] = {
+ &format_attr_event.attr,
+ &format_attr_counter.attr,
+ &format_attr_axi_id.attr,
+ &format_attr_axi_mask.attr,
+ NULL,
+};
+
+static const struct attribute_group ddr_perf_format_attr_group = {
+ .name = "format",
+ .attrs = ddr_perf_format_attrs,
+};
+
+static const struct attribute_group *attr_groups[] = {
+ &ddr_perf_identifier_attr_group,
+ &ddr_perf_cpumask_attr_group,
+ &ddr_perf_events_attr_group,
+ &ddr_perf_format_attr_group,
+ NULL,
+};
+
+static void ddr_perf_clear_counter(struct ddr_pmu *pmu, int counter)
+{
+ if (counter == CYCLES_COUNTER) {
+ writel(0, pmu->base + PMC(counter) + 0x4);
+ writel(0, pmu->base + PMC(counter));
+ } else {
+ writel(0, pmu->base + PMC(counter));
+ }
+}
+
+static u64 ddr_perf_read_counter(struct ddr_pmu *pmu, int counter)
+{
+ u32 val_lower, val_upper;
+ u64 val;
+
+ if (counter != CYCLES_COUNTER) {
+ val = readl_relaxed(pmu->base + PMC(counter));
+ goto out;
+ }
+
+ /* special handling for reading 64bit cycle counter */
+ do {
+ val_upper = readl_relaxed(pmu->base + PMC(counter) + 0x4);
+ val_lower = readl_relaxed(pmu->base + PMC(counter));
+ } while (val_upper != readl_relaxed(pmu->base + PMC(counter) + 0x4));
+
+ val = val_upper;
+ val = (val << 32);
+ val |= val_lower;
+out:
+ return val;
+}
+
+static void ddr_perf_counter_global_config(struct ddr_pmu *pmu, bool enable)
+{
+ u32 ctrl;
+
+ ctrl = readl_relaxed(pmu->base + PMGC0);
+
+ if (enable) {
+ /*
+ * The performance monitor must be reset before event counting
+ * sequences. The performance monitor can be reset by first freezing
+ * one or more counters and then clearing the freeze condition to
+ * allow the counters to count according to the settings in the
+ * performance monitor registers. Counters can be frozen individually
+ * by setting PMLCAn[FC] bits, or simultaneously by setting PMGC0[FAC].
+ * Simply clearing these freeze bits will then allow the performance
+ * monitor to begin counting based on the register settings.
+ */
+ ctrl |= PMGC0_FAC;
+ writel(ctrl, pmu->base + PMGC0);
+
+ /*
+ * Freeze all counters disabled, interrupt enabled, and freeze
+ * counters on condition enabled.
+ */
+ ctrl &= ~PMGC0_FAC;
+ ctrl |= PMGC0_PMIE | PMGC0_FCECE;
+ writel(ctrl, pmu->base + PMGC0);
+ } else {
+ ctrl |= PMGC0_FAC;
+ ctrl &= ~(PMGC0_PMIE | PMGC0_FCECE);
+ writel(ctrl, pmu->base + PMGC0);
+ }
+}
+
+static void ddr_perf_counter_local_config(struct ddr_pmu *pmu, int config,
+ int counter, bool enable)
+{
+ u32 ctrl_a;
+
+ ctrl_a = readl_relaxed(pmu->base + PMLCA(counter));
+
+ if (enable) {
+ ctrl_a |= PMLCA_FC;
+ writel(ctrl_a, pmu->base + PMLCA(counter));
+
+ ddr_perf_clear_counter(pmu, counter);
+
+ /* Freeze counter disabled, condition enabled, and program event.*/
+ ctrl_a &= ~PMLCA_FC;
+ ctrl_a |= PMLCA_CE;
+ ctrl_a &= ~FIELD_PREP(PMLCA_EVENT, 0x7F);
+ ctrl_a |= FIELD_PREP(PMLCA_EVENT, (config & 0x000000FF));
+ writel(ctrl_a, pmu->base + PMLCA(counter));
+ } else {
+ /* Freeze counter. */
+ ctrl_a |= PMLCA_FC;
+ writel(ctrl_a, pmu->base + PMLCA(counter));
+ }
+}
+
+static void ddr_perf_monitor_config(struct ddr_pmu *pmu, int cfg, int cfg1, int cfg2)
+{
+ u32 pmcfg1, pmcfg2;
+ int event, counter;
+
+ event = cfg & 0x000000FF;
+ counter = (cfg & 0x0000FF00) >> 8;
+
+ pmcfg1 = readl_relaxed(pmu->base + PMCFG1);
+
+ if (counter == 2 && event == 73)
+ pmcfg1 |= PMCFG1_RD_TRANS_FILT_EN;
+ else if (counter == 2 && event != 73)
+ pmcfg1 &= ~PMCFG1_RD_TRANS_FILT_EN;
+
+ if (counter == 3 && event == 73)
+ pmcfg1 |= PMCFG1_WR_TRANS_FILT_EN;
+ else if (counter == 3 && event != 73)
+ pmcfg1 &= ~PMCFG1_WR_TRANS_FILT_EN;
+
+ if (counter == 4 && event == 73)
+ pmcfg1 |= PMCFG1_RD_BT_FILT_EN;
+ else if (counter == 4 && event != 73)
+ pmcfg1 &= ~PMCFG1_RD_BT_FILT_EN;
+
+ pmcfg1 &= ~FIELD_PREP(PMCFG1_ID_MASK, 0x3FFFF);
+ pmcfg1 |= FIELD_PREP(PMCFG1_ID_MASK, cfg2);
+ writel(pmcfg1, pmu->base + PMCFG1);
+
+ pmcfg2 = readl_relaxed(pmu->base + PMCFG2);
+ pmcfg2 &= ~FIELD_PREP(PMCFG2_ID, 0x3FFFF);
+ pmcfg2 |= FIELD_PREP(PMCFG2_ID, cfg1);
+ writel(pmcfg2, pmu->base + PMCFG2);
+}
+
+static void ddr_perf_event_update(struct perf_event *event)
+{
+ struct ddr_pmu *pmu = to_ddr_pmu(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+ int counter = hwc->idx;
+ u64 new_raw_count;
+
+ new_raw_count = ddr_perf_read_counter(pmu, counter);
+ local64_add(new_raw_count, &event->count);
+
+ /* clear counter's value every time */
+ ddr_perf_clear_counter(pmu, counter);
+}
+
+static int ddr_perf_event_init(struct perf_event *event)
+{
+ struct ddr_pmu *pmu = to_ddr_pmu(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+ struct perf_event *sibling;
+
+ if (event->attr.type != event->pmu->type)
+ return -ENOENT;
+
+ if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
+ return -EOPNOTSUPP;
+
+ if (event->cpu < 0) {
+ dev_warn(pmu->dev, "Can't provide per-task data!\n");
+ return -EOPNOTSUPP;
+ }
+
+ /*
+ * We must NOT create groups containing mixed PMUs, although software
+ * events are acceptable (for example to create a CCN group
+ * periodically read when a hrtimer aka cpu-clock leader triggers).
+ */
+ if (event->group_leader->pmu != event->pmu &&
+ !is_software_event(event->group_leader))
+ return -EINVAL;
+
+ for_each_sibling_event(sibling, event->group_leader) {
+ if (sibling->pmu != event->pmu &&
+ !is_software_event(sibling))
+ return -EINVAL;
+ }
+
+ event->cpu = pmu->cpu;
+ hwc->idx = -1;
+
+ return 0;
+}
+
+static void ddr_perf_event_start(struct perf_event *event, int flags)
+{
+ struct ddr_pmu *pmu = to_ddr_pmu(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+ int counter = hwc->idx;
+
+ local64_set(&hwc->prev_count, 0);
+
+ ddr_perf_counter_local_config(pmu, event->attr.config, counter, true);
+ hwc->state = 0;
+}
+
+static int ddr_perf_event_add(struct perf_event *event, int flags)
+{
+ struct ddr_pmu *pmu = to_ddr_pmu(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+ int cfg = event->attr.config;
+ int cfg1 = event->attr.config1;
+ int cfg2 = event->attr.config2;
+ int counter;
+
+ counter = (cfg & 0x0000FF00) >> 8;
+
+ pmu->events[counter] = event;
+ pmu->active_events++;
+ hwc->idx = counter;
+ hwc->state |= PERF_HES_STOPPED;
+
+ if (flags & PERF_EF_START)
+ ddr_perf_event_start(event, flags);
+
+ /* read trans, write trans, read beat */
+ ddr_perf_monitor_config(pmu, cfg, cfg1, cfg2);
+
+ return 0;
+}
+
+static void ddr_perf_event_stop(struct perf_event *event, int flags)
+{
+ struct ddr_pmu *pmu = to_ddr_pmu(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+ int counter = hwc->idx;
+
+ ddr_perf_counter_local_config(pmu, event->attr.config, counter, false);
+ ddr_perf_event_update(event);
+
+ hwc->state |= PERF_HES_STOPPED;
+}
+
+static void ddr_perf_event_del(struct perf_event *event, int flags)
+{
+ struct ddr_pmu *pmu = to_ddr_pmu(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+
+ ddr_perf_event_stop(event, PERF_EF_UPDATE);
+
+ pmu->active_events--;
+ hwc->idx = -1;
+}
+
+static void ddr_perf_pmu_enable(struct pmu *pmu)
+{
+ struct ddr_pmu *ddr_pmu = to_ddr_pmu(pmu);
+
+ ddr_perf_counter_global_config(ddr_pmu, true);
+}
+
+static void ddr_perf_pmu_disable(struct pmu *pmu)
+{
+ struct ddr_pmu *ddr_pmu = to_ddr_pmu(pmu);
+
+ ddr_perf_counter_global_config(ddr_pmu, false);
+}
+
+static void ddr_perf_init(struct ddr_pmu *pmu, void __iomem *base,
+ struct device *dev)
+{
+ *pmu = (struct ddr_pmu) {
+ .pmu = (struct pmu) {
+ .module = THIS_MODULE,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
+ .task_ctx_nr = perf_invalid_context,
+ .attr_groups = attr_groups,
+ .event_init = ddr_perf_event_init,
+ .add = ddr_perf_event_add,
+ .del = ddr_perf_event_del,
+ .start = ddr_perf_event_start,
+ .stop = ddr_perf_event_stop,
+ .read = ddr_perf_event_update,
+ .pmu_enable = ddr_perf_pmu_enable,
+ .pmu_disable = ddr_perf_pmu_disable,
+ },
+ .base = base,
+ .dev = dev,
+ };
+}
+
+static irqreturn_t ddr_perf_irq_handler(int irq, void *p)
+{
+ struct ddr_pmu *pmu = (struct ddr_pmu *)p;
+ struct perf_event *event;
+ int i;
+
+ /*
+ * Counters can generate an interrupt on an overflow when msb of a
+ * counter changes from 0 to 1. For the interrupt to be signalled,
+ * below condition mush be satisfied:
+ * PMGC0[PMIE] = 1, PMGC0[FCECE] = 1, PMLCAn[CE] = 1
+ * When an interrupt is signalled, PMGC0[FAC] is set by hardware and
+ * all of the registers are frozen.
+ * Software can clear the interrupt condition by resetting the performance
+ * monitor and clearing the most significant bit of the counter that
+ * generate the overflow.
+ */
+ for (i = 0; i < NUM_COUNTERS; i++) {
+ if (!pmu->events[i])
+ continue;
+
+ event = pmu->events[i];
+
+ ddr_perf_event_update(event);
+ }
+
+ ddr_perf_counter_global_config(pmu, true);
+
+ return IRQ_HANDLED;
+}
+
+static int ddr_perf_offline_cpu(unsigned int cpu, struct hlist_node *node)
+{
+ struct ddr_pmu *pmu = hlist_entry_safe(node, struct ddr_pmu, node);
+ int target;
+
+ if (cpu != pmu->cpu)
+ return 0;
+
+ target = cpumask_any_but(cpu_online_mask, cpu);
+ if (target >= nr_cpu_ids)
+ return 0;
+
+ perf_pmu_migrate_context(&pmu->pmu, cpu, target);
+ pmu->cpu = target;
+
+ WARN_ON(irq_set_affinity(pmu->irq, cpumask_of(pmu->cpu)));
+
+ return 0;
+}
+
+static int ddr_perf_probe(struct platform_device *pdev)
+{
+ struct ddr_pmu *pmu;
+ void __iomem *base;
+ int ret, irq;
+ char *name;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ pmu = devm_kzalloc(&pdev->dev, sizeof(*pmu), GFP_KERNEL);
+ if (!pmu)
+ return -ENOMEM;
+
+ ddr_perf_init(pmu, base, &pdev->dev);
+
+ pmu->devtype_data = of_device_get_match_data(&pdev->dev);
+
+ platform_set_drvdata(pdev, pmu);
+
+ pmu->id = ida_simple_get(&ddr_ida, 0, 0, GFP_KERNEL);
+ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, DDR_PERF_DEV_NAME "%d", pmu->id);
+ if (!name) {
+ ret = -ENOMEM;
+ goto format_string_err;
+ }
+
+ pmu->cpu = raw_smp_processor_id();
+ ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, DDR_CPUHP_CB_NAME,
+ NULL, ddr_perf_offline_cpu);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to add callbacks for multi state\n");
+ goto cpuhp_state_err;
+ }
+ pmu->cpuhp_state = ret;
+
+ /* Register the pmu instance for cpu hotplug */
+ ret = cpuhp_state_add_instance_nocalls(pmu->cpuhp_state, &pmu->node);
+ if (ret) {
+ dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
+ goto cpuhp_instance_err;
+ }
+
+ /* Request irq */
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = irq;
+ goto ddr_perf_err;
+ }
+
+ ret = devm_request_irq(&pdev->dev, irq, ddr_perf_irq_handler,
+ IRQF_NOBALANCING | IRQF_NO_THREAD,
+ DDR_CPUHP_CB_NAME, pmu);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Request irq failed: %d", ret);
+ goto ddr_perf_err;
+ }
+
+ pmu->irq = irq;
+ ret = irq_set_affinity(pmu->irq, cpumask_of(pmu->cpu));
+ if (ret) {
+ dev_err(pmu->dev, "Failed to set interrupt affinity\n");
+ goto ddr_perf_err;
+ }
+
+ ret = perf_pmu_register(&pmu->pmu, name, -1);
+ if (ret)
+ goto ddr_perf_err;
+
+ return 0;
+
+ddr_perf_err:
+ cpuhp_state_remove_instance_nocalls(pmu->cpuhp_state, &pmu->node);
+cpuhp_instance_err:
+ cpuhp_remove_multi_state(pmu->cpuhp_state);
+cpuhp_state_err:
+format_string_err:
+ ida_simple_remove(&ddr_ida, pmu->id);
+ dev_warn(&pdev->dev, "i.MX9 DDR Perf PMU failed (%d), disabled\n", ret);
+ return ret;
+}
+
+static int ddr_perf_remove(struct platform_device *pdev)
+{
+ struct ddr_pmu *pmu = platform_get_drvdata(pdev);
+
+ cpuhp_state_remove_instance_nocalls(pmu->cpuhp_state, &pmu->node);
+ cpuhp_remove_multi_state(pmu->cpuhp_state);
+
+ perf_pmu_unregister(&pmu->pmu);
+
+ ida_simple_remove(&ddr_ida, pmu->id);
+
+ return 0;
+}
+
+static struct platform_driver imx_ddr_pmu_driver = {
+ .driver = {
+ .name = "imx9-ddr-pmu",
+ .of_match_table = imx_ddr_pmu_dt_ids,
+ .suppress_bind_attrs = true,
+ },
+ .probe = ddr_perf_probe,
+ .remove = ddr_perf_remove,
+};
+module_platform_driver(imx_ddr_pmu_driver);
+
+MODULE_AUTHOR("Xu Yang <xu.yang_2@nxp.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("DDRC PerfMon for i.MX9 SoCs");
diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile
index 4d2c9abe3372..48dcc8381ea7 100644
--- a/drivers/perf/hisilicon/Makefile
+++ b/drivers/perf/hisilicon/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \
hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o \
- hisi_uncore_pa_pmu.o hisi_uncore_cpa_pmu.o
+ hisi_uncore_pa_pmu.o hisi_uncore_cpa_pmu.o hisi_uncore_uc_pmu.o
obj-$(CONFIG_HISI_PCIE_PMU) += hisi_pcie_pmu.o
obj-$(CONFIG_HNS3_PMU) += hns3_pmu.o
diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c
index 6fee0b6e163b..e10fc7cb9493 100644
--- a/drivers/perf/hisilicon/hisi_pcie_pmu.c
+++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c
@@ -683,7 +683,7 @@ static int hisi_pcie_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
pcie_pmu->on_cpu = -1;
/* Choose a new CPU from all online cpus. */
- target = cpumask_first(cpu_online_mask);
+ target = cpumask_any_but(cpu_online_mask, cpu);
if (target >= nr_cpu_ids) {
pci_err(pcie_pmu->pdev, "There is no CPU to set\n");
return 0;
diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
index 71b6687d6696..d941e746b424 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
@@ -22,9 +22,15 @@
#define PA_TT_CTRL 0x1c08
#define PA_TGTID_CTRL 0x1c14
#define PA_SRCID_CTRL 0x1c18
+
+/* H32 PA interrupt registers */
#define PA_INT_MASK 0x1c70
#define PA_INT_STATUS 0x1c78
#define PA_INT_CLEAR 0x1c7c
+
+#define H60PA_INT_STATUS 0x1c70
+#define H60PA_INT_MASK 0x1c74
+
#define PA_EVENT_TYPE0 0x1c80
#define PA_PMU_VERSION 0x1cf0
#define PA_EVENT_CNT0_L 0x1d00
@@ -46,6 +52,12 @@ HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 32, 22);
HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 43, 33);
HISI_PMU_EVENT_ATTR_EXTRACTOR(tracetag_en, config1, 44, 44);
+struct hisi_pa_pmu_int_regs {
+ u32 mask_offset;
+ u32 clear_offset;
+ u32 status_offset;
+};
+
static void hisi_pa_pmu_enable_tracetag(struct perf_event *event)
{
struct hisi_pmu *pa_pmu = to_hisi_pmu(event->pmu);
@@ -219,40 +231,40 @@ static void hisi_pa_pmu_disable_counter(struct hisi_pmu *pa_pmu,
static void hisi_pa_pmu_enable_counter_int(struct hisi_pmu *pa_pmu,
struct hw_perf_event *hwc)
{
+ struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->private;
u32 val;
/* Write 0 to enable interrupt */
- val = readl(pa_pmu->base + PA_INT_MASK);
+ val = readl(pa_pmu->base + regs->mask_offset);
val &= ~(1 << hwc->idx);
- writel(val, pa_pmu->base + PA_INT_MASK);
+ writel(val, pa_pmu->base + regs->mask_offset);
}
static void hisi_pa_pmu_disable_counter_int(struct hisi_pmu *pa_pmu,
struct hw_perf_event *hwc)
{
+ struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->private;
u32 val;
/* Write 1 to mask interrupt */
- val = readl(pa_pmu->base + PA_INT_MASK);
+ val = readl(pa_pmu->base + regs->mask_offset);
val |= 1 << hwc->idx;
- writel(val, pa_pmu->base + PA_INT_MASK);
+ writel(val, pa_pmu->base + regs->mask_offset);
}
static u32 hisi_pa_pmu_get_int_status(struct hisi_pmu *pa_pmu)
{
- return readl(pa_pmu->base + PA_INT_STATUS);
+ struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->private;
+
+ return readl(pa_pmu->base + regs->status_offset);
}
static void hisi_pa_pmu_clear_int_status(struct hisi_pmu *pa_pmu, int idx)
{
- writel(1 << idx, pa_pmu->base + PA_INT_CLEAR);
-}
+ struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->private;
-static const struct acpi_device_id hisi_pa_pmu_acpi_match[] = {
- { "HISI0273", },
- {}
-};
-MODULE_DEVICE_TABLE(acpi, hisi_pa_pmu_acpi_match);
+ writel(1 << idx, pa_pmu->base + regs->clear_offset);
+}
static int hisi_pa_pmu_init_data(struct platform_device *pdev,
struct hisi_pmu *pa_pmu)
@@ -276,6 +288,10 @@ static int hisi_pa_pmu_init_data(struct platform_device *pdev,
pa_pmu->ccl_id = -1;
pa_pmu->sccl_id = -1;
+ pa_pmu->dev_info = device_get_match_data(&pdev->dev);
+ if (!pa_pmu->dev_info)
+ return -ENODEV;
+
pa_pmu->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pa_pmu->base)) {
dev_err(&pdev->dev, "ioremap failed for pa_pmu resource.\n");
@@ -314,6 +330,32 @@ static const struct attribute_group hisi_pa_pmu_v2_events_group = {
.attrs = hisi_pa_pmu_v2_events_attr,
};
+static struct attribute *hisi_pa_pmu_v3_events_attr[] = {
+ HISI_PMU_EVENT_ATTR(tx_req, 0x0),
+ HISI_PMU_EVENT_ATTR(tx_dat, 0x1),
+ HISI_PMU_EVENT_ATTR(tx_snp, 0x2),
+ HISI_PMU_EVENT_ATTR(rx_req, 0x7),
+ HISI_PMU_EVENT_ATTR(rx_dat, 0x8),
+ HISI_PMU_EVENT_ATTR(rx_snp, 0x9),
+ NULL
+};
+
+static const struct attribute_group hisi_pa_pmu_v3_events_group = {
+ .name = "events",
+ .attrs = hisi_pa_pmu_v3_events_attr,
+};
+
+static struct attribute *hisi_h60pa_pmu_events_attr[] = {
+ HISI_PMU_EVENT_ATTR(rx_flit, 0x50),
+ HISI_PMU_EVENT_ATTR(tx_flit, 0x65),
+ NULL
+};
+
+static const struct attribute_group hisi_h60pa_pmu_events_group = {
+ .name = "events",
+ .attrs = hisi_h60pa_pmu_events_attr,
+};
+
static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
static struct attribute *hisi_pa_pmu_cpumask_attrs[] = {
@@ -337,6 +379,12 @@ static const struct attribute_group hisi_pa_pmu_identifier_group = {
.attrs = hisi_pa_pmu_identifier_attrs,
};
+static struct hisi_pa_pmu_int_regs hisi_pa_pmu_regs = {
+ .mask_offset = PA_INT_MASK,
+ .clear_offset = PA_INT_CLEAR,
+ .status_offset = PA_INT_STATUS,
+};
+
static const struct attribute_group *hisi_pa_pmu_v2_attr_groups[] = {
&hisi_pa_pmu_v2_format_group,
&hisi_pa_pmu_v2_events_group,
@@ -345,6 +393,46 @@ static const struct attribute_group *hisi_pa_pmu_v2_attr_groups[] = {
NULL
};
+static const struct hisi_pmu_dev_info hisi_h32pa_v2 = {
+ .name = "pa",
+ .attr_groups = hisi_pa_pmu_v2_attr_groups,
+ .private = &hisi_pa_pmu_regs,
+};
+
+static const struct attribute_group *hisi_pa_pmu_v3_attr_groups[] = {
+ &hisi_pa_pmu_v2_format_group,
+ &hisi_pa_pmu_v3_events_group,
+ &hisi_pa_pmu_cpumask_attr_group,
+ &hisi_pa_pmu_identifier_group,
+ NULL
+};
+
+static const struct hisi_pmu_dev_info hisi_h32pa_v3 = {
+ .name = "pa",
+ .attr_groups = hisi_pa_pmu_v3_attr_groups,
+ .private = &hisi_pa_pmu_regs,
+};
+
+static struct hisi_pa_pmu_int_regs hisi_h60pa_pmu_regs = {
+ .mask_offset = H60PA_INT_MASK,
+ .clear_offset = H60PA_INT_STATUS, /* Clear on write */
+ .status_offset = H60PA_INT_STATUS,
+};
+
+static const struct attribute_group *hisi_h60pa_pmu_attr_groups[] = {
+ &hisi_pa_pmu_v2_format_group,
+ &hisi_h60pa_pmu_events_group,
+ &hisi_pa_pmu_cpumask_attr_group,
+ &hisi_pa_pmu_identifier_group,
+ NULL
+};
+
+static const struct hisi_pmu_dev_info hisi_h60pa = {
+ .name = "h60pa",
+ .attr_groups = hisi_h60pa_pmu_attr_groups,
+ .private = &hisi_h60pa_pmu_regs,
+};
+
static const struct hisi_uncore_ops hisi_uncore_pa_ops = {
.write_evtype = hisi_pa_pmu_write_evtype,
.get_event_idx = hisi_uncore_pmu_get_event_idx,
@@ -375,7 +463,7 @@ static int hisi_pa_pmu_dev_probe(struct platform_device *pdev,
if (ret)
return ret;
- pa_pmu->pmu_events.attr_groups = hisi_pa_pmu_v2_attr_groups;
+ pa_pmu->pmu_events.attr_groups = pa_pmu->dev_info->attr_groups;
pa_pmu->num_counters = PA_NR_COUNTERS;
pa_pmu->ops = &hisi_uncore_pa_ops;
pa_pmu->check_event = 0xB0;
@@ -400,8 +488,9 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev)
if (ret)
return ret;
- name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sicl%u_pa%u",
- pa_pmu->sicl_id, pa_pmu->index_id);
+ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sicl%d_%s%u",
+ pa_pmu->sicl_id, pa_pmu->dev_info->name,
+ pa_pmu->index_id);
if (!name)
return -ENOMEM;
@@ -435,6 +524,14 @@ static int hisi_pa_pmu_remove(struct platform_device *pdev)
return 0;
}
+static const struct acpi_device_id hisi_pa_pmu_acpi_match[] = {
+ { "HISI0273", (kernel_ulong_t)&hisi_h32pa_v2 },
+ { "HISI0275", (kernel_ulong_t)&hisi_h32pa_v3 },
+ { "HISI0274", (kernel_ulong_t)&hisi_h60pa },
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, hisi_pa_pmu_acpi_match);
+
static struct platform_driver hisi_pa_pmu_driver = {
.driver = {
.name = "hisi_pa_pmu",
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index 2823f381930d..04031450d5fe 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -20,7 +20,6 @@
#include "hisi_uncore_pmu.h"
-#define HISI_GET_EVENTID(ev) (ev->hw.config_base & 0xff)
#define HISI_MAX_PERIOD(nr) (GENMASK_ULL((nr) - 1, 0))
/*
@@ -226,6 +225,9 @@ int hisi_uncore_pmu_event_init(struct perf_event *event)
hwc->idx = -1;
hwc->config_base = event->attr.config;
+ if (hisi_pmu->ops->check_filter && hisi_pmu->ops->check_filter(event))
+ return -EINVAL;
+
/* Enforce to use the same CPU for all events in this PMU */
event->cpu = hisi_pmu->on_cpu;
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
index 07890a8e96ca..92402aa69d70 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
@@ -43,9 +43,15 @@
return FIELD_GET(GENMASK_ULL(hi, lo), event->attr.config); \
}
+#define HISI_GET_EVENTID(ev) (ev->hw.config_base & 0xff)
+
+#define HISI_PMU_EVTYPE_BITS 8
+#define HISI_PMU_EVTYPE_SHIFT(idx) ((idx) % 4 * HISI_PMU_EVTYPE_BITS)
+
struct hisi_pmu;
struct hisi_uncore_ops {
+ int (*check_filter)(struct perf_event *event);
void (*write_evtype)(struct hisi_pmu *, int, u32);
int (*get_event_idx)(struct perf_event *);
u64 (*read_counter)(struct hisi_pmu *, struct hw_perf_event *);
@@ -62,6 +68,13 @@ struct hisi_uncore_ops {
void (*disable_filter)(struct perf_event *event);
};
+/* Describes the HISI PMU chip features information */
+struct hisi_pmu_dev_info {
+ const char *name;
+ const struct attribute_group **attr_groups;
+ void *private;
+};
+
struct hisi_pmu_hwevents {
struct perf_event *hw_events[HISI_MAX_COUNTERS];
DECLARE_BITMAP(used_mask, HISI_MAX_COUNTERS);
@@ -72,6 +85,7 @@ struct hisi_pmu_hwevents {
struct hisi_pmu {
struct pmu pmu;
const struct hisi_uncore_ops *ops;
+ const struct hisi_pmu_dev_info *dev_info;
struct hisi_pmu_hwevents pmu_events;
/* associated_cpus: All CPUs associated with the PMU */
cpumask_t associated_cpus;
diff --git a/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c
new file mode 100644
index 000000000000..63da05e5831c
--- /dev/null
+++ b/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c
@@ -0,0 +1,578 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * HiSilicon SoC UC (unified cache) uncore Hardware event counters support
+ *
+ * Copyright (C) 2023 HiSilicon Limited
+ *
+ * This code is based on the uncore PMUs like hisi_uncore_l3c_pmu.
+ */
+#include <linux/cpuhotplug.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+#include <linux/mod_devicetable.h>
+#include <linux/property.h>
+
+#include "hisi_uncore_pmu.h"
+
+/* Dynamic CPU hotplug state used by UC PMU */
+static enum cpuhp_state hisi_uc_pmu_online;
+
+/* UC register definition */
+#define HISI_UC_INT_MASK_REG 0x0800
+#define HISI_UC_INT_STS_REG 0x0808
+#define HISI_UC_INT_CLEAR_REG 0x080c
+#define HISI_UC_TRACETAG_CTRL_REG 0x1b2c
+#define HISI_UC_TRACETAG_REQ_MSK GENMASK(9, 7)
+#define HISI_UC_TRACETAG_MARK_EN BIT(0)
+#define HISI_UC_TRACETAG_REQ_EN (HISI_UC_TRACETAG_MARK_EN | BIT(2))
+#define HISI_UC_TRACETAG_SRCID_EN BIT(3)
+#define HISI_UC_SRCID_CTRL_REG 0x1b40
+#define HISI_UC_SRCID_MSK GENMASK(14, 1)
+#define HISI_UC_EVENT_CTRL_REG 0x1c00
+#define HISI_UC_EVENT_TRACETAG_EN BIT(29)
+#define HISI_UC_EVENT_URING_MSK GENMASK(28, 27)
+#define HISI_UC_EVENT_GLB_EN BIT(26)
+#define HISI_UC_VERSION_REG 0x1cf0
+#define HISI_UC_EVTYPE_REGn(n) (0x1d00 + (n) * 4)
+#define HISI_UC_EVTYPE_MASK GENMASK(7, 0)
+#define HISI_UC_CNTR_REGn(n) (0x1e00 + (n) * 8)
+
+#define HISI_UC_NR_COUNTERS 0x8
+#define HISI_UC_V2_NR_EVENTS 0xFF
+#define HISI_UC_CNTR_REG_BITS 64
+
+#define HISI_UC_RD_REQ_TRACETAG 0x4
+#define HISI_UC_URING_EVENT_MIN 0x47
+#define HISI_UC_URING_EVENT_MAX 0x59
+
+HISI_PMU_EVENT_ATTR_EXTRACTOR(rd_req_en, config1, 0, 0);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(uring_channel, config1, 5, 4);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid, config1, 19, 6);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_en, config1, 20, 20);
+
+static int hisi_uc_pmu_check_filter(struct perf_event *event)
+{
+ struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu);
+
+ if (hisi_get_srcid_en(event) && !hisi_get_rd_req_en(event)) {
+ dev_err(uc_pmu->dev,
+ "rcid_en depends on rd_req_en being enabled!\n");
+ return -EINVAL;
+ }
+
+ if (!hisi_get_uring_channel(event))
+ return 0;
+
+ if ((HISI_GET_EVENTID(event) < HISI_UC_URING_EVENT_MIN) ||
+ (HISI_GET_EVENTID(event) > HISI_UC_URING_EVENT_MAX))
+ dev_warn(uc_pmu->dev,
+ "Only events: [%#x ~ %#x] support channel filtering!",
+ HISI_UC_URING_EVENT_MIN, HISI_UC_URING_EVENT_MAX);
+
+ return 0;
+}
+
+static void hisi_uc_pmu_config_req_tracetag(struct perf_event *event)
+{
+ struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu);
+ u32 val;
+
+ if (!hisi_get_rd_req_en(event))
+ return;
+
+ val = readl(uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG);
+
+ /* The request-type has been configured */
+ if (FIELD_GET(HISI_UC_TRACETAG_REQ_MSK, val) == HISI_UC_RD_REQ_TRACETAG)
+ return;
+
+ /* Set request-type for tracetag, only read request is supported! */
+ val &= ~HISI_UC_TRACETAG_REQ_MSK;
+ val |= FIELD_PREP(HISI_UC_TRACETAG_REQ_MSK, HISI_UC_RD_REQ_TRACETAG);
+ val |= HISI_UC_TRACETAG_REQ_EN;
+ writel(val, uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG);
+}
+
+static void hisi_uc_pmu_clear_req_tracetag(struct perf_event *event)
+{
+ struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu);
+ u32 val;
+
+ if (!hisi_get_rd_req_en(event))
+ return;
+
+ val = readl(uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG);
+
+ /* Do nothing, the request-type tracetag has been cleaned up */
+ if (FIELD_GET(HISI_UC_TRACETAG_REQ_MSK, val) == 0)
+ return;
+
+ /* Clear request-type */
+ val &= ~HISI_UC_TRACETAG_REQ_MSK;
+ val &= ~HISI_UC_TRACETAG_REQ_EN;
+ writel(val, uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG);
+}
+
+static void hisi_uc_pmu_config_srcid_tracetag(struct perf_event *event)
+{
+ struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu);
+ u32 val;
+
+ if (!hisi_get_srcid_en(event))
+ return;
+
+ val = readl(uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG);
+
+ /* Do nothing, the source id has been configured */
+ if (FIELD_GET(HISI_UC_TRACETAG_SRCID_EN, val))
+ return;
+
+ /* Enable source id tracetag */
+ val |= HISI_UC_TRACETAG_SRCID_EN;
+ writel(val, uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG);
+
+ val = readl(uc_pmu->base + HISI_UC_SRCID_CTRL_REG);
+ val &= ~HISI_UC_SRCID_MSK;
+ val |= FIELD_PREP(HISI_UC_SRCID_MSK, hisi_get_srcid(event));
+ writel(val, uc_pmu->base + HISI_UC_SRCID_CTRL_REG);
+
+ /* Depend on request-type tracetag enabled */
+ hisi_uc_pmu_config_req_tracetag(event);
+}
+
+static void hisi_uc_pmu_clear_srcid_tracetag(struct perf_event *event)
+{
+ struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu);
+ u32 val;
+
+ if (!hisi_get_srcid_en(event))
+ return;
+
+ val = readl(uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG);
+
+ /* Do nothing, the source id has been cleaned up */
+ if (FIELD_GET(HISI_UC_TRACETAG_SRCID_EN, val) == 0)
+ return;
+
+ hisi_uc_pmu_clear_req_tracetag(event);
+
+ /* Disable source id tracetag */
+ val &= ~HISI_UC_TRACETAG_SRCID_EN;
+ writel(val, uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG);
+
+ val = readl(uc_pmu->base + HISI_UC_SRCID_CTRL_REG);
+ val &= ~HISI_UC_SRCID_MSK;
+ writel(val, uc_pmu->base + HISI_UC_SRCID_CTRL_REG);
+}
+
+static void hisi_uc_pmu_config_uring_channel(struct perf_event *event)
+{
+ struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu);
+ u32 uring_channel = hisi_get_uring_channel(event);
+ u32 val;
+
+ /* Do nothing if not being set or is set explicitly to zero (default) */
+ if (uring_channel == 0)
+ return;
+
+ val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG);
+
+ /* Do nothing, the uring_channel has been configured */
+ if (uring_channel == FIELD_GET(HISI_UC_EVENT_URING_MSK, val))
+ return;
+
+ val &= ~HISI_UC_EVENT_URING_MSK;
+ val |= FIELD_PREP(HISI_UC_EVENT_URING_MSK, uring_channel);
+ writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG);
+}
+
+static void hisi_uc_pmu_clear_uring_channel(struct perf_event *event)
+{
+ struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu);
+ u32 val;
+
+ /* Do nothing if not being set or is set explicitly to zero (default) */
+ if (hisi_get_uring_channel(event) == 0)
+ return;
+
+ val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG);
+
+ /* Do nothing, the uring_channel has been cleaned up */
+ if (FIELD_GET(HISI_UC_EVENT_URING_MSK, val) == 0)
+ return;
+
+ val &= ~HISI_UC_EVENT_URING_MSK;
+ writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG);
+}
+
+static void hisi_uc_pmu_enable_filter(struct perf_event *event)
+{
+ if (event->attr.config1 == 0)
+ return;
+
+ hisi_uc_pmu_config_uring_channel(event);
+ hisi_uc_pmu_config_req_tracetag(event);
+ hisi_uc_pmu_config_srcid_tracetag(event);
+}
+
+static void hisi_uc_pmu_disable_filter(struct perf_event *event)
+{
+ if (event->attr.config1 == 0)
+ return;
+
+ hisi_uc_pmu_clear_srcid_tracetag(event);
+ hisi_uc_pmu_clear_req_tracetag(event);
+ hisi_uc_pmu_clear_uring_channel(event);
+}
+
+static void hisi_uc_pmu_write_evtype(struct hisi_pmu *uc_pmu, int idx, u32 type)
+{
+ u32 val;
+
+ /*
+ * Select the appropriate event select register.
+ * There are 2 32-bit event select registers for the
+ * 8 hardware counters, each event code is 8-bit wide.
+ */
+ val = readl(uc_pmu->base + HISI_UC_EVTYPE_REGn(idx / 4));
+ val &= ~(HISI_UC_EVTYPE_MASK << HISI_PMU_EVTYPE_SHIFT(idx));
+ val |= (type << HISI_PMU_EVTYPE_SHIFT(idx));
+ writel(val, uc_pmu->base + HISI_UC_EVTYPE_REGn(idx / 4));
+}
+
+static void hisi_uc_pmu_start_counters(struct hisi_pmu *uc_pmu)
+{
+ u32 val;
+
+ val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG);
+ val |= HISI_UC_EVENT_GLB_EN;
+ writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG);
+}
+
+static void hisi_uc_pmu_stop_counters(struct hisi_pmu *uc_pmu)
+{
+ u32 val;
+
+ val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG);
+ val &= ~HISI_UC_EVENT_GLB_EN;
+ writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG);
+}
+
+static void hisi_uc_pmu_enable_counter(struct hisi_pmu *uc_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ /* Enable counter index */
+ val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG);
+ val |= (1 << hwc->idx);
+ writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG);
+}
+
+static void hisi_uc_pmu_disable_counter(struct hisi_pmu *uc_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ /* Clear counter index */
+ val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG);
+ val &= ~(1 << hwc->idx);
+ writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG);
+}
+
+static u64 hisi_uc_pmu_read_counter(struct hisi_pmu *uc_pmu,
+ struct hw_perf_event *hwc)
+{
+ return readq(uc_pmu->base + HISI_UC_CNTR_REGn(hwc->idx));
+}
+
+static void hisi_uc_pmu_write_counter(struct hisi_pmu *uc_pmu,
+ struct hw_perf_event *hwc, u64 val)
+{
+ writeq(val, uc_pmu->base + HISI_UC_CNTR_REGn(hwc->idx));
+}
+
+static void hisi_uc_pmu_enable_counter_int(struct hisi_pmu *uc_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ val = readl(uc_pmu->base + HISI_UC_INT_MASK_REG);
+ val &= ~(1 << hwc->idx);
+ writel(val, uc_pmu->base + HISI_UC_INT_MASK_REG);
+}
+
+static void hisi_uc_pmu_disable_counter_int(struct hisi_pmu *uc_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ val = readl(uc_pmu->base + HISI_UC_INT_MASK_REG);
+ val |= (1 << hwc->idx);
+ writel(val, uc_pmu->base + HISI_UC_INT_MASK_REG);
+}
+
+static u32 hisi_uc_pmu_get_int_status(struct hisi_pmu *uc_pmu)
+{
+ return readl(uc_pmu->base + HISI_UC_INT_STS_REG);
+}
+
+static void hisi_uc_pmu_clear_int_status(struct hisi_pmu *uc_pmu, int idx)
+{
+ writel(1 << idx, uc_pmu->base + HISI_UC_INT_CLEAR_REG);
+}
+
+static int hisi_uc_pmu_init_data(struct platform_device *pdev,
+ struct hisi_pmu *uc_pmu)
+{
+ /*
+ * Use SCCL (Super CPU Cluster) ID and CCL (CPU Cluster) ID to
+ * identify the topology information of UC PMU devices in the chip.
+ * They have some CCLs per SCCL and then 4 UC PMU per CCL.
+ */
+ if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
+ &uc_pmu->sccl_id)) {
+ dev_err(&pdev->dev, "Can not read uc sccl-id!\n");
+ return -EINVAL;
+ }
+
+ if (device_property_read_u32(&pdev->dev, "hisilicon,ccl-id",
+ &uc_pmu->ccl_id)) {
+ dev_err(&pdev->dev, "Can not read uc ccl-id!\n");
+ return -EINVAL;
+ }
+
+ if (device_property_read_u32(&pdev->dev, "hisilicon,sub-id",
+ &uc_pmu->sub_id)) {
+ dev_err(&pdev->dev, "Can not read sub-id!\n");
+ return -EINVAL;
+ }
+
+ uc_pmu->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(uc_pmu->base)) {
+ dev_err(&pdev->dev, "ioremap failed for uc_pmu resource\n");
+ return PTR_ERR(uc_pmu->base);
+ }
+
+ uc_pmu->identifier = readl(uc_pmu->base + HISI_UC_VERSION_REG);
+
+ return 0;
+}
+
+static struct attribute *hisi_uc_pmu_format_attr[] = {
+ HISI_PMU_FORMAT_ATTR(event, "config:0-7"),
+ HISI_PMU_FORMAT_ATTR(rd_req_en, "config1:0-0"),
+ HISI_PMU_FORMAT_ATTR(uring_channel, "config1:4-5"),
+ HISI_PMU_FORMAT_ATTR(srcid, "config1:6-19"),
+ HISI_PMU_FORMAT_ATTR(srcid_en, "config1:20-20"),
+ NULL
+};
+
+static const struct attribute_group hisi_uc_pmu_format_group = {
+ .name = "format",
+ .attrs = hisi_uc_pmu_format_attr,
+};
+
+static struct attribute *hisi_uc_pmu_events_attr[] = {
+ HISI_PMU_EVENT_ATTR(sq_time, 0x00),
+ HISI_PMU_EVENT_ATTR(pq_time, 0x01),
+ HISI_PMU_EVENT_ATTR(hbm_time, 0x02),
+ HISI_PMU_EVENT_ATTR(iq_comp_time_cring, 0x03),
+ HISI_PMU_EVENT_ATTR(iq_comp_time_uring, 0x05),
+ HISI_PMU_EVENT_ATTR(cpu_rd, 0x10),
+ HISI_PMU_EVENT_ATTR(cpu_rd64, 0x17),
+ HISI_PMU_EVENT_ATTR(cpu_rs64, 0x19),
+ HISI_PMU_EVENT_ATTR(cpu_mru, 0x1a),
+ HISI_PMU_EVENT_ATTR(cycles, 0x9c),
+ HISI_PMU_EVENT_ATTR(spipe_hit, 0xb3),
+ HISI_PMU_EVENT_ATTR(hpipe_hit, 0xdb),
+ HISI_PMU_EVENT_ATTR(cring_rxdat_cnt, 0xfa),
+ HISI_PMU_EVENT_ATTR(cring_txdat_cnt, 0xfb),
+ HISI_PMU_EVENT_ATTR(uring_rxdat_cnt, 0xfc),
+ HISI_PMU_EVENT_ATTR(uring_txdat_cnt, 0xfd),
+ NULL
+};
+
+static const struct attribute_group hisi_uc_pmu_events_group = {
+ .name = "events",
+ .attrs = hisi_uc_pmu_events_attr,
+};
+
+static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
+
+static struct attribute *hisi_uc_pmu_cpumask_attrs[] = {
+ &dev_attr_cpumask.attr,
+ NULL,
+};
+
+static const struct attribute_group hisi_uc_pmu_cpumask_attr_group = {
+ .attrs = hisi_uc_pmu_cpumask_attrs,
+};
+
+static struct device_attribute hisi_uc_pmu_identifier_attr =
+ __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL);
+
+static struct attribute *hisi_uc_pmu_identifier_attrs[] = {
+ &hisi_uc_pmu_identifier_attr.attr,
+ NULL
+};
+
+static const struct attribute_group hisi_uc_pmu_identifier_group = {
+ .attrs = hisi_uc_pmu_identifier_attrs,
+};
+
+static const struct attribute_group *hisi_uc_pmu_attr_groups[] = {
+ &hisi_uc_pmu_format_group,
+ &hisi_uc_pmu_events_group,
+ &hisi_uc_pmu_cpumask_attr_group,
+ &hisi_uc_pmu_identifier_group,
+ NULL
+};
+
+static const struct hisi_uncore_ops hisi_uncore_uc_pmu_ops = {
+ .check_filter = hisi_uc_pmu_check_filter,
+ .write_evtype = hisi_uc_pmu_write_evtype,
+ .get_event_idx = hisi_uncore_pmu_get_event_idx,
+ .start_counters = hisi_uc_pmu_start_counters,
+ .stop_counters = hisi_uc_pmu_stop_counters,
+ .enable_counter = hisi_uc_pmu_enable_counter,
+ .disable_counter = hisi_uc_pmu_disable_counter,
+ .enable_counter_int = hisi_uc_pmu_enable_counter_int,
+ .disable_counter_int = hisi_uc_pmu_disable_counter_int,
+ .write_counter = hisi_uc_pmu_write_counter,
+ .read_counter = hisi_uc_pmu_read_counter,
+ .get_int_status = hisi_uc_pmu_get_int_status,
+ .clear_int_status = hisi_uc_pmu_clear_int_status,
+ .enable_filter = hisi_uc_pmu_enable_filter,
+ .disable_filter = hisi_uc_pmu_disable_filter,
+};
+
+static int hisi_uc_pmu_dev_probe(struct platform_device *pdev,
+ struct hisi_pmu *uc_pmu)
+{
+ int ret;
+
+ ret = hisi_uc_pmu_init_data(pdev, uc_pmu);
+ if (ret)
+ return ret;
+
+ ret = hisi_uncore_pmu_init_irq(uc_pmu, pdev);
+ if (ret)
+ return ret;
+
+ uc_pmu->pmu_events.attr_groups = hisi_uc_pmu_attr_groups;
+ uc_pmu->check_event = HISI_UC_EVTYPE_MASK;
+ uc_pmu->ops = &hisi_uncore_uc_pmu_ops;
+ uc_pmu->counter_bits = HISI_UC_CNTR_REG_BITS;
+ uc_pmu->num_counters = HISI_UC_NR_COUNTERS;
+ uc_pmu->dev = &pdev->dev;
+ uc_pmu->on_cpu = -1;
+
+ return 0;
+}
+
+static void hisi_uc_pmu_remove_cpuhp_instance(void *hotplug_node)
+{
+ cpuhp_state_remove_instance_nocalls(hisi_uc_pmu_online, hotplug_node);
+}
+
+static void hisi_uc_pmu_unregister_pmu(void *pmu)
+{
+ perf_pmu_unregister(pmu);
+}
+
+static int hisi_uc_pmu_probe(struct platform_device *pdev)
+{
+ struct hisi_pmu *uc_pmu;
+ char *name;
+ int ret;
+
+ uc_pmu = devm_kzalloc(&pdev->dev, sizeof(*uc_pmu), GFP_KERNEL);
+ if (!uc_pmu)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, uc_pmu);
+
+ ret = hisi_uc_pmu_dev_probe(pdev, uc_pmu);
+ if (ret)
+ return ret;
+
+ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%d_uc%d_%u",
+ uc_pmu->sccl_id, uc_pmu->ccl_id, uc_pmu->sub_id);
+ if (!name)
+ return -ENOMEM;
+
+ ret = cpuhp_state_add_instance(hisi_uc_pmu_online, &uc_pmu->node);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "Error registering hotplug\n");
+
+ ret = devm_add_action_or_reset(&pdev->dev,
+ hisi_uc_pmu_remove_cpuhp_instance,
+ &uc_pmu->node);
+ if (ret)
+ return ret;
+
+ hisi_pmu_init(uc_pmu, THIS_MODULE);
+
+ ret = perf_pmu_register(&uc_pmu->pmu, name, -1);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(&pdev->dev,
+ hisi_uc_pmu_unregister_pmu,
+ &uc_pmu->pmu);
+}
+
+static const struct acpi_device_id hisi_uc_pmu_acpi_match[] = {
+ { "HISI0291", },
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, hisi_uc_pmu_acpi_match);
+
+static struct platform_driver hisi_uc_pmu_driver = {
+ .driver = {
+ .name = "hisi_uc_pmu",
+ .acpi_match_table = hisi_uc_pmu_acpi_match,
+ /*
+ * We have not worked out a safe bind/unbind process,
+ * Forcefully unbinding during sampling will lead to a
+ * kernel panic, so this is not supported yet.
+ */
+ .suppress_bind_attrs = true,
+ },
+ .probe = hisi_uc_pmu_probe,
+};
+
+static int __init hisi_uc_pmu_module_init(void)
+{
+ int ret;
+
+ ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
+ "perf/hisi/uc:online",
+ hisi_uncore_pmu_online_cpu,
+ hisi_uncore_pmu_offline_cpu);
+ if (ret < 0) {
+ pr_err("UC PMU: Error setup hotplug, ret = %d\n", ret);
+ return ret;
+ }
+ hisi_uc_pmu_online = ret;
+
+ ret = platform_driver_register(&hisi_uc_pmu_driver);
+ if (ret)
+ cpuhp_remove_multi_state(hisi_uc_pmu_online);
+
+ return ret;
+}
+module_init(hisi_uc_pmu_module_init);
+
+static void __exit hisi_uc_pmu_module_exit(void)
+{
+ platform_driver_unregister(&hisi_uc_pmu_driver);
+ cpuhp_remove_multi_state(hisi_uc_pmu_online);
+}
+module_exit(hisi_uc_pmu_module_exit);
+
+MODULE_DESCRIPTION("HiSilicon SoC UC uncore PMU driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Junhao He <hejunhao3@huawei.com>");
diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c
index aaca6db7d8f6..3f9a98c17a89 100644
--- a/drivers/perf/qcom_l2_pmu.c
+++ b/drivers/perf/qcom_l2_pmu.c
@@ -857,7 +857,6 @@ static int l2_cache_pmu_probe_cluster(struct device *dev, void *data)
return -ENOMEM;
INIT_LIST_HEAD(&cluster->next);
- list_add(&cluster->next, &l2cache_pmu->clusters);
cluster->cluster_id = fw_cluster_id;
irq = platform_get_irq(sdev, 0);
@@ -883,6 +882,7 @@ static int l2_cache_pmu_probe_cluster(struct device *dev, void *data)
spin_lock_init(&cluster->pmu_lock);
+ list_add(&cluster->next, &l2cache_pmu->clusters);
l2cache_pmu->num_pmus++;
return 0;
diff --git a/drivers/perf/riscv_pmu.c b/drivers/perf/riscv_pmu.c
index ebca5eab9c9b..56897d4d4fd3 100644
--- a/drivers/perf/riscv_pmu.c
+++ b/drivers/perf/riscv_pmu.c
@@ -181,9 +181,6 @@ void riscv_pmu_start(struct perf_event *event, int flags)
uint64_t max_period = riscv_pmu_ctr_get_width_mask(event);
u64 init_val;
- if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
- return;
-
if (flags & PERF_EF_RELOAD)
WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
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/amlogic/phy-meson-g12a-usb2.c b/drivers/phy/amlogic/phy-meson-g12a-usb2.c
index 9d1efa0d9394..ec2555bb83d5 100644
--- a/drivers/phy/amlogic/phy-meson-g12a-usb2.c
+++ b/drivers/phy/amlogic/phy-meson-g12a-usb2.c
@@ -172,10 +172,16 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
int ret;
unsigned int value;
- ret = reset_control_reset(priv->reset);
+ ret = clk_prepare_enable(priv->clk);
if (ret)
return ret;
+ ret = reset_control_reset(priv->reset);
+ if (ret) {
+ clk_disable_unprepare(priv->clk);
+ return ret;
+ }
+
udelay(RESET_COMPLETE_TIME);
/* usb2_otg_aca_en == 0 */
@@ -277,8 +283,13 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
static int phy_meson_g12a_usb2_exit(struct phy *phy)
{
struct phy_meson_g12a_usb2_priv *priv = phy_get_drvdata(phy);
+ int ret;
+
+ ret = reset_control_reset(priv->reset);
+ if (!ret)
+ clk_disable_unprepare(priv->clk);
- return reset_control_reset(priv->reset);
+ return ret;
}
/* set_mode is not needed, mode setting is handled via the UTMI bus */
diff --git a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
index 76cf4280d7ed..4c10cafded4e 100644
--- a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
+++ b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
@@ -59,6 +59,8 @@
#define USB_CTLR_TP_DIAG1_wake_MASK BIT(1)
#define USB_CTRL_CTLR_CSHCR 0x50
#define USB_CTRL_CTLR_CSHCR_ctl_pme_en_MASK BIT(18)
+#define USB_CTRL_P0_U2PHY_CFG1 0x68
+#define USB_CTRL_P0_U2PHY_CFG1_COMMONONN_MASK BIT(10)
/* Register definitions for the USB_PHY block in 7211b0 */
#define USB_PHY_PLL_CTL 0x00
@@ -90,6 +92,8 @@
#define BDC_EC_AXIRDA_RTS_MASK GENMASK(31, 28)
#define BDC_EC_AXIRDA_RTS_SHIFT 28
+#define USB_XHCI_GBL_GUSB2PHYCFG 0x100
+#define USB_XHCI_GBL_GUSB2PHYCFG_U2_FREECLK_EXISTS_MASK BIT(30)
static void usb_mdio_write_7211b0(struct brcm_usb_init_params *params,
uint8_t addr, uint16_t data)
@@ -140,13 +144,17 @@ static void xhci_soft_reset(struct brcm_usb_init_params *params,
int on_off)
{
void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
+ void __iomem *xhci_gbl = params->regs[BRCM_REGS_XHCI_GBL];
/* Assert reset */
- if (on_off)
+ if (on_off) {
USB_CTRL_UNSET(ctrl, USB_PM, XHC_SOFT_RESETB);
/* De-assert reset */
- else
+ } else {
USB_CTRL_SET(ctrl, USB_PM, XHC_SOFT_RESETB);
+ /* Required for COMMONONN to be set */
+ USB_XHCI_GBL_UNSET(xhci_gbl, GUSB2PHYCFG, U2_FREECLK_EXISTS);
+ }
}
static void usb_init_ipp(struct brcm_usb_init_params *params)
@@ -320,6 +328,9 @@ static void usb_init_common_7216(struct brcm_usb_init_params *params)
/* 1 millisecond - for USB clocks to settle down */
usleep_range(1000, 2000);
+ /* Disable PHY when port is suspended */
+ USB_CTRL_SET(ctrl, P0_U2PHY_CFG1, COMMONONN);
+
usb_wake_enable_7216(params, false);
usb_init_common(params);
}
diff --git a/drivers/phy/broadcom/phy-brcm-usb-init.c b/drivers/phy/broadcom/phy-brcm-usb-init.c
index a1ca83308f98..39536b6d96a9 100644
--- a/drivers/phy/broadcom/phy-brcm-usb-init.c
+++ b/drivers/phy/broadcom/phy-brcm-usb-init.c
@@ -35,6 +35,11 @@
#define USB_CTRL_SETUP_STRAP_IPP_SEL_MASK BIT(25) /* option */
#define USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK BIT(26) /* option */
#define USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK BIT(27) /* opt */
+#define USB_CTRL_SETUP_OC_DISABLE_PORT0_MASK BIT(28)
+#define USB_CTRL_SETUP_OC_DISABLE_PORT1_MASK BIT(29)
+#define USB_CTRL_SETUP_OC_DISABLE_MASK GENMASK(29, 28) /* option */
+#define USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK BIT(30)
+#define USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK BIT(31)
#define USB_CTRL_SETUP_OC3_DISABLE_MASK GENMASK(31, 30) /* option */
#define USB_CTRL_PLL_CTL 0x04
#define USB_CTRL_PLL_CTL_PLL_SUSPEND_EN_MASK BIT(27)
@@ -114,6 +119,8 @@ enum {
USB_CTRL_SETUP_SCB2_EN_SELECTOR,
USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR,
USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR,
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR,
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR,
USB_CTRL_SETUP_OC3_DISABLE_SELECTOR,
USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR,
USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR,
@@ -190,6 +197,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = {
USB_CTRL_SETUP_SCB2_EN_MASK,
USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
USB_CTRL_SETUP_OC3_DISABLE_MASK,
0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
@@ -232,6 +241,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = {
USB_CTRL_SETUP_SCB2_EN_MASK,
USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
USB_CTRL_SETUP_OC3_DISABLE_MASK,
USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
@@ -253,6 +264,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = {
0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
USB_CTRL_SETUP_OC3_DISABLE_MASK,
0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
@@ -274,6 +287,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = {
USB_CTRL_SETUP_SCB2_EN_MASK,
USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
USB_CTRL_SETUP_OC3_DISABLE_MASK,
USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
@@ -295,6 +310,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = {
USB_CTRL_SETUP_SCB2_EN_MASK,
USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
USB_CTRL_SETUP_OC3_DISABLE_MASK,
0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
@@ -316,6 +333,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = {
USB_CTRL_SETUP_SCB2_EN_MASK,
USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
+ 0, /* USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK */
+ 0, /* USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK */
0, /* USB_CTRL_SETUP_OC3_DISABLE_MASK */
USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
@@ -337,6 +356,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = {
USB_CTRL_SETUP_SCB2_EN_MASK,
USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
USB_CTRL_SETUP_OC3_DISABLE_MASK,
0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
@@ -358,6 +379,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = {
USB_CTRL_SETUP_SCB2_EN_MASK,
USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
USB_CTRL_SETUP_OC3_DISABLE_MASK,
USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
@@ -379,6 +402,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = {
0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
USB_CTRL_SETUP_OC3_DISABLE_MASK,
0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
@@ -400,6 +425,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = {
0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
0, /*USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK */
USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
USB_CTRL_SETUP_OC3_DISABLE_MASK,
0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
@@ -872,6 +899,13 @@ static void usb_init_common(struct brcm_usb_init_params *params)
brcmusb_memc_fix(params);
+ /* Workaround for false positive OC for 7439b2 in DRD/Device mode */
+ if ((params->family_id == 0x74390012) &&
+ (params->supported_port_modes != USB_CTLR_MODE_HOST)) {
+ USB_CTRL_SET(ctrl, SETUP, OC_DISABLE_PORT1);
+ USB_CTRL_SET_FAMILY(params, SETUP, OC3_DISABLE_PORT1);
+ }
+
if (USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1, PORT_MODE)) {
reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
reg &= ~USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1,
diff --git a/drivers/phy/broadcom/phy-brcm-usb-init.h b/drivers/phy/broadcom/phy-brcm-usb-init.h
index f9fbf8fb80e5..c1a88f5cd4cd 100644
--- a/drivers/phy/broadcom/phy-brcm-usb-init.h
+++ b/drivers/phy/broadcom/phy-brcm-usb-init.h
@@ -34,6 +34,14 @@ enum brcmusb_reg_sel {
brcm_usb_ctrl_unset(USB_CTRL_REG(base, reg), \
USB_CTRL_##reg##_##field##_MASK)
+#define USB_XHCI_GBL_REG(base, reg) ((void __iomem *)base + USB_XHCI_GBL_##reg)
+#define USB_XHCI_GBL_SET(base, reg, field) \
+ brcm_usb_ctrl_set(USB_XHCI_GBL_REG(base, reg), \
+ USB_XHCI_GBL_##reg##_##field##_MASK)
+#define USB_XHCI_GBL_UNSET(base, reg, field) \
+ brcm_usb_ctrl_unset(USB_XHCI_GBL_REG(base, reg), \
+ USB_XHCI_GBL_##reg##_##field##_MASK)
+
struct brcm_usb_init_params;
struct brcm_usb_init_ops {
diff --git a/drivers/phy/cadence/phy-cadence-salvo.c b/drivers/phy/cadence/phy-cadence-salvo.c
index e569f5f67578..f461585c84c6 100644
--- a/drivers/phy/cadence/phy-cadence-salvo.c
+++ b/drivers/phy/cadence/phy-cadence-salvo.c
@@ -6,6 +6,7 @@
* Copyright (c) 2019-2020 NXP
*/
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -15,7 +16,9 @@
#include <linux/of.h>
#include <linux/of_platform.h>
-/* PHY register definition */
+#define USB3_PHY_OFFSET 0x0
+#define USB2_PHY_OFFSET 0x38000
+/* USB3 PHY register definition */
#define PHY_PMA_CMN_CTRL1 0xC800
#define TB_ADDR_CMN_DIAG_HSCLK_SEL 0x01e0
#define TB_ADDR_CMN_PLL0_VCOCAL_INIT_TMR 0x0084
@@ -87,8 +90,35 @@
#define TB_ADDR_XCVR_DIAG_LANE_FCM_EN_MGN_TMR 0x40f2
#define TB_ADDR_TX_RCVDETSC_CTRL 0x4124
+/* USB2 PHY register definition */
+#define UTMI_REG15 0xaf
+#define UTMI_AFE_RX_REG0 0x0d
+#define UTMI_AFE_RX_REG5 0x12
+#define UTMI_AFE_BC_REG4 0x29
+
+/* Align UTMI_AFE_RX_REG0 bit[7:6] define */
+enum usb2_disconn_threshold {
+ USB2_DISCONN_THRESHOLD_575 = 0x0,
+ USB2_DISCONN_THRESHOLD_610 = 0x1,
+ USB2_DISCONN_THRESHOLD_645 = 0x3,
+};
+
+#define RX_USB2_DISCONN_MASK GENMASK(7, 6)
+
/* TB_ADDR_TX_RCVDETSC_CTRL */
#define RXDET_IN_P3_32KHZ BIT(0)
+/*
+ * UTMI_REG15
+ *
+ * Gate how many us for the txvalid signal until analog
+ * HS/FS transmitters have powered up
+ */
+#define TXVALID_GATE_THRESHOLD_HS_MASK (BIT(4) | BIT(5))
+/* 0us, txvalid is ready just after HS/FS transmitters have powered up */
+#define TXVALID_GATE_THRESHOLD_HS_0US (BIT(4) | BIT(5))
+
+#define SET_B_SESSION_VALID (BIT(6) | BIT(5))
+#define CLR_B_SESSION_VALID (BIT(6))
struct cdns_reg_pairs {
u16 val;
@@ -106,19 +136,27 @@ struct cdns_salvo_phy {
struct clk *clk;
void __iomem *base;
struct cdns_salvo_data *data;
+ enum usb2_disconn_threshold usb2_disconn;
};
static const struct of_device_id cdns_salvo_phy_of_match[];
-static u16 cdns_salvo_read(struct cdns_salvo_phy *salvo_phy, u32 reg)
+static const struct cdns_salvo_data cdns_nxp_salvo_data;
+
+static bool cdns_is_nxp_phy(struct cdns_salvo_phy *salvo_phy)
+{
+ return salvo_phy->data == &cdns_nxp_salvo_data;
+}
+
+static u16 cdns_salvo_read(struct cdns_salvo_phy *salvo_phy, u32 offset, u32 reg)
{
- return (u16)readl(salvo_phy->base +
+ return (u16)readl(salvo_phy->base + offset +
reg * (1 << salvo_phy->data->reg_offset_shift));
}
-static void cdns_salvo_write(struct cdns_salvo_phy *salvo_phy,
+static void cdns_salvo_write(struct cdns_salvo_phy *salvo_phy, u32 offset,
u32 reg, u16 val)
{
- writel(val, salvo_phy->base +
+ writel(val, salvo_phy->base + offset +
reg * (1 << salvo_phy->data->reg_offset_shift));
}
@@ -219,15 +257,27 @@ static int cdns_salvo_phy_init(struct phy *phy)
for (i = 0; i < data->init_sequence_length; i++) {
const struct cdns_reg_pairs *reg_pair = data->init_sequence_val + i;
- cdns_salvo_write(salvo_phy, reg_pair->off, reg_pair->val);
+ cdns_salvo_write(salvo_phy, USB3_PHY_OFFSET, reg_pair->off, reg_pair->val);
}
/* RXDET_IN_P3_32KHZ, Receiver detect slow clock enable */
- value = cdns_salvo_read(salvo_phy, TB_ADDR_TX_RCVDETSC_CTRL);
+ value = cdns_salvo_read(salvo_phy, USB3_PHY_OFFSET, TB_ADDR_TX_RCVDETSC_CTRL);
value |= RXDET_IN_P3_32KHZ;
- cdns_salvo_write(salvo_phy, TB_ADDR_TX_RCVDETSC_CTRL,
+ cdns_salvo_write(salvo_phy, USB3_PHY_OFFSET, TB_ADDR_TX_RCVDETSC_CTRL,
RXDET_IN_P3_32KHZ);
+ value = cdns_salvo_read(salvo_phy, USB2_PHY_OFFSET, UTMI_REG15);
+ value &= ~TXVALID_GATE_THRESHOLD_HS_MASK;
+ cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_REG15,
+ value | TXVALID_GATE_THRESHOLD_HS_0US);
+
+ cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_RX_REG5, 0x5);
+
+ value = cdns_salvo_read(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_RX_REG0);
+ value &= ~RX_USB2_DISCONN_MASK;
+ value = FIELD_PREP(RX_USB2_DISCONN_MASK, salvo_phy->usb2_disconn);
+ cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_RX_REG0, value);
+
udelay(10);
clk_disable_unprepare(salvo_phy->clk);
@@ -251,11 +301,29 @@ static int cdns_salvo_phy_power_off(struct phy *phy)
return 0;
}
+static int cdns_salvo_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+ struct cdns_salvo_phy *salvo_phy = phy_get_drvdata(phy);
+
+ if (!cdns_is_nxp_phy(salvo_phy))
+ return 0;
+
+ if (mode == PHY_MODE_USB_DEVICE)
+ cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_BC_REG4,
+ SET_B_SESSION_VALID);
+ else
+ cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_BC_REG4,
+ CLR_B_SESSION_VALID);
+
+ return 0;
+}
+
static const struct phy_ops cdns_salvo_phy_ops = {
.init = cdns_salvo_phy_init,
.power_on = cdns_salvo_phy_power_on,
.power_off = cdns_salvo_phy_power_off,
.owner = THIS_MODULE,
+ .set_mode = cdns_salvo_set_mode,
};
static int cdns_salvo_phy_probe(struct platform_device *pdev)
@@ -264,6 +332,7 @@ static int cdns_salvo_phy_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct cdns_salvo_phy *salvo_phy;
struct cdns_salvo_data *data;
+ u32 val;
data = (struct cdns_salvo_data *)of_device_get_match_data(dev);
salvo_phy = devm_kzalloc(dev, sizeof(*salvo_phy), GFP_KERNEL);
@@ -275,6 +344,16 @@ static int cdns_salvo_phy_probe(struct platform_device *pdev)
if (IS_ERR(salvo_phy->clk))
return PTR_ERR(salvo_phy->clk);
+ if (of_property_read_u32(dev->of_node, "cdns,usb2-disconnect-threshold-microvolt", &val))
+ val = 575;
+
+ if (val < 610)
+ salvo_phy->usb2_disconn = USB2_DISCONN_THRESHOLD_575;
+ else if (val < 645)
+ salvo_phy->usb2_disconn = USB2_DISCONN_THRESHOLD_610;
+ else
+ salvo_phy->usb2_disconn = USB2_DISCONN_THRESHOLD_645;
+
salvo_phy->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(salvo_phy->base))
return PTR_ERR(salvo_phy->base);
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..37b6b5c05be8 100644
--- a/drivers/phy/cadence/phy-cadence-torrent.c
+++ b/drivers/phy/cadence/phy-cadence-torrent.c
@@ -38,6 +38,9 @@
#define POLL_TIMEOUT_US 5000
#define PLL_LOCK_TIMEOUT 100000
+#define DP_PLL0 BIT(0)
+#define DP_PLL1 BIT(1)
+
#define TORRENT_COMMON_CDB_OFFSET 0x0
#define TORRENT_TX_LANE_CDB_OFFSET(ln, block_offset, reg_offset) \
@@ -66,16 +69,11 @@
*/
#define PHY_AUX_CTRL 0x04
#define PHY_RESET 0x20
-#define PMA_TX_ELEC_IDLE_MASK 0xF0U
#define PMA_TX_ELEC_IDLE_SHIFT 4
-#define PHY_L00_RESET_N_MASK 0x01U
#define PHY_PMA_XCVR_PLLCLK_EN 0x24
#define PHY_PMA_XCVR_PLLCLK_EN_ACK 0x28
#define PHY_PMA_XCVR_POWER_STATE_REQ 0x2c
-#define PHY_POWER_STATE_LN_0 0x0000
-#define PHY_POWER_STATE_LN_1 0x0008
-#define PHY_POWER_STATE_LN_2 0x0010
-#define PHY_POWER_STATE_LN_3 0x0018
+#define PHY_POWER_STATE_LN(ln) ((ln) * 8)
#define PMA_XCVR_POWER_STATE_REQ_LN_MASK 0x3FU
#define PHY_PMA_XCVR_POWER_STATE_ACK 0x30
#define PHY_PMA_CMN_READY 0x34
@@ -323,6 +321,7 @@ struct cdns_torrent_phy {
void __iomem *base; /* DPTX registers base */
void __iomem *sd_base; /* SD0801 registers base */
u32 max_bit_rate; /* Maximum link bit rate to use (in Mbps) */
+ u32 dp_pll;
struct reset_control *phy_rst;
struct reset_control *apb_rst;
struct device *dev;
@@ -905,88 +904,129 @@ void cdns_torrent_dp_pma_cmn_vco_cfg_100mhz(struct cdns_torrent_phy *cdns_phy,
/* Setting VCO for 10.8GHz */
case 2700:
case 5400:
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0028);
- cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_FBH_OVRD_M0, 0x0022);
- cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBH_OVRD_M0, 0x0022);
- cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBL_OVRD_M0, 0x000C);
+ if (cdns_phy->dp_pll & DP_PLL0)
+ cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_FBH_OVRD_M0, 0x0022);
+
+ if (cdns_phy->dp_pll & DP_PLL1) {
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0028);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBH_OVRD_M0, 0x0022);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBL_OVRD_M0, 0x000C);
+ }
break;
/* Setting VCO for 9.72GHz */
case 1620:
case 2430:
case 3240:
- cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
- cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
- cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0061);
- cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0061);
- cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x3333);
- cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x3333);
- cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0042);
- cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0042);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+ if (cdns_phy->dp_pll & DP_PLL0) {
+ cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0061);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x3333);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0042);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
+ }
+ if (cdns_phy->dp_pll & DP_PLL1) {
+ cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0061);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x3333);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0042);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+ }
break;
/* Setting VCO for 8.64GHz */
case 2160:
case 4320:
- cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
- cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
- cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0056);
- cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0056);
- cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x6666);
- cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x6666);
- cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x003A);
- cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x003A);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+ if (cdns_phy->dp_pll & DP_PLL0) {
+ cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0056);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x6666);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x003A);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
+ }
+ if (cdns_phy->dp_pll & DP_PLL1) {
+ cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0056);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x6666);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x003A);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+ }
break;
/* Setting VCO for 8.1GHz */
case 8100:
- cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
- cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
- cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0051);
- cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0051);
- cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0036);
- cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0036);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+ if (cdns_phy->dp_pll & DP_PLL0) {
+ cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0051);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0036);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
+ }
+ if (cdns_phy->dp_pll & DP_PLL1) {
+ cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0051);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0036);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+ }
break;
}
}
+/* Set PLL used for DP configuration */
+static int cdns_torrent_dp_get_pll(struct cdns_torrent_phy *cdns_phy,
+ enum cdns_torrent_phy_type phy_t2)
+{
+ switch (phy_t2) {
+ case TYPE_PCIE:
+ case TYPE_USB:
+ cdns_phy->dp_pll = DP_PLL1;
+ break;
+ case TYPE_SGMII:
+ case TYPE_QSGMII:
+ cdns_phy->dp_pll = DP_PLL0;
+ break;
+ case TYPE_NONE:
+ cdns_phy->dp_pll = DP_PLL0 | DP_PLL1;
+ break;
+ default:
+ dev_err(cdns_phy->dev, "Unsupported PHY configuration\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/*
* Enable or disable PLL for selected lanes.
*/
static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy,
+ struct cdns_torrent_inst *inst,
struct phy_configure_opts_dp *dp,
bool enable)
{
- u32 rd_val;
- u32 ret;
struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
+ u32 rd_val, pll_ack_val;
+ int ret;
/*
* Used to determine, which bits to check for or enable in
@@ -996,28 +1036,18 @@ static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy,
/* Used to enable or disable lanes. */
u32 pll_val;
- /* Select values of registers and mask, depending on enabled lane
- * count.
- */
- switch (dp->lanes) {
- /* lane 0 */
- case (1):
- pll_bits = 0x00000001;
- break;
- /* lanes 0-1 */
- case (2):
- pll_bits = 0x00000003;
- break;
- /* lanes 0-3, all */
- default:
- pll_bits = 0x0000000F;
- break;
- }
+ /* Select values of registers and mask, depending on enabled lane count. */
+ pll_val = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN);
- if (enable)
- pll_val = pll_bits;
- else
- pll_val = 0x00000000;
+ if (enable) {
+ pll_bits = ((1 << dp->lanes) - 1);
+ pll_val |= pll_bits;
+ pll_ack_val = pll_bits;
+ } else {
+ pll_bits = ((1 << inst->num_lanes) - 1);
+ pll_val &= (~pll_bits);
+ pll_ack_val = 0;
+ }
cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, pll_val);
@@ -1025,22 +1055,23 @@ static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy,
ret = regmap_read_poll_timeout(regmap,
PHY_PMA_XCVR_PLLCLK_EN_ACK,
rd_val,
- (rd_val & pll_bits) == pll_val,
+ (rd_val & pll_bits) == pll_ack_val,
0, POLL_TIMEOUT_US);
ndelay(100);
return ret;
}
static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy,
+ struct cdns_torrent_inst *inst,
u32 num_lanes,
enum phy_powerstate powerstate)
{
/* Register value for power state for a single byte. */
- u32 value_part;
- u32 value;
- u32 mask;
+ u32 value_part, i;
+ u32 value = 0;
+ u32 mask = 0;
u32 read_val;
- u32 ret;
+ int ret;
struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
switch (powerstate) {
@@ -1056,29 +1087,11 @@ static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy,
break;
}
- /* Select values of registers and mask, depending on enabled
- * lane count.
- */
- switch (num_lanes) {
- /* lane 0 */
- case (1):
- value = value_part;
- mask = 0x0000003FU;
- break;
- /* lanes 0-1 */
- case (2):
- value = (value_part
- | (value_part << 8));
- mask = 0x00003F3FU;
- break;
- /* lanes 0-3, all */
- default:
- value = (value_part
- | (value_part << 8)
- | (value_part << 16)
- | (value_part << 24));
- mask = 0x3F3F3F3FU;
- break;
+ /* Select values of registers and mask, depending on enabled lane count. */
+
+ for (i = 0; i < num_lanes; i++) {
+ value |= (value_part << PHY_POWER_STATE_LN(i));
+ mask |= (PMA_XCVR_POWER_STATE_REQ_LN_MASK << PHY_POWER_STATE_LN(i));
}
/* Set power state A<n>. */
@@ -1093,7 +1106,8 @@ static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy,
return ret;
}
-static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes)
+static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy,
+ struct cdns_torrent_inst *inst, u32 num_lanes)
{
unsigned int read_val;
int ret;
@@ -1114,12 +1128,12 @@ static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes)
ndelay(100);
- ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes,
+ ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, num_lanes,
POWERSTATE_A2);
if (ret)
return ret;
- ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes,
+ ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, num_lanes,
POWERSTATE_A0);
return ret;
@@ -1143,6 +1157,7 @@ static int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy)
}
static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy,
+ struct cdns_torrent_inst *inst,
u32 rate, u32 num_lanes)
{
unsigned int clk_sel_val = 0;
@@ -1175,14 +1190,17 @@ static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy,
break;
}
- cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
- CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val);
- cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
- CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val);
+ if (cdns_phy->dp_pll & DP_PLL0)
+ cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
+ CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val);
+
+ if (cdns_phy->dp_pll & DP_PLL1)
+ cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
+ CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val);
/* PMA lane configuration to deal with multi-link operation */
for (i = 0; i < num_lanes; i++)
- cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[i],
+ cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + i],
XCVR_DIAG_HSCLK_DIV, hsclk_div_val);
}
@@ -1191,23 +1209,44 @@ static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy,
* set and PLL disable request was processed.
*/
static int cdns_torrent_dp_configure_rate(struct cdns_torrent_phy *cdns_phy,
+ struct cdns_torrent_inst *inst,
struct phy_configure_opts_dp *dp)
{
- u32 read_val, ret;
+ u32 read_val, field_val;
+ int ret;
- /* Disable the cmn_pll0_en before re-programming the new data rate. */
- regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, 0x0);
+ /*
+ * Disable the associated PLL (cmn_pll0_en or cmn_pll1_en) before
+ * re-programming the new data rate.
+ */
+ ret = regmap_field_read(cdns_phy->phy_pma_pll_raw_ctrl, &field_val);
+ if (ret)
+ return ret;
+ field_val &= ~(cdns_phy->dp_pll);
+ regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, field_val);
/*
* Wait for PLL ready de-assertion.
* For PLL0 - PHY_PMA_CMN_CTRL2[2] == 1
+ * For PLL1 - PHY_PMA_CMN_CTRL2[3] == 1
*/
- ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
- read_val,
- ((read_val >> 2) & 0x01) != 0,
- 0, POLL_TIMEOUT_US);
- if (ret)
- return ret;
+ if (cdns_phy->dp_pll & DP_PLL0) {
+ ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
+ read_val,
+ ((read_val >> 2) & 0x01) != 0,
+ 0, POLL_TIMEOUT_US);
+ if (ret)
+ return ret;
+ }
+
+ if ((cdns_phy->dp_pll & DP_PLL1) && cdns_phy->nsubnodes != 1) {
+ ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
+ read_val,
+ ((read_val >> 3) & 0x01) != 0,
+ 0, POLL_TIMEOUT_US);
+ if (ret)
+ return ret;
+ }
ndelay(200);
/* DP Rate Change - VCO Output settings. */
@@ -1221,19 +1260,35 @@ static int cdns_torrent_dp_configure_rate(struct cdns_torrent_phy *cdns_phy,
/* PMA common configuration 100MHz */
cdns_torrent_dp_pma_cmn_vco_cfg_100mhz(cdns_phy, dp->link_rate, dp->ssc);
- cdns_torrent_dp_pma_cmn_rate(cdns_phy, dp->link_rate, dp->lanes);
+ cdns_torrent_dp_pma_cmn_rate(cdns_phy, inst, dp->link_rate, dp->lanes);
- /* Enable the cmn_pll0_en. */
- regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, 0x3);
+ /* Enable the associated PLL (cmn_pll0_en or cmn_pll1_en) */
+ ret = regmap_field_read(cdns_phy->phy_pma_pll_raw_ctrl, &field_val);
+ if (ret)
+ return ret;
+ field_val |= cdns_phy->dp_pll;
+ regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, field_val);
/*
* Wait for PLL ready assertion.
* For PLL0 - PHY_PMA_CMN_CTRL2[0] == 1
+ * For PLL1 - PHY_PMA_CMN_CTRL2[1] == 1
*/
- ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
- read_val,
- (read_val & 0x01) != 0,
- 0, POLL_TIMEOUT_US);
+ if (cdns_phy->dp_pll & DP_PLL0) {
+ ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
+ read_val,
+ (read_val & 0x01) != 0,
+ 0, POLL_TIMEOUT_US);
+ if (ret)
+ return ret;
+ }
+
+ if ((cdns_phy->dp_pll & DP_PLL1) && cdns_phy->nsubnodes != 1)
+ ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
+ read_val,
+ ((read_val >> 1) & 0x01) != 0,
+ 0, POLL_TIMEOUT_US);
+
return ret;
}
@@ -1301,6 +1356,7 @@ static int cdns_torrent_dp_verify_config(struct cdns_torrent_inst *inst,
/* Set power state A0 and PLL clock enable to 0 on enabled lanes. */
static void cdns_torrent_dp_set_a0_pll(struct cdns_torrent_phy *cdns_phy,
+ struct cdns_torrent_inst *inst,
u32 num_lanes)
{
struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
@@ -1308,27 +1364,13 @@ static void cdns_torrent_dp_set_a0_pll(struct cdns_torrent_phy *cdns_phy,
PHY_PMA_XCVR_POWER_STATE_REQ);
u32 pll_clk_en = cdns_torrent_dp_read(regmap,
PHY_PMA_XCVR_PLLCLK_EN);
+ u32 i;
- /* Lane 0 is always enabled. */
- pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
- PHY_POWER_STATE_LN_0);
- pll_clk_en &= ~0x01U;
-
- if (num_lanes > 1) {
- /* lane 1 */
- pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
- PHY_POWER_STATE_LN_1);
- pll_clk_en &= ~(0x01U << 1);
- }
+ for (i = 0; i < num_lanes; i++) {
+ pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK
+ << PHY_POWER_STATE_LN(inst->mlane + i));
- if (num_lanes > 2) {
- /* lanes 2 and 3 */
- pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
- PHY_POWER_STATE_LN_2);
- pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
- PHY_POWER_STATE_LN_3);
- pll_clk_en &= ~(0x01U << 2);
- pll_clk_en &= ~(0x01U << 3);
+ pll_clk_en &= ~(0x01U << (inst->mlane + i));
}
cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, pwr_state);
@@ -1337,36 +1379,57 @@ static void cdns_torrent_dp_set_a0_pll(struct cdns_torrent_phy *cdns_phy,
/* Configure lane count as required. */
static int cdns_torrent_dp_set_lanes(struct cdns_torrent_phy *cdns_phy,
+ struct cdns_torrent_inst *inst,
struct phy_configure_opts_dp *dp)
{
- u32 value;
- u32 ret;
+ u32 value, i;
+ int ret;
struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
u8 lane_mask = (1 << dp->lanes) - 1;
+ u8 pma_tx_elec_idle_mask = 0;
+ u32 clane = inst->mlane;
+
+ lane_mask <<= clane;
value = cdns_torrent_dp_read(regmap, PHY_RESET);
/* clear pma_tx_elec_idle_ln_* bits. */
- value &= ~PMA_TX_ELEC_IDLE_MASK;
+ pma_tx_elec_idle_mask = ((1 << inst->num_lanes) - 1) << clane;
+
+ pma_tx_elec_idle_mask <<= PMA_TX_ELEC_IDLE_SHIFT;
+
+ value &= ~pma_tx_elec_idle_mask;
+
/* Assert pma_tx_elec_idle_ln_* for disabled lanes. */
value |= ((~lane_mask) << PMA_TX_ELEC_IDLE_SHIFT) &
- PMA_TX_ELEC_IDLE_MASK;
+ pma_tx_elec_idle_mask;
+
cdns_torrent_dp_write(regmap, PHY_RESET, value);
- /* reset the link by asserting phy_l00_reset_n low */
+ /* reset the link by asserting master lane phy_l0*_reset_n low */
cdns_torrent_dp_write(regmap, PHY_RESET,
- value & (~PHY_L00_RESET_N_MASK));
+ value & (~(1 << clane)));
/*
- * Assert lane reset on unused lanes and lane 0 so they remain in reset
+ * Assert lane reset on unused lanes and master lane so they remain in reset
* and powered down when re-enabling the link
*/
- value = (value & 0x0000FFF0) | (0x0000000E & lane_mask);
+ for (i = 0; i < inst->num_lanes; i++)
+ value &= (~(1 << (clane + i)));
+
+ for (i = 1; i < inst->num_lanes; i++)
+ value |= ((1 << (clane + i)) & lane_mask);
+
cdns_torrent_dp_write(regmap, PHY_RESET, value);
- cdns_torrent_dp_set_a0_pll(cdns_phy, dp->lanes);
+ cdns_torrent_dp_set_a0_pll(cdns_phy, inst, dp->lanes);
/* release phy_l0*_reset_n based on used laneCount */
- value = (value & 0x0000FFF0) | (0x0000000F & lane_mask);
+ for (i = 0; i < inst->num_lanes; i++)
+ value &= (~(1 << (clane + i)));
+
+ for (i = 0; i < inst->num_lanes; i++)
+ value |= ((1 << (clane + i)) & lane_mask);
+
cdns_torrent_dp_write(regmap, PHY_RESET, value);
/* Wait, until PHY gets ready after releasing PHY reset signal. */
@@ -1377,41 +1440,44 @@ static int cdns_torrent_dp_set_lanes(struct cdns_torrent_phy *cdns_phy,
ndelay(100);
/* release pma_xcvr_pllclk_en_ln_*, only for the master lane */
- cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, 0x0001);
+ value = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN);
+ value |= (1 << clane);
+ cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, value);
- ret = cdns_torrent_dp_run(cdns_phy, dp->lanes);
+ ret = cdns_torrent_dp_run(cdns_phy, inst, dp->lanes);
return ret;
}
/* Configure link rate as required. */
static int cdns_torrent_dp_set_rate(struct cdns_torrent_phy *cdns_phy,
+ struct cdns_torrent_inst *inst,
struct phy_configure_opts_dp *dp)
{
- u32 ret;
+ int ret;
- ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes,
+ ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes,
POWERSTATE_A3);
if (ret)
return ret;
- ret = cdns_torrent_dp_set_pll_en(cdns_phy, dp, false);
+ ret = cdns_torrent_dp_set_pll_en(cdns_phy, inst, dp, false);
if (ret)
return ret;
ndelay(200);
- ret = cdns_torrent_dp_configure_rate(cdns_phy, dp);
+ ret = cdns_torrent_dp_configure_rate(cdns_phy, inst, dp);
if (ret)
return ret;
ndelay(200);
- ret = cdns_torrent_dp_set_pll_en(cdns_phy, dp, true);
+ ret = cdns_torrent_dp_set_pll_en(cdns_phy, inst, dp, true);
if (ret)
return ret;
- ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes,
+ ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes,
POWERSTATE_A2);
if (ret)
return ret;
- ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes,
+ ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes,
POWERSTATE_A0);
if (ret)
return ret;
@@ -1422,44 +1488,45 @@ static int cdns_torrent_dp_set_rate(struct cdns_torrent_phy *cdns_phy,
/* Configure voltage swing and pre-emphasis for all enabled lanes. */
static void cdns_torrent_dp_set_voltages(struct cdns_torrent_phy *cdns_phy,
+ struct cdns_torrent_inst *inst,
struct phy_configure_opts_dp *dp)
{
u8 lane;
u16 val;
for (lane = 0; lane < dp->lanes; lane++) {
- val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[lane],
+ val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
TX_DIAG_ACYA);
/*
* Write 1 to register bit TX_DIAG_ACYA[0] to freeze the
* current state of the analog TX driver.
*/
val |= TX_DIAG_ACYA_HBDC_MASK;
- cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
+ cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
TX_DIAG_ACYA, val);
- cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
+ cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
TX_TXCC_CTRL, 0x08A4);
val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].diag_tx_drv;
- cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
+ cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
DRV_DIAG_TX_DRV, val);
val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].mgnfs_mult;
- cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
+ cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
TX_TXCC_MGNFS_MULT_000,
val);
val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].cpost_mult;
- cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
+ cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
TX_TXCC_CPOST_MULT_00,
val);
- val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[lane],
+ val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
TX_DIAG_ACYA);
/*
* Write 0 to register bit TX_DIAG_ACYA[0] to allow the state of
* analog TX driver to reflect the new programmed one.
*/
val &= ~TX_DIAG_ACYA_HBDC_MASK;
- cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
+ cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
TX_DIAG_ACYA, val);
}
};
@@ -1478,7 +1545,7 @@ static int cdns_torrent_dp_configure(struct phy *phy,
}
if (opts->dp.set_lanes) {
- ret = cdns_torrent_dp_set_lanes(cdns_phy, &opts->dp);
+ ret = cdns_torrent_dp_set_lanes(cdns_phy, inst, &opts->dp);
if (ret) {
dev_err(&phy->dev, "cdns_torrent_dp_set_lanes failed\n");
return ret;
@@ -1486,7 +1553,7 @@ static int cdns_torrent_dp_configure(struct phy *phy,
}
if (opts->dp.set_rate) {
- ret = cdns_torrent_dp_set_rate(cdns_phy, &opts->dp);
+ ret = cdns_torrent_dp_set_rate(cdns_phy, inst, &opts->dp);
if (ret) {
dev_err(&phy->dev, "cdns_torrent_dp_set_rate failed\n");
return ret;
@@ -1494,7 +1561,7 @@ static int cdns_torrent_dp_configure(struct phy *phy,
}
if (opts->dp.set_voltages)
- cdns_torrent_dp_set_voltages(cdns_phy, &opts->dp);
+ cdns_torrent_dp_set_voltages(cdns_phy, inst, &opts->dp);
return ret;
}
@@ -1562,6 +1629,7 @@ static void cdns_torrent_dp_common_init(struct cdns_torrent_phy *cdns_phy,
{
struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
unsigned char lane_bits;
+ u32 val;
cdns_torrent_dp_write(regmap, PHY_AUX_CTRL, 0x0003); /* enable AUX */
@@ -1569,18 +1637,23 @@ static void cdns_torrent_dp_common_init(struct cdns_torrent_phy *cdns_phy,
* Set lines power state to A0
* Set lines pll clk enable to 0
*/
- cdns_torrent_dp_set_a0_pll(cdns_phy, inst->num_lanes);
+ cdns_torrent_dp_set_a0_pll(cdns_phy, inst, inst->num_lanes);
/*
* release phy_l0*_reset_n and pma_tx_elec_idle_ln_* based on
* used lanes
*/
lane_bits = (1 << inst->num_lanes) - 1;
- cdns_torrent_dp_write(regmap, PHY_RESET,
- ((0xF & ~lane_bits) << 4) | (0xF & lane_bits));
+
+ val = cdns_torrent_dp_read(regmap, PHY_RESET);
+ val |= (0xF & lane_bits);
+ val &= ~(lane_bits << 4);
+ cdns_torrent_dp_write(regmap, PHY_RESET, val);
/* release pma_xcvr_pllclk_en_ln_*, only for the master lane */
- cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, 0x0001);
+ val = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN);
+ val |= 1;
+ cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, val);
/*
* PHY PMA registers configuration functions
@@ -1599,7 +1672,7 @@ static void cdns_torrent_dp_common_init(struct cdns_torrent_phy *cdns_phy,
cdns_phy->max_bit_rate,
false);
- cdns_torrent_dp_pma_cmn_rate(cdns_phy, cdns_phy->max_bit_rate,
+ cdns_torrent_dp_pma_cmn_rate(cdns_phy, inst, cdns_phy->max_bit_rate,
inst->num_lanes);
/* take out of reset */
@@ -1612,13 +1685,15 @@ static int cdns_torrent_dp_start(struct cdns_torrent_phy *cdns_phy,
{
int ret;
- cdns_torrent_phy_on(phy);
+ ret = cdns_torrent_phy_on(phy);
+ if (ret)
+ return ret;
ret = cdns_torrent_dp_wait_pma_cmn_ready(cdns_phy);
if (ret)
return ret;
- ret = cdns_torrent_dp_run(cdns_phy, inst->num_lanes);
+ ret = cdns_torrent_dp_run(cdns_phy, inst, inst->num_lanes);
return ret;
}
@@ -1627,6 +1702,7 @@ static int cdns_torrent_dp_init(struct phy *phy)
{
struct cdns_torrent_inst *inst = phy_get_drvdata(phy);
struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent);
+ int ret;
switch (cdns_phy->ref_clk_rate) {
case CLK_19_2_MHZ:
@@ -1639,6 +1715,24 @@ static int cdns_torrent_dp_init(struct phy *phy)
return -EINVAL;
}
+ ret = cdns_torrent_dp_get_pll(cdns_phy, TYPE_NONE);
+ if (ret)
+ return ret;
+
+ cdns_torrent_dp_common_init(cdns_phy, inst);
+
+ return cdns_torrent_dp_start(cdns_phy, inst, phy);
+}
+
+static int cdns_torrent_dp_multilink_init(struct cdns_torrent_phy *cdns_phy,
+ struct cdns_torrent_inst *inst,
+ struct phy *phy)
+{
+ if (cdns_phy->ref_clk_rate != CLK_100_MHZ) {
+ dev_err(cdns_phy->dev, "Unsupported Ref Clock Rate\n");
+ return -EINVAL;
+ }
+
cdns_torrent_dp_common_init(cdns_phy, inst);
return cdns_torrent_dp_start(cdns_phy, inst, phy);
@@ -1861,6 +1955,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,
};
@@ -2155,8 +2250,11 @@ static int cdns_torrent_phy_init(struct phy *phy)
u32 num_regs;
int i, j;
- if (cdns_phy->nsubnodes > 1)
+ if (cdns_phy->nsubnodes > 1) {
+ if (phy_type == TYPE_DP)
+ return cdns_torrent_dp_multilink_init(cdns_phy, inst, phy);
return 0;
+ }
/**
* Spread spectrum generation is not required or supported
@@ -2398,6 +2496,12 @@ int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy)
}
}
+ if (phy_t1 == TYPE_DP) {
+ ret = cdns_torrent_dp_get_pll(cdns_phy, phy_t2);
+ if (ret)
+ return ret;
+ }
+
reset_control_deassert(cdns_phy->phys[node].lnk_rst);
}
@@ -2793,6 +2897,109 @@ static void cdns_torrent_phy_remove(struct platform_device *pdev)
cdns_torrent_clk_cleanup(cdns_phy);
}
+/* USB and DP link configuration */
+static struct cdns_reg_pairs usb_dp_link_cmn_regs[] = {
+ {0x0002, PHY_PLL_CFG},
+ {0x8600, CMN_PDIAG_PLL0_CLK_SEL_M0}
+};
+
+static struct cdns_reg_pairs usb_dp_xcvr_diag_ln_regs[] = {
+ {0x0000, XCVR_DIAG_HSCLK_SEL},
+ {0x0001, XCVR_DIAG_HSCLK_DIV},
+ {0x0041, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static struct cdns_reg_pairs dp_usb_xcvr_diag_ln_regs[] = {
+ {0x0001, XCVR_DIAG_HSCLK_SEL},
+ {0x0009, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static struct cdns_torrent_vals usb_dp_link_cmn_vals = {
+ .reg_pairs = usb_dp_link_cmn_regs,
+ .num_regs = ARRAY_SIZE(usb_dp_link_cmn_regs),
+};
+
+static struct cdns_torrent_vals usb_dp_xcvr_diag_ln_vals = {
+ .reg_pairs = usb_dp_xcvr_diag_ln_regs,
+ .num_regs = ARRAY_SIZE(usb_dp_xcvr_diag_ln_regs),
+};
+
+static struct cdns_torrent_vals dp_usb_xcvr_diag_ln_vals = {
+ .reg_pairs = dp_usb_xcvr_diag_ln_regs,
+ .num_regs = ARRAY_SIZE(dp_usb_xcvr_diag_ln_regs),
+};
+
+/* PCIe and DP link configuration */
+static struct cdns_reg_pairs pcie_dp_link_cmn_regs[] = {
+ {0x0003, PHY_PLL_CFG},
+ {0x0601, CMN_PDIAG_PLL0_CLK_SEL_M0},
+ {0x0400, CMN_PDIAG_PLL0_CLK_SEL_M1}
+};
+
+static struct cdns_reg_pairs pcie_dp_xcvr_diag_ln_regs[] = {
+ {0x0000, XCVR_DIAG_HSCLK_SEL},
+ {0x0001, XCVR_DIAG_HSCLK_DIV},
+ {0x0012, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static struct cdns_reg_pairs dp_pcie_xcvr_diag_ln_regs[] = {
+ {0x0001, XCVR_DIAG_HSCLK_SEL},
+ {0x0009, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static struct cdns_torrent_vals pcie_dp_link_cmn_vals = {
+ .reg_pairs = pcie_dp_link_cmn_regs,
+ .num_regs = ARRAY_SIZE(pcie_dp_link_cmn_regs),
+};
+
+static struct cdns_torrent_vals pcie_dp_xcvr_diag_ln_vals = {
+ .reg_pairs = pcie_dp_xcvr_diag_ln_regs,
+ .num_regs = ARRAY_SIZE(pcie_dp_xcvr_diag_ln_regs),
+};
+
+static struct cdns_torrent_vals dp_pcie_xcvr_diag_ln_vals = {
+ .reg_pairs = dp_pcie_xcvr_diag_ln_regs,
+ .num_regs = ARRAY_SIZE(dp_pcie_xcvr_diag_ln_regs),
+};
+
+/* DP Multilink, 100 MHz Ref clk, no SSC */
+static struct cdns_reg_pairs dp_100_no_ssc_cmn_regs[] = {
+ {0x007F, CMN_TXPUCAL_TUNE},
+ {0x007F, CMN_TXPDCAL_TUNE}
+};
+
+static struct cdns_reg_pairs dp_100_no_ssc_tx_ln_regs[] = {
+ {0x00FB, TX_PSC_A0},
+ {0x04AA, TX_PSC_A2},
+ {0x04AA, TX_PSC_A3},
+ {0x000F, XCVR_DIAG_BIDI_CTRL}
+};
+
+static struct cdns_reg_pairs dp_100_no_ssc_rx_ln_regs[] = {
+ {0x0000, RX_PSC_A0},
+ {0x0000, RX_PSC_A2},
+ {0x0000, RX_PSC_A3},
+ {0x0000, RX_PSC_CAL},
+ {0x0000, RX_REE_GCSM1_CTRL},
+ {0x0000, RX_REE_GCSM2_CTRL},
+ {0x0000, RX_REE_PERGCSM_CTRL}
+};
+
+static struct cdns_torrent_vals dp_100_no_ssc_cmn_vals = {
+ .reg_pairs = dp_100_no_ssc_cmn_regs,
+ .num_regs = ARRAY_SIZE(dp_100_no_ssc_cmn_regs),
+};
+
+static struct cdns_torrent_vals dp_100_no_ssc_tx_ln_vals = {
+ .reg_pairs = dp_100_no_ssc_tx_ln_regs,
+ .num_regs = ARRAY_SIZE(dp_100_no_ssc_tx_ln_regs),
+};
+
+static struct cdns_torrent_vals dp_100_no_ssc_rx_ln_vals = {
+ .reg_pairs = dp_100_no_ssc_rx_ln_regs,
+ .num_regs = ARRAY_SIZE(dp_100_no_ssc_rx_ln_regs),
+};
+
/* Single DisplayPort(DP) link configuration */
static struct cdns_reg_pairs sl_dp_link_cmn_regs[] = {
{0x0000, PHY_PLL_CFG},
@@ -3735,6 +3942,12 @@ static const struct cdns_torrent_data cdns_map_torrent = {
[TYPE_NONE] = {
[NO_SSC] = &sl_dp_link_cmn_vals,
},
+ [TYPE_PCIE] = {
+ [NO_SSC] = &pcie_dp_link_cmn_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &usb_dp_link_cmn_vals,
+ },
},
[TYPE_PCIE] = {
[TYPE_NONE] = {
@@ -3757,6 +3970,9 @@ static const struct cdns_torrent_data cdns_map_torrent = {
[EXTERNAL_SSC] = &pcie_usb_link_cmn_vals,
[INTERNAL_SSC] = &pcie_usb_link_cmn_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &pcie_dp_link_cmn_vals,
+ },
},
[TYPE_SGMII] = {
[TYPE_NONE] = {
@@ -3809,6 +4025,9 @@ static const struct cdns_torrent_data cdns_map_torrent = {
[EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
[INTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &usb_dp_link_cmn_vals,
+ },
},
},
.xcvr_diag_vals = {
@@ -3816,6 +4035,12 @@ static const struct cdns_torrent_data cdns_map_torrent = {
[TYPE_NONE] = {
[NO_SSC] = &sl_dp_xcvr_diag_ln_vals,
},
+ [TYPE_PCIE] = {
+ [NO_SSC] = &dp_pcie_xcvr_diag_ln_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &dp_usb_xcvr_diag_ln_vals,
+ },
},
[TYPE_PCIE] = {
[TYPE_NONE] = {
@@ -3838,6 +4063,9 @@ static const struct cdns_torrent_data cdns_map_torrent = {
[EXTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals,
[INTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &pcie_dp_xcvr_diag_ln_vals,
+ },
},
[TYPE_SGMII] = {
[TYPE_NONE] = {
@@ -3890,6 +4118,9 @@ static const struct cdns_torrent_data cdns_map_torrent = {
[EXTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals,
[INTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &usb_dp_xcvr_diag_ln_vals,
+ },
},
},
.pcs_cmn_vals = {
@@ -3914,6 +4145,9 @@ static const struct cdns_torrent_data cdns_map_torrent = {
[EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
[INTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &usb_phy_pcs_cmn_vals,
+ },
},
},
.cmn_vals = {
@@ -3936,6 +4170,12 @@ static const struct cdns_torrent_data cdns_map_torrent = {
[TYPE_NONE] = {
[NO_SSC] = &sl_dp_100_no_ssc_cmn_vals,
},
+ [TYPE_PCIE] = {
+ [NO_SSC] = &dp_100_no_ssc_cmn_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals,
+ },
},
[TYPE_PCIE] = {
[TYPE_NONE] = {
@@ -3958,6 +4198,9 @@ static const struct cdns_torrent_data cdns_map_torrent = {
[EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
[INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = NULL,
+ },
},
[TYPE_SGMII] = {
[TYPE_NONE] = {
@@ -4010,6 +4253,9 @@ static const struct cdns_torrent_data cdns_map_torrent = {
[EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
[INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &usb_100_no_ssc_cmn_vals,
+ },
},
},
},
@@ -4033,6 +4279,12 @@ static const struct cdns_torrent_data cdns_map_torrent = {
[TYPE_NONE] = {
[NO_SSC] = &sl_dp_100_no_ssc_tx_ln_vals,
},
+ [TYPE_PCIE] = {
+ [NO_SSC] = &dp_100_no_ssc_tx_ln_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &dp_100_no_ssc_tx_ln_vals,
+ },
},
[TYPE_PCIE] = {
[TYPE_NONE] = {
@@ -4055,6 +4307,9 @@ static const struct cdns_torrent_data cdns_map_torrent = {
[EXTERNAL_SSC] = NULL,
[INTERNAL_SSC] = NULL,
},
+ [TYPE_DP] = {
+ [NO_SSC] = NULL,
+ },
},
[TYPE_SGMII] = {
[TYPE_NONE] = {
@@ -4107,6 +4362,9 @@ static const struct cdns_torrent_data cdns_map_torrent = {
[EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
[INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ },
},
},
},
@@ -4130,6 +4388,12 @@ static const struct cdns_torrent_data cdns_map_torrent = {
[TYPE_NONE] = {
[NO_SSC] = &sl_dp_100_no_ssc_rx_ln_vals,
},
+ [TYPE_PCIE] = {
+ [NO_SSC] = &dp_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &dp_100_no_ssc_rx_ln_vals,
+ },
},
[TYPE_PCIE] = {
[TYPE_NONE] = {
@@ -4152,6 +4416,9 @@ static const struct cdns_torrent_data cdns_map_torrent = {
[EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
[INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ },
},
[TYPE_SGMII] = {
[TYPE_NONE] = {
@@ -4204,6 +4471,9 @@ static const struct cdns_torrent_data cdns_map_torrent = {
[EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
[INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ },
},
},
},
@@ -4217,6 +4487,12 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
[TYPE_NONE] = {
[NO_SSC] = &sl_dp_link_cmn_vals,
},
+ [TYPE_PCIE] = {
+ [NO_SSC] = &pcie_dp_link_cmn_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &usb_dp_link_cmn_vals,
+ },
},
[TYPE_PCIE] = {
[TYPE_NONE] = {
@@ -4239,6 +4515,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
[EXTERNAL_SSC] = &pcie_usb_link_cmn_vals,
[INTERNAL_SSC] = &pcie_usb_link_cmn_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &pcie_dp_link_cmn_vals,
+ },
},
[TYPE_SGMII] = {
[TYPE_NONE] = {
@@ -4291,6 +4570,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
[EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
[INTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &usb_dp_link_cmn_vals,
+ },
},
},
.xcvr_diag_vals = {
@@ -4298,6 +4580,12 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
[TYPE_NONE] = {
[NO_SSC] = &sl_dp_xcvr_diag_ln_vals,
},
+ [TYPE_PCIE] = {
+ [NO_SSC] = &dp_pcie_xcvr_diag_ln_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &dp_usb_xcvr_diag_ln_vals,
+ },
},
[TYPE_PCIE] = {
[TYPE_NONE] = {
@@ -4320,6 +4608,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
[EXTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals,
[INTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &pcie_dp_xcvr_diag_ln_vals,
+ },
},
[TYPE_SGMII] = {
[TYPE_NONE] = {
@@ -4372,6 +4663,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
[EXTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals,
[INTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &usb_dp_xcvr_diag_ln_vals,
+ },
},
},
.pcs_cmn_vals = {
@@ -4396,6 +4690,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
[EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
[INTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &usb_phy_pcs_cmn_vals,
+ },
},
},
.cmn_vals = {
@@ -4418,6 +4715,12 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
[TYPE_NONE] = {
[NO_SSC] = &sl_dp_100_no_ssc_cmn_vals,
},
+ [TYPE_PCIE] = {
+ [NO_SSC] = &dp_100_no_ssc_cmn_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals,
+ },
},
[TYPE_PCIE] = {
[TYPE_NONE] = {
@@ -4440,6 +4743,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
[EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
[INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = NULL,
+ },
},
[TYPE_SGMII] = {
[TYPE_NONE] = {
@@ -4492,6 +4798,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
[EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
[INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &usb_100_no_ssc_cmn_vals,
+ },
},
},
},
@@ -4515,6 +4824,12 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
[TYPE_NONE] = {
[NO_SSC] = &sl_dp_100_no_ssc_tx_ln_vals,
},
+ [TYPE_PCIE] = {
+ [NO_SSC] = &dp_100_no_ssc_tx_ln_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &dp_100_no_ssc_tx_ln_vals,
+ },
},
[TYPE_PCIE] = {
[TYPE_NONE] = {
@@ -4537,6 +4852,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
[EXTERNAL_SSC] = NULL,
[INTERNAL_SSC] = NULL,
},
+ [TYPE_DP] = {
+ [NO_SSC] = NULL,
+ },
},
[TYPE_SGMII] = {
[TYPE_NONE] = {
@@ -4589,6 +4907,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
[EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
[INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ },
},
},
},
@@ -4612,6 +4933,12 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
[TYPE_NONE] = {
[NO_SSC] = &sl_dp_100_no_ssc_rx_ln_vals,
},
+ [TYPE_PCIE] = {
+ [NO_SSC] = &dp_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &dp_100_no_ssc_rx_ln_vals,
+ },
},
[TYPE_PCIE] = {
[TYPE_NONE] = {
@@ -4634,6 +4961,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
[EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
[INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ },
},
[TYPE_SGMII] = {
[TYPE_NONE] = {
@@ -4686,6 +5016,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
[EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
[INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
},
+ [TYPE_DP] = {
+ [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ },
},
},
},
diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
index afc63552ecaf..d4c92498ad1e 100644
--- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
@@ -206,7 +206,6 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct imx8_pcie_phy *imx8_phy;
- struct resource *res;
imx8_phy = devm_kzalloc(dev, sizeof(*imx8_phy), GFP_KERNEL);
if (!imx8_phy)
@@ -259,8 +258,7 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev)
"Failed to get PCIE PHY PERST control\n");
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- imx8_phy->base = devm_ioremap_resource(dev, res);
+ imx8_phy->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(imx8_phy->base))
return PTR_ERR(imx8_phy->base);
diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
index a29b4a6f7c24..88826ceb72f8 100644
--- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
+++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
@@ -27,17 +27,231 @@
#define PHY_CTRL2_TXENABLEN0 BIT(8)
#define PHY_CTRL2_OTG_DISABLE BIT(9)
+#define PHY_CTRL3 0xc
+#define PHY_CTRL3_COMPDISTUNE_MASK GENMASK(2, 0)
+#define PHY_CTRL3_TXPREEMP_TUNE_MASK GENMASK(16, 15)
+#define PHY_CTRL3_TXRISE_TUNE_MASK GENMASK(21, 20)
+#define PHY_CTRL3_TXVREF_TUNE_MASK GENMASK(25, 22)
+#define PHY_CTRL3_TX_VBOOST_LEVEL_MASK GENMASK(31, 29)
+
+#define PHY_CTRL4 0x10
+#define PHY_CTRL4_PCS_TX_DEEMPH_3P5DB_MASK GENMASK(20, 15)
+
+#define PHY_CTRL5 0x14
+#define PHY_CTRL5_DMPWD_OVERRIDE_SEL BIT(23)
+#define PHY_CTRL5_DMPWD_OVERRIDE BIT(22)
+#define PHY_CTRL5_DPPWD_OVERRIDE_SEL BIT(21)
+#define PHY_CTRL5_DPPWD_OVERRIDE BIT(20)
+#define PHY_CTRL5_PCS_TX_SWING_FULL_MASK GENMASK(6, 0)
+
#define PHY_CTRL6 0x18
#define PHY_CTRL6_ALT_CLK_EN BIT(1)
#define PHY_CTRL6_ALT_CLK_SEL BIT(0)
+#define PHY_TUNE_DEFAULT 0xffffffff
+
struct imx8mq_usb_phy {
struct phy *phy;
struct clk *clk;
void __iomem *base;
struct regulator *vbus;
+ u32 pcs_tx_swing_full;
+ u32 pcs_tx_deemph_3p5db;
+ u32 tx_vref_tune;
+ u32 tx_rise_tune;
+ u32 tx_preemp_amp_tune;
+ u32 tx_vboost_level;
+ u32 comp_dis_tune;
};
+static u32 phy_tx_vref_tune_from_property(u32 percent)
+{
+ percent = clamp(percent, 94U, 124U);
+
+ return DIV_ROUND_CLOSEST(percent - 94U, 2);
+}
+
+static u32 phy_tx_rise_tune_from_property(u32 percent)
+{
+ switch (percent) {
+ case 0 ... 98:
+ return 3;
+ case 99:
+ return 2;
+ case 100 ... 101:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static u32 phy_tx_preemp_amp_tune_from_property(u32 microamp)
+{
+ microamp = min(microamp, 1800U);
+
+ return microamp / 600;
+}
+
+static u32 phy_tx_vboost_level_from_property(u32 microvolt)
+{
+ switch (microvolt) {
+ case 0 ... 960:
+ return 0;
+ case 961 ... 1160:
+ return 2;
+ default:
+ return 3;
+ }
+}
+
+static u32 phy_pcs_tx_deemph_3p5db_from_property(u32 decibel)
+{
+ return min(decibel, 36U);
+}
+
+static u32 phy_comp_dis_tune_from_property(u32 percent)
+{
+ switch (percent) {
+ case 0 ... 92:
+ return 0;
+ case 93 ... 95:
+ return 1;
+ case 96 ... 97:
+ return 2;
+ case 98 ... 102:
+ return 3;
+ case 103 ... 105:
+ return 4;
+ case 106 ... 109:
+ return 5;
+ case 110 ... 113:
+ return 6;
+ default:
+ return 7;
+ }
+}
+static u32 phy_pcs_tx_swing_full_from_property(u32 percent)
+{
+ percent = min(percent, 100U);
+
+ return (percent * 127) / 100;
+}
+
+static void imx8m_get_phy_tuning_data(struct imx8mq_usb_phy *imx_phy)
+{
+ struct device *dev = imx_phy->phy->dev.parent;
+
+ if (device_property_read_u32(dev, "fsl,phy-tx-vref-tune-percent",
+ &imx_phy->tx_vref_tune))
+ imx_phy->tx_vref_tune = PHY_TUNE_DEFAULT;
+ else
+ imx_phy->tx_vref_tune =
+ phy_tx_vref_tune_from_property(imx_phy->tx_vref_tune);
+
+ if (device_property_read_u32(dev, "fsl,phy-tx-rise-tune-percent",
+ &imx_phy->tx_rise_tune))
+ imx_phy->tx_rise_tune = PHY_TUNE_DEFAULT;
+ else
+ imx_phy->tx_rise_tune =
+ phy_tx_rise_tune_from_property(imx_phy->tx_rise_tune);
+
+ if (device_property_read_u32(dev, "fsl,phy-tx-preemp-amp-tune-microamp",
+ &imx_phy->tx_preemp_amp_tune))
+ imx_phy->tx_preemp_amp_tune = PHY_TUNE_DEFAULT;
+ else
+ imx_phy->tx_preemp_amp_tune =
+ phy_tx_preemp_amp_tune_from_property(imx_phy->tx_preemp_amp_tune);
+
+ if (device_property_read_u32(dev, "fsl,phy-tx-vboost-level-microvolt",
+ &imx_phy->tx_vboost_level))
+ imx_phy->tx_vboost_level = PHY_TUNE_DEFAULT;
+ else
+ imx_phy->tx_vboost_level =
+ phy_tx_vboost_level_from_property(imx_phy->tx_vboost_level);
+
+ if (device_property_read_u32(dev, "fsl,phy-comp-dis-tune-percent",
+ &imx_phy->comp_dis_tune))
+ imx_phy->comp_dis_tune = PHY_TUNE_DEFAULT;
+ else
+ imx_phy->comp_dis_tune =
+ phy_comp_dis_tune_from_property(imx_phy->comp_dis_tune);
+
+ if (device_property_read_u32(dev, "fsl,pcs-tx-deemph-3p5db-attenuation-db",
+ &imx_phy->pcs_tx_deemph_3p5db))
+ imx_phy->pcs_tx_deemph_3p5db = PHY_TUNE_DEFAULT;
+ else
+ imx_phy->pcs_tx_deemph_3p5db =
+ phy_pcs_tx_deemph_3p5db_from_property(imx_phy->pcs_tx_deemph_3p5db);
+
+ if (device_property_read_u32(dev, "fsl,phy-pcs-tx-swing-full-percent",
+ &imx_phy->pcs_tx_swing_full))
+ imx_phy->pcs_tx_swing_full = PHY_TUNE_DEFAULT;
+ else
+ imx_phy->pcs_tx_swing_full =
+ phy_pcs_tx_swing_full_from_property(imx_phy->pcs_tx_swing_full);
+}
+
+static void imx8m_phy_tune(struct imx8mq_usb_phy *imx_phy)
+{
+ u32 value;
+
+ /* PHY tuning */
+ if (imx_phy->pcs_tx_deemph_3p5db != PHY_TUNE_DEFAULT) {
+ value = readl(imx_phy->base + PHY_CTRL4);
+ value &= ~PHY_CTRL4_PCS_TX_DEEMPH_3P5DB_MASK;
+ value |= FIELD_PREP(PHY_CTRL4_PCS_TX_DEEMPH_3P5DB_MASK,
+ imx_phy->pcs_tx_deemph_3p5db);
+ writel(value, imx_phy->base + PHY_CTRL4);
+ }
+
+ if (imx_phy->pcs_tx_swing_full != PHY_TUNE_DEFAULT) {
+ value = readl(imx_phy->base + PHY_CTRL5);
+ value |= FIELD_PREP(PHY_CTRL5_PCS_TX_SWING_FULL_MASK,
+ imx_phy->pcs_tx_swing_full);
+ writel(value, imx_phy->base + PHY_CTRL5);
+ }
+
+ if ((imx_phy->tx_vref_tune & imx_phy->tx_rise_tune &
+ imx_phy->tx_preemp_amp_tune & imx_phy->comp_dis_tune &
+ imx_phy->tx_vboost_level) == PHY_TUNE_DEFAULT)
+ /* If all are the default values, no need update. */
+ return;
+
+ value = readl(imx_phy->base + PHY_CTRL3);
+
+ if (imx_phy->tx_vref_tune != PHY_TUNE_DEFAULT) {
+ value &= ~PHY_CTRL3_TXVREF_TUNE_MASK;
+ value |= FIELD_PREP(PHY_CTRL3_TXVREF_TUNE_MASK,
+ imx_phy->tx_vref_tune);
+ }
+
+ if (imx_phy->tx_rise_tune != PHY_TUNE_DEFAULT) {
+ value &= ~PHY_CTRL3_TXRISE_TUNE_MASK;
+ value |= FIELD_PREP(PHY_CTRL3_TXRISE_TUNE_MASK,
+ imx_phy->tx_rise_tune);
+ }
+
+ if (imx_phy->tx_preemp_amp_tune != PHY_TUNE_DEFAULT) {
+ value &= ~PHY_CTRL3_TXPREEMP_TUNE_MASK;
+ value |= FIELD_PREP(PHY_CTRL3_TXPREEMP_TUNE_MASK,
+ imx_phy->tx_preemp_amp_tune);
+ }
+
+ if (imx_phy->comp_dis_tune != PHY_TUNE_DEFAULT) {
+ value &= ~PHY_CTRL3_COMPDISTUNE_MASK;
+ value |= FIELD_PREP(PHY_CTRL3_COMPDISTUNE_MASK,
+ imx_phy->comp_dis_tune);
+ }
+
+ if (imx_phy->tx_vboost_level != PHY_TUNE_DEFAULT) {
+ value &= ~PHY_CTRL3_TX_VBOOST_LEVEL_MASK;
+ value |= FIELD_PREP(PHY_CTRL3_TX_VBOOST_LEVEL_MASK,
+ imx_phy->tx_vboost_level);
+ }
+
+ writel(value, imx_phy->base + PHY_CTRL3);
+}
+
static int imx8mq_usb_phy_init(struct phy *phy)
{
struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy);
@@ -99,6 +313,8 @@ static int imx8mp_usb_phy_init(struct phy *phy)
value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET);
writel(value, imx_phy->base + PHY_CTRL1);
+ imx8m_phy_tune(imx_phy);
+
return 0;
}
@@ -182,6 +398,8 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
phy_set_drvdata(imx_phy->phy, imx_phy);
+ imx8m_get_phy_tuning_data(imx_phy);
+
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
return PTR_ERR_OR_ZERO(phy_provider);
diff --git a/drivers/phy/hisilicon/Kconfig b/drivers/phy/hisilicon/Kconfig
index d3b92c288554..6c89136fc8c2 100644
--- a/drivers/phy/hisilicon/Kconfig
+++ b/drivers/phy/hisilicon/Kconfig
@@ -54,7 +54,7 @@ config PHY_HISTB_COMBPHY
config PHY_HISI_INNO_USB2
tristate "HiSilicon INNO USB2 PHY support"
- depends on (ARCH_HISI && ARM64) || COMPILE_TEST
+ depends on ARCH_HISI || COMPILE_TEST
select GENERIC_PHY
select MFD_SYSCON
help
diff --git a/drivers/phy/hisilicon/phy-hisi-inno-usb2.c b/drivers/phy/hisilicon/phy-hisi-inno-usb2.c
index b133ae06757a..6ae6d509dfdd 100644
--- a/drivers/phy/hisilicon/phy-hisi-inno-usb2.c
+++ b/drivers/phy/hisilicon/phy-hisi-inno-usb2.c
@@ -9,7 +9,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/module.h>
-#include <linux/platform_device.h>
+#include <linux/of_device.h>
#include <linux/phy/phy.h>
#include <linux/reset.h>
@@ -20,12 +20,25 @@
#define PHY_CLK_STABLE_TIME 2 /* unit:ms */
#define UTMI_RST_COMPLETE_TIME 2 /* unit:ms */
#define POR_RST_COMPLETE_TIME 300 /* unit:us */
+
+#define PHY_TYPE_0 0
+#define PHY_TYPE_1 1
+
#define PHY_TEST_DATA GENMASK(7, 0)
-#define PHY_TEST_ADDR GENMASK(15, 8)
-#define PHY_TEST_PORT GENMASK(18, 16)
-#define PHY_TEST_WREN BIT(21)
-#define PHY_TEST_CLK BIT(22) /* rising edge active */
-#define PHY_TEST_RST BIT(23) /* low active */
+#define PHY_TEST_ADDR_OFFSET 8
+#define PHY0_TEST_ADDR GENMASK(15, 8)
+#define PHY0_TEST_PORT_OFFSET 16
+#define PHY0_TEST_PORT GENMASK(18, 16)
+#define PHY0_TEST_WREN BIT(21)
+#define PHY0_TEST_CLK BIT(22) /* rising edge active */
+#define PHY0_TEST_RST BIT(23) /* low active */
+#define PHY1_TEST_ADDR GENMASK(11, 8)
+#define PHY1_TEST_PORT_OFFSET 12
+#define PHY1_TEST_PORT BIT(12)
+#define PHY1_TEST_WREN BIT(13)
+#define PHY1_TEST_CLK BIT(14) /* rising edge active */
+#define PHY1_TEST_RST BIT(15) /* low active */
+
#define PHY_CLK_ENABLE BIT(2)
struct hisi_inno_phy_port {
@@ -37,6 +50,7 @@ struct hisi_inno_phy_priv {
void __iomem *mmio;
struct clk *ref_clk;
struct reset_control *por_rst;
+ unsigned int type;
struct hisi_inno_phy_port ports[INNO_PHY_PORT_NUM];
};
@@ -45,17 +59,27 @@ static void hisi_inno_phy_write_reg(struct hisi_inno_phy_priv *priv,
{
void __iomem *reg = priv->mmio;
u32 val;
-
- val = (data & PHY_TEST_DATA) |
- ((addr << 8) & PHY_TEST_ADDR) |
- ((port << 16) & PHY_TEST_PORT) |
- PHY_TEST_WREN | PHY_TEST_RST;
+ u32 value;
+
+ if (priv->type == PHY_TYPE_0)
+ val = (data & PHY_TEST_DATA) |
+ ((addr << PHY_TEST_ADDR_OFFSET) & PHY0_TEST_ADDR) |
+ ((port << PHY0_TEST_PORT_OFFSET) & PHY0_TEST_PORT) |
+ PHY0_TEST_WREN | PHY0_TEST_RST;
+ else
+ val = (data & PHY_TEST_DATA) |
+ ((addr << PHY_TEST_ADDR_OFFSET) & PHY1_TEST_ADDR) |
+ ((port << PHY1_TEST_PORT_OFFSET) & PHY1_TEST_PORT) |
+ PHY1_TEST_WREN | PHY1_TEST_RST;
writel(val, reg);
- val |= PHY_TEST_CLK;
- writel(val, reg);
+ value = val;
+ if (priv->type == PHY_TYPE_0)
+ value |= PHY0_TEST_CLK;
+ else
+ value |= PHY1_TEST_CLK;
+ writel(value, reg);
- val &= ~PHY_TEST_CLK;
writel(val, reg);
}
@@ -135,6 +159,8 @@ static int hisi_inno_phy_probe(struct platform_device *pdev)
if (IS_ERR(priv->por_rst))
return PTR_ERR(priv->por_rst);
+ priv->type = (uintptr_t) of_device_get_match_data(dev);
+
for_each_child_of_node(np, child) {
struct reset_control *rst;
struct phy *phy;
@@ -158,7 +184,7 @@ static int hisi_inno_phy_probe(struct platform_device *pdev)
phy_set_drvdata(phy, &priv->ports[i]);
i++;
- if (i > INNO_PHY_PORT_NUM) {
+ if (i >= INNO_PHY_PORT_NUM) {
dev_warn(dev, "Support %d ports in maximum\n", i);
of_node_put(child);
break;
@@ -170,8 +196,12 @@ static int hisi_inno_phy_probe(struct platform_device *pdev)
}
static const struct of_device_id hisi_inno_phy_of_match[] = {
- { .compatible = "hisilicon,inno-usb2-phy", },
- { .compatible = "hisilicon,hi3798cv200-usb2-phy", },
+ { .compatible = "hisilicon,inno-usb2-phy",
+ .data = (void *) PHY_TYPE_0 },
+ { .compatible = "hisilicon,hi3798cv200-usb2-phy",
+ .data = (void *) PHY_TYPE_0 },
+ { .compatible = "hisilicon,hi3798mv100-usb2-phy",
+ .data = (void *) PHY_TYPE_1 },
{ },
};
MODULE_DEVICE_TABLE(of, hisi_inno_phy_of_match);
diff --git a/drivers/phy/mediatek/phy-mtk-dp.c b/drivers/phy/mediatek/phy-mtk-dp.c
index 232fd3f1ff1b..d7024a144335 100644
--- a/drivers/phy/mediatek/phy-mtk-dp.c
+++ b/drivers/phy/mediatek/phy-mtk-dp.c
@@ -169,7 +169,7 @@ static int mtk_dp_phy_probe(struct platform_device *pdev)
regs = *(struct regmap **)dev->platform_data;
if (!regs)
- return dev_err_probe(dev, EINVAL,
+ return dev_err_probe(dev, -EINVAL,
"No data passed, requires struct regmap**\n");
dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
diff --git a/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c b/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c
index 8aa7251de4a9..bbfe11d6a69d 100644
--- a/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c
+++ b/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c
@@ -253,7 +253,7 @@ static int mtk_hdmi_pll_calc(struct mtk_hdmi_phy *hdmi_phy, struct clk_hw *hw,
for (i = 0; i < ARRAY_SIZE(txpredivs); i++) {
ns_hdmipll_ck = 5 * tmds_clk * txposdiv * txpredivs[i];
if (ns_hdmipll_ck >= 5 * GIGA &&
- ns_hdmipll_ck <= 1 * GIGA)
+ ns_hdmipll_ck <= 12 * GIGA)
break;
}
if (i == (ARRAY_SIZE(txpredivs) - 1) &&
diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c
index e906a82791bd..0d110e50bbfd 100644
--- a/drivers/phy/mediatek/phy-mtk-tphy.c
+++ b/drivers/phy/mediatek/phy-mtk-tphy.c
@@ -7,6 +7,7 @@
#include <dt-bindings/phy/phy.h>
#include <linux/clk.h>
+#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/iopoll.h>
#include <linux/mfd/syscon.h>
@@ -264,6 +265,8 @@
#define TPHY_CLKS_CNT 2
+#define USER_BUF_LEN(count) min_t(size_t, 8, (count))
+
enum mtk_phy_version {
MTK_PHY_V1 = 1,
MTK_PHY_V2,
@@ -336,6 +339,358 @@ struct mtk_tphy {
int src_coef; /* coefficient for slew rate calibrate */
};
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+
+enum u2_phy_params {
+ U2P_EYE_VRT = 0,
+ U2P_EYE_TERM,
+ U2P_EFUSE_EN,
+ U2P_EFUSE_INTR,
+ U2P_DISCTH,
+ U2P_PRE_EMPHASIS,
+};
+
+enum u3_phy_params {
+ U3P_EFUSE_EN = 0,
+ U3P_EFUSE_INTR,
+ U3P_EFUSE_TX_IMP,
+ U3P_EFUSE_RX_IMP,
+};
+
+static const char *const u2_phy_files[] = {
+ [U2P_EYE_VRT] = "vrt",
+ [U2P_EYE_TERM] = "term",
+ [U2P_EFUSE_EN] = "efuse",
+ [U2P_EFUSE_INTR] = "intr",
+ [U2P_DISCTH] = "discth",
+ [U2P_PRE_EMPHASIS] = "preemph",
+};
+
+static const char *const u3_phy_files[] = {
+ [U3P_EFUSE_EN] = "efuse",
+ [U3P_EFUSE_INTR] = "intr",
+ [U3P_EFUSE_TX_IMP] = "tx-imp",
+ [U3P_EFUSE_RX_IMP] = "rx-imp",
+};
+
+static int u2_phy_params_show(struct seq_file *sf, void *unused)
+{
+ struct mtk_phy_instance *inst = sf->private;
+ const char *fname = file_dentry(sf->file)->d_iname;
+ struct u2phy_banks *u2_banks = &inst->u2_banks;
+ void __iomem *com = u2_banks->com;
+ u32 max = 0;
+ u32 tmp = 0;
+ u32 val = 0;
+ int ret;
+
+ ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname);
+ if (ret < 0)
+ return ret;
+
+ switch (ret) {
+ case U2P_EYE_VRT:
+ tmp = readl(com + U3P_USBPHYACR1);
+ val = FIELD_GET(PA1_RG_VRT_SEL, tmp);
+ max = FIELD_MAX(PA1_RG_VRT_SEL);
+ break;
+
+ case U2P_EYE_TERM:
+ tmp = readl(com + U3P_USBPHYACR1);
+ val = FIELD_GET(PA1_RG_TERM_SEL, tmp);
+ max = FIELD_MAX(PA1_RG_TERM_SEL);
+ break;
+
+ case U2P_EFUSE_EN:
+ if (u2_banks->misc) {
+ tmp = readl(u2_banks->misc + U3P_MISC_REG1);
+ max = 1;
+ }
+
+ val = !!(tmp & MR1_EFUSE_AUTO_LOAD_DIS);
+ break;
+
+ case U2P_EFUSE_INTR:
+ tmp = readl(com + U3P_USBPHYACR1);
+ val = FIELD_GET(PA1_RG_INTR_CAL, tmp);
+ max = FIELD_MAX(PA1_RG_INTR_CAL);
+ break;
+
+ case U2P_DISCTH:
+ tmp = readl(com + U3P_USBPHYACR6);
+ val = FIELD_GET(PA6_RG_U2_DISCTH, tmp);
+ max = FIELD_MAX(PA6_RG_U2_DISCTH);
+ break;
+
+ case U2P_PRE_EMPHASIS:
+ tmp = readl(com + U3P_USBPHYACR6);
+ val = FIELD_GET(PA6_RG_U2_PRE_EMP, tmp);
+ max = FIELD_MAX(PA6_RG_U2_PRE_EMP);
+ break;
+
+ default:
+ seq_printf(sf, "invalid, %d\n", ret);
+ break;
+ }
+
+ seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max);
+
+ return 0;
+}
+
+static int u2_phy_params_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, u2_phy_params_show, inode->i_private);
+}
+
+static ssize_t u2_phy_params_write(struct file *file, const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ const char *fname = file_dentry(file)->d_iname;
+ struct seq_file *sf = file->private_data;
+ struct mtk_phy_instance *inst = sf->private;
+ struct u2phy_banks *u2_banks = &inst->u2_banks;
+ void __iomem *com = u2_banks->com;
+ ssize_t rc;
+ u32 val;
+ int ret;
+
+ rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val);
+ if (rc)
+ return rc;
+
+ ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname);
+ if (ret < 0)
+ return (ssize_t)ret;
+
+ switch (ret) {
+ case U2P_EYE_VRT:
+ mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_VRT_SEL, val);
+ break;
+
+ case U2P_EYE_TERM:
+ mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_TERM_SEL, val);
+ break;
+
+ case U2P_EFUSE_EN:
+ if (u2_banks->misc)
+ mtk_phy_update_field(u2_banks->misc + U3P_MISC_REG1,
+ MR1_EFUSE_AUTO_LOAD_DIS, !!val);
+ break;
+
+ case U2P_EFUSE_INTR:
+ mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_INTR_CAL, val);
+ break;
+
+ case U2P_DISCTH:
+ mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_DISCTH, val);
+ break;
+
+ case U2P_PRE_EMPHASIS:
+ mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_PRE_EMP, val);
+ break;
+
+ default:
+ break;
+ }
+
+ return count;
+}
+
+static const struct file_operations u2_phy_fops = {
+ .open = u2_phy_params_open,
+ .write = u2_phy_params_write,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void u2_phy_dbgfs_files_create(struct mtk_phy_instance *inst)
+{
+ u32 count = ARRAY_SIZE(u2_phy_files);
+ int i;
+
+ for (i = 0; i < count; i++)
+ debugfs_create_file(u2_phy_files[i], 0644, inst->phy->debugfs,
+ inst, &u2_phy_fops);
+}
+
+static int u3_phy_params_show(struct seq_file *sf, void *unused)
+{
+ struct mtk_phy_instance *inst = sf->private;
+ const char *fname = file_dentry(sf->file)->d_iname;
+ struct u3phy_banks *u3_banks = &inst->u3_banks;
+ u32 val = 0;
+ u32 max = 0;
+ u32 tmp;
+ int ret;
+
+ ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname);
+ if (ret < 0)
+ return ret;
+
+ switch (ret) {
+ case U3P_EFUSE_EN:
+ tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV);
+ val = !!(tmp & P3D_RG_EFUSE_AUTO_LOAD_DIS);
+ max = 1;
+ break;
+
+ case U3P_EFUSE_INTR:
+ tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG0);
+ val = FIELD_GET(P3A_RG_IEXT_INTR, tmp);
+ max = FIELD_MAX(P3A_RG_IEXT_INTR);
+ break;
+
+ case U3P_EFUSE_TX_IMP:
+ tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL0);
+ val = FIELD_GET(P3D_RG_TX_IMPEL, tmp);
+ max = FIELD_MAX(P3D_RG_TX_IMPEL);
+ break;
+
+ case U3P_EFUSE_RX_IMP:
+ tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL1);
+ val = FIELD_GET(P3D_RG_RX_IMPEL, tmp);
+ max = FIELD_MAX(P3D_RG_RX_IMPEL);
+ break;
+
+ default:
+ seq_printf(sf, "invalid, %d\n", ret);
+ break;
+ }
+
+ seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max);
+
+ return 0;
+}
+
+static int u3_phy_params_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, u3_phy_params_show, inode->i_private);
+}
+
+static ssize_t u3_phy_params_write(struct file *file, const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ const char *fname = file_dentry(file)->d_iname;
+ struct seq_file *sf = file->private_data;
+ struct mtk_phy_instance *inst = sf->private;
+ struct u3phy_banks *u3_banks = &inst->u3_banks;
+ void __iomem *phyd = u3_banks->phyd;
+ ssize_t rc;
+ u32 val;
+ int ret;
+
+ rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val);
+ if (rc)
+ return rc;
+
+ ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname);
+ if (ret < 0)
+ return (ssize_t)ret;
+
+ switch (ret) {
+ case U3P_EFUSE_EN:
+ mtk_phy_update_field(phyd + U3P_U3_PHYD_RSV,
+ P3D_RG_EFUSE_AUTO_LOAD_DIS, !!val);
+ break;
+
+ case U3P_EFUSE_INTR:
+ mtk_phy_update_field(u3_banks->phya + U3P_U3_PHYA_REG0,
+ P3A_RG_IEXT_INTR, val);
+ break;
+
+ case U3P_EFUSE_TX_IMP:
+ mtk_phy_update_field(phyd + U3P_U3_PHYD_IMPCAL0, P3D_RG_TX_IMPEL, val);
+ mtk_phy_set_bits(phyd + U3P_U3_PHYD_IMPCAL0, P3D_RG_FORCE_TX_IMPEL);
+ break;
+
+ case U3P_EFUSE_RX_IMP:
+ mtk_phy_update_field(phyd + U3P_U3_PHYD_IMPCAL1, P3D_RG_RX_IMPEL, val);
+ mtk_phy_set_bits(phyd + U3P_U3_PHYD_IMPCAL1, P3D_RG_FORCE_RX_IMPEL);
+ break;
+
+ default:
+ break;
+ }
+
+ return count;
+}
+
+static const struct file_operations u3_phy_fops = {
+ .open = u3_phy_params_open,
+ .write = u3_phy_params_write,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void u3_phy_dbgfs_files_create(struct mtk_phy_instance *inst)
+{
+ u32 count = ARRAY_SIZE(u3_phy_files);
+ int i;
+
+ for (i = 0; i < count; i++)
+ debugfs_create_file(u3_phy_files[i], 0644, inst->phy->debugfs,
+ inst, &u3_phy_fops);
+}
+
+static int phy_type_show(struct seq_file *sf, void *unused)
+{
+ struct mtk_phy_instance *inst = sf->private;
+ const char *type;
+
+ switch (inst->type) {
+ case PHY_TYPE_USB2:
+ type = "USB2";
+ break;
+ case PHY_TYPE_USB3:
+ type = "USB3";
+ break;
+ case PHY_TYPE_PCIE:
+ type = "PCIe";
+ break;
+ case PHY_TYPE_SGMII:
+ type = "SGMII";
+ break;
+ case PHY_TYPE_SATA:
+ type = "SATA";
+ break;
+ default:
+ type = "";
+ }
+
+ seq_printf(sf, "%s\n", type);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(phy_type);
+
+/* these files will be removed when phy is released by phy core */
+static void phy_debugfs_init(struct mtk_phy_instance *inst)
+{
+ debugfs_create_file("type", 0444, inst->phy->debugfs, inst, &phy_type_fops);
+
+ switch (inst->type) {
+ case PHY_TYPE_USB2:
+ u2_phy_dbgfs_files_create(inst);
+ break;
+ case PHY_TYPE_USB3:
+ case PHY_TYPE_PCIE:
+ u3_phy_dbgfs_files_create(inst);
+ break;
+ default:
+ break;
+ }
+}
+
+#else
+
+static void phy_debugfs_init(struct mtk_phy_instance *inst)
+{}
+
+#endif
+
static void hs_slew_rate_calibrate(struct mtk_tphy *tphy,
struct mtk_phy_instance *instance)
{
@@ -1140,6 +1495,7 @@ static struct phy *mtk_phy_xlate(struct device *dev,
phy_parse_property(tphy, instance);
phy_type_set(instance);
+ phy_debugfs_init(instance);
return instance->phy;
}
diff --git a/drivers/phy/microchip/sparx5_serdes.c b/drivers/phy/microchip/sparx5_serdes.c
index ab1b0986aa67..01bd5ea620c5 100644
--- a/drivers/phy/microchip/sparx5_serdes.c
+++ b/drivers/phy/microchip/sparx5_serdes.c
@@ -25,12 +25,17 @@
#define SPX5_SERDES_10G_START 13
#define SPX5_SERDES_25G_START 25
+#define SPX5_SERDES_6G10G_CNT SPX5_SERDES_25G_START
+
+/* Optimal power settings from GUC */
+#define SPX5_SERDES_QUIET_MODE_VAL 0x01ef4e0c
enum sparx5_10g28cmu_mode {
SPX5_SD10G28_CMU_MAIN = 0,
SPX5_SD10G28_CMU_AUX1 = 1,
SPX5_SD10G28_CMU_AUX2 = 3,
SPX5_SD10G28_CMU_NONE = 4,
+ SPX5_SD10G28_CMU_MAX,
};
enum sparx5_sd25g28_mode_preset_type {
@@ -922,6 +927,222 @@ static void sparx5_sd10g28_get_params(struct sparx5_serdes_macro *macro,
*params = init;
}
+static int sparx5_cmu_apply_cfg(struct sparx5_serdes_private *priv,
+ u32 cmu_idx,
+ void __iomem *cmu_tgt,
+ void __iomem *cmu_cfg_tgt,
+ u32 spd10g)
+{
+ void __iomem **regs = priv->regs;
+ struct device *dev = priv->dev;
+ int value;
+
+ cmu_tgt = sdx5_inst_get(priv, TARGET_SD_CMU, cmu_idx);
+ cmu_cfg_tgt = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, cmu_idx);
+
+ if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 ||
+ cmu_idx == 10 || cmu_idx == 13) {
+ spd10g = 0;
+ }
+
+ sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(1),
+ SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST,
+ cmu_cfg_tgt,
+ SD_CMU_CFG_SD_CMU_CFG(cmu_idx));
+
+ sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(0),
+ SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST,
+ cmu_cfg_tgt,
+ SD_CMU_CFG_SD_CMU_CFG(cmu_idx));
+
+ sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(1),
+ SD_CMU_CFG_SD_CMU_CFG_CMU_RST,
+ cmu_cfg_tgt,
+ SD_CMU_CFG_SD_CMU_CFG(cmu_idx));
+
+ sdx5_inst_rmw(SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT_SET(0x1) |
+ SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT_SET(0x1) |
+ SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT_SET(0x1) |
+ SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT_SET(0x1) |
+ SD_CMU_CMU_45_R_EN_RATECHG_CTRL_SET(0x0),
+ SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT |
+ SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT |
+ SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT |
+ SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT |
+ SD_CMU_CMU_45_R_EN_RATECHG_CTRL,
+ cmu_tgt,
+ SD_CMU_CMU_45(cmu_idx));
+
+ sdx5_inst_rmw(SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0_SET(0),
+ SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0,
+ cmu_tgt,
+ SD_CMU_CMU_47(cmu_idx));
+
+ sdx5_inst_rmw(SD_CMU_CMU_1B_CFG_RESERVE_7_0_SET(0),
+ SD_CMU_CMU_1B_CFG_RESERVE_7_0,
+ cmu_tgt,
+ SD_CMU_CMU_1B(cmu_idx));
+
+ sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_JC_BYP_SET(0x1),
+ SD_CMU_CMU_0D_CFG_JC_BYP,
+ cmu_tgt,
+ SD_CMU_CMU_0D(cmu_idx));
+
+ sdx5_inst_rmw(SD_CMU_CMU_1F_CFG_VTUNE_SEL_SET(1),
+ SD_CMU_CMU_1F_CFG_VTUNE_SEL,
+ cmu_tgt,
+ SD_CMU_CMU_1F(cmu_idx));
+
+ sdx5_inst_rmw(SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0_SET(3),
+ SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0,
+ cmu_tgt,
+ SD_CMU_CMU_00(cmu_idx));
+
+ sdx5_inst_rmw(SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0_SET(3),
+ SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0,
+ cmu_tgt,
+ SD_CMU_CMU_05(cmu_idx));
+
+ sdx5_inst_rmw(SD_CMU_CMU_30_R_PLL_DLOL_EN_SET(1),
+ SD_CMU_CMU_30_R_PLL_DLOL_EN,
+ cmu_tgt,
+ SD_CMU_CMU_30(cmu_idx));
+
+ sdx5_inst_rmw(SD_CMU_CMU_09_CFG_SW_10G_SET(spd10g),
+ SD_CMU_CMU_09_CFG_SW_10G,
+ cmu_tgt,
+ SD_CMU_CMU_09(cmu_idx));
+
+ sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(0),
+ SD_CMU_CFG_SD_CMU_CFG_CMU_RST,
+ cmu_cfg_tgt,
+ SD_CMU_CFG_SD_CMU_CFG(cmu_idx));
+
+ msleep(20);
+
+ sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(0),
+ SD_CMU_CMU_44_R_PLL_RSTN,
+ cmu_tgt,
+ SD_CMU_CMU_44(cmu_idx));
+
+ sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(1),
+ SD_CMU_CMU_44_R_PLL_RSTN,
+ cmu_tgt,
+ SD_CMU_CMU_44(cmu_idx));
+
+ msleep(20);
+
+ value = readl(sdx5_addr(regs, SD_CMU_CMU_E0(cmu_idx)));
+ value = SD_CMU_CMU_E0_PLL_LOL_UDL_GET(value);
+
+ if (value) {
+ dev_err(dev, "CMU PLL Loss of Lock: 0x%x\n", value);
+ return -EINVAL;
+ }
+ sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD_SET(0),
+ SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD,
+ cmu_tgt,
+ SD_CMU_CMU_0D(cmu_idx));
+ return 0;
+}
+
+static int sparx5_cmu_cfg(struct sparx5_serdes_private *priv, u32 cmu_idx)
+{
+ void __iomem *cmu_tgt, *cmu_cfg_tgt;
+ u32 spd10g = 1;
+
+ if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 ||
+ cmu_idx == 10 || cmu_idx == 13) {
+ spd10g = 0;
+ }
+
+ cmu_tgt = sdx5_inst_get(priv, TARGET_SD_CMU, cmu_idx);
+ cmu_cfg_tgt = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, cmu_idx);
+
+ return sparx5_cmu_apply_cfg(priv, cmu_idx, cmu_tgt, cmu_cfg_tgt, spd10g);
+}
+
+/* Map of 6G/10G serdes mode and index to CMU index. */
+static const int
+sparx5_serdes_cmu_map[SPX5_SD10G28_CMU_MAX][SPX5_SERDES_6G10G_CNT] = {
+ [SPX5_SD10G28_CMU_MAIN] = { 2, 2, 2, 2, 2,
+ 2, 2, 2, 5, 5,
+ 5, 5, 5, 5, 5,
+ 5, 8, 11, 11, 11,
+ 11, 11, 11, 11, 11 },
+ [SPX5_SD10G28_CMU_AUX1] = { 0, 0, 3, 3, 3,
+ 3, 3, 3, 3, 3,
+ 6, 6, 6, 6, 6,
+ 6, 6, 9, 9, 12,
+ 12, 12, 12, 12, 12 },
+ [SPX5_SD10G28_CMU_AUX2] = { 1, 1, 1, 1, 4,
+ 4, 4, 4, 4, 4,
+ 4, 4, 7, 7, 7,
+ 7, 7, 10, 10, 10,
+ 10, 13, 13, 13, 13 },
+ [SPX5_SD10G28_CMU_NONE] = { 1, 1, 1, 1, 4,
+ 4, 4, 4, 4, 4,
+ 4, 4, 7, 7, 7,
+ 7, 7, 10, 10, 10,
+ 10, 13, 13, 13, 13 },
+};
+
+/* Get the index of the CMU which provides the clock for the specified serdes
+ * mode and index.
+ */
+static int sparx5_serdes_cmu_get(enum sparx5_10g28cmu_mode mode, int sd_index)
+{
+ return sparx5_serdes_cmu_map[mode][sd_index];
+}
+
+static void sparx5_serdes_cmu_power_off(struct sparx5_serdes_private *priv)
+{
+ void __iomem *cmu_inst, *cmu_cfg_inst;
+ int i;
+
+ /* Power down each CMU */
+ for (i = 0; i < SPX5_CMU_MAX; i++) {
+ cmu_inst = sdx5_inst_get(priv, TARGET_SD_CMU, i);
+ cmu_cfg_inst = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, i);
+
+ sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(0),
+ SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, cmu_cfg_inst,
+ SD_CMU_CFG_SD_CMU_CFG(0));
+
+ sdx5_inst_rmw(SD_CMU_CMU_05_CFG_REFCK_TERM_EN_SET(0),
+ SD_CMU_CMU_05_CFG_REFCK_TERM_EN, cmu_inst,
+ SD_CMU_CMU_05(0));
+
+ sdx5_inst_rmw(SD_CMU_CMU_09_CFG_EN_TX_CK_DN_SET(0),
+ SD_CMU_CMU_09_CFG_EN_TX_CK_DN, cmu_inst,
+ SD_CMU_CMU_09(0));
+
+ sdx5_inst_rmw(SD_CMU_CMU_06_CFG_VCO_PD_SET(1),
+ SD_CMU_CMU_06_CFG_VCO_PD, cmu_inst,
+ SD_CMU_CMU_06(0));
+
+ sdx5_inst_rmw(SD_CMU_CMU_09_CFG_EN_TX_CK_UP_SET(0),
+ SD_CMU_CMU_09_CFG_EN_TX_CK_UP, cmu_inst,
+ SD_CMU_CMU_09(0));
+
+ sdx5_inst_rmw(SD_CMU_CMU_08_CFG_CK_TREE_PD_SET(1),
+ SD_CMU_CMU_08_CFG_CK_TREE_PD, cmu_inst,
+ SD_CMU_CMU_08(0));
+
+ sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_REFCK_PD_SET(1) |
+ SD_CMU_CMU_0D_CFG_PD_DIV64_SET(1) |
+ SD_CMU_CMU_0D_CFG_PD_DIV66_SET(1),
+ SD_CMU_CMU_0D_CFG_REFCK_PD |
+ SD_CMU_CMU_0D_CFG_PD_DIV64 |
+ SD_CMU_CMU_0D_CFG_PD_DIV66, cmu_inst,
+ SD_CMU_CMU_0D(0));
+
+ sdx5_inst_rmw(SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD_SET(1),
+ SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD, cmu_inst,
+ SD_CMU_CMU_06(0));
+ }
+}
+
static void sparx5_sd25g28_reset(void __iomem *regs[],
struct sparx5_sd25g28_params *params,
u32 sd_index)
@@ -1422,7 +1643,17 @@ static int sparx5_sd10g28_apply_params(struct sparx5_serdes_macro *macro,
u32 lane_index = macro->sidx;
u32 sd_index = macro->stpidx;
void __iomem *sd_inst;
- u32 value;
+ u32 value, cmu_idx;
+ int err;
+
+ /* Do not configure serdes if CMU is not to be configured too */
+ if (params->skip_cmu_cfg)
+ return 0;
+
+ cmu_idx = sparx5_serdes_cmu_get(params->cmu_sel, lane_index);
+ err = sparx5_cmu_cfg(priv, cmu_idx);
+ if (err)
+ return err;
if (params->is_6g)
sd_inst = sdx5_inst_get(priv, TARGET_SD6G_LANE, sd_index);
@@ -1884,6 +2115,7 @@ static int sparx5_sd10g28_config(struct sparx5_serdes_macro *macro, bool reset)
.rxinvert = 1,
.txswing = 240,
.reg_rst = reset,
+ .skip_cmu_cfg = reset,
};
int err;
@@ -1899,7 +2131,7 @@ static int sparx5_sd10g28_config(struct sparx5_serdes_macro *macro, bool reset)
static int sparx5_serdes_power_save(struct sparx5_serdes_macro *macro, u32 pwdn)
{
struct sparx5_serdes_private *priv = macro->priv;
- void __iomem *sd_inst;
+ void __iomem *sd_inst, *sd_lane_inst;
if (macro->serdestype == SPX5_SDT_6G)
sd_inst = sdx5_inst_get(priv, TARGET_SD6G_LANE, macro->stpidx);
@@ -1909,12 +2141,36 @@ static int sparx5_serdes_power_save(struct sparx5_serdes_macro *macro, u32 pwdn)
sd_inst = sdx5_inst_get(priv, TARGET_SD25G_LANE, macro->stpidx);
if (macro->serdestype == SPX5_SDT_25G) {
+ sd_lane_inst = sdx5_inst_get(priv, TARGET_SD_LANE_25G,
+ macro->stpidx);
+ /* Take serdes out of reset */
+ sdx5_inst_rmw(SD_LANE_25G_SD_LANE_CFG_EXT_CFG_RST_SET(0),
+ SD_LANE_25G_SD_LANE_CFG_EXT_CFG_RST, sd_lane_inst,
+ SD_LANE_25G_SD_LANE_CFG(0));
+
+ /* Configure optimal settings for quiet mode */
+ sdx5_inst_rmw(SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE_SET(SPX5_SERDES_QUIET_MODE_VAL),
+ SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE,
+ sd_lane_inst, SD_LANE_25G_QUIET_MODE_6G(0));
+
sdx5_inst_rmw(SD25G_LANE_LANE_04_LN_CFG_PD_DRIVER_SET(pwdn),
SD25G_LANE_LANE_04_LN_CFG_PD_DRIVER,
sd_inst,
SD25G_LANE_LANE_04(0));
} else {
/* 6G and 10G */
+ sd_lane_inst = sdx5_inst_get(priv, TARGET_SD_LANE, macro->sidx);
+
+ /* Take serdes out of reset */
+ sdx5_inst_rmw(SD_LANE_SD_LANE_CFG_EXT_CFG_RST_SET(0),
+ SD_LANE_SD_LANE_CFG_EXT_CFG_RST, sd_lane_inst,
+ SD_LANE_SD_LANE_CFG(0));
+
+ /* Configure optimal settings for quiet mode */
+ sdx5_inst_rmw(SD_LANE_QUIET_MODE_6G_QUIET_MODE_SET(SPX5_SERDES_QUIET_MODE_VAL),
+ SD_LANE_QUIET_MODE_6G_QUIET_MODE, sd_lane_inst,
+ SD_LANE_QUIET_MODE_6G(0));
+
sdx5_inst_rmw(SD10G_LANE_LANE_06_CFG_PD_DRIVER_SET(pwdn),
SD10G_LANE_LANE_06_CFG_PD_DRIVER,
sd_inst,
@@ -1939,159 +2195,6 @@ static int sparx5_serdes_clock_config(struct sparx5_serdes_macro *macro)
return 0;
}
-static int sparx5_cmu_apply_cfg(struct sparx5_serdes_private *priv,
- u32 cmu_idx,
- void __iomem *cmu_tgt,
- void __iomem *cmu_cfg_tgt,
- u32 spd10g)
-{
- void __iomem **regs = priv->regs;
- struct device *dev = priv->dev;
- int value;
-
- cmu_tgt = sdx5_inst_get(priv, TARGET_SD_CMU, cmu_idx);
- cmu_cfg_tgt = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, cmu_idx);
-
- if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 ||
- cmu_idx == 10 || cmu_idx == 13) {
- spd10g = 0;
- }
-
- sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(1),
- SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST,
- cmu_cfg_tgt,
- SD_CMU_CFG_SD_CMU_CFG(cmu_idx));
-
- sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(0),
- SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST,
- cmu_cfg_tgt,
- SD_CMU_CFG_SD_CMU_CFG(cmu_idx));
-
- sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(1),
- SD_CMU_CFG_SD_CMU_CFG_CMU_RST,
- cmu_cfg_tgt,
- SD_CMU_CFG_SD_CMU_CFG(cmu_idx));
-
- sdx5_inst_rmw(SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT_SET(0x1) |
- SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT_SET(0x1) |
- SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT_SET(0x1) |
- SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT_SET(0x1) |
- SD_CMU_CMU_45_R_EN_RATECHG_CTRL_SET(0x0),
- SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT |
- SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT |
- SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT |
- SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT |
- SD_CMU_CMU_45_R_EN_RATECHG_CTRL,
- cmu_tgt,
- SD_CMU_CMU_45(cmu_idx));
-
- sdx5_inst_rmw(SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0_SET(0),
- SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0,
- cmu_tgt,
- SD_CMU_CMU_47(cmu_idx));
-
- sdx5_inst_rmw(SD_CMU_CMU_1B_CFG_RESERVE_7_0_SET(0),
- SD_CMU_CMU_1B_CFG_RESERVE_7_0,
- cmu_tgt,
- SD_CMU_CMU_1B(cmu_idx));
-
- sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_JC_BYP_SET(0x1),
- SD_CMU_CMU_0D_CFG_JC_BYP,
- cmu_tgt,
- SD_CMU_CMU_0D(cmu_idx));
-
- sdx5_inst_rmw(SD_CMU_CMU_1F_CFG_VTUNE_SEL_SET(1),
- SD_CMU_CMU_1F_CFG_VTUNE_SEL,
- cmu_tgt,
- SD_CMU_CMU_1F(cmu_idx));
-
- sdx5_inst_rmw(SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0_SET(3),
- SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0,
- cmu_tgt,
- SD_CMU_CMU_00(cmu_idx));
-
- sdx5_inst_rmw(SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0_SET(3),
- SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0,
- cmu_tgt,
- SD_CMU_CMU_05(cmu_idx));
-
- sdx5_inst_rmw(SD_CMU_CMU_30_R_PLL_DLOL_EN_SET(1),
- SD_CMU_CMU_30_R_PLL_DLOL_EN,
- cmu_tgt,
- SD_CMU_CMU_30(cmu_idx));
-
- sdx5_inst_rmw(SD_CMU_CMU_09_CFG_SW_10G_SET(spd10g),
- SD_CMU_CMU_09_CFG_SW_10G,
- cmu_tgt,
- SD_CMU_CMU_09(cmu_idx));
-
- sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(0),
- SD_CMU_CFG_SD_CMU_CFG_CMU_RST,
- cmu_cfg_tgt,
- SD_CMU_CFG_SD_CMU_CFG(cmu_idx));
-
- msleep(20);
-
- sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(0),
- SD_CMU_CMU_44_R_PLL_RSTN,
- cmu_tgt,
- SD_CMU_CMU_44(cmu_idx));
-
- sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(1),
- SD_CMU_CMU_44_R_PLL_RSTN,
- cmu_tgt,
- SD_CMU_CMU_44(cmu_idx));
-
- msleep(20);
-
- value = readl(sdx5_addr(regs, SD_CMU_CMU_E0(cmu_idx)));
- value = SD_CMU_CMU_E0_PLL_LOL_UDL_GET(value);
-
- if (value) {
- dev_err(dev, "CMU PLL Loss of Lock: 0x%x\n", value);
- return -EINVAL;
- }
- sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD_SET(0),
- SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD,
- cmu_tgt,
- SD_CMU_CMU_0D(cmu_idx));
- return 0;
-}
-
-static int sparx5_cmu_cfg(struct sparx5_serdes_private *priv, u32 cmu_idx)
-{
- void __iomem *cmu_tgt, *cmu_cfg_tgt;
- u32 spd10g = 1;
-
- if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 ||
- cmu_idx == 10 || cmu_idx == 13) {
- spd10g = 0;
- }
-
- cmu_tgt = sdx5_inst_get(priv, TARGET_SD_CMU, cmu_idx);
- cmu_cfg_tgt = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, cmu_idx);
-
- return sparx5_cmu_apply_cfg(priv, cmu_idx, cmu_tgt, cmu_cfg_tgt, spd10g);
-}
-
-static int sparx5_serdes_cmu_enable(struct sparx5_serdes_private *priv)
-{
- int idx, err = 0;
-
- if (!priv->cmu_enabled) {
- for (idx = 0; idx < SPX5_CMU_MAX; idx++) {
- err = sparx5_cmu_cfg(priv, idx);
- if (err) {
- dev_err(priv->dev, "CMU %u, error: %d\n", idx, err);
- goto leave;
- }
- }
- priv->cmu_enabled = true;
- }
-leave:
- return err;
-}
-
static int sparx5_serdes_get_serdesmode(phy_interface_t portmode, int speed)
{
switch (portmode) {
@@ -2120,10 +2223,6 @@ static int sparx5_serdes_config(struct sparx5_serdes_macro *macro)
int serdesmode;
int err;
- err = sparx5_serdes_cmu_enable(macro->priv);
- if (err)
- return err;
-
serdesmode = sparx5_serdes_get_serdesmode(macro->portmode, macro->speed);
if (serdesmode < 0) {
dev_err(dev, "SerDes %u, interface not supported: %s\n",
@@ -2215,9 +2314,6 @@ static int sparx5_serdes_reset(struct phy *phy)
struct sparx5_serdes_macro *macro = phy_get_drvdata(phy);
int err;
- err = sparx5_serdes_cmu_enable(macro->priv);
- if (err)
- return err;
if (macro->serdestype == SPX5_SDT_25G)
err = sparx5_sd25g28_config(macro, true);
else
@@ -2308,6 +2404,9 @@ static int sparx5_phy_create(struct sparx5_serdes_private *priv,
phy_set_drvdata(*phy, macro);
+ /* Power off serdes by default */
+ sparx5_serdes_power_off(*phy);
+
return 0;
}
@@ -2491,6 +2590,9 @@ static int sparx5_serdes_probe(struct platform_device *pdev)
return err;
}
+ /* Power down all CMUs by default */
+ sparx5_serdes_cmu_power_off(priv);
+
provider = devm_of_phy_provider_register(priv->dev, sparx5_serdes_xlate);
return PTR_ERR_OR_ZERO(provider);
diff --git a/drivers/phy/microchip/sparx5_serdes.h b/drivers/phy/microchip/sparx5_serdes.h
index 0a3e496e6210..13f94a29225a 100644
--- a/drivers/phy/microchip/sparx5_serdes.h
+++ b/drivers/phy/microchip/sparx5_serdes.h
@@ -30,7 +30,6 @@ struct sparx5_serdes_private {
struct device *dev;
void __iomem *regs[NUM_TARGETS];
struct phy *phys[SPX5_SERDES_MAX];
- bool cmu_enabled;
unsigned long coreclock;
};
diff --git a/drivers/phy/microchip/sparx5_serdes_regs.h b/drivers/phy/microchip/sparx5_serdes_regs.h
index b96386a4df5a..d0543fd3dc94 100644
--- a/drivers/phy/microchip/sparx5_serdes_regs.h
+++ b/drivers/phy/microchip/sparx5_serdes_regs.h
@@ -2149,6 +2149,92 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0_GET(x)\
FIELD_GET(SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0, x)
+/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_06 */
+#define SD_CMU_CMU_06(t) \
+ __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 4, 0, 1, 4)
+
+#define SD_CMU_CMU_06_CFG_DISLOS BIT(0)
+#define SD_CMU_CMU_06_CFG_DISLOS_SET(x)\
+ FIELD_PREP(SD_CMU_CMU_06_CFG_DISLOS, x)
+#define SD_CMU_CMU_06_CFG_DISLOS_GET(x)\
+ FIELD_GET(SD_CMU_CMU_06_CFG_DISLOS, x)
+
+#define SD_CMU_CMU_06_CFG_DISLOL BIT(1)
+#define SD_CMU_CMU_06_CFG_DISLOL_SET(x)\
+ FIELD_PREP(SD_CMU_CMU_06_CFG_DISLOL, x)
+#define SD_CMU_CMU_06_CFG_DISLOL_GET(x)\
+ FIELD_GET(SD_CMU_CMU_06_CFG_DISLOL, x)
+
+#define SD_CMU_CMU_06_CFG_DCLOL BIT(2)
+#define SD_CMU_CMU_06_CFG_DCLOL_SET(x)\
+ FIELD_PREP(SD_CMU_CMU_06_CFG_DCLOL, x)
+#define SD_CMU_CMU_06_CFG_DCLOL_GET(x)\
+ FIELD_GET(SD_CMU_CMU_06_CFG_DCLOL, x)
+
+#define SD_CMU_CMU_06_CFG_FORCE_RX_FILT BIT(3)
+#define SD_CMU_CMU_06_CFG_FORCE_RX_FILT_SET(x)\
+ FIELD_PREP(SD_CMU_CMU_06_CFG_FORCE_RX_FILT, x)
+#define SD_CMU_CMU_06_CFG_FORCE_RX_FILT_GET(x)\
+ FIELD_GET(SD_CMU_CMU_06_CFG_FORCE_RX_FILT, x)
+
+#define SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD BIT(4)
+#define SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD_SET(x)\
+ FIELD_PREP(SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD, x)
+#define SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD_GET(x)\
+ FIELD_GET(SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD, x)
+
+#define SD_CMU_CMU_06_CFG_VCO_PD BIT(5)
+#define SD_CMU_CMU_06_CFG_VCO_PD_SET(x)\
+ FIELD_PREP(SD_CMU_CMU_06_CFG_VCO_PD, x)
+#define SD_CMU_CMU_06_CFG_VCO_PD_GET(x)\
+ FIELD_GET(SD_CMU_CMU_06_CFG_VCO_PD, x)
+
+#define SD_CMU_CMU_06_CFG_VCO_CAL_RESETN BIT(6)
+#define SD_CMU_CMU_06_CFG_VCO_CAL_RESETN_SET(x)\
+ FIELD_PREP(SD_CMU_CMU_06_CFG_VCO_CAL_RESETN, x)
+#define SD_CMU_CMU_06_CFG_VCO_CAL_RESETN_GET(x)\
+ FIELD_GET(SD_CMU_CMU_06_CFG_VCO_CAL_RESETN, x)
+
+#define SD_CMU_CMU_06_CFG_VCO_CAL_BYP BIT(7)
+#define SD_CMU_CMU_06_CFG_VCO_CAL_BYP_SET(x)\
+ FIELD_PREP(SD_CMU_CMU_06_CFG_VCO_CAL_BYP, x)
+#define SD_CMU_CMU_06_CFG_VCO_CAL_BYP_GET(x)\
+ FIELD_GET(SD_CMU_CMU_06_CFG_VCO_CAL_BYP, x)
+
+/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_08 */
+#define SD_CMU_CMU_08(t) \
+ __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 12, 0, 1, 4)
+
+#define SD_CMU_CMU_08_CFG_VFILT2PAD BIT(0)
+#define SD_CMU_CMU_08_CFG_VFILT2PAD_SET(x)\
+ FIELD_PREP(SD_CMU_CMU_08_CFG_VFILT2PAD, x)
+#define SD_CMU_CMU_08_CFG_VFILT2PAD_GET(x)\
+ FIELD_GET(SD_CMU_CMU_08_CFG_VFILT2PAD, x)
+
+#define SD_CMU_CMU_08_CFG_EN_DUMMY BIT(1)
+#define SD_CMU_CMU_08_CFG_EN_DUMMY_SET(x)\
+ FIELD_PREP(SD_CMU_CMU_08_CFG_EN_DUMMY, x)
+#define SD_CMU_CMU_08_CFG_EN_DUMMY_GET(x)\
+ FIELD_GET(SD_CMU_CMU_08_CFG_EN_DUMMY, x)
+
+#define SD_CMU_CMU_08_CFG_CK_TREE_PD BIT(2)
+#define SD_CMU_CMU_08_CFG_CK_TREE_PD_SET(x)\
+ FIELD_PREP(SD_CMU_CMU_08_CFG_CK_TREE_PD, x)
+#define SD_CMU_CMU_08_CFG_CK_TREE_PD_GET(x)\
+ FIELD_GET(SD_CMU_CMU_08_CFG_CK_TREE_PD, x)
+
+#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN BIT(3)
+#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_SET(x)\
+ FIELD_PREP(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN, x)
+#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_GET(x)\
+ FIELD_GET(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN, x)
+
+#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN BIT(4)
+#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN_SET(x)\
+ FIELD_PREP(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN, x)
+#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN_GET(x)\
+ FIELD_GET(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN, x)
+
/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_09 */
#define SD_CMU_CMU_09(t) __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 16, 0, 1, 4)
@@ -2443,6 +2529,16 @@ enum sparx5_serdes_target {
#define SD_LANE_SD_LANE_STAT_DBG_OBS_GET(x)\
FIELD_GET(SD_LANE_SD_LANE_STAT_DBG_OBS, x)
+/* SD_LANE_TARGET:SD_PWR_CFG:QUIET_MODE_6G */
+#define SD_LANE_QUIET_MODE_6G(t) \
+ __REG(TARGET_SD_LANE, t, 25, 24, 0, 1, 8, 4, 0, 1, 4)
+
+#define SD_LANE_QUIET_MODE_6G_QUIET_MODE GENMASK(24, 0)
+#define SD_LANE_QUIET_MODE_6G_QUIET_MODE_SET(x)\
+ FIELD_PREP(SD_LANE_QUIET_MODE_6G_QUIET_MODE, x)
+#define SD_LANE_QUIET_MODE_6G_QUIET_MODE_GET(x)\
+ FIELD_GET(SD_LANE_QUIET_MODE_6G_QUIET_MODE, x)
+
/* SD_LANE_TARGET:CFG_STAT_FX100:MISC */
#define SD_LANE_MISC(t) __REG(TARGET_SD_LANE, t, 25, 56, 0, 1, 56, 0, 0, 1, 4)
@@ -2692,4 +2788,14 @@ enum sparx5_serdes_target {
#define SD_LANE_25G_SD_LANE_STAT_DBG_OBS_GET(x)\
FIELD_GET(SD_LANE_25G_SD_LANE_STAT_DBG_OBS, x)
+/* SD25G_CFG_TARGET:SD_PWR_CFG:QUIET_MODE_6G */
+#define SD_LANE_25G_QUIET_MODE_6G(t) \
+ __REG(TARGET_SD_LANE_25G, t, 8, 28, 0, 1, 8, 4, 0, 1, 4)
+
+#define SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE GENMASK(24, 0)
+#define SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE_SET(x)\
+ FIELD_PREP(SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE, x)
+#define SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE_GET(x)\
+ FIELD_GET(SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE, x)
+
#endif /* _SPARX5_SERDES_REGS_H_ */
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 6464dcb56d56..96a0b1e111f3 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -11,6 +11,7 @@
#include <linux/export.h>
#include <linux/module.h>
#include <linux/err.h>
+#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/of.h>
@@ -20,6 +21,7 @@
#include <linux/regulator/consumer.h>
static struct class *phy_class;
+static struct dentry *phy_debugfs_root;
static DEFINE_MUTEX(phy_provider_mutex);
static LIST_HEAD(phy_provider_list);
static LIST_HEAD(phys);
@@ -996,6 +998,8 @@ struct phy *phy_create(struct device *dev, struct device_node *node,
pm_runtime_no_callbacks(&phy->dev);
}
+ phy->debugfs = debugfs_create_dir(dev_name(&phy->dev), phy_debugfs_root);
+
return phy;
put_dev:
@@ -1226,6 +1230,7 @@ static void phy_release(struct device *dev)
phy = to_phy(dev);
dev_vdbg(dev, "releasing '%s'\n", dev_name(dev));
+ debugfs_remove_recursive(phy->debugfs);
regulator_put(phy->pwr);
ida_simple_remove(&phy_ida, phy->id);
kfree(phy);
@@ -1242,6 +1247,15 @@ static int __init phy_core_init(void)
phy_class->dev_release = phy_release;
+ phy_debugfs_root = debugfs_create_dir("phy", NULL);
+
return 0;
}
device_initcall(phy_core_init);
+
+static void __exit phy_core_exit(void)
+{
+ debugfs_remove_recursive(phy_debugfs_root);
+ class_destroy(phy_class);
+}
+module_exit(phy_core_exit);
diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
index 4850d48f31fa..97ca5952e34e 100644
--- a/drivers/phy/qualcomm/Kconfig
+++ b/drivers/phy/qualcomm/Kconfig
@@ -59,8 +59,11 @@ if PHY_QCOM_QMP
config PHY_QCOM_QMP_COMBO
tristate "Qualcomm QMP Combo PHY Driver"
default PHY_QCOM_QMP
+ depends on TYPEC || TYPEC=n
+ depends on DRM || DRM=n
select GENERIC_PHY
select MFD_SYSCON
+ select DRM_PANEL_BRIDGE if DRM
help
Enable this to support the QMP Combo PHY transceiver that is used
with USB3 and DisplayPort controllers on Qualcomm chips.
@@ -185,3 +188,12 @@ config PHY_QCOM_IPQ806X_USB
This option enables support for the Synopsis PHYs present inside the
Qualcomm USB3.0 DWC3 controller on ipq806x SoC. This driver supports
both HS and SS PHY controllers.
+
+config PHY_QCOM_SGMII_ETH
+ tristate "Qualcomm DWMAC SGMII SerDes/PHY driver"
+ depends on OF && (ARCH_QCOM || COMPILE_TEST)
+ depends on HAS_IOMEM
+ select GENERIC_PHY
+ help
+ Enable this to support the internal SerDes/SGMII PHY on various
+ Qualcomm chipsets.
diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile
index de3dc9ccf067..b030858e0f8d 100644
--- a/drivers/phy/qualcomm/Makefile
+++ b/drivers/phy/qualcomm/Makefile
@@ -20,4 +20,5 @@ obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o
obj-$(CONFIG_PHY_QCOM_USB_HS_28NM) += phy-qcom-usb-hs-28nm.o
obj-$(CONFIG_PHY_QCOM_USB_SS) += phy-qcom-usb-ss.o
obj-$(CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2)+= phy-qcom-snps-femto-v2.o
-obj-$(CONFIG_PHY_QCOM_IPQ806X_USB) += phy-qcom-ipq806x-usb.o
+obj-$(CONFIG_PHY_QCOM_IPQ806X_USB) += phy-qcom-ipq806x-usb.o
+obj-$(CONFIG_PHY_QCOM_SGMII_ETH) += phy-qcom-sgmii-eth.o
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
index 87b17e5877ab..bebce8c591a3 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
@@ -19,6 +19,10 @@
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
#include <linux/slab.h>
+#include <linux/usb/typec.h>
+#include <linux/usb/typec_mux.h>
+
+#include <drm/drm_bridge.h>
#include <dt-bindings/phy/phy-qcom-qmp.h>
@@ -63,6 +67,10 @@
/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
#define CLAMP_EN BIT(0) /* enables i/o clamp_n */
+/* QPHY_V3_DP_COM_TYPEC_CTRL register bits */
+#define SW_PORTSELECT_VAL BIT(0)
+#define SW_PORTSELECT_MUX BIT(1)
+
#define PHY_INIT_COMPLETE_TIMEOUT 10000
struct qmp_phy_init_tbl {
@@ -1315,14 +1323,21 @@ struct qmp_combo {
struct phy *usb_phy;
enum phy_mode mode;
+ unsigned int usb_init_count;
struct phy *dp_phy;
unsigned int dp_aux_cfg;
struct phy_configure_opts_dp dp_opts;
+ unsigned int dp_init_count;
struct clk_fixed_rate pipe_clk_fixed;
struct clk_hw dp_link_hw;
struct clk_hw dp_pixel_hw;
+
+ struct drm_bridge bridge;
+
+ struct typec_switch_dev *sw;
+ enum typec_orientation orientation;
};
static void qmp_v3_dp_aux_init(struct qmp_combo *qmp);
@@ -1954,30 +1969,24 @@ static void qmp_v3_configure_dp_tx(struct qmp_combo *qmp)
static bool qmp_combo_configure_dp_mode(struct qmp_combo *qmp)
{
+ bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE);
+ const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
u32 val;
- bool reverse = false;
val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN;
- /*
- * TODO: Assume orientation is CC1 for now and two lanes, need to
- * use type-c connector to understand orientation and lanes.
- *
- * Otherwise val changes to be like below if this code understood
- * the orientation of the type-c cable.
- *
- * if (lane_cnt == 4 || orientation == ORIENTATION_CC2)
- * val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN;
- * if (lane_cnt == 4 || orientation == ORIENTATION_CC1)
- * val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
- * if (orientation == ORIENTATION_CC2)
- * writel(0x4c, qmp->dp_dp_phy + QSERDES_V3_DP_PHY_MODE);
- */
- val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
+ if (dp_opts->lanes == 4 || reverse)
+ val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN;
+ if (dp_opts->lanes == 4 || !reverse)
+ val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
+
writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL);
- writel(0x5c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE);
+ if (reverse)
+ writel(0x4c, qmp->pcs + QSERDES_DP_PHY_MODE);
+ else
+ writel(0x5c, qmp->pcs + QSERDES_DP_PHY_MODE);
return reverse;
}
@@ -2142,6 +2151,7 @@ static void qmp_v4_configure_dp_tx(struct qmp_combo *qmp)
static int qmp_v456_configure_dp_phy(struct qmp_combo *qmp,
unsigned int com_resetm_ctrl_reg,
unsigned int com_c_ready_status_reg,
+ unsigned int com_cmn_status_reg,
unsigned int dp_phy_status_reg)
{
const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
@@ -2198,14 +2208,14 @@ static int qmp_v456_configure_dp_phy(struct qmp_combo *qmp,
10000))
return -ETIMEDOUT;
- if (readl_poll_timeout(qmp->dp_serdes + QSERDES_V4_COM_CMN_STATUS,
+ if (readl_poll_timeout(qmp->dp_serdes + com_cmn_status_reg,
status,
((status & BIT(0)) > 0),
500,
10000))
return -ETIMEDOUT;
- if (readl_poll_timeout(qmp->dp_serdes + QSERDES_V4_COM_CMN_STATUS,
+ if (readl_poll_timeout(qmp->dp_serdes + com_cmn_status_reg,
status,
((status & BIT(1)) > 0),
500,
@@ -2233,14 +2243,15 @@ static int qmp_v456_configure_dp_phy(struct qmp_combo *qmp,
static int qmp_v4_configure_dp_phy(struct qmp_combo *qmp)
{
+ bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE);
const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
- bool reverse = false;
u32 status;
int ret;
ret = qmp_v456_configure_dp_phy(qmp, QSERDES_V4_COM_RESETSM_CNTRL,
QSERDES_V4_COM_C_READY_STATUS,
+ QSERDES_V4_COM_CMN_STATUS,
QSERDES_V4_DP_PHY_STATUS);
if (ret < 0)
return ret;
@@ -2297,14 +2308,15 @@ static int qmp_v4_configure_dp_phy(struct qmp_combo *qmp)
static int qmp_v5_configure_dp_phy(struct qmp_combo *qmp)
{
+ bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE);
const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
- bool reverse = false;
u32 status;
int ret;
ret = qmp_v456_configure_dp_phy(qmp, QSERDES_V4_COM_RESETSM_CNTRL,
QSERDES_V4_COM_C_READY_STATUS,
+ QSERDES_V4_COM_CMN_STATUS,
QSERDES_V4_DP_PHY_STATUS);
if (ret < 0)
return ret;
@@ -2356,14 +2368,15 @@ static int qmp_v5_configure_dp_phy(struct qmp_combo *qmp)
static int qmp_v6_configure_dp_phy(struct qmp_combo *qmp)
{
+ bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE);
const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
- bool reverse = false;
u32 status;
int ret;
ret = qmp_v456_configure_dp_phy(qmp, QSERDES_V6_COM_RESETSM_CNTRL,
QSERDES_V6_COM_C_READY_STATUS,
+ QSERDES_V6_COM_CMN_STATUS,
QSERDES_V6_DP_PHY_STATUS);
if (ret < 0)
return ret;
@@ -2437,12 +2450,16 @@ static int qmp_combo_dp_configure(struct phy *phy, union phy_configure_opts *opt
struct qmp_combo *qmp = phy_get_drvdata(phy);
const struct qmp_phy_cfg *cfg = qmp->cfg;
+ mutex_lock(&qmp->phy_mutex);
+
memcpy(&qmp->dp_opts, dp_opts, sizeof(*dp_opts));
if (qmp->dp_opts.set_voltages) {
cfg->configure_dp_tx(qmp);
qmp->dp_opts.set_voltages = 0;
}
+ mutex_unlock(&qmp->phy_mutex);
+
return 0;
}
@@ -2450,24 +2467,27 @@ static int qmp_combo_dp_calibrate(struct phy *phy)
{
struct qmp_combo *qmp = phy_get_drvdata(phy);
const struct qmp_phy_cfg *cfg = qmp->cfg;
+ int ret = 0;
+
+ mutex_lock(&qmp->phy_mutex);
if (cfg->calibrate_dp_phy)
- return cfg->calibrate_dp_phy(qmp);
+ ret = cfg->calibrate_dp_phy(qmp);
- return 0;
+ mutex_unlock(&qmp->phy_mutex);
+
+ return ret;
}
-static int qmp_combo_com_init(struct qmp_combo *qmp)
+static int qmp_combo_com_init(struct qmp_combo *qmp, bool force)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
void __iomem *com = qmp->com;
int ret;
+ u32 val;
- mutex_lock(&qmp->phy_mutex);
- if (qmp->init_count++) {
- mutex_unlock(&qmp->phy_mutex);
+ if (!force && qmp->init_count++)
return 0;
- }
ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
if (ret) {
@@ -2498,10 +2518,12 @@ static int qmp_combo_com_init(struct qmp_combo *qmp)
SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
- /* Default type-c orientation, i.e CC1 */
- qphy_setbits(com, QPHY_V3_DP_COM_TYPEC_CTRL, 0x02);
-
- qphy_setbits(com, QPHY_V3_DP_COM_PHY_MODE_CTRL, USB3_MODE | DP_MODE);
+ /* Use software based port select and switch on typec orientation */
+ val = SW_PORTSELECT_MUX;
+ if (qmp->orientation == TYPEC_ORIENTATION_REVERSE)
+ val |= SW_PORTSELECT_VAL;
+ writel(val, com + QPHY_V3_DP_COM_TYPEC_CTRL);
+ writel(USB3_MODE | DP_MODE, com + QPHY_V3_DP_COM_PHY_MODE_CTRL);
/* bring both QMP USB and QMP DP PHYs PCS block out of reset */
qphy_clrbits(com, QPHY_V3_DP_COM_RESET_OVRD_CTRL,
@@ -2514,8 +2536,6 @@ static int qmp_combo_com_init(struct qmp_combo *qmp)
qphy_setbits(qmp->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL],
SW_PWRDN);
- mutex_unlock(&qmp->phy_mutex);
-
return 0;
err_assert_reset:
@@ -2524,20 +2544,16 @@ err_disable_regulators:
regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
err_decrement_count:
qmp->init_count--;
- mutex_unlock(&qmp->phy_mutex);
return ret;
}
-static int qmp_combo_com_exit(struct qmp_combo *qmp)
+static int qmp_combo_com_exit(struct qmp_combo *qmp, bool force)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
- mutex_lock(&qmp->phy_mutex);
- if (--qmp->init_count) {
- mutex_unlock(&qmp->phy_mutex);
+ if (!force && --qmp->init_count)
return 0;
- }
reset_control_bulk_assert(cfg->num_resets, qmp->resets);
@@ -2545,8 +2561,6 @@ static int qmp_combo_com_exit(struct qmp_combo *qmp)
regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
- mutex_unlock(&qmp->phy_mutex);
-
return 0;
}
@@ -2556,20 +2570,32 @@ static int qmp_combo_dp_init(struct phy *phy)
const struct qmp_phy_cfg *cfg = qmp->cfg;
int ret;
- ret = qmp_combo_com_init(qmp);
+ mutex_lock(&qmp->phy_mutex);
+
+ ret = qmp_combo_com_init(qmp, false);
if (ret)
- return ret;
+ goto out_unlock;
cfg->dp_aux_init(qmp);
- return 0;
+ qmp->dp_init_count++;
+
+out_unlock:
+ mutex_unlock(&qmp->phy_mutex);
+ return ret;
}
static int qmp_combo_dp_exit(struct phy *phy)
{
struct qmp_combo *qmp = phy_get_drvdata(phy);
- qmp_combo_com_exit(qmp);
+ mutex_lock(&qmp->phy_mutex);
+
+ qmp_combo_com_exit(qmp, false);
+
+ qmp->dp_init_count--;
+
+ mutex_unlock(&qmp->phy_mutex);
return 0;
}
@@ -2581,6 +2607,8 @@ static int qmp_combo_dp_power_on(struct phy *phy)
void __iomem *tx = qmp->dp_tx;
void __iomem *tx2 = qmp->dp_tx2;
+ mutex_lock(&qmp->phy_mutex);
+
qmp_combo_dp_serdes_init(qmp);
qmp_combo_configure_lane(tx, cfg->dp_tx_tbl, cfg->dp_tx_tbl_num, 1);
@@ -2592,6 +2620,8 @@ static int qmp_combo_dp_power_on(struct phy *phy)
/* Configure link rate, swing, etc. */
cfg->configure_dp_phy(qmp);
+ mutex_unlock(&qmp->phy_mutex);
+
return 0;
}
@@ -2599,9 +2629,13 @@ static int qmp_combo_dp_power_off(struct phy *phy)
{
struct qmp_combo *qmp = phy_get_drvdata(phy);
+ mutex_lock(&qmp->phy_mutex);
+
/* Assert DP PHY power down */
writel(DP_PHY_PD_CTL_PSR_PWRDN, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL);
+ mutex_unlock(&qmp->phy_mutex);
+
return 0;
}
@@ -2687,14 +2721,21 @@ static int qmp_combo_usb_init(struct phy *phy)
struct qmp_combo *qmp = phy_get_drvdata(phy);
int ret;
- ret = qmp_combo_com_init(qmp);
+ mutex_lock(&qmp->phy_mutex);
+ ret = qmp_combo_com_init(qmp, false);
if (ret)
- return ret;
+ goto out_unlock;
ret = qmp_combo_usb_power_on(phy);
- if (ret)
- qmp_combo_com_exit(qmp);
+ if (ret) {
+ qmp_combo_com_exit(qmp, false);
+ goto out_unlock;
+ }
+
+ qmp->usb_init_count++;
+out_unlock:
+ mutex_unlock(&qmp->phy_mutex);
return ret;
}
@@ -2703,11 +2744,20 @@ static int qmp_combo_usb_exit(struct phy *phy)
struct qmp_combo *qmp = phy_get_drvdata(phy);
int ret;
+ mutex_lock(&qmp->phy_mutex);
ret = qmp_combo_usb_power_off(phy);
if (ret)
- return ret;
+ goto out_unlock;
+
+ ret = qmp_combo_com_exit(qmp, false);
+ if (ret)
+ goto out_unlock;
+
+ qmp->usb_init_count--;
- return qmp_combo_com_exit(qmp);
+out_unlock:
+ mutex_unlock(&qmp->phy_mutex);
+ return ret;
}
static int qmp_combo_usb_set_mode(struct phy *phy, enum phy_mode mode, int submode)
@@ -3173,6 +3223,103 @@ static int qmp_combo_register_clocks(struct qmp_combo *qmp, struct device_node *
return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, dp_np);
}
+#if IS_ENABLED(CONFIG_TYPEC)
+static int qmp_combo_typec_switch_set(struct typec_switch_dev *sw,
+ enum typec_orientation orientation)
+{
+ struct qmp_combo *qmp = typec_switch_get_drvdata(sw);
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+
+ if (orientation == qmp->orientation || orientation == TYPEC_ORIENTATION_NONE)
+ return 0;
+
+ mutex_lock(&qmp->phy_mutex);
+ qmp->orientation = orientation;
+
+ if (qmp->init_count) {
+ if (qmp->usb_init_count)
+ qmp_combo_usb_power_off(qmp->usb_phy);
+ qmp_combo_com_exit(qmp, true);
+
+ qmp_combo_com_init(qmp, true);
+ if (qmp->usb_init_count)
+ qmp_combo_usb_power_on(qmp->usb_phy);
+ if (qmp->dp_init_count)
+ cfg->dp_aux_init(qmp);
+ }
+ mutex_unlock(&qmp->phy_mutex);
+
+ return 0;
+}
+
+static void qmp_combo_typec_unregister(void *data)
+{
+ struct qmp_combo *qmp = data;
+
+ typec_switch_unregister(qmp->sw);
+}
+
+static int qmp_combo_typec_switch_register(struct qmp_combo *qmp)
+{
+ struct typec_switch_desc sw_desc = {};
+ struct device *dev = qmp->dev;
+
+ sw_desc.drvdata = qmp;
+ sw_desc.fwnode = dev->fwnode;
+ sw_desc.set = qmp_combo_typec_switch_set;
+ qmp->sw = typec_switch_register(dev, &sw_desc);
+ if (IS_ERR(qmp->sw)) {
+ dev_err(dev, "Unable to register typec switch: %pe\n", qmp->sw);
+ return PTR_ERR(qmp->sw);
+ }
+
+ return devm_add_action_or_reset(dev, qmp_combo_typec_unregister, qmp);
+}
+#else
+static int qmp_combo_typec_switch_register(struct qmp_combo *qmp)
+{
+ return 0;
+}
+#endif
+
+#if IS_ENABLED(CONFIG_DRM)
+static int qmp_combo_bridge_attach(struct drm_bridge *bridge,
+ enum drm_bridge_attach_flags flags)
+{
+ struct qmp_combo *qmp = container_of(bridge, struct qmp_combo, bridge);
+ struct drm_bridge *next_bridge;
+
+ if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
+ return -EINVAL;
+
+ next_bridge = devm_drm_of_get_bridge(qmp->dev, qmp->dev->of_node, 0, 0);
+ if (IS_ERR(next_bridge)) {
+ dev_err(qmp->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 qmp_combo_bridge_funcs = {
+ .attach = qmp_combo_bridge_attach,
+};
+
+static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp)
+{
+ qmp->bridge.funcs = &qmp_combo_bridge_funcs;
+ qmp->bridge.of_node = qmp->dev->of_node;
+
+ return devm_drm_bridge_add(qmp->dev, &qmp->bridge);
+}
+#else
+static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp)
+{
+ return 0;
+}
+#endif
+
static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, struct device_node *np)
{
struct device *dev = qmp->dev;
@@ -3353,6 +3500,8 @@ static int qmp_combo_probe(struct platform_device *pdev)
qmp->dev = dev;
+ qmp->orientation = TYPEC_ORIENTATION_NORMAL;
+
qmp->cfg = of_device_get_match_data(dev);
if (!qmp->cfg)
return -EINVAL;
@@ -3371,6 +3520,14 @@ static int qmp_combo_probe(struct platform_device *pdev)
if (ret)
return ret;
+ ret = qmp_combo_typec_switch_register(qmp);
+ if (ret)
+ return ret;
+
+ ret = qmp_combo_dp_register_bridge(qmp);
+ if (ret)
+ return ret;
+
/* Check for legacy binding with child nodes. */
usb_np = of_get_child_by_name(dev->of_node, "usb3-phy");
if (usb_np) {
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
index a49711c5a63d..466f0a56c82e 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
@@ -139,6 +139,88 @@ static const unsigned int qmp_v5_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V5_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR,
};
+static const struct qmp_phy_init_tbl ipq9574_usb3_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x1a),
+ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30),
+ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06),
+ /* PLL and Loop filter settings */
+ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x68),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
+ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0xa0),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x29),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a),
+ /* SSC settings */
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x7d),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x05),
+};
+
+static const struct qmp_phy_init_tbl ipq9574_usb3_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45),
+ QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06),
+};
+
+static const struct qmp_phy_init_tbl ipq9574_usb3_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x6c),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xb8),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x0c),
+};
+
+static const struct qmp_phy_init_tbl ipq9574_usb3_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0e),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f),
+};
+
static const struct qmp_phy_init_tbl ipq8074_usb3_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
@@ -1408,12 +1490,36 @@ static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x21),
};
+static const struct qmp_phy_init_tbl sa8775p_usb3_uniphy_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG1, 0xc4),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG2, 0x89),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG3, 0x20),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG6, 0x13),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0xaa),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCS_TX_RX_CONFIG, 0x0c),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_POWER_STATE_CONFIG1, 0x6f),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_CDR_RESET_TIME, 0x0a),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG1, 0x88),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG2, 0x13),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG1, 0x4b),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG5, 0x10),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x21),
+};
+
struct qmp_usb_offsets {
u16 serdes;
u16 pcs;
+ u16 pcs_misc;
u16 pcs_usb;
u16 tx;
u16 rx;
+ /* for PHYs with >= 2 lanes */
+ u16 tx2;
+ u16 rx2;
};
/* struct qmp_phy_cfg - per-PHY initialization config */
@@ -1558,6 +1664,24 @@ static const char * const qmp_phy_vreg_l[] = {
"vdda-phy", "vdda-pll",
};
+static const struct qmp_usb_offsets qmp_usb_offsets_ipq9574 = {
+ .serdes = 0,
+ .pcs = 0x800,
+ .pcs_usb = 0x800,
+ .tx = 0x200,
+ .rx = 0x400,
+};
+
+static const struct qmp_usb_offsets qmp_usb_offsets_v3 = {
+ .serdes = 0,
+ .pcs = 0xc00,
+ .pcs_misc = 0xa00,
+ .tx = 0x200,
+ .rx = 0x400,
+ .tx2 = 0x600,
+ .rx2 = 0x800,
+};
+
static const struct qmp_usb_offsets qmp_usb_offsets_v5 = {
.serdes = 0,
.pcs = 0x0200,
@@ -1586,6 +1710,28 @@ static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = {
.regs = qmp_v3_usb3phy_regs_layout,
};
+static const struct qmp_phy_cfg ipq9574_usb3phy_cfg = {
+ .lanes = 1,
+
+ .offsets = &qmp_usb_offsets_ipq9574,
+
+ .serdes_tbl = ipq9574_usb3_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(ipq9574_usb3_serdes_tbl),
+ .tx_tbl = ipq9574_usb3_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(ipq9574_usb3_tx_tbl),
+ .rx_tbl = ipq9574_usb3_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(ipq9574_usb3_rx_tbl),
+ .pcs_tbl = ipq9574_usb3_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(ipq9574_usb3_pcs_tbl),
+ .clk_list = msm8996_phy_clk_l,
+ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l),
+ .reset_list = qcm2290_usb3phy_reset_l,
+ .num_resets = ARRAY_SIZE(qcm2290_usb3phy_reset_l),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = qmp_v3_usb3phy_regs_layout,
+};
+
static const struct qmp_phy_cfg msm8996_usb3phy_cfg = {
.lanes = 1,
@@ -1629,6 +1775,28 @@ static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = {
.has_phy_dp_com_ctrl = true,
};
+static const struct qmp_phy_cfg sa8775p_usb3_uniphy_cfg = {
+ .lanes = 1,
+
+ .offsets = &qmp_usb_offsets_v5,
+
+ .serdes_tbl = sc8280xp_usb3_uniphy_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_serdes_tbl),
+ .tx_tbl = sc8280xp_usb3_uniphy_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_tx_tbl),
+ .rx_tbl = sc8280xp_usb3_uniphy_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_rx_tbl),
+ .pcs_tbl = sa8775p_usb3_uniphy_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(sa8775p_usb3_uniphy_pcs_tbl),
+ .clk_list = qmp_v4_phy_clk_l,
+ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l),
+ .reset_list = qcm2290_usb3phy_reset_l,
+ .num_resets = ARRAY_SIZE(qcm2290_usb3phy_reset_l),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = qmp_v5_usb3phy_regs_layout,
+};
+
static const struct qmp_phy_cfg sc7180_usb3phy_cfg = {
.lanes = 2,
@@ -1922,6 +2090,8 @@ static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = {
static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = {
.lanes = 2,
+ .offsets = &qmp_usb_offsets_v3,
+
.serdes_tbl = qcm2290_usb3_serdes_tbl,
.serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl),
.tx_tbl = qcm2290_usb3_tx_tbl,
@@ -2493,10 +2663,16 @@ static int qmp_usb_parse_dt(struct qmp_usb *qmp)
qmp->serdes = base + offs->serdes;
qmp->pcs = base + offs->pcs;
+ qmp->pcs_misc = base + offs->pcs_misc;
qmp->pcs_usb = base + offs->pcs_usb;
qmp->tx = base + offs->tx;
qmp->rx = base + offs->rx;
+ if (cfg->lanes >= 2) {
+ qmp->tx2 = base + offs->tx2;
+ qmp->rx2 = base + offs->rx2;
+ }
+
qmp->pipe_clk = devm_clk_get(dev, "pipe");
if (IS_ERR(qmp->pipe_clk)) {
return dev_err_probe(dev, PTR_ERR(qmp->pipe_clk),
@@ -2589,6 +2765,9 @@ static const struct of_device_id qmp_usb_of_match_table[] = {
.compatible = "qcom,ipq8074-qmp-usb3-phy",
.data = &ipq8074_usb3phy_cfg,
}, {
+ .compatible = "qcom,ipq9574-qmp-usb3-phy",
+ .data = &ipq9574_usb3phy_cfg,
+ }, {
.compatible = "qcom,msm8996-qmp-usb3-phy",
.data = &msm8996_usb3phy_cfg,
}, {
@@ -2598,6 +2777,9 @@ static const struct of_device_id qmp_usb_of_match_table[] = {
.compatible = "qcom,qcm2290-qmp-usb3-phy",
.data = &qcm2290_usb3phy_cfg,
}, {
+ .compatible = "qcom,sa8775p-qmp-usb3-uni-phy",
+ .data = &sa8775p_usb3_uniphy_cfg,
+ }, {
.compatible = "qcom,sc7180-qmp-usb3-phy",
.data = &sc7180_usb3phy_cfg,
}, {
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index 2ef638b32e8f..bec6e40d5280 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -912,6 +912,9 @@ static const struct of_device_id qusb2_phy_of_match_table[] = {
.compatible = "qcom,ipq8074-qusb2-phy",
.data = &msm8996_phy_cfg,
}, {
+ .compatible = "qcom,ipq9574-qusb2-phy",
+ .data = &ipq6018_phy_cfg,
+ }, {
.compatible = "qcom,msm8953-qusb2-phy",
.data = &msm8996_phy_cfg,
}, {
diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
new file mode 100644
index 000000000000..03dc753f0de1
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
@@ -0,0 +1,451 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#include <linux/clk.h>
+#include <linux/ethtool.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define QSERDES_QMP_PLL 0x0
+#define QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0 (QSERDES_QMP_PLL + 0x1ac)
+#define QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0 (QSERDES_QMP_PLL + 0x1b0)
+#define QSERDES_COM_BIN_VCOCAL_HSCLK_SEL (QSERDES_QMP_PLL + 0x1bc)
+#define QSERDES_COM_CORE_CLK_EN (QSERDES_QMP_PLL + 0x174)
+#define QSERDES_COM_CORECLK_DIV_MODE0 (QSERDES_QMP_PLL + 0x168)
+#define QSERDES_COM_CP_CTRL_MODE0 (QSERDES_QMP_PLL + 0x74)
+#define QSERDES_COM_DEC_START_MODE0 (QSERDES_QMP_PLL + 0xbc)
+#define QSERDES_COM_DIV_FRAC_START1_MODE0 (QSERDES_QMP_PLL + 0xcc)
+#define QSERDES_COM_DIV_FRAC_START2_MODE0 (QSERDES_QMP_PLL + 0xd0)
+#define QSERDES_COM_DIV_FRAC_START3_MODE0 (QSERDES_QMP_PLL + 0xd4)
+#define QSERDES_COM_HSCLK_HS_SWITCH_SEL (QSERDES_QMP_PLL + 0x15c)
+#define QSERDES_COM_HSCLK_SEL (QSERDES_QMP_PLL + 0x158)
+#define QSERDES_COM_LOCK_CMP1_MODE0 (QSERDES_QMP_PLL + 0xac)
+#define QSERDES_COM_LOCK_CMP2_MODE0 (QSERDES_QMP_PLL + 0xb0)
+#define QSERDES_COM_PLL_CCTRL_MODE0 (QSERDES_QMP_PLL + 0x84)
+#define QSERDES_COM_PLL_IVCO (QSERDES_QMP_PLL + 0x58)
+#define QSERDES_COM_PLL_RCTRL_MODE0 (QSERDES_QMP_PLL + 0x7c)
+#define QSERDES_COM_SYSCLK_EN_SEL (QSERDES_QMP_PLL + 0x94)
+#define QSERDES_COM_VCO_TUNE1_MODE0 (QSERDES_QMP_PLL + 0x110)
+#define QSERDES_COM_VCO_TUNE2_MODE0 (QSERDES_QMP_PLL + 0x114)
+#define QSERDES_COM_VCO_TUNE_INITVAL2 (QSERDES_QMP_PLL + 0x124)
+#define QSERDES_COM_C_READY_STATUS (QSERDES_QMP_PLL + 0x178)
+#define QSERDES_COM_CMN_STATUS (QSERDES_QMP_PLL + 0x140)
+
+#define QSERDES_RX 0x600
+#define QSERDES_RX_UCDR_FO_GAIN (QSERDES_RX + 0x8)
+#define QSERDES_RX_UCDR_SO_GAIN (QSERDES_RX + 0x14)
+#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN (QSERDES_RX + 0x30)
+#define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE (QSERDES_RX + 0x34)
+#define QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW (QSERDES_RX + 0x3c)
+#define QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH (QSERDES_RX + 0x40)
+#define QSERDES_RX_UCDR_PI_CONTROLS (QSERDES_RX + 0x44)
+#define QSERDES_RX_UCDR_PI_CTRL2 (QSERDES_RX + 0x48)
+#define QSERDES_RX_RX_TERM_BW (QSERDES_RX + 0x80)
+#define QSERDES_RX_VGA_CAL_CNTRL2 (QSERDES_RX + 0xd8)
+#define QSERDES_RX_GM_CAL (QSERDES_RX + 0xdc)
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1 (QSERDES_RX + 0xe8)
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 (QSERDES_RX + 0xec)
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3 (QSERDES_RX + 0xf0)
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4 (QSERDES_RX + 0xf4)
+#define QSERDES_RX_RX_IDAC_TSETTLE_LOW (QSERDES_RX + 0xf8)
+#define QSERDES_RX_RX_IDAC_TSETTLE_HIGH (QSERDES_RX + 0xfc)
+#define QSERDES_RX_RX_IDAC_MEASURE_TIME (QSERDES_RX + 0x100)
+#define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 (QSERDES_RX + 0x110)
+#define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2 (QSERDES_RX + 0x114)
+#define QSERDES_RX_SIGDET_CNTRL (QSERDES_RX + 0x11c)
+#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL (QSERDES_RX + 0x124)
+#define QSERDES_RX_RX_BAND (QSERDES_RX + 0x128)
+#define QSERDES_RX_RX_MODE_00_LOW (QSERDES_RX + 0x15c)
+#define QSERDES_RX_RX_MODE_00_HIGH (QSERDES_RX + 0x160)
+#define QSERDES_RX_RX_MODE_00_HIGH2 (QSERDES_RX + 0x164)
+#define QSERDES_RX_RX_MODE_00_HIGH3 (QSERDES_RX + 0x168)
+#define QSERDES_RX_RX_MODE_00_HIGH4 (QSERDES_RX + 0x16c)
+#define QSERDES_RX_RX_MODE_01_LOW (QSERDES_RX + 0x170)
+#define QSERDES_RX_RX_MODE_01_HIGH (QSERDES_RX + 0x174)
+#define QSERDES_RX_RX_MODE_01_HIGH2 (QSERDES_RX + 0x178)
+#define QSERDES_RX_RX_MODE_01_HIGH3 (QSERDES_RX + 0x17c)
+#define QSERDES_RX_RX_MODE_01_HIGH4 (QSERDES_RX + 0x180)
+#define QSERDES_RX_RX_MODE_10_LOW (QSERDES_RX + 0x184)
+#define QSERDES_RX_RX_MODE_10_HIGH (QSERDES_RX + 0x188)
+#define QSERDES_RX_RX_MODE_10_HIGH2 (QSERDES_RX + 0x18c)
+#define QSERDES_RX_RX_MODE_10_HIGH3 (QSERDES_RX + 0x190)
+#define QSERDES_RX_RX_MODE_10_HIGH4 (QSERDES_RX + 0x194)
+#define QSERDES_RX_DCC_CTRL1 (QSERDES_RX + 0x1a8)
+
+#define QSERDES_TX 0x400
+#define QSERDES_TX_TX_BAND (QSERDES_TX + 0x24)
+#define QSERDES_TX_SLEW_CNTL (QSERDES_TX + 0x28)
+#define QSERDES_TX_RES_CODE_LANE_OFFSET_TX (QSERDES_TX + 0x3c)
+#define QSERDES_TX_RES_CODE_LANE_OFFSET_RX (QSERDES_TX + 0x40)
+#define QSERDES_TX_LANE_MODE_1 (QSERDES_TX + 0x84)
+#define QSERDES_TX_LANE_MODE_3 (QSERDES_TX + 0x8c)
+#define QSERDES_TX_RCV_DETECT_LVL_2 (QSERDES_TX + 0xa4)
+#define QSERDES_TX_TRAN_DRVR_EMP_EN (QSERDES_TX + 0xc0)
+
+#define QSERDES_PCS 0xC00
+#define QSERDES_PCS_PHY_START (QSERDES_PCS + 0x0)
+#define QSERDES_PCS_POWER_DOWN_CONTROL (QSERDES_PCS + 0x4)
+#define QSERDES_PCS_SW_RESET (QSERDES_PCS + 0x8)
+#define QSERDES_PCS_LINE_RESET_TIME (QSERDES_PCS + 0xc)
+#define QSERDES_PCS_TX_LARGE_AMP_DRV_LVL (QSERDES_PCS + 0x20)
+#define QSERDES_PCS_TX_SMALL_AMP_DRV_LVL (QSERDES_PCS + 0x28)
+#define QSERDES_PCS_TX_MID_TERM_CTRL1 (QSERDES_PCS + 0xd8)
+#define QSERDES_PCS_TX_MID_TERM_CTRL2 (QSERDES_PCS + 0xdc)
+#define QSERDES_PCS_SGMII_MISC_CTRL8 (QSERDES_PCS + 0x118)
+#define QSERDES_PCS_PCS_READY_STATUS (QSERDES_PCS + 0x94)
+
+#define QSERDES_COM_C_READY BIT(0)
+#define QSERDES_PCS_READY BIT(0)
+#define QSERDES_PCS_SGMIIPHY_READY BIT(7)
+#define QSERDES_COM_C_PLL_LOCKED BIT(1)
+
+struct qcom_dwmac_sgmii_phy_data {
+ struct regmap *regmap;
+ struct clk *refclk;
+ int speed;
+};
+
+static void qcom_dwmac_sgmii_phy_init_1g(struct regmap *regmap)
+{
+ regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x01);
+ regmap_write(regmap, QSERDES_PCS_POWER_DOWN_CONTROL, 0x01);
+
+ regmap_write(regmap, QSERDES_COM_PLL_IVCO, 0x0F);
+ regmap_write(regmap, QSERDES_COM_CP_CTRL_MODE0, 0x06);
+ regmap_write(regmap, QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
+ regmap_write(regmap, QSERDES_COM_PLL_CCTRL_MODE0, 0x36);
+ regmap_write(regmap, QSERDES_COM_SYSCLK_EN_SEL, 0x1A);
+ regmap_write(regmap, QSERDES_COM_LOCK_CMP1_MODE0, 0x0A);
+ regmap_write(regmap, QSERDES_COM_LOCK_CMP2_MODE0, 0x1A);
+ regmap_write(regmap, QSERDES_COM_DEC_START_MODE0, 0x82);
+ regmap_write(regmap, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55);
+ regmap_write(regmap, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55);
+ regmap_write(regmap, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03);
+ regmap_write(regmap, QSERDES_COM_VCO_TUNE1_MODE0, 0x24);
+
+ regmap_write(regmap, QSERDES_COM_VCO_TUNE2_MODE0, 0x02);
+ regmap_write(regmap, QSERDES_COM_VCO_TUNE_INITVAL2, 0x00);
+ regmap_write(regmap, QSERDES_COM_HSCLK_SEL, 0x04);
+ regmap_write(regmap, QSERDES_COM_HSCLK_HS_SWITCH_SEL, 0x00);
+ regmap_write(regmap, QSERDES_COM_CORECLK_DIV_MODE0, 0x0A);
+ regmap_write(regmap, QSERDES_COM_CORE_CLK_EN, 0x00);
+ regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xB9);
+ regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1E);
+ regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);
+
+ regmap_write(regmap, QSERDES_TX_TX_BAND, 0x05);
+ regmap_write(regmap, QSERDES_TX_SLEW_CNTL, 0x0A);
+ regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_TX, 0x09);
+ regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_RX, 0x09);
+ regmap_write(regmap, QSERDES_TX_LANE_MODE_1, 0x05);
+ regmap_write(regmap, QSERDES_TX_LANE_MODE_3, 0x00);
+ regmap_write(regmap, QSERDES_TX_RCV_DETECT_LVL_2, 0x12);
+ regmap_write(regmap, QSERDES_TX_TRAN_DRVR_EMP_EN, 0x0C);
+
+ regmap_write(regmap, QSERDES_RX_UCDR_FO_GAIN, 0x0A);
+ regmap_write(regmap, QSERDES_RX_UCDR_SO_GAIN, 0x06);
+ regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);
+ regmap_write(regmap, QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);
+ regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);
+ regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);
+ regmap_write(regmap, QSERDES_RX_UCDR_PI_CONTROLS, 0x81);
+ regmap_write(regmap, QSERDES_RX_UCDR_PI_CTRL2, 0x80);
+ regmap_write(regmap, QSERDES_RX_RX_TERM_BW, 0x04);
+ regmap_write(regmap, QSERDES_RX_VGA_CAL_CNTRL2, 0x08);
+ regmap_write(regmap, QSERDES_RX_GM_CAL, 0x0F);
+ regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);
+ regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);
+ regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);
+ regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);
+ regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_LOW, 0x80);
+ regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_HIGH, 0x01);
+ regmap_write(regmap, QSERDES_RX_RX_IDAC_MEASURE_TIME, 0x20);
+ regmap_write(regmap, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);
+ regmap_write(regmap, QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);
+ regmap_write(regmap, QSERDES_RX_SIGDET_CNTRL, 0x0F);
+ regmap_write(regmap, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);
+ regmap_write(regmap, QSERDES_RX_RX_BAND, 0x05);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_LOW, 0xE0);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH3, 0x09);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH4, 0xB1);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_LOW, 0xE0);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH3, 0x09);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH4, 0xB1);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_LOW, 0xE0);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH3, 0x3B);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH4, 0xB7);
+ regmap_write(regmap, QSERDES_RX_DCC_CTRL1, 0x0C);
+
+ regmap_write(regmap, QSERDES_PCS_LINE_RESET_TIME, 0x0C);
+ regmap_write(regmap, QSERDES_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);
+ regmap_write(regmap, QSERDES_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);
+ regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL1, 0x83);
+ regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
+ regmap_write(regmap, QSERDES_PCS_SGMII_MISC_CTRL8, 0x0C);
+ regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x00);
+
+ regmap_write(regmap, QSERDES_PCS_PHY_START, 0x01);
+}
+
+static void qcom_dwmac_sgmii_phy_init_2p5g(struct regmap *regmap)
+{
+ regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x01);
+ regmap_write(regmap, QSERDES_PCS_POWER_DOWN_CONTROL, 0x01);
+
+ regmap_write(regmap, QSERDES_COM_PLL_IVCO, 0x0F);
+ regmap_write(regmap, QSERDES_COM_CP_CTRL_MODE0, 0x06);
+ regmap_write(regmap, QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
+ regmap_write(regmap, QSERDES_COM_PLL_CCTRL_MODE0, 0x36);
+ regmap_write(regmap, QSERDES_COM_SYSCLK_EN_SEL, 0x1A);
+ regmap_write(regmap, QSERDES_COM_LOCK_CMP1_MODE0, 0x1A);
+ regmap_write(regmap, QSERDES_COM_LOCK_CMP2_MODE0, 0x41);
+ regmap_write(regmap, QSERDES_COM_DEC_START_MODE0, 0x7A);
+ regmap_write(regmap, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00);
+ regmap_write(regmap, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x20);
+ regmap_write(regmap, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x01);
+ regmap_write(regmap, QSERDES_COM_VCO_TUNE1_MODE0, 0xA1);
+
+ regmap_write(regmap, QSERDES_COM_VCO_TUNE2_MODE0, 0x02);
+ regmap_write(regmap, QSERDES_COM_VCO_TUNE_INITVAL2, 0x00);
+ regmap_write(regmap, QSERDES_COM_HSCLK_SEL, 0x03);
+ regmap_write(regmap, QSERDES_COM_HSCLK_HS_SWITCH_SEL, 0x00);
+ regmap_write(regmap, QSERDES_COM_CORECLK_DIV_MODE0, 0x05);
+ regmap_write(regmap, QSERDES_COM_CORE_CLK_EN, 0x00);
+ regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xCD);
+ regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1C);
+ regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);
+
+ regmap_write(regmap, QSERDES_TX_TX_BAND, 0x04);
+ regmap_write(regmap, QSERDES_TX_SLEW_CNTL, 0x0A);
+ regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_TX, 0x09);
+ regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_RX, 0x02);
+ regmap_write(regmap, QSERDES_TX_LANE_MODE_1, 0x05);
+ regmap_write(regmap, QSERDES_TX_LANE_MODE_3, 0x00);
+ regmap_write(regmap, QSERDES_TX_RCV_DETECT_LVL_2, 0x12);
+ regmap_write(regmap, QSERDES_TX_TRAN_DRVR_EMP_EN, 0x0C);
+
+ regmap_write(regmap, QSERDES_RX_UCDR_FO_GAIN, 0x0A);
+ regmap_write(regmap, QSERDES_RX_UCDR_SO_GAIN, 0x06);
+ regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);
+ regmap_write(regmap, QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);
+ regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);
+ regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);
+ regmap_write(regmap, QSERDES_RX_UCDR_PI_CONTROLS, 0x81);
+ regmap_write(regmap, QSERDES_RX_UCDR_PI_CTRL2, 0x80);
+ regmap_write(regmap, QSERDES_RX_RX_TERM_BW, 0x00);
+ regmap_write(regmap, QSERDES_RX_VGA_CAL_CNTRL2, 0x08);
+ regmap_write(regmap, QSERDES_RX_GM_CAL, 0x0F);
+ regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);
+ regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);
+ regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);
+ regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);
+ regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_LOW, 0x80);
+ regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_HIGH, 0x01);
+ regmap_write(regmap, QSERDES_RX_RX_IDAC_MEASURE_TIME, 0x20);
+ regmap_write(regmap, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);
+ regmap_write(regmap, QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);
+ regmap_write(regmap, QSERDES_RX_SIGDET_CNTRL, 0x0F);
+ regmap_write(regmap, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);
+ regmap_write(regmap, QSERDES_RX_RX_BAND, 0x18);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_LOW, 0x18);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH3, 0x0C);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH4, 0xB8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_LOW, 0xE0);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH3, 0x09);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH4, 0xB1);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_LOW, 0xE0);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH3, 0x3B);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH4, 0xB7);
+ regmap_write(regmap, QSERDES_RX_DCC_CTRL1, 0x0C);
+
+ regmap_write(regmap, QSERDES_PCS_LINE_RESET_TIME, 0x0C);
+ regmap_write(regmap, QSERDES_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);
+ regmap_write(regmap, QSERDES_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);
+ regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL1, 0x83);
+ regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
+ regmap_write(regmap, QSERDES_PCS_SGMII_MISC_CTRL8, 0x8C);
+ regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x00);
+
+ regmap_write(regmap, QSERDES_PCS_PHY_START, 0x01);
+}
+
+static inline int
+qcom_dwmac_sgmii_phy_poll_status(struct regmap *regmap, unsigned int reg,
+ unsigned int bit)
+{
+ unsigned int val;
+
+ return regmap_read_poll_timeout(regmap, reg, val,
+ val & bit, 1500, 750000);
+}
+
+static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy)
+{
+ struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
+ struct device *dev = phy->dev.parent;
+
+ switch (data->speed) {
+ case SPEED_10:
+ case SPEED_100:
+ case SPEED_1000:
+ qcom_dwmac_sgmii_phy_init_1g(data->regmap);
+ break;
+ case SPEED_2500:
+ qcom_dwmac_sgmii_phy_init_2p5g(data->regmap);
+ break;
+ }
+
+ if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
+ QSERDES_COM_C_READY_STATUS,
+ QSERDES_COM_C_READY)) {
+ dev_err(dev, "QSERDES_COM_C_READY_STATUS timed-out");
+ return -ETIMEDOUT;
+ }
+
+ if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
+ QSERDES_PCS_PCS_READY_STATUS,
+ QSERDES_PCS_READY)) {
+ dev_err(dev, "PCS_READY timed-out");
+ return -ETIMEDOUT;
+ }
+
+ if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
+ QSERDES_PCS_PCS_READY_STATUS,
+ QSERDES_PCS_SGMIIPHY_READY)) {
+ dev_err(dev, "SGMIIPHY_READY timed-out");
+ return -ETIMEDOUT;
+ }
+
+ if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
+ QSERDES_COM_CMN_STATUS,
+ QSERDES_COM_C_PLL_LOCKED)) {
+ dev_err(dev, "PLL Lock Status timed-out");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int qcom_dwmac_sgmii_phy_power_on(struct phy *phy)
+{
+ struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
+
+ return clk_prepare_enable(data->refclk);
+}
+
+static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy)
+{
+ struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
+
+ regmap_write(data->regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
+ regmap_write(data->regmap, QSERDES_PCS_SW_RESET, 0x01);
+ udelay(100);
+ regmap_write(data->regmap, QSERDES_PCS_SW_RESET, 0x00);
+ regmap_write(data->regmap, QSERDES_PCS_PHY_START, 0x01);
+
+ clk_disable_unprepare(data->refclk);
+
+ return 0;
+}
+
+static int qcom_dwmac_sgmii_phy_set_speed(struct phy *phy, int speed)
+{
+ struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
+
+ if (speed != data->speed)
+ data->speed = speed;
+
+ return qcom_dwmac_sgmii_phy_calibrate(phy);
+}
+
+static const struct phy_ops qcom_dwmac_sgmii_phy_ops = {
+ .power_on = qcom_dwmac_sgmii_phy_power_on,
+ .power_off = qcom_dwmac_sgmii_phy_power_off,
+ .set_speed = qcom_dwmac_sgmii_phy_set_speed,
+ .calibrate = qcom_dwmac_sgmii_phy_calibrate,
+ .owner = THIS_MODULE,
+};
+
+static const struct regmap_config qcom_dwmac_sgmii_phy_regmap_cfg = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .use_relaxed_mmio = true,
+ .disable_locking = true,
+};
+
+static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev)
+{
+ struct qcom_dwmac_sgmii_phy_data *data;
+ struct device *dev = &pdev->dev;
+ struct phy_provider *provider;
+ void __iomem *base;
+ struct phy *phy;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->speed = SPEED_10;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ data->regmap = devm_regmap_init_mmio(dev, base,
+ &qcom_dwmac_sgmii_phy_regmap_cfg);
+ if (IS_ERR(data->regmap))
+ return PTR_ERR(data->regmap);
+
+ phy = devm_phy_create(dev, NULL, &qcom_dwmac_sgmii_phy_ops);
+ if (IS_ERR(phy))
+ return PTR_ERR(phy);
+
+ data->refclk = devm_clk_get(dev, "sgmi_ref");
+ if (IS_ERR(data->refclk))
+ return PTR_ERR(data->refclk);
+
+ provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ if (IS_ERR(provider))
+ return PTR_ERR(provider);
+
+ phy_set_drvdata(phy, data);
+
+ return 0;
+}
+
+static const struct of_device_id qcom_dwmac_sgmii_phy_of_match[] = {
+ { .compatible = "qcom,sa8775p-dwmac-sgmii-phy" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, qcom_dwmac_sgmii_phy_of_match);
+
+static struct platform_driver qcom_dwmac_sgmii_phy_driver = {
+ .probe = qcom_dwmac_sgmii_phy_probe,
+ .driver = {
+ .name = "qcom-dwmac-sgmii-phy",
+ .of_match_table = qcom_dwmac_sgmii_phy_of_match,
+ }
+};
+
+module_platform_driver(qcom_dwmac_sgmii_phy_driver);
+
+MODULE_DESCRIPTION("Qualcomm DWMAC SGMII PHY driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
index 6c237f3cc66d..d0319bee01c0 100644
--- a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
+++ b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
@@ -110,11 +110,13 @@ struct phy_override_seq {
/**
* struct qcom_snps_hsphy - snps hs phy attributes
*
+ * @dev: device structure
+ *
* @phy: generic phy
* @base: iomapped memory space for snps hs phy
*
- * @cfg_ahb_clk: AHB2PHY interface clock
- * @ref_clk: phy reference clock
+ * @num_clks: number of clocks
+ * @clks: array of clocks
* @phy_reset: phy reset control
* @vregs: regulator supplies bulk data
* @phy_initialized: if PHY has been initialized correctly
@@ -122,11 +124,13 @@ struct phy_override_seq {
* @update_seq_cfg: tuning parameters for phy init
*/
struct qcom_snps_hsphy {
+ struct device *dev;
+
struct phy *phy;
void __iomem *base;
- struct clk *cfg_ahb_clk;
- struct clk *ref_clk;
+ int num_clks;
+ struct clk_bulk_data *clks;
struct reset_control *phy_reset;
struct regulator_bulk_data vregs[SNPS_HS_NUM_VREGS];
@@ -135,6 +139,34 @@ struct qcom_snps_hsphy {
struct phy_override_seq update_seq_cfg[NUM_HSPHY_TUNING_PARAMS];
};
+static int qcom_snps_hsphy_clk_init(struct qcom_snps_hsphy *hsphy)
+{
+ struct device *dev = hsphy->dev;
+
+ hsphy->num_clks = 2;
+ hsphy->clks = devm_kcalloc(dev, hsphy->num_clks, sizeof(*hsphy->clks), GFP_KERNEL);
+ if (!hsphy->clks)
+ return -ENOMEM;
+
+ /*
+ * TODO: Currently no device tree instantiation of the PHY is using the clock.
+ * This needs to be fixed in order for this code to be able to use devm_clk_bulk_get().
+ */
+ hsphy->clks[0].id = "cfg_ahb";
+ hsphy->clks[0].clk = devm_clk_get_optional(dev, "cfg_ahb");
+ if (IS_ERR(hsphy->clks[0].clk))
+ return dev_err_probe(dev, PTR_ERR(hsphy->clks[0].clk),
+ "failed to get cfg_ahb clk\n");
+
+ hsphy->clks[1].id = "ref";
+ hsphy->clks[1].clk = devm_clk_get(dev, "ref");
+ if (IS_ERR(hsphy->clks[1].clk))
+ return dev_err_probe(dev, PTR_ERR(hsphy->clks[1].clk),
+ "failed to get ref clk\n");
+
+ return 0;
+}
+
static inline void qcom_snps_hsphy_write_mask(void __iomem *base, u32 offset,
u32 mask, u32 val)
{
@@ -165,22 +197,13 @@ static int qcom_snps_hsphy_suspend(struct qcom_snps_hsphy *hsphy)
0, USB2_AUTO_RESUME);
}
- clk_disable_unprepare(hsphy->cfg_ahb_clk);
return 0;
}
static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy *hsphy)
{
- int ret;
-
dev_dbg(&hsphy->phy->dev, "Resume QCOM SNPS PHY, mode\n");
- ret = clk_prepare_enable(hsphy->cfg_ahb_clk);
- if (ret) {
- dev_err(&hsphy->phy->dev, "failed to enable cfg ahb clock\n");
- return ret;
- }
-
return 0;
}
@@ -191,8 +214,7 @@ static int __maybe_unused qcom_snps_hsphy_runtime_suspend(struct device *dev)
if (!hsphy->phy_initialized)
return 0;
- qcom_snps_hsphy_suspend(hsphy);
- return 0;
+ return qcom_snps_hsphy_suspend(hsphy);
}
static int __maybe_unused qcom_snps_hsphy_runtime_resume(struct device *dev)
@@ -202,8 +224,7 @@ static int __maybe_unused qcom_snps_hsphy_runtime_resume(struct device *dev)
if (!hsphy->phy_initialized)
return 0;
- qcom_snps_hsphy_resume(hsphy);
- return 0;
+ return qcom_snps_hsphy_resume(hsphy);
}
static int qcom_snps_hsphy_set_mode(struct phy *phy, enum phy_mode mode,
@@ -374,16 +395,16 @@ static int qcom_snps_hsphy_init(struct phy *phy)
if (ret)
return ret;
- ret = clk_prepare_enable(hsphy->cfg_ahb_clk);
+ ret = clk_bulk_prepare_enable(hsphy->num_clks, hsphy->clks);
if (ret) {
- dev_err(&phy->dev, "failed to enable cfg ahb clock, %d\n", ret);
+ dev_err(&phy->dev, "failed to enable clocks, %d\n", ret);
goto poweroff_phy;
}
ret = reset_control_assert(hsphy->phy_reset);
if (ret) {
dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
- goto disable_ahb_clk;
+ goto disable_clks;
}
usleep_range(100, 150);
@@ -391,7 +412,7 @@ static int qcom_snps_hsphy_init(struct phy *phy)
ret = reset_control_deassert(hsphy->phy_reset);
if (ret) {
dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret);
- goto disable_ahb_clk;
+ goto disable_clks;
}
qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
@@ -448,8 +469,8 @@ static int qcom_snps_hsphy_init(struct phy *phy)
return 0;
-disable_ahb_clk:
- clk_disable_unprepare(hsphy->cfg_ahb_clk);
+disable_clks:
+ clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
poweroff_phy:
regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
@@ -461,7 +482,7 @@ static int qcom_snps_hsphy_exit(struct phy *phy)
struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
reset_control_assert(hsphy->phy_reset);
- clk_disable_unprepare(hsphy->cfg_ahb_clk);
+ clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
hsphy->phy_initialized = false;
@@ -554,14 +575,15 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev)
if (!hsphy)
return -ENOMEM;
+ hsphy->dev = dev;
+
hsphy->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(hsphy->base))
return PTR_ERR(hsphy->base);
- hsphy->ref_clk = devm_clk_get(dev, "ref");
- if (IS_ERR(hsphy->ref_clk))
- return dev_err_probe(dev, PTR_ERR(hsphy->ref_clk),
- "failed to get ref clk\n");
+ ret = qcom_snps_hsphy_clk_init(hsphy);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to initialize clocks\n");
hsphy->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(hsphy->phy_reset)) {
diff --git a/drivers/phy/samsung/Kconfig b/drivers/phy/samsung/Kconfig
index 3ccaabf2850a..f10afa3d7ff5 100644
--- a/drivers/phy/samsung/Kconfig
+++ b/drivers/phy/samsung/Kconfig
@@ -59,7 +59,7 @@ config PHY_EXYNOS4210_USB2
config PHY_EXYNOS4X12_USB2
bool
depends on PHY_SAMSUNG_USB2
- default SOC_EXYNOS3250 || SOC_EXYNOS4412
+ default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412
config PHY_EXYNOS5250_USB2
bool
diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
index b55d4e9f42b5..a296b87dced1 100644
--- a/drivers/phy/tegra/xusb.c
+++ b/drivers/phy/tegra/xusb.c
@@ -568,6 +568,7 @@ static void tegra_xusb_port_unregister(struct tegra_xusb_port *port)
usb_role_switch_unregister(port->usb_role_sw);
cancel_work_sync(&port->usb_phy_work);
usb_remove_phy(&port->usb_phy);
+ port->usb_phy.dev->driver = NULL;
}
if (port->ops->remove)
@@ -675,6 +676,9 @@ static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
port->dev.driver = devm_kzalloc(&port->dev,
sizeof(struct device_driver),
GFP_KERNEL);
+ if (!port->dev.driver)
+ return -ENOMEM;
+
port->dev.driver->owner = THIS_MODULE;
port->usb_role_sw = usb_role_switch_register(&port->dev,
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-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c
index 8c667819c39a..6286cf25a426 100644
--- a/drivers/phy/ti/phy-gmii-sel.c
+++ b/drivers/phy/ti/phy-gmii-sel.c
@@ -23,7 +23,9 @@
#define AM33XX_GMII_SEL_MODE_RGMII 2
/* J72xx SoC specific definitions for the CONTROL port */
+#define J72XX_GMII_SEL_MODE_SGMII 3
#define J72XX_GMII_SEL_MODE_QSGMII 4
+#define J72XX_GMII_SEL_MODE_USXGMII 5
#define J72XX_GMII_SEL_MODE_QSGMII_SUB 6
#define PHY_GMII_PORT(n) BIT((n) - 1)
@@ -106,6 +108,20 @@ static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode)
gmii_sel_mode = J72XX_GMII_SEL_MODE_QSGMII_SUB;
break;
+ case PHY_INTERFACE_MODE_SGMII:
+ if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_SGMII)))
+ goto unsupported;
+ else
+ gmii_sel_mode = J72XX_GMII_SEL_MODE_SGMII;
+ break;
+
+ case PHY_INTERFACE_MODE_USXGMII:
+ if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_USXGMII)))
+ goto unsupported;
+ else
+ gmii_sel_mode = J72XX_GMII_SEL_MODE_USXGMII;
+ break;
+
default:
goto unsupported;
}
@@ -213,7 +229,7 @@ static const
struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw5g_soc_j7200 = {
.use_of_data = true,
.regfields = phy_gmii_sel_fields_am654,
- .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII),
+ .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII),
.num_ports = 4,
.num_qsgmii_main_ports = 1,
};
@@ -222,7 +238,17 @@ static const
struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j721e = {
.use_of_data = true,
.regfields = phy_gmii_sel_fields_am654,
- .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII),
+ .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII),
+ .num_ports = 8,
+ .num_qsgmii_main_ports = 2,
+};
+
+static const
+struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j784s4 = {
+ .use_of_data = true,
+ .regfields = phy_gmii_sel_fields_am654,
+ .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) |
+ BIT(PHY_INTERFACE_MODE_USXGMII),
.num_ports = 8,
.num_qsgmii_main_ports = 2,
};
@@ -256,6 +282,10 @@ static const struct of_device_id phy_gmii_sel_id_table[] = {
.compatible = "ti,j721e-cpsw9g-phy-gmii-sel",
.data = &phy_gmii_sel_cpsw9g_soc_j721e,
},
+ {
+ .compatible = "ti,j784s4-cpsw9g-phy-gmii-sel",
+ .data = &phy_gmii_sel_cpsw9g_soc_j784s4,
+ },
{}
};
MODULE_DEVICE_TABLE(of, phy_gmii_sel_id_table);
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 5787c579dcf6..57d57af1f624 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -407,7 +407,7 @@ config PINCTRL_PISTACHIO
config PINCTRL_RK805
tristate "Pinctrl and GPIO driver for RK805 PMIC"
- depends on MFD_RK808
+ depends on MFD_RK8XX
select GPIOLIB
select PINMUX
select GENERIC_PINCONF
@@ -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 f279b360c20d..4dff656af3ad 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -30,6 +30,7 @@
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinmux.h>
+#include <linux/suspend.h>
#include "core.h"
#include "pinctrl-utils.h"
@@ -115,16 +116,20 @@ static void amd_gpio_set_value(struct gpio_chip *gc, unsigned offset, int value)
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
}
-static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset,
- unsigned debounce)
+static int amd_gpio_set_debounce(struct amd_gpio *gpio_dev, unsigned int offset,
+ unsigned int debounce)
{
u32 time;
u32 pin_reg;
int ret = 0;
- unsigned long flags;
- struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
- raw_spin_lock_irqsave(&gpio_dev->lock, flags);
+ /* Use special handling for Pin0 debounce */
+ if (offset == 0) {
+ 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) {
@@ -175,23 +180,10 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset,
pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF);
}
writel(pin_reg, gpio_dev->base + offset * 4);
- raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
return ret;
}
-static int amd_gpio_set_config(struct gpio_chip *gc, unsigned offset,
- unsigned long config)
-{
- u32 debounce;
-
- if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
- return -ENOTSUPP;
-
- debounce = pinconf_to_config_argument(config);
- return amd_gpio_set_debounce(gc, offset, debounce);
-}
-
#ifdef CONFIG_DEBUG_FS
static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
{
@@ -213,12 +205,12 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
char *pin_sts;
char *interrupt_sts;
char *wake_sts;
- char *pull_up_sel;
char *orientation;
char debounce_value[40];
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;
@@ -320,14 +312,9 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
seq_printf(s, " %s|", wake_sts);
if (pin_reg & BIT(PULL_UP_ENABLE_OFF)) {
- if (pin_reg & BIT(PULL_UP_SEL_OFF))
- pull_up_sel = "8k";
- else
- pull_up_sel = "4k";
- seq_printf(s, "%s ↑|",
- pull_up_sel);
+ seq_puts(s, " ↑ |");
} else if (pin_reg & BIT(PULL_DOWN_ENABLE_OFF)) {
- seq_puts(s, " ↓|");
+ seq_puts(s, " ↓ |");
} else {
seq_puts(s, " |");
}
@@ -636,9 +623,8 @@ static bool do_amd_gpio_irq_handler(int irq, void *dev_id)
regval = readl(regs + i);
if (regval & PIN_IRQ_PENDING)
- dev_dbg(&gpio_dev->pdev->dev,
- "GPIO %d is active: 0x%x",
- irqnr + i, regval);
+ pm_pr_dbg("GPIO %d is active: 0x%x",
+ irqnr + i, regval);
/* caused wake on resume context for shared IRQ */
if (irq < 0 && (regval & BIT(WAKE_STS_OFF)))
@@ -653,21 +639,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 */
@@ -754,7 +740,7 @@ static int amd_pinconf_get(struct pinctrl_dev *pctldev,
break;
case PIN_CONFIG_BIAS_PULL_UP:
- arg = (pin_reg >> PULL_UP_SEL_OFF) & (BIT(0) | BIT(1));
+ arg = (pin_reg >> PULL_UP_ENABLE_OFF) & BIT(0);
break;
case PIN_CONFIG_DRIVE_STRENGTH:
@@ -773,7 +759,7 @@ static int amd_pinconf_get(struct pinctrl_dev *pctldev,
}
static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
- unsigned long *configs, unsigned num_configs)
+ unsigned long *configs, unsigned int num_configs)
{
int i;
u32 arg;
@@ -791,9 +777,8 @@ static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
switch (param) {
case PIN_CONFIG_INPUT_DEBOUNCE:
- pin_reg &= ~DB_TMR_OUT_MASK;
- pin_reg |= arg & DB_TMR_OUT_MASK;
- break;
+ ret = amd_gpio_set_debounce(gpio_dev, pin, arg);
+ goto out_unlock;
case PIN_CONFIG_BIAS_PULL_DOWN:
pin_reg &= ~BIT(PULL_DOWN_ENABLE_OFF);
@@ -801,10 +786,8 @@ static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
break;
case PIN_CONFIG_BIAS_PULL_UP:
- pin_reg &= ~BIT(PULL_UP_SEL_OFF);
- pin_reg |= (arg & BIT(0)) << PULL_UP_SEL_OFF;
pin_reg &= ~BIT(PULL_UP_ENABLE_OFF);
- pin_reg |= ((arg>>1) & BIT(0)) << PULL_UP_ENABLE_OFF;
+ pin_reg |= (arg & BIT(0)) << PULL_UP_ENABLE_OFF;
break;
case PIN_CONFIG_DRIVE_STRENGTH:
@@ -822,6 +805,7 @@ static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
writel(pin_reg, gpio_dev->base + pin*4);
}
+out_unlock:
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
return ret;
@@ -863,6 +847,14 @@ static int amd_pinconf_group_set(struct pinctrl_dev *pctldev,
return 0;
}
+static int amd_gpio_set_config(struct gpio_chip *gc, unsigned int pin,
+ unsigned long config)
+{
+ struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
+
+ return amd_pinconf_set(gpio_dev->pctrl, pin, &config, 1);
+}
+
static const struct pinconf_ops amd_pinconf_ops = {
.pin_config_get = amd_pinconf_get,
.pin_config_set = amd_pinconf_set,
@@ -878,7 +870,6 @@ static void amd_gpio_irq_init(struct amd_gpio *gpio_dev)
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++) {
@@ -890,9 +881,9 @@ static void amd_gpio_irq_init(struct amd_gpio *gpio_dev)
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
- pin_reg = readl(gpio_dev->base + i * 4);
+ pin_reg = readl(gpio_dev->base + pin * 4);
pin_reg &= ~mask;
- writel(pin_reg, gpio_dev->base + i * 4);
+ writel(pin_reg, gpio_dev->base + pin * 4);
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
}
diff --git a/drivers/pinctrl/pinctrl-amd.h b/drivers/pinctrl/pinctrl-amd.h
index 81ae8319a1f0..34c5c3e71fb2 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
@@ -35,7 +36,6 @@
#define WAKE_CNTRL_OFF_S4 15
#define PIN_STS_OFF 16
#define DRV_STRENGTH_SEL_OFF 17
-#define PULL_UP_SEL_OFF 19
#define PULL_UP_ENABLE_OFF 20
#define PULL_DOWN_ENABLE_OFF 21
#define OUTPUT_VALUE_OFF 22
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-rk805.c b/drivers/pinctrl/pinctrl-rk805.c
index 7c1f7408fb9a..2639a9ee82cd 100644
--- a/drivers/pinctrl/pinctrl-rk805.c
+++ b/drivers/pinctrl/pinctrl-rk805.c
@@ -1,10 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Pinctrl driver for Rockchip RK805 PMIC
+ * Pinctrl driver for Rockchip RK805/RK806 PMIC
*
* Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
+ * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
*
* Author: Joseph Chen <chenjh@rock-chips.com>
+ * Author: Xu Shengfei <xsf@rock-chips.com>
*
* Based on the pinctrl-as3722 driver
*/
@@ -44,6 +46,7 @@ struct rk805_pin_group {
/*
* @reg: gpio setting register;
+ * @fun_reg: functions select register;
* @fun_mask: functions select mask value, when set is gpio;
* @dir_mask: input or output mask value, when set is output, otherwise input;
* @val_mask: gpio set value, when set is level high, otherwise low;
@@ -56,6 +59,7 @@ struct rk805_pin_group {
*/
struct rk805_pin_config {
u8 reg;
+ u8 fun_reg;
u8 fun_msk;
u8 dir_msk;
u8 val_msk;
@@ -80,22 +84,50 @@ enum rk805_pinmux_option {
RK805_PINMUX_GPIO,
};
+enum rk806_pinmux_option {
+ RK806_PINMUX_FUN0 = 0,
+ RK806_PINMUX_FUN1,
+ RK806_PINMUX_FUN2,
+ RK806_PINMUX_FUN3,
+ RK806_PINMUX_FUN4,
+ RK806_PINMUX_FUN5,
+};
+
enum {
RK805_GPIO0,
RK805_GPIO1,
};
+enum {
+ RK806_GPIO_DVS1,
+ RK806_GPIO_DVS2,
+ RK806_GPIO_DVS3
+};
+
static const char *const rk805_gpio_groups[] = {
"gpio0",
"gpio1",
};
+static const char *const rk806_gpio_groups[] = {
+ "gpio_pwrctrl1",
+ "gpio_pwrctrl2",
+ "gpio_pwrctrl3",
+};
+
/* RK805: 2 output only GPIOs */
static const struct pinctrl_pin_desc rk805_pins_desc[] = {
PINCTRL_PIN(RK805_GPIO0, "gpio0"),
PINCTRL_PIN(RK805_GPIO1, "gpio1"),
};
+/* RK806 */
+static const struct pinctrl_pin_desc rk806_pins_desc[] = {
+ PINCTRL_PIN(RK806_GPIO_DVS1, "gpio_pwrctrl1"),
+ PINCTRL_PIN(RK806_GPIO_DVS2, "gpio_pwrctrl2"),
+ PINCTRL_PIN(RK806_GPIO_DVS3, "gpio_pwrctrl3"),
+};
+
static const struct rk805_pin_function rk805_pin_functions[] = {
{
.name = "gpio",
@@ -105,6 +137,45 @@ static const struct rk805_pin_function rk805_pin_functions[] = {
},
};
+static const struct rk805_pin_function rk806_pin_functions[] = {
+ {
+ .name = "pin_fun0",
+ .groups = rk806_gpio_groups,
+ .ngroups = ARRAY_SIZE(rk806_gpio_groups),
+ .mux_option = RK806_PINMUX_FUN0,
+ },
+ {
+ .name = "pin_fun1",
+ .groups = rk806_gpio_groups,
+ .ngroups = ARRAY_SIZE(rk806_gpio_groups),
+ .mux_option = RK806_PINMUX_FUN1,
+ },
+ {
+ .name = "pin_fun2",
+ .groups = rk806_gpio_groups,
+ .ngroups = ARRAY_SIZE(rk806_gpio_groups),
+ .mux_option = RK806_PINMUX_FUN2,
+ },
+ {
+ .name = "pin_fun3",
+ .groups = rk806_gpio_groups,
+ .ngroups = ARRAY_SIZE(rk806_gpio_groups),
+ .mux_option = RK806_PINMUX_FUN3,
+ },
+ {
+ .name = "pin_fun4",
+ .groups = rk806_gpio_groups,
+ .ngroups = ARRAY_SIZE(rk806_gpio_groups),
+ .mux_option = RK806_PINMUX_FUN4,
+ },
+ {
+ .name = "pin_fun5",
+ .groups = rk806_gpio_groups,
+ .ngroups = ARRAY_SIZE(rk806_gpio_groups),
+ .mux_option = RK806_PINMUX_FUN5,
+ },
+};
+
static const struct rk805_pin_group rk805_pin_groups[] = {
{
.name = "gpio0",
@@ -118,6 +189,24 @@ static const struct rk805_pin_group rk805_pin_groups[] = {
},
};
+static const struct rk805_pin_group rk806_pin_groups[] = {
+ {
+ .name = "gpio_pwrctrl1",
+ .pins = { RK806_GPIO_DVS1 },
+ .npins = 1,
+ },
+ {
+ .name = "gpio_pwrctrl2",
+ .pins = { RK806_GPIO_DVS2 },
+ .npins = 1,
+ },
+ {
+ .name = "gpio_pwrctrl3",
+ .pins = { RK806_GPIO_DVS3 },
+ .npins = 1,
+ }
+};
+
#define RK805_GPIO0_VAL_MSK BIT(0)
#define RK805_GPIO1_VAL_MSK BIT(1)
@@ -132,6 +221,40 @@ static const struct rk805_pin_config rk805_gpio_cfgs[] = {
},
};
+#define RK806_PWRCTRL1_DR BIT(0)
+#define RK806_PWRCTRL2_DR BIT(1)
+#define RK806_PWRCTRL3_DR BIT(2)
+#define RK806_PWRCTRL1_DATA BIT(4)
+#define RK806_PWRCTRL2_DATA BIT(5)
+#define RK806_PWRCTRL3_DATA BIT(6)
+#define RK806_PWRCTRL1_FUN GENMASK(2, 0)
+#define RK806_PWRCTRL2_FUN GENMASK(6, 4)
+#define RK806_PWRCTRL3_FUN GENMASK(2, 0)
+
+static struct rk805_pin_config rk806_gpio_cfgs[] = {
+ {
+ .fun_reg = RK806_SLEEP_CONFIG0,
+ .fun_msk = RK806_PWRCTRL1_FUN,
+ .reg = RK806_SLEEP_GPIO,
+ .val_msk = RK806_PWRCTRL1_DATA,
+ .dir_msk = RK806_PWRCTRL1_DR,
+ },
+ {
+ .fun_reg = RK806_SLEEP_CONFIG0,
+ .fun_msk = RK806_PWRCTRL2_FUN,
+ .reg = RK806_SLEEP_GPIO,
+ .val_msk = RK806_PWRCTRL2_DATA,
+ .dir_msk = RK806_PWRCTRL2_DR,
+ },
+ {
+ .fun_reg = RK806_SLEEP_CONFIG1,
+ .fun_msk = RK806_PWRCTRL3_FUN,
+ .reg = RK806_SLEEP_GPIO,
+ .val_msk = RK806_PWRCTRL3_DATA,
+ .dir_msk = RK806_PWRCTRL3_DR,
+ }
+};
+
/* generic gpio chip */
static int rk805_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
@@ -289,19 +412,13 @@ static int _rk805_pinctrl_set_mux(struct pinctrl_dev *pctldev,
if (!pci->pin_cfg[offset].fun_msk)
return 0;
- if (mux == RK805_PINMUX_GPIO) {
- ret = regmap_update_bits(pci->rk808->regmap,
- pci->pin_cfg[offset].reg,
- pci->pin_cfg[offset].fun_msk,
- pci->pin_cfg[offset].fun_msk);
- if (ret) {
- dev_err(pci->dev, "set gpio%d GPIO failed\n", offset);
- return ret;
- }
- } else {
- dev_err(pci->dev, "Couldn't find function mux %d\n", mux);
- return -EINVAL;
- }
+ mux <<= ffs(pci->pin_cfg[offset].fun_msk) - 1;
+ ret = regmap_update_bits(pci->rk808->regmap,
+ pci->pin_cfg[offset].fun_reg,
+ pci->pin_cfg[offset].fun_msk, mux);
+
+ if (ret)
+ dev_err(pci->dev, "set gpio%d func%d failed\n", offset, mux);
return 0;
}
@@ -317,6 +434,22 @@ static int rk805_pinctrl_set_mux(struct pinctrl_dev *pctldev,
return _rk805_pinctrl_set_mux(pctldev, offset, mux);
}
+static int rk805_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset)
+{
+ struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev);
+
+ switch (pci->rk808->variant) {
+ case RK805_ID:
+ return _rk805_pinctrl_set_mux(pctldev, offset, RK805_PINMUX_GPIO);
+ case RK806_ID:
+ return _rk805_pinctrl_set_mux(pctldev, offset, RK806_PINMUX_FUN5);
+ }
+
+ return -ENOTSUPP;
+}
+
static int rk805_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned int offset, bool input)
@@ -324,13 +457,6 @@ static int rk805_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev);
int ret;
- /* switch to gpio function */
- ret = _rk805_pinctrl_set_mux(pctldev, offset, RK805_PINMUX_GPIO);
- if (ret) {
- dev_err(pci->dev, "set gpio%d mux failed\n", offset);
- return ret;
- }
-
/* set direction */
if (!pci->pin_cfg[offset].dir_msk)
return 0;
@@ -352,6 +478,7 @@ static const struct pinmux_ops rk805_pinmux_ops = {
.get_function_name = rk805_pinctrl_get_func_name,
.get_function_groups = rk805_pinctrl_get_func_groups,
.set_mux = rk805_pinctrl_set_mux,
+ .gpio_request_enable = rk805_pinctrl_gpio_request_enable,
.gpio_set_direction = rk805_pmx_gpio_set_direction,
};
@@ -364,6 +491,7 @@ static int rk805_pinconf_get(struct pinctrl_dev *pctldev,
switch (param) {
case PIN_CONFIG_OUTPUT:
+ case PIN_CONFIG_INPUT_ENABLE:
arg = rk805_gpio_get(&pci->gpio_chip, pin);
break;
default:
@@ -393,6 +521,12 @@ static int rk805_pinconf_set(struct pinctrl_dev *pctldev,
rk805_gpio_set(&pci->gpio_chip, pin, arg);
rk805_pmx_gpio_set_direction(pctldev, NULL, pin, false);
break;
+ case PIN_CONFIG_INPUT_ENABLE:
+ if (pci->rk808->variant != RK805_ID && arg) {
+ rk805_pmx_gpio_set_direction(pctldev, NULL, pin, true);
+ break;
+ }
+ fallthrough;
default:
dev_err(pci->dev, "Properties not supported\n");
return -ENOTSUPP;
@@ -448,6 +582,18 @@ static int rk805_pinctrl_probe(struct platform_device *pdev)
pci->pin_cfg = rk805_gpio_cfgs;
pci->gpio_chip.ngpio = ARRAY_SIZE(rk805_gpio_cfgs);
break;
+ case RK806_ID:
+ pci->pins = rk806_pins_desc;
+ pci->num_pins = ARRAY_SIZE(rk806_pins_desc);
+ pci->functions = rk806_pin_functions;
+ pci->num_functions = ARRAY_SIZE(rk806_pin_functions);
+ pci->groups = rk806_pin_groups;
+ pci->num_pin_groups = ARRAY_SIZE(rk806_pin_groups);
+ pci->pinctrl_desc.pins = rk806_pins_desc;
+ pci->pinctrl_desc.npins = ARRAY_SIZE(rk806_pins_desc);
+ pci->pin_cfg = rk806_gpio_cfgs;
+ pci->gpio_chip.ngpio = ARRAY_SIZE(rk806_gpio_cfgs);
+ break;
default:
dev_err(&pdev->dev, "unsupported RK805 ID %lu\n",
pci->rk808->variant);
@@ -488,5 +634,6 @@ static struct platform_driver rk805_pinctrl_driver = {
module_platform_driver(rk805_pinctrl_driver);
MODULE_DESCRIPTION("RK805 pin control and GPIO driver");
+MODULE_AUTHOR("Xu Shengfei <xsf@rock-chips.com>");
MODULE_AUTHOR("Joseph Chen <chenjh@rock-chips.com>");
MODULE_LICENSE("GPL v2");
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..115b83e2d8e6 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)
@@ -1039,6 +1038,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
const struct msm_pingroup *g;
+ u32 intr_target_mask = GENMASK(2, 0);
unsigned long flags;
bool was_enabled;
u32 val;
@@ -1075,13 +1075,15 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
* With intr_target_use_scm interrupts are routed to
* application cpu using scm calls.
*/
+ if (g->intr_target_width)
+ intr_target_mask = GENMASK(g->intr_target_width - 1, 0);
+
if (pctrl->intr_target_use_scm) {
u32 addr = pctrl->phys_base[0] + g->intr_target_reg;
int ret;
qcom_scm_io_readl(addr, &val);
-
- val &= ~(7 << g->intr_target_bit);
+ val &= ~(intr_target_mask << g->intr_target_bit);
val |= g->intr_target_kpss_val << g->intr_target_bit;
ret = qcom_scm_io_writel(addr, val);
@@ -1091,7 +1093,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
d->hwirq);
} else {
val = msm_readl_intr_target(pctrl, g);
- val &= ~(7 << g->intr_target_bit);
+ val &= ~(intr_target_mask << g->intr_target_bit);
val |= g->intr_target_kpss_val << g->intr_target_bit;
msm_writel_intr_target(val, pctrl, g);
}
@@ -1442,7 +1444,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..1d2f2e904da1 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.
@@ -51,6 +59,7 @@ struct msm_function {
* @intr_status_bit: Offset in @intr_status_reg for reading and acking the interrupt
* status.
* @intr_target_bit: Offset in @intr_target_reg for configuring the interrupt routing.
+ * @intr_target_width: Number of bits used for specifying interrupt routing target.
* @intr_target_kpss_val: Value in @intr_target_bit for specifying that the interrupt from
* this gpio should get routed to the KPSS processor.
* @intr_raw_status_bit: Offset in @intr_cfg_reg for the raw status bit.
@@ -61,9 +70,7 @@ struct msm_function {
* otherwise 1.
*/
struct msm_pingroup {
- const char *name;
- const unsigned *pins;
- unsigned npins;
+ struct pingroup grp;
unsigned *funcs;
unsigned nfuncs;
@@ -94,6 +101,7 @@ struct msm_pingroup {
unsigned intr_ack_high:1;
unsigned intr_target_bit:5;
+ unsigned intr_target_width:5;
unsigned intr_target_kpss_val:5;
unsigned intr_raw_status_bit:5;
unsigned intr_polarity_bit:5;
@@ -138,7 +146,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..8fdea25d8d67 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, \
@@ -54,6 +46,7 @@
.intr_enable_bit = 0, \
.intr_status_bit = 0, \
.intr_target_bit = 5, \
+ .intr_target_width = 4, \
.intr_target_kpss_val = 3, \
.intr_raw_status_bit = 4, \
.intr_polarity_bit = 1, \
@@ -63,9 +56,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 +81,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 +1172,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 +1484,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 +1509,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/renesas/pinctrl-rza2.c b/drivers/pinctrl/renesas/pinctrl-rza2.c
index 40b1326a1077..5591ddf16fdf 100644
--- a/drivers/pinctrl/renesas/pinctrl-rza2.c
+++ b/drivers/pinctrl/renesas/pinctrl-rza2.c
@@ -14,6 +14,7 @@
#include <linux/gpio/driver.h>
#include <linux/io.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/pinctrl/pinmux.h>
@@ -46,6 +47,7 @@ struct rza2_pinctrl_priv {
struct pinctrl_dev *pctl;
struct pinctrl_gpio_range gpio_range;
int npins;
+ struct mutex mutex; /* serialize adding groups and functions */
};
#define RZA2_PDR(port) (0x0000 + (port) * 2) /* Direction 16-bit */
@@ -358,10 +360,14 @@ static int rza2_dt_node_to_map(struct pinctrl_dev *pctldev,
psel_val[i] = MUX_FUNC(value);
}
+ mutex_lock(&priv->mutex);
+
/* Register a single pin group listing all the pins we read from DT */
gsel = pinctrl_generic_add_group(pctldev, np->name, pins, npins, NULL);
- if (gsel < 0)
- return gsel;
+ if (gsel < 0) {
+ ret = gsel;
+ goto unlock;
+ }
/*
* Register a single group function where the 'data' is an array PSEL
@@ -390,6 +396,8 @@ static int rza2_dt_node_to_map(struct pinctrl_dev *pctldev,
(*map)->data.mux.function = np->name;
*num_maps = 1;
+ mutex_unlock(&priv->mutex);
+
return 0;
remove_function:
@@ -398,6 +406,9 @@ remove_function:
remove_group:
pinctrl_generic_remove_group(pctldev, gsel);
+unlock:
+ mutex_unlock(&priv->mutex);
+
dev_err(priv->dev, "Unable to parse DT node %s\n", np->name);
return ret;
@@ -473,6 +484,8 @@ static int rza2_pinctrl_probe(struct platform_device *pdev)
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
+ mutex_init(&priv->mutex);
+
platform_set_drvdata(pdev, priv);
priv->npins = (int)(uintptr_t)of_device_get_match_data(&pdev->dev) *
diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
index 9511d920565e..6e8a76556e23 100644
--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c
+++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
@@ -11,6 +11,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/seq_file.h>
@@ -149,10 +150,11 @@ struct rzg2l_pinctrl {
struct gpio_chip gpio_chip;
struct pinctrl_gpio_range gpio_range;
DECLARE_BITMAP(tint_slot, RZG2L_TINT_MAX_INTERRUPT);
- spinlock_t bitmap_lock;
+ spinlock_t bitmap_lock; /* protect tint_slot bitmap */
unsigned int hwirq[RZG2L_TINT_MAX_INTERRUPT];
- spinlock_t lock;
+ spinlock_t lock; /* lock read/write registers */
+ struct mutex mutex; /* serialize adding groups and functions */
};
static const unsigned int iolh_groupa_mA[] = { 2, 4, 8, 12 };
@@ -249,6 +251,7 @@ static int rzg2l_map_add_config(struct pinctrl_map *map,
static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev,
struct device_node *np,
+ struct device_node *parent,
struct pinctrl_map **map,
unsigned int *num_maps,
unsigned int *index)
@@ -266,6 +269,7 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev,
struct property *prop;
int ret, gsel, fsel;
const char **pin_fn;
+ const char *name;
const char *pin;
pinmux = of_find_property(np, "pinmux", NULL);
@@ -349,28 +353,42 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev,
psel_val[i] = MUX_FUNC(value);
}
+ if (parent) {
+ name = devm_kasprintf(pctrl->dev, GFP_KERNEL, "%pOFn.%pOFn",
+ parent, np);
+ if (!name) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ } else {
+ name = np->name;
+ }
+
+ mutex_lock(&pctrl->mutex);
+
/* Register a single pin group listing all the pins we read from DT */
- gsel = pinctrl_generic_add_group(pctldev, np->name, pins, num_pinmux, NULL);
+ gsel = pinctrl_generic_add_group(pctldev, name, pins, num_pinmux, NULL);
if (gsel < 0) {
ret = gsel;
- goto done;
+ goto unlock;
}
/*
* Register a single group function where the 'data' is an array PSEL
* register values read from DT.
*/
- pin_fn[0] = np->name;
- fsel = pinmux_generic_add_function(pctldev, np->name, pin_fn, 1,
- psel_val);
+ pin_fn[0] = name;
+ fsel = pinmux_generic_add_function(pctldev, name, pin_fn, 1, psel_val);
if (fsel < 0) {
ret = fsel;
goto remove_group;
}
+ mutex_unlock(&pctrl->mutex);
+
maps[idx].type = PIN_MAP_TYPE_MUX_GROUP;
- maps[idx].data.mux.group = np->name;
- maps[idx].data.mux.function = np->name;
+ maps[idx].data.mux.group = name;
+ maps[idx].data.mux.function = name;
idx++;
dev_dbg(pctrl->dev, "Parsed %pOF with %d pins\n", np, num_pinmux);
@@ -379,6 +397,8 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev,
remove_group:
pinctrl_generic_remove_group(pctldev, gsel);
+unlock:
+ mutex_unlock(&pctrl->mutex);
done:
*index = idx;
kfree(configs);
@@ -417,7 +437,7 @@ static int rzg2l_dt_node_to_map(struct pinctrl_dev *pctldev,
index = 0;
for_each_child_of_node(np, child) {
- ret = rzg2l_dt_subnode_to_map(pctldev, child, map,
+ ret = rzg2l_dt_subnode_to_map(pctldev, child, np, map,
num_maps, &index);
if (ret < 0) {
of_node_put(child);
@@ -426,7 +446,7 @@ static int rzg2l_dt_node_to_map(struct pinctrl_dev *pctldev,
}
if (*num_maps == 0) {
- ret = rzg2l_dt_subnode_to_map(pctldev, np, map,
+ ret = rzg2l_dt_subnode_to_map(pctldev, np, NULL, map,
num_maps, &index);
if (ret < 0)
goto done;
@@ -1497,6 +1517,7 @@ static int rzg2l_pinctrl_probe(struct platform_device *pdev)
spin_lock_init(&pctrl->lock);
spin_lock_init(&pctrl->bitmap_lock);
+ mutex_init(&pctrl->mutex);
platform_set_drvdata(pdev, pctrl);
diff --git a/drivers/pinctrl/renesas/pinctrl-rzv2m.c b/drivers/pinctrl/renesas/pinctrl-rzv2m.c
index e5472293bc7f..9146101ea9e2 100644
--- a/drivers/pinctrl/renesas/pinctrl-rzv2m.c
+++ b/drivers/pinctrl/renesas/pinctrl-rzv2m.c
@@ -14,6 +14,7 @@
#include <linux/gpio/driver.h>
#include <linux/io.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/spinlock.h>
@@ -123,7 +124,8 @@ struct rzv2m_pinctrl {
struct gpio_chip gpio_chip;
struct pinctrl_gpio_range gpio_range;
- spinlock_t lock;
+ spinlock_t lock; /* lock read/write registers */
+ struct mutex mutex; /* serialize adding groups and functions */
};
static const unsigned int drv_1_8V_group2_uA[] = { 1800, 3800, 7800, 11000 };
@@ -209,6 +211,7 @@ static int rzv2m_map_add_config(struct pinctrl_map *map,
static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev,
struct device_node *np,
+ struct device_node *parent,
struct pinctrl_map **map,
unsigned int *num_maps,
unsigned int *index)
@@ -226,6 +229,7 @@ static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev,
struct property *prop;
int ret, gsel, fsel;
const char **pin_fn;
+ const char *name;
const char *pin;
pinmux = of_find_property(np, "pinmux", NULL);
@@ -309,28 +313,42 @@ static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev,
psel_val[i] = MUX_FUNC(value);
}
+ if (parent) {
+ name = devm_kasprintf(pctrl->dev, GFP_KERNEL, "%pOFn.%pOFn",
+ parent, np);
+ if (!name) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ } else {
+ name = np->name;
+ }
+
+ mutex_lock(&pctrl->mutex);
+
/* Register a single pin group listing all the pins we read from DT */
- gsel = pinctrl_generic_add_group(pctldev, np->name, pins, num_pinmux, NULL);
+ gsel = pinctrl_generic_add_group(pctldev, name, pins, num_pinmux, NULL);
if (gsel < 0) {
ret = gsel;
- goto done;
+ goto unlock;
}
/*
* Register a single group function where the 'data' is an array PSEL
* register values read from DT.
*/
- pin_fn[0] = np->name;
- fsel = pinmux_generic_add_function(pctldev, np->name, pin_fn, 1,
- psel_val);
+ pin_fn[0] = name;
+ fsel = pinmux_generic_add_function(pctldev, name, pin_fn, 1, psel_val);
if (fsel < 0) {
ret = fsel;
goto remove_group;
}
+ mutex_unlock(&pctrl->mutex);
+
maps[idx].type = PIN_MAP_TYPE_MUX_GROUP;
- maps[idx].data.mux.group = np->name;
- maps[idx].data.mux.function = np->name;
+ maps[idx].data.mux.group = name;
+ maps[idx].data.mux.function = name;
idx++;
dev_dbg(pctrl->dev, "Parsed %pOF with %d pins\n", np, num_pinmux);
@@ -339,6 +357,8 @@ static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev,
remove_group:
pinctrl_generic_remove_group(pctldev, gsel);
+unlock:
+ mutex_unlock(&pctrl->mutex);
done:
*index = idx;
kfree(configs);
@@ -377,7 +397,7 @@ static int rzv2m_dt_node_to_map(struct pinctrl_dev *pctldev,
index = 0;
for_each_child_of_node(np, child) {
- ret = rzv2m_dt_subnode_to_map(pctldev, child, map,
+ ret = rzv2m_dt_subnode_to_map(pctldev, child, np, map,
num_maps, &index);
if (ret < 0) {
of_node_put(child);
@@ -386,7 +406,7 @@ static int rzv2m_dt_node_to_map(struct pinctrl_dev *pctldev,
}
if (*num_maps == 0) {
- ret = rzv2m_dt_subnode_to_map(pctldev, np, map,
+ ret = rzv2m_dt_subnode_to_map(pctldev, np, NULL, map,
num_maps, &index);
if (ret < 0)
goto done;
@@ -1059,6 +1079,7 @@ static int rzv2m_pinctrl_probe(struct platform_device *pdev)
}
spin_lock_init(&pctrl->lock);
+ mutex_init(&pctrl->mutex);
platform_set_drvdata(pdev, pctrl);
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_i2c.c b/drivers/platform/chrome/cros_ec_i2c.c
index dbe698f33128..e29c51cbfd71 100644
--- a/drivers/platform/chrome/cros_ec_i2c.c
+++ b/drivers/platform/chrome/cros_ec_i2c.c
@@ -372,7 +372,7 @@ static struct i2c_driver cros_ec_driver = {
.of_match_table = of_match_ptr(cros_ec_i2c_of_match),
.pm = &cros_ec_i2c_pm_ops,
},
- .probe_new = cros_ec_i2c_probe,
+ .probe = cros_ec_i2c_probe,
.remove = cros_ec_i2c_remove,
.id_table = cros_ec_i2c_id,
};
diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
index 68bba0fcafab..500a61b093e4 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/interrupt.h>
+#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/platform_data/cros_ec_commands.h>
#include <linux/platform_data/cros_ec_proto.h>
@@ -315,6 +316,7 @@ static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset,
static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
{
+ static const char *env[] = { "ERROR=PANIC", NULL };
struct cros_ec_device *ec_dev = data;
bool ec_has_more_events;
int ret;
@@ -324,6 +326,7 @@ static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
if (value == ACPI_NOTIFY_CROS_EC_PANIC) {
dev_emerg(ec_dev->dev, "CrOS EC Panic Reported. Shutdown is imminent!");
blocking_notifier_call_chain(&ec_dev->panic_notifier, 0, ec_dev);
+ kobject_uevent_env(&ec_dev->dev->kobj, KOBJ_CHANGE, (char **)env);
/* Begin orderly shutdown. Force shutdown after 1 second. */
hw_protection_shutdown("CrOS EC Panic", 1000);
/* Do not query for other events after a panic is reported */
@@ -543,23 +546,25 @@ static const struct dmi_system_id cros_ec_lpc_dmi_table[] __initconst = {
MODULE_DEVICE_TABLE(dmi, cros_ec_lpc_dmi_table);
#ifdef CONFIG_PM_SLEEP
-static int cros_ec_lpc_suspend(struct device *dev)
+static int cros_ec_lpc_prepare(struct device *dev)
{
struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
return cros_ec_suspend(ec_dev);
}
-static int cros_ec_lpc_resume(struct device *dev)
+static void cros_ec_lpc_complete(struct device *dev)
{
struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
-
- return cros_ec_resume(ec_dev);
+ cros_ec_resume(ec_dev);
}
#endif
static const struct dev_pm_ops cros_ec_lpc_pm_ops = {
- SET_LATE_SYSTEM_SLEEP_PM_OPS(cros_ec_lpc_suspend, cros_ec_lpc_resume)
+#ifdef CONFIG_PM_SLEEP
+ .prepare = cros_ec_lpc_prepare,
+ .complete = cros_ec_lpc_complete
+#endif
};
static struct platform_driver cros_ec_lpc_driver = {
diff --git a/drivers/platform/chrome/cros_ec_spi.c b/drivers/platform/chrome/cros_ec_spi.c
index 21143dba8970..3e88cc92e819 100644
--- a/drivers/platform/chrome/cros_ec_spi.c
+++ b/drivers/platform/chrome/cros_ec_spi.c
@@ -104,13 +104,7 @@ static void debug_packet(struct device *dev, const char *name, u8 *ptr,
int len)
{
#ifdef DEBUG
- int i;
-
- dev_dbg(dev, "%s: ", name);
- for (i = 0; i < len; i++)
- pr_cont(" %02x", ptr[i]);
-
- pr_cont("\n");
+ dev_dbg(dev, "%s: %*ph\n", name, len, ptr);
#endif
}
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/chrome/cros_hps_i2c.c b/drivers/platform/chrome/cros_hps_i2c.c
index 62ccb1acb5de..b31313080332 100644
--- a/drivers/platform/chrome/cros_hps_i2c.c
+++ b/drivers/platform/chrome/cros_hps_i2c.c
@@ -143,7 +143,7 @@ MODULE_DEVICE_TABLE(acpi, hps_acpi_id);
#endif /* CONFIG_ACPI */
static struct i2c_driver hps_i2c_driver = {
- .probe_new = hps_i2c_probe,
+ .probe = hps_i2c_probe,
.remove = hps_i2c_remove,
.id_table = hps_i2c_id,
.driver = {
diff --git a/drivers/platform/chrome/cros_typec_switch.c b/drivers/platform/chrome/cros_typec_switch.c
index 752720483753..0eefdcf14d63 100644
--- a/drivers/platform/chrome/cros_typec_switch.c
+++ b/drivers/platform/chrome/cros_typec_switch.c
@@ -51,13 +51,18 @@ static int cros_typec_cmd_mux_set(struct cros_typec_switch_data *sdata, int port
static int cros_typec_get_mux_state(unsigned long mode, struct typec_altmode *alt)
{
int ret = -EOPNOTSUPP;
+ u8 pin_assign;
- if (mode == TYPEC_STATE_SAFE)
+ if (mode == TYPEC_STATE_SAFE) {
ret = USB_PD_MUX_SAFE_MODE;
- else if (mode == TYPEC_STATE_USB)
+ } else if (mode == TYPEC_STATE_USB) {
ret = USB_PD_MUX_USB_ENABLED;
- else if (alt && alt->svid == USB_TYPEC_DP_SID)
+ } else if (alt && alt->svid == USB_TYPEC_DP_SID) {
ret = USB_PD_MUX_DP_ENABLED;
+ pin_assign = mode - TYPEC_STATE_MODAL;
+ if (pin_assign & DP_PIN_ASSIGN_D)
+ ret |= USB_PD_MUX_USB_ENABLED;
+ }
return 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/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c
index a79318e90a13..b600b77d91ef 100644
--- a/drivers/platform/mellanox/mlxbf-tmfifo.c
+++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
@@ -887,6 +887,7 @@ static bool mlxbf_tmfifo_virtio_notify(struct virtqueue *vq)
tm_vdev = fifo->vdev[VIRTIO_ID_CONSOLE];
mlxbf_tmfifo_console_output(tm_vdev, vring);
spin_unlock_irqrestore(&fifo->spin_lock[0], flags);
+ set_bit(MLXBF_TM_TX_LWM_IRQ, &fifo->pend_events);
} else if (test_and_set_bit(MLXBF_TM_TX_LWM_IRQ,
&fifo->pend_events)) {
return true;
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/Makefile b/drivers/platform/x86/amd/Makefile
index 2c229198e24c..65732f0a3913 100644
--- a/drivers/platform/x86/amd/Makefile
+++ b/drivers/platform/x86/amd/Makefile
@@ -4,7 +4,7 @@
# AMD x86 Platform-Specific Drivers
#
-amd-pmc-y := pmc.o
+amd-pmc-y := pmc.o pmc-quirks.o
obj-$(CONFIG_AMD_PMC) += amd-pmc.o
amd_hsmp-y := hsmp.o
obj-$(CONFIG_AMD_HSMP) += amd_hsmp.o
diff --git a/drivers/platform/x86/amd/pmc-quirks.c b/drivers/platform/x86/amd/pmc-quirks.c
new file mode 100644
index 000000000000..ad702463a65d
--- /dev/null
+++ b/drivers/platform/x86/amd/pmc-quirks.c
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * AMD SoC Power Management Controller Driver Quirks
+ *
+ * Copyright (c) 2023, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Author: Mario Limonciello <mario.limonciello@amd.com>
+ */
+
+#include <linux/dmi.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+
+#include "pmc.h"
+
+struct quirk_entry {
+ u32 s2idle_bug_mmio;
+};
+
+static struct quirk_entry quirk_s2idle_bug = {
+ .s2idle_bug_mmio = 0xfed80380,
+};
+
+static const struct dmi_system_id fwbug_list[] = {
+ {
+ .ident = "L14 Gen2 AMD",
+ .driver_data = &quirk_s2idle_bug,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "20X5"),
+ }
+ },
+ {
+ .ident = "T14s Gen2 AMD",
+ .driver_data = &quirk_s2idle_bug,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "20XF"),
+ }
+ },
+ {
+ .ident = "X13 Gen2 AMD",
+ .driver_data = &quirk_s2idle_bug,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "20XH"),
+ }
+ },
+ {
+ .ident = "T14 Gen2 AMD",
+ .driver_data = &quirk_s2idle_bug,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "20XK"),
+ }
+ },
+ {
+ .ident = "T14 Gen1 AMD",
+ .driver_data = &quirk_s2idle_bug,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "20UD"),
+ }
+ },
+ {
+ .ident = "T14 Gen1 AMD",
+ .driver_data = &quirk_s2idle_bug,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "20UE"),
+ }
+ },
+ {
+ .ident = "T14s Gen1 AMD",
+ .driver_data = &quirk_s2idle_bug,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "20UH"),
+ }
+ },
+ {
+ .ident = "T14s Gen1 AMD",
+ .driver_data = &quirk_s2idle_bug,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "20UJ"),
+ }
+ },
+ {
+ .ident = "P14s Gen1 AMD",
+ .driver_data = &quirk_s2idle_bug,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"),
+ }
+ },
+ {
+ .ident = "P14s Gen2 AMD",
+ .driver_data = &quirk_s2idle_bug,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21A0"),
+ }
+ },
+ {
+ .ident = "P14s Gen2 AMD",
+ .driver_data = &quirk_s2idle_bug,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21A1"),
+ }
+ },
+ /* https://gitlab.freedesktop.org/drm/amd/-/issues/2684 */
+ {
+ .ident = "HP Laptop 15s-eq2xxx",
+ .driver_data = &quirk_s2idle_bug,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Laptop 15s-eq2xxx"),
+ }
+ },
+ {}
+};
+
+/*
+ * Laptops that run a SMI handler during the D3->D0 transition that occurs
+ * specifically when exiting suspend to idle which can cause
+ * large delays during resume when the IOMMU translation layer is enabled (the default
+ * behavior) for NVME devices:
+ *
+ * To avoid this firmware problem, skip the SMI handler on these machines before the
+ * D0 transition occurs.
+ */
+static void amd_pmc_skip_nvme_smi_handler(u32 s2idle_bug_mmio)
+{
+ void __iomem *addr;
+ u8 val;
+
+ if (!request_mem_region_muxed(s2idle_bug_mmio, 1, "amd_pmc_pm80"))
+ return;
+
+ addr = ioremap(s2idle_bug_mmio, 1);
+ if (!addr)
+ goto cleanup_resource;
+
+ val = ioread8(addr);
+ iowrite8(val & ~BIT(0), addr);
+
+ iounmap(addr);
+cleanup_resource:
+ release_mem_region(s2idle_bug_mmio, 1);
+}
+
+void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev)
+{
+ if (dev->quirks && dev->quirks->s2idle_bug_mmio)
+ amd_pmc_skip_nvme_smi_handler(dev->quirks->s2idle_bug_mmio);
+}
+
+void amd_pmc_quirks_init(struct amd_pmc_dev *dev)
+{
+ const struct dmi_system_id *dmi_id;
+
+ dmi_id = dmi_first_match(fwbug_list);
+ if (!dmi_id)
+ return;
+ dev->quirks = dmi_id->driver_data;
+ if (dev->quirks->s2idle_bug_mmio)
+ pr_info("Using s2idle quirk to avoid %s platform firmware bug\n",
+ dmi_id->ident);
+}
diff --git a/drivers/platform/x86/amd/pmc.c b/drivers/platform/x86/amd/pmc.c
index 427905714f79..c1e788b67a74 100644
--- a/drivers/platform/x86/amd/pmc.c
+++ b/drivers/platform/x86/amd/pmc.c
@@ -28,6 +28,8 @@
#include <linux/seq_file.h>
#include <linux/uaccess.h>
+#include "pmc.h"
+
/* SMU communication registers */
#define AMD_PMC_REGISTER_MESSAGE 0x538
#define AMD_PMC_REGISTER_RESPONSE 0x980
@@ -45,7 +47,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
@@ -95,11 +96,11 @@
#define AMD_CPU_ID_CB 0x14D8
#define AMD_CPU_ID_PS 0x14E8
#define AMD_CPU_ID_SP 0x14A4
+#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507
#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 +116,7 @@ enum s2d_arg {
S2D_PHYS_ADDR_LOW,
S2D_PHYS_ADDR_HIGH,
S2D_NUM_SAMPLES,
+ S2D_DRAM_SIZE,
};
struct amd_pmc_bit_map {
@@ -132,32 +134,21 @@ 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)},
{}
};
-struct amd_pmc_dev {
- void __iomem *regbase;
- void __iomem *smu_virt_addr;
- void __iomem *stb_virt_addr;
- void __iomem *fch_virt_addr;
- bool msg_port;
- u32 base_addr;
- u32 cpu_id;
- u32 active_ips;
-/* SMU version information */
- u8 smu_program;
- u8 major;
- u8 minor;
- u8 rev;
- struct device *dev;
- struct pci_dev *rdev;
- struct mutex lock; /* generic mutex lock */
- struct dentry *dbgfs_dir;
-};
-
static bool enable_stb;
module_param(enable_stb, bool, 0644);
MODULE_PARM_DESC(enable_stb, "Enable the STB debug mechanism");
@@ -194,8 +185,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 +252,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 +299,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 +325,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 +343,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 +385,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 +477,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]);
@@ -543,7 +551,7 @@ static int amd_pmc_idlemask_read(struct amd_pmc_dev *pdev, struct device *dev,
}
if (dev)
- dev_dbg(pdev->dev, "SMU idlemask s0i3: 0x%x\n", val);
+ pm_pr_dbg("SMU idlemask s0i3: 0x%x\n", val);
if (s)
seq_printf(s, "SMU idlemask : 0x%x\n", val);
@@ -562,6 +570,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 +593,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
@@ -769,7 +788,7 @@ static int amd_pmc_verify_czn_rtc(struct amd_pmc_dev *pdev, u32 *arg)
*arg |= (duration << 16);
rc = rtc_alarm_irq_enable(rtc_device, 0);
- dev_dbg(pdev->dev, "wakeup timer programmed for %lld seconds\n", duration);
+ pm_pr_dbg("wakeup timer programmed for %lld seconds\n", duration);
return rc;
}
@@ -794,7 +813,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 +848,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 +858,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);
@@ -852,6 +871,8 @@ static void amd_pmc_s2idle_restore(void)
/* Notify on failed entry */
amd_pmc_validate_deepest(pdev);
+
+ amd_pmc_process_restore_quirks(pdev);
}
static struct acpi_s2idle_dev_ops amd_pmc_s2idle_dev_ops = {
@@ -887,32 +908,69 @@ static const struct pci_device_id pmc_pci_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PCO) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RV) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_SP) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) },
{ }
};
+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 +1059,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;
@@ -1012,6 +1070,8 @@ static int amd_pmc_probe(struct platform_device *pdev)
err = acpi_register_lps0_dev(&amd_pmc_s2idle_dev_ops);
if (err)
dev_warn(dev->dev, "failed to register LPS0 sleep handler, expect increased power consumption\n");
+ if (!disable_workarounds)
+ amd_pmc_quirks_init(dev);
}
amd_pmc_dbgfs_register(dev);
@@ -1040,6 +1100,7 @@ static const struct acpi_device_id amd_pmc_acpi_ids[] = {
{"AMDI0007", 0},
{"AMDI0008", 0},
{"AMDI0009", 0},
+ {"AMDI000A", 0},
{"AMD0004", 0},
{"AMD0005", 0},
{ }
diff --git a/drivers/platform/x86/amd/pmc.h b/drivers/platform/x86/amd/pmc.h
new file mode 100644
index 000000000000..c27bd6a5642f
--- /dev/null
+++ b/drivers/platform/x86/amd/pmc.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * AMD SoC Power Management Controller Driver
+ *
+ * Copyright (c) 2023, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Author: Mario Limonciello <mario.limonciello@amd.com>
+ */
+
+#ifndef PMC_H
+#define PMC_H
+
+#include <linux/types.h>
+#include <linux/mutex.h>
+
+struct amd_pmc_dev {
+ void __iomem *regbase;
+ void __iomem *smu_virt_addr;
+ void __iomem *stb_virt_addr;
+ void __iomem *fch_virt_addr;
+ bool msg_port;
+ 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;
+ u8 minor;
+ u8 rev;
+ struct device *dev;
+ struct pci_dev *rdev;
+ struct mutex lock; /* generic mutex lock */
+ struct dentry *dbgfs_dir;
+ struct quirk_entry *quirks;
+};
+
+void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev);
+void amd_pmc_quirks_init(struct amd_pmc_dev *dev);
+
+#endif /* PMC_H */
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/acpi.c b/drivers/platform/x86/amd/pmf/acpi.c
index 081e84e116e7..3fc5e4547d9f 100644
--- a/drivers/platform/x86/amd/pmf/acpi.c
+++ b/drivers/platform/x86/amd/pmf/acpi.c
@@ -106,6 +106,27 @@ int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev,
data, sizeof(*data));
}
+int apmf_os_power_slider_update(struct amd_pmf_dev *pdev, u8 event)
+{
+ struct os_power_slider args;
+ struct acpi_buffer params;
+ union acpi_object *info;
+ int err = 0;
+
+ args.size = sizeof(args);
+ args.slider_event = event;
+
+ params.length = sizeof(args);
+ params.pointer = (void *)&args;
+
+ info = apmf_if_call(pdev, APMF_FUNC_OS_POWER_SLIDER_UPDATE, &params);
+ if (!info)
+ err = -EIO;
+
+ kfree(info);
+ return err;
+}
+
static void apmf_sbios_heartbeat_notify(struct work_struct *work)
{
struct amd_pmf_dev *dev = container_of(work, struct amd_pmf_dev, heart_beat.work);
@@ -289,7 +310,7 @@ int apmf_acpi_init(struct amd_pmf_dev *pmf_dev)
ret = apmf_get_system_params(pmf_dev);
if (ret) {
- dev_err(pmf_dev->dev, "APMF apmf_get_system_params failed :%d\n", ret);
+ dev_dbg(pmf_dev->dev, "APMF apmf_get_system_params failed :%d\n", ret);
goto out;
}
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/core.c b/drivers/platform/x86/amd/pmf/core.c
index 7780705917b7..57bf1a9f0e76 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -40,6 +40,7 @@
/* List of supported CPU ids */
#define AMD_CPU_ID_RMB 0x14b5
#define AMD_CPU_ID_PS 0x14e8
+#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507
#define PMF_MSG_DELAY_MIN_US 50
#define RESPONSE_REGISTER_LOOP_MAX 20000
@@ -71,7 +72,11 @@ static int amd_pmf_pwr_src_notify_call(struct notifier_block *nb, unsigned long
return NOTIFY_DONE;
}
- amd_pmf_set_sps_power_limits(pmf);
+ if (is_apmf_func_supported(pmf, APMF_FUNC_STATIC_SLIDER_GRANULAR))
+ amd_pmf_set_sps_power_limits(pmf);
+
+ if (is_apmf_func_supported(pmf, APMF_FUNC_OS_POWER_SLIDER_UPDATE))
+ amd_pmf_power_slider_update_event(pmf);
return NOTIFY_OK;
}
@@ -242,6 +247,7 @@ out_unlock:
static const struct pci_device_id pmf_pci_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RMB) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) },
{ }
};
@@ -295,7 +301,8 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
int ret;
/* Enable Static Slider */
- if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
+ if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR) ||
+ is_apmf_func_supported(dev, APMF_FUNC_OS_POWER_SLIDER_UPDATE)) {
amd_pmf_init_sps(dev);
dev->pwr_src_notifier.notifier_call = amd_pmf_pwr_src_notify_call;
power_supply_reg_notifier(&dev->pwr_src_notifier);
@@ -333,6 +340,7 @@ static void amd_pmf_deinit_features(struct amd_pmf_dev *dev)
static const struct acpi_device_id amd_pmf_acpi_ids[] = {
{"AMDI0100", 0x100},
{"AMDI0102", 0},
+ {"AMDI0103", 0},
{ }
};
MODULE_DEVICE_TABLE(acpi, amd_pmf_acpi_ids);
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 06c30cdc0573..deba88e6e4c8 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -21,6 +21,7 @@
#define APMF_FUNC_SBIOS_HEARTBEAT 4
#define APMF_FUNC_AUTO_MODE 5
#define APMF_FUNC_SET_FAN_IDX 7
+#define APMF_FUNC_OS_POWER_SLIDER_UPDATE 8
#define APMF_FUNC_STATIC_SLIDER_GRANULAR 9
#define APMF_FUNC_DYN_SLIDER_AC 11
#define APMF_FUNC_DYN_SLIDER_DC 12
@@ -44,6 +45,14 @@
#define GET_STT_LIMIT_APU 0x20
#define GET_STT_LIMIT_HS2 0x21
+/* OS slider update notification */
+#define DC_BEST_PERF 0
+#define DC_BETTER_PERF 1
+#define DC_BATTERY_SAVER 3
+#define AC_BEST_PERF 4
+#define AC_BETTER_PERF 5
+#define AC_BETTER_BATTERY 6
+
/* Fan Index for Auto Mode */
#define FAN_INDEX_AUTO 0xFFFFFFFF
@@ -193,6 +202,11 @@ struct amd_pmf_static_slider_granular {
struct apmf_sps_prop_granular prop[POWER_SOURCE_MAX][POWER_MODE_MAX];
};
+struct os_power_slider {
+ u16 size;
+ u8 slider_event;
+} __packed;
+
struct fan_table_control {
bool manual;
unsigned long fan_id;
@@ -383,6 +397,7 @@ int amd_pmf_send_cmd(struct amd_pmf_dev *dev, u8 message, bool get, u32 arg, u32
int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev);
int amd_pmf_get_power_source(void);
int apmf_install_handler(struct amd_pmf_dev *pmf_dev);
+int apmf_os_power_slider_update(struct amd_pmf_dev *dev, u8 flag);
/* SPS Layer */
int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf);
@@ -393,6 +408,7 @@ void amd_pmf_deinit_sps(struct amd_pmf_dev *dev);
int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev,
struct apmf_static_slider_granular_output *output);
bool is_pprof_balanced(struct amd_pmf_dev *pmf);
+int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev);
int apmf_update_fan_idx(struct amd_pmf_dev *pdev, bool manual, u32 idx);
diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
index bed762d47a14..a70e67749be3 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,
@@ -119,14 +174,78 @@ int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf)
return mode;
}
+int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev)
+{
+ u8 flag = 0;
+ int mode;
+ int src;
+
+ mode = amd_pmf_get_pprof_modes(dev);
+ if (mode < 0)
+ return mode;
+
+ src = amd_pmf_get_power_source();
+
+ if (src == POWER_SOURCE_AC) {
+ switch (mode) {
+ case POWER_MODE_PERFORMANCE:
+ flag |= BIT(AC_BEST_PERF);
+ break;
+ case POWER_MODE_BALANCED_POWER:
+ flag |= BIT(AC_BETTER_PERF);
+ break;
+ case POWER_MODE_POWER_SAVER:
+ flag |= BIT(AC_BETTER_BATTERY);
+ break;
+ default:
+ dev_err(dev->dev, "unsupported platform profile\n");
+ return -EOPNOTSUPP;
+ }
+
+ } else if (src == POWER_SOURCE_DC) {
+ switch (mode) {
+ case POWER_MODE_PERFORMANCE:
+ flag |= BIT(DC_BEST_PERF);
+ break;
+ case POWER_MODE_BALANCED_POWER:
+ flag |= BIT(DC_BETTER_PERF);
+ break;
+ case POWER_MODE_POWER_SAVER:
+ flag |= BIT(DC_BATTERY_SAVER);
+ break;
+ default:
+ dev_err(dev->dev, "unsupported platform profile\n");
+ return -EOPNOTSUPP;
+ }
+ }
+
+ apmf_os_power_slider_update(dev, flag);
+
+ return 0;
+}
+
static int amd_pmf_profile_set(struct platform_profile_handler *pprof,
enum platform_profile_option profile)
{
struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);
+ int ret = 0;
pmf->current_profile = profile;
- return amd_pmf_set_sps_power_limits(pmf);
+ /* Notify EC about the slider position change */
+ if (is_apmf_func_supported(pmf, APMF_FUNC_OS_POWER_SLIDER_UPDATE)) {
+ ret = amd_pmf_power_slider_update_event(pmf);
+ if (ret)
+ return ret;
+ }
+
+ if (is_apmf_func_supported(pmf, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
+ ret = amd_pmf_set_sps_power_limits(pmf);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
}
int amd_pmf_init_sps(struct amd_pmf_dev *dev)
@@ -134,10 +253,13 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
int err;
dev->current_profile = PLATFORM_PROFILE_BALANCED;
- amd_pmf_load_defaults_sps(dev);
- /* update SPS balanced power mode thermals */
- amd_pmf_set_sps_power_limits(dev);
+ if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
+ amd_pmf_load_defaults_sps(dev);
+
+ /* update SPS balanced power mode thermals */
+ amd_pmf_set_sps_power_limits(dev);
+ }
dev->pprof.profile_get = amd_pmf_profile_get;
dev->pprof.profile_set = amd_pmf_profile_set;
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/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 1038dfdcdd32..8bef66a2f0ce 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -738,13 +738,23 @@ static ssize_t kbd_rgb_mode_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- u32 cmd, mode, r, g, b, speed;
+ u32 cmd, mode, r, g, b, speed;
int err;
if (sscanf(buf, "%d %d %d %d %d %d", &cmd, &mode, &r, &g, &b, &speed) != 6)
return -EINVAL;
- cmd = !!cmd;
+ /* B3 is set and B4 is save to BIOS */
+ switch (cmd) {
+ case 0:
+ cmd = 0xb3;
+ break;
+ case 1:
+ cmd = 0xb4;
+ break;
+ default:
+ return -EINVAL;
+ }
/* These are the known usable modes across all TUF/ROG */
if (mode >= 12 || mode == 9)
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-ddv.c b/drivers/platform/x86/dell/dell-wmi-ddv.c
index 2750dee99c3e..db1e9240dd02 100644
--- a/drivers/platform/x86/dell/dell-wmi-ddv.c
+++ b/drivers/platform/x86/dell/dell-wmi-ddv.c
@@ -616,7 +616,8 @@ static int dell_wmi_ddv_hwmon_add(struct dell_wmi_ddv_data *data)
}
if (index < 2) {
- ret = -ENODEV;
+ /* Finding no available sensors is not an error */
+ ret = 0;
goto err_release;
}
@@ -841,13 +842,13 @@ static int dell_wmi_ddv_probe(struct wmi_device *wdev, const void *context)
if (IS_REACHABLE(CONFIG_ACPI_BATTERY)) {
ret = dell_wmi_ddv_battery_add(data);
- if (ret < 0 && ret != -ENODEV)
+ if (ret < 0)
dev_warn(&wdev->dev, "Unable to register ACPI battery hook: %d\n", ret);
}
if (IS_REACHABLE(CONFIG_HWMON)) {
ret = dell_wmi_ddv_hwmon_add(data);
- if (ret < 0 && ret != -ENODEV)
+ if (ret < 0)
dev_warn(&wdev->dev, "Unable to register hwmon interface: %d\n", ret);
}
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/huawei-wmi.c b/drivers/platform/x86/huawei-wmi.c
index 70e5c4c0574d..0ef1c46b617b 100644
--- a/drivers/platform/x86/huawei-wmi.c
+++ b/drivers/platform/x86/huawei-wmi.c
@@ -85,6 +85,8 @@ static const struct key_entry huawei_wmi_keymap[] = {
{ KE_IGNORE, 0x293, { KEY_KBDILLUMTOGGLE } },
{ KE_IGNORE, 0x294, { KEY_KBDILLUMUP } },
{ KE_IGNORE, 0x295, { KEY_KBDILLUMUP } },
+ // Ignore Ambient Light Sensoring
+ { KE_KEY, 0x2c1, { KEY_RESERVED } },
{ KE_END, 0 }
};
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index d2fee9a3e239..6d9297c1d96c 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -1049,6 +1049,11 @@ static const struct key_entry ideapad_keymap[] = {
{ KE_IGNORE, 0x03 | IDEAPAD_WMI_KEY },
/* Customizable Lenovo Hotkey ("star" with 'S' inside) */
{ KE_KEY, 0x01 | IDEAPAD_WMI_KEY, { KEY_FAVORITES } },
+ { KE_KEY, 0x04 | IDEAPAD_WMI_KEY, { KEY_SELECTIVE_SCREENSHOT } },
+ /* Lenovo Support */
+ { KE_KEY, 0x07 | IDEAPAD_WMI_KEY, { KEY_HELP } },
+ { KE_KEY, 0x0e | IDEAPAD_WMI_KEY, { KEY_PICKUP_PHONE } },
+ { KE_KEY, 0x0f | IDEAPAD_WMI_KEY, { KEY_HANGUP_PHONE } },
/* Dark mode toggle */
{ KE_KEY, 0x13 | IDEAPAD_WMI_KEY, { KEY_PROG1 } },
/* Sound profile switch */
diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c
index 5632bd3c534a..7457ca2b27a6 100644
--- a/drivers/platform/x86/intel/hid.c
+++ b/drivers/platform/x86/intel/hid.c
@@ -150,6 +150,12 @@ static const struct dmi_system_id dmi_vgbs_allow_list[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go"),
},
},
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Elite Dragonfly G2 Notebook PC"),
+ },
+ },
{ }
};
@@ -620,7 +626,7 @@ static bool button_array_present(struct platform_device *device)
static int intel_hid_probe(struct platform_device *device)
{
acpi_handle handle = ACPI_HANDLE(&device->dev);
- unsigned long long mode;
+ unsigned long long mode, dummy;
struct intel_hid_priv *priv;
acpi_status status;
int err;
@@ -692,18 +698,15 @@ static int intel_hid_probe(struct platform_device *device)
if (err)
goto err_remove_notify;
- if (priv->array) {
- unsigned long long dummy;
+ intel_button_array_enable(&device->dev, true);
- intel_button_array_enable(&device->dev, true);
-
- /* Call button load method to enable HID power button */
- if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN,
- &dummy)) {
- dev_warn(&device->dev,
- "failed to enable HID power button\n");
- }
- }
+ /*
+ * Call button load method to enable HID power button
+ * Always do this since it activates events on some devices without
+ * a button array too.
+ */
+ if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN, &dummy))
+ dev_warn(&device->dev, "failed to enable HID power button\n");
device_init_wakeup(&device->dev, true);
/*
diff --git a/drivers/platform/x86/intel/int3472/clk_and_regulator.c b/drivers/platform/x86/intel/int3472/clk_and_regulator.c
index 399f0623ca1b..ef4b3141efcd 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.
+ */
+static 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..a95004e3d80b 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
@@ -335,8 +335,8 @@ static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn
node = dev_to_node(&_pci_dev->dev);
if (node == NUMA_NO_NODE) {
- pr_info("Fail to get numa node for CPU:%d bus:%d dev:%d fn:%d\n",
- cpu, bus_no, dev, fn);
+ pr_info_once("Fail to get numa node for CPU:%d bus:%d dev:%d fn:%d\n",
+ cpu, bus_no, dev, fn);
continue;
}
@@ -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..d1fd6e69401c 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,9 +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->vsec_offset = pfs_start + pfs->pfs_header.cap_offset;
+ pfs->vsec_offset = pfs_start + pfs->pfs_header.cap_offset * TPMI_CAP_OFFSET_UNIT;
/*
* Process TPMI_INFO to get PCI device to CPU package ID.
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-ymc.c b/drivers/platform/x86/lenovo-ymc.c
index 41676188b373..e1fbc35504d4 100644
--- a/drivers/platform/x86/lenovo-ymc.c
+++ b/drivers/platform/x86/lenovo-ymc.c
@@ -24,6 +24,10 @@ static bool ec_trigger __read_mostly;
module_param(ec_trigger, bool, 0444);
MODULE_PARM_DESC(ec_trigger, "Enable EC triggering work-around to force emitting tablet mode events");
+static bool force;
+module_param(force, bool, 0444);
+MODULE_PARM_DESC(force, "Force loading on boards without a convertible DMI chassis-type");
+
static const struct dmi_system_id ec_trigger_quirk_dmi_table[] = {
{
/* Lenovo Yoga 7 14ARB7 */
@@ -32,6 +36,27 @@ static const struct dmi_system_id ec_trigger_quirk_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "82QF"),
},
},
+ {
+ /* Lenovo Yoga 7 14ACN6 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "82N7"),
+ },
+ },
+ { }
+};
+
+static const struct dmi_system_id allowed_chasis_types_dmi_table[] = {
+ {
+ .matches = {
+ DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "31" /* Convertible */),
+ },
+ },
+ {
+ .matches = {
+ DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "32" /* Detachable */),
+ },
+ },
{ }
};
@@ -111,6 +136,13 @@ static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx)
struct input_dev *input_dev;
int err;
+ if (!dmi_check_system(allowed_chasis_types_dmi_table)) {
+ if (force)
+ dev_info(&wdev->dev, "Force loading Lenovo YMC support\n");
+ else
+ return -ENODEV;
+ }
+
ec_trigger |= dmi_check_system(ec_trigger_quirk_dmi_table);
priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
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/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
index 67367f010139..7d33977d9c60 100644
--- a/drivers/platform/x86/mlx-platform.c
+++ b/drivers/platform/x86/mlx-platform.c
@@ -62,10 +62,6 @@
#define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET 0x37
#define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a
#define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET 0x3b
-#define MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET 0x3c
-#define MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET 0x3d
-#define MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET 0x3e
-#define MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET 0x3f
#define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40
#define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET 0x41
#define MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET 0x42
@@ -126,6 +122,10 @@
#define MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET 0xaa
#define MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET 0xab
#define MLXPLAT_CPLD_LPC_REG_LC_PWR_ON 0xb2
+#define MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET 0xb6
+#define MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET 0xb7
+#define MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET 0xb8
+#define MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET 0xb9
#define MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET 0xc2
#define MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT 0xc3
#define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET 0xc7
@@ -222,7 +222,7 @@
MLXPLAT_CPLD_AGGR_MASK_LC_SDWN)
#define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc1
#define MLXPLAT_CPLD_LOW_AGGR_MASK_ASIC2 BIT(2)
-#define MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT BIT(4)
+#define MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT GENMASK(5, 4)
#define MLXPLAT_CPLD_LOW_AGGR_MASK_I2C BIT(6)
#define MLXPLAT_CPLD_PSU_MASK GENMASK(1, 0)
#define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0)
@@ -237,7 +237,7 @@
#define MLXPLAT_CPLD_GWP_MASK GENMASK(0, 0)
#define MLXPLAT_CPLD_EROT_MASK GENMASK(1, 0)
#define MLXPLAT_CPLD_PWR_BUTTON_MASK BIT(0)
-#define MLXPLAT_CPLD_LATCH_RST_MASK BIT(5)
+#define MLXPLAT_CPLD_LATCH_RST_MASK BIT(6)
#define MLXPLAT_CPLD_THERMAL1_PDB_MASK BIT(3)
#define MLXPLAT_CPLD_THERMAL2_PDB_MASK BIT(4)
#define MLXPLAT_CPLD_INTRUSION_MASK BIT(6)
@@ -2356,7 +2356,7 @@ mlxplat_mlxcpld_l1_switch_pwr_events_handler(void *handle, enum mlxreg_hotplug_k
u8 action)
{
dev_info(&mlxplat_dev->dev, "System shutdown due to short press of power button");
- kernel_halt();
+ kernel_power_off();
return 0;
}
@@ -2475,7 +2475,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_l1_switch_events_items[] = {
.reg = MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET,
.mask = MLXPLAT_CPLD_PWR_BUTTON_MASK,
.count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_pwr_events_items_data),
- .inversed = 0,
+ .inversed = 1,
.health = false,
},
{
@@ -2484,7 +2484,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_l1_switch_events_items[] = {
.reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET,
.mask = MLXPLAT_CPLD_L1_CHA_HEALTH_MASK,
.count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_health_events_items_data),
- .inversed = 0,
+ .inversed = 1,
.health = false,
.ind = 8,
},
@@ -3677,7 +3677,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
{
.label = "latch_reset",
.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
- .mask = GENMASK(7, 0) & ~BIT(5),
+ .mask = GENMASK(7, 0) & ~BIT(6),
.mode = 0200,
},
{
@@ -6238,8 +6238,6 @@ static void mlxplat_i2c_mux_topolgy_exit(struct mlxplat_priv *priv)
if (priv->pdev_mux[i])
platform_device_unregister(priv->pdev_mux[i]);
}
-
- mlxplat_post_exit();
}
static int mlxplat_i2c_main_complition_notify(void *handle, int id)
@@ -6369,6 +6367,7 @@ static void __exit mlxplat_exit(void)
pm_power_off = NULL;
mlxplat_pre_exit(priv);
mlxplat_i2c_main_exit(priv);
+ mlxplat_post_exit();
}
module_exit(mlxplat_exit);
diff --git a/drivers/platform/x86/msi-ec.c b/drivers/platform/x86/msi-ec.c
index ff93986e3d35..f26a3121092f 100644
--- a/drivers/platform/x86/msi-ec.c
+++ b/drivers/platform/x86/msi-ec.c
@@ -27,15 +27,15 @@
#include <linux/seq_file.h>
#include <linux/string.h>
-static const char *const SM_ECO_NAME = "eco";
-static const char *const SM_COMFORT_NAME = "comfort";
-static const char *const SM_SPORT_NAME = "sport";
-static const char *const SM_TURBO_NAME = "turbo";
-
-static const char *const FM_AUTO_NAME = "auto";
-static const char *const FM_SILENT_NAME = "silent";
-static const char *const FM_BASIC_NAME = "basic";
-static const char *const FM_ADVANCED_NAME = "advanced";
+#define SM_ECO_NAME "eco"
+#define SM_COMFORT_NAME "comfort"
+#define SM_SPORT_NAME "sport"
+#define SM_TURBO_NAME "turbo"
+
+#define FM_AUTO_NAME "auto"
+#define FM_SILENT_NAME "silent"
+#define FM_BASIC_NAME "basic"
+#define FM_ADVANCED_NAME "advanced"
static const char * const ALLOWED_FW_0[] __initconst = {
"14C1EMS1.012",
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index 6b18ec543ac3..f4c6c36e05a5 100644
--- a/drivers/platform/x86/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
@@ -208,7 +208,7 @@ static ssize_t set_device_state(const char *buf, size_t count, u8 mask)
return -EINVAL;
if (quirks->ec_read_only)
- return -EOPNOTSUPP;
+ return 0;
/* read current device state */
result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata);
@@ -838,15 +838,15 @@ static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str,
static void msi_init_rfkill(struct work_struct *ignored)
{
if (rfk_wlan) {
- rfkill_set_sw_state(rfk_wlan, !wlan_s);
+ msi_rfkill_set_state(rfk_wlan, !wlan_s);
rfkill_wlan_set(NULL, !wlan_s);
}
if (rfk_bluetooth) {
- rfkill_set_sw_state(rfk_bluetooth, !bluetooth_s);
+ msi_rfkill_set_state(rfk_bluetooth, !bluetooth_s);
rfkill_bluetooth_set(NULL, !bluetooth_s);
}
if (rfk_threeg) {
- rfkill_set_sw_state(rfk_threeg, !threeg_s);
+ msi_rfkill_set_state(rfk_threeg, !threeg_s);
rfkill_threeg_set(NULL, !threeg_s);
}
}
diff --git a/drivers/platform/x86/serial-multi-instantiate.c b/drivers/platform/x86/serial-multi-instantiate.c
index f3dcbdd72fec..8158e3cf5d6d 100644
--- a/drivers/platform/x86/serial-multi-instantiate.c
+++ b/drivers/platform/x86/serial-multi-instantiate.c
@@ -21,6 +21,7 @@
#define IRQ_RESOURCE_NONE 0
#define IRQ_RESOURCE_GPIO 1
#define IRQ_RESOURCE_APIC 2
+#define IRQ_RESOURCE_AUTO 3
enum smi_bus_type {
SMI_I2C,
@@ -52,6 +53,18 @@ static int smi_get_irq(struct platform_device *pdev, struct acpi_device *adev,
int ret;
switch (inst->flags & IRQ_RESOURCE_TYPE) {
+ case IRQ_RESOURCE_AUTO:
+ ret = acpi_dev_gpio_irq_get(adev, inst->irq_idx);
+ if (ret > 0) {
+ dev_dbg(&pdev->dev, "Using gpio irq\n");
+ break;
+ }
+ ret = platform_get_irq(pdev, inst->irq_idx);
+ if (ret > 0) {
+ dev_dbg(&pdev->dev, "Using platform irq\n");
+ break;
+ }
+ break;
case IRQ_RESOURCE_GPIO:
ret = acpi_dev_gpio_irq_get(adev, inst->irq_idx);
break;
@@ -307,10 +320,23 @@ static const struct smi_node int3515_data = {
static const struct smi_node cs35l41_hda = {
.instances = {
- { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
- { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
- { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
- { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
+ { "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
+ { "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
+ { "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
+ { "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
+ {}
+ },
+ .bus_type = SMI_AUTO_DETECT,
+};
+
+static const struct smi_node cs35l56_hda = {
+ .instances = {
+ { "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
+ { "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
+ { "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
+ { "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
+ /* a 5th entry is an alias address, not a real device */
+ { "cs35l56-hda_dummy_dev" },
{}
},
.bus_type = SMI_AUTO_DETECT,
@@ -324,6 +350,7 @@ static const struct acpi_device_id smi_acpi_ids[] = {
{ "BSG1160", (unsigned long)&bsg1160_data },
{ "BSG2150", (unsigned long)&bsg2150_data },
{ "CSC3551", (unsigned long)&cs35l41_hda },
+ { "CSC3556", (unsigned long)&cs35l56_hda },
{ "INT3515", (unsigned long)&int3515_data },
/* Non-conforming _HID for Cirrus Logic already released */
{ "CLSA0100", (unsigned long)&cs35l41_hda },
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..79346881cadb 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;
}
@@ -713,12 +719,12 @@ static ssize_t cert_to_password_store(struct kobject *kobj,
/* Format: 'Password,Signature' */
auth_str = kasprintf(GFP_KERNEL, "%s,%s", passwd, setting->signature);
if (!auth_str) {
- kfree(passwd);
+ kfree_sensitive(passwd);
return -ENOMEM;
}
ret = tlmi_simple_call(LENOVO_CERT_TO_PASSWORD_GUID, auth_str);
kfree(auth_str);
- kfree(passwd);
+ kfree_sensitive(passwd);
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..ad460417f901 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -315,17 +315,12 @@ struct ibm_init_struct {
/* DMI Quirks */
struct quirk_entry {
bool btusb_bug;
- u32 s2idle_bug_mmio;
};
static struct quirk_entry quirk_btusb_bug = {
.btusb_bug = true,
};
-static struct quirk_entry quirk_s2idle_bug = {
- .s2idle_bug_mmio = 0xfed80380,
-};
-
static struct {
u32 bluetooth:1;
u32 hotkey:1;
@@ -4422,136 +4417,9 @@ static const struct dmi_system_id fwbug_list[] __initconst = {
DMI_MATCH(DMI_BOARD_NAME, "20MV"),
},
},
- {
- .ident = "L14 Gen2 AMD",
- .driver_data = &quirk_s2idle_bug,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "20X5"),
- }
- },
- {
- .ident = "T14s Gen2 AMD",
- .driver_data = &quirk_s2idle_bug,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "20XF"),
- }
- },
- {
- .ident = "X13 Gen2 AMD",
- .driver_data = &quirk_s2idle_bug,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "20XH"),
- }
- },
- {
- .ident = "T14 Gen2 AMD",
- .driver_data = &quirk_s2idle_bug,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "20XK"),
- }
- },
- {
- .ident = "T14 Gen1 AMD",
- .driver_data = &quirk_s2idle_bug,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "20UD"),
- }
- },
- {
- .ident = "T14 Gen1 AMD",
- .driver_data = &quirk_s2idle_bug,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "20UE"),
- }
- },
- {
- .ident = "T14s Gen1 AMD",
- .driver_data = &quirk_s2idle_bug,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "20UH"),
- }
- },
- {
- .ident = "T14s Gen1 AMD",
- .driver_data = &quirk_s2idle_bug,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "20UJ"),
- }
- },
- {
- .ident = "P14s Gen1 AMD",
- .driver_data = &quirk_s2idle_bug,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"),
- }
- },
- {
- .ident = "P14s Gen2 AMD",
- .driver_data = &quirk_s2idle_bug,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "21A0"),
- }
- },
- {
- .ident = "P14s Gen2 AMD",
- .driver_data = &quirk_s2idle_bug,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "21A1"),
- }
- },
{}
};
-#ifdef CONFIG_SUSPEND
-/*
- * Lenovo laptops from a variety of generations run a SMI handler during the D3->D0
- * transition that occurs specifically when exiting suspend to idle which can cause
- * large delays during resume when the IOMMU translation layer is enabled (the default
- * behavior) for NVME devices:
- *
- * To avoid this firmware problem, skip the SMI handler on these machines before the
- * D0 transition occurs.
- */
-static void thinkpad_acpi_amd_s2idle_restore(void)
-{
- struct resource *res;
- void __iomem *addr;
- u8 val;
-
- res = request_mem_region_muxed(tp_features.quirks->s2idle_bug_mmio, 1,
- "thinkpad_acpi_pm80");
- if (!res)
- return;
-
- addr = ioremap(tp_features.quirks->s2idle_bug_mmio, 1);
- if (!addr)
- goto cleanup_resource;
-
- val = ioread8(addr);
- iowrite8(val & ~BIT(0), addr);
-
- iounmap(addr);
-cleanup_resource:
- release_resource(res);
- kfree(res);
-}
-
-static struct acpi_s2idle_dev_ops thinkpad_acpi_s2idle_dev_ops = {
- .restore = thinkpad_acpi_amd_s2idle_restore,
-};
-#endif
-
static const struct pci_device_id fwbug_cards_ids[] __initconst = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x24F3) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x24FD) },
@@ -10524,8 +10392,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 +10406,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)
@@ -11666,10 +11536,6 @@ static void thinkpad_acpi_module_exit(void)
tpacpi_lifecycle = TPACPI_LIFE_EXITING;
-#ifdef CONFIG_SUSPEND
- if (tp_features.quirks && tp_features.quirks->s2idle_bug_mmio)
- acpi_unregister_lps0_dev(&thinkpad_acpi_s2idle_dev_ops);
-#endif
if (tpacpi_hwmon)
hwmon_device_unregister(tpacpi_hwmon);
if (tp_features.sensors_pdrv_registered)
@@ -11859,13 +11725,6 @@ static int __init thinkpad_acpi_module_init(void)
tp_features.input_device_registered = 1;
}
-#ifdef CONFIG_SUSPEND
- if (tp_features.quirks && tp_features.quirks->s2idle_bug_mmio) {
- if (!acpi_register_lps0_dev(&thinkpad_acpi_s2idle_dev_ops))
- pr_info("Using s2idle quirk to avoid %s platform firmware bug\n",
- (dmi_id && dmi_id->ident) ? dmi_id->ident : "");
- }
-#endif
return 0;
}
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/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c
index 68e66b60445c..f9301a9382e7 100644
--- a/drivers/platform/x86/touchscreen_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -26,6 +26,22 @@ struct ts_dmi_data {
/* NOTE: Please keep all entries sorted alphabetically */
+static const struct property_entry archos_101_cesium_educ_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1850),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
+ PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
+ PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+ PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+ PROPERTY_ENTRY_BOOL("silead,home-button"),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-archos-101-cesium-educ.fw"),
+ { }
+};
+
+static const struct ts_dmi_data archos_101_cesium_educ_data = {
+ .acpi_name = "MSSL1680:00",
+ .properties = archos_101_cesium_educ_props,
+};
+
static const struct property_entry chuwi_hi8_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
@@ -1048,6 +1064,13 @@ static const struct ts_dmi_data vinga_twizzle_j116_data = {
/* NOTE: Please keep this table sorted alphabetically */
const struct dmi_system_id touchscreen_dmi_table[] = {
{
+ /* Archos 101 Cesium Educ */
+ .driver_data = (void *)&archos_101_cesium_educ_data,
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "ARCHOS 101 Cesium Educ"),
+ },
+ },
+ {
/* Chuwi Hi8 */
.driver_data = (void *)&chuwi_hi8_data,
.matches = {
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index d81319a502ef..a78ddd83cda0 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -136,6 +136,16 @@ static acpi_status find_guid(const char *guid_string, struct wmi_block **out)
return AE_NOT_FOUND;
}
+static bool guid_parse_and_compare(const char *string, const guid_t *guid)
+{
+ guid_t guid_input;
+
+ if (guid_parse(string, &guid_input))
+ return false;
+
+ return guid_equal(&guid_input, guid);
+}
+
static const void *find_guid_context(struct wmi_block *wblock,
struct wmi_driver *wdriver)
{
@@ -146,11 +156,7 @@ static const void *find_guid_context(struct wmi_block *wblock,
return NULL;
while (*id->guid_string) {
- guid_t guid_input;
-
- if (guid_parse(id->guid_string, &guid_input))
- continue;
- if (guid_equal(&wblock->gblock.guid, &guid_input))
+ if (guid_parse_and_compare(id->guid_string, &wblock->gblock.guid))
return id->context;
id++;
}
@@ -248,7 +254,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 +270,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 +345,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 +464,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 +482,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 +504,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 +615,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 +661,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 +708,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
+ *
+ * Get extra data associated with an WMI event, the caller needs to free @out.
*
- * Returns extra data associated with an event in WMI.
+ * Return: acpi_status signaling success or error.
*/
acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out)
{
@@ -664,7 +736,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 +747,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)
{
@@ -827,11 +901,7 @@ static int wmi_dev_match(struct device *dev, struct device_driver *driver)
return 0;
while (*id->guid_string) {
- guid_t driver_guid;
-
- if (WARN_ON(guid_parse(id->guid_string, &driver_guid)))
- continue;
- if (guid_equal(&driver_guid, &wblock->gblock.guid))
+ if (guid_parse_and_compare(id->guid_string, &wblock->gblock.guid))
return 1;
id++;
@@ -1171,11 +1241,7 @@ static bool guid_already_parsed_for_legacy(struct acpi_device *device, const gui
list_for_each_entry(wblock, &wmi_block_list, list) {
/* skip warning and register if we know the driver will use struct wmi_driver */
for (int i = 0; allow_duplicates[i] != NULL; i++) {
- guid_t tmp;
-
- if (guid_parse(allow_duplicates[i], &tmp))
- continue;
- if (guid_equal(&tmp, guid))
+ if (guid_parse_and_compare(allow_duplicates[i], guid))
return false;
}
if (guid_equal(&wblock->gblock.guid, guid)) {
@@ -1454,6 +1520,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 c78be9f322e6..663a1c423806 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -706,7 +706,7 @@ config CHARGER_BQ256XX
config CHARGER_RK817
tristate "Rockchip RK817 PMIC Battery Charger"
- depends on MFD_RK808
+ depends on MFD_RK8XX
help
Say Y to include support for Rockchip RK817 Battery Charger.
@@ -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/Kconfig b/drivers/powercap/Kconfig
index 90d33cd1b670..69ef8d081c98 100644
--- a/drivers/powercap/Kconfig
+++ b/drivers/powercap/Kconfig
@@ -18,10 +18,12 @@ if POWERCAP
# Client driver configurations go here.
config INTEL_RAPL_CORE
tristate
+ depends on PCI
+ select IOSF_MBI
config INTEL_RAPL
tristate "Intel RAPL Support via MSR Interface"
- depends on X86 && IOSF_MBI
+ depends on X86 && PCI
select INTEL_RAPL_CORE
help
This enables support for the Intel Running Average Power Limit (RAPL)
@@ -33,6 +35,20 @@ config INTEL_RAPL
controller, CPU core (Power Plane 0), graphics uncore (Power Plane
1), etc.
+config INTEL_RAPL_TPMI
+ tristate "Intel RAPL Support via TPMI Interface"
+ depends on X86
+ depends on INTEL_TPMI
+ select INTEL_RAPL_CORE
+ help
+ This enables support for the Intel Running Average Power Limit (RAPL)
+ technology via TPMI interface, which allows power limits to be enforced
+ and monitored.
+
+ In RAPL, the platform level settings are divided into domains for
+ fine grained control. These domains include processor package, DRAM
+ controller, platform, etc.
+
config IDLE_INJECT
bool "Idle injection framework"
depends on CPU_IDLE
diff --git a/drivers/powercap/Makefile b/drivers/powercap/Makefile
index 4474201b4aa7..5ab0dce565b9 100644
--- a/drivers/powercap/Makefile
+++ b/drivers/powercap/Makefile
@@ -5,5 +5,6 @@ obj-$(CONFIG_DTPM_DEVFREQ) += dtpm_devfreq.o
obj-$(CONFIG_POWERCAP) += powercap_sys.o
obj-$(CONFIG_INTEL_RAPL_CORE) += intel_rapl_common.o
obj-$(CONFIG_INTEL_RAPL) += intel_rapl_msr.o
+obj-$(CONFIG_INTEL_RAPL_TPMI) += intel_rapl_tpmi.o
obj-$(CONFIG_IDLE_INJECT) += idle_inject.o
obj-$(CONFIG_ARM_SCMI_POWERCAP) += arm_scmi_powercap.o
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/powercap/intel_rapl_common.c b/drivers/powercap/intel_rapl_common.c
index 8970c7b80884..8fac57b28f8a 100644
--- a/drivers/powercap/intel_rapl_common.c
+++ b/drivers/powercap/intel_rapl_common.c
@@ -75,6 +75,15 @@
#define PSYS_TIME_WINDOW1_MASK (0x7FULL<<19)
#define PSYS_TIME_WINDOW2_MASK (0x7FULL<<51)
+/* bitmasks for RAPL TPMI, used by primitive access functions */
+#define TPMI_POWER_LIMIT_MASK 0x3FFFF
+#define TPMI_POWER_LIMIT_ENABLE BIT_ULL(62)
+#define TPMI_TIME_WINDOW_MASK (0x7FULL<<18)
+#define TPMI_INFO_SPEC_MASK 0x3FFFF
+#define TPMI_INFO_MIN_MASK (0x3FFFFULL << 18)
+#define TPMI_INFO_MAX_MASK (0x3FFFFULL << 36)
+#define TPMI_INFO_MAX_TIME_WIN_MASK (0x7FULL << 54)
+
/* Non HW constants */
#define RAPL_PRIMITIVE_DERIVED BIT(1) /* not from raw data */
#define RAPL_PRIMITIVE_DUMMY BIT(2)
@@ -94,26 +103,120 @@ enum unit_type {
#define DOMAIN_STATE_INACTIVE BIT(0)
#define DOMAIN_STATE_POWER_LIMIT_SET BIT(1)
-#define DOMAIN_STATE_BIOS_LOCKED BIT(2)
-static const char pl1_name[] = "long_term";
-static const char pl2_name[] = "short_term";
-static const char pl4_name[] = "peak_power";
+static const char *pl_names[NR_POWER_LIMITS] = {
+ [POWER_LIMIT1] = "long_term",
+ [POWER_LIMIT2] = "short_term",
+ [POWER_LIMIT4] = "peak_power",
+};
+
+enum pl_prims {
+ PL_ENABLE,
+ PL_CLAMP,
+ PL_LIMIT,
+ PL_TIME_WINDOW,
+ PL_MAX_POWER,
+ PL_LOCK,
+};
+
+static bool is_pl_valid(struct rapl_domain *rd, int pl)
+{
+ if (pl < POWER_LIMIT1 || pl > POWER_LIMIT4)
+ return false;
+ return rd->rpl[pl].name ? true : false;
+}
+
+static int get_pl_lock_prim(struct rapl_domain *rd, int pl)
+{
+ if (rd->rp->priv->type == RAPL_IF_TPMI) {
+ if (pl == POWER_LIMIT1)
+ return PL1_LOCK;
+ if (pl == POWER_LIMIT2)
+ return PL2_LOCK;
+ if (pl == POWER_LIMIT4)
+ return PL4_LOCK;
+ }
+
+ /* MSR/MMIO Interface doesn't have Lock bit for PL4 */
+ if (pl == POWER_LIMIT4)
+ return -EINVAL;
+
+ /*
+ * Power Limit register that supports two power limits has a different
+ * bit position for the Lock bit.
+ */
+ if (rd->rp->priv->limits[rd->id] & BIT(POWER_LIMIT2))
+ return FW_HIGH_LOCK;
+ return FW_LOCK;
+}
+
+static int get_pl_prim(struct rapl_domain *rd, int pl, enum pl_prims prim)
+{
+ switch (pl) {
+ case POWER_LIMIT1:
+ if (prim == PL_ENABLE)
+ return PL1_ENABLE;
+ if (prim == PL_CLAMP && rd->rp->priv->type != RAPL_IF_TPMI)
+ return PL1_CLAMP;
+ if (prim == PL_LIMIT)
+ return POWER_LIMIT1;
+ if (prim == PL_TIME_WINDOW)
+ return TIME_WINDOW1;
+ if (prim == PL_MAX_POWER)
+ return THERMAL_SPEC_POWER;
+ if (prim == PL_LOCK)
+ return get_pl_lock_prim(rd, pl);
+ return -EINVAL;
+ case POWER_LIMIT2:
+ if (prim == PL_ENABLE)
+ return PL2_ENABLE;
+ if (prim == PL_CLAMP && rd->rp->priv->type != RAPL_IF_TPMI)
+ return PL2_CLAMP;
+ if (prim == PL_LIMIT)
+ return POWER_LIMIT2;
+ if (prim == PL_TIME_WINDOW)
+ return TIME_WINDOW2;
+ if (prim == PL_MAX_POWER)
+ return MAX_POWER;
+ if (prim == PL_LOCK)
+ return get_pl_lock_prim(rd, pl);
+ return -EINVAL;
+ case POWER_LIMIT4:
+ if (prim == PL_LIMIT)
+ return POWER_LIMIT4;
+ if (prim == PL_ENABLE)
+ return PL4_ENABLE;
+ /* PL4 would be around two times PL2, use same prim as PL2. */
+ if (prim == PL_MAX_POWER)
+ return MAX_POWER;
+ if (prim == PL_LOCK)
+ return get_pl_lock_prim(rd, pl);
+ return -EINVAL;
+ default:
+ return -EINVAL;
+ }
+}
#define power_zone_to_rapl_domain(_zone) \
container_of(_zone, struct rapl_domain, power_zone)
struct rapl_defaults {
u8 floor_freq_reg_addr;
- int (*check_unit)(struct rapl_package *rp, int cpu);
+ int (*check_unit)(struct rapl_domain *rd);
void (*set_floor_freq)(struct rapl_domain *rd, bool mode);
- u64 (*compute_time_window)(struct rapl_package *rp, u64 val,
+ u64 (*compute_time_window)(struct rapl_domain *rd, u64 val,
bool to_raw);
unsigned int dram_domain_energy_unit;
unsigned int psys_domain_energy_unit;
bool spr_psys_bits;
};
-static struct rapl_defaults *rapl_defaults;
+static struct rapl_defaults *defaults_msr;
+static const struct rapl_defaults defaults_tpmi;
+
+static struct rapl_defaults *get_defaults(struct rapl_package *rp)
+{
+ return rp->priv->defaults;
+}
/* Sideband MBI registers */
#define IOSF_CPU_POWER_BUDGET_CTL_BYT (0x2)
@@ -150,6 +253,12 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
static int rapl_write_data_raw(struct rapl_domain *rd,
enum rapl_primitives prim,
unsigned long long value);
+static int rapl_read_pl_data(struct rapl_domain *rd, int pl,
+ enum pl_prims pl_prim,
+ bool xlate, u64 *data);
+static int rapl_write_pl_data(struct rapl_domain *rd, int pl,
+ enum pl_prims pl_prim,
+ unsigned long long value);
static u64 rapl_unit_xlate(struct rapl_domain *rd,
enum unit_type type, u64 value, int to_raw);
static void package_power_limit_irq_save(struct rapl_package *rp);
@@ -217,7 +326,7 @@ static int find_nr_power_limit(struct rapl_domain *rd)
int i, nr_pl = 0;
for (i = 0; i < NR_POWER_LIMITS; i++) {
- if (rd->rpl[i].name)
+ if (is_pl_valid(rd, i))
nr_pl++;
}
@@ -227,37 +336,35 @@ static int find_nr_power_limit(struct rapl_domain *rd)
static int set_domain_enable(struct powercap_zone *power_zone, bool mode)
{
struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone);
-
- if (rd->state & DOMAIN_STATE_BIOS_LOCKED)
- return -EACCES;
+ struct rapl_defaults *defaults = get_defaults(rd->rp);
+ int ret;
cpus_read_lock();
- rapl_write_data_raw(rd, PL1_ENABLE, mode);
- if (rapl_defaults->set_floor_freq)
- rapl_defaults->set_floor_freq(rd, mode);
+ ret = rapl_write_pl_data(rd, POWER_LIMIT1, PL_ENABLE, mode);
+ if (!ret && defaults->set_floor_freq)
+ defaults->set_floor_freq(rd, mode);
cpus_read_unlock();
- return 0;
+ return ret;
}
static int get_domain_enable(struct powercap_zone *power_zone, bool *mode)
{
struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone);
u64 val;
+ int ret;
- if (rd->state & DOMAIN_STATE_BIOS_LOCKED) {
+ if (rd->rpl[POWER_LIMIT1].locked) {
*mode = false;
return 0;
}
cpus_read_lock();
- if (rapl_read_data_raw(rd, PL1_ENABLE, true, &val)) {
- cpus_read_unlock();
- return -EIO;
- }
- *mode = val;
+ ret = rapl_read_pl_data(rd, POWER_LIMIT1, PL_ENABLE, true, &val);
+ if (!ret)
+ *mode = val;
cpus_read_unlock();
- return 0;
+ return ret;
}
/* per RAPL domain ops, in the order of rapl_domain_type */
@@ -313,8 +420,8 @@ static int contraint_to_pl(struct rapl_domain *rd, int cid)
{
int i, j;
- for (i = 0, j = 0; i < NR_POWER_LIMITS; i++) {
- if ((rd->rpl[i].name) && j++ == cid) {
+ for (i = POWER_LIMIT1, j = 0; i < NR_POWER_LIMITS; i++) {
+ if (is_pl_valid(rd, i) && j++ == cid) {
pr_debug("%s: index %d\n", __func__, i);
return i;
}
@@ -335,36 +442,11 @@ static int set_power_limit(struct powercap_zone *power_zone, int cid,
cpus_read_lock();
rd = power_zone_to_rapl_domain(power_zone);
id = contraint_to_pl(rd, cid);
- if (id < 0) {
- ret = id;
- goto set_exit;
- }
-
rp = rd->rp;
- if (rd->state & DOMAIN_STATE_BIOS_LOCKED) {
- dev_warn(&power_zone->dev,
- "%s locked by BIOS, monitoring only\n", rd->name);
- ret = -EACCES;
- goto set_exit;
- }
-
- switch (rd->rpl[id].prim_id) {
- case PL1_ENABLE:
- rapl_write_data_raw(rd, POWER_LIMIT1, power_limit);
- break;
- case PL2_ENABLE:
- rapl_write_data_raw(rd, POWER_LIMIT2, power_limit);
- break;
- case PL4_ENABLE:
- rapl_write_data_raw(rd, POWER_LIMIT4, power_limit);
- break;
- default:
- ret = -EINVAL;
- }
+ ret = rapl_write_pl_data(rd, id, PL_LIMIT, power_limit);
if (!ret)
package_power_limit_irq_save(rp);
-set_exit:
cpus_read_unlock();
return ret;
}
@@ -374,38 +456,17 @@ static int get_current_power_limit(struct powercap_zone *power_zone, int cid,
{
struct rapl_domain *rd;
u64 val;
- int prim;
int ret = 0;
int id;
cpus_read_lock();
rd = power_zone_to_rapl_domain(power_zone);
id = contraint_to_pl(rd, cid);
- if (id < 0) {
- ret = id;
- goto get_exit;
- }
- switch (rd->rpl[id].prim_id) {
- case PL1_ENABLE:
- prim = POWER_LIMIT1;
- break;
- case PL2_ENABLE:
- prim = POWER_LIMIT2;
- break;
- case PL4_ENABLE:
- prim = POWER_LIMIT4;
- break;
- default:
- cpus_read_unlock();
- return -EINVAL;
- }
- if (rapl_read_data_raw(rd, prim, true, &val))
- ret = -EIO;
- else
+ ret = rapl_read_pl_data(rd, id, PL_LIMIT, true, &val);
+ if (!ret)
*data = val;
-get_exit:
cpus_read_unlock();
return ret;
@@ -421,23 +482,9 @@ static int set_time_window(struct powercap_zone *power_zone, int cid,
cpus_read_lock();
rd = power_zone_to_rapl_domain(power_zone);
id = contraint_to_pl(rd, cid);
- if (id < 0) {
- ret = id;
- goto set_time_exit;
- }
- switch (rd->rpl[id].prim_id) {
- case PL1_ENABLE:
- rapl_write_data_raw(rd, TIME_WINDOW1, window);
- break;
- case PL2_ENABLE:
- rapl_write_data_raw(rd, TIME_WINDOW2, window);
- break;
- default:
- ret = -EINVAL;
- }
+ ret = rapl_write_pl_data(rd, id, PL_TIME_WINDOW, window);
-set_time_exit:
cpus_read_unlock();
return ret;
}
@@ -453,33 +500,11 @@ static int get_time_window(struct powercap_zone *power_zone, int cid,
cpus_read_lock();
rd = power_zone_to_rapl_domain(power_zone);
id = contraint_to_pl(rd, cid);
- if (id < 0) {
- ret = id;
- goto get_time_exit;
- }
- switch (rd->rpl[id].prim_id) {
- case PL1_ENABLE:
- ret = rapl_read_data_raw(rd, TIME_WINDOW1, true, &val);
- break;
- case PL2_ENABLE:
- ret = rapl_read_data_raw(rd, TIME_WINDOW2, true, &val);
- break;
- case PL4_ENABLE:
- /*
- * Time window parameter is not applicable for PL4 entry
- * so assigining '0' as default value.
- */
- val = 0;
- break;
- default:
- cpus_read_unlock();
- return -EINVAL;
- }
+ ret = rapl_read_pl_data(rd, id, PL_TIME_WINDOW, true, &val);
if (!ret)
*data = val;
-get_time_exit:
cpus_read_unlock();
return ret;
@@ -499,36 +524,23 @@ static const char *get_constraint_name(struct powercap_zone *power_zone,
return NULL;
}
-static int get_max_power(struct powercap_zone *power_zone, int id, u64 *data)
+static int get_max_power(struct powercap_zone *power_zone, int cid, u64 *data)
{
struct rapl_domain *rd;
u64 val;
- int prim;
int ret = 0;
+ int id;
cpus_read_lock();
rd = power_zone_to_rapl_domain(power_zone);
- switch (rd->rpl[id].prim_id) {
- case PL1_ENABLE:
- prim = THERMAL_SPEC_POWER;
- break;
- case PL2_ENABLE:
- prim = MAX_POWER;
- break;
- case PL4_ENABLE:
- prim = MAX_POWER;
- break;
- default:
- cpus_read_unlock();
- return -EINVAL;
- }
- if (rapl_read_data_raw(rd, prim, true, &val))
- ret = -EIO;
- else
+ id = contraint_to_pl(rd, cid);
+
+ ret = rapl_read_pl_data(rd, id, PL_MAX_POWER, true, &val);
+ if (!ret)
*data = val;
/* As a generalization rule, PL4 would be around two times PL2. */
- if (rd->rpl[id].prim_id == PL4_ENABLE)
+ if (id == POWER_LIMIT4)
*data = *data * 2;
cpus_read_unlock();
@@ -545,6 +557,12 @@ static const struct powercap_zone_constraint_ops constraint_ops = {
.get_name = get_constraint_name,
};
+/* Return the id used for read_raw/write_raw callback */
+static int get_rid(struct rapl_package *rp)
+{
+ return rp->lead_cpu >= 0 ? rp->lead_cpu : rp->id;
+}
+
/* called after domain detection and package level data are set */
static void rapl_init_domains(struct rapl_package *rp)
{
@@ -554,6 +572,7 @@ static void rapl_init_domains(struct rapl_package *rp)
for (i = 0; i < RAPL_DOMAIN_MAX; i++) {
unsigned int mask = rp->domain_map & (1 << i);
+ int t;
if (!mask)
continue;
@@ -562,51 +581,26 @@ static void rapl_init_domains(struct rapl_package *rp)
if (i == RAPL_DOMAIN_PLATFORM && rp->id > 0) {
snprintf(rd->name, RAPL_DOMAIN_NAME_LENGTH, "psys-%d",
- topology_physical_package_id(rp->lead_cpu));
- } else
+ rp->lead_cpu >= 0 ? topology_physical_package_id(rp->lead_cpu) :
+ rp->id);
+ } else {
snprintf(rd->name, RAPL_DOMAIN_NAME_LENGTH, "%s",
rapl_domain_names[i]);
+ }
rd->id = i;
- rd->rpl[0].prim_id = PL1_ENABLE;
- rd->rpl[0].name = pl1_name;
- /*
- * The PL2 power domain is applicable for limits two
- * and limits three
- */
- if (rp->priv->limits[i] >= 2) {
- rd->rpl[1].prim_id = PL2_ENABLE;
- rd->rpl[1].name = pl2_name;
- }
+ /* PL1 is supported by default */
+ rp->priv->limits[i] |= BIT(POWER_LIMIT1);
- /* Enable PL4 domain if the total power limits are three */
- if (rp->priv->limits[i] == 3) {
- rd->rpl[2].prim_id = PL4_ENABLE;
- rd->rpl[2].name = pl4_name;
+ for (t = POWER_LIMIT1; t < NR_POWER_LIMITS; t++) {
+ if (rp->priv->limits[i] & BIT(t))
+ rd->rpl[t].name = pl_names[t];
}
for (j = 0; j < RAPL_DOMAIN_REG_MAX; j++)
rd->regs[j] = rp->priv->regs[i][j];
- switch (i) {
- case RAPL_DOMAIN_DRAM:
- rd->domain_energy_unit =
- rapl_defaults->dram_domain_energy_unit;
- if (rd->domain_energy_unit)
- pr_info("DRAM domain energy unit %dpj\n",
- rd->domain_energy_unit);
- break;
- case RAPL_DOMAIN_PLATFORM:
- rd->domain_energy_unit =
- rapl_defaults->psys_domain_energy_unit;
- if (rd->domain_energy_unit)
- pr_info("Platform domain energy unit %dpj\n",
- rd->domain_energy_unit);
- break;
- default:
- break;
- }
rd++;
}
}
@@ -615,23 +609,19 @@ static u64 rapl_unit_xlate(struct rapl_domain *rd, enum unit_type type,
u64 value, int to_raw)
{
u64 units = 1;
- struct rapl_package *rp = rd->rp;
+ struct rapl_defaults *defaults = get_defaults(rd->rp);
u64 scale = 1;
switch (type) {
case POWER_UNIT:
- units = rp->power_unit;
+ units = rd->power_unit;
break;
case ENERGY_UNIT:
scale = ENERGY_UNIT_SCALE;
- /* per domain unit takes precedence */
- if (rd->domain_energy_unit)
- units = rd->domain_energy_unit;
- else
- units = rp->energy_unit;
+ units = rd->energy_unit;
break;
case TIME_UNIT:
- return rapl_defaults->compute_time_window(rp, value, to_raw);
+ return defaults->compute_time_window(rd, value, to_raw);
case ARBITRARY_UNIT:
default:
return value;
@@ -645,67 +635,141 @@ static u64 rapl_unit_xlate(struct rapl_domain *rd, enum unit_type type,
return div64_u64(value, scale);
}
-/* in the order of enum rapl_primitives */
-static struct rapl_primitive_info rpi[] = {
+/* RAPL primitives for MSR and MMIO I/F */
+static struct rapl_primitive_info rpi_msr[NR_RAPL_PRIMITIVES] = {
/* name, mask, shift, msr index, unit divisor */
- PRIMITIVE_INFO_INIT(ENERGY_COUNTER, ENERGY_STATUS_MASK, 0,
- RAPL_DOMAIN_REG_STATUS, ENERGY_UNIT, 0),
- PRIMITIVE_INFO_INIT(POWER_LIMIT1, POWER_LIMIT1_MASK, 0,
+ [POWER_LIMIT1] = PRIMITIVE_INFO_INIT(POWER_LIMIT1, POWER_LIMIT1_MASK, 0,
RAPL_DOMAIN_REG_LIMIT, POWER_UNIT, 0),
- PRIMITIVE_INFO_INIT(POWER_LIMIT2, POWER_LIMIT2_MASK, 32,
+ [POWER_LIMIT2] = PRIMITIVE_INFO_INIT(POWER_LIMIT2, POWER_LIMIT2_MASK, 32,
RAPL_DOMAIN_REG_LIMIT, POWER_UNIT, 0),
- PRIMITIVE_INFO_INIT(POWER_LIMIT4, POWER_LIMIT4_MASK, 0,
+ [POWER_LIMIT4] = PRIMITIVE_INFO_INIT(POWER_LIMIT4, POWER_LIMIT4_MASK, 0,
RAPL_DOMAIN_REG_PL4, POWER_UNIT, 0),
- PRIMITIVE_INFO_INIT(FW_LOCK, POWER_LOW_LOCK, 31,
+ [ENERGY_COUNTER] = PRIMITIVE_INFO_INIT(ENERGY_COUNTER, ENERGY_STATUS_MASK, 0,
+ RAPL_DOMAIN_REG_STATUS, ENERGY_UNIT, 0),
+ [FW_LOCK] = PRIMITIVE_INFO_INIT(FW_LOCK, POWER_LOW_LOCK, 31,
RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
- PRIMITIVE_INFO_INIT(PL1_ENABLE, POWER_LIMIT1_ENABLE, 15,
+ [FW_HIGH_LOCK] = PRIMITIVE_INFO_INIT(FW_LOCK, POWER_HIGH_LOCK, 63,
RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
- PRIMITIVE_INFO_INIT(PL1_CLAMP, POWER_LIMIT1_CLAMP, 16,
+ [PL1_ENABLE] = PRIMITIVE_INFO_INIT(PL1_ENABLE, POWER_LIMIT1_ENABLE, 15,
RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
- PRIMITIVE_INFO_INIT(PL2_ENABLE, POWER_LIMIT2_ENABLE, 47,
+ [PL1_CLAMP] = PRIMITIVE_INFO_INIT(PL1_CLAMP, POWER_LIMIT1_CLAMP, 16,
RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
- PRIMITIVE_INFO_INIT(PL2_CLAMP, POWER_LIMIT2_CLAMP, 48,
+ [PL2_ENABLE] = PRIMITIVE_INFO_INIT(PL2_ENABLE, POWER_LIMIT2_ENABLE, 47,
RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
- PRIMITIVE_INFO_INIT(PL4_ENABLE, POWER_LIMIT4_MASK, 0,
+ [PL2_CLAMP] = PRIMITIVE_INFO_INIT(PL2_CLAMP, POWER_LIMIT2_CLAMP, 48,
+ RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
+ [PL4_ENABLE] = PRIMITIVE_INFO_INIT(PL4_ENABLE, POWER_LIMIT4_MASK, 0,
RAPL_DOMAIN_REG_PL4, ARBITRARY_UNIT, 0),
- PRIMITIVE_INFO_INIT(TIME_WINDOW1, TIME_WINDOW1_MASK, 17,
+ [TIME_WINDOW1] = PRIMITIVE_INFO_INIT(TIME_WINDOW1, TIME_WINDOW1_MASK, 17,
RAPL_DOMAIN_REG_LIMIT, TIME_UNIT, 0),
- PRIMITIVE_INFO_INIT(TIME_WINDOW2, TIME_WINDOW2_MASK, 49,
+ [TIME_WINDOW2] = PRIMITIVE_INFO_INIT(TIME_WINDOW2, TIME_WINDOW2_MASK, 49,
RAPL_DOMAIN_REG_LIMIT, TIME_UNIT, 0),
- PRIMITIVE_INFO_INIT(THERMAL_SPEC_POWER, POWER_INFO_THERMAL_SPEC_MASK,
+ [THERMAL_SPEC_POWER] = PRIMITIVE_INFO_INIT(THERMAL_SPEC_POWER, POWER_INFO_THERMAL_SPEC_MASK,
0, RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0),
- PRIMITIVE_INFO_INIT(MAX_POWER, POWER_INFO_MAX_MASK, 32,
+ [MAX_POWER] = PRIMITIVE_INFO_INIT(MAX_POWER, POWER_INFO_MAX_MASK, 32,
RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0),
- PRIMITIVE_INFO_INIT(MIN_POWER, POWER_INFO_MIN_MASK, 16,
+ [MIN_POWER] = PRIMITIVE_INFO_INIT(MIN_POWER, POWER_INFO_MIN_MASK, 16,
RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0),
- PRIMITIVE_INFO_INIT(MAX_TIME_WINDOW, POWER_INFO_MAX_TIME_WIN_MASK, 48,
+ [MAX_TIME_WINDOW] = PRIMITIVE_INFO_INIT(MAX_TIME_WINDOW, POWER_INFO_MAX_TIME_WIN_MASK, 48,
RAPL_DOMAIN_REG_INFO, TIME_UNIT, 0),
- PRIMITIVE_INFO_INIT(THROTTLED_TIME, PERF_STATUS_THROTTLE_TIME_MASK, 0,
+ [THROTTLED_TIME] = PRIMITIVE_INFO_INIT(THROTTLED_TIME, PERF_STATUS_THROTTLE_TIME_MASK, 0,
RAPL_DOMAIN_REG_PERF, TIME_UNIT, 0),
- PRIMITIVE_INFO_INIT(PRIORITY_LEVEL, PP_POLICY_MASK, 0,
+ [PRIORITY_LEVEL] = PRIMITIVE_INFO_INIT(PRIORITY_LEVEL, PP_POLICY_MASK, 0,
RAPL_DOMAIN_REG_POLICY, ARBITRARY_UNIT, 0),
- PRIMITIVE_INFO_INIT(PSYS_POWER_LIMIT1, PSYS_POWER_LIMIT1_MASK, 0,
+ [PSYS_POWER_LIMIT1] = PRIMITIVE_INFO_INIT(PSYS_POWER_LIMIT1, PSYS_POWER_LIMIT1_MASK, 0,
RAPL_DOMAIN_REG_LIMIT, POWER_UNIT, 0),
- PRIMITIVE_INFO_INIT(PSYS_POWER_LIMIT2, PSYS_POWER_LIMIT2_MASK, 32,
+ [PSYS_POWER_LIMIT2] = PRIMITIVE_INFO_INIT(PSYS_POWER_LIMIT2, PSYS_POWER_LIMIT2_MASK, 32,
RAPL_DOMAIN_REG_LIMIT, POWER_UNIT, 0),
- PRIMITIVE_INFO_INIT(PSYS_PL1_ENABLE, PSYS_POWER_LIMIT1_ENABLE, 17,
+ [PSYS_PL1_ENABLE] = PRIMITIVE_INFO_INIT(PSYS_PL1_ENABLE, PSYS_POWER_LIMIT1_ENABLE, 17,
RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
- PRIMITIVE_INFO_INIT(PSYS_PL2_ENABLE, PSYS_POWER_LIMIT2_ENABLE, 49,
+ [PSYS_PL2_ENABLE] = PRIMITIVE_INFO_INIT(PSYS_PL2_ENABLE, PSYS_POWER_LIMIT2_ENABLE, 49,
RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
- PRIMITIVE_INFO_INIT(PSYS_TIME_WINDOW1, PSYS_TIME_WINDOW1_MASK, 19,
+ [PSYS_TIME_WINDOW1] = PRIMITIVE_INFO_INIT(PSYS_TIME_WINDOW1, PSYS_TIME_WINDOW1_MASK, 19,
RAPL_DOMAIN_REG_LIMIT, TIME_UNIT, 0),
- PRIMITIVE_INFO_INIT(PSYS_TIME_WINDOW2, PSYS_TIME_WINDOW2_MASK, 51,
+ [PSYS_TIME_WINDOW2] = PRIMITIVE_INFO_INIT(PSYS_TIME_WINDOW2, PSYS_TIME_WINDOW2_MASK, 51,
RAPL_DOMAIN_REG_LIMIT, TIME_UNIT, 0),
/* non-hardware */
- PRIMITIVE_INFO_INIT(AVERAGE_POWER, 0, 0, 0, POWER_UNIT,
+ [AVERAGE_POWER] = PRIMITIVE_INFO_INIT(AVERAGE_POWER, 0, 0, 0, POWER_UNIT,
RAPL_PRIMITIVE_DERIVED),
- {NULL, 0, 0, 0},
};
+/* RAPL primitives for TPMI I/F */
+static struct rapl_primitive_info rpi_tpmi[NR_RAPL_PRIMITIVES] = {
+ /* name, mask, shift, msr index, unit divisor */
+ [POWER_LIMIT1] = PRIMITIVE_INFO_INIT(POWER_LIMIT1, TPMI_POWER_LIMIT_MASK, 0,
+ RAPL_DOMAIN_REG_LIMIT, POWER_UNIT, 0),
+ [POWER_LIMIT2] = PRIMITIVE_INFO_INIT(POWER_LIMIT2, TPMI_POWER_LIMIT_MASK, 0,
+ RAPL_DOMAIN_REG_PL2, POWER_UNIT, 0),
+ [POWER_LIMIT4] = PRIMITIVE_INFO_INIT(POWER_LIMIT4, TPMI_POWER_LIMIT_MASK, 0,
+ RAPL_DOMAIN_REG_PL4, POWER_UNIT, 0),
+ [ENERGY_COUNTER] = PRIMITIVE_INFO_INIT(ENERGY_COUNTER, ENERGY_STATUS_MASK, 0,
+ RAPL_DOMAIN_REG_STATUS, ENERGY_UNIT, 0),
+ [PL1_LOCK] = PRIMITIVE_INFO_INIT(PL1_LOCK, POWER_HIGH_LOCK, 63,
+ RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
+ [PL2_LOCK] = PRIMITIVE_INFO_INIT(PL2_LOCK, POWER_HIGH_LOCK, 63,
+ RAPL_DOMAIN_REG_PL2, ARBITRARY_UNIT, 0),
+ [PL4_LOCK] = PRIMITIVE_INFO_INIT(PL4_LOCK, POWER_HIGH_LOCK, 63,
+ RAPL_DOMAIN_REG_PL4, ARBITRARY_UNIT, 0),
+ [PL1_ENABLE] = PRIMITIVE_INFO_INIT(PL1_ENABLE, TPMI_POWER_LIMIT_ENABLE, 62,
+ RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
+ [PL2_ENABLE] = PRIMITIVE_INFO_INIT(PL2_ENABLE, TPMI_POWER_LIMIT_ENABLE, 62,
+ RAPL_DOMAIN_REG_PL2, ARBITRARY_UNIT, 0),
+ [PL4_ENABLE] = PRIMITIVE_INFO_INIT(PL4_ENABLE, TPMI_POWER_LIMIT_ENABLE, 62,
+ RAPL_DOMAIN_REG_PL4, ARBITRARY_UNIT, 0),
+ [TIME_WINDOW1] = PRIMITIVE_INFO_INIT(TIME_WINDOW1, TPMI_TIME_WINDOW_MASK, 18,
+ RAPL_DOMAIN_REG_LIMIT, TIME_UNIT, 0),
+ [TIME_WINDOW2] = PRIMITIVE_INFO_INIT(TIME_WINDOW2, TPMI_TIME_WINDOW_MASK, 18,
+ RAPL_DOMAIN_REG_PL2, TIME_UNIT, 0),
+ [THERMAL_SPEC_POWER] = PRIMITIVE_INFO_INIT(THERMAL_SPEC_POWER, TPMI_INFO_SPEC_MASK, 0,
+ RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0),
+ [MAX_POWER] = PRIMITIVE_INFO_INIT(MAX_POWER, TPMI_INFO_MAX_MASK, 36,
+ RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0),
+ [MIN_POWER] = PRIMITIVE_INFO_INIT(MIN_POWER, TPMI_INFO_MIN_MASK, 18,
+ RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0),
+ [MAX_TIME_WINDOW] = PRIMITIVE_INFO_INIT(MAX_TIME_WINDOW, TPMI_INFO_MAX_TIME_WIN_MASK, 54,
+ RAPL_DOMAIN_REG_INFO, TIME_UNIT, 0),
+ [THROTTLED_TIME] = PRIMITIVE_INFO_INIT(THROTTLED_TIME, PERF_STATUS_THROTTLE_TIME_MASK, 0,
+ RAPL_DOMAIN_REG_PERF, TIME_UNIT, 0),
+ /* non-hardware */
+ [AVERAGE_POWER] = PRIMITIVE_INFO_INIT(AVERAGE_POWER, 0, 0, 0,
+ POWER_UNIT, RAPL_PRIMITIVE_DERIVED),
+};
+
+static struct rapl_primitive_info *get_rpi(struct rapl_package *rp, int prim)
+{
+ struct rapl_primitive_info *rpi = rp->priv->rpi;
+
+ if (prim < 0 || prim > NR_RAPL_PRIMITIVES || !rpi)
+ return NULL;
+
+ return &rpi[prim];
+}
+
+static int rapl_config(struct rapl_package *rp)
+{
+ switch (rp->priv->type) {
+ /* MMIO I/F shares the same register layout as MSR registers */
+ case RAPL_IF_MMIO:
+ case RAPL_IF_MSR:
+ rp->priv->defaults = (void *)defaults_msr;
+ rp->priv->rpi = (void *)rpi_msr;
+ break;
+ case RAPL_IF_TPMI:
+ rp->priv->defaults = (void *)&defaults_tpmi;
+ rp->priv->rpi = (void *)rpi_tpmi;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
static enum rapl_primitives
prim_fixups(struct rapl_domain *rd, enum rapl_primitives prim)
{
- if (!rapl_defaults->spr_psys_bits)
+ struct rapl_defaults *defaults = get_defaults(rd->rp);
+
+ if (!defaults->spr_psys_bits)
return prim;
if (rd->id != RAPL_DOMAIN_PLATFORM)
@@ -747,41 +811,33 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
{
u64 value;
enum rapl_primitives prim_fixed = prim_fixups(rd, prim);
- struct rapl_primitive_info *rp = &rpi[prim_fixed];
+ struct rapl_primitive_info *rpi = get_rpi(rd->rp, prim_fixed);
struct reg_action ra;
- int cpu;
- if (!rp->name || rp->flag & RAPL_PRIMITIVE_DUMMY)
+ if (!rpi || !rpi->name || rpi->flag & RAPL_PRIMITIVE_DUMMY)
return -EINVAL;
- ra.reg = rd->regs[rp->id];
- if (!ra.reg)
+ ra.reg = rd->regs[rpi->id];
+ if (!ra.reg.val)
return -EINVAL;
- cpu = rd->rp->lead_cpu;
-
- /* domain with 2 limits has different bit */
- if (prim == FW_LOCK && rd->rp->priv->limits[rd->id] == 2) {
- rp->mask = POWER_HIGH_LOCK;
- rp->shift = 63;
- }
/* non-hardware data are collected by the polling thread */
- if (rp->flag & RAPL_PRIMITIVE_DERIVED) {
+ if (rpi->flag & RAPL_PRIMITIVE_DERIVED) {
*data = rd->rdd.primitives[prim];
return 0;
}
- ra.mask = rp->mask;
+ ra.mask = rpi->mask;
- if (rd->rp->priv->read_raw(cpu, &ra)) {
- pr_debug("failed to read reg 0x%llx on cpu %d\n", ra.reg, cpu);
+ if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) {
+ pr_debug("failed to read reg 0x%llx for %s:%s\n", ra.reg.val, rd->rp->name, rd->name);
return -EIO;
}
- value = ra.value >> rp->shift;
+ value = ra.value >> rpi->shift;
if (xlate)
- *data = rapl_unit_xlate(rd, rp->unit, value, 0);
+ *data = rapl_unit_xlate(rd, rpi->unit, value, 0);
else
*data = value;
@@ -794,28 +850,56 @@ static int rapl_write_data_raw(struct rapl_domain *rd,
unsigned long long value)
{
enum rapl_primitives prim_fixed = prim_fixups(rd, prim);
- struct rapl_primitive_info *rp = &rpi[prim_fixed];
- int cpu;
+ struct rapl_primitive_info *rpi = get_rpi(rd->rp, prim_fixed);
u64 bits;
struct reg_action ra;
int ret;
- cpu = rd->rp->lead_cpu;
- bits = rapl_unit_xlate(rd, rp->unit, value, 1);
- bits <<= rp->shift;
- bits &= rp->mask;
+ if (!rpi || !rpi->name || rpi->flag & RAPL_PRIMITIVE_DUMMY)
+ return -EINVAL;
+
+ bits = rapl_unit_xlate(rd, rpi->unit, value, 1);
+ bits <<= rpi->shift;
+ bits &= rpi->mask;
memset(&ra, 0, sizeof(ra));
- ra.reg = rd->regs[rp->id];
- ra.mask = rp->mask;
+ ra.reg = rd->regs[rpi->id];
+ ra.mask = rpi->mask;
ra.value = bits;
- ret = rd->rp->priv->write_raw(cpu, &ra);
+ ret = rd->rp->priv->write_raw(get_rid(rd->rp), &ra);
return ret;
}
+static int rapl_read_pl_data(struct rapl_domain *rd, int pl,
+ enum pl_prims pl_prim, bool xlate, u64 *data)
+{
+ enum rapl_primitives prim = get_pl_prim(rd, pl, pl_prim);
+
+ if (!is_pl_valid(rd, pl))
+ return -EINVAL;
+
+ return rapl_read_data_raw(rd, prim, xlate, data);
+}
+
+static int rapl_write_pl_data(struct rapl_domain *rd, int pl,
+ enum pl_prims pl_prim,
+ unsigned long long value)
+{
+ enum rapl_primitives prim = get_pl_prim(rd, pl, pl_prim);
+
+ if (!is_pl_valid(rd, pl))
+ return -EINVAL;
+
+ if (rd->rpl[pl].locked) {
+ pr_warn("%s:%s:%s locked by BIOS\n", rd->rp->name, rd->name, pl_names[pl]);
+ return -EACCES;
+ }
+
+ return rapl_write_data_raw(rd, prim, value);
+}
/*
* Raw RAPL data stored in MSRs are in certain scales. We need to
* convert them into standard units based on the units reported in
@@ -827,58 +911,58 @@ static int rapl_write_data_raw(struct rapl_domain *rd,
* power unit : microWatts : Represented in milliWatts by default
* time unit : microseconds: Represented in seconds by default
*/
-static int rapl_check_unit_core(struct rapl_package *rp, int cpu)
+static int rapl_check_unit_core(struct rapl_domain *rd)
{
struct reg_action ra;
u32 value;
- ra.reg = rp->priv->reg_unit;
+ ra.reg = rd->regs[RAPL_DOMAIN_REG_UNIT];
ra.mask = ~0;
- if (rp->priv->read_raw(cpu, &ra)) {
- pr_err("Failed to read power unit REG 0x%llx on CPU %d, exit.\n",
- rp->priv->reg_unit, cpu);
+ if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) {
+ pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n",
+ ra.reg.val, rd->rp->name, rd->name);
return -ENODEV;
}
value = (ra.value & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET;
- rp->energy_unit = ENERGY_UNIT_SCALE * 1000000 / (1 << value);
+ rd->energy_unit = ENERGY_UNIT_SCALE * 1000000 / (1 << value);
value = (ra.value & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET;
- rp->power_unit = 1000000 / (1 << value);
+ rd->power_unit = 1000000 / (1 << value);
value = (ra.value & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET;
- rp->time_unit = 1000000 / (1 << value);
+ rd->time_unit = 1000000 / (1 << value);
- pr_debug("Core CPU %s energy=%dpJ, time=%dus, power=%duW\n",
- rp->name, rp->energy_unit, rp->time_unit, rp->power_unit);
+ pr_debug("Core CPU %s:%s energy=%dpJ, time=%dus, power=%duW\n",
+ rd->rp->name, rd->name, rd->energy_unit, rd->time_unit, rd->power_unit);
return 0;
}
-static int rapl_check_unit_atom(struct rapl_package *rp, int cpu)
+static int rapl_check_unit_atom(struct rapl_domain *rd)
{
struct reg_action ra;
u32 value;
- ra.reg = rp->priv->reg_unit;
+ ra.reg = rd->regs[RAPL_DOMAIN_REG_UNIT];
ra.mask = ~0;
- if (rp->priv->read_raw(cpu, &ra)) {
- pr_err("Failed to read power unit REG 0x%llx on CPU %d, exit.\n",
- rp->priv->reg_unit, cpu);
+ if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) {
+ pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n",
+ ra.reg.val, rd->rp->name, rd->name);
return -ENODEV;
}
value = (ra.value & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET;
- rp->energy_unit = ENERGY_UNIT_SCALE * 1 << value;
+ rd->energy_unit = ENERGY_UNIT_SCALE * 1 << value;
value = (ra.value & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET;
- rp->power_unit = (1 << value) * 1000;
+ rd->power_unit = (1 << value) * 1000;
value = (ra.value & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET;
- rp->time_unit = 1000000 / (1 << value);
+ rd->time_unit = 1000000 / (1 << value);
- pr_debug("Atom %s energy=%dpJ, time=%dus, power=%duW\n",
- rp->name, rp->energy_unit, rp->time_unit, rp->power_unit);
+ pr_debug("Atom %s:%s energy=%dpJ, time=%dus, power=%duW\n",
+ rd->rp->name, rd->name, rd->energy_unit, rd->time_unit, rd->power_unit);
return 0;
}
@@ -910,6 +994,9 @@ static void power_limit_irq_save_cpu(void *info)
static void package_power_limit_irq_save(struct rapl_package *rp)
{
+ if (rp->lead_cpu < 0)
+ return;
+
if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN))
return;
@@ -924,6 +1011,9 @@ static void package_power_limit_irq_restore(struct rapl_package *rp)
{
u32 l, h;
+ if (rp->lead_cpu < 0)
+ return;
+
if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN))
return;
@@ -943,33 +1033,33 @@ static void package_power_limit_irq_restore(struct rapl_package *rp)
static void set_floor_freq_default(struct rapl_domain *rd, bool mode)
{
- int nr_powerlimit = find_nr_power_limit(rd);
+ int i;
/* always enable clamp such that p-state can go below OS requested
* range. power capping priority over guranteed frequency.
*/
- rapl_write_data_raw(rd, PL1_CLAMP, mode);
+ rapl_write_pl_data(rd, POWER_LIMIT1, PL_CLAMP, mode);
- /* some domains have pl2 */
- if (nr_powerlimit > 1) {
- rapl_write_data_raw(rd, PL2_ENABLE, mode);
- rapl_write_data_raw(rd, PL2_CLAMP, mode);
+ for (i = POWER_LIMIT2; i < NR_POWER_LIMITS; i++) {
+ rapl_write_pl_data(rd, i, PL_ENABLE, mode);
+ rapl_write_pl_data(rd, i, PL_CLAMP, mode);
}
}
static void set_floor_freq_atom(struct rapl_domain *rd, bool enable)
{
static u32 power_ctrl_orig_val;
+ struct rapl_defaults *defaults = get_defaults(rd->rp);
u32 mdata;
- if (!rapl_defaults->floor_freq_reg_addr) {
+ if (!defaults->floor_freq_reg_addr) {
pr_err("Invalid floor frequency config register\n");
return;
}
if (!power_ctrl_orig_val)
iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_CR_READ,
- rapl_defaults->floor_freq_reg_addr,
+ defaults->floor_freq_reg_addr,
&power_ctrl_orig_val);
mdata = power_ctrl_orig_val;
if (enable) {
@@ -977,10 +1067,10 @@ static void set_floor_freq_atom(struct rapl_domain *rd, bool enable)
mdata |= 1 << 8;
}
iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_CR_WRITE,
- rapl_defaults->floor_freq_reg_addr, mdata);
+ defaults->floor_freq_reg_addr, mdata);
}
-static u64 rapl_compute_time_window_core(struct rapl_package *rp, u64 value,
+static u64 rapl_compute_time_window_core(struct rapl_domain *rd, u64 value,
bool to_raw)
{
u64 f, y; /* fraction and exp. used for time unit */
@@ -992,12 +1082,12 @@ static u64 rapl_compute_time_window_core(struct rapl_package *rp, u64 value,
if (!to_raw) {
f = (value & 0x60) >> 5;
y = value & 0x1f;
- value = (1 << y) * (4 + f) * rp->time_unit / 4;
+ value = (1 << y) * (4 + f) * rd->time_unit / 4;
} else {
- if (value < rp->time_unit)
+ if (value < rd->time_unit)
return 0;
- do_div(value, rp->time_unit);
+ do_div(value, rd->time_unit);
y = ilog2(value);
/*
@@ -1013,7 +1103,7 @@ static u64 rapl_compute_time_window_core(struct rapl_package *rp, u64 value,
return value;
}
-static u64 rapl_compute_time_window_atom(struct rapl_package *rp, u64 value,
+static u64 rapl_compute_time_window_atom(struct rapl_domain *rd, u64 value,
bool to_raw)
{
/*
@@ -1021,13 +1111,56 @@ static u64 rapl_compute_time_window_atom(struct rapl_package *rp, u64 value,
* where time_unit is default to 1 sec. Never 0.
*/
if (!to_raw)
- return (value) ? value * rp->time_unit : rp->time_unit;
+ return (value) ? value * rd->time_unit : rd->time_unit;
- value = div64_u64(value, rp->time_unit);
+ value = div64_u64(value, rd->time_unit);
return value;
}
+/* TPMI Unit register has different layout */
+#define TPMI_POWER_UNIT_OFFSET POWER_UNIT_OFFSET
+#define TPMI_POWER_UNIT_MASK POWER_UNIT_MASK
+#define TPMI_ENERGY_UNIT_OFFSET 0x06
+#define TPMI_ENERGY_UNIT_MASK 0x7C0
+#define TPMI_TIME_UNIT_OFFSET 0x0C
+#define TPMI_TIME_UNIT_MASK 0xF000
+
+static int rapl_check_unit_tpmi(struct rapl_domain *rd)
+{
+ struct reg_action ra;
+ u32 value;
+
+ ra.reg = rd->regs[RAPL_DOMAIN_REG_UNIT];
+ ra.mask = ~0;
+ if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) {
+ pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n",
+ ra.reg.val, rd->rp->name, rd->name);
+ return -ENODEV;
+ }
+
+ value = (ra.value & TPMI_ENERGY_UNIT_MASK) >> TPMI_ENERGY_UNIT_OFFSET;
+ rd->energy_unit = ENERGY_UNIT_SCALE * 1000000 / (1 << value);
+
+ value = (ra.value & TPMI_POWER_UNIT_MASK) >> TPMI_POWER_UNIT_OFFSET;
+ rd->power_unit = 1000000 / (1 << value);
+
+ value = (ra.value & TPMI_TIME_UNIT_MASK) >> TPMI_TIME_UNIT_OFFSET;
+ rd->time_unit = 1000000 / (1 << value);
+
+ pr_debug("Core CPU %s:%s energy=%dpJ, time=%dus, power=%duW\n",
+ rd->rp->name, rd->name, rd->energy_unit, rd->time_unit, rd->power_unit);
+
+ return 0;
+}
+
+static const struct rapl_defaults defaults_tpmi = {
+ .check_unit = rapl_check_unit_tpmi,
+ /* Reuse existing logic, ignore the PL_CLAMP failures and enable all Power Limits */
+ .set_floor_freq = set_floor_freq_default,
+ .compute_time_window = rapl_compute_time_window_core,
+};
+
static const struct rapl_defaults rapl_defaults_core = {
.floor_freq_reg_addr = 0,
.check_unit = rapl_check_unit_core,
@@ -1159,8 +1292,10 @@ static void rapl_update_domain_data(struct rapl_package *rp)
rp->domains[dmn].name);
/* exclude non-raw primitives */
for (prim = 0; prim < NR_RAW_PRIMITIVES; prim++) {
+ struct rapl_primitive_info *rpi = get_rpi(rp, prim);
+
if (!rapl_read_data_raw(&rp->domains[dmn], prim,
- rpi[prim].unit, &val))
+ rpi->unit, &val))
rp->domains[dmn].rdd.primitives[prim] = val;
}
}
@@ -1239,7 +1374,7 @@ err_cleanup:
return ret;
}
-static int rapl_check_domain(int cpu, int domain, struct rapl_package *rp)
+static int rapl_check_domain(int domain, struct rapl_package *rp)
{
struct reg_action ra;
@@ -1260,9 +1395,43 @@ static int rapl_check_domain(int cpu, int domain, struct rapl_package *rp)
*/
ra.mask = ENERGY_STATUS_MASK;
- if (rp->priv->read_raw(cpu, &ra) || !ra.value)
+ if (rp->priv->read_raw(get_rid(rp), &ra) || !ra.value)
+ return -ENODEV;
+
+ return 0;
+}
+
+/*
+ * Get per domain energy/power/time unit.
+ * RAPL Interfaces without per domain unit register will use the package
+ * scope unit register to set per domain units.
+ */
+static int rapl_get_domain_unit(struct rapl_domain *rd)
+{
+ struct rapl_defaults *defaults = get_defaults(rd->rp);
+ int ret;
+
+ if (!rd->regs[RAPL_DOMAIN_REG_UNIT].val) {
+ if (!rd->rp->priv->reg_unit.val) {
+ pr_err("No valid Unit register found\n");
+ return -ENODEV;
+ }
+ rd->regs[RAPL_DOMAIN_REG_UNIT] = rd->rp->priv->reg_unit;
+ }
+
+ if (!defaults->check_unit) {
+ pr_err("missing .check_unit() callback\n");
return -ENODEV;
+ }
+
+ ret = defaults->check_unit(rd);
+ if (ret)
+ return ret;
+ if (rd->id == RAPL_DOMAIN_DRAM && defaults->dram_domain_energy_unit)
+ rd->energy_unit = defaults->dram_domain_energy_unit;
+ if (rd->id == RAPL_DOMAIN_PLATFORM && defaults->psys_domain_energy_unit)
+ rd->energy_unit = defaults->psys_domain_energy_unit;
return 0;
}
@@ -1280,19 +1449,16 @@ static void rapl_detect_powerlimit(struct rapl_domain *rd)
u64 val64;
int i;
- /* check if the domain is locked by BIOS, ignore if MSR doesn't exist */
- if (!rapl_read_data_raw(rd, FW_LOCK, false, &val64)) {
- if (val64) {
- pr_info("RAPL %s domain %s locked by BIOS\n",
- rd->rp->name, rd->name);
- rd->state |= DOMAIN_STATE_BIOS_LOCKED;
+ for (i = POWER_LIMIT1; i < NR_POWER_LIMITS; i++) {
+ if (!rapl_read_pl_data(rd, i, PL_LOCK, false, &val64)) {
+ if (val64) {
+ rd->rpl[i].locked = true;
+ pr_info("%s:%s:%s locked by BIOS\n",
+ rd->rp->name, rd->name, pl_names[i]);
+ }
}
- }
- /* check if power limit MSR exists, otherwise domain is monitoring only */
- for (i = 0; i < NR_POWER_LIMITS; i++) {
- int prim = rd->rpl[i].prim_id;
- if (rapl_read_data_raw(rd, prim, false, &val64))
+ if (rapl_read_pl_data(rd, i, PL_ENABLE, false, &val64))
rd->rpl[i].name = NULL;
}
}
@@ -1300,14 +1466,14 @@ static void rapl_detect_powerlimit(struct rapl_domain *rd)
/* Detect active and valid domains for the given CPU, caller must
* ensure the CPU belongs to the targeted package and CPU hotlug is disabled.
*/
-static int rapl_detect_domains(struct rapl_package *rp, int cpu)
+static int rapl_detect_domains(struct rapl_package *rp)
{
struct rapl_domain *rd;
int i;
for (i = 0; i < RAPL_DOMAIN_MAX; i++) {
/* use physical package id to read counters */
- if (!rapl_check_domain(cpu, i, rp)) {
+ if (!rapl_check_domain(i, rp)) {
rp->domain_map |= 1 << i;
pr_info("Found RAPL domain %s\n", rapl_domain_names[i]);
}
@@ -1326,8 +1492,10 @@ static int rapl_detect_domains(struct rapl_package *rp, int cpu)
rapl_init_domains(rp);
- for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++)
+ for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
+ rapl_get_domain_unit(rd);
rapl_detect_powerlimit(rd);
+ }
return 0;
}
@@ -1340,13 +1508,13 @@ void rapl_remove_package(struct rapl_package *rp)
package_power_limit_irq_restore(rp);
for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
- rapl_write_data_raw(rd, PL1_ENABLE, 0);
- rapl_write_data_raw(rd, PL1_CLAMP, 0);
- if (find_nr_power_limit(rd) > 1) {
- rapl_write_data_raw(rd, PL2_ENABLE, 0);
- rapl_write_data_raw(rd, PL2_CLAMP, 0);
- rapl_write_data_raw(rd, PL4_ENABLE, 0);
+ int i;
+
+ for (i = POWER_LIMIT1; i < NR_POWER_LIMITS; i++) {
+ rapl_write_pl_data(rd, i, PL_ENABLE, 0);
+ rapl_write_pl_data(rd, i, PL_CLAMP, 0);
}
+
if (rd->id == RAPL_DOMAIN_PACKAGE) {
rd_package = rd;
continue;
@@ -1365,13 +1533,18 @@ void rapl_remove_package(struct rapl_package *rp)
EXPORT_SYMBOL_GPL(rapl_remove_package);
/* caller to ensure CPU hotplug lock is held */
-struct rapl_package *rapl_find_package_domain(int cpu, struct rapl_if_priv *priv)
+struct rapl_package *rapl_find_package_domain(int id, struct rapl_if_priv *priv, bool id_is_cpu)
{
- int id = topology_logical_die_id(cpu);
struct rapl_package *rp;
+ int uid;
+
+ if (id_is_cpu)
+ uid = topology_logical_die_id(id);
+ else
+ uid = id;
list_for_each_entry(rp, &rapl_packages, plist) {
- if (rp->id == id
+ if (rp->id == uid
&& rp->priv->control_type == priv->control_type)
return rp;
}
@@ -1381,34 +1554,37 @@ struct rapl_package *rapl_find_package_domain(int cpu, struct rapl_if_priv *priv
EXPORT_SYMBOL_GPL(rapl_find_package_domain);
/* called from CPU hotplug notifier, hotplug lock held */
-struct rapl_package *rapl_add_package(int cpu, struct rapl_if_priv *priv)
+struct rapl_package *rapl_add_package(int id, struct rapl_if_priv *priv, bool id_is_cpu)
{
- int id = topology_logical_die_id(cpu);
struct rapl_package *rp;
int ret;
- if (!rapl_defaults)
- return ERR_PTR(-ENODEV);
-
rp = kzalloc(sizeof(struct rapl_package), GFP_KERNEL);
if (!rp)
return ERR_PTR(-ENOMEM);
- /* add the new package to the list */
- rp->id = id;
- rp->lead_cpu = cpu;
- rp->priv = priv;
+ if (id_is_cpu) {
+ rp->id = topology_logical_die_id(id);
+ rp->lead_cpu = id;
+ if (topology_max_die_per_package() > 1)
+ snprintf(rp->name, PACKAGE_DOMAIN_NAME_LENGTH, "package-%d-die-%d",
+ topology_physical_package_id(id), topology_die_id(id));
+ else
+ snprintf(rp->name, PACKAGE_DOMAIN_NAME_LENGTH, "package-%d",
+ topology_physical_package_id(id));
+ } else {
+ rp->id = id;
+ rp->lead_cpu = -1;
+ snprintf(rp->name, PACKAGE_DOMAIN_NAME_LENGTH, "package-%d", id);
+ }
- if (topology_max_die_per_package() > 1)
- snprintf(rp->name, PACKAGE_DOMAIN_NAME_LENGTH,
- "package-%d-die-%d",
- topology_physical_package_id(cpu), topology_die_id(cpu));
- else
- snprintf(rp->name, PACKAGE_DOMAIN_NAME_LENGTH, "package-%d",
- topology_physical_package_id(cpu));
+ rp->priv = priv;
+ ret = rapl_config(rp);
+ if (ret)
+ goto err_free_package;
/* check if the package contains valid domains */
- if (rapl_detect_domains(rp, cpu) || rapl_defaults->check_unit(rp, cpu)) {
+ if (rapl_detect_domains(rp)) {
ret = -ENODEV;
goto err_free_package;
}
@@ -1430,38 +1606,18 @@ static void power_limit_state_save(void)
{
struct rapl_package *rp;
struct rapl_domain *rd;
- int nr_pl, ret, i;
+ int ret, i;
cpus_read_lock();
list_for_each_entry(rp, &rapl_packages, plist) {
if (!rp->power_zone)
continue;
rd = power_zone_to_rapl_domain(rp->power_zone);
- nr_pl = find_nr_power_limit(rd);
- for (i = 0; i < nr_pl; i++) {
- switch (rd->rpl[i].prim_id) {
- case PL1_ENABLE:
- ret = rapl_read_data_raw(rd,
- POWER_LIMIT1, true,
- &rd->rpl[i].last_power_limit);
- if (ret)
- rd->rpl[i].last_power_limit = 0;
- break;
- case PL2_ENABLE:
- ret = rapl_read_data_raw(rd,
- POWER_LIMIT2, true,
+ for (i = POWER_LIMIT1; i < NR_POWER_LIMITS; i++) {
+ ret = rapl_read_pl_data(rd, i, PL_LIMIT, true,
&rd->rpl[i].last_power_limit);
- if (ret)
- rd->rpl[i].last_power_limit = 0;
- break;
- case PL4_ENABLE:
- ret = rapl_read_data_raw(rd,
- POWER_LIMIT4, true,
- &rd->rpl[i].last_power_limit);
- if (ret)
- rd->rpl[i].last_power_limit = 0;
- break;
- }
+ if (ret)
+ rd->rpl[i].last_power_limit = 0;
}
}
cpus_read_unlock();
@@ -1471,33 +1627,17 @@ static void power_limit_state_restore(void)
{
struct rapl_package *rp;
struct rapl_domain *rd;
- int nr_pl, i;
+ int i;
cpus_read_lock();
list_for_each_entry(rp, &rapl_packages, plist) {
if (!rp->power_zone)
continue;
rd = power_zone_to_rapl_domain(rp->power_zone);
- nr_pl = find_nr_power_limit(rd);
- for (i = 0; i < nr_pl; i++) {
- switch (rd->rpl[i].prim_id) {
- case PL1_ENABLE:
- if (rd->rpl[i].last_power_limit)
- rapl_write_data_raw(rd, POWER_LIMIT1,
- rd->rpl[i].last_power_limit);
- break;
- case PL2_ENABLE:
- if (rd->rpl[i].last_power_limit)
- rapl_write_data_raw(rd, POWER_LIMIT2,
- rd->rpl[i].last_power_limit);
- break;
- case PL4_ENABLE:
- if (rd->rpl[i].last_power_limit)
- rapl_write_data_raw(rd, POWER_LIMIT4,
- rd->rpl[i].last_power_limit);
- break;
- }
- }
+ for (i = POWER_LIMIT1; i < NR_POWER_LIMITS; i++)
+ if (rd->rpl[i].last_power_limit)
+ rapl_write_pl_data(rd, i, PL_LIMIT,
+ rd->rpl[i].last_power_limit);
}
cpus_read_unlock();
}
@@ -1528,32 +1668,25 @@ static int __init rapl_init(void)
int ret;
id = x86_match_cpu(rapl_ids);
- if (!id) {
- pr_err("driver does not support CPU family %d model %d\n",
- boot_cpu_data.x86, boot_cpu_data.x86_model);
-
- return -ENODEV;
- }
+ if (id) {
+ defaults_msr = (struct rapl_defaults *)id->driver_data;
- rapl_defaults = (struct rapl_defaults *)id->driver_data;
-
- ret = register_pm_notifier(&rapl_pm_notifier);
- if (ret)
- return ret;
+ rapl_msr_platdev = platform_device_alloc("intel_rapl_msr", 0);
+ if (!rapl_msr_platdev)
+ return -ENOMEM;
- rapl_msr_platdev = platform_device_alloc("intel_rapl_msr", 0);
- if (!rapl_msr_platdev) {
- ret = -ENOMEM;
- goto end;
+ ret = platform_device_add(rapl_msr_platdev);
+ if (ret) {
+ platform_device_put(rapl_msr_platdev);
+ return ret;
+ }
}
- ret = platform_device_add(rapl_msr_platdev);
- if (ret)
+ ret = register_pm_notifier(&rapl_pm_notifier);
+ if (ret && rapl_msr_platdev) {
+ platform_device_del(rapl_msr_platdev);
platform_device_put(rapl_msr_platdev);
-
-end:
- if (ret)
- unregister_pm_notifier(&rapl_pm_notifier);
+ }
return ret;
}
diff --git a/drivers/powercap/intel_rapl_msr.c b/drivers/powercap/intel_rapl_msr.c
index a27673706c3d..dd471021f237 100644
--- a/drivers/powercap/intel_rapl_msr.c
+++ b/drivers/powercap/intel_rapl_msr.c
@@ -22,7 +22,6 @@
#include <linux/processor.h>
#include <linux/platform_device.h>
-#include <asm/iosf_mbi.h>
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
@@ -34,27 +33,33 @@
static struct rapl_if_priv *rapl_msr_priv;
static struct rapl_if_priv rapl_msr_priv_intel = {
- .reg_unit = MSR_RAPL_POWER_UNIT,
- .regs[RAPL_DOMAIN_PACKAGE] = {
- MSR_PKG_POWER_LIMIT, MSR_PKG_ENERGY_STATUS, MSR_PKG_PERF_STATUS, 0, MSR_PKG_POWER_INFO },
- .regs[RAPL_DOMAIN_PP0] = {
- MSR_PP0_POWER_LIMIT, MSR_PP0_ENERGY_STATUS, 0, MSR_PP0_POLICY, 0 },
- .regs[RAPL_DOMAIN_PP1] = {
- MSR_PP1_POWER_LIMIT, MSR_PP1_ENERGY_STATUS, 0, MSR_PP1_POLICY, 0 },
- .regs[RAPL_DOMAIN_DRAM] = {
- MSR_DRAM_POWER_LIMIT, MSR_DRAM_ENERGY_STATUS, MSR_DRAM_PERF_STATUS, 0, MSR_DRAM_POWER_INFO },
- .regs[RAPL_DOMAIN_PLATFORM] = {
- MSR_PLATFORM_POWER_LIMIT, MSR_PLATFORM_ENERGY_STATUS, 0, 0, 0},
- .limits[RAPL_DOMAIN_PACKAGE] = 2,
- .limits[RAPL_DOMAIN_PLATFORM] = 2,
+ .type = RAPL_IF_MSR,
+ .reg_unit.msr = MSR_RAPL_POWER_UNIT,
+ .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_LIMIT].msr = MSR_PKG_POWER_LIMIT,
+ .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_STATUS].msr = MSR_PKG_ENERGY_STATUS,
+ .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PERF].msr = MSR_PKG_PERF_STATUS,
+ .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_INFO].msr = MSR_PKG_POWER_INFO,
+ .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_LIMIT].msr = MSR_PP0_POWER_LIMIT,
+ .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_STATUS].msr = MSR_PP0_ENERGY_STATUS,
+ .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_POLICY].msr = MSR_PP0_POLICY,
+ .regs[RAPL_DOMAIN_PP1][RAPL_DOMAIN_REG_LIMIT].msr = MSR_PP1_POWER_LIMIT,
+ .regs[RAPL_DOMAIN_PP1][RAPL_DOMAIN_REG_STATUS].msr = MSR_PP1_ENERGY_STATUS,
+ .regs[RAPL_DOMAIN_PP1][RAPL_DOMAIN_REG_POLICY].msr = MSR_PP1_POLICY,
+ .regs[RAPL_DOMAIN_DRAM][RAPL_DOMAIN_REG_LIMIT].msr = MSR_DRAM_POWER_LIMIT,
+ .regs[RAPL_DOMAIN_DRAM][RAPL_DOMAIN_REG_STATUS].msr = MSR_DRAM_ENERGY_STATUS,
+ .regs[RAPL_DOMAIN_DRAM][RAPL_DOMAIN_REG_PERF].msr = MSR_DRAM_PERF_STATUS,
+ .regs[RAPL_DOMAIN_DRAM][RAPL_DOMAIN_REG_INFO].msr = MSR_DRAM_POWER_INFO,
+ .regs[RAPL_DOMAIN_PLATFORM][RAPL_DOMAIN_REG_LIMIT].msr = MSR_PLATFORM_POWER_LIMIT,
+ .regs[RAPL_DOMAIN_PLATFORM][RAPL_DOMAIN_REG_STATUS].msr = MSR_PLATFORM_ENERGY_STATUS,
+ .limits[RAPL_DOMAIN_PACKAGE] = BIT(POWER_LIMIT2),
+ .limits[RAPL_DOMAIN_PLATFORM] = BIT(POWER_LIMIT2),
};
static struct rapl_if_priv rapl_msr_priv_amd = {
- .reg_unit = MSR_AMD_RAPL_POWER_UNIT,
- .regs[RAPL_DOMAIN_PACKAGE] = {
- 0, MSR_AMD_PKG_ENERGY_STATUS, 0, 0, 0 },
- .regs[RAPL_DOMAIN_PP0] = {
- 0, MSR_AMD_CORE_ENERGY_STATUS, 0, 0, 0 },
+ .type = RAPL_IF_MSR,
+ .reg_unit.msr = MSR_AMD_RAPL_POWER_UNIT,
+ .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_STATUS].msr = MSR_AMD_PKG_ENERGY_STATUS,
+ .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_STATUS].msr = MSR_AMD_CORE_ENERGY_STATUS,
};
/* Handles CPU hotplug on multi-socket systems.
@@ -68,9 +73,9 @@ static int rapl_cpu_online(unsigned int cpu)
{
struct rapl_package *rp;
- rp = rapl_find_package_domain(cpu, rapl_msr_priv);
+ rp = rapl_find_package_domain(cpu, rapl_msr_priv, true);
if (!rp) {
- rp = rapl_add_package(cpu, rapl_msr_priv);
+ rp = rapl_add_package(cpu, rapl_msr_priv, true);
if (IS_ERR(rp))
return PTR_ERR(rp);
}
@@ -83,7 +88,7 @@ static int rapl_cpu_down_prep(unsigned int cpu)
struct rapl_package *rp;
int lead_cpu;
- rp = rapl_find_package_domain(cpu, rapl_msr_priv);
+ rp = rapl_find_package_domain(cpu, rapl_msr_priv, true);
if (!rp)
return 0;
@@ -98,10 +103,8 @@ static int rapl_cpu_down_prep(unsigned int cpu)
static int rapl_msr_read_raw(int cpu, struct reg_action *ra)
{
- u32 msr = (u32)ra->reg;
-
- if (rdmsrl_safe_on_cpu(cpu, msr, &ra->value)) {
- pr_debug("failed to read msr 0x%x on cpu %d\n", msr, cpu);
+ if (rdmsrl_safe_on_cpu(cpu, ra->reg.msr, &ra->value)) {
+ pr_debug("failed to read msr 0x%x on cpu %d\n", ra->reg.msr, cpu);
return -EIO;
}
ra->value &= ra->mask;
@@ -111,17 +114,16 @@ static int rapl_msr_read_raw(int cpu, struct reg_action *ra)
static void rapl_msr_update_func(void *info)
{
struct reg_action *ra = info;
- u32 msr = (u32)ra->reg;
u64 val;
- ra->err = rdmsrl_safe(msr, &val);
+ ra->err = rdmsrl_safe(ra->reg.msr, &val);
if (ra->err)
return;
val &= ~ra->mask;
val |= ra->value;
- ra->err = wrmsrl_safe(msr, val);
+ ra->err = wrmsrl_safe(ra->reg.msr, val);
}
static int rapl_msr_write_raw(int cpu, struct reg_action *ra)
@@ -137,14 +139,14 @@ static int rapl_msr_write_raw(int cpu, struct reg_action *ra)
/* List of verified CPUs. */
static const struct x86_cpu_id pl4_support_ids[] = {
- { X86_VENDOR_INTEL, 6, INTEL_FAM6_TIGERLAKE_L, X86_FEATURE_ANY },
- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ALDERLAKE, X86_FEATURE_ANY },
- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ALDERLAKE_L, X86_FEATURE_ANY },
- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ALDERLAKE_N, X86_FEATURE_ANY },
- { X86_VENDOR_INTEL, 6, INTEL_FAM6_RAPTORLAKE, X86_FEATURE_ANY },
- { X86_VENDOR_INTEL, 6, INTEL_FAM6_RAPTORLAKE_P, X86_FEATURE_ANY },
- { X86_VENDOR_INTEL, 6, INTEL_FAM6_METEORLAKE, X86_FEATURE_ANY },
- { X86_VENDOR_INTEL, 6, INTEL_FAM6_METEORLAKE_L, X86_FEATURE_ANY },
+ X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, NULL),
+ X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, NULL),
+ X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, NULL),
+ X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, NULL),
+ X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, NULL),
+ X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, NULL),
+ X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE, NULL),
+ X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE_L, NULL),
{}
};
@@ -169,8 +171,8 @@ static int rapl_msr_probe(struct platform_device *pdev)
rapl_msr_priv->write_raw = rapl_msr_write_raw;
if (id) {
- rapl_msr_priv->limits[RAPL_DOMAIN_PACKAGE] = 3;
- rapl_msr_priv->regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PL4] =
+ rapl_msr_priv->limits[RAPL_DOMAIN_PACKAGE] |= BIT(POWER_LIMIT4);
+ rapl_msr_priv->regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PL4].msr =
MSR_VR_CURRENT_CONFIG;
pr_info("PL4 support detected.\n");
}
diff --git a/drivers/powercap/intel_rapl_tpmi.c b/drivers/powercap/intel_rapl_tpmi.c
new file mode 100644
index 000000000000..891c90fefd8b
--- /dev/null
+++ b/drivers/powercap/intel_rapl_tpmi.c
@@ -0,0 +1,324 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * intel_rapl_tpmi: Intel RAPL driver via TPMI interface
+ *
+ * Copyright (c) 2023, Intel Corporation.
+ * All Rights Reserved.
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/auxiliary_bus.h>
+#include <linux/io.h>
+#include <linux/intel_tpmi.h>
+#include <linux/intel_rapl.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#define TPMI_RAPL_VERSION 1
+
+/* 1 header + 10 registers + 5 reserved. 8 bytes for each. */
+#define TPMI_RAPL_DOMAIN_SIZE 128
+
+enum tpmi_rapl_domain_type {
+ TPMI_RAPL_DOMAIN_INVALID,
+ TPMI_RAPL_DOMAIN_SYSTEM,
+ TPMI_RAPL_DOMAIN_PACKAGE,
+ TPMI_RAPL_DOMAIN_RESERVED,
+ TPMI_RAPL_DOMAIN_MEMORY,
+ TPMI_RAPL_DOMAIN_MAX,
+};
+
+enum tpmi_rapl_register {
+ TPMI_RAPL_REG_HEADER,
+ TPMI_RAPL_REG_UNIT,
+ TPMI_RAPL_REG_PL1,
+ TPMI_RAPL_REG_PL2,
+ TPMI_RAPL_REG_PL3,
+ TPMI_RAPL_REG_PL4,
+ TPMI_RAPL_REG_RESERVED,
+ TPMI_RAPL_REG_ENERGY_STATUS,
+ TPMI_RAPL_REG_PERF_STATUS,
+ TPMI_RAPL_REG_POWER_INFO,
+ TPMI_RAPL_REG_INTERRUPT,
+ TPMI_RAPL_REG_MAX = 15,
+};
+
+struct tpmi_rapl_package {
+ struct rapl_if_priv priv;
+ struct intel_tpmi_plat_info *tpmi_info;
+ struct rapl_package *rp;
+ void __iomem *base;
+ struct list_head node;
+};
+
+static LIST_HEAD(tpmi_rapl_packages);
+static DEFINE_MUTEX(tpmi_rapl_lock);
+
+static struct powercap_control_type *tpmi_control_type;
+
+static int tpmi_rapl_read_raw(int id, struct reg_action *ra)
+{
+ if (!ra->reg.mmio)
+ return -EINVAL;
+
+ ra->value = readq(ra->reg.mmio);
+
+ ra->value &= ra->mask;
+ return 0;
+}
+
+static int tpmi_rapl_write_raw(int id, struct reg_action *ra)
+{
+ u64 val;
+
+ if (!ra->reg.mmio)
+ return -EINVAL;
+
+ val = readq(ra->reg.mmio);
+
+ val &= ~ra->mask;
+ val |= ra->value;
+
+ writeq(val, ra->reg.mmio);
+ return 0;
+}
+
+static struct tpmi_rapl_package *trp_alloc(int pkg_id)
+{
+ struct tpmi_rapl_package *trp;
+ int ret;
+
+ mutex_lock(&tpmi_rapl_lock);
+
+ if (list_empty(&tpmi_rapl_packages)) {
+ tpmi_control_type = powercap_register_control_type(NULL, "intel-rapl", NULL);
+ if (IS_ERR(tpmi_control_type)) {
+ ret = PTR_ERR(tpmi_control_type);
+ goto err_unlock;
+ }
+ }
+
+ trp = kzalloc(sizeof(*trp), GFP_KERNEL);
+ if (!trp) {
+ ret = -ENOMEM;
+ goto err_del_powercap;
+ }
+
+ list_add(&trp->node, &tpmi_rapl_packages);
+
+ mutex_unlock(&tpmi_rapl_lock);
+ return trp;
+
+err_del_powercap:
+ if (list_empty(&tpmi_rapl_packages))
+ powercap_unregister_control_type(tpmi_control_type);
+err_unlock:
+ mutex_unlock(&tpmi_rapl_lock);
+ return ERR_PTR(ret);
+}
+
+static void trp_release(struct tpmi_rapl_package *trp)
+{
+ mutex_lock(&tpmi_rapl_lock);
+ list_del(&trp->node);
+
+ if (list_empty(&tpmi_rapl_packages))
+ powercap_unregister_control_type(tpmi_control_type);
+
+ kfree(trp);
+ mutex_unlock(&tpmi_rapl_lock);
+}
+
+static int parse_one_domain(struct tpmi_rapl_package *trp, u32 offset)
+{
+ u8 tpmi_domain_version;
+ enum rapl_domain_type domain_type;
+ enum tpmi_rapl_domain_type tpmi_domain_type;
+ enum tpmi_rapl_register reg_index;
+ enum rapl_domain_reg_id reg_id;
+ int tpmi_domain_size, tpmi_domain_flags;
+ u64 tpmi_domain_header = readq(trp->base + offset);
+
+ /* Domain Parent bits are ignored for now */
+ tpmi_domain_version = tpmi_domain_header & 0xff;
+ tpmi_domain_type = tpmi_domain_header >> 8 & 0xff;
+ tpmi_domain_size = tpmi_domain_header >> 16 & 0xff;
+ tpmi_domain_flags = tpmi_domain_header >> 32 & 0xffff;
+
+ if (tpmi_domain_version != TPMI_RAPL_VERSION) {
+ pr_warn(FW_BUG "Unsupported version:%d\n", tpmi_domain_version);
+ return -ENODEV;
+ }
+
+ /* Domain size: in unit of 128 Bytes */
+ if (tpmi_domain_size != 1) {
+ pr_warn(FW_BUG "Invalid Domain size %d\n", tpmi_domain_size);
+ return -EINVAL;
+ }
+
+ /* Unit register and Energy Status register are mandatory for each domain */
+ if (!(tpmi_domain_flags & BIT(TPMI_RAPL_REG_UNIT)) ||
+ !(tpmi_domain_flags & BIT(TPMI_RAPL_REG_ENERGY_STATUS))) {
+ pr_warn(FW_BUG "Invalid Domain flag 0x%x\n", tpmi_domain_flags);
+ return -EINVAL;
+ }
+
+ switch (tpmi_domain_type) {
+ case TPMI_RAPL_DOMAIN_PACKAGE:
+ domain_type = RAPL_DOMAIN_PACKAGE;
+ break;
+ case TPMI_RAPL_DOMAIN_SYSTEM:
+ domain_type = RAPL_DOMAIN_PLATFORM;
+ break;
+ case TPMI_RAPL_DOMAIN_MEMORY:
+ domain_type = RAPL_DOMAIN_DRAM;
+ break;
+ default:
+ pr_warn(FW_BUG "Unsupported Domain type %d\n", tpmi_domain_type);
+ return -EINVAL;
+ }
+
+ if (trp->priv.regs[domain_type][RAPL_DOMAIN_REG_UNIT].mmio) {
+ pr_warn(FW_BUG "Duplicate Domain type %d\n", tpmi_domain_type);
+ return -EINVAL;
+ }
+
+ reg_index = TPMI_RAPL_REG_HEADER;
+ while (++reg_index != TPMI_RAPL_REG_MAX) {
+ if (!(tpmi_domain_flags & BIT(reg_index)))
+ continue;
+
+ switch (reg_index) {
+ case TPMI_RAPL_REG_UNIT:
+ reg_id = RAPL_DOMAIN_REG_UNIT;
+ break;
+ case TPMI_RAPL_REG_PL1:
+ reg_id = RAPL_DOMAIN_REG_LIMIT;
+ trp->priv.limits[domain_type] |= BIT(POWER_LIMIT1);
+ break;
+ case TPMI_RAPL_REG_PL2:
+ reg_id = RAPL_DOMAIN_REG_PL2;
+ trp->priv.limits[domain_type] |= BIT(POWER_LIMIT2);
+ break;
+ case TPMI_RAPL_REG_PL4:
+ reg_id = RAPL_DOMAIN_REG_PL4;
+ trp->priv.limits[domain_type] |= BIT(POWER_LIMIT4);
+ break;
+ case TPMI_RAPL_REG_ENERGY_STATUS:
+ reg_id = RAPL_DOMAIN_REG_STATUS;
+ break;
+ case TPMI_RAPL_REG_PERF_STATUS:
+ reg_id = RAPL_DOMAIN_REG_PERF;
+ break;
+ case TPMI_RAPL_REG_POWER_INFO:
+ reg_id = RAPL_DOMAIN_REG_INFO;
+ break;
+ default:
+ continue;
+ }
+ trp->priv.regs[domain_type][reg_id].mmio = trp->base + offset + reg_index * 8;
+ }
+
+ return 0;
+}
+
+static int intel_rapl_tpmi_probe(struct auxiliary_device *auxdev,
+ const struct auxiliary_device_id *id)
+{
+ struct tpmi_rapl_package *trp;
+ struct intel_tpmi_plat_info *info;
+ struct resource *res;
+ u32 offset;
+ int ret;
+
+ info = tpmi_get_platform_data(auxdev);
+ if (!info)
+ return -ENODEV;
+
+ trp = trp_alloc(info->package_id);
+ if (IS_ERR(trp))
+ return PTR_ERR(trp);
+
+ if (tpmi_get_resource_count(auxdev) > 1) {
+ dev_err(&auxdev->dev, "does not support multiple resources\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ res = tpmi_get_resource_at_index(auxdev, 0);
+ if (!res) {
+ dev_err(&auxdev->dev, "can't fetch device resource info\n");
+ ret = -EIO;
+ goto err;
+ }
+
+ trp->base = devm_ioremap_resource(&auxdev->dev, res);
+ if (IS_ERR(trp->base)) {
+ ret = PTR_ERR(trp->base);
+ goto err;
+ }
+
+ for (offset = 0; offset < resource_size(res); offset += TPMI_RAPL_DOMAIN_SIZE) {
+ ret = parse_one_domain(trp, offset);
+ if (ret)
+ goto err;
+ }
+
+ trp->tpmi_info = info;
+ trp->priv.type = RAPL_IF_TPMI;
+ trp->priv.read_raw = tpmi_rapl_read_raw;
+ trp->priv.write_raw = tpmi_rapl_write_raw;
+ trp->priv.control_type = tpmi_control_type;
+
+ /* RAPL TPMI I/F is per physical package */
+ trp->rp = rapl_find_package_domain(info->package_id, &trp->priv, false);
+ if (trp->rp) {
+ dev_err(&auxdev->dev, "Domain for Package%d already exists\n", info->package_id);
+ ret = -EEXIST;
+ goto err;
+ }
+
+ trp->rp = rapl_add_package(info->package_id, &trp->priv, false);
+ if (IS_ERR(trp->rp)) {
+ dev_err(&auxdev->dev, "Failed to add RAPL Domain for Package%d, %ld\n",
+ info->package_id, PTR_ERR(trp->rp));
+ ret = PTR_ERR(trp->rp);
+ goto err;
+ }
+
+ auxiliary_set_drvdata(auxdev, trp);
+
+ return 0;
+err:
+ trp_release(trp);
+ return ret;
+}
+
+static void intel_rapl_tpmi_remove(struct auxiliary_device *auxdev)
+{
+ struct tpmi_rapl_package *trp = auxiliary_get_drvdata(auxdev);
+
+ rapl_remove_package(trp->rp);
+ trp_release(trp);
+}
+
+static const struct auxiliary_device_id intel_rapl_tpmi_ids[] = {
+ {.name = "intel_vsec.tpmi-rapl" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(auxiliary, intel_rapl_tpmi_ids);
+
+static struct auxiliary_driver intel_rapl_tpmi_driver = {
+ .probe = intel_rapl_tpmi_probe,
+ .remove = intel_rapl_tpmi_remove,
+ .id_table = intel_rapl_tpmi_ids,
+};
+
+module_auxiliary_driver(intel_rapl_tpmi_driver)
+
+MODULE_IMPORT_NS(INTEL_TPMI);
+
+MODULE_DESCRIPTION("Intel RAPL TPMI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index b00201d81313..32dff1b4f891 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -102,7 +102,7 @@ config PTP_1588_CLOCK_INES
config PTP_1588_CLOCK_PCH
tristate "Intel PCH EG20T as PTP clock"
- depends on X86_32 || COMPILE_TEST
+ depends on MIPS_GENERIC || X86_32 || COMPILE_TEST
depends on HAS_IOMEM && PCI
depends on NET
depends on PTP_1588_CLOCK
diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
index af3bc65c4595..362bf756e6b7 100644
--- a/drivers/ptp/ptp_chardev.c
+++ b/drivers/ptp/ptp_chardev.c
@@ -136,7 +136,10 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
caps.pps = ptp->info->pps;
caps.n_pins = ptp->info->n_pins;
caps.cross_timestamping = ptp->info->getcrosststamp != NULL;
- caps.adjust_phase = ptp->info->adjphase != NULL;
+ caps.adjust_phase = ptp->info->adjphase != NULL &&
+ ptp->info->getmaxphase != NULL;
+ if (caps.adjust_phase)
+ caps.max_phase_adj = ptp->info->getmaxphase(ptp->info);
if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
err = -EFAULT;
break;
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index 790f9250b381..80f74e38c2da 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -135,11 +135,15 @@ static int ptp_clock_adjtime(struct posix_clock *pc, struct __kernel_timex *tx)
ptp->dialed_frequency = tx->freq;
} else if (tx->modes & ADJ_OFFSET) {
if (ops->adjphase) {
+ s32 max_phase_adj = ops->getmaxphase(ops);
s32 offset = tx->offset;
if (!(tx->modes & ADJ_NANO))
offset *= NSEC_PER_USEC;
+ if (offset > max_phase_adj || offset < -max_phase_adj)
+ return -ERANGE;
+
err = ops->adjphase(ops, offset);
}
} else if (tx->modes == 0) {
diff --git a/drivers/ptp/ptp_clockmatrix.c b/drivers/ptp/ptp_clockmatrix.c
index c9d451bf89e2..f6f9d4adce04 100644
--- a/drivers/ptp/ptp_clockmatrix.c
+++ b/drivers/ptp/ptp_clockmatrix.c
@@ -1692,14 +1692,23 @@ static int initialize_dco_operating_mode(struct idtcm_channel *channel)
/* PTP Hardware Clock interface */
/*
- * Maximum absolute value for write phase offset in picoseconds
- *
- * @channel: channel
- * @delta_ns: delta in nanoseconds
+ * Maximum absolute value for write phase offset in nanoseconds
*
* Destination signed register is 32-bit register in resolution of 50ps
*
- * 0x7fffffff * 50 = 2147483647 * 50 = 107374182350
+ * 0x7fffffff * 50 = 2147483647 * 50 = 107374182350 ps
+ * Represent 107374182350 ps as 107374182 ns
+ */
+static s32 idtcm_getmaxphase(struct ptp_clock_info *ptp __always_unused)
+{
+ return MAX_ABS_WRITE_PHASE_NANOSECONDS;
+}
+
+/*
+ * Internal function for implementing support for write phase offset
+ *
+ * @channel: channel
+ * @delta_ns: delta in nanoseconds
*/
static int _idtcm_adjphase(struct idtcm_channel *channel, s32 delta_ns)
{
@@ -1708,7 +1717,6 @@ static int _idtcm_adjphase(struct idtcm_channel *channel, s32 delta_ns)
u8 i;
u8 buf[4] = {0};
s32 phase_50ps;
- s64 offset_ps;
if (channel->mode != PTP_PLL_MODE_WRITE_PHASE) {
err = channel->configure_write_phase(channel);
@@ -1716,19 +1724,7 @@ static int _idtcm_adjphase(struct idtcm_channel *channel, s32 delta_ns)
return err;
}
- offset_ps = (s64)delta_ns * 1000;
-
- /*
- * Check for 32-bit signed max * 50:
- *
- * 0x7fffffff * 50 = 2147483647 * 50 = 107374182350
- */
- if (offset_ps > MAX_ABS_WRITE_PHASE_PICOSECONDS)
- offset_ps = MAX_ABS_WRITE_PHASE_PICOSECONDS;
- else if (offset_ps < -MAX_ABS_WRITE_PHASE_PICOSECONDS)
- offset_ps = -MAX_ABS_WRITE_PHASE_PICOSECONDS;
-
- phase_50ps = div_s64(offset_ps, 50);
+ phase_50ps = div_s64((s64)delta_ns * 1000, 50);
for (i = 0; i < 4; i++) {
buf[i] = phase_50ps & 0xff;
@@ -2048,6 +2044,7 @@ static const struct ptp_clock_info idtcm_caps = {
.n_ext_ts = MAX_TOD,
.n_pins = MAX_REF_CLK,
.adjphase = &idtcm_adjphase,
+ .getmaxphase = &idtcm_getmaxphase,
.adjfine = &idtcm_adjfine,
.adjtime = &idtcm_adjtime,
.gettime64 = &idtcm_gettime,
@@ -2064,6 +2061,7 @@ static const struct ptp_clock_info idtcm_caps_deprecated = {
.n_ext_ts = MAX_TOD,
.n_pins = MAX_REF_CLK,
.adjphase = &idtcm_adjphase,
+ .getmaxphase = &idtcm_getmaxphase,
.adjfine = &idtcm_adjfine,
.adjtime = &idtcm_adjtime_deprecated,
.gettime64 = &idtcm_gettime,
diff --git a/drivers/ptp/ptp_clockmatrix.h b/drivers/ptp/ptp_clockmatrix.h
index bf1e49409844..7c17c4f7f573 100644
--- a/drivers/ptp/ptp_clockmatrix.h
+++ b/drivers/ptp/ptp_clockmatrix.h
@@ -18,7 +18,7 @@
#define MAX_PLL (8)
#define MAX_REF_CLK (16)
-#define MAX_ABS_WRITE_PHASE_PICOSECONDS (107374182350LL)
+#define MAX_ABS_WRITE_PHASE_NANOSECONDS (107374182L)
#define TOD_MASK_ADDR (0xFFA5)
#define DEFAULT_TOD_MASK (0x04)
diff --git a/drivers/ptp/ptp_idt82p33.c b/drivers/ptp/ptp_idt82p33.c
index afc76c22271a..057190b9cd3d 100644
--- a/drivers/ptp/ptp_idt82p33.c
+++ b/drivers/ptp/ptp_idt82p33.c
@@ -978,24 +978,23 @@ static int idt82p33_enable(struct ptp_clock_info *ptp,
return err;
}
+static s32 idt82p33_getmaxphase(__always_unused struct ptp_clock_info *ptp)
+{
+ return WRITE_PHASE_OFFSET_LIMIT;
+}
+
static int idt82p33_adjwritephase(struct ptp_clock_info *ptp, s32 offset_ns)
{
struct idt82p33_channel *channel =
container_of(ptp, struct idt82p33_channel, caps);
struct idt82p33 *idt82p33 = channel->idt82p33;
- s64 offset_regval, offset_fs;
+ s64 offset_regval;
u8 val[4] = {0};
int err;
- offset_fs = (s64)(-offset_ns) * 1000000;
-
- if (offset_fs > WRITE_PHASE_OFFSET_LIMIT)
- offset_fs = WRITE_PHASE_OFFSET_LIMIT;
- else if (offset_fs < -WRITE_PHASE_OFFSET_LIMIT)
- offset_fs = -WRITE_PHASE_OFFSET_LIMIT;
-
/* Convert from phaseoffset_fs to register value */
- offset_regval = div_s64(offset_fs * 1000, IDT_T0DPLL_PHASE_RESOL);
+ offset_regval = div_s64((s64)(-offset_ns) * 1000000000ll,
+ IDT_T0DPLL_PHASE_RESOL);
val[0] = offset_regval & 0xFF;
val[1] = (offset_regval >> 8) & 0xFF;
@@ -1175,6 +1174,7 @@ static void idt82p33_caps_init(u32 index, struct ptp_clock_info *caps,
caps->n_ext_ts = MAX_PHC_PLL,
caps->n_pins = max_pins,
caps->adjphase = idt82p33_adjwritephase,
+ caps->getmaxphase = idt82p33_getmaxphase,
caps->adjfine = idt82p33_adjfine;
caps->adjtime = idt82p33_adjtime;
caps->gettime64 = idt82p33_gettime;
diff --git a/drivers/ptp/ptp_idt82p33.h b/drivers/ptp/ptp_idt82p33.h
index 8fcb0b17d207..6a63c14b6966 100644
--- a/drivers/ptp/ptp_idt82p33.h
+++ b/drivers/ptp/ptp_idt82p33.h
@@ -43,9 +43,9 @@
#define DEFAULT_OUTPUT_MASK_PLL1 DEFAULT_OUTPUT_MASK_PLL0
/**
- * @brief Maximum absolute value for write phase offset in femtoseconds
+ * @brief Maximum absolute value for write phase offset in nanoseconds
*/
-#define WRITE_PHASE_OFFSET_LIMIT (20000052084ll)
+#define WRITE_PHASE_OFFSET_LIMIT (20000l)
/** @brief Phase offset resolution
*
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index ab8cab4d1560..20a974ced8d6 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -1124,6 +1124,12 @@ ptp_ocp_null_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm)
return -EOPNOTSUPP;
}
+static s32
+ptp_ocp_null_getmaxphase(struct ptp_clock_info *ptp_info)
+{
+ return 0;
+}
+
static int
ptp_ocp_null_adjphase(struct ptp_clock_info *ptp_info, s32 phase_ns)
{
@@ -1239,6 +1245,7 @@ static const struct ptp_clock_info ptp_ocp_clock_info = {
.adjtime = ptp_ocp_adjtime,
.adjfine = ptp_ocp_null_adjfine,
.adjphase = ptp_ocp_null_adjphase,
+ .getmaxphase = ptp_ocp_null_getmaxphase,
.enable = ptp_ocp_enable,
.verify = ptp_ocp_verify,
.pps = true,
diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c
index f30b0a439470..6e4d5456a885 100644
--- a/drivers/ptp/ptp_sysfs.c
+++ b/drivers/ptp/ptp_sysfs.c
@@ -18,6 +18,17 @@ static ssize_t clock_name_show(struct device *dev,
}
static DEVICE_ATTR_RO(clock_name);
+static ssize_t max_phase_adjustment_show(struct device *dev,
+ struct device_attribute *attr,
+ char *page)
+{
+ struct ptp_clock *ptp = dev_get_drvdata(dev);
+
+ return snprintf(page, PAGE_SIZE - 1, "%d\n",
+ ptp->info->getmaxphase(ptp->info));
+}
+static DEVICE_ATTR_RO(max_phase_adjustment);
+
#define PTP_SHOW_INT(name, var) \
static ssize_t var##_show(struct device *dev, \
struct device_attribute *attr, char *page) \
@@ -309,6 +320,7 @@ static struct attribute *ptp_attrs[] = {
&dev_attr_clock_name.attr,
&dev_attr_max_adjustment.attr,
+ &dev_attr_max_phase_adjustment.attr,
&dev_attr_n_alarms.attr,
&dev_attr_n_external_timestamps.attr,
&dev_attr_n_periodic_outputs.attr,
@@ -346,6 +358,9 @@ static umode_t ptp_is_attribute_visible(struct kobject *kobj,
attr == &dev_attr_max_vclocks.attr) {
if (ptp->is_virtual_clock)
mode = 0;
+ } else if (attr == &dev_attr_max_phase_adjustment.attr) {
+ if (!info->adjphase || !info->getmaxphase)
+ mode = 0;
}
return mode;
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-atmel.c b/drivers/pwm/pwm-atmel.c
index 0c567d9623cd..5f7d286871cf 100644
--- a/drivers/pwm/pwm-atmel.c
+++ b/drivers/pwm/pwm-atmel.c
@@ -6,7 +6,7 @@
* Bo Shen <voice.shen@atmel.com>
*
* Links to reference manuals for the supported PWM chips can be found in
- * Documentation/arm/microchip.rst.
+ * Documentation/arch/arm/microchip.rst.
*
* Limitations:
* - Periods start with the inactive level.
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-pxa.c b/drivers/pwm/pwm-pxa.c
index 46ed668bd141..762429d5647f 100644
--- a/drivers/pwm/pwm-pxa.c
+++ b/drivers/pwm/pwm-pxa.c
@@ -8,7 +8,7 @@
* eric miao <eric.miao@marvell.com>
*
* Links to reference manuals for some of the supported PWM chips can be found
- * in Documentation/arm/marvell.rst.
+ * in Documentation/arch/arm/marvell.rst.
*
* Limitations:
* - When PWM is stopped, the current PWM period stops abruptly at the next
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/ras/debugfs.c b/drivers/ras/debugfs.c
index f0a6391b1146..ffb973c328e3 100644
--- a/drivers/ras/debugfs.c
+++ b/drivers/ras/debugfs.c
@@ -46,7 +46,7 @@ int __init ras_add_daemon_trace(void)
fentry = debugfs_create_file("daemon_active", S_IRUSR, ras_debugfs_dir,
NULL, &trace_fops);
- if (!fentry)
+ if (IS_ERR(fentry))
return -ENODEV;
return 0;
diff --git a/drivers/regulator/88pg86x.c b/drivers/regulator/88pg86x.c
index 74275b681f46..e6598e74ec94 100644
--- a/drivers/regulator/88pg86x.c
+++ b/drivers/regulator/88pg86x.c
@@ -104,7 +104,7 @@ static struct i2c_driver pg86x_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(pg86x_dt_ids),
},
- .probe_new = pg86x_i2c_probe,
+ .probe = pg86x_i2c_probe,
.id_table = pg86x_i2c_id,
};
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index e5f3613c15fa..823f8e6e4801 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
@@ -1033,6 +1044,14 @@ config REGULATOR_QCOM_USB_VBUS
Say M here if you want to include support for enabling the VBUS output
as a module. The module will be named "qcom_usb_vbus_regulator".
+config REGULATOR_RAA215300
+ tristate "Renesas RAA215300 driver"
+ select REGMAP_I2C
+ depends on COMMON_CLK
+ depends on I2C
+ help
+ Support for the Renesas RAA215300 PMIC.
+
config REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY
tristate "Raspberry Pi 7-inch touchscreen panel ATTINY regulator"
depends on BACKLIGHT_CLASS_DEVICE
@@ -1056,7 +1075,7 @@ config REGULATOR_RC5T583
config REGULATOR_RK808
tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power regulators"
- depends on MFD_RK808
+ depends on MFD_RK8XX
help
Select this option to enable the power regulator of ROCKCHIP
PMIC RK805,RK809&RK817,RK808 and RK818.
@@ -1397,6 +1416,17 @@ config REGULATOR_TPS6286X
high-frequency synchronous step-down converters with an I2C
interface.
+config REGULATOR_TPS6287X
+ tristate "TI TPS6287x Power Regulator"
+ depends on I2C && OF
+ select REGMAP_I2C
+ help
+ This driver supports TPS6287x voltage regulator chips. These are
+ pin-to-pin high-frequency synchronous step-down dc-dc converters
+ with an I2C interface.
+
+ If built as a module it will be called tps6287x-regulator.
+
config REGULATOR_TPS65023
tristate "TI TPS65023 Power regulators"
depends on I2C
@@ -1463,6 +1493,19 @@ config REGULATOR_TPS65219
voltage regulators. It supports software based voltage control
for different voltage domains.
+config REGULATOR_TPS6594
+ tristate "TI TPS6594 Power regulators"
+ depends on MFD_TPS6594 && OF
+ default MFD_TPS6594
+ help
+ This driver supports TPS6594 voltage regulator chips.
+ TPS6594 series of PMICs have 5 BUCKs and 4 LDOs
+ voltage regulators.
+ BUCKs 1,2,3,4 can be used in single phase or multiphase mode.
+ Part number defines which single or multiphase mode is i used.
+ It supports software based voltage control
+ for different voltage domains.
+
config REGULATOR_TPS6524X
tristate "TI TPS6524X Power regulators"
depends on SPI
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 58dfe0147cd4..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
@@ -124,6 +125,7 @@ obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
obj-$(CONFIG_REGULATOR_PBIAS) += pbias-regulator.o
obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
+obj-$(CONFIG_REGULATOR_RAA215300) += raa215300.o
obj-$(CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY) += rpi-panel-attiny-regulator.o
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
obj-$(CONFIG_REGULATOR_RK808) += rk808-regulator.o
@@ -163,6 +165,7 @@ obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
obj-$(CONFIG_REGULATOR_TPS6286X) += tps6286x-regulator.o
+obj-$(CONFIG_REGULATOR_TPS6287X) += tps6287x-regulator.o
obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
obj-$(CONFIG_REGULATOR_TPS65086) += tps65086-regulator.o
@@ -174,6 +177,7 @@ obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
+obj-$(CONFIG_REGULATOR_TPS6594) += tps6594-regulator.o
obj-$(CONFIG_REGULATOR_TPS65132) += tps65132-regulator.o
obj-$(CONFIG_REGULATOR_TPS68470) += tps68470-regulator.o
obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o twl6030-regulator.o
diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c
index 5c409ff4aa99..a504b01dd99c 100644
--- a/drivers/regulator/act8865-regulator.c
+++ b/drivers/regulator/act8865-regulator.c
@@ -791,7 +791,7 @@ static struct i2c_driver act8865_pmic_driver = {
.name = "act8865",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
- .probe_new = act8865_pmic_probe,
+ .probe = act8865_pmic_probe,
.id_table = act8865_ids,
};
diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
index c228cf6956d1..40f7dba42b5a 100644
--- a/drivers/regulator/ad5398.c
+++ b/drivers/regulator/ad5398.c
@@ -254,7 +254,7 @@ static int ad5398_probe(struct i2c_client *client)
}
static struct i2c_driver ad5398_driver = {
- .probe_new = ad5398_probe,
+ .probe = ad5398_probe,
.driver = {
.name = "ad5398",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 943172b19722..810f90f3e2a1 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -134,6 +134,11 @@
#define AXP22X_PWR_OUT_DLDO4_MASK BIT_MASK(6)
#define AXP22X_PWR_OUT_ALDO3_MASK BIT_MASK(7)
+#define AXP313A_DCDC1_NUM_VOLTAGES 107
+#define AXP313A_DCDC23_NUM_VOLTAGES 88
+#define AXP313A_DCDC_V_OUT_MASK GENMASK(6, 0)
+#define AXP313A_LDO_V_OUT_MASK GENMASK(4, 0)
+
#define AXP803_PWR_OUT_DCDC1_MASK BIT_MASK(0)
#define AXP803_PWR_OUT_DCDC2_MASK BIT_MASK(1)
#define AXP803_PWR_OUT_DCDC3_MASK BIT_MASK(2)
@@ -270,6 +275,74 @@
#define AXP813_PWR_OUT_DCDC7_MASK BIT_MASK(6)
+#define AXP15060_DCDC1_V_CTRL_MASK GENMASK(4, 0)
+#define AXP15060_DCDC2_V_CTRL_MASK GENMASK(6, 0)
+#define AXP15060_DCDC3_V_CTRL_MASK GENMASK(6, 0)
+#define AXP15060_DCDC4_V_CTRL_MASK GENMASK(6, 0)
+#define AXP15060_DCDC5_V_CTRL_MASK GENMASK(6, 0)
+#define AXP15060_DCDC6_V_CTRL_MASK GENMASK(4, 0)
+#define AXP15060_ALDO1_V_CTRL_MASK GENMASK(4, 0)
+#define AXP15060_ALDO2_V_CTRL_MASK GENMASK(4, 0)
+#define AXP15060_ALDO3_V_CTRL_MASK GENMASK(4, 0)
+#define AXP15060_ALDO4_V_CTRL_MASK GENMASK(4, 0)
+#define AXP15060_ALDO5_V_CTRL_MASK GENMASK(4, 0)
+#define AXP15060_BLDO1_V_CTRL_MASK GENMASK(4, 0)
+#define AXP15060_BLDO2_V_CTRL_MASK GENMASK(4, 0)
+#define AXP15060_BLDO3_V_CTRL_MASK GENMASK(4, 0)
+#define AXP15060_BLDO4_V_CTRL_MASK GENMASK(4, 0)
+#define AXP15060_BLDO5_V_CTRL_MASK GENMASK(4, 0)
+#define AXP15060_CLDO1_V_CTRL_MASK GENMASK(4, 0)
+#define AXP15060_CLDO2_V_CTRL_MASK GENMASK(4, 0)
+#define AXP15060_CLDO3_V_CTRL_MASK GENMASK(4, 0)
+#define AXP15060_CLDO4_V_CTRL_MASK GENMASK(5, 0)
+#define AXP15060_CPUSLDO_V_CTRL_MASK GENMASK(3, 0)
+
+#define AXP15060_PWR_OUT_DCDC1_MASK BIT_MASK(0)
+#define AXP15060_PWR_OUT_DCDC2_MASK BIT_MASK(1)
+#define AXP15060_PWR_OUT_DCDC3_MASK BIT_MASK(2)
+#define AXP15060_PWR_OUT_DCDC4_MASK BIT_MASK(3)
+#define AXP15060_PWR_OUT_DCDC5_MASK BIT_MASK(4)
+#define AXP15060_PWR_OUT_DCDC6_MASK BIT_MASK(5)
+#define AXP15060_PWR_OUT_ALDO1_MASK BIT_MASK(0)
+#define AXP15060_PWR_OUT_ALDO2_MASK BIT_MASK(1)
+#define AXP15060_PWR_OUT_ALDO3_MASK BIT_MASK(2)
+#define AXP15060_PWR_OUT_ALDO4_MASK BIT_MASK(3)
+#define AXP15060_PWR_OUT_ALDO5_MASK BIT_MASK(4)
+#define AXP15060_PWR_OUT_BLDO1_MASK BIT_MASK(5)
+#define AXP15060_PWR_OUT_BLDO2_MASK BIT_MASK(6)
+#define AXP15060_PWR_OUT_BLDO3_MASK BIT_MASK(7)
+#define AXP15060_PWR_OUT_BLDO4_MASK BIT_MASK(0)
+#define AXP15060_PWR_OUT_BLDO5_MASK BIT_MASK(1)
+#define AXP15060_PWR_OUT_CLDO1_MASK BIT_MASK(2)
+#define AXP15060_PWR_OUT_CLDO2_MASK BIT_MASK(3)
+#define AXP15060_PWR_OUT_CLDO3_MASK BIT_MASK(4)
+#define AXP15060_PWR_OUT_CLDO4_MASK BIT_MASK(5)
+#define AXP15060_PWR_OUT_CPUSLDO_MASK BIT_MASK(6)
+#define AXP15060_PWR_OUT_SW_MASK BIT_MASK(7)
+
+#define AXP15060_DCDC23_POLYPHASE_DUAL_MASK BIT_MASK(6)
+#define AXP15060_DCDC46_POLYPHASE_DUAL_MASK BIT_MASK(7)
+
+#define AXP15060_DCDC234_500mV_START 0x00
+#define AXP15060_DCDC234_500mV_STEPS 70
+#define AXP15060_DCDC234_500mV_END \
+ (AXP15060_DCDC234_500mV_START + AXP15060_DCDC234_500mV_STEPS)
+#define AXP15060_DCDC234_1220mV_START 0x47
+#define AXP15060_DCDC234_1220mV_STEPS 16
+#define AXP15060_DCDC234_1220mV_END \
+ (AXP15060_DCDC234_1220mV_START + AXP15060_DCDC234_1220mV_STEPS)
+#define AXP15060_DCDC234_NUM_VOLTAGES 88
+
+#define AXP15060_DCDC5_800mV_START 0x00
+#define AXP15060_DCDC5_800mV_STEPS 32
+#define AXP15060_DCDC5_800mV_END \
+ (AXP15060_DCDC5_800mV_START + AXP15060_DCDC5_800mV_STEPS)
+#define AXP15060_DCDC5_1140mV_START 0x21
+#define AXP15060_DCDC5_1140mV_STEPS 35
+#define AXP15060_DCDC5_1140mV_END \
+ (AXP15060_DCDC5_1140mV_START + AXP15060_DCDC5_1140mV_STEPS)
+#define AXP15060_DCDC5_NUM_VOLTAGES 69
+
#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask, _enable_val, _disable_val) \
[_family##_##_id] = { \
@@ -638,6 +711,48 @@ static const struct regulator_desc axp22x_drivevbus_regulator = {
.ops = &axp20x_ops_sw,
};
+static const struct linear_range axp313a_dcdc1_ranges[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000),
+ REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000),
+ REGULATOR_LINEAR_RANGE(1600000, 88, 106, 100000),
+};
+
+static const struct linear_range axp313a_dcdc2_ranges[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000),
+ REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000),
+};
+
+/*
+ * This is deviating from the datasheet. The values here are taken from the
+ * BSP driver and have been confirmed by measurements.
+ */
+static const struct linear_range axp313a_dcdc3_ranges[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000),
+ REGULATOR_LINEAR_RANGE(1220000, 71, 102, 20000),
+};
+
+static const struct regulator_desc axp313a_regulators[] = {
+ AXP_DESC_RANGES(AXP313A, DCDC1, "dcdc1", "vin1",
+ axp313a_dcdc1_ranges, AXP313A_DCDC1_NUM_VOLTAGES,
+ AXP313A_DCDC1_CONRTOL, AXP313A_DCDC_V_OUT_MASK,
+ AXP313A_OUTPUT_CONTROL, BIT(0)),
+ AXP_DESC_RANGES(AXP313A, DCDC2, "dcdc2", "vin2",
+ axp313a_dcdc2_ranges, AXP313A_DCDC23_NUM_VOLTAGES,
+ AXP313A_DCDC2_CONRTOL, AXP313A_DCDC_V_OUT_MASK,
+ AXP313A_OUTPUT_CONTROL, BIT(1)),
+ AXP_DESC_RANGES(AXP313A, DCDC3, "dcdc3", "vin3",
+ axp313a_dcdc3_ranges, AXP313A_DCDC23_NUM_VOLTAGES,
+ AXP313A_DCDC3_CONRTOL, AXP313A_DCDC_V_OUT_MASK,
+ AXP313A_OUTPUT_CONTROL, BIT(2)),
+ AXP_DESC(AXP313A, ALDO1, "aldo1", "vin1", 500, 3500, 100,
+ AXP313A_ALDO1_CONRTOL, AXP313A_LDO_V_OUT_MASK,
+ AXP313A_OUTPUT_CONTROL, BIT(3)),
+ AXP_DESC(AXP313A, DLDO1, "dldo1", "vin1", 500, 3500, 100,
+ AXP313A_DLDO1_CONRTOL, AXP313A_LDO_V_OUT_MASK,
+ AXP313A_OUTPUT_CONTROL, BIT(4)),
+ AXP_DESC_FIXED(AXP313A, RTC_LDO, "rtc-ldo", "vin1", 1800),
+};
+
/* DCDC ranges shared with AXP813 */
static const struct linear_range axp803_dcdc234_ranges[] = {
REGULATOR_LINEAR_RANGE(500000,
@@ -1001,6 +1116,104 @@ static const struct regulator_desc axp813_regulators[] = {
AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DC1SW_MASK),
};
+static const struct linear_range axp15060_dcdc234_ranges[] = {
+ REGULATOR_LINEAR_RANGE(500000,
+ AXP15060_DCDC234_500mV_START,
+ AXP15060_DCDC234_500mV_END,
+ 10000),
+ REGULATOR_LINEAR_RANGE(1220000,
+ AXP15060_DCDC234_1220mV_START,
+ AXP15060_DCDC234_1220mV_END,
+ 20000),
+};
+
+static const struct linear_range axp15060_dcdc5_ranges[] = {
+ REGULATOR_LINEAR_RANGE(800000,
+ AXP15060_DCDC5_800mV_START,
+ AXP15060_DCDC5_800mV_END,
+ 10000),
+ REGULATOR_LINEAR_RANGE(1140000,
+ AXP15060_DCDC5_1140mV_START,
+ AXP15060_DCDC5_1140mV_END,
+ 20000),
+};
+
+static const struct regulator_desc axp15060_regulators[] = {
+ AXP_DESC(AXP15060, DCDC1, "dcdc1", "vin1", 1500, 3400, 100,
+ AXP15060_DCDC1_V_CTRL, AXP15060_DCDC1_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC1_MASK),
+ AXP_DESC_RANGES(AXP15060, DCDC2, "dcdc2", "vin2",
+ axp15060_dcdc234_ranges, AXP15060_DCDC234_NUM_VOLTAGES,
+ AXP15060_DCDC2_V_CTRL, AXP15060_DCDC2_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC2_MASK),
+ AXP_DESC_RANGES(AXP15060, DCDC3, "dcdc3", "vin3",
+ axp15060_dcdc234_ranges, AXP15060_DCDC234_NUM_VOLTAGES,
+ AXP15060_DCDC3_V_CTRL, AXP15060_DCDC3_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC3_MASK),
+ AXP_DESC_RANGES(AXP15060, DCDC4, "dcdc4", "vin4",
+ axp15060_dcdc234_ranges, AXP15060_DCDC234_NUM_VOLTAGES,
+ AXP15060_DCDC4_V_CTRL, AXP15060_DCDC4_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC4_MASK),
+ AXP_DESC_RANGES(AXP15060, DCDC5, "dcdc5", "vin5",
+ axp15060_dcdc5_ranges, AXP15060_DCDC5_NUM_VOLTAGES,
+ AXP15060_DCDC5_V_CTRL, AXP15060_DCDC5_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC5_MASK),
+ AXP_DESC(AXP15060, DCDC6, "dcdc6", "vin6", 500, 3400, 100,
+ AXP15060_DCDC6_V_CTRL, AXP15060_DCDC6_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC6_MASK),
+ AXP_DESC(AXP15060, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
+ AXP15060_ALDO1_V_CTRL, AXP15060_ALDO1_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO1_MASK),
+ AXP_DESC(AXP15060, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
+ AXP15060_ALDO2_V_CTRL, AXP15060_ALDO2_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO2_MASK),
+ AXP_DESC(AXP15060, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
+ AXP15060_ALDO3_V_CTRL, AXP15060_ALDO3_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO3_MASK),
+ AXP_DESC(AXP15060, ALDO4, "aldo4", "aldoin", 700, 3300, 100,
+ AXP15060_ALDO4_V_CTRL, AXP15060_ALDO4_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO4_MASK),
+ AXP_DESC(AXP15060, ALDO5, "aldo5", "aldoin", 700, 3300, 100,
+ AXP15060_ALDO5_V_CTRL, AXP15060_ALDO5_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO5_MASK),
+ AXP_DESC(AXP15060, BLDO1, "bldo1", "bldoin", 700, 3300, 100,
+ AXP15060_BLDO1_V_CTRL, AXP15060_BLDO1_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_BLDO1_MASK),
+ AXP_DESC(AXP15060, BLDO2, "bldo2", "bldoin", 700, 3300, 100,
+ AXP15060_BLDO2_V_CTRL, AXP15060_BLDO2_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_BLDO2_MASK),
+ AXP_DESC(AXP15060, BLDO3, "bldo3", "bldoin", 700, 3300, 100,
+ AXP15060_BLDO3_V_CTRL, AXP15060_BLDO3_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_BLDO3_MASK),
+ AXP_DESC(AXP15060, BLDO4, "bldo4", "bldoin", 700, 3300, 100,
+ AXP15060_BLDO4_V_CTRL, AXP15060_BLDO4_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_BLDO4_MASK),
+ AXP_DESC(AXP15060, BLDO5, "bldo5", "bldoin", 700, 3300, 100,
+ AXP15060_BLDO5_V_CTRL, AXP15060_BLDO5_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_BLDO5_MASK),
+ AXP_DESC(AXP15060, CLDO1, "cldo1", "cldoin", 700, 3300, 100,
+ AXP15060_CLDO1_V_CTRL, AXP15060_CLDO1_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO1_MASK),
+ AXP_DESC(AXP15060, CLDO2, "cldo2", "cldoin", 700, 3300, 100,
+ AXP15060_CLDO2_V_CTRL, AXP15060_CLDO2_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO2_MASK),
+ AXP_DESC(AXP15060, CLDO3, "cldo3", "cldoin", 700, 3300, 100,
+ AXP15060_CLDO3_V_CTRL, AXP15060_CLDO3_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO3_MASK),
+ AXP_DESC(AXP15060, CLDO4, "cldo4", "cldoin", 700, 4200, 100,
+ AXP15060_CLDO4_V_CTRL, AXP15060_CLDO4_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO4_MASK),
+ /* Supply comes from DCDC5 */
+ AXP_DESC(AXP15060, CPUSLDO, "cpusldo", NULL, 700, 1400, 50,
+ AXP15060_CPUSLDO_V_CTRL, AXP15060_CPUSLDO_V_CTRL_MASK,
+ AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CPUSLDO_MASK),
+ /* Supply comes from DCDC1 */
+ AXP_DESC_SW(AXP15060, SW, "sw", NULL,
+ AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_SW_MASK),
+ /* Supply comes from ALDO1 */
+ AXP_DESC_FIXED(AXP15060, RTC_LDO, "rtc-ldo", NULL, 1800),
+};
+
static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
{
struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
@@ -1040,6 +1253,16 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
def = 3000;
step = 150;
break;
+ case AXP313A_ID:
+ case AXP15060_ID:
+ /* The DCDC PWM frequency seems to be fixed to 3 MHz. */
+ if (dcdcfreq != 0) {
+ dev_err(&pdev->dev,
+ "DCDC frequency on this PMIC is fixed to 3 MHz.\n");
+ return -EINVAL;
+ }
+
+ return 0;
default:
dev_err(&pdev->dev,
"Setting DCDC frequency for unsupported AXP variant\n");
@@ -1145,6 +1368,15 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work
workmode <<= id - AXP813_DCDC1;
break;
+ case AXP15060_ID:
+ reg = AXP15060_DCDC_MODE_CTRL2;
+ if (id < AXP15060_DCDC1 || id > AXP15060_DCDC6)
+ return -EINVAL;
+
+ mask = AXP22X_WORKMODE_DCDCX_MASK(id - AXP15060_DCDC1);
+ workmode <<= id - AXP15060_DCDC1;
+ break;
+
default:
/* should not happen */
WARN_ON(1);
@@ -1164,7 +1396,7 @@ static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id)
/*
* Currently in our supported AXP variants, only AXP803, AXP806,
- * and AXP813 have polyphase regulators.
+ * AXP813 and AXP15060 have polyphase regulators.
*/
switch (axp20x->variant) {
case AXP803_ID:
@@ -1196,6 +1428,17 @@ static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id)
}
break;
+ case AXP15060_ID:
+ regmap_read(axp20x->regmap, AXP15060_DCDC_MODE_CTRL1, &reg);
+
+ switch (id) {
+ case AXP15060_DCDC3:
+ return !!(reg & AXP15060_DCDC23_POLYPHASE_DUAL_MASK);
+ case AXP15060_DCDC6:
+ return !!(reg & AXP15060_DCDC46_POLYPHASE_DUAL_MASK);
+ }
+ break;
+
default:
return false;
}
@@ -1217,6 +1460,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
u32 workmode;
const char *dcdc1_name = axp22x_regulators[AXP22X_DCDC1].name;
const char *dcdc5_name = axp22x_regulators[AXP22X_DCDC5].name;
+ const char *aldo1_name = axp15060_regulators[AXP15060_ALDO1].name;
bool drivevbus = false;
switch (axp20x->variant) {
@@ -1232,6 +1476,10 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
drivevbus = of_property_read_bool(pdev->dev.parent->of_node,
"x-powers,drive-vbus-en");
break;
+ case AXP313A_ID:
+ regulators = axp313a_regulators;
+ nregulators = AXP313A_REG_ID_MAX;
+ break;
case AXP803_ID:
regulators = axp803_regulators;
nregulators = AXP803_REG_ID_MAX;
@@ -1252,6 +1500,10 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
drivevbus = of_property_read_bool(pdev->dev.parent->of_node,
"x-powers,drive-vbus-en");
break;
+ case AXP15060_ID:
+ regulators = axp15060_regulators;
+ nregulators = AXP15060_REG_ID_MAX;
+ break;
default:
dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
axp20x->variant);
@@ -1278,8 +1530,9 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
continue;
/*
- * Regulators DC1SW and DC5LDO are connected internally,
- * so we have to handle their supply names separately.
+ * Regulators DC1SW, DC5LDO and RTCLDO on AXP15060 are
+ * connected internally, so we have to handle their supply
+ * names separately.
*
* We always register the regulators in proper sequence,
* so the supply names are correctly read. See the last
@@ -1288,7 +1541,8 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
*/
if ((regulators == axp22x_regulators && i == AXP22X_DC1SW) ||
(regulators == axp803_regulators && i == AXP803_DC1SW) ||
- (regulators == axp809_regulators && i == AXP809_DC1SW)) {
+ (regulators == axp809_regulators && i == AXP809_DC1SW) ||
+ (regulators == axp15060_regulators && i == AXP15060_SW)) {
new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
GFP_KERNEL);
if (!new_desc)
@@ -1300,7 +1554,8 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
}
if ((regulators == axp22x_regulators && i == AXP22X_DC5LDO) ||
- (regulators == axp809_regulators && i == AXP809_DC5LDO)) {
+ (regulators == axp809_regulators && i == AXP809_DC5LDO) ||
+ (regulators == axp15060_regulators && i == AXP15060_CPUSLDO)) {
new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
GFP_KERNEL);
if (!new_desc)
@@ -1311,6 +1566,18 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
desc = new_desc;
}
+
+ if (regulators == axp15060_regulators && i == AXP15060_RTC_LDO) {
+ new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
+ GFP_KERNEL);
+ if (!new_desc)
+ return -ENOMEM;
+
+ *new_desc = regulators[i];
+ new_desc->supply_name = aldo1_name;
+ desc = new_desc;
+ }
+
rdev = devm_regulator_register(&pdev->dev, desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "Failed to register %s\n",
@@ -1329,19 +1596,26 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
}
/*
- * Save AXP22X DCDC1 / DCDC5 regulator names for later.
+ * Save AXP22X DCDC1 / DCDC5 / AXP15060 ALDO1 regulator names for later.
*/
if ((regulators == axp22x_regulators && i == AXP22X_DCDC1) ||
- (regulators == axp809_regulators && i == AXP809_DCDC1))
+ (regulators == axp809_regulators && i == AXP809_DCDC1) ||
+ (regulators == axp15060_regulators && i == AXP15060_DCDC1))
of_property_read_string(rdev->dev.of_node,
"regulator-name",
&dcdc1_name);
if ((regulators == axp22x_regulators && i == AXP22X_DCDC5) ||
- (regulators == axp809_regulators && i == AXP809_DCDC5))
+ (regulators == axp809_regulators && i == AXP809_DCDC5) ||
+ (regulators == axp15060_regulators && i == AXP15060_DCDC5))
of_property_read_string(rdev->dev.of_node,
"regulator-name",
&dcdc5_name);
+
+ if (regulators == axp15060_regulators && i == AXP15060_ALDO1)
+ of_property_read_string(rdev->dev.of_node,
+ "regulator-name",
+ &aldo1_name);
}
if (drivevbus) {
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 698ab7f5004b..d8e1caaf207e 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1911,19 +1911,17 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
if (err != -EEXIST)
regulator->debugfs = debugfs_create_dir(supply_name, rdev->debugfs);
- if (!regulator->debugfs) {
+ if (IS_ERR(regulator->debugfs))
rdev_dbg(rdev, "Failed to create debugfs directory\n");
- } else {
- debugfs_create_u32("uA_load", 0444, regulator->debugfs,
- &regulator->uA_load);
- debugfs_create_u32("min_uV", 0444, regulator->debugfs,
- &regulator->voltage[PM_SUSPEND_ON].min_uV);
- debugfs_create_u32("max_uV", 0444, regulator->debugfs,
- &regulator->voltage[PM_SUSPEND_ON].max_uV);
- debugfs_create_file("constraint_flags", 0444,
- regulator->debugfs, regulator,
- &constraint_flags_fops);
- }
+
+ debugfs_create_u32("uA_load", 0444, regulator->debugfs,
+ &regulator->uA_load);
+ debugfs_create_u32("min_uV", 0444, regulator->debugfs,
+ &regulator->voltage[PM_SUSPEND_ON].min_uV);
+ debugfs_create_u32("max_uV", 0444, regulator->debugfs,
+ &regulator->voltage[PM_SUSPEND_ON].max_uV);
+ debugfs_create_file("constraint_flags", 0444, regulator->debugfs,
+ regulator, &constraint_flags_fops);
/*
* Check now if the regulator is an always on regulator - if
@@ -5256,10 +5254,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
}
rdev->debugfs = debugfs_create_dir(rname, debugfs_root);
- if (IS_ERR(rdev->debugfs)) {
- rdev_warn(rdev, "Failed to create debugfs directory\n");
- return;
- }
+ if (IS_ERR(rdev->debugfs))
+ rdev_dbg(rdev, "Failed to create debugfs directory\n");
debugfs_create_u32("use_count", 0444, rdev->debugfs,
&rdev->use_count);
@@ -6179,7 +6175,7 @@ static int __init regulator_init(void)
debugfs_root = debugfs_create_dir("regulator", NULL);
if (IS_ERR(debugfs_root))
- pr_warn("regulator: Failed to create debugfs directory\n");
+ pr_debug("regulator: Failed to create debugfs directory\n");
#ifdef CONFIG_DEBUG_FS
debugfs_create_file("supply_map", 0444, debugfs_root, NULL,
diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c
index c5dd77be558b..a0621665a6d2 100644
--- a/drivers/regulator/da9063-regulator.c
+++ b/drivers/regulator/da9063-regulator.c
@@ -1028,9 +1028,12 @@ static int da9063_regulator_probe(struct platform_device *pdev)
config.of_node = da9063_reg_matches[id].of_node;
config.regmap = da9063->regmap;
- ret = da9063_check_xvp_constraints(&config);
- if (ret)
- return ret;
+ /* Checking constraints requires init_data from DT. */
+ if (config.init_data) {
+ ret = da9063_check_xvp_constraints(&config);
+ if (ret)
+ return ret;
+ }
regl->rdev = devm_regulator_register(&pdev->dev, &regl->desc,
&config);
diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c
index 6ce0fdc18b9c..122124944749 100644
--- a/drivers/regulator/da9121-regulator.c
+++ b/drivers/regulator/da9121-regulator.c
@@ -1197,7 +1197,7 @@ static struct i2c_driver da9121_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(da9121_dt_ids),
},
- .probe_new = da9121_i2c_probe,
+ .probe = da9121_i2c_probe,
.remove = da9121_i2c_remove,
.id_table = da9121_i2c_id,
};
diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c
index 4332a3b8a672..252f74ab9bc0 100644
--- a/drivers/regulator/da9210-regulator.c
+++ b/drivers/regulator/da9210-regulator.c
@@ -224,7 +224,7 @@ static struct i2c_driver da9210_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(da9210_dt_ids),
},
- .probe_new = da9210_i2c_probe,
+ .probe = da9210_i2c_probe,
.id_table = da9210_i2c_id,
};
diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c
index a2b4f6f1e34b..af383ff0fe57 100644
--- a/drivers/regulator/da9211-regulator.c
+++ b/drivers/regulator/da9211-regulator.c
@@ -555,7 +555,7 @@ static struct i2c_driver da9211_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(da9211_dt_ids),
},
- .probe_new = da9211_i2c_probe,
+ .probe = da9211_i2c_probe,
.id_table = da9211_i2c_id,
};
diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
index 130f3dbe9840..289c06e09f47 100644
--- a/drivers/regulator/fan53555.c
+++ b/drivers/regulator/fan53555.c
@@ -775,7 +775,7 @@ static struct i2c_driver fan53555_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(fan53555_dt_ids),
},
- .probe_new = fan53555_regulator_probe,
+ .probe = fan53555_regulator_probe,
.id_table = fan53555_id,
};
diff --git a/drivers/regulator/fan53880.c b/drivers/regulator/fan53880.c
index a3bebdee570e..6cb5656845f9 100644
--- a/drivers/regulator/fan53880.c
+++ b/drivers/regulator/fan53880.c
@@ -175,7 +175,7 @@ static struct i2c_driver fan53880_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = fan53880_dt_ids,
},
- .probe_new = fan53880_i2c_probe,
+ .probe = fan53880_i2c_probe,
.id_table = fan53880_i2c_id,
};
module_i2c_driver(fan53880_regulator_driver);
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index ad2237a95572..e6c999ba3fa2 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -902,8 +902,21 @@ bool regulator_is_equal(struct regulator *reg1, struct regulator *reg2)
}
EXPORT_SYMBOL_GPL(regulator_is_equal);
-static int find_closest_bigger(unsigned int target, const unsigned int *table,
- unsigned int num_sel, unsigned int *sel)
+/**
+ * regulator_find_closest_bigger - helper to find offset in ramp delay table
+ *
+ * @target: targeted ramp_delay
+ * @table: table with supported ramp delays
+ * @num_sel: number of entries in the table
+ * @sel: Pointer to store table offset
+ *
+ * This is the internal helper used by regulator_set_ramp_delay_regmap to
+ * map ramp delay to register value. It should only be used directly if
+ * regulator_set_ramp_delay_regmap cannot handle a specific device setup
+ * (e.g. because the value is split over multiple registers).
+ */
+int regulator_find_closest_bigger(unsigned int target, const unsigned int *table,
+ unsigned int num_sel, unsigned int *sel)
{
unsigned int s, tmp, max, maxsel = 0;
bool found = false;
@@ -933,11 +946,13 @@ static int find_closest_bigger(unsigned int target, const unsigned int *table,
return 0;
}
+EXPORT_SYMBOL_GPL(regulator_find_closest_bigger);
/**
* regulator_set_ramp_delay_regmap - set_ramp_delay() helper
*
* @rdev: regulator to operate on
+ * @ramp_delay: ramp-rate value given in units V/S (uV/uS)
*
* Regulators that use regmap for their register I/O can set the ramp_reg
* and ramp_mask fields in their descriptor and then use this as their
@@ -951,8 +966,8 @@ int regulator_set_ramp_delay_regmap(struct regulator_dev *rdev, int ramp_delay)
if (WARN_ON(!rdev->desc->n_ramp_values || !rdev->desc->ramp_delay_table))
return -EINVAL;
- ret = find_closest_bigger(ramp_delay, rdev->desc->ramp_delay_table,
- rdev->desc->n_ramp_values, &sel);
+ ret = regulator_find_closest_bigger(ramp_delay, rdev->desc->ramp_delay_table,
+ rdev->desc->n_ramp_values, &sel);
if (ret) {
dev_warn(rdev_get_dev(rdev),
diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c
index 3c37c4de1d82..69b4afe95e66 100644
--- a/drivers/regulator/isl6271a-regulator.c
+++ b/drivers/regulator/isl6271a-regulator.c
@@ -149,7 +149,7 @@ static struct i2c_driver isl6271a_i2c_driver = {
.name = "isl6271a",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
- .probe_new = isl6271a_probe,
+ .probe = isl6271a_probe,
.id_table = isl6271a_id,
};
diff --git a/drivers/regulator/isl9305.c b/drivers/regulator/isl9305.c
index 90bc8d054304..0f7560093091 100644
--- a/drivers/regulator/isl9305.c
+++ b/drivers/regulator/isl9305.c
@@ -198,7 +198,7 @@ static struct i2c_driver isl9305_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(isl9305_dt_ids),
},
- .probe_new = isl9305_i2c_probe,
+ .probe = isl9305_i2c_probe,
.id_table = isl9305_i2c_id,
};
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index e06f2a092b89..e1b5c45f97f4 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -449,7 +449,7 @@ static struct i2c_driver lp3971_i2c_driver = {
.name = "LP3971",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
- .probe_new = lp3971_i2c_probe,
+ .probe = lp3971_i2c_probe,
.id_table = lp3971_i2c_id,
};
diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c
index edacca8e14af..7bd6f05edd8d 100644
--- a/drivers/regulator/lp3972.c
+++ b/drivers/regulator/lp3972.c
@@ -547,7 +547,7 @@ static struct i2c_driver lp3972_i2c_driver = {
.name = "lp3972",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
- .probe_new = lp3972_i2c_probe,
+ .probe = lp3972_i2c_probe,
.id_table = lp3972_i2c_id,
};
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index a8b0969d4f31..63aa227b1813 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -947,7 +947,7 @@ static struct i2c_driver lp872x_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(lp872x_dt_ids),
},
- .probe_new = lp872x_probe,
+ .probe = lp872x_probe,
.id_table = lp872x_ids,
};
diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c
index 37b51b94fb5a..4bc310f972ed 100644
--- a/drivers/regulator/lp8755.c
+++ b/drivers/regulator/lp8755.c
@@ -442,7 +442,7 @@ static struct i2c_driver lp8755_i2c_driver = {
.name = LP8755_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
- .probe_new = lp8755_probe,
+ .probe = lp8755_probe,
.remove = lp8755_remove,
.id_table = lp8755_id,
};
diff --git a/drivers/regulator/ltc3589.c b/drivers/regulator/ltc3589.c
index 359b534d8c70..e9751c206d95 100644
--- a/drivers/regulator/ltc3589.c
+++ b/drivers/regulator/ltc3589.c
@@ -348,7 +348,7 @@ static const struct regmap_config ltc3589_regmap_config = {
.num_reg_defaults = ARRAY_SIZE(ltc3589_reg_defaults),
.use_single_read = true,
.use_single_write = true,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static irqreturn_t ltc3589_isr(int irq, void *dev_id)
@@ -477,7 +477,7 @@ static struct i2c_driver ltc3589_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(ltc3589_of_match),
},
- .probe_new = ltc3589_probe,
+ .probe = ltc3589_probe,
.id_table = ltc3589_i2c_id,
};
module_i2c_driver(ltc3589_driver);
diff --git a/drivers/regulator/ltc3676.c b/drivers/regulator/ltc3676.c
index a28e6c3460f1..73d511eb1c1d 100644
--- a/drivers/regulator/ltc3676.c
+++ b/drivers/regulator/ltc3676.c
@@ -261,7 +261,7 @@ static const struct regmap_config ltc3676_regmap_config = {
.max_register = LTC3676_CLIRQ,
.use_single_read = true,
.use_single_write = true,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static irqreturn_t ltc3676_isr(int irq, void *dev_id)
@@ -374,7 +374,7 @@ static struct i2c_driver ltc3676_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(ltc3676_of_match),
},
- .probe_new = ltc3676_regulator_probe,
+ .probe = ltc3676_regulator_probe,
.id_table = ltc3676_i2c_id,
};
module_i2c_driver(ltc3676_driver);
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
index 5d8852b2c168..90aa5b723c03 100644
--- a/drivers/regulator/max1586.c
+++ b/drivers/regulator/max1586.c
@@ -289,7 +289,7 @@ static const struct i2c_device_id max1586_id[] = {
MODULE_DEVICE_TABLE(i2c, max1586_id);
static struct i2c_driver max1586_pmic_driver = {
- .probe_new = max1586_pmic_probe,
+ .probe = max1586_pmic_probe,
.driver = {
.name = "max1586",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/regulator/max20086-regulator.c b/drivers/regulator/max20086-regulator.c
index ace1d582a191..fad31f5f435e 100644
--- a/drivers/regulator/max20086-regulator.c
+++ b/drivers/regulator/max20086-regulator.c
@@ -323,7 +323,7 @@ static struct i2c_driver max20086_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(max20086_dt_ids),
},
- .probe_new = max20086_i2c_probe,
+ .probe = max20086_i2c_probe,
.id_table = max20086_i2c_id,
};
diff --git a/drivers/regulator/max20411-regulator.c b/drivers/regulator/max20411-regulator.c
index be8169b86a89..8c09dc71b16d 100644
--- a/drivers/regulator/max20411-regulator.c
+++ b/drivers/regulator/max20411-regulator.c
@@ -156,7 +156,7 @@ static struct i2c_driver max20411_i2c_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_max20411_match_tbl,
},
- .probe_new = max20411_probe,
+ .probe = max20411_probe,
.id_table = max20411_id,
};
module_i2c_driver(max20411_i2c_driver);
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/regulator/max77826-regulator.c b/drivers/regulator/max77826-regulator.c
index ea5d4b18b464..3855f5e686d8 100644
--- a/drivers/regulator/max77826-regulator.c
+++ b/drivers/regulator/max77826-regulator.c
@@ -292,7 +292,7 @@ static struct i2c_driver max77826_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(max77826_of_match),
},
- .probe_new = max77826_i2c_probe,
+ .probe = max77826_i2c_probe,
.id_table = max77826_id,
};
module_i2c_driver(max77826_regulator_driver);
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index a517fb4e3669..24e1dfba78c8 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -246,7 +246,7 @@ static const struct i2c_device_id max8649_id[] = {
MODULE_DEVICE_TABLE(i2c, max8649_id);
static struct i2c_driver max8649_driver = {
- .probe_new = max8649_regulator_probe,
+ .probe = max8649_regulator_probe,
.driver = {
.name = "max8649",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
index d6b89f07ae9e..ede17099b727 100644
--- a/drivers/regulator/max8660.c
+++ b/drivers/regulator/max8660.c
@@ -503,7 +503,7 @@ static const struct i2c_device_id max8660_id[] = {
MODULE_DEVICE_TABLE(i2c, max8660_id);
static struct i2c_driver max8660_driver = {
- .probe_new = max8660_probe,
+ .probe = max8660_probe,
.driver = {
.name = "max8660",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/regulator/max8893.c b/drivers/regulator/max8893.c
index 10ffd77828b7..cb0e72948dd4 100644
--- a/drivers/regulator/max8893.c
+++ b/drivers/regulator/max8893.c
@@ -168,7 +168,7 @@ static const struct i2c_device_id max8893_ids[] = {
MODULE_DEVICE_TABLE(i2c, max8893_ids);
static struct i2c_driver max8893_driver = {
- .probe_new = max8893_probe_new,
+ .probe = max8893_probe_new,
.driver = {
.name = "max8893",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c
index 8ad8fe7fd263..0b0b841d214a 100644
--- a/drivers/regulator/max8952.c
+++ b/drivers/regulator/max8952.c
@@ -313,7 +313,7 @@ static const struct i2c_device_id max8952_ids[] = {
MODULE_DEVICE_TABLE(i2c, max8952_ids);
static struct i2c_driver max8952_pmic_driver = {
- .probe_new = max8952_pmic_probe,
+ .probe = max8952_pmic_probe,
.driver = {
.name = "max8952",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c
index a991a884a31b..8d5193207552 100644
--- a/drivers/regulator/max8973-regulator.c
+++ b/drivers/regulator/max8973-regulator.c
@@ -807,7 +807,7 @@ static struct i2c_driver max8973_i2c_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_max8973_match_tbl,
},
- .probe_new = max8973_probe,
+ .probe = max8973_probe,
.id_table = max8973_id,
};
diff --git a/drivers/regulator/mcp16502.c b/drivers/regulator/mcp16502.c
index 3a6d79556942..6c6f5a21362b 100644
--- a/drivers/regulator/mcp16502.c
+++ b/drivers/regulator/mcp16502.c
@@ -584,7 +584,7 @@ static const struct i2c_device_id mcp16502_i2c_id[] = {
MODULE_DEVICE_TABLE(i2c, mcp16502_i2c_id);
static struct i2c_driver mcp16502_drv = {
- .probe_new = mcp16502_probe,
+ .probe = mcp16502_probe,
.driver = {
.name = "mcp16502-regulator",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/regulator/mp5416.c b/drivers/regulator/mp5416.c
index 91e9019430b8..3886b252fbe7 100644
--- a/drivers/regulator/mp5416.c
+++ b/drivers/regulator/mp5416.c
@@ -240,7 +240,7 @@ static struct i2c_driver mp5416_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(mp5416_of_match),
},
- .probe_new = mp5416_i2c_probe,
+ .probe = mp5416_i2c_probe,
.id_table = mp5416_id,
};
module_i2c_driver(mp5416_regulator_driver);
diff --git a/drivers/regulator/mp8859.c b/drivers/regulator/mp8859.c
index b968a682f38a..b820bd6043e5 100644
--- a/drivers/regulator/mp8859.c
+++ b/drivers/regulator/mp8859.c
@@ -147,7 +147,7 @@ static struct i2c_driver mp8859_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(mp8859_dt_id),
},
- .probe_new = mp8859_i2c_probe,
+ .probe = mp8859_i2c_probe,
.id_table = mp8859_i2c_id,
};
diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c
index 250c27e462f1..ede1b1e58002 100644
--- a/drivers/regulator/mp886x.c
+++ b/drivers/regulator/mp886x.c
@@ -365,7 +365,7 @@ static struct i2c_driver mp886x_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = mp886x_dt_ids,
},
- .probe_new = mp886x_i2c_probe,
+ .probe = mp886x_i2c_probe,
.id_table = mp886x_id,
};
module_i2c_driver(mp886x_regulator_driver);
diff --git a/drivers/regulator/mpq7920.c b/drivers/regulator/mpq7920.c
index 544d41b88514..bf677c535edc 100644
--- a/drivers/regulator/mpq7920.c
+++ b/drivers/regulator/mpq7920.c
@@ -321,7 +321,7 @@ static struct i2c_driver mpq7920_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(mpq7920_of_match),
},
- .probe_new = mpq7920_i2c_probe,
+ .probe = mpq7920_i2c_probe,
.id_table = mpq7920_id,
};
module_i2c_driver(mpq7920_regulator_driver);
diff --git a/drivers/regulator/mt6311-regulator.c b/drivers/regulator/mt6311-regulator.c
index a9f0c9f725d4..b0771770cc26 100644
--- a/drivers/regulator/mt6311-regulator.c
+++ b/drivers/regulator/mt6311-regulator.c
@@ -154,7 +154,7 @@ static struct i2c_driver mt6311_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(mt6311_dt_ids),
},
- .probe_new = mt6311_i2c_probe,
+ .probe = mt6311_i2c_probe,
.id_table = mt6311_i2c_id,
};
diff --git a/drivers/regulator/mt6358-regulator.c b/drivers/regulator/mt6358-regulator.c
index c9e16bd092f6..b9cda2210c33 100644
--- a/drivers/regulator/mt6358-regulator.c
+++ b/drivers/regulator/mt6358-regulator.c
@@ -34,8 +34,10 @@ struct mt6358_regulator_info {
u32 modeset_mask;
};
+#define to_regulator_info(x) container_of((x), struct mt6358_regulator_info, desc)
+
#define MT6358_BUCK(match, vreg, min, max, step, \
- volt_ranges, vosel_mask, _da_vsel_reg, _da_vsel_mask, \
+ vosel_mask, _da_vsel_reg, _da_vsel_mask, \
_modeset_reg, _modeset_shift) \
[MT6358_ID_##vreg] = { \
.desc = { \
@@ -46,8 +48,8 @@ struct mt6358_regulator_info {
.id = MT6358_ID_##vreg, \
.owner = THIS_MODULE, \
.n_voltages = ((max) - (min)) / (step) + 1, \
- .linear_ranges = volt_ranges, \
- .n_linear_ranges = ARRAY_SIZE(volt_ranges), \
+ .min_uV = (min), \
+ .uV_step = (step), \
.vsel_reg = MT6358_BUCK_##vreg##_ELR0, \
.vsel_mask = vosel_mask, \
.enable_reg = MT6358_BUCK_##vreg##_CON0, \
@@ -87,7 +89,7 @@ struct mt6358_regulator_info {
}
#define MT6358_LDO1(match, vreg, min, max, step, \
- volt_ranges, _da_vsel_reg, _da_vsel_mask, \
+ _da_vsel_reg, _da_vsel_mask, \
vosel, vosel_mask) \
[MT6358_ID_##vreg] = { \
.desc = { \
@@ -98,8 +100,8 @@ struct mt6358_regulator_info {
.id = MT6358_ID_##vreg, \
.owner = THIS_MODULE, \
.n_voltages = ((max) - (min)) / (step) + 1, \
- .linear_ranges = volt_ranges, \
- .n_linear_ranges = ARRAY_SIZE(volt_ranges), \
+ .min_uV = (min), \
+ .uV_step = (step), \
.vsel_reg = vosel, \
.vsel_mask = vosel_mask, \
.enable_reg = MT6358_LDO_##vreg##_CON0, \
@@ -131,7 +133,7 @@ struct mt6358_regulator_info {
}
#define MT6366_BUCK(match, vreg, min, max, step, \
- volt_ranges, vosel_mask, _da_vsel_reg, _da_vsel_mask, \
+ vosel_mask, _da_vsel_reg, _da_vsel_mask, \
_modeset_reg, _modeset_shift) \
[MT6366_ID_##vreg] = { \
.desc = { \
@@ -142,8 +144,8 @@ struct mt6358_regulator_info {
.id = MT6366_ID_##vreg, \
.owner = THIS_MODULE, \
.n_voltages = ((max) - (min)) / (step) + 1, \
- .linear_ranges = volt_ranges, \
- .n_linear_ranges = ARRAY_SIZE(volt_ranges), \
+ .min_uV = (min), \
+ .uV_step = (step), \
.vsel_reg = MT6358_BUCK_##vreg##_ELR0, \
.vsel_mask = vosel_mask, \
.enable_reg = MT6358_BUCK_##vreg##_CON0, \
@@ -183,7 +185,7 @@ struct mt6358_regulator_info {
}
#define MT6366_LDO1(match, vreg, min, max, step, \
- volt_ranges, _da_vsel_reg, _da_vsel_mask, \
+ _da_vsel_reg, _da_vsel_mask, \
vosel, vosel_mask) \
[MT6366_ID_##vreg] = { \
.desc = { \
@@ -194,8 +196,8 @@ struct mt6358_regulator_info {
.id = MT6366_ID_##vreg, \
.owner = THIS_MODULE, \
.n_voltages = ((max) - (min)) / (step) + 1, \
- .linear_ranges = volt_ranges, \
- .n_linear_ranges = ARRAY_SIZE(volt_ranges), \
+ .min_uV = (min), \
+ .uV_step = (step), \
.vsel_reg = vosel, \
.vsel_mask = vosel_mask, \
.enable_reg = MT6358_LDO_##vreg##_CON0, \
@@ -226,21 +228,6 @@ struct mt6358_regulator_info {
.qi = BIT(15), \
}
-static const struct linear_range buck_volt_range1[] = {
- REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 6250),
-};
-
-static const struct linear_range buck_volt_range2[] = {
- REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 12500),
-};
-
-static const struct linear_range buck_volt_range3[] = {
- REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000),
-};
-
-static const struct linear_range buck_volt_range4[] = {
- REGULATOR_LINEAR_RANGE(1000000, 0, 0x7f, 12500),
-};
static const unsigned int vdram2_voltages[] = {
600000, 1800000,
@@ -277,7 +264,7 @@ static const unsigned int vcama_voltages[] = {
2800000, 2900000, 3000000,
};
-static const unsigned int vcn33_bt_wifi_voltages[] = {
+static const unsigned int vcn33_voltages[] = {
3300000, 3400000, 3500000,
};
@@ -321,7 +308,7 @@ static const u32 vcama_idx[] = {
0, 7, 9, 10, 11, 12,
};
-static const u32 vcn33_bt_wifi_idx[] = {
+static const u32 vcn33_idx[] = {
1, 2, 3,
};
@@ -342,9 +329,9 @@ static unsigned int mt6358_map_mode(unsigned int mode)
static int mt6358_set_voltage_sel(struct regulator_dev *rdev,
unsigned int selector)
{
+ const struct mt6358_regulator_info *info = to_regulator_info(rdev->desc);
int idx, ret;
const u32 *pvol;
- struct mt6358_regulator_info *info = rdev_get_drvdata(rdev);
pvol = info->index_table;
@@ -358,9 +345,9 @@ static int mt6358_set_voltage_sel(struct regulator_dev *rdev,
static int mt6358_get_voltage_sel(struct regulator_dev *rdev)
{
+ const struct mt6358_regulator_info *info = to_regulator_info(rdev->desc);
int idx, ret;
u32 selector;
- struct mt6358_regulator_info *info = rdev_get_drvdata(rdev);
const u32 *pvol;
ret = regmap_read(rdev->regmap, info->desc.vsel_reg, &selector);
@@ -384,8 +371,8 @@ static int mt6358_get_voltage_sel(struct regulator_dev *rdev)
static int mt6358_get_buck_voltage_sel(struct regulator_dev *rdev)
{
+ const struct mt6358_regulator_info *info = to_regulator_info(rdev->desc);
int ret, regval;
- struct mt6358_regulator_info *info = rdev_get_drvdata(rdev);
ret = regmap_read(rdev->regmap, info->da_vsel_reg, &regval);
if (ret != 0) {
@@ -402,9 +389,9 @@ static int mt6358_get_buck_voltage_sel(struct regulator_dev *rdev)
static int mt6358_get_status(struct regulator_dev *rdev)
{
+ const struct mt6358_regulator_info *info = to_regulator_info(rdev->desc);
int ret;
u32 regval;
- struct mt6358_regulator_info *info = rdev_get_drvdata(rdev);
ret = regmap_read(rdev->regmap, info->status_reg, &regval);
if (ret != 0) {
@@ -418,7 +405,7 @@ static int mt6358_get_status(struct regulator_dev *rdev)
static int mt6358_regulator_set_mode(struct regulator_dev *rdev,
unsigned int mode)
{
- struct mt6358_regulator_info *info = rdev_get_drvdata(rdev);
+ const struct mt6358_regulator_info *info = to_regulator_info(rdev->desc);
int val;
switch (mode) {
@@ -443,7 +430,7 @@ static int mt6358_regulator_set_mode(struct regulator_dev *rdev,
static unsigned int mt6358_regulator_get_mode(struct regulator_dev *rdev)
{
- struct mt6358_regulator_info *info = rdev_get_drvdata(rdev);
+ const struct mt6358_regulator_info *info = to_regulator_info(rdev->desc);
int ret, regval;
ret = regmap_read(rdev->regmap, info->modeset_reg, &regval);
@@ -464,8 +451,8 @@ static unsigned int mt6358_regulator_get_mode(struct regulator_dev *rdev)
}
static const struct regulator_ops mt6358_volt_range_ops = {
- .list_voltage = regulator_list_voltage_linear_range,
- .map_voltage = regulator_map_voltage_linear_range,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = mt6358_get_buck_voltage_sel,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
@@ -498,37 +485,25 @@ static const struct regulator_ops mt6358_volt_fixed_ops = {
};
/* The array is indexed by id(MT6358_ID_XXX) */
-static struct mt6358_regulator_info mt6358_regulators[] = {
+static const struct mt6358_regulator_info mt6358_regulators[] = {
MT6358_BUCK("buck_vdram1", VDRAM1, 500000, 2087500, 12500,
- buck_volt_range2, 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f,
- MT6358_VDRAM1_ANA_CON0, 8),
+ 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f, MT6358_VDRAM1_ANA_CON0, 8),
MT6358_BUCK("buck_vcore", VCORE, 500000, 1293750, 6250,
- buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f,
- MT6358_VCORE_VGPU_ANA_CON0, 1),
- MT6358_BUCK("buck_vcore_sshub", VCORE_SSHUB, 500000, 1293750, 6250,
- buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_SSHUB_ELR0, 0x7f,
- MT6358_VCORE_VGPU_ANA_CON0, 1),
+ 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f, MT6358_VCORE_VGPU_ANA_CON0, 1),
MT6358_BUCK("buck_vpa", VPA, 500000, 3650000, 50000,
- buck_volt_range3, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f,
- MT6358_VPA_ANA_CON0, 3),
+ 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, MT6358_VPA_ANA_CON0, 3),
MT6358_BUCK("buck_vproc11", VPROC11, 500000, 1293750, 6250,
- buck_volt_range1, 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f,
- MT6358_VPROC_ANA_CON0, 1),
+ 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f, MT6358_VPROC_ANA_CON0, 1),
MT6358_BUCK("buck_vproc12", VPROC12, 500000, 1293750, 6250,
- buck_volt_range1, 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f,
- MT6358_VPROC_ANA_CON0, 2),
+ 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f, MT6358_VPROC_ANA_CON0, 2),
MT6358_BUCK("buck_vgpu", VGPU, 500000, 1293750, 6250,
- buck_volt_range1, 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f,
- MT6358_VCORE_VGPU_ANA_CON0, 2),
+ 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f, MT6358_VCORE_VGPU_ANA_CON0, 2),
MT6358_BUCK("buck_vs2", VS2, 500000, 2087500, 12500,
- buck_volt_range2, 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f,
- MT6358_VS2_ANA_CON0, 8),
+ 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f, MT6358_VS2_ANA_CON0, 8),
MT6358_BUCK("buck_vmodem", VMODEM, 500000, 1293750, 6250,
- buck_volt_range1, 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f,
- MT6358_VMODEM_ANA_CON0, 8),
+ 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f, MT6358_VMODEM_ANA_CON0, 8),
MT6358_BUCK("buck_vs1", VS1, 1000000, 2587500, 12500,
- buck_volt_range4, 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f,
- MT6358_VS1_ANA_CON0, 8),
+ 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f, MT6358_VS1_ANA_CON0, 8),
MT6358_REG_FIXED("ldo_vrf12", VRF12,
MT6358_LDO_VRF12_CON0, 0, 1200000),
MT6358_REG_FIXED("ldo_vio18", VIO18,
@@ -566,12 +541,8 @@ static struct mt6358_regulator_info mt6358_regulators[] = {
MT6358_LDO_VCAMA1_CON0, 0, MT6358_VCAMA1_ANA_CON0, 0xf00),
MT6358_LDO("ldo_vemc", VEMC, vmch_vemc_voltages, vmch_vemc_idx,
MT6358_LDO_VEMC_CON0, 0, MT6358_VEMC_ANA_CON0, 0x700),
- MT6358_LDO("ldo_vcn33_bt", VCN33_BT, vcn33_bt_wifi_voltages,
- vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_0,
- 0, MT6358_VCN33_ANA_CON0, 0x300),
- MT6358_LDO("ldo_vcn33_wifi", VCN33_WIFI, vcn33_bt_wifi_voltages,
- vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_1,
- 0, MT6358_VCN33_ANA_CON0, 0x300),
+ MT6358_LDO("ldo_vcn33", VCN33, vcn33_voltages, vcn33_idx,
+ MT6358_LDO_VCN33_CON0_0, 0, MT6358_VCN33_ANA_CON0, 0x300),
MT6358_LDO("ldo_vcama2", VCAMA2, vcama_voltages, vcama_idx,
MT6358_LDO_VCAMA2_CON0, 0, MT6358_VCAMA2_ANA_CON0, 0xf00),
MT6358_LDO("ldo_vmc", VMC, vmc_voltages, vmc_idx,
@@ -582,55 +553,35 @@ static struct mt6358_regulator_info mt6358_regulators[] = {
MT6358_LDO("ldo_vsim2", VSIM2, vsim_voltages, vsim_idx,
MT6358_LDO_VSIM2_CON0, 0, MT6358_VSIM2_ANA_CON0, 0xf00),
MT6358_LDO1("ldo_vsram_proc11", VSRAM_PROC11, 500000, 1293750, 6250,
- buck_volt_range1, MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f00,
- MT6358_LDO_VSRAM_CON0, 0x7f),
+ MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON0, 0x7f),
MT6358_LDO1("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250,
- buck_volt_range1, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00,
- MT6358_LDO_VSRAM_CON2, 0x7f),
- MT6358_LDO1("ldo_vsram_others_sshub", VSRAM_OTHERS_SSHUB, 500000,
- 1293750, 6250, buck_volt_range1,
- MT6358_LDO_VSRAM_OTHERS_SSHUB_CON1, 0x7f,
- MT6358_LDO_VSRAM_OTHERS_SSHUB_CON1, 0x7f),
+ MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON2, 0x7f),
MT6358_LDO1("ldo_vsram_gpu", VSRAM_GPU, 500000, 1293750, 6250,
- buck_volt_range1, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00,
- MT6358_LDO_VSRAM_CON3, 0x7f),
+ MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON3, 0x7f),
MT6358_LDO1("ldo_vsram_proc12", VSRAM_PROC12, 500000, 1293750, 6250,
- buck_volt_range1, MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f00,
- MT6358_LDO_VSRAM_CON1, 0x7f),
+ MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON1, 0x7f),
};
/* The array is indexed by id(MT6366_ID_XXX) */
-static struct mt6358_regulator_info mt6366_regulators[] = {
+static const struct mt6358_regulator_info mt6366_regulators[] = {
MT6366_BUCK("buck_vdram1", VDRAM1, 500000, 2087500, 12500,
- buck_volt_range2, 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f,
- MT6358_VDRAM1_ANA_CON0, 8),
+ 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f, MT6358_VDRAM1_ANA_CON0, 8),
MT6366_BUCK("buck_vcore", VCORE, 500000, 1293750, 6250,
- buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f,
- MT6358_VCORE_VGPU_ANA_CON0, 1),
- MT6366_BUCK("buck_vcore_sshub", VCORE_SSHUB, 500000, 1293750, 6250,
- buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_SSHUB_ELR0, 0x7f,
- MT6358_VCORE_VGPU_ANA_CON0, 1),
+ 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f, MT6358_VCORE_VGPU_ANA_CON0, 1),
MT6366_BUCK("buck_vpa", VPA, 500000, 3650000, 50000,
- buck_volt_range3, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f,
- MT6358_VPA_ANA_CON0, 3),
+ 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, MT6358_VPA_ANA_CON0, 3),
MT6366_BUCK("buck_vproc11", VPROC11, 500000, 1293750, 6250,
- buck_volt_range1, 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f,
- MT6358_VPROC_ANA_CON0, 1),
+ 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f, MT6358_VPROC_ANA_CON0, 1),
MT6366_BUCK("buck_vproc12", VPROC12, 500000, 1293750, 6250,
- buck_volt_range1, 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f,
- MT6358_VPROC_ANA_CON0, 2),
+ 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f, MT6358_VPROC_ANA_CON0, 2),
MT6366_BUCK("buck_vgpu", VGPU, 500000, 1293750, 6250,
- buck_volt_range1, 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f,
- MT6358_VCORE_VGPU_ANA_CON0, 2),
+ 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f, MT6358_VCORE_VGPU_ANA_CON0, 2),
MT6366_BUCK("buck_vs2", VS2, 500000, 2087500, 12500,
- buck_volt_range2, 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f,
- MT6358_VS2_ANA_CON0, 8),
+ 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f, MT6358_VS2_ANA_CON0, 8),
MT6366_BUCK("buck_vmodem", VMODEM, 500000, 1293750, 6250,
- buck_volt_range1, 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f,
- MT6358_VMODEM_ANA_CON0, 8),
+ 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f, MT6358_VMODEM_ANA_CON0, 8),
MT6366_BUCK("buck_vs1", VS1, 1000000, 2587500, 12500,
- buck_volt_range4, 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f,
- MT6358_VS1_ANA_CON0, 8),
+ 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f, MT6358_VS1_ANA_CON0, 8),
MT6366_REG_FIXED("ldo_vrf12", VRF12,
MT6358_LDO_VRF12_CON0, 0, 1200000),
MT6366_REG_FIXED("ldo_vio18", VIO18,
@@ -662,41 +613,68 @@ static struct mt6358_regulator_info mt6366_regulators[] = {
MT6358_LDO_VMCH_CON0, 0, MT6358_VMCH_ANA_CON0, 0x700),
MT6366_LDO("ldo_vemc", VEMC, vmch_vemc_voltages, vmch_vemc_idx,
MT6358_LDO_VEMC_CON0, 0, MT6358_VEMC_ANA_CON0, 0x700),
- MT6366_LDO("ldo_vcn33_bt", VCN33_BT, vcn33_bt_wifi_voltages,
- vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_0,
- 0, MT6358_VCN33_ANA_CON0, 0x300),
- MT6366_LDO("ldo_vcn33_wifi", VCN33_WIFI, vcn33_bt_wifi_voltages,
- vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_1,
- 0, MT6358_VCN33_ANA_CON0, 0x300),
+ MT6366_LDO("ldo_vcn33", VCN33, vcn33_voltages, vcn33_idx,
+ MT6358_LDO_VCN33_CON0_0, 0, MT6358_VCN33_ANA_CON0, 0x300),
MT6366_LDO("ldo_vmc", VMC, vmc_voltages, vmc_idx,
MT6358_LDO_VMC_CON0, 0, MT6358_VMC_ANA_CON0, 0xf00),
MT6366_LDO("ldo_vsim2", VSIM2, vsim_voltages, vsim_idx,
MT6358_LDO_VSIM2_CON0, 0, MT6358_VSIM2_ANA_CON0, 0xf00),
MT6366_LDO1("ldo_vsram_proc11", VSRAM_PROC11, 500000, 1293750, 6250,
- buck_volt_range1, MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f00,
- MT6358_LDO_VSRAM_CON0, 0x7f),
+ MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON0, 0x7f),
MT6366_LDO1("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250,
- buck_volt_range1, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00,
- MT6358_LDO_VSRAM_CON2, 0x7f),
- MT6366_LDO1("ldo_vsram_others_sshub", VSRAM_OTHERS_SSHUB, 500000,
- 1293750, 6250, buck_volt_range1,
- MT6358_LDO_VSRAM_OTHERS_SSHUB_CON1, 0x7f,
- MT6358_LDO_VSRAM_OTHERS_SSHUB_CON1, 0x7f),
+ MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON2, 0x7f),
MT6366_LDO1("ldo_vsram_gpu", VSRAM_GPU, 500000, 1293750, 6250,
- buck_volt_range1, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00,
- MT6358_LDO_VSRAM_CON3, 0x7f),
+ MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON3, 0x7f),
MT6366_LDO1("ldo_vsram_proc12", VSRAM_PROC12, 500000, 1293750, 6250,
- buck_volt_range1, MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f00,
- MT6358_LDO_VSRAM_CON1, 0x7f),
+ MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON1, 0x7f),
};
+static int mt6358_sync_vcn33_setting(struct device *dev)
+{
+ struct mt6397_chip *mt6397 = dev_get_drvdata(dev->parent);
+ unsigned int val;
+ int ret;
+
+ /*
+ * VCN33_WIFI and VCN33_BT are two separate enable bits for the same
+ * regulator. They share the same voltage setting and output pin.
+ * Instead of having two potentially conflicting regulators, just have
+ * one VCN33 regulator. Sync the two enable bits and only use one in
+ * the regulator device.
+ */
+ ret = regmap_read(mt6397->regmap, MT6358_LDO_VCN33_CON0_1, &val);
+ if (ret) {
+ dev_err(dev, "Failed to read VCN33_WIFI setting\n");
+ return ret;
+ }
+
+ if (!(val & BIT(0)))
+ return 0;
+
+ /* Sync VCN33_WIFI enable status to VCN33_BT */
+ ret = regmap_update_bits(mt6397->regmap, MT6358_LDO_VCN33_CON0_0, BIT(0), BIT(0));
+ if (ret) {
+ dev_err(dev, "Failed to sync VCN33_WIFI setting to VCN33_BT\n");
+ return ret;
+ }
+
+ /* Disable VCN33_WIFI */
+ ret = regmap_update_bits(mt6397->regmap, MT6358_LDO_VCN33_CON0_1, BIT(0), 0);
+ if (ret) {
+ dev_err(dev, "Failed to disable VCN33_WIFI\n");
+ return ret;
+ }
+
+ return 0;
+}
+
static int mt6358_regulator_probe(struct platform_device *pdev)
{
struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = {};
struct regulator_dev *rdev;
- struct mt6358_regulator_info *mt6358_info;
- int i, max_regulator;
+ const struct mt6358_regulator_info *mt6358_info;
+ int i, max_regulator, ret;
if (mt6397->chip_id == MT6366_CHIP_ID) {
max_regulator = MT6366_MAX_REGULATOR;
@@ -706,9 +684,12 @@ static int mt6358_regulator_probe(struct platform_device *pdev)
mt6358_info = mt6358_regulators;
}
+ ret = mt6358_sync_vcn33_setting(&pdev->dev);
+ if (ret)
+ return ret;
+
for (i = 0; i < max_regulator; i++) {
config.dev = &pdev->dev;
- config.driver_data = &mt6358_info[i];
config.regmap = mt6397->regmap;
rdev = devm_regulator_register(&pdev->dev,
diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c
index e75dd92f86ca..91bfb7e026c9 100644
--- a/drivers/regulator/pca9450-regulator.c
+++ b/drivers/regulator/pca9450-regulator.c
@@ -875,7 +875,7 @@ static struct i2c_driver pca9450_i2c_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = pca9450_of_match,
},
- .probe_new = pca9450_i2c_probe,
+ .probe = pca9450_i2c_probe,
};
module_i2c_driver(pca9450_i2c_driver);
diff --git a/drivers/regulator/pf8x00-regulator.c b/drivers/regulator/pf8x00-regulator.c
index 99a15c3be396..b0781d9a1058 100644
--- a/drivers/regulator/pf8x00-regulator.c
+++ b/drivers/regulator/pf8x00-regulator.c
@@ -610,7 +610,7 @@ static struct i2c_driver pf8x00_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = pf8x00_dt_ids,
},
- .probe_new = pf8x00_i2c_probe,
+ .probe = pf8x00_i2c_probe,
};
module_i2c_driver(pf8x00_regulator_driver);
diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c
index a9fcf6a41494..8d7e6c323324 100644
--- a/drivers/regulator/pfuze100-regulator.c
+++ b/drivers/regulator/pfuze100-regulator.c
@@ -848,7 +848,7 @@ static struct i2c_driver pfuze_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = pfuze_dt_ids,
},
- .probe_new = pfuze100_regulator_probe,
+ .probe = pfuze100_regulator_probe,
};
module_i2c_driver(pfuze_driver);
diff --git a/drivers/regulator/pv88060-regulator.c b/drivers/regulator/pv88060-regulator.c
index f170e0dd1819..aa90360fa046 100644
--- a/drivers/regulator/pv88060-regulator.c
+++ b/drivers/regulator/pv88060-regulator.c
@@ -379,7 +379,7 @@ static struct i2c_driver pv88060_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(pv88060_dt_ids),
},
- .probe_new = pv88060_i2c_probe,
+ .probe = pv88060_i2c_probe,
.id_table = pv88060_i2c_id,
};
diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c
index 133b89d5215c..7ab3e4a9bd28 100644
--- a/drivers/regulator/pv88080-regulator.c
+++ b/drivers/regulator/pv88080-regulator.c
@@ -560,7 +560,7 @@ static struct i2c_driver pv88080_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(pv88080_dt_ids),
},
- .probe_new = pv88080_i2c_probe,
+ .probe = pv88080_i2c_probe,
.id_table = pv88080_i2c_id,
};
diff --git a/drivers/regulator/pv88090-regulator.c b/drivers/regulator/pv88090-regulator.c
index 1bc33bc10992..f4acde4d56c8 100644
--- a/drivers/regulator/pv88090-regulator.c
+++ b/drivers/regulator/pv88090-regulator.c
@@ -400,7 +400,7 @@ static struct i2c_driver pv88090_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(pv88090_dt_ids),
},
- .probe_new = pv88090_i2c_probe,
+ .probe = pv88090_i2c_probe,
.id_table = pv88090_i2c_id,
};
diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c
index f3b280af0773..cd077b7c4aff 100644
--- a/drivers/regulator/qcom-rpmh-regulator.c
+++ b/drivers/regulator/qcom-rpmh-regulator.c
@@ -1068,7 +1068,7 @@ static const struct rpmh_vreg_init_data pm8550_vreg_data[] = {
RPMH_VREG("ldo9", "ldo%s9", &pmic5_pldo, "vdd-l8-l9"),
RPMH_VREG("ldo10", "ldo%s10", &pmic5_nldo515, "vdd-l1-l4-l10"),
RPMH_VREG("ldo11", "ldo%s11", &pmic5_nldo515, "vdd-l11"),
- RPMH_VREG("ldo12", "ldo%s12", &pmic5_pldo, "vdd-l12"),
+ RPMH_VREG("ldo12", "ldo%s12", &pmic5_nldo515, "vdd-l12"),
RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo, "vdd-l2-l13-l14"),
RPMH_VREG("ldo14", "ldo%s14", &pmic5_pldo, "vdd-l2-l13-l14"),
RPMH_VREG("ldo15", "ldo%s15", &pmic5_nldo515, "vdd-l15"),
diff --git a/drivers/regulator/raa215300.c b/drivers/regulator/raa215300.c
new file mode 100644
index 000000000000..24a1c89f5dbc
--- /dev/null
+++ b/drivers/regulator/raa215300.c
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Renesas RAA215300 PMIC driver
+//
+// Copyright (C) 2023 Renesas Electronics Corporation
+//
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+
+#define RAA215300_FAULT_LATCHED_STATUS_1 0x59
+#define RAA215300_FAULT_LATCHED_STATUS_2 0x5a
+#define RAA215300_FAULT_LATCHED_STATUS_3 0x5b
+#define RAA215300_FAULT_LATCHED_STATUS_4 0x5c
+#define RAA215300_FAULT_LATCHED_STATUS_6 0x5e
+
+#define RAA215300_INT_MASK_1 0x64
+#define RAA215300_INT_MASK_2 0x65
+#define RAA215300_INT_MASK_3 0x66
+#define RAA215300_INT_MASK_4 0x67
+#define RAA215300_INT_MASK_6 0x68
+
+#define RAA215300_REG_BLOCK_EN 0x6c
+#define RAA215300_HW_REV 0xf8
+
+#define RAA215300_INT_MASK_1_ALL GENMASK(5, 0)
+#define RAA215300_INT_MASK_2_ALL GENMASK(3, 0)
+#define RAA215300_INT_MASK_3_ALL GENMASK(5, 0)
+#define RAA215300_INT_MASK_4_ALL BIT(0)
+#define RAA215300_INT_MASK_6_ALL GENMASK(7, 0)
+
+#define RAA215300_REG_BLOCK_EN_RTC_EN BIT(6)
+#define RAA215300_RTC_DEFAULT_ADDR 0x6f
+
+const char *clkin_name = "clkin";
+const char *xin_name = "xin";
+static struct clk *clk;
+
+static const struct regmap_config raa215300_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xff,
+};
+
+static void raa215300_rtc_unregister_device(void *data)
+{
+ i2c_unregister_device(data);
+ if (!clk) {
+ clk_unregister_fixed_rate(clk);
+ clk = NULL;
+ }
+}
+
+static int raa215300_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 raa215300_i2c_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ const char *clk_name = xin_name;
+ unsigned int pmic_version, val;
+ struct regmap *regmap;
+ int ret;
+
+ regmap = devm_regmap_init_i2c(client, &raa215300_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "regmap i2c init failed\n");
+
+ ret = regmap_read(regmap, RAA215300_HW_REV, &pmic_version);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "HW rev read failed\n");
+
+ dev_dbg(dev, "RAA215300 PMIC version 0x%04x\n", pmic_version);
+
+ /* Clear all blocks except RTC, if enabled */
+ regmap_read(regmap, RAA215300_REG_BLOCK_EN, &val);
+ val &= RAA215300_REG_BLOCK_EN_RTC_EN;
+ regmap_write(regmap, RAA215300_REG_BLOCK_EN, val);
+
+ /*Clear the latched registers */
+ regmap_read(regmap, RAA215300_FAULT_LATCHED_STATUS_1, &val);
+ regmap_write(regmap, RAA215300_FAULT_LATCHED_STATUS_1, val);
+ regmap_read(regmap, RAA215300_FAULT_LATCHED_STATUS_2, &val);
+ regmap_write(regmap, RAA215300_FAULT_LATCHED_STATUS_2, val);
+ regmap_read(regmap, RAA215300_FAULT_LATCHED_STATUS_3, &val);
+ regmap_write(regmap, RAA215300_FAULT_LATCHED_STATUS_3, val);
+ regmap_read(regmap, RAA215300_FAULT_LATCHED_STATUS_4, &val);
+ regmap_write(regmap, RAA215300_FAULT_LATCHED_STATUS_4, val);
+ regmap_read(regmap, RAA215300_FAULT_LATCHED_STATUS_6, &val);
+ regmap_write(regmap, RAA215300_FAULT_LATCHED_STATUS_6, val);
+
+ /* Mask all the PMIC interrupts */
+ regmap_write(regmap, RAA215300_INT_MASK_1, RAA215300_INT_MASK_1_ALL);
+ regmap_write(regmap, RAA215300_INT_MASK_2, RAA215300_INT_MASK_2_ALL);
+ regmap_write(regmap, RAA215300_INT_MASK_3, RAA215300_INT_MASK_3_ALL);
+ regmap_write(regmap, RAA215300_INT_MASK_4, RAA215300_INT_MASK_4_ALL);
+ regmap_write(regmap, RAA215300_INT_MASK_6, RAA215300_INT_MASK_6_ALL);
+
+ ret = raa215300_clk_present(client, xin_name);
+ if (ret < 0) {
+ return ret;
+ } else if (!ret) {
+ ret = raa215300_clk_present(client, clkin_name);
+ if (ret < 0)
+ return ret;
+
+ clk_name = clkin_name;
+ }
+
+ if (ret) {
+ char *name = pmic_version >= 0x12 ? "isl1208" : "raa215300_a0";
+ struct device_node *np = client->dev.of_node;
+ u32 addr = RAA215300_RTC_DEFAULT_ADDR;
+ struct i2c_board_info info = {};
+ struct i2c_client *rtc_client;
+ ssize_t size;
+
+ clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 32000);
+ clk_register_clkdev(clk, clk_name, NULL);
+
+ if (np) {
+ int i;
+
+ i = of_property_match_string(np, "reg-names", "rtc");
+ if (i >= 0)
+ of_property_read_u32_index(np, "reg", i, &addr);
+ }
+
+ info.addr = addr;
+ if (client->irq > 0)
+ info.irq = client->irq;
+
+ size = strscpy(info.type, name, sizeof(info.type));
+ if (size < 0)
+ return dev_err_probe(dev, size,
+ "Invalid device name: %s\n", name);
+
+ /* Enable RTC block */
+ regmap_update_bits(regmap, RAA215300_REG_BLOCK_EN,
+ RAA215300_REG_BLOCK_EN_RTC_EN,
+ RAA215300_REG_BLOCK_EN_RTC_EN);
+
+ rtc_client = i2c_new_client_device(client->adapter, &info);
+ if (IS_ERR(rtc_client))
+ return PTR_ERR(rtc_client);
+
+ ret = devm_add_action_or_reset(dev,
+ raa215300_rtc_unregister_device,
+ rtc_client);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id raa215300_dt_match[] = {
+ { .compatible = "renesas,raa215300" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, raa215300_dt_match);
+
+static struct i2c_driver raa215300_i2c_driver = {
+ .driver = {
+ .name = "raa215300",
+ .of_match_table = raa215300_dt_match,
+ },
+ .probe_new = raa215300_i2c_probe,
+};
+module_i2c_driver(raa215300_i2c_driver);
+
+MODULE_DESCRIPTION("Renesas RAA215300 PMIC driver");
+MODULE_AUTHOR("Fabrizio Castro <fabrizio.castro.jz@renesas.com>");
+MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index 3637e81654a8..460525ed006c 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -3,9 +3,11 @@
* Regulator driver for Rockchip RK805/RK808/RK818
*
* Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
*
* Author: Chris Zhong <zyw@rock-chips.com>
* Author: Zhang Qing <zhangqing@rock-chips.com>
+ * Author: Xu Shengfei <xsf@rock-chips.com>
*
* Copyright (C) 2016 PHYTEC Messtechnik GmbH
*
@@ -39,6 +41,13 @@
#define RK818_LDO3_ON_VSEL_MASK 0xf
#define RK818_BOOST_ON_VSEL_MASK 0xe0
+#define RK806_DCDC_SLP_REG_OFFSET 0x0A
+#define RK806_NLDO_SLP_REG_OFFSET 0x05
+#define RK806_PLDO_SLP_REG_OFFSET 0x06
+
+#define RK806_BUCK_SEL_CNT 0xff
+#define RK806_LDO_SEL_CNT 0xff
+
/* Ramp rate definitions for buck1 / buck2 only */
#define RK808_RAMP_RATE_OFFSET 3
#define RK808_RAMP_RATE_MASK (3 << RK808_RAMP_RATE_OFFSET)
@@ -117,6 +126,34 @@
RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask, 0, 0, _etime, &rk805_reg_ops)
+#define RK806_REGULATOR(_name, _supply_name, _id, _ops,\
+ _n_voltages, _vr, _er, _lr, ctrl_bit,\
+ _rr, _rm, _rt)\
+[_id] = {\
+ .name = _name,\
+ .supply_name = _supply_name,\
+ .of_match = of_match_ptr(_name),\
+ .regulators_node = of_match_ptr("regulators"),\
+ .id = _id,\
+ .ops = &_ops,\
+ .type = REGULATOR_VOLTAGE,\
+ .n_voltages = _n_voltages,\
+ .linear_ranges = _lr,\
+ .n_linear_ranges = ARRAY_SIZE(_lr),\
+ .vsel_reg = _vr,\
+ .vsel_mask = 0xff,\
+ .enable_reg = _er,\
+ .enable_mask = ENABLE_MASK(ctrl_bit),\
+ .enable_val = ENABLE_MASK(ctrl_bit),\
+ .disable_val = DISABLE_VAL(ctrl_bit),\
+ .of_map_mode = rk8xx_regulator_of_map_mode,\
+ .ramp_reg = _rr,\
+ .ramp_mask = _rm,\
+ .ramp_delay_table = _rt, \
+ .n_ramp_values = ARRAY_SIZE(_rt), \
+ .owner = THIS_MODULE,\
+ }
+
#define RK8XX_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask, _etime) \
RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \
@@ -153,6 +190,17 @@
RKXX_DESC_SWITCH_COM(_id, _match, _supply, _ereg, _emask, \
0, 0, &rk808_switch_ops)
+struct rk8xx_register_bit {
+ u8 reg;
+ u8 bit;
+};
+
+#define RK8XX_REG_BIT(_reg, _bit) \
+ { \
+ .reg = _reg, \
+ .bit = BIT(_bit), \
+ }
+
struct rk808_regulator_data {
struct gpio_desc *dvs_gpio[2];
};
@@ -216,6 +264,133 @@ static const unsigned int rk817_buck1_4_ramp_table[] = {
3000, 6300, 12500, 25000
};
+static int rk806_set_mode_dcdc(struct regulator_dev *rdev, unsigned int mode)
+{
+ int rid = rdev_get_id(rdev);
+ int ctr_bit, reg;
+
+ reg = RK806_POWER_FPWM_EN0 + rid / 8;
+ ctr_bit = rid % 8;
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ return regmap_update_bits(rdev->regmap, reg,
+ PWM_MODE_MSK << ctr_bit,
+ FPWM_MODE << ctr_bit);
+ case REGULATOR_MODE_NORMAL:
+ return regmap_update_bits(rdev->regmap, reg,
+ PWM_MODE_MSK << ctr_bit,
+ AUTO_PWM_MODE << ctr_bit);
+ default:
+ dev_err(rdev_get_dev(rdev), "mode unsupported: %u\n", mode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static unsigned int rk806_get_mode_dcdc(struct regulator_dev *rdev)
+{
+ int rid = rdev_get_id(rdev);
+ int ctr_bit, reg;
+ unsigned int val;
+ int err;
+
+ reg = RK806_POWER_FPWM_EN0 + rid / 8;
+ ctr_bit = rid % 8;
+
+ err = regmap_read(rdev->regmap, reg, &val);
+ if (err)
+ return err;
+
+ if ((val >> ctr_bit) & FPWM_MODE)
+ return REGULATOR_MODE_FAST;
+ else
+ return REGULATOR_MODE_NORMAL;
+}
+
+static const struct rk8xx_register_bit rk806_dcdc_rate2[] = {
+ RK8XX_REG_BIT(0xEB, 0),
+ RK8XX_REG_BIT(0xEB, 1),
+ RK8XX_REG_BIT(0xEB, 2),
+ RK8XX_REG_BIT(0xEB, 3),
+ RK8XX_REG_BIT(0xEB, 4),
+ RK8XX_REG_BIT(0xEB, 5),
+ RK8XX_REG_BIT(0xEB, 6),
+ RK8XX_REG_BIT(0xEB, 7),
+ RK8XX_REG_BIT(0xEA, 0),
+ RK8XX_REG_BIT(0xEA, 1),
+};
+
+static const unsigned int rk806_ramp_delay_table_dcdc[] = {
+ 50000, 25000, 12500, 6250, 3125, 1560, 961, 390
+};
+
+static int rk806_set_ramp_delay_dcdc(struct regulator_dev *rdev, int ramp_delay)
+{
+ int rid = rdev_get_id(rdev);
+ int regval, ramp_value, ret;
+
+ ret = regulator_find_closest_bigger(ramp_delay, rdev->desc->ramp_delay_table,
+ rdev->desc->n_ramp_values, &ramp_value);
+ if (ret) {
+ dev_warn(rdev_get_dev(rdev),
+ "Can't set ramp-delay %u, setting %u\n", ramp_delay,
+ rdev->desc->ramp_delay_table[ramp_value]);
+ }
+
+ regval = ramp_value << (ffs(rdev->desc->ramp_mask) - 1);
+
+ ret = regmap_update_bits(rdev->regmap, rdev->desc->ramp_reg,
+ rdev->desc->ramp_mask, regval);
+ if (ret)
+ return ret;
+
+ /*
+ * The above is effectively a copy of regulator_set_ramp_delay_regmap(),
+ * but that only stores the lower 2 bits for rk806 DCDC ramp. The MSB must
+ * be stored in a separate register, so this open codes the implementation
+ * to have access to the ramp_value.
+ */
+
+ regval = (ramp_value >> 2) & 0x1 ? rk806_dcdc_rate2[rid].bit : 0;
+ return regmap_update_bits(rdev->regmap, rk806_dcdc_rate2[rid].reg,
+ rk806_dcdc_rate2[rid].bit,
+ regval);
+}
+
+static const unsigned int rk806_ramp_delay_table_ldo[] = {
+ 100000, 50000, 25000, 12500, 6280, 3120, 1900, 780
+};
+
+static int rk806_set_suspend_voltage_range(struct regulator_dev *rdev, int reg_offset, int uv)
+{
+ int sel = regulator_map_voltage_linear_range(rdev, uv, uv);
+ unsigned int reg;
+
+ if (sel < 0)
+ return -EINVAL;
+
+ reg = rdev->desc->vsel_reg + reg_offset;
+
+ return regmap_update_bits(rdev->regmap, reg, rdev->desc->vsel_mask, sel);
+}
+
+static int rk806_set_suspend_voltage_range_dcdc(struct regulator_dev *rdev, int uv)
+{
+ return rk806_set_suspend_voltage_range(rdev, RK806_DCDC_SLP_REG_OFFSET, uv);
+}
+
+static int rk806_set_suspend_voltage_range_nldo(struct regulator_dev *rdev, int uv)
+{
+ return rk806_set_suspend_voltage_range(rdev, RK806_NLDO_SLP_REG_OFFSET, uv);
+}
+
+static int rk806_set_suspend_voltage_range_pldo(struct regulator_dev *rdev, int uv)
+{
+ return rk806_set_suspend_voltage_range(rdev, RK806_PLDO_SLP_REG_OFFSET, uv);
+}
+
static int rk808_buck1_2_get_voltage_sel_regmap(struct regulator_dev *rdev)
{
struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev);
@@ -393,6 +568,47 @@ static int rk805_set_suspend_disable(struct regulator_dev *rdev)
0);
}
+static const struct rk8xx_register_bit rk806_suspend_bits[] = {
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 0),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 1),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 2),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 3),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 4),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 5),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 6),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 7),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 6),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 7),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 0),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 1),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 2),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 3),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 4),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 1),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 2),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 3),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 4),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 5),
+ RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 0),
+};
+
+static int rk806_set_suspend_enable(struct regulator_dev *rdev)
+{
+ int rid = rdev_get_id(rdev);
+
+ return regmap_update_bits(rdev->regmap, rk806_suspend_bits[rid].reg,
+ rk806_suspend_bits[rid].bit,
+ rk806_suspend_bits[rid].bit);
+}
+
+static int rk806_set_suspend_disable(struct regulator_dev *rdev)
+{
+ int rid = rdev_get_id(rdev);
+
+ return regmap_update_bits(rdev->regmap, rk806_suspend_bits[rid].reg,
+ rk806_suspend_bits[rid].bit, 0);
+}
+
static int rk808_set_suspend_enable(struct regulator_dev *rdev)
{
unsigned int reg;
@@ -561,6 +777,64 @@ static const struct regulator_ops rk805_switch_ops = {
.set_suspend_disable = rk805_set_suspend_disable,
};
+static const struct regulator_ops rk806_ops_dcdc = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_mode = rk806_set_mode_dcdc,
+ .get_mode = rk806_get_mode_dcdc,
+
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = rk8xx_is_enabled_wmsk_regmap,
+
+ .set_suspend_mode = rk806_set_mode_dcdc,
+ .set_ramp_delay = rk806_set_ramp_delay_dcdc,
+
+ .set_suspend_voltage = rk806_set_suspend_voltage_range_dcdc,
+ .set_suspend_enable = rk806_set_suspend_enable,
+ .set_suspend_disable = rk806_set_suspend_disable,
+};
+
+static const struct regulator_ops rk806_ops_nldo = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+
+ .set_ramp_delay = regulator_set_ramp_delay_regmap,
+
+ .set_suspend_voltage = rk806_set_suspend_voltage_range_nldo,
+ .set_suspend_enable = rk806_set_suspend_enable,
+ .set_suspend_disable = rk806_set_suspend_disable,
+};
+
+static const struct regulator_ops rk806_ops_pldo = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+
+ .set_ramp_delay = regulator_set_ramp_delay_regmap,
+
+ .set_suspend_voltage = rk806_set_suspend_voltage_range_pldo,
+ .set_suspend_enable = rk806_set_suspend_enable,
+ .set_suspend_disable = rk806_set_suspend_disable,
+};
+
static const struct regulator_ops rk808_buck1_2_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
@@ -743,6 +1017,112 @@ static const struct regulator_desc rk805_reg[] = {
BIT(2), 400),
};
+static const struct linear_range rk806_buck_voltage_ranges[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0, 160, 6250), /* 500mV ~ 1500mV */
+ REGULATOR_LINEAR_RANGE(1500000, 161, 237, 25000), /* 1500mV ~ 3400mV */
+ REGULATOR_LINEAR_RANGE(3400000, 238, 255, 0),
+};
+
+static const struct linear_range rk806_ldo_voltage_ranges[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0, 232, 12500), /* 500mV ~ 3400mV */
+ REGULATOR_LINEAR_RANGE(3400000, 233, 255, 0), /* 500mV ~ 3400mV */
+};
+
+static const struct regulator_desc rk806_reg[] = {
+ RK806_REGULATOR("dcdc-reg1", "vcc1", RK806_ID_DCDC1, rk806_ops_dcdc,
+ RK806_BUCK_SEL_CNT, RK806_BUCK1_ON_VSEL,
+ RK806_POWER_EN0, rk806_buck_voltage_ranges, 0,
+ RK806_BUCK1_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc),
+ RK806_REGULATOR("dcdc-reg2", "vcc2", RK806_ID_DCDC2, rk806_ops_dcdc,
+ RK806_BUCK_SEL_CNT, RK806_BUCK2_ON_VSEL,
+ RK806_POWER_EN0, rk806_buck_voltage_ranges, 1,
+ RK806_BUCK2_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc),
+ RK806_REGULATOR("dcdc-reg3", "vcc3", RK806_ID_DCDC3, rk806_ops_dcdc,
+ RK806_BUCK_SEL_CNT, RK806_BUCK3_ON_VSEL,
+ RK806_POWER_EN0, rk806_buck_voltage_ranges, 2,
+ RK806_BUCK3_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc),
+ RK806_REGULATOR("dcdc-reg4", "vcc4", RK806_ID_DCDC4, rk806_ops_dcdc,
+ RK806_BUCK_SEL_CNT, RK806_BUCK4_ON_VSEL,
+ RK806_POWER_EN0, rk806_buck_voltage_ranges, 3,
+ RK806_BUCK4_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc),
+
+ RK806_REGULATOR("dcdc-reg5", "vcc5", RK806_ID_DCDC5, rk806_ops_dcdc,
+ RK806_BUCK_SEL_CNT, RK806_BUCK5_ON_VSEL,
+ RK806_POWER_EN1, rk806_buck_voltage_ranges, 0,
+ RK806_BUCK5_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc),
+ RK806_REGULATOR("dcdc-reg6", "vcc6", RK806_ID_DCDC6, rk806_ops_dcdc,
+ RK806_BUCK_SEL_CNT, RK806_BUCK6_ON_VSEL,
+ RK806_POWER_EN1, rk806_buck_voltage_ranges, 1,
+ RK806_BUCK6_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc),
+ RK806_REGULATOR("dcdc-reg7", "vcc7", RK806_ID_DCDC7, rk806_ops_dcdc,
+ RK806_BUCK_SEL_CNT, RK806_BUCK7_ON_VSEL,
+ RK806_POWER_EN1, rk806_buck_voltage_ranges, 2,
+ RK806_BUCK7_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc),
+ RK806_REGULATOR("dcdc-reg8", "vcc8", RK806_ID_DCDC8, rk806_ops_dcdc,
+ RK806_BUCK_SEL_CNT, RK806_BUCK8_ON_VSEL,
+ RK806_POWER_EN1, rk806_buck_voltage_ranges, 3,
+ RK806_BUCK8_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc),
+
+ RK806_REGULATOR("dcdc-reg9", "vcc9", RK806_ID_DCDC9, rk806_ops_dcdc,
+ RK806_BUCK_SEL_CNT, RK806_BUCK9_ON_VSEL,
+ RK806_POWER_EN2, rk806_buck_voltage_ranges, 0,
+ RK806_BUCK9_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc),
+ RK806_REGULATOR("dcdc-reg10", "vcc10", RK806_ID_DCDC10, rk806_ops_dcdc,
+ RK806_BUCK_SEL_CNT, RK806_BUCK10_ON_VSEL,
+ RK806_POWER_EN2, rk806_buck_voltage_ranges, 1,
+ RK806_BUCK10_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc),
+
+ RK806_REGULATOR("nldo-reg1", "vcc13", RK806_ID_NLDO1, rk806_ops_nldo,
+ RK806_LDO_SEL_CNT, RK806_NLDO1_ON_VSEL,
+ RK806_POWER_EN3, rk806_ldo_voltage_ranges, 0,
+ 0xEA, 0x38, rk806_ramp_delay_table_ldo),
+ RK806_REGULATOR("nldo-reg2", "vcc13", RK806_ID_NLDO2, rk806_ops_nldo,
+ RK806_LDO_SEL_CNT, RK806_NLDO2_ON_VSEL,
+ RK806_POWER_EN3, rk806_ldo_voltage_ranges, 1,
+ 0xEA, 0x38, rk806_ramp_delay_table_ldo),
+ RK806_REGULATOR("nldo-reg3", "vcc13", RK806_ID_NLDO3, rk806_ops_nldo,
+ RK806_LDO_SEL_CNT, RK806_NLDO3_ON_VSEL,
+ RK806_POWER_EN3, rk806_ldo_voltage_ranges, 2,
+ 0xEA, 0x38, rk806_ramp_delay_table_ldo),
+ RK806_REGULATOR("nldo-reg4", "vcc14", RK806_ID_NLDO4, rk806_ops_nldo,
+ RK806_LDO_SEL_CNT, RK806_NLDO4_ON_VSEL,
+ RK806_POWER_EN3, rk806_ldo_voltage_ranges, 3,
+ 0xEA, 0x38, rk806_ramp_delay_table_ldo),
+
+ RK806_REGULATOR("nldo-reg5", "vcc14", RK806_ID_NLDO5, rk806_ops_nldo,
+ RK806_LDO_SEL_CNT, RK806_NLDO5_ON_VSEL,
+ RK806_POWER_EN5, rk806_ldo_voltage_ranges, 2,
+ 0xEA, 0x38, rk806_ramp_delay_table_ldo),
+
+ RK806_REGULATOR("pldo-reg1", "vcc11", RK806_ID_PLDO1, rk806_ops_pldo,
+ RK806_LDO_SEL_CNT, RK806_PLDO1_ON_VSEL,
+ RK806_POWER_EN4, rk806_ldo_voltage_ranges, 1,
+ 0xEA, 0x38, rk806_ramp_delay_table_ldo),
+ RK806_REGULATOR("pldo-reg2", "vcc11", RK806_ID_PLDO2, rk806_ops_pldo,
+ RK806_LDO_SEL_CNT, RK806_PLDO2_ON_VSEL,
+ RK806_POWER_EN4, rk806_ldo_voltage_ranges, 2,
+ 0xEA, 0x38, rk806_ramp_delay_table_ldo),
+ RK806_REGULATOR("pldo-reg3", "vcc11", RK806_ID_PLDO3, rk806_ops_pldo,
+ RK806_LDO_SEL_CNT, RK806_PLDO3_ON_VSEL,
+ RK806_POWER_EN4, rk806_ldo_voltage_ranges, 3,
+ 0xEA, 0x38, rk806_ramp_delay_table_ldo),
+
+ RK806_REGULATOR("pldo-reg4", "vcc12", RK806_ID_PLDO4, rk806_ops_pldo,
+ RK806_LDO_SEL_CNT, RK806_PLDO4_ON_VSEL,
+ RK806_POWER_EN5, rk806_ldo_voltage_ranges, 0,
+ 0xEA, 0x38, rk806_ramp_delay_table_ldo),
+ RK806_REGULATOR("pldo-reg5", "vcc12", RK806_ID_PLDO5, rk806_ops_pldo,
+ RK806_LDO_SEL_CNT, RK806_PLDO5_ON_VSEL,
+ RK806_POWER_EN5, rk806_ldo_voltage_ranges, 1,
+ 0xEA, 0x38, rk806_ramp_delay_table_ldo),
+
+ RK806_REGULATOR("pldo-reg6", "vcca", RK806_ID_PLDO6, rk806_ops_pldo,
+ RK806_LDO_SEL_CNT, RK806_PLDO6_ON_VSEL,
+ RK806_POWER_EN4, rk806_ldo_voltage_ranges, 0,
+ 0xEA, 0x38, rk806_ramp_delay_table_ldo),
+};
+
+
static const struct regulator_desc rk808_reg[] = {
{
.name = "DCDC_REG1",
@@ -1245,20 +1625,19 @@ static const struct regulator_desc rk818_reg[] = {
};
static int rk808_regulator_dt_parse_pdata(struct device *dev,
- struct device *client_dev,
struct regmap *map,
struct rk808_regulator_data *pdata)
{
struct device_node *np;
int tmp, ret = 0, i;
- np = of_get_child_by_name(client_dev->of_node, "regulators");
+ np = of_get_child_by_name(dev->of_node, "regulators");
if (!np)
return -ENXIO;
for (i = 0; i < ARRAY_SIZE(pdata->dvs_gpio); i++) {
pdata->dvs_gpio[i] =
- devm_gpiod_get_index_optional(client_dev, "dvs", i,
+ devm_gpiod_get_index_optional(dev, "dvs", i,
GPIOD_OUT_LOW);
if (IS_ERR(pdata->dvs_gpio[i])) {
ret = PTR_ERR(pdata->dvs_gpio[i]);
@@ -1292,6 +1671,9 @@ static int rk808_regulator_probe(struct platform_device *pdev)
struct regmap *regmap;
int ret, i, nregulators;
+ pdev->dev.of_node = pdev->dev.parent->of_node;
+ pdev->dev.of_node_reused = true;
+
regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!regmap)
return -ENODEV;
@@ -1300,8 +1682,7 @@ static int rk808_regulator_probe(struct platform_device *pdev)
if (!pdata)
return -ENOMEM;
- ret = rk808_regulator_dt_parse_pdata(&pdev->dev, pdev->dev.parent,
- regmap, pdata);
+ ret = rk808_regulator_dt_parse_pdata(&pdev->dev, regmap, pdata);
if (ret < 0)
return ret;
@@ -1312,6 +1693,10 @@ static int rk808_regulator_probe(struct platform_device *pdev)
regulators = rk805_reg;
nregulators = RK805_NUM_REGULATORS;
break;
+ case RK806_ID:
+ regulators = rk806_reg;
+ nregulators = ARRAY_SIZE(rk806_reg);
+ break;
case RK808_ID:
regulators = rk808_reg;
nregulators = RK808_NUM_REGULATORS;
@@ -1335,7 +1720,6 @@ static int rk808_regulator_probe(struct platform_device *pdev)
}
config.dev = &pdev->dev;
- config.dev->of_node = pdev->dev.parent->of_node;
config.driver_data = pdata;
config.regmap = regmap;
@@ -1355,7 +1739,7 @@ static struct platform_driver rk808_regulator_driver = {
.probe = rk808_regulator_probe,
.driver = {
.name = "rk808-regulator",
- .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ .probe_type = PROBE_FORCE_SYNCHRONOUS,
},
};
@@ -1366,5 +1750,6 @@ MODULE_AUTHOR("Tony xie <tony.xie@rock-chips.com>");
MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
+MODULE_AUTHOR("Xu Shengfei <xsf@rock-chips.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:rk808-regulator");
diff --git a/drivers/regulator/rpi-panel-attiny-regulator.c b/drivers/regulator/rpi-panel-attiny-regulator.c
index 9afe961a87f1..e9719a378a0b 100644
--- a/drivers/regulator/rpi-panel-attiny-regulator.c
+++ b/drivers/regulator/rpi-panel-attiny-regulator.c
@@ -399,7 +399,7 @@ static struct i2c_driver attiny_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(attiny_dt_ids),
},
- .probe_new = attiny_i2c_probe,
+ .probe = attiny_i2c_probe,
.remove = attiny_i2c_remove,
};
diff --git a/drivers/regulator/rt4801-regulator.c b/drivers/regulator/rt4801-regulator.c
index be3dc981195c..4955bfea4e84 100644
--- a/drivers/regulator/rt4801-regulator.c
+++ b/drivers/regulator/rt4801-regulator.c
@@ -242,7 +242,7 @@ static struct i2c_driver rt4801_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(rt4801_of_id),
},
- .probe_new = rt4801_probe,
+ .probe = rt4801_probe,
};
module_i2c_driver(rt4801_driver);
diff --git a/drivers/regulator/rt5190a-regulator.c b/drivers/regulator/rt5190a-regulator.c
index f6c12f87fb8d..a53ed523b5d7 100644
--- a/drivers/regulator/rt5190a-regulator.c
+++ b/drivers/regulator/rt5190a-regulator.c
@@ -508,7 +508,7 @@ static struct i2c_driver rt5190a_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = rt5190a_device_table,
},
- .probe_new = rt5190a_probe,
+ .probe = rt5190a_probe,
};
module_i2c_driver(rt5190a_driver);
diff --git a/drivers/regulator/rt5739.c b/drivers/regulator/rt5739.c
index 74fc5bf6d87e..0ce6a1666752 100644
--- a/drivers/regulator/rt5739.c
+++ b/drivers/regulator/rt5739.c
@@ -282,7 +282,7 @@ static struct i2c_driver rt5739_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = rt5739_device_table,
},
- .probe_new = rt5739_probe,
+ .probe = rt5739_probe,
};
module_i2c_driver(rt5739_driver);
diff --git a/drivers/regulator/rt5759-regulator.c b/drivers/regulator/rt5759-regulator.c
index d5a42ad21a9a..90555a9ef1b0 100644
--- a/drivers/regulator/rt5759-regulator.c
+++ b/drivers/regulator/rt5759-regulator.c
@@ -362,7 +362,7 @@ static struct i2c_driver rt5759_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(rt5759_device_table),
},
- .probe_new = rt5759_probe,
+ .probe = rt5759_probe,
};
module_i2c_driver(rt5759_driver);
diff --git a/drivers/regulator/rt6160-regulator.c b/drivers/regulator/rt6160-regulator.c
index 8990dac23460..e2a0eee95c61 100644
--- a/drivers/regulator/rt6160-regulator.c
+++ b/drivers/regulator/rt6160-regulator.c
@@ -311,7 +311,7 @@ static struct i2c_driver rt6160_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = rt6160_of_match_table,
},
- .probe_new = rt6160_probe,
+ .probe = rt6160_probe,
};
module_i2c_driver(rt6160_driver);
diff --git a/drivers/regulator/rt6190-regulator.c b/drivers/regulator/rt6190-regulator.c
index ca91a1f6d3c8..3883440295ed 100644
--- a/drivers/regulator/rt6190-regulator.c
+++ b/drivers/regulator/rt6190-regulator.c
@@ -487,7 +487,7 @@ static struct i2c_driver rt6190_driver = {
.of_match_table = rt6190_of_dev_table,
.pm = pm_ptr(&rt6190_dev_pm),
},
- .probe_new = rt6190_probe,
+ .probe = rt6190_probe,
};
module_i2c_driver(rt6190_driver);
diff --git a/drivers/regulator/rt6245-regulator.c b/drivers/regulator/rt6245-regulator.c
index 8721d11c7964..1843ecec1922 100644
--- a/drivers/regulator/rt6245-regulator.c
+++ b/drivers/regulator/rt6245-regulator.c
@@ -246,7 +246,7 @@ static struct i2c_driver rt6245_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = rt6245_of_match_table,
},
- .probe_new = rt6245_probe,
+ .probe = rt6245_probe,
};
module_i2c_driver(rt6245_driver);
diff --git a/drivers/regulator/rtmv20-regulator.c b/drivers/regulator/rtmv20-regulator.c
index 7cbb812477e1..dfd1522637e4 100644
--- a/drivers/regulator/rtmv20-regulator.c
+++ b/drivers/regulator/rtmv20-regulator.c
@@ -429,7 +429,7 @@ static struct i2c_driver rtmv20_driver = {
.of_match_table = of_match_ptr(rtmv20_of_id),
.pm = &rtmv20_pm,
},
- .probe_new = rtmv20_probe,
+ .probe = rtmv20_probe,
};
module_i2c_driver(rtmv20_driver);
diff --git a/drivers/regulator/rtq2134-regulator.c b/drivers/regulator/rtq2134-regulator.c
index ee1577dc3cfc..b7372cb2b97d 100644
--- a/drivers/regulator/rtq2134-regulator.c
+++ b/drivers/regulator/rtq2134-regulator.c
@@ -366,7 +366,7 @@ static struct i2c_driver rtq2134_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = rtq2134_device_tables,
},
- .probe_new = rtq2134_probe,
+ .probe = rtq2134_probe,
};
module_i2c_driver(rtq2134_driver);
diff --git a/drivers/regulator/rtq6752-regulator.c b/drivers/regulator/rtq6752-regulator.c
index 8559a266a7eb..8176e5ab0683 100644
--- a/drivers/regulator/rtq6752-regulator.c
+++ b/drivers/regulator/rtq6752-regulator.c
@@ -281,7 +281,7 @@ static struct i2c_driver rtq6752_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = rtq6752_device_table,
},
- .probe_new = rtq6752_probe,
+ .probe = rtq6752_probe,
};
module_i2c_driver(rtq6752_driver);
diff --git a/drivers/regulator/slg51000-regulator.c b/drivers/regulator/slg51000-regulator.c
index 559ae031010f..59aa16825d8a 100644
--- a/drivers/regulator/slg51000-regulator.c
+++ b/drivers/regulator/slg51000-regulator.c
@@ -507,7 +507,7 @@ static struct i2c_driver slg51000_regulator_driver = {
.name = "slg51000-regulator",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
- .probe_new = slg51000_i2c_probe,
+ .probe = slg51000_i2c_probe,
.id_table = slg51000_i2c_id,
};
diff --git a/drivers/regulator/stm32-pwr.c b/drivers/regulator/stm32-pwr.c
index 0e101dff6dda..4c60eddad60d 100644
--- a/drivers/regulator/stm32-pwr.c
+++ b/drivers/regulator/stm32-pwr.c
@@ -93,7 +93,7 @@ static int stm32_pwr_reg_disable(struct regulator_dev *rdev)
writel_relaxed(val, priv->base + REG_PWR_CR3);
/* use an arbitrary timeout of 20ms */
- ret = readx_poll_timeout(stm32_pwr_reg_is_ready, rdev, val, !val,
+ ret = readx_poll_timeout(stm32_pwr_reg_is_enabled, rdev, val, !val,
100, 20 * 1000);
if (ret)
dev_err(&rdev->dev, "regulator disable timed out!\n");
diff --git a/drivers/regulator/sy8106a-regulator.c b/drivers/regulator/sy8106a-regulator.c
index e3c753986309..1bcfdd6dcfc1 100644
--- a/drivers/regulator/sy8106a-regulator.c
+++ b/drivers/regulator/sy8106a-regulator.c
@@ -141,7 +141,7 @@ static struct i2c_driver sy8106a_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = sy8106a_i2c_of_match,
},
- .probe_new = sy8106a_i2c_probe,
+ .probe = sy8106a_i2c_probe,
.id_table = sy8106a_i2c_id,
};
diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c
index c327ad69f676..d0703105c439 100644
--- a/drivers/regulator/sy8824x.c
+++ b/drivers/regulator/sy8824x.c
@@ -236,7 +236,7 @@ static struct i2c_driver sy8824_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = sy8824_dt_ids,
},
- .probe_new = sy8824_i2c_probe,
+ .probe = sy8824_i2c_probe,
.id_table = sy8824_id,
};
module_i2c_driver(sy8824_regulator_driver);
diff --git a/drivers/regulator/sy8827n.c b/drivers/regulator/sy8827n.c
index 99ca08cc3a6a..433959b43549 100644
--- a/drivers/regulator/sy8827n.c
+++ b/drivers/regulator/sy8827n.c
@@ -190,7 +190,7 @@ static struct i2c_driver sy8827n_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = sy8827n_dt_ids,
},
- .probe_new = sy8827n_i2c_probe,
+ .probe = sy8827n_i2c_probe,
.id_table = sy8827n_id,
};
module_i2c_driver(sy8827n_regulator_driver);
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
index 9bd4e72914ed..d8a856c1587a 100644
--- a/drivers/regulator/tps51632-regulator.c
+++ b/drivers/regulator/tps51632-regulator.c
@@ -354,7 +354,7 @@ static struct i2c_driver tps51632_i2c_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(tps51632_of_match),
},
- .probe_new = tps51632_probe,
+ .probe = tps51632_probe,
.id_table = tps51632_id,
};
diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c
index 65cc08d1a67d..32e1a05a57fd 100644
--- a/drivers/regulator/tps62360-regulator.c
+++ b/drivers/regulator/tps62360-regulator.c
@@ -491,7 +491,7 @@ static struct i2c_driver tps62360_i2c_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(tps62360_of_match),
},
- .probe_new = tps62360_probe,
+ .probe = tps62360_probe,
.shutdown = tps62360_shutdown,
.id_table = tps62360_id,
};
diff --git a/drivers/regulator/tps6286x-regulator.c b/drivers/regulator/tps6286x-regulator.c
index f92e7649d0a0..b1c4b5120745 100644
--- a/drivers/regulator/tps6286x-regulator.c
+++ b/drivers/regulator/tps6286x-regulator.c
@@ -150,7 +150,7 @@ static struct i2c_driver tps6286x_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(tps6286x_dt_ids),
},
- .probe_new = tps6286x_i2c_probe,
+ .probe = tps6286x_i2c_probe,
.id_table = tps6286x_i2c_id,
};
diff --git a/drivers/regulator/tps6287x-regulator.c b/drivers/regulator/tps6287x-regulator.c
new file mode 100644
index 000000000000..b1c0963586ac
--- /dev/null
+++ b/drivers/regulator/tps6287x-regulator.c
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2023 Axis Communications AB
+ *
+ * Driver for Texas Instruments TPS6287x PMIC.
+ * Datasheet: https://www.ti.com/lit/ds/symlink/tps62873.pdf
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/driver.h>
+#include <linux/bitfield.h>
+#include <linux/linear_range.h>
+
+#define TPS6287X_VSET 0x00
+#define TPS6287X_CTRL1 0x01
+#define TPS6287X_CTRL1_VRAMP GENMASK(1, 0)
+#define TPS6287X_CTRL1_FPWMEN BIT(4)
+#define TPS6287X_CTRL1_SWEN BIT(5)
+#define TPS6287X_CTRL2 0x02
+#define TPS6287X_CTRL2_VRANGE GENMASK(3, 2)
+#define TPS6287X_CTRL3 0x03
+#define TPS6287X_STATUS 0x04
+
+static const struct regmap_config tps6287x_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = TPS6287X_STATUS,
+};
+
+static const struct linear_range tps6287x_voltage_ranges[] = {
+ LINEAR_RANGE(400000, 0, 0xFF, 1250),
+ LINEAR_RANGE(400000, 0, 0xFF, 2500),
+ LINEAR_RANGE(400000, 0, 0xFF, 5000),
+ LINEAR_RANGE(800000, 0, 0xFF, 10000),
+};
+
+static const unsigned int tps6287x_voltage_range_sel[] = {
+ 0x0, 0x4, 0x8, 0xC
+};
+
+static const unsigned int tps6287x_ramp_table[] = {
+ 10000, 5000, 1250, 500
+};
+
+static int tps6287x_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+ unsigned int val;
+
+ switch (mode) {
+ case REGULATOR_MODE_NORMAL:
+ val = 0;
+ break;
+ case REGULATOR_MODE_FAST:
+ val = TPS6287X_CTRL1_FPWMEN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(rdev->regmap, TPS6287X_CTRL1,
+ TPS6287X_CTRL1_FPWMEN, val);
+}
+
+static unsigned int tps6287x_get_mode(struct regulator_dev *rdev)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, TPS6287X_CTRL1, &val);
+ if (ret < 0)
+ return 0;
+
+ return (val & TPS6287X_CTRL1_FPWMEN) ? REGULATOR_MODE_FAST :
+ REGULATOR_MODE_NORMAL;
+}
+
+static unsigned int tps6287x_of_map_mode(unsigned int mode)
+{
+ switch (mode) {
+ case REGULATOR_MODE_NORMAL:
+ case REGULATOR_MODE_FAST:
+ return mode;
+ default:
+ return REGULATOR_MODE_INVALID;
+ }
+}
+
+static const struct regulator_ops tps6287x_regulator_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .set_mode = tps6287x_set_mode,
+ .get_mode = tps6287x_get_mode,
+ .is_enabled = regulator_is_enabled_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_pickable_regmap,
+ .list_voltage = regulator_list_voltage_pickable_linear_range,
+ .set_ramp_delay = regulator_set_ramp_delay_regmap,
+};
+
+static struct regulator_desc tps6287x_reg = {
+ .name = "tps6287x",
+ .owner = THIS_MODULE,
+ .ops = &tps6287x_regulator_ops,
+ .of_map_mode = tps6287x_of_map_mode,
+ .type = REGULATOR_VOLTAGE,
+ .enable_reg = TPS6287X_CTRL1,
+ .enable_mask = TPS6287X_CTRL1_SWEN,
+ .vsel_reg = TPS6287X_VSET,
+ .vsel_mask = 0xFF,
+ .vsel_range_reg = TPS6287X_CTRL2,
+ .vsel_range_mask = TPS6287X_CTRL2_VRANGE,
+ .ramp_reg = TPS6287X_CTRL1,
+ .ramp_mask = TPS6287X_CTRL1_VRAMP,
+ .ramp_delay_table = tps6287x_ramp_table,
+ .n_ramp_values = ARRAY_SIZE(tps6287x_ramp_table),
+ .n_voltages = 256,
+ .linear_ranges = tps6287x_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(tps6287x_voltage_ranges),
+ .linear_range_selectors = tps6287x_voltage_range_sel,
+};
+
+static int tps6287x_i2c_probe(struct i2c_client *i2c)
+{
+ struct device *dev = &i2c->dev;
+ struct regulator_config config = {};
+ struct regulator_dev *rdev;
+
+ config.regmap = devm_regmap_init_i2c(i2c, &tps6287x_regmap_config);
+ if (IS_ERR(config.regmap)) {
+ dev_err(dev, "Failed to init i2c\n");
+ return PTR_ERR(config.regmap);
+ }
+
+ config.dev = dev;
+ config.of_node = dev->of_node;
+ config.init_data = of_get_regulator_init_data(dev, dev->of_node,
+ &tps6287x_reg);
+
+ rdev = devm_regulator_register(dev, &tps6287x_reg, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(dev, "Failed to register regulator\n");
+ return PTR_ERR(rdev);
+ }
+
+ dev_dbg(dev, "Probed regulator\n");
+
+ return 0;
+}
+
+static const struct of_device_id tps6287x_dt_ids[] = {
+ { .compatible = "ti,tps62870", },
+ { .compatible = "ti,tps62871", },
+ { .compatible = "ti,tps62872", },
+ { .compatible = "ti,tps62873", },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, tps6287x_dt_ids);
+
+static const struct i2c_device_id tps6287x_i2c_id[] = {
+ { "tps62870", 0 },
+ { "tps62871", 0 },
+ { "tps62872", 0 },
+ { "tps62873", 0 },
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, tps6287x_i2c_id);
+
+static struct i2c_driver tps6287x_regulator_driver = {
+ .driver = {
+ .name = "tps6287x",
+ .of_match_table = tps6287x_dt_ids,
+ },
+ .probe = tps6287x_i2c_probe,
+ .id_table = tps6287x_i2c_id,
+};
+
+module_i2c_driver(tps6287x_regulator_driver);
+
+MODULE_AUTHOR("Mårten Lindahl <marten.lindahl@axis.com>");
+MODULE_DESCRIPTION("Regulator driver for TI TPS6287X PMIC");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index d87cac63f346..d5757fd9a65b 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -337,7 +337,7 @@ static struct i2c_driver tps_65023_i2c_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(tps65023_of_match),
},
- .probe_new = tps_65023_probe,
+ .probe = tps_65023_probe,
.id_table = tps_65023_id,
};
diff --git a/drivers/regulator/tps65132-regulator.c b/drivers/regulator/tps65132-regulator.c
index d4b02ee791d1..a06f5f2d7932 100644
--- a/drivers/regulator/tps65132-regulator.c
+++ b/drivers/regulator/tps65132-regulator.c
@@ -272,7 +272,7 @@ static struct i2c_driver tps65132_i2c_driver = {
.name = "tps65132",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
- .probe_new = tps65132_probe,
+ .probe = tps65132_probe,
.id_table = tps65132_id,
};
diff --git a/drivers/regulator/tps65219-regulator.c b/drivers/regulator/tps65219-regulator.c
index b1719ee990ab..8971b507a79a 100644
--- a/drivers/regulator/tps65219-regulator.c
+++ b/drivers/regulator/tps65219-regulator.c
@@ -289,13 +289,13 @@ static irqreturn_t tps65219_regulator_irq_handler(int irq, void *data)
static int tps65219_get_rdev_by_name(const char *regulator_name,
struct regulator_dev *rdevtbl[7],
- struct regulator_dev *dev)
+ struct regulator_dev **dev)
{
int i;
for (i = 0; i < ARRAY_SIZE(regulators); i++) {
if (strcmp(regulator_name, regulators[i].name) == 0) {
- dev = rdevtbl[i];
+ *dev = rdevtbl[i];
return 0;
}
}
@@ -348,7 +348,7 @@ static int tps65219_regulator_probe(struct platform_device *pdev)
irq_data[i].dev = tps->dev;
irq_data[i].type = irq_type;
- tps65219_get_rdev_by_name(irq_type->regulator_name, rdevtbl, rdev);
+ tps65219_get_rdev_by_name(irq_type->regulator_name, rdevtbl, &rdev);
if (IS_ERR(rdev)) {
dev_err(tps->dev, "Failed to get rdev for %s\n",
irq_type->regulator_name);
diff --git a/drivers/regulator/tps6594-regulator.c b/drivers/regulator/tps6594-regulator.c
new file mode 100644
index 000000000000..d5a574ec6d12
--- /dev/null
+++ b/drivers/regulator/tps6594-regulator.c
@@ -0,0 +1,615 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Regulator driver for tps6594 PMIC
+//
+// Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+#include <linux/mfd/tps6594.h>
+
+#define BUCK_NB 5
+#define LDO_NB 4
+#define MULTI_PHASE_NB 4
+#define REGS_INT_NB 4
+
+enum tps6594_regulator_id {
+ /* DCDC's */
+ TPS6594_BUCK_1,
+ TPS6594_BUCK_2,
+ TPS6594_BUCK_3,
+ TPS6594_BUCK_4,
+ TPS6594_BUCK_5,
+
+ /* LDOs */
+ TPS6594_LDO_1,
+ TPS6594_LDO_2,
+ TPS6594_LDO_3,
+ TPS6594_LDO_4,
+};
+
+enum tps6594_multi_regulator_id {
+ /* Multi-phase DCDC's */
+ TPS6594_BUCK_12,
+ TPS6594_BUCK_34,
+ TPS6594_BUCK_123,
+ TPS6594_BUCK_1234,
+};
+
+struct tps6594_regulator_irq_type {
+ const char *irq_name;
+ const char *regulator_name;
+ const char *event_name;
+ unsigned long event;
+};
+
+static struct tps6594_regulator_irq_type tps6594_ext_regulator_irq_types[] = {
+ { TPS6594_IRQ_NAME_VCCA_OV, "VCCA", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+ { TPS6594_IRQ_NAME_VCCA_UV, "VCCA", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+ { TPS6594_IRQ_NAME_VMON1_OV, "VMON1", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+ { TPS6594_IRQ_NAME_VMON1_UV, "VMON1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+ { TPS6594_IRQ_NAME_VMON1_RV, "VMON1", "residual voltage",
+ REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+ { TPS6594_IRQ_NAME_VMON2_OV, "VMON2", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+ { TPS6594_IRQ_NAME_VMON2_UV, "VMON2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+ { TPS6594_IRQ_NAME_VMON2_RV, "VMON2", "residual voltage",
+ REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+};
+
+struct tps6594_regulator_irq_data {
+ struct device *dev;
+ struct tps6594_regulator_irq_type *type;
+ struct regulator_dev *rdev;
+};
+
+struct tps6594_ext_regulator_irq_data {
+ struct device *dev;
+ struct tps6594_regulator_irq_type *type;
+};
+
+#define TPS6594_REGULATOR(_name, _of, _id, _type, _ops, _n, _vr, _vm, _er, \
+ _em, _cr, _cm, _lr, _nlr, _delay, _fuv, \
+ _ct, _ncl, _bpm) \
+ { \
+ .name = _name, \
+ .of_match = _of, \
+ .regulators_node = of_match_ptr("regulators"), \
+ .supply_name = _of, \
+ .id = _id, \
+ .ops = &(_ops), \
+ .n_voltages = _n, \
+ .type = _type, \
+ .owner = THIS_MODULE, \
+ .vsel_reg = _vr, \
+ .vsel_mask = _vm, \
+ .csel_reg = _cr, \
+ .csel_mask = _cm, \
+ .curr_table = _ct, \
+ .n_current_limits = _ncl, \
+ .enable_reg = _er, \
+ .enable_mask = _em, \
+ .volt_table = NULL, \
+ .linear_ranges = _lr, \
+ .n_linear_ranges = _nlr, \
+ .ramp_delay = _delay, \
+ .fixed_uV = _fuv, \
+ .bypass_reg = _vr, \
+ .bypass_mask = _bpm, \
+ } \
+
+static const struct linear_range bucks_ranges[] = {
+ REGULATOR_LINEAR_RANGE(300000, 0x0, 0xe, 20000),
+ REGULATOR_LINEAR_RANGE(600000, 0xf, 0x72, 5000),
+ REGULATOR_LINEAR_RANGE(1100000, 0x73, 0xaa, 10000),
+ REGULATOR_LINEAR_RANGE(1660000, 0xab, 0xff, 20000),
+};
+
+static const struct linear_range ldos_1_2_3_ranges[] = {
+ REGULATOR_LINEAR_RANGE(600000, 0x4, 0x3a, 50000),
+};
+
+static const struct linear_range ldos_4_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1200000, 0x20, 0x74, 25000),
+};
+
+/* Operations permitted on BUCK1/2/3/4/5 */
+static const struct regulator_ops tps6594_bucks_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+
+};
+
+/* Operations permitted on LDO1/2/3 */
+static const struct regulator_ops tps6594_ldos_1_2_3_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .set_bypass = regulator_set_bypass_regmap,
+ .get_bypass = regulator_get_bypass_regmap,
+};
+
+/* Operations permitted on LDO4 */
+static const struct regulator_ops tps6594_ldos_4_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+};
+
+static const struct regulator_desc buck_regs[] = {
+ TPS6594_REGULATOR("BUCK1", "buck1", TPS6594_BUCK_1,
+ REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_VOUT_1(0),
+ TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_CTRL(0),
+ TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+ 4, 0, 0, NULL, 0, 0),
+ TPS6594_REGULATOR("BUCK2", "buck2", TPS6594_BUCK_2,
+ REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_VOUT_1(1),
+ TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_CTRL(1),
+ TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+ 4, 0, 0, NULL, 0, 0),
+ TPS6594_REGULATOR("BUCK3", "buck3", TPS6594_BUCK_3,
+ REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_VOUT_1(2),
+ TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_CTRL(2),
+ TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+ 4, 0, 0, NULL, 0, 0),
+ TPS6594_REGULATOR("BUCK4", "buck4", TPS6594_BUCK_4,
+ REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_VOUT_1(3),
+ TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_CTRL(3),
+ TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+ 4, 0, 0, NULL, 0, 0),
+ TPS6594_REGULATOR("BUCK5", "buck5", TPS6594_BUCK_5,
+ REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_VOUT_1(4),
+ TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_CTRL(4),
+ TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+ 4, 0, 0, NULL, 0, 0),
+};
+
+static struct tps6594_regulator_irq_type tps6594_buck1_irq_types[] = {
+ { TPS6594_IRQ_NAME_BUCK1_OV, "BUCK1", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+ { TPS6594_IRQ_NAME_BUCK1_UV, "BUCK1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+ { TPS6594_IRQ_NAME_BUCK1_SC, "BUCK1", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+ { TPS6594_IRQ_NAME_BUCK1_ILIM, "BUCK1", "reach ilim, overcurrent",
+ REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type tps6594_buck2_irq_types[] = {
+ { TPS6594_IRQ_NAME_BUCK2_OV, "BUCK2", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+ { TPS6594_IRQ_NAME_BUCK2_UV, "BUCK2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+ { TPS6594_IRQ_NAME_BUCK2_SC, "BUCK2", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+ { TPS6594_IRQ_NAME_BUCK2_ILIM, "BUCK2", "reach ilim, overcurrent",
+ REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type tps6594_buck3_irq_types[] = {
+ { TPS6594_IRQ_NAME_BUCK3_OV, "BUCK3", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+ { TPS6594_IRQ_NAME_BUCK3_UV, "BUCK3", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+ { TPS6594_IRQ_NAME_BUCK3_SC, "BUCK3", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+ { TPS6594_IRQ_NAME_BUCK3_ILIM, "BUCK3", "reach ilim, overcurrent",
+ REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type tps6594_buck4_irq_types[] = {
+ { TPS6594_IRQ_NAME_BUCK4_OV, "BUCK4", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+ { TPS6594_IRQ_NAME_BUCK4_UV, "BUCK4", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+ { TPS6594_IRQ_NAME_BUCK4_SC, "BUCK4", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+ { TPS6594_IRQ_NAME_BUCK4_ILIM, "BUCK4", "reach ilim, overcurrent",
+ REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type tps6594_buck5_irq_types[] = {
+ { TPS6594_IRQ_NAME_BUCK5_OV, "BUCK5", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+ { TPS6594_IRQ_NAME_BUCK5_UV, "BUCK5", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+ { TPS6594_IRQ_NAME_BUCK5_SC, "BUCK5", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+ { TPS6594_IRQ_NAME_BUCK5_ILIM, "BUCK5", "reach ilim, overcurrent",
+ REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type tps6594_ldo1_irq_types[] = {
+ { TPS6594_IRQ_NAME_LDO1_OV, "LDO1", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+ { TPS6594_IRQ_NAME_LDO1_UV, "LDO1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+ { TPS6594_IRQ_NAME_LDO1_SC, "LDO1", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+ { TPS6594_IRQ_NAME_LDO1_ILIM, "LDO1", "reach ilim, overcurrent",
+ REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type tps6594_ldo2_irq_types[] = {
+ { TPS6594_IRQ_NAME_LDO2_OV, "LDO2", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+ { TPS6594_IRQ_NAME_LDO2_UV, "LDO2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+ { TPS6594_IRQ_NAME_LDO2_SC, "LDO2", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+ { TPS6594_IRQ_NAME_LDO2_ILIM, "LDO2", "reach ilim, overcurrent",
+ REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type tps6594_ldo3_irq_types[] = {
+ { TPS6594_IRQ_NAME_LDO3_OV, "LDO3", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+ { TPS6594_IRQ_NAME_LDO3_UV, "LDO3", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+ { TPS6594_IRQ_NAME_LDO3_SC, "LDO3", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+ { TPS6594_IRQ_NAME_LDO3_ILIM, "LDO3", "reach ilim, overcurrent",
+ REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type tps6594_ldo4_irq_types[] = {
+ { TPS6594_IRQ_NAME_LDO4_OV, "LDO4", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+ { TPS6594_IRQ_NAME_LDO4_UV, "LDO4", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+ { TPS6594_IRQ_NAME_LDO4_SC, "LDO4", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+ { TPS6594_IRQ_NAME_LDO4_ILIM, "LDO4", "reach ilim, overcurrent",
+ REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type *tps6594_bucks_irq_types[] = {
+ tps6594_buck1_irq_types,
+ tps6594_buck2_irq_types,
+ tps6594_buck3_irq_types,
+ tps6594_buck4_irq_types,
+ tps6594_buck5_irq_types,
+};
+
+static struct tps6594_regulator_irq_type *tps6594_ldos_irq_types[] = {
+ tps6594_ldo1_irq_types,
+ tps6594_ldo2_irq_types,
+ tps6594_ldo3_irq_types,
+ tps6594_ldo4_irq_types,
+};
+
+static const struct regulator_desc multi_regs[] = {
+ TPS6594_REGULATOR("BUCK12", "buck12", TPS6594_BUCK_1,
+ REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_VOUT_1(1),
+ TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_CTRL(1),
+ TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+ 4, 4000, 0, NULL, 0, 0),
+ TPS6594_REGULATOR("BUCK34", "buck34", TPS6594_BUCK_3,
+ REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_VOUT_1(3),
+ TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_CTRL(3),
+ TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+ 4, 0, 0, NULL, 0, 0),
+ TPS6594_REGULATOR("BUCK123", "buck123", TPS6594_BUCK_1,
+ REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_VOUT_1(1),
+ TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_CTRL(1),
+ TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+ 4, 4000, 0, NULL, 0, 0),
+ TPS6594_REGULATOR("BUCK1234", "buck1234", TPS6594_BUCK_1,
+ REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_VOUT_1(1),
+ TPS6594_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_CTRL(1),
+ TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+ 4, 4000, 0, NULL, 0, 0),
+};
+
+static const struct regulator_desc ldo_regs[] = {
+ TPS6594_REGULATOR("LDO1", "ldo1", TPS6594_LDO_1,
+ REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET,
+ TPS6594_REG_LDOX_VOUT(0),
+ TPS6594_MASK_LDO123_VSET,
+ TPS6594_REG_LDOX_CTRL(0),
+ TPS6594_BIT_LDO_EN, 0, 0, ldos_1_2_3_ranges,
+ 1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS),
+ TPS6594_REGULATOR("LDO2", "ldo2", TPS6594_LDO_2,
+ REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET,
+ TPS6594_REG_LDOX_VOUT(1),
+ TPS6594_MASK_LDO123_VSET,
+ TPS6594_REG_LDOX_CTRL(1),
+ TPS6594_BIT_LDO_EN, 0, 0, ldos_1_2_3_ranges,
+ 1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS),
+ TPS6594_REGULATOR("LDO3", "ldo3", TPS6594_LDO_3,
+ REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET,
+ TPS6594_REG_LDOX_VOUT(2),
+ TPS6594_MASK_LDO123_VSET,
+ TPS6594_REG_LDOX_CTRL(2),
+ TPS6594_BIT_LDO_EN, 0, 0, ldos_1_2_3_ranges,
+ 1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS),
+ TPS6594_REGULATOR("LDO4", "ldo4", TPS6594_LDO_4,
+ REGULATOR_VOLTAGE, tps6594_ldos_4_ops, TPS6594_MASK_LDO4_VSET >> 1,
+ TPS6594_REG_LDOX_VOUT(3),
+ TPS6594_MASK_LDO4_VSET,
+ TPS6594_REG_LDOX_CTRL(3),
+ TPS6594_BIT_LDO_EN, 0, 0, ldos_4_ranges,
+ 1, 0, 0, NULL, 0, 0),
+};
+
+static irqreturn_t tps6594_regulator_irq_handler(int irq, void *data)
+{
+ struct tps6594_regulator_irq_data *irq_data = data;
+
+ if (irq_data->type->event_name[0] == '\0') {
+ /* This is the timeout interrupt no specific regulator */
+ dev_err(irq_data->dev,
+ "System was put in shutdown due to timeout during an active or standby transition.\n");
+ return IRQ_HANDLED;
+ }
+
+ dev_err(irq_data->dev, "Error IRQ trap %s for %s\n",
+ irq_data->type->event_name, irq_data->type->regulator_name);
+
+ regulator_notifier_call_chain(irq_data->rdev,
+ irq_data->type->event, NULL);
+
+ return IRQ_HANDLED;
+}
+
+static int tps6594_request_reg_irqs(struct platform_device *pdev,
+ struct regulator_dev *rdev,
+ struct tps6594_regulator_irq_data *irq_data,
+ struct tps6594_regulator_irq_type *tps6594_regs_irq_types,
+ int *irq_idx)
+{
+ struct tps6594_regulator_irq_type *irq_type;
+ struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
+ int j;
+ int irq;
+ int error;
+
+ for (j = 0; j < REGS_INT_NB; j++) {
+ irq_type = &tps6594_regs_irq_types[j];
+ irq = platform_get_irq_byname(pdev, irq_type->irq_name);
+ if (irq < 0)
+ return -EINVAL;
+
+ irq_data[*irq_idx + j].dev = tps->dev;
+ irq_data[*irq_idx + j].type = irq_type;
+ irq_data[*irq_idx + j].rdev = rdev;
+
+ error = devm_request_threaded_irq(tps->dev, irq, NULL,
+ tps6594_regulator_irq_handler,
+ IRQF_ONESHOT,
+ irq_type->irq_name,
+ &irq_data[*irq_idx]);
+ (*irq_idx)++;
+ if (error) {
+ dev_err(tps->dev, "tps6594 failed to request %s IRQ %d: %d\n",
+ irq_type->irq_name, irq, error);
+ return error;
+ }
+ }
+ return 0;
+}
+
+static int tps6594_regulator_probe(struct platform_device *pdev)
+{
+ struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
+ struct regulator_dev *rdev;
+ struct device_node *np = NULL;
+ struct device_node *np_pmic_parent = NULL;
+ struct regulator_config config = {};
+ struct tps6594_regulator_irq_data *irq_data;
+ struct tps6594_ext_regulator_irq_data *irq_ext_reg_data;
+ struct tps6594_regulator_irq_type *irq_type;
+ u8 buck_configured[BUCK_NB] = { 0 };
+ u8 buck_multi[MULTI_PHASE_NB] = { 0 };
+ static const char * const multiphases[] = {"buck12", "buck123", "buck1234", "buck34"};
+ static const char *npname;
+ int error, i, irq, multi, delta;
+ int irq_idx = 0;
+ int buck_idx = 0;
+ int ext_reg_irq_nb = 2;
+
+ enum {
+ MULTI_BUCK12,
+ MULTI_BUCK123,
+ MULTI_BUCK1234,
+ MULTI_BUCK12_34,
+ MULTI_FIRST = MULTI_BUCK12,
+ MULTI_LAST = MULTI_BUCK12_34,
+ MULTI_NUM = MULTI_LAST - MULTI_FIRST + 1
+ };
+
+ config.dev = tps->dev;
+ config.driver_data = tps;
+ config.regmap = tps->regmap;
+
+ /*
+ * Switch case defines different possible multi phase config
+ * This is based on dts buck node name.
+ * Buck node name must be chosen accordingly.
+ * Default case is no Multiphase buck.
+ * In case of Multiphase configuration, value should be defined for
+ * buck_configured to avoid creating bucks for every buck in multiphase
+ */
+ for (multi = MULTI_FIRST; multi < MULTI_NUM; multi++) {
+ np = of_find_node_by_name(tps->dev->of_node, multiphases[multi]);
+ npname = of_node_full_name(np);
+ np_pmic_parent = of_get_parent(of_get_parent(np));
+ if (of_node_cmp(of_node_full_name(np_pmic_parent), tps->dev->of_node->full_name))
+ continue;
+ delta = strcmp(npname, multiphases[multi]);
+ if (!delta) {
+ switch (multi) {
+ case MULTI_BUCK12:
+ buck_multi[0] = 1;
+ buck_configured[0] = 1;
+ buck_configured[1] = 1;
+ break;
+ /* multiphase buck34 is supported only with buck12 */
+ case MULTI_BUCK12_34:
+ buck_multi[0] = 1;
+ buck_multi[1] = 1;
+ buck_configured[0] = 1;
+ buck_configured[1] = 1;
+ buck_configured[2] = 1;
+ buck_configured[3] = 1;
+ break;
+ case MULTI_BUCK123:
+ buck_multi[2] = 1;
+ buck_configured[0] = 1;
+ buck_configured[1] = 1;
+ buck_configured[2] = 1;
+ break;
+ case MULTI_BUCK1234:
+ buck_multi[3] = 1;
+ buck_configured[0] = 1;
+ buck_configured[1] = 1;
+ buck_configured[2] = 1;
+ buck_configured[3] = 1;
+ break;
+ }
+ }
+ }
+
+ if (tps->chip_id == LP8764)
+ /* There is only 4 buck on LP8764 */
+ buck_configured[4] = 1;
+
+ irq_data = devm_kmalloc_array(tps->dev,
+ REGS_INT_NB * sizeof(struct tps6594_regulator_irq_data),
+ ARRAY_SIZE(tps6594_bucks_irq_types) +
+ ARRAY_SIZE(tps6594_ldos_irq_types),
+ GFP_KERNEL);
+ if (!irq_data)
+ return -ENOMEM;
+
+ for (i = 0; i < MULTI_PHASE_NB; i++) {
+ if (buck_multi[i] == 0)
+ continue;
+
+ rdev = devm_regulator_register(&pdev->dev, &multi_regs[i], &config);
+ if (IS_ERR(rdev))
+ return dev_err_probe(tps->dev, PTR_ERR(rdev),
+ "failed to register %s regulator\n",
+ pdev->name);
+
+ /* config multiphase buck12+buck34 */
+ if (i == 1)
+ buck_idx = 2;
+ error = tps6594_request_reg_irqs(pdev, rdev, irq_data,
+ tps6594_bucks_irq_types[buck_idx], &irq_idx);
+ if (error)
+ return error;
+ error = tps6594_request_reg_irqs(pdev, rdev, irq_data,
+ tps6594_bucks_irq_types[buck_idx + 1], &irq_idx);
+ if (error)
+ return error;
+
+ if (i == 2 || i == 3) {
+ error = tps6594_request_reg_irqs(pdev, rdev, irq_data,
+ tps6594_bucks_irq_types[buck_idx + 2],
+ &irq_idx);
+ if (error)
+ return error;
+ }
+ if (i == 3) {
+ error = tps6594_request_reg_irqs(pdev, rdev, irq_data,
+ tps6594_bucks_irq_types[buck_idx + 3],
+ &irq_idx);
+ if (error)
+ return error;
+ }
+ }
+
+ for (i = 0; i < BUCK_NB; i++) {
+ if (buck_configured[i] == 1)
+ continue;
+
+ rdev = devm_regulator_register(&pdev->dev, &buck_regs[i], &config);
+ if (IS_ERR(rdev))
+ return dev_err_probe(tps->dev, PTR_ERR(rdev),
+ "failed to register %s regulator\n",
+ pdev->name);
+
+ error = tps6594_request_reg_irqs(pdev, rdev, irq_data,
+ tps6594_bucks_irq_types[i], &irq_idx);
+ if (error)
+ return error;
+ }
+
+ /* LP8764 dosen't have LDO */
+ if (tps->chip_id != LP8764) {
+ for (i = 0; i < ARRAY_SIZE(ldo_regs); i++) {
+ rdev = devm_regulator_register(&pdev->dev, &ldo_regs[i], &config);
+ if (IS_ERR(rdev))
+ return dev_err_probe(tps->dev, PTR_ERR(rdev),
+ "failed to register %s regulator\n",
+ pdev->name);
+
+ error = tps6594_request_reg_irqs(pdev, rdev, irq_data,
+ tps6594_ldos_irq_types[i],
+ &irq_idx);
+ if (error)
+ return error;
+ }
+ }
+
+ if (tps->chip_id == LP8764)
+ ext_reg_irq_nb = ARRAY_SIZE(tps6594_ext_regulator_irq_types);
+
+ irq_ext_reg_data = devm_kmalloc_array(tps->dev,
+ ext_reg_irq_nb,
+ sizeof(struct tps6594_ext_regulator_irq_data),
+ GFP_KERNEL);
+ if (!irq_ext_reg_data)
+ return -ENOMEM;
+
+ for (i = 0; i < ext_reg_irq_nb; ++i) {
+ irq_type = &tps6594_ext_regulator_irq_types[i];
+
+ irq = platform_get_irq_byname(pdev, irq_type->irq_name);
+ if (irq < 0)
+ return -EINVAL;
+
+ irq_ext_reg_data[i].dev = tps->dev;
+ irq_ext_reg_data[i].type = irq_type;
+
+ error = devm_request_threaded_irq(tps->dev, irq, NULL,
+ tps6594_regulator_irq_handler,
+ IRQF_ONESHOT,
+ irq_type->irq_name,
+ &irq_ext_reg_data[i]);
+ if (error)
+ return dev_err_probe(tps->dev, error,
+ "failed to request %s IRQ %d\n",
+ irq_type->irq_name, irq);
+ }
+ return 0;
+}
+
+static struct platform_driver tps6594_regulator_driver = {
+ .driver = {
+ .name = "tps6594-regulator",
+ },
+ .probe = tps6594_regulator_probe,
+};
+
+module_platform_driver(tps6594_regulator_driver);
+
+MODULE_ALIAS("platform:tps6594-regulator");
+MODULE_AUTHOR("Jerome Neanne <jneanne@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 voltage 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 753872408615..05f4b2d66290 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -395,7 +395,7 @@ config RTC_DRV_NCT3018Y
config RTC_DRV_RK808
tristate "Rockchip RK805/RK808/RK809/RK817/RK818 RTC"
- depends on MFD_RK808
+ depends on MFD_RK8XX
help
If you say yes here you will get support for the
RTC of RK805, RK809 and RK817, RK808 and RK818 PMIC.
@@ -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 9fbfce735d56..50a5ff70814a 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;
@@ -2938,41 +2943,32 @@ static void _dasd_wake_block_flush_cb(struct dasd_ccw_req *cqr, void *data)
* Requeue a request back to the block request queue
* only works for block requests
*/
-static int _dasd_requeue_request(struct dasd_ccw_req *cqr)
+static void _dasd_requeue_request(struct dasd_ccw_req *cqr)
{
- struct dasd_block *block = cqr->block;
struct request *req;
- if (!block)
- return -EINVAL;
/*
* If the request is an ERP request there is nothing to requeue.
* This will be done with the remaining original request.
*/
if (cqr->refers)
- return 0;
+ return;
spin_lock_irq(&cqr->dq->lock);
req = (struct request *) cqr->callback_data;
blk_mq_requeue_request(req, true);
spin_unlock_irq(&cqr->dq->lock);
- return 0;
+ return;
}
-/*
- * Go through all request on the dasd_block request queue, cancel them
- * on the respective dasd_device, and return them to the generic
- * block layer.
- */
-static int dasd_flush_block_queue(struct dasd_block *block)
+static int _dasd_requests_to_flushqueue(struct dasd_block *block,
+ struct list_head *flush_queue)
{
struct dasd_ccw_req *cqr, *n;
- int rc, i;
- struct list_head flush_queue;
unsigned long flags;
+ int rc, i;
- INIT_LIST_HEAD(&flush_queue);
- spin_lock_bh(&block->queue_lock);
+ spin_lock_irqsave(&block->queue_lock, flags);
rc = 0;
restart:
list_for_each_entry_safe(cqr, n, &block->ccw_queue, blocklist) {
@@ -2987,13 +2983,32 @@ restart:
* is returned from the dasd_device layer.
*/
cqr->callback = _dasd_wake_block_flush_cb;
- for (i = 0; cqr != NULL; cqr = cqr->refers, i++)
- list_move_tail(&cqr->blocklist, &flush_queue);
+ for (i = 0; cqr; cqr = cqr->refers, i++)
+ list_move_tail(&cqr->blocklist, flush_queue);
if (i > 1)
/* moved more than one request - need to restart */
goto restart;
}
- spin_unlock_bh(&block->queue_lock);
+ spin_unlock_irqrestore(&block->queue_lock, flags);
+
+ return rc;
+}
+
+/*
+ * Go through all request on the dasd_block request queue, cancel them
+ * on the respective dasd_device, and return them to the generic
+ * block layer.
+ */
+static int dasd_flush_block_queue(struct dasd_block *block)
+{
+ struct dasd_ccw_req *cqr, *n;
+ struct list_head flush_queue;
+ unsigned long flags;
+ int rc;
+
+ INIT_LIST_HEAD(&flush_queue);
+ rc = _dasd_requests_to_flushqueue(block, &flush_queue);
+
/* Now call the callback function of flushed requests */
restart_cb:
list_for_each_entry_safe(cqr, n, &flush_queue, blocklist) {
@@ -3234,12 +3249,12 @@ struct blk_mq_ops dasd_mq_ops = {
.exit_hctx = dasd_exit_hctx,
};
-static int dasd_open(struct block_device *bdev, fmode_t mode)
+static int dasd_open(struct gendisk *disk, blk_mode_t mode)
{
struct dasd_device *base;
int rc;
- base = dasd_device_from_gendisk(bdev->bd_disk);
+ base = dasd_device_from_gendisk(disk);
if (!base)
return -ENODEV;
@@ -3268,14 +3283,12 @@ static int dasd_open(struct block_device *bdev, fmode_t mode)
rc = -ENODEV;
goto out;
}
-
- if ((mode & FMODE_WRITE) &&
+ if ((mode & BLK_OPEN_WRITE) &&
(test_bit(DASD_FLAG_DEVICE_RO, &base->flags) ||
(base->features & DASD_FEATURE_READONLY))) {
rc = -EROFS;
goto out;
}
-
dasd_put_device(base);
return 0;
@@ -3287,7 +3300,7 @@ unlock:
return rc;
}
-static void dasd_release(struct gendisk *disk, fmode_t mode)
+static void dasd_release(struct gendisk *disk)
{
struct dasd_device *base = dasd_device_from_gendisk(disk);
if (base) {
@@ -3878,75 +3891,36 @@ EXPORT_SYMBOL_GPL(dasd_generic_space_avail);
*/
int dasd_generic_requeue_all_requests(struct dasd_device *device)
{
+ struct dasd_block *block = device->block;
struct list_head requeue_queue;
struct dasd_ccw_req *cqr, *n;
- struct dasd_ccw_req *refers;
int rc;
- INIT_LIST_HEAD(&requeue_queue);
- spin_lock_irq(get_ccwdev_lock(device->cdev));
- rc = 0;
- list_for_each_entry_safe(cqr, n, &device->ccw_queue, devlist) {
- /* Check status and move request to flush_queue */
- if (cqr->status == DASD_CQR_IN_IO) {
- rc = device->discipline->term_IO(cqr);
- if (rc) {
- /* unable to terminate requeust */
- dev_err(&device->cdev->dev,
- "Unable to terminate request %p "
- "on suspend\n", cqr);
- spin_unlock_irq(get_ccwdev_lock(device->cdev));
- dasd_put_device(device);
- return rc;
- }
- }
- list_move_tail(&cqr->devlist, &requeue_queue);
- }
- spin_unlock_irq(get_ccwdev_lock(device->cdev));
-
- list_for_each_entry_safe(cqr, n, &requeue_queue, devlist) {
- wait_event(dasd_flush_wq,
- (cqr->status != DASD_CQR_CLEAR_PENDING));
+ if (!block)
+ return 0;
- /*
- * requeue requests to blocklayer will only work
- * for block device requests
- */
- if (_dasd_requeue_request(cqr))
- continue;
+ INIT_LIST_HEAD(&requeue_queue);
+ rc = _dasd_requests_to_flushqueue(block, &requeue_queue);
- /* remove requests from device and block queue */
- list_del_init(&cqr->devlist);
- while (cqr->refers != NULL) {
- refers = cqr->refers;
- /* remove the request from the block queue */
- list_del(&cqr->blocklist);
- /* free the finished erp request */
- dasd_free_erp_request(cqr, cqr->memdev);
- cqr = refers;
+ /* Now call the callback function of flushed requests */
+restart_cb:
+ list_for_each_entry_safe(cqr, n, &requeue_queue, blocklist) {
+ wait_event(dasd_flush_wq, (cqr->status < DASD_CQR_QUEUED));
+ /* Process finished ERP request. */
+ if (cqr->refers) {
+ spin_lock_bh(&block->queue_lock);
+ __dasd_process_erp(block->base, cqr);
+ spin_unlock_bh(&block->queue_lock);
+ /* restart list_for_xx loop since dasd_process_erp
+ * might remove multiple elements
+ */
+ goto restart_cb;
}
-
- /*
- * _dasd_requeue_request already checked for a valid
- * blockdevice, no need to check again
- * all erp requests (cqr->refers) have a cqr->block
- * pointer copy from the original cqr
- */
+ _dasd_requeue_request(cqr);
list_del_init(&cqr->blocklist);
cqr->block->base->discipline->free_cp(
cqr, (struct request *) cqr->callback_data);
}
-
- /*
- * if requests remain then they are internal request
- * and go back to the device queue
- */
- if (!list_empty(&requeue_queue)) {
- /* move freeze_queue to start of the ccw_queue */
- spin_lock_irq(get_ccwdev_lock(device->cdev));
- list_splice_tail(&requeue_queue, &device->ccw_queue);
- spin_unlock_irq(get_ccwdev_lock(device->cdev));
- }
dasd_schedule_device_bh(device);
return rc;
}
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index 9fd36c468706..89957bb7244d 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -1050,7 +1050,7 @@ dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense)
dev_err(&device->cdev->dev, "An I/O request was rejected"
" because writing is inhibited\n");
erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
- } else if (sense[7] & SNS7_INVALID_ON_SEC) {
+ } else if (sense[7] == SNS7_INVALID_ON_SEC) {
dev_err(&device->cdev->dev, "An I/O request was rejected on a copy pair secondary device\n");
/* suppress dump of sense data for this error */
set_bit(DASD_CQR_SUPPRESS_CR, &erp->refers->flags);
@@ -2441,7 +2441,7 @@ static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr)
erp->block = cqr->block;
erp->magic = cqr->magic;
erp->expires = cqr->expires;
- erp->retries = 256;
+ erp->retries = device->default_retries;
erp->buildclk = get_tod_clock();
erp->status = DASD_CQR_FILLED;
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index f956a4ac9881..2e4e555b37c3 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -24,7 +24,7 @@
#include <asm/debug.h>
#include <asm/diag.h>
#include <asm/ebcdic.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/irq.h>
#include <asm/vtoc.h>
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 113c509bf6d0..8587e423169e 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -21,13 +21,13 @@
#include <linux/compat.h>
#include <linux/init.h>
#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
#include <asm/css_chars.h>
#include <asm/debug.h>
#include <asm/idals.h>
#include <asm/ebcdic.h>
-#include <asm/io.h>
-#include <linux/uaccess.h>
#include <asm/cio.h>
#include <asm/ccwdev.h>
#include <asm/itcw.h>
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index bcb67fa747a7..c06fa2b27120 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -16,10 +16,10 @@
#include <linux/bio.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/io.h>
#include <asm/idals.h>
#include <asm/ebcdic.h>
-#include <asm/io.h>
#include <asm/ccwdev.h>
#include "dasd_int.h"
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index 998a961e1704..fe5108a1b332 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -130,7 +130,8 @@ int dasd_scan_partitions(struct dasd_block *block)
struct block_device *bdev;
int rc;
- bdev = blkdev_get_by_dev(disk_devt(block->gdp), FMODE_READ, NULL);
+ bdev = blkdev_get_by_dev(disk_devt(block->gdp), BLK_OPEN_READ, NULL,
+ NULL);
if (IS_ERR(bdev)) {
DBF_DEV_EVENT(DBF_ERR, block->base,
"scan partitions error, blkdev_get returned %ld",
@@ -179,7 +180,7 @@ void dasd_destroy_partitions(struct dasd_block *block)
mutex_unlock(&bdev->bd_disk->open_mutex);
/* Matching blkdev_put to the blkdev_get in dasd_scan_partitions. */
- blkdev_put(bdev, FMODE_READ);
+ blkdev_put(bdev, NULL);
}
int dasd_gendisk_init(void)
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 33f812f0e515..0aa56351da72 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -965,7 +965,8 @@ int dasd_scan_partitions(struct dasd_block *);
void dasd_destroy_partitions(struct dasd_block *);
/* externals in dasd_ioctl.c */
-int dasd_ioctl(struct block_device *, fmode_t, unsigned int, unsigned long);
+int dasd_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd,
+ unsigned long arg);
int dasd_set_read_only(struct block_device *bdev, bool ro);
/* externals in dasd_proc.c */
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 8fca725b3dae..d55862605b82 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -131,6 +131,7 @@ static int dasd_ioctl_resume(struct dasd_block *block)
spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags);
dasd_schedule_block_bh(block);
+ dasd_schedule_device_bh(base);
return 0;
}
@@ -612,7 +613,7 @@ static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd,
return ret;
}
-int dasd_ioctl(struct block_device *bdev, fmode_t mode,
+int dasd_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long arg)
{
struct dasd_block *block;
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index c09f2e053bf8..09acf3853a77 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -20,16 +20,16 @@
#include <linux/pfn_t.h>
#include <linux/uio.h>
#include <linux/dax.h>
+#include <linux/io.h>
#include <asm/extmem.h>
-#include <asm/io.h>
#define DCSSBLK_NAME "dcssblk"
#define DCSSBLK_MINORS_PER_DISK 1
#define DCSSBLK_PARM_LEN 400
#define DCSS_BUS_ID_SIZE 20
-static int dcssblk_open(struct block_device *bdev, fmode_t mode);
-static void dcssblk_release(struct gendisk *disk, fmode_t mode);
+static int dcssblk_open(struct gendisk *disk, blk_mode_t mode);
+static void dcssblk_release(struct gendisk *disk);
static void dcssblk_submit_bio(struct bio *bio);
static long dcssblk_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff,
long nr_pages, enum dax_access_mode mode, void **kaddr,
@@ -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;
@@ -809,12 +810,11 @@ out_buf:
}
static int
-dcssblk_open(struct block_device *bdev, fmode_t mode)
+dcssblk_open(struct gendisk *disk, blk_mode_t mode)
{
- struct dcssblk_dev_info *dev_info;
+ struct dcssblk_dev_info *dev_info = disk->private_data;
int rc;
- dev_info = bdev->bd_disk->private_data;
if (NULL == dev_info) {
rc = -ENODEV;
goto out;
@@ -826,7 +826,7 @@ out:
}
static void
-dcssblk_release(struct gendisk *disk, fmode_t mode)
+dcssblk_release(struct gendisk *disk)
{
struct dcssblk_dev_info *dev_info = disk->private_data;
struct segment_info *entry;
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/con3215.c b/drivers/s390/char/con3215.c
index 0b05cd76b7d0..a1fef666c9b0 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -25,7 +25,7 @@
#include <linux/slab.h>
#include <asm/ccwdev.h>
#include <asm/cio.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/ebcdic.h>
#include <linux/uaccess.h>
#include <asm/delay.h>
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index 9cd1ea92d619..bc5193d81f9c 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -22,8 +22,8 @@
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
+#include <linux/io.h>
#include <asm/ebcdic.h>
-#include <asm/io.h>
#include <asm/appldata.h>
#include <asm/monwriter.h>
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/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 599f547310f8..942c73a11ca3 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -51,6 +51,7 @@ static struct dentry *zcore_dir;
static struct dentry *zcore_reipl_file;
static struct dentry *zcore_hsa_file;
static struct ipl_parameter_block *zcore_ipl_block;
+static unsigned long os_info_flags;
static DEFINE_MUTEX(hsa_buf_mutex);
static char hsa_buf[PAGE_SIZE] __aligned(PAGE_SIZE);
@@ -139,7 +140,13 @@ static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf,
{
if (zcore_ipl_block) {
diag308(DIAG308_SET, zcore_ipl_block);
- diag308(DIAG308_LOAD_CLEAR, NULL);
+ if (os_info_flags & OS_INFO_FLAG_REIPL_CLEAR)
+ diag308(DIAG308_LOAD_CLEAR, NULL);
+ /* Use special diag308 subcode for CCW normal ipl */
+ if (zcore_ipl_block->pb0_hdr.pbt == IPL_PBT_CCW)
+ diag308(DIAG308_LOAD_NORMAL_DUMP, NULL);
+ else
+ diag308(DIAG308_LOAD_NORMAL, NULL);
}
return count;
}
@@ -212,7 +219,10 @@ static int __init check_sdias(void)
*/
static int __init zcore_reipl_init(void)
{
+ struct os_info_entry *entry;
struct ipib_info ipib_info;
+ unsigned long os_info_addr;
+ struct os_info *os_info;
int rc;
rc = memcpy_hsa_kernel(&ipib_info, __LC_DUMP_REIPL, sizeof(ipib_info));
@@ -234,6 +244,35 @@ static int __init zcore_reipl_init(void)
free_page((unsigned long) zcore_ipl_block);
zcore_ipl_block = NULL;
}
+ /*
+ * Read the bit-flags field from os_info flags entry.
+ * Return zero even for os_info read or entry checksum errors in order
+ * to continue dump processing, considering that os_info could be
+ * corrupted on the panicked system.
+ */
+ os_info = (void *)__get_free_page(GFP_KERNEL);
+ if (!os_info)
+ return -ENOMEM;
+ rc = memcpy_hsa_kernel(&os_info_addr, __LC_OS_INFO, sizeof(os_info_addr));
+ if (rc)
+ goto out;
+ if (os_info_addr < sclp.hsa_size)
+ rc = memcpy_hsa_kernel(os_info, os_info_addr, PAGE_SIZE);
+ else
+ rc = memcpy_real(os_info, os_info_addr, PAGE_SIZE);
+ if (rc || os_info_csum(os_info) != os_info->csum)
+ goto out;
+ entry = &os_info->entry[OS_INFO_FLAGS_ENTRY];
+ if (entry->addr && entry->size) {
+ if (entry->addr < sclp.hsa_size)
+ rc = memcpy_hsa_kernel(&os_info_flags, entry->addr, sizeof(os_info_flags));
+ else
+ rc = memcpy_real(&os_info_flags, entry->addr, sizeof(os_info_flags));
+ if (rc || (__force u32)csum_partial(&os_info_flags, entry->size, 0) != entry->csum)
+ os_info_flags = 0;
+ }
+out:
+ free_page((unsigned long)os_info);
return 0;
}
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index f0538609dfe4..aa3292e57e38 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -152,7 +152,7 @@ static ssize_t ccwgroup_online_show(struct device *dev,
/*
* Provide an 'ungroup' attribute so the user can remove group devices no
- * longer needed or accidentially created. Saves memory :)
+ * longer needed or accidentally created. Saves memory :)
*/
static void ccwgroup_ungroup(struct ccwgroup_device *gdev)
{
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index c0d620ffea61..4ca5adce9107 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -943,7 +943,7 @@ static int ccw_device_move_to_sch(struct ccw_device *cdev,
cdev->private->dev_id.devno, sch->schid.ssid,
sch->schib.pmcw.dev, rc);
if (old_enabled) {
- /* Try to reenable the old subchannel. */
+ /* Try to re-enable the old subchannel. */
spin_lock_irq(old_sch->lock);
cio_enable_subchannel(old_sch, (u32)virt_to_phys(old_sch));
spin_unlock_irq(old_sch->lock);
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 2b2058427a2b..c396ac3e3a32 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -310,7 +310,7 @@ static void ccw_device_oper_notify(struct ccw_device *cdev)
struct subchannel *sch = to_subchannel(cdev->dev.parent);
if (ccw_device_notify(cdev, CIO_OPER) == NOTIFY_OK) {
- /* Reenable channel measurements, if needed. */
+ /* Re-enable channel measurements, if needed. */
ccw_device_sched_todo(cdev, CDEV_TODO_ENABLE_CMF);
/* Save indication for new paths. */
cdev->private->path_new_mask = sch->vpm;
@@ -947,7 +947,7 @@ void ccw_device_trigger_reprobe(struct ccw_device *cdev)
*/
sch->lpm = sch->schib.pmcw.pam & sch->opm;
/*
- * Use the initial configuration since we can't be shure that the old
+ * Use the initial configuration since we can't be sure that the old
* paths are valid.
*/
io_subchannel_init_config(sch);
diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 1c31e81ca8de..aafd66305ead 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -672,7 +672,7 @@ out_init:
/*
* Fetch one ccw.
* To reduce memory copy, we'll pin the cda page in memory,
- * and to get rid of the cda 2G limitiaion of ccw1, we'll translate
+ * and to get rid of the cda 2G limitation of ccw1, we'll translate
* direct ccws to idal ccws.
*/
static int ccwchain_fetch_one(struct ccw1 *ccw,
@@ -787,7 +787,7 @@ void cp_free(struct channel_program *cp)
* program.
*
* These APIs will copy the ccws into kernel-space buffers, and update
- * the guest phsical addresses with their corresponding host physical
+ * the guest physical addresses with their corresponding host physical
* addresses. Then channel I/O device drivers could issue the
* translated channel program to real devices to perform an I/O
* operation.
diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c
index ff538a086fc7..43601816ea4e 100644
--- a/drivers/s390/cio/vfio_ccw_drv.c
+++ b/drivers/s390/cio/vfio_ccw_drv.c
@@ -171,7 +171,7 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
return -ENODEV;
}
- parent = kzalloc(sizeof(*parent), GFP_KERNEL);
+ parent = kzalloc(struct_size(parent, mdev_types, 1), GFP_KERNEL);
if (!parent)
return -ENOMEM;
diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_ccw_private.h
index b441ae6700fd..b62bbc5c6376 100644
--- a/drivers/s390/cio/vfio_ccw_private.h
+++ b/drivers/s390/cio/vfio_ccw_private.h
@@ -79,7 +79,7 @@ struct vfio_ccw_parent {
struct mdev_parent parent;
struct mdev_type mdev_type;
- struct mdev_type *mdev_types[1];
+ struct mdev_type *mdev_types[];
};
/**
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 8d6b9a52bf3c..420120be300f 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -497,7 +497,7 @@ static void ap_tasklet_fn(unsigned long dummy)
enum ap_sm_wait wait = AP_SM_WAIT_NONE;
/* Reset the indicator if interrupts are used. Thus new interrupts can
- * be received. Doing it in the beginning of the tasklet is therefor
+ * be received. Doing it in the beginning of the tasklet is therefore
* important that no requests on any AP get lost.
*/
if (ap_irq_flag)
@@ -2289,7 +2289,7 @@ static int __init ap_module_init(void)
timer_setup(&ap_config_timer, ap_config_timeout, 0);
/*
- * Setup the high resultion poll timer.
+ * Setup the high resolution poll timer.
* If we are running under z/VM adjust polling to z/VM polling rate.
*/
if (MACHINE_IS_VM)
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 101fb324476f..0d7b7eb374ad 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -233,30 +233,6 @@ struct ap_queue {
typedef enum ap_sm_wait (ap_func_t)(struct ap_queue *queue);
-/* failure injection cmd struct */
-struct ap_fi {
- union {
- u16 cmd; /* fi flags + action */
- struct {
- u8 flags; /* fi flags only */
- u8 action; /* fi action only */
- };
- };
-};
-
-/* all currently known fi actions */
-enum ap_fi_actions {
- AP_FI_ACTION_CCA_AGENT_FF = 0x01,
- AP_FI_ACTION_CCA_DOM_INVAL = 0x02,
- AP_FI_ACTION_NQAP_QID_INVAL = 0x03,
-};
-
-/* all currently known fi flags */
-enum ap_fi_flags {
- AP_FI_FLAG_NO_RETRY = 0x01,
- AP_FI_FLAG_TOGGLE_SPECIAL = 0x02,
-};
-
struct ap_message {
struct list_head list; /* Request queueing. */
unsigned long psmid; /* Message id. */
@@ -264,7 +240,6 @@ struct ap_message {
size_t len; /* actual msg len in msg buffer */
size_t bufsize; /* allocated msg buffer size */
u16 flags; /* Flags, see AP_MSG_FLAG_xxx */
- struct ap_fi fi; /* Failure Injection cmd */
int rc; /* Return code for this message */
void *private; /* ap driver private pointer. */
/* receive is called from tasklet context */
@@ -384,7 +359,7 @@ int ap_apqn_in_matrix_owned_by_def_drv(unsigned long *apm,
* like "+1-16,-32,-0x40,+128" where only single bits or ranges of
* bits are cleared or set. Distinction is done based on the very
* first character which may be '+' or '-' for the relative string
- * and othewise assume to be an absolute value string. If parsing fails
+ * and otherwise assume to be an absolute value string. If parsing fails
* a negative errno value is returned. All arguments and bitmaps are
* big endian order.
*/
diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c
index ed8f813653fe..30df83735adf 100644
--- a/drivers/s390/crypto/ap_queue.c
+++ b/drivers/s390/crypto/ap_queue.c
@@ -274,13 +274,6 @@ static enum ap_sm_wait ap_sm_write(struct ap_queue *aq)
/* Start the next request on the queue. */
ap_msg = list_entry(aq->requestq.next, struct ap_message, list);
-#ifdef CONFIG_ZCRYPT_DEBUG
- if (ap_msg->fi.action == AP_FI_ACTION_NQAP_QID_INVAL) {
- AP_DBF_WARN("%s fi cmd 0x%04x: forcing invalid qid 0xFF00\n",
- __func__, ap_msg->fi.cmd);
- qid = 0xFF00;
- }
-#endif
status = __ap_send(qid, ap_msg->psmid,
ap_msg->msg, ap_msg->len,
ap_msg->flags & AP_MSG_FLAG_SPECIAL);
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c
index a8def50c149b..e58bfd225323 100644
--- a/drivers/s390/crypto/pkey_api.c
+++ b/drivers/s390/crypto/pkey_api.c
@@ -2,7 +2,8 @@
/*
* pkey device driver
*
- * Copyright IBM Corp. 2017,2019
+ * Copyright IBM Corp. 2017, 2023
+ *
* Author(s): Harald Freudenberger
*/
@@ -32,8 +33,10 @@ MODULE_AUTHOR("IBM Corporation");
MODULE_DESCRIPTION("s390 protected key interface");
#define KEYBLOBBUFSIZE 8192 /* key buffer size used for internal processing */
+#define MINKEYBLOBBUFSIZE (sizeof(struct keytoken_header))
#define PROTKEYBLOBBUFSIZE 256 /* protected key buffer size used internal */
#define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */
+#define AES_WK_VP_SIZE 32 /* Size of WK VP block appended to a prot key */
/*
* debug feature data and functions
@@ -71,49 +74,106 @@ struct protaeskeytoken {
} __packed;
/* inside view of a clear key token (type 0x00 version 0x02) */
-struct clearaeskeytoken {
- u8 type; /* 0x00 for PAES specific key tokens */
+struct clearkeytoken {
+ u8 type; /* 0x00 for PAES specific key tokens */
u8 res0[3];
- u8 version; /* 0x02 for clear AES key token */
+ u8 version; /* 0x02 for clear key token */
u8 res1[3];
- u32 keytype; /* key type, one of the PKEY_KEYTYPE values */
- u32 len; /* bytes actually stored in clearkey[] */
+ u32 keytype; /* key type, one of the PKEY_KEYTYPE_* values */
+ u32 len; /* bytes actually stored in clearkey[] */
u8 clearkey[]; /* clear key value */
} __packed;
+/* helper function which translates the PKEY_KEYTYPE_AES_* to their keysize */
+static inline u32 pkey_keytype_aes_to_size(u32 keytype)
+{
+ switch (keytype) {
+ case PKEY_KEYTYPE_AES_128:
+ return 16;
+ case PKEY_KEYTYPE_AES_192:
+ return 24;
+ case PKEY_KEYTYPE_AES_256:
+ return 32;
+ default:
+ return 0;
+ }
+}
+
/*
- * Create a protected key from a clear key value.
+ * Create a protected key from a clear key value via PCKMO instruction.
*/
-static int pkey_clr2protkey(u32 keytype,
- const struct pkey_clrkey *clrkey,
- struct pkey_protkey *protkey)
+static int pkey_clr2protkey(u32 keytype, const u8 *clrkey,
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype)
{
/* mask of available pckmo subfunctions */
static cpacf_mask_t pckmo_functions;
- long fc;
+ u8 paramblock[112];
+ u32 pkeytype;
int keysize;
- u8 paramblock[64];
+ long fc;
switch (keytype) {
case PKEY_KEYTYPE_AES_128:
+ /* 16 byte key, 32 byte aes wkvp, total 48 bytes */
keysize = 16;
+ pkeytype = keytype;
fc = CPACF_PCKMO_ENC_AES_128_KEY;
break;
case PKEY_KEYTYPE_AES_192:
+ /* 24 byte key, 32 byte aes wkvp, total 56 bytes */
keysize = 24;
+ pkeytype = keytype;
fc = CPACF_PCKMO_ENC_AES_192_KEY;
break;
case PKEY_KEYTYPE_AES_256:
+ /* 32 byte key, 32 byte aes wkvp, total 64 bytes */
keysize = 32;
+ pkeytype = keytype;
fc = CPACF_PCKMO_ENC_AES_256_KEY;
break;
+ case PKEY_KEYTYPE_ECC_P256:
+ /* 32 byte key, 32 byte aes wkvp, total 64 bytes */
+ keysize = 32;
+ pkeytype = PKEY_KEYTYPE_ECC;
+ fc = CPACF_PCKMO_ENC_ECC_P256_KEY;
+ break;
+ case PKEY_KEYTYPE_ECC_P384:
+ /* 48 byte key, 32 byte aes wkvp, total 80 bytes */
+ keysize = 48;
+ pkeytype = PKEY_KEYTYPE_ECC;
+ fc = CPACF_PCKMO_ENC_ECC_P384_KEY;
+ break;
+ case PKEY_KEYTYPE_ECC_P521:
+ /* 80 byte key, 32 byte aes wkvp, total 112 bytes */
+ keysize = 80;
+ pkeytype = PKEY_KEYTYPE_ECC;
+ fc = CPACF_PCKMO_ENC_ECC_P521_KEY;
+ break;
+ case PKEY_KEYTYPE_ECC_ED25519:
+ /* 32 byte key, 32 byte aes wkvp, total 64 bytes */
+ keysize = 32;
+ pkeytype = PKEY_KEYTYPE_ECC;
+ fc = CPACF_PCKMO_ENC_ECC_ED25519_KEY;
+ break;
+ case PKEY_KEYTYPE_ECC_ED448:
+ /* 64 byte key, 32 byte aes wkvp, total 96 bytes */
+ keysize = 64;
+ pkeytype = PKEY_KEYTYPE_ECC;
+ fc = CPACF_PCKMO_ENC_ECC_ED448_KEY;
+ break;
default:
- DEBUG_ERR("%s unknown/unsupported keytype %d\n",
+ DEBUG_ERR("%s unknown/unsupported keytype %u\n",
__func__, keytype);
return -EINVAL;
}
+ if (*protkeylen < keysize + AES_WK_VP_SIZE) {
+ DEBUG_ERR("%s prot key buffer size too small: %u < %d\n",
+ __func__, *protkeylen, keysize + AES_WK_VP_SIZE);
+ return -EINVAL;
+ }
+
/* Did we already check for PCKMO ? */
if (!pckmo_functions.bytes[0]) {
/* no, so check now */
@@ -128,15 +188,15 @@ static int pkey_clr2protkey(u32 keytype,
/* prepare param block */
memset(paramblock, 0, sizeof(paramblock));
- memcpy(paramblock, clrkey->clrkey, keysize);
+ memcpy(paramblock, clrkey, keysize);
/* call the pckmo instruction */
cpacf_pckmo(fc, paramblock);
- /* copy created protected key */
- protkey->type = keytype;
- protkey->len = keysize + 32;
- memcpy(protkey->protkey, paramblock, keysize + 32);
+ /* copy created protected key to key buffer including the wkvp block */
+ *protkeylen = keysize + AES_WK_VP_SIZE;
+ memcpy(protkey, paramblock, *protkeylen);
+ *protkeytype = pkeytype;
return 0;
}
@@ -144,11 +204,12 @@ static int pkey_clr2protkey(u32 keytype,
/*
* Find card and transform secure key into protected key.
*/
-static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey)
+static int pkey_skey2pkey(const u8 *key, u8 *protkey,
+ u32 *protkeylen, u32 *protkeytype)
{
- int rc, verify;
- u16 cardnr, domain;
struct keytoken_header *hdr = (struct keytoken_header *)key;
+ u16 cardnr, domain;
+ int rc, verify;
zcrypt_wait_api_operational();
@@ -167,14 +228,13 @@ static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey)
continue;
switch (hdr->version) {
case TOKVER_CCA_AES:
- rc = cca_sec2protkey(cardnr, domain,
- key, pkey->protkey,
- &pkey->len, &pkey->type);
+ rc = cca_sec2protkey(cardnr, domain, key,
+ protkey, protkeylen, protkeytype);
break;
case TOKVER_CCA_VLSC:
- rc = cca_cipher2protkey(cardnr, domain,
- key, pkey->protkey,
- &pkey->len, &pkey->type);
+ rc = cca_cipher2protkey(cardnr, domain, key,
+ protkey, protkeylen,
+ protkeytype);
break;
default:
return -EINVAL;
@@ -195,9 +255,9 @@ static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey)
static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen,
u8 *keybuf, size_t *keybuflen)
{
- int i, rc;
- u16 card, dom;
u32 nr_apqns, *apqns = NULL;
+ u16 card, dom;
+ int i, rc;
zcrypt_wait_api_operational();
@@ -227,12 +287,13 @@ out:
/*
* Find card and transform EP11 secure key into protected key.
*/
-static int pkey_ep11key2pkey(const u8 *key, struct pkey_protkey *pkey)
+static int pkey_ep11key2pkey(const u8 *key, u8 *protkey,
+ u32 *protkeylen, u32 *protkeytype)
{
- int i, rc;
- u16 card, dom;
- u32 nr_apqns, *apqns = NULL;
struct ep11keyblob *kb = (struct ep11keyblob *)key;
+ u32 nr_apqns, *apqns = NULL;
+ u16 card, dom;
+ int i, rc;
zcrypt_wait_api_operational();
@@ -246,9 +307,8 @@ static int pkey_ep11key2pkey(const u8 *key, struct pkey_protkey *pkey)
for (rc = -ENODEV, i = 0; i < nr_apqns; i++) {
card = apqns[i] >> 16;
dom = apqns[i] & 0xFFFF;
- pkey->len = sizeof(pkey->protkey);
rc = ep11_kblob2protkey(card, dom, key, kb->head.len,
- pkey->protkey, &pkey->len, &pkey->type);
+ protkey, protkeylen, protkeytype);
if (rc == 0)
break;
}
@@ -306,38 +366,31 @@ out:
/*
* Generate a random protected key
*/
-static int pkey_genprotkey(u32 keytype, struct pkey_protkey *protkey)
+static int pkey_genprotkey(u32 keytype, u8 *protkey,
+ u32 *protkeylen, u32 *protkeytype)
{
- struct pkey_clrkey clrkey;
+ u8 clrkey[32];
int keysize;
int rc;
- switch (keytype) {
- case PKEY_KEYTYPE_AES_128:
- keysize = 16;
- break;
- case PKEY_KEYTYPE_AES_192:
- keysize = 24;
- break;
- case PKEY_KEYTYPE_AES_256:
- keysize = 32;
- break;
- default:
+ keysize = pkey_keytype_aes_to_size(keytype);
+ if (!keysize) {
DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__,
keytype);
return -EINVAL;
}
/* generate a dummy random clear key */
- get_random_bytes(clrkey.clrkey, keysize);
+ get_random_bytes(clrkey, keysize);
/* convert it to a dummy protected key */
- rc = pkey_clr2protkey(keytype, &clrkey, protkey);
+ rc = pkey_clr2protkey(keytype, clrkey,
+ protkey, protkeylen, protkeytype);
if (rc)
return rc;
/* replace the key part of the protected key with random bytes */
- get_random_bytes(protkey->protkey, keysize);
+ get_random_bytes(protkey, keysize);
return 0;
}
@@ -345,37 +398,46 @@ static int pkey_genprotkey(u32 keytype, struct pkey_protkey *protkey)
/*
* Verify if a protected key is still valid
*/
-static int pkey_verifyprotkey(const struct pkey_protkey *protkey)
+static int pkey_verifyprotkey(const u8 *protkey, u32 protkeylen,
+ u32 protkeytype)
{
- unsigned long fc;
struct {
u8 iv[AES_BLOCK_SIZE];
u8 key[MAXPROTKEYSIZE];
} param;
u8 null_msg[AES_BLOCK_SIZE];
u8 dest_buf[AES_BLOCK_SIZE];
- unsigned int k;
+ unsigned int k, pkeylen;
+ unsigned long fc;
- switch (protkey->type) {
+ switch (protkeytype) {
case PKEY_KEYTYPE_AES_128:
+ pkeylen = 16 + AES_WK_VP_SIZE;
fc = CPACF_KMC_PAES_128;
break;
case PKEY_KEYTYPE_AES_192:
+ pkeylen = 24 + AES_WK_VP_SIZE;
fc = CPACF_KMC_PAES_192;
break;
case PKEY_KEYTYPE_AES_256:
+ pkeylen = 32 + AES_WK_VP_SIZE;
fc = CPACF_KMC_PAES_256;
break;
default:
- DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__,
- protkey->type);
+ DEBUG_ERR("%s unknown/unsupported keytype %u\n", __func__,
+ protkeytype);
+ return -EINVAL;
+ }
+ if (protkeylen != pkeylen) {
+ DEBUG_ERR("%s invalid protected key size %u for keytype %u\n",
+ __func__, protkeylen, protkeytype);
return -EINVAL;
}
memset(null_msg, 0, sizeof(null_msg));
memset(param.iv, 0, sizeof(param.iv));
- memcpy(param.key, protkey->protkey, sizeof(param.key));
+ memcpy(param.key, protkey, protkeylen);
k = cpacf_kmc(fc | CPACF_ENCRYPT, &param, null_msg, dest_buf,
sizeof(null_msg));
@@ -387,15 +449,119 @@ static int pkey_verifyprotkey(const struct pkey_protkey *protkey)
return 0;
}
+/* Helper for pkey_nonccatok2pkey, handles aes clear key token */
+static int nonccatokaes2pkey(const struct clearkeytoken *t,
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype)
+{
+ size_t tmpbuflen = max_t(size_t, SECKEYBLOBSIZE, MAXEP11AESKEYBLOBSIZE);
+ u8 *tmpbuf = NULL;
+ u32 keysize;
+ int rc;
+
+ keysize = pkey_keytype_aes_to_size(t->keytype);
+ if (!keysize) {
+ DEBUG_ERR("%s unknown/unsupported keytype %u\n",
+ __func__, t->keytype);
+ return -EINVAL;
+ }
+ if (t->len != keysize) {
+ DEBUG_ERR("%s non clear key aes token: invalid key len %u\n",
+ __func__, t->len);
+ return -EINVAL;
+ }
+
+ /* try direct way with the PCKMO instruction */
+ rc = pkey_clr2protkey(t->keytype, t->clearkey,
+ protkey, protkeylen, protkeytype);
+ if (!rc)
+ goto out;
+
+ /* PCKMO failed, so try the CCA secure key way */
+ tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC);
+ if (!tmpbuf)
+ return -ENOMEM;
+ zcrypt_wait_api_operational();
+ rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, t->clearkey, tmpbuf);
+ if (rc)
+ goto try_via_ep11;
+ rc = pkey_skey2pkey(tmpbuf,
+ protkey, protkeylen, protkeytype);
+ if (!rc)
+ goto out;
+
+try_via_ep11:
+ /* if the CCA way also failed, let's try via EP11 */
+ rc = pkey_clr2ep11key(t->clearkey, t->len,
+ tmpbuf, &tmpbuflen);
+ if (rc)
+ goto failure;
+ rc = pkey_ep11key2pkey(tmpbuf,
+ protkey, protkeylen, protkeytype);
+ if (!rc)
+ goto out;
+
+failure:
+ DEBUG_ERR("%s unable to build protected key from clear", __func__);
+
+out:
+ kfree(tmpbuf);
+ return rc;
+}
+
+/* Helper for pkey_nonccatok2pkey, handles ecc clear key token */
+static int nonccatokecc2pkey(const struct clearkeytoken *t,
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype)
+{
+ u32 keylen;
+ int rc;
+
+ switch (t->keytype) {
+ case PKEY_KEYTYPE_ECC_P256:
+ keylen = 32;
+ break;
+ case PKEY_KEYTYPE_ECC_P384:
+ keylen = 48;
+ break;
+ case PKEY_KEYTYPE_ECC_P521:
+ keylen = 80;
+ break;
+ case PKEY_KEYTYPE_ECC_ED25519:
+ keylen = 32;
+ break;
+ case PKEY_KEYTYPE_ECC_ED448:
+ keylen = 64;
+ break;
+ default:
+ DEBUG_ERR("%s unknown/unsupported keytype %u\n",
+ __func__, t->keytype);
+ return -EINVAL;
+ }
+
+ if (t->len != keylen) {
+ DEBUG_ERR("%s non clear key ecc token: invalid key len %u\n",
+ __func__, t->len);
+ return -EINVAL;
+ }
+
+ /* only one path possible: via PCKMO instruction */
+ rc = pkey_clr2protkey(t->keytype, t->clearkey,
+ protkey, protkeylen, protkeytype);
+ if (rc) {
+ DEBUG_ERR("%s unable to build protected key from clear",
+ __func__);
+ }
+
+ return rc;
+}
+
/*
* Transform a non-CCA key token into a protected key
*/
static int pkey_nonccatok2pkey(const u8 *key, u32 keylen,
- struct pkey_protkey *protkey)
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype)
{
- int rc = -EINVAL;
- u8 *tmpbuf = NULL;
struct keytoken_header *hdr = (struct keytoken_header *)key;
+ int rc = -EINVAL;
switch (hdr->version) {
case TOKVER_PROTECTED_KEY: {
@@ -404,59 +570,40 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen,
if (keylen != sizeof(struct protaeskeytoken))
goto out;
t = (struct protaeskeytoken *)key;
- protkey->len = t->len;
- protkey->type = t->keytype;
- memcpy(protkey->protkey, t->protkey,
- sizeof(protkey->protkey));
- rc = pkey_verifyprotkey(protkey);
+ rc = pkey_verifyprotkey(t->protkey, t->len, t->keytype);
+ if (rc)
+ goto out;
+ memcpy(protkey, t->protkey, t->len);
+ *protkeylen = t->len;
+ *protkeytype = t->keytype;
break;
}
case TOKVER_CLEAR_KEY: {
- struct clearaeskeytoken *t;
- struct pkey_clrkey ckey;
- union u_tmpbuf {
- u8 skey[SECKEYBLOBSIZE];
- u8 ep11key[MAXEP11AESKEYBLOBSIZE];
- };
- size_t tmpbuflen = sizeof(union u_tmpbuf);
-
- if (keylen < sizeof(struct clearaeskeytoken))
- goto out;
- t = (struct clearaeskeytoken *)key;
- if (keylen != sizeof(*t) + t->len)
- goto out;
- if ((t->keytype == PKEY_KEYTYPE_AES_128 && t->len == 16) ||
- (t->keytype == PKEY_KEYTYPE_AES_192 && t->len == 24) ||
- (t->keytype == PKEY_KEYTYPE_AES_256 && t->len == 32))
- memcpy(ckey.clrkey, t->clearkey, t->len);
- else
- goto out;
- /* alloc temp key buffer space */
- tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC);
- if (!tmpbuf) {
- rc = -ENOMEM;
+ struct clearkeytoken *t = (struct clearkeytoken *)key;
+
+ if (keylen < sizeof(struct clearkeytoken) ||
+ keylen != sizeof(*t) + t->len)
goto out;
- }
- /* try direct way with the PCKMO instruction */
- rc = pkey_clr2protkey(t->keytype, &ckey, protkey);
- if (rc == 0)
+ switch (t->keytype) {
+ case PKEY_KEYTYPE_AES_128:
+ case PKEY_KEYTYPE_AES_192:
+ case PKEY_KEYTYPE_AES_256:
+ rc = nonccatokaes2pkey(t, protkey,
+ protkeylen, protkeytype);
break;
- /* PCKMO failed, so try the CCA secure key way */
- zcrypt_wait_api_operational();
- rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype,
- ckey.clrkey, tmpbuf);
- if (rc == 0)
- rc = pkey_skey2pkey(tmpbuf, protkey);
- if (rc == 0)
+ case PKEY_KEYTYPE_ECC_P256:
+ case PKEY_KEYTYPE_ECC_P384:
+ case PKEY_KEYTYPE_ECC_P521:
+ case PKEY_KEYTYPE_ECC_ED25519:
+ case PKEY_KEYTYPE_ECC_ED448:
+ rc = nonccatokecc2pkey(t, protkey,
+ protkeylen, protkeytype);
break;
- /* if the CCA way also failed, let's try via EP11 */
- rc = pkey_clr2ep11key(ckey.clrkey, t->len,
- tmpbuf, &tmpbuflen);
- if (rc == 0)
- rc = pkey_ep11key2pkey(tmpbuf, protkey);
- /* now we should really have an protected key */
- DEBUG_ERR("%s unable to build protected key from clear",
- __func__);
+ default:
+ DEBUG_ERR("%s unknown/unsupported non cca clear key type %u\n",
+ __func__, t->keytype);
+ return -EINVAL;
+ }
break;
}
case TOKVER_EP11_AES: {
@@ -464,7 +611,8 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen,
rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1);
if (rc)
goto out;
- rc = pkey_ep11key2pkey(key, protkey);
+ rc = pkey_ep11key2pkey(key,
+ protkey, protkeylen, protkeytype);
break;
}
case TOKVER_EP11_AES_WITH_HEADER:
@@ -473,16 +621,14 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen,
if (rc)
goto out;
rc = pkey_ep11key2pkey(key + sizeof(struct ep11kblob_header),
- protkey);
+ protkey, protkeylen, protkeytype);
break;
default:
DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n",
__func__, hdr->version);
- rc = -EINVAL;
}
out:
- kfree(tmpbuf);
return rc;
}
@@ -490,7 +636,7 @@ out:
* Transform a CCA internal key token into a protected key
*/
static int pkey_ccainttok2pkey(const u8 *key, u32 keylen,
- struct pkey_protkey *protkey)
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype)
{
struct keytoken_header *hdr = (struct keytoken_header *)key;
@@ -509,17 +655,17 @@ static int pkey_ccainttok2pkey(const u8 *key, u32 keylen,
return -EINVAL;
}
- return pkey_skey2pkey(key, protkey);
+ return pkey_skey2pkey(key, protkey, protkeylen, protkeytype);
}
/*
* Transform a key blob (of any type) into a protected key
*/
int pkey_keyblob2pkey(const u8 *key, u32 keylen,
- struct pkey_protkey *protkey)
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype)
{
- int rc;
struct keytoken_header *hdr = (struct keytoken_header *)key;
+ int rc;
if (keylen < sizeof(struct keytoken_header)) {
DEBUG_ERR("%s invalid keylen %d\n", __func__, keylen);
@@ -528,10 +674,12 @@ int pkey_keyblob2pkey(const u8 *key, u32 keylen,
switch (hdr->type) {
case TOKTYPE_NON_CCA:
- rc = pkey_nonccatok2pkey(key, keylen, protkey);
+ rc = pkey_nonccatok2pkey(key, keylen,
+ protkey, protkeylen, protkeytype);
break;
case TOKTYPE_CCA_INTERNAL:
- rc = pkey_ccainttok2pkey(key, keylen, protkey);
+ rc = pkey_ccainttok2pkey(key, keylen,
+ protkey, protkeylen, protkeytype);
break;
default:
DEBUG_ERR("%s unknown/unsupported blob type %d\n",
@@ -663,9 +811,9 @@ static int pkey_verifykey2(const u8 *key, size_t keylen,
enum pkey_key_type *ktype,
enum pkey_key_size *ksize, u32 *flags)
{
- int rc;
- u32 _nr_apqns, *_apqns = NULL;
struct keytoken_header *hdr = (struct keytoken_header *)key;
+ u32 _nr_apqns, *_apqns = NULL;
+ int rc;
if (keylen < sizeof(struct keytoken_header))
return -EINVAL;
@@ -771,10 +919,10 @@ out:
static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns,
const u8 *key, size_t keylen,
- struct pkey_protkey *pkey)
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype)
{
- int i, card, dom, rc;
struct keytoken_header *hdr = (struct keytoken_header *)key;
+ int i, card, dom, rc;
/* check for at least one apqn given */
if (!apqns || !nr_apqns)
@@ -806,7 +954,9 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns,
if (ep11_check_aes_key(debug_info, 3, key, keylen, 1))
return -EINVAL;
} else {
- return pkey_nonccatok2pkey(key, keylen, pkey);
+ return pkey_nonccatok2pkey(key, keylen,
+ protkey, protkeylen,
+ protkeytype);
}
} else {
DEBUG_ERR("%s unknown/unsupported blob type %d\n",
@@ -822,20 +972,20 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns,
dom = apqns[i].domain;
if (hdr->type == TOKTYPE_CCA_INTERNAL &&
hdr->version == TOKVER_CCA_AES) {
- rc = cca_sec2protkey(card, dom, key, pkey->protkey,
- &pkey->len, &pkey->type);
+ rc = cca_sec2protkey(card, dom, key,
+ protkey, protkeylen, protkeytype);
} else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
hdr->version == TOKVER_CCA_VLSC) {
- rc = cca_cipher2protkey(card, dom, key, pkey->protkey,
- &pkey->len, &pkey->type);
+ rc = cca_cipher2protkey(card, dom, key,
+ protkey, protkeylen,
+ protkeytype);
} else {
/* EP11 AES secure key blob */
struct ep11keyblob *kb = (struct ep11keyblob *)key;
- pkey->len = sizeof(pkey->protkey);
rc = ep11_kblob2protkey(card, dom, key, kb->head.len,
- pkey->protkey, &pkey->len,
- &pkey->type);
+ protkey, protkeylen,
+ protkeytype);
}
if (rc == 0)
break;
@@ -847,9 +997,9 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns,
static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags,
struct pkey_apqn *apqns, size_t *nr_apqns)
{
- int rc;
- u32 _nr_apqns, *_apqns = NULL;
struct keytoken_header *hdr = (struct keytoken_header *)key;
+ u32 _nr_apqns, *_apqns = NULL;
+ int rc;
if (keylen < sizeof(struct keytoken_header) || flags == 0)
return -EINVAL;
@@ -860,9 +1010,9 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags,
(hdr->version == TOKVER_EP11_AES_WITH_HEADER ||
hdr->version == TOKVER_EP11_ECC_WITH_HEADER) &&
is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {
- int minhwtype = 0, api = 0;
struct ep11keyblob *kb = (struct ep11keyblob *)
(key + sizeof(struct ep11kblob_header));
+ int minhwtype = 0, api = 0;
if (flags != PKEY_FLAGS_MATCH_CUR_MKVP)
return -EINVAL;
@@ -877,8 +1027,8 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags,
} else if (hdr->type == TOKTYPE_NON_CCA &&
hdr->version == TOKVER_EP11_AES &&
is_ep11_keyblob(key)) {
- int minhwtype = 0, api = 0;
struct ep11keyblob *kb = (struct ep11keyblob *)key;
+ int minhwtype = 0, api = 0;
if (flags != PKEY_FLAGS_MATCH_CUR_MKVP)
return -EINVAL;
@@ -891,8 +1041,8 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags,
if (rc)
goto out;
} else if (hdr->type == TOKTYPE_CCA_INTERNAL) {
- int minhwtype = ZCRYPT_CEX3C;
u64 cur_mkvp = 0, old_mkvp = 0;
+ int minhwtype = ZCRYPT_CEX3C;
if (hdr->version == TOKVER_CCA_AES) {
struct secaeskeytoken *t = (struct secaeskeytoken *)key;
@@ -919,8 +1069,8 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags,
if (rc)
goto out;
} else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
- u64 cur_mkvp = 0, old_mkvp = 0;
struct eccprivkeytoken *t = (struct eccprivkeytoken *)key;
+ u64 cur_mkvp = 0, old_mkvp = 0;
if (t->secid == 0x20) {
if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
@@ -957,8 +1107,8 @@ static int pkey_apqns4keytype(enum pkey_key_type ktype,
u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,
struct pkey_apqn *apqns, size_t *nr_apqns)
{
- int rc;
u32 _nr_apqns, *_apqns = NULL;
+ int rc;
zcrypt_wait_api_operational();
@@ -1020,11 +1170,11 @@ out:
}
static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns,
- const u8 *key, size_t keylen, u32 *protkeytype,
- u8 *protkey, u32 *protkeylen)
+ const u8 *key, size_t keylen,
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype)
{
- int i, card, dom, rc;
struct keytoken_header *hdr = (struct keytoken_header *)key;
+ int i, card, dom, rc;
/* check for at least one apqn given */
if (!apqns || !nr_apqns)
@@ -1076,15 +1226,8 @@ static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns,
if (cca_check_sececckeytoken(debug_info, 3, key, keylen, 1))
return -EINVAL;
} else if (hdr->type == TOKTYPE_NON_CCA) {
- struct pkey_protkey pkey;
-
- rc = pkey_nonccatok2pkey(key, keylen, &pkey);
- if (rc)
- return rc;
- memcpy(protkey, pkey.protkey, pkey.len);
- *protkeylen = pkey.len;
- *protkeytype = pkey.type;
- return 0;
+ return pkey_nonccatok2pkey(key, keylen,
+ protkey, protkeylen, protkeytype);
} else {
DEBUG_ERR("%s unknown/unsupported blob type %d\n",
__func__, hdr->type);
@@ -1130,7 +1273,7 @@ static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns,
static void *_copy_key_from_user(void __user *ukey, size_t keylen)
{
- if (!ukey || keylen < MINKEYBLOBSIZE || keylen > KEYBLOBBUFSIZE)
+ if (!ukey || keylen < MINKEYBLOBBUFSIZE || keylen > KEYBLOBBUFSIZE)
return ERR_PTR(-EINVAL);
return memdup_user(ukey, keylen);
@@ -1187,6 +1330,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
if (copy_from_user(&ksp, usp, sizeof(ksp)))
return -EFAULT;
+ ksp.protkey.len = sizeof(ksp.protkey.protkey);
rc = cca_sec2protkey(ksp.cardnr, ksp.domain,
ksp.seckey.seckey, ksp.protkey.protkey,
&ksp.protkey.len, &ksp.protkey.type);
@@ -1203,8 +1347,10 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
if (copy_from_user(&kcp, ucp, sizeof(kcp)))
return -EFAULT;
- rc = pkey_clr2protkey(kcp.keytype,
- &kcp.clrkey, &kcp.protkey);
+ kcp.protkey.len = sizeof(kcp.protkey.protkey);
+ rc = pkey_clr2protkey(kcp.keytype, kcp.clrkey.clrkey,
+ kcp.protkey.protkey,
+ &kcp.protkey.len, &kcp.protkey.type);
DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc);
if (rc)
break;
@@ -1234,7 +1380,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
if (copy_from_user(&ksp, usp, sizeof(ksp)))
return -EFAULT;
- rc = pkey_skey2pkey(ksp.seckey.seckey, &ksp.protkey);
+ ksp.protkey.len = sizeof(ksp.protkey.protkey);
+ rc = pkey_skey2pkey(ksp.seckey.seckey, ksp.protkey.protkey,
+ &ksp.protkey.len, &ksp.protkey.type);
DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc);
if (rc)
break;
@@ -1263,7 +1411,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
if (copy_from_user(&kgp, ugp, sizeof(kgp)))
return -EFAULT;
- rc = pkey_genprotkey(kgp.keytype, &kgp.protkey);
+ kgp.protkey.len = sizeof(kgp.protkey.protkey);
+ rc = pkey_genprotkey(kgp.keytype, kgp.protkey.protkey,
+ &kgp.protkey.len, &kgp.protkey.type);
DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc);
if (rc)
break;
@@ -1277,7 +1427,8 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
if (copy_from_user(&kvp, uvp, sizeof(kvp)))
return -EFAULT;
- rc = pkey_verifyprotkey(&kvp.protkey);
+ rc = pkey_verifyprotkey(kvp.protkey.protkey,
+ kvp.protkey.len, kvp.protkey.type);
DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc);
break;
}
@@ -1291,7 +1442,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
kkey = _copy_key_from_user(ktp.key, ktp.keylen);
if (IS_ERR(kkey))
return PTR_ERR(kkey);
- rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey);
+ ktp.protkey.len = sizeof(ktp.protkey.protkey);
+ rc = pkey_keyblob2pkey(kkey, ktp.keylen, ktp.protkey.protkey,
+ &ktp.protkey.len, &ktp.protkey.type);
DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc);
memzero_explicit(kkey, ktp.keylen);
kfree(kkey);
@@ -1303,9 +1456,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
}
case PKEY_GENSECK2: {
struct pkey_genseck2 __user *ugs = (void __user *)arg;
+ size_t klen = KEYBLOBBUFSIZE;
struct pkey_genseck2 kgs;
struct pkey_apqn *apqns;
- size_t klen = KEYBLOBBUFSIZE;
u8 *kkey;
if (copy_from_user(&kgs, ugs, sizeof(kgs)))
@@ -1345,9 +1498,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
}
case PKEY_CLR2SECK2: {
struct pkey_clr2seck2 __user *ucs = (void __user *)arg;
+ size_t klen = KEYBLOBBUFSIZE;
struct pkey_clr2seck2 kcs;
struct pkey_apqn *apqns;
- size_t klen = KEYBLOBBUFSIZE;
u8 *kkey;
if (copy_from_user(&kcs, ucs, sizeof(kcs)))
@@ -1409,8 +1562,8 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
}
case PKEY_KBLOB2PROTK2: {
struct pkey_kblob2pkey2 __user *utp = (void __user *)arg;
- struct pkey_kblob2pkey2 ktp;
struct pkey_apqn *apqns = NULL;
+ struct pkey_kblob2pkey2 ktp;
u8 *kkey;
if (copy_from_user(&ktp, utp, sizeof(ktp)))
@@ -1423,8 +1576,11 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
kfree(apqns);
return PTR_ERR(kkey);
}
+ ktp.protkey.len = sizeof(ktp.protkey.protkey);
rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries,
- kkey, ktp.keylen, &ktp.protkey);
+ kkey, ktp.keylen,
+ ktp.protkey.protkey, &ktp.protkey.len,
+ &ktp.protkey.type);
DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc);
kfree(apqns);
memzero_explicit(kkey, ktp.keylen);
@@ -1437,8 +1593,8 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
}
case PKEY_APQNS4K: {
struct pkey_apqns4key __user *uak = (void __user *)arg;
- struct pkey_apqns4key kak;
struct pkey_apqn *apqns = NULL;
+ struct pkey_apqns4key kak;
size_t nr_apqns, len;
u8 *kkey;
@@ -1486,8 +1642,8 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
}
case PKEY_APQNS4KT: {
struct pkey_apqns4keytype __user *uat = (void __user *)arg;
- struct pkey_apqns4keytype kat;
struct pkey_apqn *apqns = NULL;
+ struct pkey_apqns4keytype kat;
size_t nr_apqns, len;
if (copy_from_user(&kat, uat, sizeof(kat)))
@@ -1528,9 +1684,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
}
case PKEY_KBLOB2PROTK3: {
struct pkey_kblob2pkey3 __user *utp = (void __user *)arg;
- struct pkey_kblob2pkey3 ktp;
- struct pkey_apqn *apqns = NULL;
u32 protkeylen = PROTKEYBLOBBUFSIZE;
+ struct pkey_apqn *apqns = NULL;
+ struct pkey_kblob2pkey3 ktp;
u8 *kkey, *protkey;
if (copy_from_user(&ktp, utp, sizeof(ktp)))
@@ -1549,9 +1705,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
kfree(kkey);
return -ENOMEM;
}
- rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries, kkey,
- ktp.keylen, &ktp.pkeytype,
- protkey, &protkeylen);
+ rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries,
+ kkey, ktp.keylen,
+ protkey, &protkeylen, &ktp.pkeytype);
DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc);
kfree(apqns);
memzero_explicit(kkey, ktp.keylen);
@@ -1612,7 +1768,9 @@ static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf,
protkeytoken.version = TOKVER_PROTECTED_KEY;
protkeytoken.keytype = keytype;
- rc = pkey_genprotkey(protkeytoken.keytype, &protkey);
+ protkey.len = sizeof(protkey.protkey);
+ rc = pkey_genprotkey(protkeytoken.keytype,
+ protkey.protkey, &protkey.len, &protkey.type);
if (rc)
return rc;
@@ -1622,7 +1780,10 @@ static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf,
memcpy(buf, &protkeytoken, sizeof(protkeytoken));
if (is_xts) {
- rc = pkey_genprotkey(protkeytoken.keytype, &protkey);
+ /* xts needs a second protected key, reuse protkey struct */
+ protkey.len = sizeof(protkey.protkey);
+ rc = pkey_genprotkey(protkeytoken.keytype,
+ protkey.protkey, &protkey.len, &protkey.type);
if (rc)
return rc;
@@ -1717,8 +1878,8 @@ static struct attribute_group protkey_attr_group = {
static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf,
loff_t off, size_t count)
{
- int rc;
struct pkey_seckey *seckey = (struct pkey_seckey *)buf;
+ int rc;
if (off != 0 || count < sizeof(struct secaeskeytoken))
return -EINVAL;
@@ -1824,9 +1985,9 @@ static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits,
bool is_xts, char *buf, loff_t off,
size_t count)
{
- int i, rc, card, dom;
- u32 nr_apqns, *apqns = NULL;
size_t keysize = CCACIPHERTOKENSIZE;
+ u32 nr_apqns, *apqns = NULL;
+ int i, rc, card, dom;
if (off != 0 || count < CCACIPHERTOKENSIZE)
return -EINVAL;
@@ -1947,9 +2108,9 @@ static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits,
bool is_xts, char *buf, loff_t off,
size_t count)
{
- int i, rc, card, dom;
- u32 nr_apqns, *apqns = NULL;
size_t keysize = MAXEP11AESKEYBLOBSIZE;
+ u32 nr_apqns, *apqns = NULL;
+ int i, rc, card, dom;
if (off != 0 || count < MAXEP11AESKEYBLOBSIZE)
return -EINVAL;
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index cfbcb864ab63..b441745b0418 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -445,7 +445,7 @@ static struct ap_queue_status vfio_ap_irq_enable(struct vfio_ap_queue *q,
q->saved_isc = isc;
break;
case AP_RESPONSE_OTHERWISE_CHANGED:
- /* We could not modify IRQ setings: clear new configuration */
+ /* We could not modify IRQ settings: clear new configuration */
vfio_unpin_pages(&q->matrix_mdev->vdev, nib, 1);
kvm_s390_gisc_unregister(kvm, isc);
break;
@@ -524,7 +524,7 @@ static void vfio_ap_le_guid_to_be_uuid(guid_t *guid, unsigned long *uuid)
* Response.status may be set to following Response Code:
* - AP_RESPONSE_Q_NOT_AVAIL: if the queue is not available
* - AP_RESPONSE_DECONFIGURED: if the queue is not configured
- * - AP_RESPONSE_NORMAL (0) : in case of successs
+ * - AP_RESPONSE_NORMAL (0) : in case of success
* Check vfio_ap_setirq() and vfio_ap_clrirq() for other possible RC.
* We take the matrix_dev lock to ensure serialization on queues and
* mediated device access.
@@ -716,6 +716,7 @@ static int vfio_ap_mdev_probe(struct mdev_device *mdev)
ret = vfio_register_emulated_iommu_dev(&matrix_mdev->vdev);
if (ret)
goto err_put_vdev;
+ matrix_mdev->req_trigger = NULL;
dev_set_drvdata(&mdev->dev, matrix_mdev);
mutex_lock(&matrix_dev->mdevs_lock);
list_add(&matrix_mdev->node, &matrix_dev->mdev_list);
@@ -1735,6 +1736,26 @@ static void vfio_ap_mdev_close_device(struct vfio_device *vdev)
vfio_ap_mdev_unset_kvm(matrix_mdev);
}
+static void vfio_ap_mdev_request(struct vfio_device *vdev, unsigned int count)
+{
+ struct device *dev = vdev->dev;
+ struct ap_matrix_mdev *matrix_mdev;
+
+ matrix_mdev = container_of(vdev, struct ap_matrix_mdev, vdev);
+
+ if (matrix_mdev->req_trigger) {
+ if (!(count % 10))
+ dev_notice_ratelimited(dev,
+ "Relaying device request to user (#%u)\n",
+ count);
+
+ eventfd_signal(matrix_mdev->req_trigger, 1);
+ } else if (count == 0) {
+ dev_notice(dev,
+ "No device request registered, blocked until released by user\n");
+ }
+}
+
static int vfio_ap_mdev_get_device_info(unsigned long arg)
{
unsigned long minsz;
@@ -1750,11 +1771,115 @@ static int vfio_ap_mdev_get_device_info(unsigned long arg)
info.flags = VFIO_DEVICE_FLAGS_AP | VFIO_DEVICE_FLAGS_RESET;
info.num_regions = 0;
- info.num_irqs = 0;
+ info.num_irqs = VFIO_AP_NUM_IRQS;
return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0;
}
+static ssize_t vfio_ap_get_irq_info(unsigned long arg)
+{
+ unsigned long minsz;
+ struct vfio_irq_info info;
+
+ minsz = offsetofend(struct vfio_irq_info, count);
+
+ if (copy_from_user(&info, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (info.argsz < minsz || info.index >= VFIO_AP_NUM_IRQS)
+ return -EINVAL;
+
+ switch (info.index) {
+ case VFIO_AP_REQ_IRQ_INDEX:
+ info.count = 1;
+ info.flags = VFIO_IRQ_INFO_EVENTFD;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0;
+}
+
+static int vfio_ap_irq_set_init(struct vfio_irq_set *irq_set, unsigned long arg)
+{
+ int ret;
+ size_t data_size;
+ unsigned long minsz;
+
+ minsz = offsetofend(struct vfio_irq_set, count);
+
+ if (copy_from_user(irq_set, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ ret = vfio_set_irqs_validate_and_prepare(irq_set, 1, VFIO_AP_NUM_IRQS,
+ &data_size);
+ if (ret)
+ return ret;
+
+ if (!(irq_set->flags & VFIO_IRQ_SET_ACTION_TRIGGER))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int vfio_ap_set_request_irq(struct ap_matrix_mdev *matrix_mdev,
+ unsigned long arg)
+{
+ s32 fd;
+ void __user *data;
+ unsigned long minsz;
+ struct eventfd_ctx *req_trigger;
+
+ minsz = offsetofend(struct vfio_irq_set, count);
+ data = (void __user *)(arg + minsz);
+
+ if (get_user(fd, (s32 __user *)data))
+ return -EFAULT;
+
+ if (fd == -1) {
+ if (matrix_mdev->req_trigger)
+ eventfd_ctx_put(matrix_mdev->req_trigger);
+ matrix_mdev->req_trigger = NULL;
+ } else if (fd >= 0) {
+ req_trigger = eventfd_ctx_fdget(fd);
+ if (IS_ERR(req_trigger))
+ return PTR_ERR(req_trigger);
+
+ if (matrix_mdev->req_trigger)
+ eventfd_ctx_put(matrix_mdev->req_trigger);
+
+ matrix_mdev->req_trigger = req_trigger;
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vfio_ap_set_irqs(struct ap_matrix_mdev *matrix_mdev,
+ unsigned long arg)
+{
+ int ret;
+ struct vfio_irq_set irq_set;
+
+ ret = vfio_ap_irq_set_init(&irq_set, arg);
+ if (ret)
+ return ret;
+
+ switch (irq_set.flags & VFIO_IRQ_SET_DATA_TYPE_MASK) {
+ case VFIO_IRQ_SET_DATA_EVENTFD:
+ switch (irq_set.index) {
+ case VFIO_AP_REQ_IRQ_INDEX:
+ return vfio_ap_set_request_irq(matrix_mdev, arg);
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
static ssize_t vfio_ap_mdev_ioctl(struct vfio_device *vdev,
unsigned int cmd, unsigned long arg)
{
@@ -1770,6 +1895,12 @@ static ssize_t vfio_ap_mdev_ioctl(struct vfio_device *vdev,
case VFIO_DEVICE_RESET:
ret = vfio_ap_mdev_reset_queues(&matrix_mdev->qtable);
break;
+ case VFIO_DEVICE_GET_IRQ_INFO:
+ ret = vfio_ap_get_irq_info(arg);
+ break;
+ case VFIO_DEVICE_SET_IRQS:
+ ret = vfio_ap_set_irqs(matrix_mdev, arg);
+ break;
default:
ret = -EOPNOTSUPP;
break;
@@ -1844,6 +1975,7 @@ static const struct vfio_device_ops vfio_ap_matrix_dev_ops = {
.bind_iommufd = vfio_iommufd_emulated_bind,
.unbind_iommufd = vfio_iommufd_emulated_unbind,
.attach_ioas = vfio_iommufd_emulated_attach_ioas,
+ .request = vfio_ap_mdev_request
};
static struct mdev_driver vfio_ap_matrix_driver = {
diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h
index 976a65f32e7d..4642bbdbd1b2 100644
--- a/drivers/s390/crypto/vfio_ap_private.h
+++ b/drivers/s390/crypto/vfio_ap_private.h
@@ -15,6 +15,7 @@
#include <linux/types.h>
#include <linux/mdev.h>
#include <linux/delay.h>
+#include <linux/eventfd.h>
#include <linux/mutex.h>
#include <linux/kvm_host.h>
#include <linux/vfio.h>
@@ -103,6 +104,7 @@ struct ap_queue_table {
* PQAP(AQIC) instruction.
* @mdev: the mediated device
* @qtable: table of queues (struct vfio_ap_queue) assigned to the mdev
+ * @req_trigger eventfd ctx for signaling userspace to return a device
* @apm_add: bitmap of APIDs added to the host's AP configuration
* @aqm_add: bitmap of APQIs added to the host's AP configuration
* @adm_add: bitmap of control domain numbers added to the host's AP
@@ -117,6 +119,7 @@ struct ap_matrix_mdev {
crypto_hook pqap_hook;
struct mdev_device *mdev;
struct ap_queue_table qtable;
+ struct eventfd_ctx *req_trigger;
DECLARE_BITMAP(apm_add, AP_DEVICES);
DECLARE_BITMAP(aqm_add, AP_DOMAINS);
DECLARE_BITMAP(adm_add, AP_DOMAINS);
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 444ef95d3f59..4b23c9f7f3e5 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -111,8 +111,6 @@ EXPORT_SYMBOL(zcrypt_msgtype);
* Multi device nodes extension functions.
*/
-#ifdef CONFIG_ZCRYPT_MULTIDEVNODES
-
struct zcdn_device;
static struct class *zcrypt_class;
@@ -477,8 +475,6 @@ static void zcdn_destroy_all(void)
mutex_unlock(&ap_perms_mutex);
}
-#endif
-
/*
* zcrypt_read (): Not supported beyond zcrypt 1.3.1.
*
@@ -510,7 +506,6 @@ static int zcrypt_open(struct inode *inode, struct file *filp)
{
struct ap_perms *perms = &ap_perms;
-#ifdef CONFIG_ZCRYPT_MULTIDEVNODES
if (filp->f_inode->i_cdev == &zcrypt_cdev) {
struct zcdn_device *zcdndev;
@@ -522,7 +517,6 @@ static int zcrypt_open(struct inode *inode, struct file *filp)
if (zcdndev)
perms = &zcdndev->perms;
}
-#endif
filp->private_data = (void *)perms;
atomic_inc(&zcrypt_open_count);
@@ -536,7 +530,6 @@ static int zcrypt_open(struct inode *inode, struct file *filp)
*/
static int zcrypt_release(struct inode *inode, struct file *filp)
{
-#ifdef CONFIG_ZCRYPT_MULTIDEVNODES
if (filp->f_inode->i_cdev == &zcrypt_cdev) {
struct zcdn_device *zcdndev;
@@ -549,7 +542,6 @@ static int zcrypt_release(struct inode *inode, struct file *filp)
put_device(&zcdndev->device);
}
}
-#endif
atomic_dec(&zcrypt_open_count);
return 0;
@@ -661,11 +653,6 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms,
ap_init_message(&ap_msg);
-#ifdef CONFIG_ZCRYPT_DEBUG
- if (tr && tr->fi.cmd)
- ap_msg.fi.cmd = tr->fi.cmd;
-#endif
-
if (mex->outputdatalength < mex->inputdatalength) {
func_code = 0;
rc = -EINVAL;
@@ -687,7 +674,7 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms,
pref_zq = NULL;
spin_lock(&zcrypt_list_lock);
for_each_zcrypt_card(zc) {
- /* Check for usable accelarator or CCA card */
+ /* Check for usable accelerator or CCA card */
if (!zc->online || !zc->card->config || zc->card->chkstop ||
!(zc->card->functions & 0x18000000))
continue;
@@ -771,11 +758,6 @@ static long zcrypt_rsa_crt(struct ap_perms *perms,
ap_init_message(&ap_msg);
-#ifdef CONFIG_ZCRYPT_DEBUG
- if (tr && tr->fi.cmd)
- ap_msg.fi.cmd = tr->fi.cmd;
-#endif
-
if (crt->outputdatalength < crt->inputdatalength) {
func_code = 0;
rc = -EINVAL;
@@ -797,7 +779,7 @@ static long zcrypt_rsa_crt(struct ap_perms *perms,
pref_zq = NULL;
spin_lock(&zcrypt_list_lock);
for_each_zcrypt_card(zc) {
- /* Check for usable accelarator or CCA card */
+ /* Check for usable accelerator or CCA card */
if (!zc->online || !zc->card->config || zc->card->chkstop ||
!(zc->card->functions & 0x18000000))
continue;
@@ -883,16 +865,6 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
xcrb->status = 0;
ap_init_message(&ap_msg);
-#ifdef CONFIG_ZCRYPT_DEBUG
- if (tr && tr->fi.cmd)
- ap_msg.fi.cmd = tr->fi.cmd;
- if (tr && tr->fi.action == AP_FI_ACTION_CCA_AGENT_FF) {
- ZCRYPT_DBF_WARN("%s fi cmd 0x%04x: forcing invalid agent_ID 'FF'\n",
- __func__, tr->fi.cmd);
- xcrb->agent_ID = 0x4646;
- }
-#endif
-
rc = prep_cca_ap_msg(userspace, xcrb, &ap_msg, &func_code, &domain);
if (rc)
goto out;
@@ -982,14 +954,6 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
if (*domain == AUTOSEL_DOM)
*domain = AP_QID_QUEUE(qid);
-#ifdef CONFIG_ZCRYPT_DEBUG
- if (tr && tr->fi.action == AP_FI_ACTION_CCA_DOM_INVAL) {
- ZCRYPT_DBF_WARN("%s fi cmd 0x%04x: forcing invalid domain\n",
- __func__, tr->fi.cmd);
- *domain = 99;
- }
-#endif
-
rc = pref_zq->ops->send_cprb(userspace, pref_zq, xcrb, &ap_msg);
spin_lock(&zcrypt_list_lock);
@@ -1058,11 +1022,6 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
ap_init_message(&ap_msg);
-#ifdef CONFIG_ZCRYPT_DEBUG
- if (tr && tr->fi.cmd)
- ap_msg.fi.cmd = tr->fi.cmd;
-#endif
-
target_num = (unsigned short)xcrb->targets_num;
/* empty list indicates autoselect (all available targets) */
@@ -1473,23 +1432,10 @@ static int icarsamodexpo_ioctl(struct ap_perms *perms, unsigned long arg)
if (copy_from_user(&mex, umex, sizeof(mex)))
return -EFAULT;
-#ifdef CONFIG_ZCRYPT_DEBUG
- if (mex.inputdatalength & (1U << 31)) {
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- tr.fi.cmd = (u16)(mex.inputdatalength >> 16);
- }
- mex.inputdatalength &= 0x0000FFFF;
-#endif
-
do {
rc = zcrypt_rsa_modexpo(perms, &tr, &mex);
if (rc == -EAGAIN)
tr.again_counter++;
-#ifdef CONFIG_ZCRYPT_DEBUG
- if (rc == -EAGAIN && (tr.fi.flags & AP_FI_FLAG_NO_RETRY))
- break;
-#endif
} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
/* on failure: retry once again after a requested rescan */
if ((rc == -ENODEV) && (zcrypt_process_rescan()))
@@ -1518,23 +1464,10 @@ static int icarsacrt_ioctl(struct ap_perms *perms, unsigned long arg)
if (copy_from_user(&crt, ucrt, sizeof(crt)))
return -EFAULT;
-#ifdef CONFIG_ZCRYPT_DEBUG
- if (crt.inputdatalength & (1U << 31)) {
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- tr.fi.cmd = (u16)(crt.inputdatalength >> 16);
- }
- crt.inputdatalength &= 0x0000FFFF;
-#endif
-
do {
rc = zcrypt_rsa_crt(perms, &tr, &crt);
if (rc == -EAGAIN)
tr.again_counter++;
-#ifdef CONFIG_ZCRYPT_DEBUG
- if (rc == -EAGAIN && (tr.fi.flags & AP_FI_FLAG_NO_RETRY))
- break;
-#endif
} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
/* on failure: retry once again after a requested rescan */
if ((rc == -ENODEV) && (zcrypt_process_rescan()))
@@ -1563,23 +1496,10 @@ static int zsecsendcprb_ioctl(struct ap_perms *perms, unsigned long arg)
if (copy_from_user(&xcrb, uxcrb, sizeof(xcrb)))
return -EFAULT;
-#ifdef CONFIG_ZCRYPT_DEBUG
- if ((xcrb.status & 0x8000FFFF) == 0x80004649 /* 'FI' */) {
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- tr.fi.cmd = (u16)(xcrb.status >> 16);
- }
- xcrb.status = 0;
-#endif
-
do {
rc = _zcrypt_send_cprb(true, perms, &tr, &xcrb);
if (rc == -EAGAIN)
tr.again_counter++;
-#ifdef CONFIG_ZCRYPT_DEBUG
- if (rc == -EAGAIN && (tr.fi.flags & AP_FI_FLAG_NO_RETRY))
- break;
-#endif
} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
/* on failure: retry once again after a requested rescan */
if ((rc == -ENODEV) && (zcrypt_process_rescan()))
@@ -1609,23 +1529,10 @@ static int zsendep11cprb_ioctl(struct ap_perms *perms, unsigned long arg)
if (copy_from_user(&xcrb, uxcrb, sizeof(xcrb)))
return -EFAULT;
-#ifdef CONFIG_ZCRYPT_DEBUG
- if (xcrb.req_len & (1ULL << 63)) {
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- tr.fi.cmd = (u16)(xcrb.req_len >> 48);
- }
- xcrb.req_len &= 0x0000FFFFFFFFFFFFULL;
-#endif
-
do {
rc = _zcrypt_send_ep11_cprb(true, perms, &tr, &xcrb);
if (rc == -EAGAIN)
tr.again_counter++;
-#ifdef CONFIG_ZCRYPT_DEBUG
- if (rc == -EAGAIN && (tr.fi.flags & AP_FI_FLAG_NO_RETRY))
- break;
-#endif
} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
/* on failure: retry once again after a requested rescan */
if ((rc == -ENODEV) && (zcrypt_process_rescan()))
@@ -1668,14 +1575,16 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
size_t total_size = MAX_ZDEV_ENTRIES_EXT
* sizeof(struct zcrypt_device_status_ext);
- device_status = kzalloc(total_size, GFP_KERNEL);
+ device_status = kvmalloc_array(MAX_ZDEV_ENTRIES_EXT,
+ sizeof(struct zcrypt_device_status_ext),
+ GFP_KERNEL);
if (!device_status)
return -ENOMEM;
zcrypt_device_status_mask_ext(device_status);
if (copy_to_user((char __user *)arg, device_status,
total_size))
rc = -EFAULT;
- kfree(device_status);
+ kvfree(device_status);
return rc;
}
case ZCRYPT_STATUS_MASK: {
@@ -2144,8 +2053,6 @@ void zcrypt_debug_exit(void)
debug_unregister(zcrypt_dbf_info);
}
-#ifdef CONFIG_ZCRYPT_MULTIDEVNODES
-
static int __init zcdn_init(void)
{
int rc;
@@ -2203,8 +2110,6 @@ static void zcdn_exit(void)
class_destroy(zcrypt_class);
}
-#endif
-
/*
* zcrypt_api_init(): Module initialization.
*
@@ -2218,11 +2123,9 @@ int __init zcrypt_api_init(void)
if (rc)
goto out;
-#ifdef CONFIG_ZCRYPT_MULTIDEVNODES
rc = zcdn_init();
if (rc)
goto out;
-#endif
/* Register the request sprayer. */
rc = misc_register(&zcrypt_misc_device);
@@ -2235,9 +2138,7 @@ int __init zcrypt_api_init(void)
return 0;
out_misc_register_failed:
-#ifdef CONFIG_ZCRYPT_MULTIDEVNODES
zcdn_exit();
-#endif
zcrypt_debug_exit();
out:
return rc;
@@ -2250,9 +2151,7 @@ out:
*/
void __exit zcrypt_api_exit(void)
{
-#ifdef CONFIG_ZCRYPT_MULTIDEVNODES
zcdn_exit();
-#endif
misc_deregister(&zcrypt_misc_device);
zcrypt_msgtype6_exit();
zcrypt_msgtype50_exit();
diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h
index f299deb8b8c7..de659954c8f7 100644
--- a/drivers/s390/crypto/zcrypt_api.h
+++ b/drivers/s390/crypto/zcrypt_api.h
@@ -60,9 +60,6 @@ struct zcrypt_track {
int again_counter; /* retry attempts counter */
int last_qid; /* last qid used */
int last_rc; /* last return code */
-#ifdef CONFIG_ZCRYPT_DEBUG
- struct ap_fi fi; /* failure injection cmd */
-#endif
};
/* defines related to message tracking */
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c
index 8c8808cc68a4..263fe182648b 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.c
+++ b/drivers/s390/crypto/zcrypt_ccamisc.c
@@ -689,7 +689,7 @@ int cca_sec2protkey(u16 cardnr, u16 domain,
goto out;
}
- /* copy the tanslated protected key */
+ /* copy the translated protected key */
switch (prepparm->lv3.ckb.len) {
case 16 + 32:
/* AES 128 protected key */
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h
index 78bf5631848e..5ddf02f965f9 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.h
+++ b/drivers/s390/crypto/zcrypt_ccamisc.h
@@ -115,7 +115,7 @@ struct eccprivkeytoken {
u64 mkvp; /* master key verification pattern */
u8 opk[48]; /* encrypted object protection key data */
u16 adatalen; /* associated data length in bytes */
- u16 fseclen; /* formated section length in bytes */
+ u16 fseclen; /* formatted section length in bytes */
u8 more_data[]; /* more data follows */
} __packed;
@@ -232,7 +232,7 @@ int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify);
* the number of apqns stored into the list is returned in *nr_apqns. One apqn
* entry is simple a 32 bit value with 16 bit cardnr and 16 bit domain nr and
* may be casted to struct pkey_apqn. The return value is either 0 for success
- * or a negative errno value. If no apqn meeting the criterias is found,
+ * or a negative errno value. If no apqn meeting the criteria is found,
* -ENODEV is returned.
*/
int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
diff --git a/drivers/s390/crypto/zcrypt_ep11misc.c b/drivers/s390/crypto/zcrypt_ep11misc.c
index f67d19d08571..958f5ee47f1b 100644
--- a/drivers/s390/crypto/zcrypt_ep11misc.c
+++ b/drivers/s390/crypto/zcrypt_ep11misc.c
@@ -1368,7 +1368,7 @@ int ep11_kblob2protkey(u16 card, u16 dom, const u8 *keyblob, size_t keybloblen,
goto out;
}
- /* copy the tanslated protected key */
+ /* copy the translated protected key */
if (wki->pkeysize > *protkeylen) {
DEBUG_ERR("%s wk info pkeysize %llu > protkeysize %u\n",
__func__, wki->pkeysize, *protkeylen);
diff --git a/drivers/s390/crypto/zcrypt_ep11misc.h b/drivers/s390/crypto/zcrypt_ep11misc.h
index 07445041869f..a3eddf51242d 100644
--- a/drivers/s390/crypto/zcrypt_ep11misc.h
+++ b/drivers/s390/crypto/zcrypt_ep11misc.h
@@ -131,14 +131,14 @@ int ep11_clr2keyblob(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
* - if minapi > 0 only apqns with API_ord_nr >= minapi
* - if wkvp != NULL only apqns where the wkvp (EP11_WKVPLEN bytes) matches
* to the first EP11_WKVPLEN bytes of the wkvp of the current wrapping
- * key for this domain. When a wkvp is given there will aways be a re-fetch
+ * key for this domain. When a wkvp is given there will always be a re-fetch
* of the domain info for the potential apqn - so this triggers an request
* reply to each apqn eligible.
* The array of apqn entries is allocated with kmalloc and returned in *apqns;
* the number of apqns stored into the list is returned in *nr_apqns. One apqn
* entry is simple a 32 bit value with 16 bit cardnr and 16 bit domain nr and
* may be casted to struct pkey_apqn. The return value is either 0 for success
- * or a negative errno value. If no apqn meeting the criterias is found,
+ * or a negative errno value. If no apqn meeting the criteria is found,
* -ENODEV is returned.
*/
int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
diff --git a/drivers/s390/crypto/zcrypt_msgtype50.c b/drivers/s390/crypto/zcrypt_msgtype50.c
index 05ace18c12b0..51f8f7a463f7 100644
--- a/drivers/s390/crypto/zcrypt_msgtype50.c
+++ b/drivers/s390/crypto/zcrypt_msgtype50.c
@@ -246,11 +246,6 @@ static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_queue *zq,
copy_from_user(inp, mex->inputdata, mod_len))
return -EFAULT;
-#ifdef CONFIG_ZCRYPT_DEBUG
- if (ap_msg->fi.flags & AP_FI_FLAG_TOGGLE_SPECIAL)
- ap_msg->flags ^= AP_MSG_FLAG_SPECIAL;
-#endif
-
return 0;
}
@@ -338,11 +333,6 @@ static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_queue *zq,
copy_from_user(inp, crt->inputdata, mod_len))
return -EFAULT;
-#ifdef CONFIG_ZCRYPT_DEBUG
- if (ap_msg->fi.flags & AP_FI_FLAG_TOGGLE_SPECIAL)
- ap_msg->flags ^= AP_MSG_FLAG_SPECIAL;
-#endif
-
return 0;
}
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c
index 2f9bf23fbb44..e668ff5eb384 100644
--- a/drivers/s390/crypto/zcrypt_msgtype6.c
+++ b/drivers/s390/crypto/zcrypt_msgtype6.c
@@ -425,11 +425,6 @@ static int xcrb_msg_to_type6cprb_msgx(bool userspace, struct ap_message *ap_msg,
memcmp(function_code, "AU", 2) == 0)
ap_msg->flags |= AP_MSG_FLAG_SPECIAL;
-#ifdef CONFIG_ZCRYPT_DEBUG
- if (ap_msg->fi.flags & AP_FI_FLAG_TOGGLE_SPECIAL)
- ap_msg->flags ^= AP_MSG_FLAG_SPECIAL;
-#endif
-
/* check CPRB minor version, set info bits in ap_message flag field */
switch (*(unsigned short *)(&msg->cprbx.func_id[0])) {
case 0x5432: /* "T2" */
@@ -535,11 +530,6 @@ static int xcrb_msg_to_type6_ep11cprb_msgx(bool userspace, struct ap_message *ap
if (msg->cprbx.flags & 0x20)
ap_msg->flags |= AP_MSG_FLAG_SPECIAL;
-#ifdef CONFIG_ZCRYPT_DEBUG
- if (ap_msg->fi.flags & AP_FI_FLAG_TOGGLE_SPECIAL)
- ap_msg->flags ^= AP_MSG_FLAG_SPECIAL;
-#endif
-
/* set info bits in ap_message flag field */
if (msg->cprbx.flags & 0x80)
ap_msg->flags |= AP_MSG_FLAG_ADMIN;
@@ -1111,23 +1101,36 @@ static long zcrypt_msgtype6_send_cprb(bool userspace, struct zcrypt_queue *zq,
struct ica_xcRB *xcrb,
struct ap_message *ap_msg)
{
- int rc;
struct response_type *rtype = ap_msg->private;
struct {
struct type6_hdr hdr;
struct CPRBX cprbx;
/* ... more data blocks ... */
} __packed * msg = ap_msg->msg;
-
- /*
- * Set the queue's reply buffer length minus 128 byte padding
- * as reply limit for the card firmware.
- */
- msg->hdr.fromcardlen1 = min_t(unsigned int, msg->hdr.fromcardlen1,
- zq->reply.bufsize - 128);
- if (msg->hdr.fromcardlen2)
- msg->hdr.fromcardlen2 =
- zq->reply.bufsize - msg->hdr.fromcardlen1 - 128;
+ unsigned int max_payload_size;
+ int rc, delta;
+
+ /* calculate maximum payload for this card and msg type */
+ max_payload_size = zq->reply.bufsize - sizeof(struct type86_fmt2_msg);
+
+ /* limit each of the two from fields to the maximum payload size */
+ msg->hdr.fromcardlen1 = min(msg->hdr.fromcardlen1, max_payload_size);
+ msg->hdr.fromcardlen2 = min(msg->hdr.fromcardlen2, max_payload_size);
+
+ /* calculate delta if the sum of both exceeds max payload size */
+ delta = msg->hdr.fromcardlen1 + msg->hdr.fromcardlen2
+ - max_payload_size;
+ if (delta > 0) {
+ /*
+ * Sum exceeds maximum payload size, prune fromcardlen1
+ * (always trust fromcardlen2)
+ */
+ if (delta > msg->hdr.fromcardlen1) {
+ rc = -EINVAL;
+ goto out;
+ }
+ msg->hdr.fromcardlen1 -= delta;
+ }
init_completion(&rtype->work);
rc = ap_queue_message(zq->queue, ap_msg);
@@ -1143,6 +1146,9 @@ static long zcrypt_msgtype6_send_cprb(bool userspace, struct zcrypt_queue *zq,
ap_cancel_message(zq->queue, ap_msg);
}
+ if (rc == -EAGAIN && ap_msg->flags & AP_MSG_FLAG_ADMIN)
+ rc = -EIO; /* do not retry administrative requests */
+
out:
if (rc)
ZCRYPT_DBF_DBG("%s send cprb at dev=%02x.%04x rc=%d\n",
@@ -1263,6 +1269,9 @@ static long zcrypt_msgtype6_send_ep11_cprb(bool userspace, struct zcrypt_queue *
ap_cancel_message(zq->queue, ap_msg);
}
+ if (rc == -EAGAIN && ap_msg->flags & AP_MSG_FLAG_ADMIN)
+ rc = -EIO; /* do not retry administrative requests */
+
out:
if (rc)
ZCRYPT_DBF_DBG("%s send cprb at dev=%02x.%04x rc=%d\n",
diff --git a/drivers/s390/net/ctcm_dbug.c b/drivers/s390/net/ctcm_dbug.c
index f7ec51db3cd6..b6f0e2f114b4 100644
--- a/drivers/s390/net/ctcm_dbug.c
+++ b/drivers/s390/net/ctcm_dbug.c
@@ -70,7 +70,7 @@ void ctcm_dbf_longtext(enum ctcm_dbf_names dbf_nix, int level, char *fmt, ...)
if (!debug_level_enabled(ctcm_dbf[dbf_nix].id, level))
return;
va_start(args, fmt);
- vsnprintf(dbf_txt_buf, sizeof(dbf_txt_buf), fmt, args);
+ vscnprintf(dbf_txt_buf, sizeof(dbf_txt_buf), fmt, args);
va_end(args);
debug_text_event(ctcm_dbf[dbf_nix].id, level, dbf_txt_buf);
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 28db69d91f17..6faf27136024 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -1333,7 +1333,7 @@ static int add_channel(struct ccw_device *cdev, enum ctcm_channel_types type,
goto nomem_return;
ch->cdev = cdev;
- snprintf(ch->id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev->dev));
+ scnprintf(ch->id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev->dev));
ch->type = type;
/*
@@ -1498,8 +1498,8 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
type = get_channel_type(&cdev0->id);
- snprintf(read_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev0->dev));
- snprintf(write_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev1->dev));
+ scnprintf(read_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev0->dev));
+ scnprintf(write_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev1->dev));
ret = add_channel(cdev0, type, priv);
if (ret) {
diff --git a/drivers/s390/net/ctcm_main.h b/drivers/s390/net/ctcm_main.h
index 90bd7b3f80c3..25164e8bf13d 100644
--- a/drivers/s390/net/ctcm_main.h
+++ b/drivers/s390/net/ctcm_main.h
@@ -100,6 +100,7 @@ enum ctcm_channel_types {
#define CTCM_PROTO_MPC 4
#define CTCM_PROTO_MAX 4
+#define CTCM_STATSIZE_LIMIT 64
#define CTCM_BUFSIZE_LIMIT 65535
#define CTCM_BUFSIZE_DEFAULT 32768
#define MPC_BUFSIZE_DEFAULT CTCM_BUFSIZE_LIMIT
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
index b8a226c6e1a9..7a2f34a5e0e0 100644
--- a/drivers/s390/net/ctcm_mpc.c
+++ b/drivers/s390/net/ctcm_mpc.c
@@ -43,13 +43,13 @@
#include <linux/netdevice.h>
#include <net/dst.h>
-#include <linux/io.h> /* instead of <asm/io.h> ok ? */
-#include <asm/ccwdev.h>
-#include <asm/ccwgroup.h>
-#include <linux/bitops.h> /* instead of <asm/bitops.h> ok ? */
-#include <linux/uaccess.h> /* instead of <asm/uaccess.h> ok ? */
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/uaccess.h>
#include <linux/wait.h>
#include <linux/moduleparam.h>
+#include <asm/ccwdev.h>
+#include <asm/ccwgroup.h>
#include <asm/idals.h>
#include "ctcm_main.h"
@@ -144,9 +144,9 @@ void ctcmpc_dumpit(char *buf, int len)
for (ct = 0; ct < len; ct++, ptr++, rptr++) {
if (sw == 0) {
- sprintf(addr, "%16.16llx", (__u64)rptr);
+ scnprintf(addr, sizeof(addr), "%16.16llx", (__u64)rptr);
- sprintf(boff, "%4.4X", (__u32)ct);
+ scnprintf(boff, sizeof(boff), "%4.4X", (__u32)ct);
bhex[0] = '\0';
basc[0] = '\0';
}
@@ -155,7 +155,7 @@ void ctcmpc_dumpit(char *buf, int len)
if (sw == 8)
strcat(bhex, " ");
- sprintf(tbuf, "%2.2llX", (__u64)*ptr);
+ scnprintf(tbuf, sizeof(tbuf), "%2.2llX", (__u64)*ptr);
tbuf[2] = '\0';
strcat(bhex, tbuf);
@@ -171,8 +171,8 @@ void ctcmpc_dumpit(char *buf, int len)
continue;
if ((strcmp(duphex, bhex)) != 0) {
if (dup != 0) {
- sprintf(tdup,
- "Duplicate as above to %s", addr);
+ scnprintf(tdup, sizeof(tdup),
+ "Duplicate as above to %s", addr);
ctcm_pr_debug(" --- %s ---\n",
tdup);
}
@@ -197,14 +197,16 @@ void ctcmpc_dumpit(char *buf, int len)
strcat(basc, " ");
}
if (dup != 0) {
- sprintf(tdup, "Duplicate as above to %s", addr);
+ scnprintf(tdup, sizeof(tdup),
+ "Duplicate as above to %s", addr);
ctcm_pr_debug(" --- %s ---\n", tdup);
}
ctcm_pr_debug(" %s (+%s) : %s [%s]\n",
addr, boff, bhex, basc);
} else {
if (dup >= 1) {
- sprintf(tdup, "Duplicate as above to %s", addr);
+ scnprintf(tdup, sizeof(tdup),
+ "Duplicate as above to %s", addr);
ctcm_pr_debug(" --- %s ---\n", tdup);
}
if (dup != 0) {
@@ -291,7 +293,7 @@ static struct net_device *ctcmpc_get_dev(int port_num)
struct net_device *dev;
struct ctcm_priv *priv;
- sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
+ scnprintf(device, sizeof(device), "%s%i", MPC_DEVICE_NAME, port_num);
dev = __dev_get_by_name(&init_net, device);
diff --git a/drivers/s390/net/ctcm_sysfs.c b/drivers/s390/net/ctcm_sysfs.c
index e3813a7aa5e6..0c5d8a3eaa2e 100644
--- a/drivers/s390/net/ctcm_sysfs.c
+++ b/drivers/s390/net/ctcm_sysfs.c
@@ -28,7 +28,7 @@ static ssize_t ctcm_buffer_show(struct device *dev,
if (!priv)
return -ENODEV;
- return sprintf(buf, "%d\n", priv->buffer_size);
+ return sysfs_emit(buf, "%d\n", priv->buffer_size);
}
static ssize_t ctcm_buffer_write(struct device *dev,
@@ -86,24 +86,24 @@ static void ctcm_print_statistics(struct ctcm_priv *priv)
return;
p = sbuf;
- p += sprintf(p, " Device FSM state: %s\n",
- fsm_getstate_str(priv->fsm));
- p += sprintf(p, " RX channel FSM state: %s\n",
- fsm_getstate_str(priv->channel[CTCM_READ]->fsm));
- p += sprintf(p, " TX channel FSM state: %s\n",
- fsm_getstate_str(priv->channel[CTCM_WRITE]->fsm));
- p += sprintf(p, " Max. TX buffer used: %ld\n",
- priv->channel[WRITE]->prof.maxmulti);
- p += sprintf(p, " Max. chained SKBs: %ld\n",
- priv->channel[WRITE]->prof.maxcqueue);
- p += sprintf(p, " TX single write ops: %ld\n",
- priv->channel[WRITE]->prof.doios_single);
- p += sprintf(p, " TX multi write ops: %ld\n",
- priv->channel[WRITE]->prof.doios_multi);
- p += sprintf(p, " Netto bytes written: %ld\n",
- priv->channel[WRITE]->prof.txlen);
- p += sprintf(p, " Max. TX IO-time: %u\n",
- jiffies_to_usecs(priv->channel[WRITE]->prof.tx_time));
+ p += scnprintf(p, CTCM_STATSIZE_LIMIT, " Device FSM state: %s\n",
+ fsm_getstate_str(priv->fsm));
+ p += scnprintf(p, CTCM_STATSIZE_LIMIT, " RX channel FSM state: %s\n",
+ fsm_getstate_str(priv->channel[CTCM_READ]->fsm));
+ p += scnprintf(p, CTCM_STATSIZE_LIMIT, " TX channel FSM state: %s\n",
+ fsm_getstate_str(priv->channel[CTCM_WRITE]->fsm));
+ p += scnprintf(p, CTCM_STATSIZE_LIMIT, " Max. TX buffer used: %ld\n",
+ priv->channel[WRITE]->prof.maxmulti);
+ p += scnprintf(p, CTCM_STATSIZE_LIMIT, " Max. chained SKBs: %ld\n",
+ priv->channel[WRITE]->prof.maxcqueue);
+ p += scnprintf(p, CTCM_STATSIZE_LIMIT, " TX single write ops: %ld\n",
+ priv->channel[WRITE]->prof.doios_single);
+ p += scnprintf(p, CTCM_STATSIZE_LIMIT, " TX multi write ops: %ld\n",
+ priv->channel[WRITE]->prof.doios_multi);
+ p += scnprintf(p, CTCM_STATSIZE_LIMIT, " Netto bytes written: %ld\n",
+ priv->channel[WRITE]->prof.txlen);
+ p += scnprintf(p, CTCM_STATSIZE_LIMIT, " Max. TX IO-time: %u\n",
+ jiffies_to_usecs(priv->channel[WRITE]->prof.tx_time));
printk(KERN_INFO "Statistics for %s:\n%s",
priv->channel[CTCM_WRITE]->netdev->name, sbuf);
@@ -120,7 +120,7 @@ static ssize_t stats_show(struct device *dev,
if (!priv || gdev->state != CCWGROUP_ONLINE)
return -ENODEV;
ctcm_print_statistics(priv);
- return sprintf(buf, "0\n");
+ return sysfs_emit(buf, "0\n");
}
static ssize_t stats_write(struct device *dev, struct device_attribute *attr,
@@ -142,7 +142,7 @@ static ssize_t ctcm_proto_show(struct device *dev,
if (!priv)
return -ENODEV;
- return sprintf(buf, "%d\n", priv->protocol);
+ return sysfs_emit(buf, "%d\n", priv->protocol);
}
static ssize_t ctcm_proto_store(struct device *dev,
@@ -184,8 +184,8 @@ static ssize_t ctcm_type_show(struct device *dev,
if (!cgdev)
return -ENODEV;
- return sprintf(buf, "%s\n",
- ctcm_type[cgdev->cdev[0]->id.driver_info]);
+ return sysfs_emit(buf, "%s\n",
+ ctcm_type[cgdev->cdev[0]->id.driver_info]);
}
static DEVICE_ATTR(buffer, 0644, ctcm_buffer_show, ctcm_buffer_write);
diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c
index c2096e4bba31..6df7f377d2f9 100644
--- a/drivers/s390/net/ism_drv.c
+++ b/drivers/s390/net/ism_drv.c
@@ -36,7 +36,7 @@ static const struct smcd_ops ism_ops;
static struct ism_client *clients[MAX_CLIENTS]; /* use an array rather than */
/* a list for fast mapping */
static u8 max_client;
-static DEFINE_SPINLOCK(clients_lock);
+static DEFINE_MUTEX(clients_lock);
struct ism_dev_list {
struct list_head list;
struct mutex mutex; /* protects ism device list */
@@ -47,14 +47,22 @@ static struct ism_dev_list ism_dev_list = {
.mutex = __MUTEX_INITIALIZER(ism_dev_list.mutex),
};
+static void ism_setup_forwarding(struct ism_client *client, struct ism_dev *ism)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ism->lock, flags);
+ ism->subs[client->id] = client;
+ spin_unlock_irqrestore(&ism->lock, flags);
+}
+
int ism_register_client(struct ism_client *client)
{
struct ism_dev *ism;
- unsigned long flags;
int i, rc = -ENOSPC;
mutex_lock(&ism_dev_list.mutex);
- spin_lock_irqsave(&clients_lock, flags);
+ mutex_lock(&clients_lock);
for (i = 0; i < MAX_CLIENTS; ++i) {
if (!clients[i]) {
clients[i] = client;
@@ -65,12 +73,14 @@ int ism_register_client(struct ism_client *client)
break;
}
}
- spin_unlock_irqrestore(&clients_lock, flags);
+ mutex_unlock(&clients_lock);
+
if (i < MAX_CLIENTS) {
/* initialize with all devices that we got so far */
list_for_each_entry(ism, &ism_dev_list.list, list) {
ism->priv[i] = NULL;
client->add(ism);
+ ism_setup_forwarding(client, ism);
}
}
mutex_unlock(&ism_dev_list.mutex);
@@ -86,25 +96,32 @@ int ism_unregister_client(struct ism_client *client)
int rc = 0;
mutex_lock(&ism_dev_list.mutex);
- spin_lock_irqsave(&clients_lock, flags);
- clients[client->id] = NULL;
- if (client->id + 1 == max_client)
- max_client--;
- spin_unlock_irqrestore(&clients_lock, flags);
list_for_each_entry(ism, &ism_dev_list.list, list) {
+ spin_lock_irqsave(&ism->lock, flags);
+ /* Stop forwarding IRQs and events */
+ ism->subs[client->id] = NULL;
for (int i = 0; i < ISM_NR_DMBS; ++i) {
if (ism->sba_client_arr[i] == client->id) {
- pr_err("%s: attempt to unregister client '%s'"
- "with registered dmb(s)\n", __func__,
- client->name);
+ WARN(1, "%s: attempt to unregister '%s' with registered dmb(s)\n",
+ __func__, client->name);
rc = -EBUSY;
- goto out;
+ goto err_reg_dmb;
}
}
+ spin_unlock_irqrestore(&ism->lock, flags);
}
-out:
mutex_unlock(&ism_dev_list.mutex);
+ mutex_lock(&clients_lock);
+ clients[client->id] = NULL;
+ if (client->id + 1 == max_client)
+ max_client--;
+ mutex_unlock(&clients_lock);
+ return rc;
+
+err_reg_dmb:
+ spin_unlock_irqrestore(&ism->lock, flags);
+ mutex_unlock(&ism_dev_list.mutex);
return rc;
}
EXPORT_SYMBOL_GPL(ism_unregister_client);
@@ -328,6 +345,7 @@ int ism_register_dmb(struct ism_dev *ism, struct ism_dmb *dmb,
struct ism_client *client)
{
union ism_reg_dmb cmd;
+ unsigned long flags;
int ret;
ret = ism_alloc_dmb(ism, dmb);
@@ -351,7 +369,9 @@ int ism_register_dmb(struct ism_dev *ism, struct ism_dmb *dmb,
goto out;
}
dmb->dmb_tok = cmd.response.dmb_tok;
+ spin_lock_irqsave(&ism->lock, flags);
ism->sba_client_arr[dmb->sba_idx - ISM_DMB_BIT_OFFSET] = client->id;
+ spin_unlock_irqrestore(&ism->lock, flags);
out:
return ret;
}
@@ -360,6 +380,7 @@ EXPORT_SYMBOL_GPL(ism_register_dmb);
int ism_unregister_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
{
union ism_unreg_dmb cmd;
+ unsigned long flags;
int ret;
memset(&cmd, 0, sizeof(cmd));
@@ -368,7 +389,9 @@ int ism_unregister_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
cmd.request.dmb_tok = dmb->dmb_tok;
+ spin_lock_irqsave(&ism->lock, flags);
ism->sba_client_arr[dmb->sba_idx - ISM_DMB_BIT_OFFSET] = NO_CLIENT;
+ spin_unlock_irqrestore(&ism->lock, flags);
ret = ism_cmd(ism, &cmd);
if (ret && ret != ISM_ERROR)
@@ -491,6 +514,7 @@ static u16 ism_get_chid(struct ism_dev *ism)
static void ism_handle_event(struct ism_dev *ism)
{
struct ism_event *entry;
+ struct ism_client *clt;
int i;
while ((ism->ieq_idx + 1) != READ_ONCE(ism->ieq->header.idx)) {
@@ -499,21 +523,21 @@ static void ism_handle_event(struct ism_dev *ism)
entry = &ism->ieq->entry[ism->ieq_idx];
debug_event(ism_debug_info, 2, entry, sizeof(*entry));
- spin_lock(&clients_lock);
- for (i = 0; i < max_client; ++i)
- if (clients[i])
- clients[i]->handle_event(ism, entry);
- spin_unlock(&clients_lock);
+ for (i = 0; i < max_client; ++i) {
+ clt = ism->subs[i];
+ if (clt)
+ clt->handle_event(ism, entry);
+ }
}
}
static irqreturn_t ism_handle_irq(int irq, void *data)
{
struct ism_dev *ism = data;
- struct ism_client *clt;
unsigned long bit, end;
unsigned long *bv;
u16 dmbemask;
+ u8 client_id;
bv = (void *) &ism->sba->dmb_bits[ISM_DMB_WORD_OFFSET];
end = sizeof(ism->sba->dmb_bits) * BITS_PER_BYTE - ISM_DMB_BIT_OFFSET;
@@ -530,8 +554,10 @@ static irqreturn_t ism_handle_irq(int irq, void *data)
dmbemask = ism->sba->dmbe_mask[bit + ISM_DMB_BIT_OFFSET];
ism->sba->dmbe_mask[bit + ISM_DMB_BIT_OFFSET] = 0;
barrier();
- clt = clients[ism->sba_client_arr[bit]];
- clt->handle_irq(ism, bit + ISM_DMB_BIT_OFFSET, dmbemask);
+ client_id = ism->sba_client_arr[bit];
+ if (unlikely(client_id == NO_CLIENT || !ism->subs[client_id]))
+ continue;
+ ism->subs[client_id]->handle_irq(ism, bit + ISM_DMB_BIT_OFFSET, dmbemask);
}
if (ism->sba->e) {
@@ -548,20 +574,9 @@ static u64 ism_get_local_gid(struct ism_dev *ism)
return ism->local_gid;
}
-static void ism_dev_add_work_func(struct work_struct *work)
-{
- struct ism_client *client = container_of(work, struct ism_client,
- add_work);
-
- client->add(client->tgt_ism);
- atomic_dec(&client->tgt_ism->add_dev_cnt);
- wake_up(&client->tgt_ism->waitq);
-}
-
static int ism_dev_init(struct ism_dev *ism)
{
struct pci_dev *pdev = ism->pdev;
- unsigned long flags;
int i, ret;
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
@@ -594,25 +609,16 @@ static int ism_dev_init(struct ism_dev *ism)
/* hardware is V2 capable */
ism_create_system_eid();
- init_waitqueue_head(&ism->waitq);
- atomic_set(&ism->free_clients_cnt, 0);
- atomic_set(&ism->add_dev_cnt, 0);
-
- wait_event(ism->waitq, !atomic_read(&ism->add_dev_cnt));
- spin_lock_irqsave(&clients_lock, flags);
- for (i = 0; i < max_client; ++i)
+ mutex_lock(&ism_dev_list.mutex);
+ mutex_lock(&clients_lock);
+ for (i = 0; i < max_client; ++i) {
if (clients[i]) {
- INIT_WORK(&clients[i]->add_work,
- ism_dev_add_work_func);
- clients[i]->tgt_ism = ism;
- atomic_inc(&ism->add_dev_cnt);
- schedule_work(&clients[i]->add_work);
+ clients[i]->add(ism);
+ ism_setup_forwarding(clients[i], ism);
}
- spin_unlock_irqrestore(&clients_lock, flags);
-
- wait_event(ism->waitq, !atomic_read(&ism->add_dev_cnt));
+ }
+ mutex_unlock(&clients_lock);
- mutex_lock(&ism_dev_list.mutex);
list_add(&ism->list, &ism_dev_list.list);
mutex_unlock(&ism_dev_list.mutex);
@@ -660,7 +666,7 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
goto err_disable;
- ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (ret)
goto err_resource;
@@ -687,36 +693,24 @@ err_dev:
return ret;
}
-static void ism_dev_remove_work_func(struct work_struct *work)
-{
- struct ism_client *client = container_of(work, struct ism_client,
- remove_work);
-
- client->remove(client->tgt_ism);
- atomic_dec(&client->tgt_ism->free_clients_cnt);
- wake_up(&client->tgt_ism->waitq);
-}
-
-/* Callers must hold ism_dev_list.mutex */
static void ism_dev_exit(struct ism_dev *ism)
{
struct pci_dev *pdev = ism->pdev;
unsigned long flags;
int i;
- wait_event(ism->waitq, !atomic_read(&ism->free_clients_cnt));
- spin_lock_irqsave(&clients_lock, flags);
+ spin_lock_irqsave(&ism->lock, flags);
for (i = 0; i < max_client; ++i)
- if (clients[i]) {
- INIT_WORK(&clients[i]->remove_work,
- ism_dev_remove_work_func);
- clients[i]->tgt_ism = ism;
- atomic_inc(&ism->free_clients_cnt);
- schedule_work(&clients[i]->remove_work);
- }
- spin_unlock_irqrestore(&clients_lock, flags);
+ ism->subs[i] = NULL;
+ spin_unlock_irqrestore(&ism->lock, flags);
- wait_event(ism->waitq, !atomic_read(&ism->free_clients_cnt));
+ mutex_lock(&ism_dev_list.mutex);
+ mutex_lock(&clients_lock);
+ for (i = 0; i < max_client; ++i) {
+ if (clients[i])
+ clients[i]->remove(ism);
+ }
+ mutex_unlock(&clients_lock);
if (SYSTEM_EID.serial_number[0] != '0' ||
SYSTEM_EID.type[0] != '0')
@@ -727,15 +721,14 @@ static void ism_dev_exit(struct ism_dev *ism)
kfree(ism->sba_client_arr);
pci_free_irq_vectors(pdev);
list_del_init(&ism->list);
+ mutex_unlock(&ism_dev_list.mutex);
}
static void ism_remove(struct pci_dev *pdev)
{
struct ism_dev *ism = dev_get_drvdata(&pdev->dev);
- mutex_lock(&ism_dev_list.mutex);
ism_dev_exit(ism);
- mutex_unlock(&ism_dev_list.mutex);
pci_release_mem_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 38f312664ce7..9fd8e6f07a03 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -1899,14 +1899,14 @@ lcs_open_device(struct net_device *dev)
static ssize_t
lcs_portno_show (struct device *dev, struct device_attribute *attr, char *buf)
{
- struct lcs_card *card;
+ struct lcs_card *card;
card = dev_get_drvdata(dev);
- if (!card)
- return 0;
+ if (!card)
+ return 0;
- return sprintf(buf, "%d\n", card->portno);
+ return sysfs_emit(buf, "%d\n", card->portno);
}
/*
@@ -1956,7 +1956,8 @@ lcs_type_show(struct device *dev, struct device_attribute *attr, char *buf)
if (!cgdev)
return -ENODEV;
- return sprintf(buf, "%s\n", lcs_type[cgdev->cdev[0]->id.driver_info]);
+ return sysfs_emit(buf, "%s\n",
+ lcs_type[cgdev->cdev[0]->id.driver_info]);
}
static DEVICE_ATTR(type, 0444, lcs_type_show, NULL);
@@ -1968,7 +1969,7 @@ lcs_timeout_show(struct device *dev, struct device_attribute *attr, char *buf)
card = dev_get_drvdata(dev);
- return card ? sprintf(buf, "%u\n", card->lancmd_timeout) : 0;
+ return card ? sysfs_emit(buf, "%u\n", card->lancmd_timeout) : 0;
}
static ssize_t
diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h
index bd52caa3b11b..a2699b70b050 100644
--- a/drivers/s390/net/lcs.h
+++ b/drivers/s390/net/lcs.h
@@ -21,7 +21,7 @@ do { \
#define LCS_DBF_TEXT_(level,name,text...) \
do { \
if (debug_level_enabled(lcs_dbf_##name, level)) { \
- sprintf(debug_buffer, text); \
+ scnprintf(debug_buffer, sizeof(debug_buffer), text); \
debug_text_event(lcs_dbf_##name, level, debug_buffer); \
} \
} while (0)
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 66076cada8ae..8852b03f943b 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -47,7 +47,7 @@
#include <linux/ctype.h>
#include <net/dst.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <linux/uaccess.h>
#include <asm/ebcdic.h>
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 1d195429753d..613eab729704 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -716,7 +716,6 @@ struct qeth_card_info {
u16 chid;
u8 ids_valid:1; /* cssid,iid,chid */
u8 dev_addr_is_registered:1;
- u8 open_when_online:1;
u8 promisc_mode:1;
u8 use_v1_blkt:1;
u8 is_vm_nic:1;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 1d5b207c2b9e..cd783290bde5 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -5373,8 +5373,6 @@ int qeth_set_offline(struct qeth_card *card, const struct qeth_discipline *disc,
qeth_clear_ipacmd_list(card);
rtnl_lock();
- card->info.open_when_online = card->dev->flags & IFF_UP;
- dev_close(card->dev);
netif_device_detach(card->dev);
netif_carrier_off(card->dev);
rtnl_unlock();
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 9f13ed170a43..75910c0bcc2b 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -2388,9 +2388,12 @@ static int qeth_l2_set_online(struct qeth_card *card, bool carrier_ok)
qeth_enable_hw_features(dev);
qeth_l2_enable_brport_features(card);
- if (card->info.open_when_online) {
- card->info.open_when_online = 0;
- dev_open(dev, NULL);
+ if (netif_running(dev)) {
+ local_bh_disable();
+ napi_schedule(&card->napi);
+ /* kick-start the NAPI softirq: */
+ local_bh_enable();
+ qeth_l2_set_rx_mode(dev);
}
rtnl_unlock();
}
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index af4e60d2917e..b92a32b4b114 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2018,9 +2018,11 @@ static int qeth_l3_set_online(struct qeth_card *card, bool carrier_ok)
netif_device_attach(dev);
qeth_enable_hw_features(dev);
- if (card->info.open_when_online) {
- card->info.open_when_online = 0;
- dev_open(dev, NULL);
+ if (netif_running(dev)) {
+ local_bh_disable();
+ napi_schedule(&card->napi);
+ /* kick-start the NAPI softirq: */
+ local_bh_enable();
}
rtnl_unlock();
}
diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c
index 9f90a860ca2c..a6b64228ead2 100644
--- a/drivers/s390/net/qeth_l3_sys.c
+++ b/drivers/s390/net/qeth_l3_sys.c
@@ -625,7 +625,7 @@ static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- return qeth_l3_vipa_store(dev, buf, true, count, QETH_PROT_IPV4);
+ return qeth_l3_vipa_store(dev, buf, false, count, QETH_PROT_IPV4);
}
static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index f21307537829..4f0d0e55f0d4 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -534,8 +534,7 @@ static void zfcp_fc_adisc_handler(void *data)
/* re-init to undo drop from zfcp_fc_adisc() */
port->d_id = ntoh24(adisc_resp->adisc_port_id);
- /* port is good, unblock rport without going through erp */
- zfcp_scsi_schedule_rport_register(port);
+ /* port is still good, nothing to do */
out:
atomic_andnot(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
put_device(&port->dev);
@@ -595,9 +594,6 @@ void zfcp_fc_link_test_work(struct work_struct *work)
int retval;
set_worker_desc("zadisc%16llx", port->wwpn); /* < WORKER_DESC_LEN=24 */
- get_device(&port->dev);
- port->rport_task = RPORT_DEL;
- zfcp_scsi_rport_work(&port->rport_work);
/* only issue one test command at one time per port */
if (atomic_read(&port->status) & ZFCP_STATUS_PORT_LINK_TEST)
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-9xxx.c b/drivers/scsi/3w-9xxx.c
index 38d20a69ee12..f925f8664c2c 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -617,7 +617,7 @@ static int twa_check_srl(TW_Device_Extension *tw_dev, int *flashed)
}
/* Load rest of compatibility struct */
- strlcpy(tw_dev->tw_compat_info.driver_version, TW_DRIVER_VERSION,
+ strscpy(tw_dev->tw_compat_info.driver_version, TW_DRIVER_VERSION,
sizeof(tw_dev->tw_compat_info.driver_version));
tw_dev->tw_compat_info.driver_srl_high = TW_CURRENT_DRIVER_SRL;
tw_dev->tw_compat_info.driver_branch_high = TW_CURRENT_DRIVER_BRANCH;
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/53c700.c b/drivers/scsi/53c700.c
index e1e4f9d10887..857be0f3ae5b 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -1598,7 +1598,7 @@ NCR_700_intr(int irq, void *dev_id)
printk("scsi%d (%d:%d) PHASE MISMATCH IN SEND MESSAGE %d remain, return %p[%04x], phase %s\n", host->host_no, pun, lun, count, (void *)temp, temp - hostdata->pScript, sbcl_to_string(NCR_700_readb(host, SBCL_REG)));
#endif
resume_offset = hostdata->pScript + Ent_SendMessagePhaseMismatch;
- } else if(dsp >= to32bit(&slot->pSG[0].ins) &&
+ } else if (slot && dsp >= to32bit(&slot->pSG[0].ins) &&
dsp <= to32bit(&slot->pSG[NCR_700_SG_SEGMENTS].ins)) {
int data_transfer = NCR_700_readl(host, DBC_REG) & 0xffffff;
int SGcount = (dsp - to32bit(&slot->pSG[0].ins))/sizeof(struct NCR_700_SG_List);
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/NCR5380.c b/drivers/scsi/NCR5380.c
index ca85bddb582b..cea3a79d538e 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -417,7 +417,7 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags)
INIT_WORK(&hostdata->main_task, NCR5380_main);
hostdata->work_q = alloc_workqueue("ncr5380_%d",
WQ_UNBOUND | WQ_MEM_RECLAIM,
- 1, instance->host_no);
+ 0, instance->host_no);
if (!hostdata->work_q)
return -ENOMEM;
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 24c049eff157..70e1cac1975e 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -3289,7 +3289,7 @@ static int query_disk(struct aac_dev *dev, void __user *arg)
else
qd.unmapped = 0;
- strlcpy(qd.name, fsa_dev_ptr[qd.cnum].devname,
+ strscpy(qd.name, fsa_dev_ptr[qd.cnum].devname,
min(sizeof(qd.name), sizeof(fsa_dev_ptr[qd.cnum].devname) + 1));
if (copy_to_user(arg, &qd, sizeof (struct aac_query_disk)))
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 7c6efde75da6..73b6ac0c01f5 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -2618,7 +2618,7 @@ struct aac_hba_info {
struct aac_aifcmd {
__le32 command; /* Tell host what type of notify this is */
__le32 seqnum; /* To allow ordering of reports (if necessary) */
- u8 data[1]; /* Undefined length (from kernel viewpoint) */
+ u8 data[]; /* Undefined length (from kernel viewpoint) */
};
/**
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/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 2b3f0c10478e..872ad37e2a6e 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -383,7 +383,7 @@ int bnx2i_get_stats(void *handle)
if (!stats)
return -ENOMEM;
- strlcpy(stats->version, DRV_MODULE_VERSION, sizeof(stats->version));
+ strscpy(stats->version, DRV_MODULE_VERSION, sizeof(stats->version));
memcpy(stats->mac_add1 + 2, hba->cnic->mac_addr, ETH_ALEN);
stats->max_frame_size = hba->netdev->mtu;
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index ac648bb8f7e7..cb0a399be1cc 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -877,7 +877,8 @@ static long ch_ioctl(struct file *file,
}
default:
- return scsi_ioctl(ch->device, file->f_mode, cmd, argp);
+ return scsi_ioctl(ch->device, file->f_mode & FMODE_WRITE, cmd,
+ argp);
}
}
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.h b/drivers/scsi/fnic/fnic.h
index d82de34f6fd7..e51e92f932fa 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -27,7 +27,7 @@
#define DRV_NAME "fnic"
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
-#define DRV_VERSION "1.6.0.54"
+#define DRV_VERSION "1.6.0.55"
#define PFX DRV_NAME ": "
#define DFX DRV_NAME "%d: "
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/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 26dbd347156e..be89ce96df46 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -2139,7 +2139,7 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
bool new_sc)
{
- int ret = SUCCESS;
+ int ret = 0;
struct fnic_pending_aborts_iter_data iter_data = {
.fnic = fnic,
.lun_dev = lr_sc->device,
@@ -2159,9 +2159,11 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
/* walk again to check, if IOs are still pending in fw */
if (fnic_is_abts_pending(fnic, lr_sc))
- ret = FAILED;
+ ret = 1;
clean_pending_aborts_end:
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
+ "%s: exit status: %d\n", __func__, ret);
return ret;
}
diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c
index f3c3a26a1384..be0d7c57b242 100644
--- a/drivers/scsi/fnic/fnic_trace.c
+++ b/drivers/scsi/fnic/fnic_trace.c
@@ -465,7 +465,7 @@ int fnic_trace_buf_init(void)
fnic_max_trace_entries = (trace_max_pages * PAGE_SIZE)/
FNIC_ENTRY_SIZE_BYTES;
- fnic_trace_buf_p = (unsigned long)vzalloc(trace_max_pages * PAGE_SIZE);
+ fnic_trace_buf_p = (unsigned long)vcalloc(trace_max_pages, PAGE_SIZE);
if (!fnic_trace_buf_p) {
printk(KERN_ERR PFX "Failed to allocate memory "
"for fnic_trace_buf_p\n");
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/hptiop.c b/drivers/scsi/hptiop.c
index 06ccb51bf6a9..f5334ccbf2ca 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -1394,8 +1394,8 @@ static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id)
host->cmd_per_lun = le32_to_cpu(iop_config.max_requests);
host->max_cmd_len = 16;
- req_size = struct_size((struct hpt_iop_request_scsi_command *)0,
- sg_list, hba->max_sg_descriptors);
+ req_size = struct_size_t(struct hpt_iop_request_scsi_command,
+ sg_list, hba->max_sg_descriptors);
if ((req_size & 0x1f) != 0)
req_size = (req_size + 0x1f) & ~0x1f;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 63f32f843e75..59599299615d 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -250,7 +250,7 @@ static void gather_partition_info(void)
ppartition_name = of_get_property(of_root, "ibm,partition-name", NULL);
if (ppartition_name)
- strlcpy(partition_name, ppartition_name,
+ strscpy(partition_name, ppartition_name,
sizeof(partition_name));
p_number_ptr = of_get_property(of_root, "ibm,partition-no", NULL);
if (p_number_ptr)
@@ -1282,12 +1282,12 @@ static void send_mad_capabilities(struct ibmvscsi_host_data *hostdata)
if (hostdata->client_migrated)
hostdata->caps.flags |= cpu_to_be32(CLIENT_MIGRATED);
- strlcpy(hostdata->caps.name, dev_name(&hostdata->host->shost_gendev),
+ strscpy(hostdata->caps.name, dev_name(&hostdata->host->shost_gendev),
sizeof(hostdata->caps.name));
location = of_get_property(of_node, "ibm,loc-code", NULL);
location = location ? location : dev_name(hostdata->dev);
- strlcpy(hostdata->caps.loc, location, sizeof(hostdata->caps.loc));
+ strscpy(hostdata->caps.loc, location, sizeof(hostdata->caps.loc));
req->common.type = cpu_to_be32(VIOSRP_CAPABILITIES_TYPE);
req->buffer = cpu_to_be64(hostdata->caps_addr);
diff --git a/drivers/scsi/isci/scu_task_context.h b/drivers/scsi/isci/scu_task_context.h
index 869a979eb5b2..582d22d54689 100644
--- a/drivers/scsi/isci/scu_task_context.h
+++ b/drivers/scsi/isci/scu_task_context.h
@@ -845,7 +845,7 @@ struct scu_task_context {
/**
* This field is used by the SCU TL to determine when to take a snapshot when
- * tranmitting read data frames.
+ * transmitting read data frames.
* - 0x00 The entire IO
* - 0x01 32k
* - 0x02 64k
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 9637d4bc2bc9..9ab8555180a3 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -301,35 +301,32 @@ static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn,
while (!iscsi_tcp_segment_done(tcp_conn, segment, 0, r)) {
struct scatterlist *sg;
+ struct msghdr msg = {};
+ struct bio_vec bv;
unsigned int offset, copy;
- int flags = 0;
r = 0;
offset = segment->copied;
copy = segment->size - offset;
if (segment->total_copied + segment->size < segment->total_size)
- flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST;
+ msg.msg_flags |= MSG_MORE;
if (tcp_sw_conn->queue_recv)
- flags |= MSG_DONTWAIT;
+ msg.msg_flags |= MSG_DONTWAIT;
- /* Use sendpage if we can; else fall back to sendmsg */
if (!segment->data) {
+ if (!tcp_conn->iscsi_conn->datadgst_en)
+ msg.msg_flags |= MSG_SPLICE_PAGES;
sg = segment->sg;
offset += segment->sg_offset + sg->offset;
- r = tcp_sw_conn->sendpage(sk, sg_page(sg), offset,
- copy, flags);
+ bvec_set_page(&bv, sg_page(sg), copy, offset);
} else {
- struct msghdr msg = { .msg_flags = flags };
- struct kvec iov = {
- .iov_base = segment->data + offset,
- .iov_len = copy
- };
-
- r = kernel_sendmsg(sk, &msg, &iov, 1, copy);
+ bvec_set_virt(&bv, segment->data + offset, copy);
}
+ iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bv, 1, copy);
+ r = sock_sendmsg(sk, &msg);
if (r < 0) {
iscsi_tcp_segment_unmap(segment);
return r;
@@ -746,7 +743,6 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session,
sock_no_linger(sk);
iscsi_sw_tcp_conn_set_callbacks(conn);
- tcp_sw_conn->sendpage = tcp_sw_conn->sock->ops->sendpage;
/*
* set receive state machine into initial state
*/
@@ -777,8 +773,6 @@ static int iscsi_sw_tcp_conn_set_param(struct iscsi_cls_conn *cls_conn,
return -ENOTCONN;
}
iscsi_set_param(cls_conn, param, buf, buflen);
- tcp_sw_conn->sendpage = conn->datadgst_en ?
- sock_no_sendpage : tcp_sw_conn->sock->ops->sendpage;
mutex_unlock(&tcp_sw_conn->sock_lock);
break;
case ISCSI_PARAM_MAX_R2T:
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index 68e14a344904..89a6fc552f0b 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -47,8 +47,6 @@ struct iscsi_sw_tcp_conn {
/* MIB custom statistics */
uint32_t sendpage_failures_cnt;
uint32_t discontiguous_hdr_cnt;
-
- ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
};
struct iscsi_sw_tcp_host {
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..fdd7f69d87ef 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.
@@ -6961,7 +6944,9 @@ lpfc_unregister_fcf_rescan(struct lpfc_hba *phba)
if (rc)
return;
/* Reset HBA FCF states after successful unregister FCF */
+ spin_lock_irq(&phba->hbalock);
phba->fcf.fcf_flag = 0;
+ spin_unlock_irq(&phba->hbalock);
phba->fcf.current_rec.flag = 0;
/*
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 19b2d2754f32..aaea3e31944d 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
@@ -365,7 +365,7 @@ struct lpfc_name {
uint8_t IEEE[6]; /* FC IEEE address */
} s;
uint8_t wwn[8];
- uint64_t name;
+ uint64_t name __packed __aligned(4);
} u;
};
@@ -850,7 +850,7 @@ typedef struct _ADISC { /* Structure is in Big Endian format */
struct lpfc_name portName;
struct lpfc_name nodeName;
uint32_t DID;
-} __packed ADISC;
+} ADISC;
typedef struct _FARP { /* Structure is in Big Endian format */
uint32_t Mflags:8;
@@ -880,7 +880,7 @@ typedef struct _FAN { /* Structure is in Big Endian format */
uint32_t Fdid;
struct lpfc_name FportName;
struct lpfc_name FnodeName;
-} __packed FAN;
+} FAN;
typedef struct _SCR { /* Structure is in Big Endian format */
uint8_t resvd1;
@@ -924,7 +924,7 @@ typedef struct _RNID { /* Structure is in Big Endian format */
union {
RNID_TOP_DISC topologyDisc; /* topology disc (0xdf) */
} un;
-} __packed RNID;
+} RNID;
struct RLS { /* Structure is in Big Endian format */
uint32_t rls;
@@ -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,9 +1512,9 @@ 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;
+};
/*
* Register HBA(RHBA)
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..d26941b131fd 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -109,8 +109,6 @@ lpfc_sli4_set_rsp_sgl_last(struct lpfc_hba *phba,
}
}
-#define LPFC_INVALID_REFTAG ((u32)-1)
-
/**
* lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread
* @phba: The Hba for which this call is being executed.
@@ -978,8 +976,6 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc,
sgpe = scsi_prot_sglist(sc);
lba = scsi_prot_ref_tag(sc);
- if (lba == LPFC_INVALID_REFTAG)
- return 0;
/* First check if we need to match the LBA */
if (phba->lpfc_injerr_lba != LPFC_INJERR_LBA_OFF) {
@@ -1560,8 +1556,6 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
/* extract some info from the scsi command for pde*/
reftag = scsi_prot_ref_tag(sc);
- if (reftag == LPFC_INVALID_REFTAG)
- goto out;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1);
@@ -1723,8 +1717,6 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
/* extract some info from the scsi command */
blksize = scsi_prot_interval(sc);
reftag = scsi_prot_ref_tag(sc);
- if (reftag == LPFC_INVALID_REFTAG)
- goto out;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1);
@@ -1953,8 +1945,6 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
/* extract some info from the scsi command for pde*/
reftag = scsi_prot_ref_tag(sc);
- if (reftag == LPFC_INVALID_REFTAG)
- goto out;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1);
@@ -2154,8 +2144,6 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
/* extract some info from the scsi command */
blksize = scsi_prot_interval(sc);
reftag = scsi_prot_ref_tag(sc);
- if (reftag == LPFC_INVALID_REFTAG)
- goto out;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1);
@@ -2746,8 +2734,6 @@ lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
src = (struct scsi_dif_tuple *)sg_virt(sgpe);
start_ref_tag = scsi_prot_ref_tag(cmd);
- if (start_ref_tag == LPFC_INVALID_REFTAG)
- goto out;
start_app_tag = src->app_tag;
len = sgpe->length;
while (src && protsegcnt) {
@@ -3493,11 +3479,11 @@ err:
scsi_cmnd->sc_data_direction);
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
- "9084 Cannot setup S/G List for HBA"
- "IO segs %d/%d SGL %d SCSI %d: %d %d\n",
+ "9084 Cannot setup S/G List for HBA "
+ "IO segs %d/%d SGL %d SCSI %d: %d %d %d\n",
lpfc_cmd->seg_cnt, lpfc_cmd->prot_seg_cnt,
phba->cfg_total_seg_cnt, phba->cfg_sg_seg_cnt,
- prot_group_type, num_sge);
+ prot_group_type, num_sge, ret);
lpfc_cmd->seg_cnt = 0;
lpfc_cmd->prot_seg_cnt = 0;
@@ -4026,7 +4012,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 +4047,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 +4089,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 +4113,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 +4165,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 +4196,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 +4217,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 +4235,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 +4253,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 +4990,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/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 317c944c68e3..050eed8e2684 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -5153,8 +5153,8 @@ static void megasas_update_ext_vd_details(struct megasas_instance *instance)
fusion->max_map_sz = ventura_map_sz;
} else {
fusion->old_map_sz =
- struct_size((struct MR_FW_RAID_MAP *)0, ldSpanMap,
- instance->fw_supported_vd_count);
+ struct_size_t(struct MR_FW_RAID_MAP, ldSpanMap,
+ instance->fw_supported_vd_count);
fusion->new_map_sz = sizeof(struct MR_FW_RAID_MAP_EXT);
fusion->max_map_sz =
@@ -5789,8 +5789,8 @@ megasas_setup_jbod_map(struct megasas_instance *instance)
struct fusion_context *fusion = instance->ctrl_context;
size_t pd_seq_map_sz;
- pd_seq_map_sz = struct_size((struct MR_PD_CFG_SEQ_NUM_SYNC *)0, seq,
- MAX_PHYSICAL_DEVICES);
+ pd_seq_map_sz = struct_size_t(struct MR_PD_CFG_SEQ_NUM_SYNC, seq,
+ MAX_PHYSICAL_DEVICES);
instance->use_seqnum_jbod_fp =
instance->support_seqnum_jbod_fp;
@@ -8033,8 +8033,8 @@ skip_firing_dcmds:
if (instance->adapter_type != MFI_SERIES) {
megasas_release_fusion(instance);
pd_seq_map_sz =
- struct_size((struct MR_PD_CFG_SEQ_NUM_SYNC *)0,
- seq, MAX_PHYSICAL_DEVICES);
+ struct_size_t(struct MR_PD_CFG_SEQ_NUM_SYNC,
+ seq, MAX_PHYSICAL_DEVICES);
for (i = 0; i < 2 ; i++) {
if (fusion->ld_map[i])
dma_free_coherent(&instance->pdev->dev,
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index 4463a538102a..b8b388a4e28f 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -326,9 +326,9 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance, u64 map_id)
else if (instance->supportmax256vd)
expected_size = sizeof(struct MR_FW_RAID_MAP_EXT);
else
- expected_size = struct_size((struct MR_FW_RAID_MAP *)0,
- ldSpanMap,
- le16_to_cpu(pDrvRaidMap->ldCount));
+ expected_size = struct_size_t(struct MR_FW_RAID_MAP,
+ ldSpanMap,
+ le16_to_cpu(pDrvRaidMap->ldCount));
if (le32_to_cpu(pDrvRaidMap->totalSize) != expected_size) {
dev_dbg(&instance->pdev->dev, "megasas: map info structure size 0x%x",
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/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index 4458449c960b..35869b4f9329 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -4555,7 +4555,7 @@ static void ncr_detach(struct ncb *np)
char inst_name[16];
/* Local copy so we don't access np after freeing it! */
- strlcpy(inst_name, ncr_name(np), sizeof(inst_name));
+ strscpy(inst_name, ncr_name(np), sizeof(inst_name));
printk("%s: releasing host resources\n", ncr_name(np));
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..4995e1ef4e0e 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;
}
- wait_for_completion(&completion);
+ 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;
+ }
+
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,9 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
pm80xx_set_thermal_config(pm8001_ha);
}
- pm8001_init_sas_add(pm8001_ha);
+ rc = pm8001_init_sas_add(pm8001_ha);
+ if (rc)
+ 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..7825765c936c 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -31,6 +31,7 @@ static void qedf_remove(struct pci_dev *pdev);
static void qedf_shutdown(struct pci_dev *pdev);
static void qedf_schedule_recovery_handler(void *dev);
static void qedf_recovery_handler(struct work_struct *work);
+static int qedf_suspend(struct pci_dev *pdev, pm_message_t state);
/*
* Driver module parameters.
@@ -3041,9 +3042,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 *)
@@ -3272,6 +3272,7 @@ static struct pci_driver qedf_pci_driver = {
.probe = qedf_probe,
.remove = qedf_remove,
.shutdown = qedf_shutdown,
+ .suspend = qedf_suspend,
};
static int __qedf_probe(struct pci_dev *pdev, int mode)
@@ -4001,6 +4002,22 @@ static void qedf_shutdown(struct pci_dev *pdev)
__qedf_remove(pdev, QEDF_MODE_NORMAL);
}
+static int qedf_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct qedf_ctx *qedf;
+
+ if (!pdev) {
+ QEDF_ERR(NULL, "pdev is NULL.\n");
+ return -ENODEV;
+ }
+
+ qedf = pci_get_drvdata(pdev);
+
+ QEDF_ERR(&qedf->dbg_ctx, "%s: Device does not support suspend operation\n", __func__);
+
+ return -EPERM;
+}
+
/*
* Recovery handler code
*/
diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c
index 45d359554182..cd0180b1f5b9 100644
--- a/drivers/scsi/qedi/qedi_main.c
+++ b/drivers/scsi/qedi/qedi_main.c
@@ -69,6 +69,7 @@ static struct nvm_iscsi_block *qedi_get_nvram_block(struct qedi_ctx *qedi);
static void qedi_recovery_handler(struct work_struct *work);
static void qedi_schedule_hw_err_handler(void *dev,
enum qed_hw_err_type err_type);
+static int qedi_suspend(struct pci_dev *pdev, pm_message_t state);
static int qedi_iscsi_event_cb(void *context, u8 fw_event_code, void *fw_handle)
{
@@ -1976,8 +1977,9 @@ static int qedi_cpu_offline(unsigned int cpu)
struct qedi_percpu_s *p = this_cpu_ptr(&qedi_percpu);
struct qedi_work *work, *tmp;
struct task_struct *thread;
+ unsigned long flags;
- spin_lock_bh(&p->p_work_lock);
+ spin_lock_irqsave(&p->p_work_lock, flags);
thread = p->iothread;
p->iothread = NULL;
@@ -1988,7 +1990,7 @@ static int qedi_cpu_offline(unsigned int cpu)
kfree(work);
}
- spin_unlock_bh(&p->p_work_lock);
+ spin_unlock_irqrestore(&p->p_work_lock, flags);
if (thread)
kthread_stop(thread);
return 0;
@@ -2510,6 +2512,22 @@ static void qedi_shutdown(struct pci_dev *pdev)
__qedi_remove(pdev, QEDI_MODE_SHUTDOWN);
}
+static int qedi_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct qedi_ctx *qedi;
+
+ if (!pdev) {
+ QEDI_ERR(NULL, "pdev is NULL.\n");
+ return -ENODEV;
+ }
+
+ qedi = pci_get_drvdata(pdev);
+
+ QEDI_ERR(&qedi->dbg_ctx, "%s: Device does not support suspend operation\n", __func__);
+
+ return -EPERM;
+}
+
static int __qedi_probe(struct pci_dev *pdev, int mode)
{
struct qedi_ctx *qedi;
@@ -2593,7 +2611,7 @@ retry_probe:
sp_params.drv_minor = QEDI_DRIVER_MINOR_VER;
sp_params.drv_rev = QEDI_DRIVER_REV_VER;
sp_params.drv_eng = QEDI_DRIVER_ENG_VER;
- strlcpy(sp_params.name, "qedi iSCSI", QED_DRV_VER_STR_SIZE);
+ strscpy(sp_params.name, "qedi iSCSI", QED_DRV_VER_STR_SIZE);
rc = qedi_ops->common->slowpath_start(qedi->cdev, &sp_params);
if (rc) {
QEDI_ERR(&qedi->dbg_ctx, "Cannot start slowpath\n");
@@ -2868,6 +2886,7 @@ static struct pci_driver qedi_pci_driver = {
.remove = qedi_remove,
.shutdown = qedi_shutdown,
.err_handler = &qedi_err_handler,
+ .suspend = qedi_suspend,
};
static int __init qedi_init(void)
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..4ae38305c15a 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 */
@@ -4446,7 +4462,6 @@ struct qla_hw_data {
/* n2n */
struct fc_els_flogi plogi_els_payld;
-#define LOGIN_TEMPLATE_SIZE (sizeof(struct fc_els_flogi) - 4)
void *swl;
@@ -5499,4 +5514,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..367fba27fe69 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;
@@ -8219,7 +8434,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
ql_dbg(ql_dbg_init, vha, 0x0163,
"-> fwdt%u template allocate template %#x words...\n",
j, risc_size);
- fwdt->template = vmalloc(risc_size * sizeof(*dcode));
+ fwdt->template = vmalloc_array(risc_size, sizeof(*dcode));
if (!fwdt->template) {
ql_log(ql_log_warn, vha, 0x0164,
"-> fwdt%u failed allocate template.\n", j);
@@ -8474,7 +8689,7 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
ql_dbg(ql_dbg_init, vha, 0x0173,
"-> fwdt%u template allocate template %#x words...\n",
j, risc_size);
- fwdt->template = vmalloc(risc_size * sizeof(*dcode));
+ fwdt->template = vmalloc_array(risc_size, sizeof(*dcode));
if (!fwdt->template) {
ql_log(ql_log_warn, vha, 0x0174,
"-> fwdt%u failed allocate template.\n", j);
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..730d8609276c 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));
@@ -3067,7 +3073,8 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
memset(ptr, 0, sizeof(struct els_plogi_payload));
memset(resp_ptr, 0, sizeof(struct els_plogi_payload));
memcpy(elsio->u.els_plogi.els_plogi_pyld->data,
- &ha->plogi_els_payld.fl_csp, LOGIN_TEMPLATE_SIZE);
+ (void *)&ha->plogi_els_payld + offsetof(struct fc_els_flogi, fl_csp),
+ sizeof(ha->plogi_els_payld) - offsetof(struct fc_els_flogi, fl_csp));
elsio->u.els_plogi.els_cmd = els_opcode;
elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode;
@@ -3852,9 +3859,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 +3877,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)
{
@@ -3892,7 +3912,7 @@ qla2x00_start_sp(srb_t *sp)
pkt = __qla2x00_alloc_iocbs(sp->qpair, sp);
if (!pkt) {
- rval = EAGAIN;
+ rval = -EAGAIN;
ql_log(ql_log_warn, vha, 0x700c,
"qla2x00_alloc_iocbs failed.\n");
goto done;
@@ -3973,6 +3993,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/raid_class.c b/drivers/scsi/raid_class.c
index 898a0bdf8df6..95a86e0dfd77 100644
--- a/drivers/scsi/raid_class.c
+++ b/drivers/scsi/raid_class.c
@@ -209,53 +209,6 @@ raid_attr_ro_state(level);
raid_attr_ro_fn(resync);
raid_attr_ro_state_fn(state);
-static void raid_component_release(struct device *dev)
-{
- struct raid_component *rc =
- container_of(dev, struct raid_component, dev);
- dev_printk(KERN_ERR, rc->dev.parent, "COMPONENT RELEASE\n");
- put_device(rc->dev.parent);
- kfree(rc);
-}
-
-int raid_component_add(struct raid_template *r,struct device *raid_dev,
- struct device *component_dev)
-{
- struct device *cdev =
- attribute_container_find_class_device(&r->raid_attrs.ac,
- raid_dev);
- struct raid_component *rc;
- struct raid_data *rd = dev_get_drvdata(cdev);
- int err;
-
- rc = kzalloc(sizeof(*rc), GFP_KERNEL);
- if (!rc)
- return -ENOMEM;
-
- INIT_LIST_HEAD(&rc->node);
- device_initialize(&rc->dev);
- rc->dev.release = raid_component_release;
- rc->dev.parent = get_device(component_dev);
- rc->num = rd->component_count++;
-
- dev_set_name(&rc->dev, "component-%d", rc->num);
- list_add_tail(&rc->node, &rd->component_list);
- rc->dev.class = &raid_class.class;
- err = device_add(&rc->dev);
- if (err)
- goto err_out;
-
- return 0;
-
-err_out:
- list_del(&rc->node);
- rd->component_count--;
- put_device(component_dev);
- kfree(rc);
- return err;
-}
-EXPORT_SYMBOL(raid_component_add);
-
struct raid_template *
raid_class_attach(struct raid_function_template *ft)
{
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 09ef0b31dfc0..d0911bc28663 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,140 @@ 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 parameter data format for
+ * REPORT SUPPORTED OPERATION CODES. We have the following cases
+ * depending on rwcdlp (buf[0] & 0x01) value:
+ * - rwcdlp == 0: then cdlp indicates support for the A mode page when
+ * it is equal to 1 and for the B mode page when it is
+ * equal to 2.
+ * - rwcdlp == 1: then cdlp indicates support for the T2A mode page
+ * when it is equal to 1 and for the T2B mode page when
+ * it is equal to 2.
+ * Overall, to detect support for command duration limits, we only need
+ * to check that cdlp is 1 or 2.
+ */
+ cdlp = (buf[1] & 0x18) >> 3;
+
+ return cdlp == 0x01 || cdlp == 0x02;
+}
+
+/**
+ * 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_bsg.c b/drivers/scsi/scsi_bsg.c
index 96ee35256a16..a9a9ec086a7e 100644
--- a/drivers/scsi/scsi_bsg.c
+++ b/drivers/scsi/scsi_bsg.c
@@ -10,7 +10,7 @@
#define uptr64(val) ((void __user *)(uintptr_t)(val))
static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,
- fmode_t mode, unsigned int timeout)
+ bool open_for_write, unsigned int timeout)
{
struct scsi_cmnd *scmd;
struct request *rq;
@@ -42,7 +42,7 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,
if (copy_from_user(scmd->cmnd, uptr64(hdr->request), scmd->cmd_len))
goto out_put_request;
ret = -EPERM;
- if (!scsi_cmd_allowed(scmd->cmnd, mode))
+ if (!scsi_cmd_allowed(scmd->cmnd, open_for_write))
goto out_put_request;
ret = 0;
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_debug.c b/drivers/scsi/scsi_debug.c
index 8c58128ad32a..9c0af50501f9 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -841,11 +841,6 @@ static int sdeb_zbc_nr_conv = DEF_ZBC_NR_CONV_ZONES;
static int submit_queues = DEF_SUBMIT_QUEUES; /* > 1 for multi-queue (mq) */
static int poll_queues; /* iouring iopoll interface.*/
-static DEFINE_RWLOCK(atomic_rw);
-static DEFINE_RWLOCK(atomic_rw2);
-
-static rwlock_t *ramdisk_lck_a[2];
-
static char sdebug_proc_name[] = MY_NAME;
static const char *my_name = MY_NAME;
@@ -6818,9 +6813,6 @@ static int __init scsi_debug_init(void)
int k, ret, hosts_to_add;
int idx = -1;
- ramdisk_lck_a[0] = &atomic_rw;
- ramdisk_lck_a[1] = &atomic_rw2;
-
if (sdebug_ndelay >= 1000 * 1000 * 1000) {
pr_warn("ndelay must be less than 1 second, ignored\n");
sdebug_ndelay = 0;
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_ioctl.c b/drivers/scsi/scsi_ioctl.c
index e3b31d32b6a9..6f6c5973c3ea 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -248,7 +248,7 @@ static int scsi_send_start_stop(struct scsi_device *sdev, int data)
* Only a subset of commands are allowed for unprivileged users. Commands used
* to format the media, update the firmware, etc. are not permitted.
*/
-bool scsi_cmd_allowed(unsigned char *cmd, fmode_t mode)
+bool scsi_cmd_allowed(unsigned char *cmd, bool open_for_write)
{
/* root can do any command. */
if (capable(CAP_SYS_RAWIO))
@@ -338,7 +338,7 @@ bool scsi_cmd_allowed(unsigned char *cmd, fmode_t mode)
case GPCMD_SET_READ_AHEAD:
/* ZBC */
case ZBC_OUT:
- return (mode & FMODE_WRITE);
+ return open_for_write;
default:
return false;
}
@@ -346,7 +346,7 @@ bool scsi_cmd_allowed(unsigned char *cmd, fmode_t mode)
EXPORT_SYMBOL(scsi_cmd_allowed);
static int scsi_fill_sghdr_rq(struct scsi_device *sdev, struct request *rq,
- struct sg_io_hdr *hdr, fmode_t mode)
+ struct sg_io_hdr *hdr, bool open_for_write)
{
struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq);
@@ -354,7 +354,7 @@ static int scsi_fill_sghdr_rq(struct scsi_device *sdev, struct request *rq,
return -EMSGSIZE;
if (copy_from_user(scmd->cmnd, hdr->cmdp, hdr->cmd_len))
return -EFAULT;
- if (!scsi_cmd_allowed(scmd->cmnd, mode))
+ if (!scsi_cmd_allowed(scmd->cmnd, open_for_write))
return -EPERM;
scmd->cmd_len = hdr->cmd_len;
@@ -407,7 +407,8 @@ static int scsi_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
return ret;
}
-static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode)
+static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr,
+ bool open_for_write)
{
unsigned long start_time;
ssize_t ret = 0;
@@ -448,7 +449,7 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode)
goto out_put_request;
}
- ret = scsi_fill_sghdr_rq(sdev, rq, hdr, mode);
+ ret = scsi_fill_sghdr_rq(sdev, rq, hdr, open_for_write);
if (ret < 0)
goto out_put_request;
@@ -477,8 +478,7 @@ out_put_request:
/**
* sg_scsi_ioctl -- handle deprecated SCSI_IOCTL_SEND_COMMAND ioctl
* @q: request queue to send scsi commands down
- * @mode: mode used to open the file through which the ioctl has been
- * submitted
+ * @open_for_write: is the file / block device opened for writing?
* @sic: userspace structure describing the command to perform
*
* Send down the scsi command described by @sic to the device below
@@ -501,7 +501,7 @@ out_put_request:
* Positive numbers returned are the compacted SCSI error codes (4
* bytes in one int) where the lowest byte is the SCSI status.
*/
-static int sg_scsi_ioctl(struct request_queue *q, fmode_t mode,
+static int sg_scsi_ioctl(struct request_queue *q, bool open_for_write,
struct scsi_ioctl_command __user *sic)
{
struct request *rq;
@@ -554,7 +554,7 @@ static int sg_scsi_ioctl(struct request_queue *q, fmode_t mode,
goto error;
err = -EPERM;
- if (!scsi_cmd_allowed(scmd->cmnd, mode))
+ if (!scsi_cmd_allowed(scmd->cmnd, open_for_write))
goto error;
/* default. possible overridden later */
@@ -776,7 +776,7 @@ static int scsi_put_cdrom_generic_arg(const struct cdrom_generic_command *cgc,
return 0;
}
-static int scsi_cdrom_send_packet(struct scsi_device *sdev, fmode_t mode,
+static int scsi_cdrom_send_packet(struct scsi_device *sdev, bool open_for_write,
void __user *arg)
{
struct cdrom_generic_command cgc;
@@ -817,7 +817,7 @@ static int scsi_cdrom_send_packet(struct scsi_device *sdev, fmode_t mode,
hdr.cmdp = ((struct cdrom_generic_command __user *) arg)->cmd;
hdr.cmd_len = sizeof(cgc.cmd);
- err = sg_io(sdev, &hdr, mode);
+ err = sg_io(sdev, &hdr, open_for_write);
if (err == -EFAULT)
return -EFAULT;
@@ -832,7 +832,7 @@ static int scsi_cdrom_send_packet(struct scsi_device *sdev, fmode_t mode,
return err;
}
-static int scsi_ioctl_sg_io(struct scsi_device *sdev, fmode_t mode,
+static int scsi_ioctl_sg_io(struct scsi_device *sdev, bool open_for_write,
void __user *argp)
{
struct sg_io_hdr hdr;
@@ -841,7 +841,7 @@ static int scsi_ioctl_sg_io(struct scsi_device *sdev, fmode_t mode,
error = get_sg_io_hdr(&hdr, argp);
if (error)
return error;
- error = sg_io(sdev, &hdr, mode);
+ error = sg_io(sdev, &hdr, open_for_write);
if (error == -EFAULT)
return error;
if (put_sg_io_hdr(&hdr, argp))
@@ -852,7 +852,7 @@ static int scsi_ioctl_sg_io(struct scsi_device *sdev, fmode_t mode,
/**
* scsi_ioctl - Dispatch ioctl to scsi device
* @sdev: scsi device receiving ioctl
- * @mode: mode the block/char device is opened with
+ * @open_for_write: is the file / block device opened for writing?
* @cmd: which ioctl is it
* @arg: data associated with ioctl
*
@@ -860,7 +860,7 @@ static int scsi_ioctl_sg_io(struct scsi_device *sdev, fmode_t mode,
* does not take a major/minor number as the dev field. Rather, it takes
* a pointer to a &struct scsi_device.
*/
-int scsi_ioctl(struct scsi_device *sdev, fmode_t mode, int cmd,
+int scsi_ioctl(struct scsi_device *sdev, bool open_for_write, int cmd,
void __user *arg)
{
struct request_queue *q = sdev->request_queue;
@@ -896,11 +896,11 @@ int scsi_ioctl(struct scsi_device *sdev, fmode_t mode, int cmd,
case SG_EMULATED_HOST:
return sg_emulated_host(q, arg);
case SG_IO:
- return scsi_ioctl_sg_io(sdev, mode, arg);
+ return scsi_ioctl_sg_io(sdev, open_for_write, arg);
case SCSI_IOCTL_SEND_COMMAND:
- return sg_scsi_ioctl(q, mode, arg);
+ return sg_scsi_ioctl(q, open_for_write, arg);
case CDROM_SEND_PACKET:
- return scsi_cdrom_send_packet(sdev, mode, arg);
+ return scsi_cdrom_send_packet(sdev, open_for_write, arg);
case CDROMCLOSETRAY:
return scsi_send_start_stop(sdev, 3);
case CDROMEJECT:
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_proc.c b/drivers/scsi/scsi_proc.c
index 4a6eb1741be0..41f23cd0bfb4 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -406,7 +406,7 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
size_t length, loff_t *ppos)
{
int host, channel, id, lun;
- char *buffer, *p;
+ char *buffer, *end, *p;
int err;
if (!buf || length > PAGE_SIZE)
@@ -421,10 +421,14 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
goto out;
err = -EINVAL;
- if (length < PAGE_SIZE)
- buffer[length] = '\0';
- else if (buffer[PAGE_SIZE-1])
- goto out;
+ if (length < PAGE_SIZE) {
+ end = buffer + length;
+ *end = '\0';
+ } else {
+ end = buffer + PAGE_SIZE - 1;
+ if (*end)
+ goto out;
+ }
/*
* Usage: echo "scsi add-single-device 0 1 2 3" >/proc/scsi/scsi
@@ -433,10 +437,10 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
if (!strncmp("scsi add-single-device", buffer, 22)) {
p = buffer + 23;
- host = simple_strtoul(p, &p, 0);
- channel = simple_strtoul(p + 1, &p, 0);
- id = simple_strtoul(p + 1, &p, 0);
- lun = simple_strtoul(p + 1, &p, 0);
+ host = (p < end) ? simple_strtoul(p, &p, 0) : 0;
+ channel = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
+ id = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
+ lun = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
err = scsi_add_single_device(host, channel, id, lun);
@@ -447,10 +451,10 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
} else if (!strncmp("scsi remove-single-device", buffer, 25)) {
p = buffer + 26;
- host = simple_strtoul(p, &p, 0);
- channel = simple_strtoul(p + 1, &p, 0);
- id = simple_strtoul(p + 1, &p, 0);
- lun = simple_strtoul(p + 1, &p, 0);
+ host = (p < end) ? simple_strtoul(p, &p, 0) : 0;
+ channel = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
+ id = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
+ lun = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
err = scsi_remove_single_device(host, channel, id, lun);
}
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 1624d528aa1f..3c668cfb146d 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,
@@ -1280,11 +1309,10 @@ static void sd_uninit_command(struct scsi_cmnd *SCpnt)
mempool_free(rq->special_vec.bv_page, sd_page_pool);
}
-static bool sd_need_revalidate(struct block_device *bdev,
- struct scsi_disk *sdkp)
+static bool sd_need_revalidate(struct gendisk *disk, struct scsi_disk *sdkp)
{
if (sdkp->device->removable || sdkp->write_prot) {
- if (bdev_check_media_change(bdev))
+ if (disk_check_media_change(disk))
return true;
}
@@ -1293,13 +1321,13 @@ static bool sd_need_revalidate(struct block_device *bdev,
* nothing to do with partitions, BLKRRPART is used to force a full
* revalidate after things like a format for historical reasons.
*/
- return test_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state);
+ return test_bit(GD_NEED_PART_SCAN, &disk->state);
}
/**
* sd_open - open a scsi disk device
- * @bdev: Block device of the scsi disk to open
- * @mode: FMODE_* mask
+ * @disk: disk to open
+ * @mode: open mode
*
* Returns 0 if successful. Returns a negated errno value in case
* of error.
@@ -1309,11 +1337,11 @@ static bool sd_need_revalidate(struct block_device *bdev,
* In the latter case @inode and @filp carry an abridged amount
* of information as noted above.
*
- * Locking: called with bdev->bd_disk->open_mutex held.
+ * Locking: called with disk->open_mutex held.
**/
-static int sd_open(struct block_device *bdev, fmode_t mode)
+static int sd_open(struct gendisk *disk, blk_mode_t mode)
{
- struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
+ struct scsi_disk *sdkp = scsi_disk(disk);
struct scsi_device *sdev = sdkp->device;
int retval;
@@ -1330,14 +1358,15 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
if (!scsi_block_when_processing_errors(sdev))
goto error_out;
- if (sd_need_revalidate(bdev, sdkp))
- sd_revalidate_disk(bdev->bd_disk);
+ if (sd_need_revalidate(disk, sdkp))
+ sd_revalidate_disk(disk);
/*
* If the drive is empty, just let the open fail.
*/
retval = -ENOMEDIUM;
- if (sdev->removable && !sdkp->media_present && !(mode & FMODE_NDELAY))
+ if (sdev->removable && !sdkp->media_present &&
+ !(mode & BLK_OPEN_NDELAY))
goto error_out;
/*
@@ -1345,7 +1374,7 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
* if the user expects to be able to write to the thing.
*/
retval = -EROFS;
- if (sdkp->write_prot && (mode & FMODE_WRITE))
+ if (sdkp->write_prot && (mode & BLK_OPEN_WRITE))
goto error_out;
/*
@@ -1374,16 +1403,15 @@ error_out:
* sd_release - invoked when the (last) close(2) is called on this
* scsi disk.
* @disk: disk to release
- * @mode: FMODE_* mask
*
* Returns 0.
*
* Note: may block (uninterruptible) if error recovery is underway
* on this disk.
*
- * Locking: called with bdev->bd_disk->open_mutex held.
+ * Locking: called with disk->open_mutex held.
**/
-static void sd_release(struct gendisk *disk, fmode_t mode)
+static void sd_release(struct gendisk *disk)
{
struct scsi_disk *sdkp = scsi_disk(disk);
struct scsi_device *sdev = sdkp->device;
@@ -1426,7 +1454,7 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
/**
* sd_ioctl - process an ioctl
* @bdev: target block device
- * @mode: FMODE_* mask
+ * @mode: open mode
* @cmd: ioctl command number
* @arg: this is third argument given to ioctl(2) system call.
* Often contains a pointer.
@@ -1437,7 +1465,7 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
* Note: most ioctls are forward onto the block subsystem or further
* down in the scsi subsystem.
**/
-static int sd_ioctl(struct block_device *bdev, fmode_t mode,
+static int sd_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long arg)
{
struct gendisk *disk = bdev->bd_disk;
@@ -1459,13 +1487,13 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
* access to the device is prohibited.
*/
error = scsi_ioctl_block_when_processing_errors(sdp, cmd,
- (mode & FMODE_NDELAY) != 0);
+ (mode & BLK_OPEN_NDELAY));
if (error)
return error;
if (is_sed_ioctl(cmd))
return sed_ioctl(sdkp->opal_dev, cmd, p);
- return scsi_ioctl(sdp, mode, cmd, p);
+ return scsi_ioctl(sdp, mode & BLK_OPEN_WRITE, cmd, p);
}
static void set_media_not_present(struct scsi_disk *sdkp)
@@ -1691,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)) {
@@ -1741,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;
@@ -1784,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 */);
}
@@ -1794,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 = {
@@ -1820,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)
@@ -2609,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);
}
/*
@@ -2868,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 ||
@@ -3057,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;
@@ -3073,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;
}
@@ -3088,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;
}
@@ -3776,7 +3876,7 @@ static int sd_suspend_runtime(struct device *dev)
static int sd_resume(struct device *dev)
{
struct scsi_disk *sdkp = dev_get_drvdata(dev);
- int ret;
+ int ret = 0;
if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */
return 0;
@@ -3784,8 +3884,11 @@ static int sd_resume(struct device *dev)
if (!sdkp->device->manage_start_stop)
return 0;
- sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
- ret = sd_start_stop_device(sdkp, 1);
+ if (!sdkp->device->no_start_on_resume) {
+ sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
+ ret = sd_start_stop_device(sdkp, 1);
+ }
+
if (!ret)
opal_unlock_from_suspend(sdkp->opal_dev);
return ret;
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index 22801c24ea19..a25215507668 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -831,7 +831,6 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
struct request_queue *q = disk->queue;
u32 zone_blocks = sdkp->early_zone_info.zone_blocks;
unsigned int nr_zones = sdkp->early_zone_info.nr_zones;
- u32 max_append;
int ret = 0;
unsigned int flags;
@@ -876,6 +875,11 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
goto unlock;
}
+ blk_queue_chunk_sectors(q,
+ logical_to_sectors(sdkp->device, zone_blocks));
+ blk_queue_max_zone_append_sectors(q,
+ q->limits.max_segments << PAGE_SECTORS_SHIFT);
+
ret = blk_revalidate_disk_zones(disk, sd_zbc_revalidate_zones_cb);
memalloc_noio_restore(flags);
@@ -888,12 +892,6 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
goto unlock;
}
- max_append = min_t(u32, logical_to_sectors(sdkp->device, zone_blocks),
- q->limits.max_segments << (PAGE_SHIFT - 9));
- max_append = min_t(u32, max_append, queue_max_hw_sectors(q));
-
- blk_queue_max_zone_append_sectors(q, max_append);
-
sd_zbc_print_zones(sdkp);
unlock:
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 037f8c98a6d3..0d8afffd1683 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
@@ -237,7 +237,7 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd)
if (sfp->parentdp->device->type == TYPE_SCANNER)
return 0;
- if (!scsi_cmd_allowed(cmd, filp->f_mode))
+ if (!scsi_cmd_allowed(cmd, filp->f_mode & FMODE_WRITE))
return -EPERM;
return 0;
}
@@ -1103,7 +1103,8 @@ sg_ioctl_common(struct file *filp, Sg_device *sdp, Sg_fd *sfp,
case SCSI_IOCTL_SEND_COMMAND:
if (atomic_read(&sdp->detaching))
return -ENODEV;
- return scsi_ioctl(sdp->device, filp->f_mode, cmd_in, p);
+ return scsi_ioctl(sdp->device, filp->f_mode & FMODE_WRITE,
+ cmd_in, p);
case SG_SET_DEBUG:
result = get_user(val, ip);
if (result)
@@ -1159,7 +1160,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
ret = sg_ioctl_common(filp, sdp, sfp, cmd_in, p);
if (ret != -ENOIOCTLCMD)
return ret;
- return scsi_ioctl(sdp->device, filp->f_mode, cmd_in, p);
+ return scsi_ioctl(sdp->device, filp->f_mode & FMODE_WRITE, cmd_in, p);
}
static __poll_t
@@ -1496,6 +1497,11 @@ sg_add_device(struct device *cl_dev)
int error;
unsigned long iflags;
+ if (!blk_get_queue(scsidp->request_queue)) {
+ pr_warn("%s: get scsi_device queue failed\n", __func__);
+ return -ENODEV;
+ }
+
error = -ENOMEM;
cdev = cdev_alloc();
if (!cdev) {
@@ -1553,6 +1559,7 @@ cdev_add_err:
out:
if (cdev)
cdev_del(cdev);
+ blk_put_queue(scsidp->request_queue);
return error;
}
@@ -1560,6 +1567,7 @@ static void
sg_device_destroy(struct kref *kref)
{
struct sg_device *sdp = container_of(kref, struct sg_device, d_ref);
+ struct request_queue *q = sdp->device->request_queue;
unsigned long flags;
/* CAUTION! Note that the device can still be found via idr_find()
@@ -1567,6 +1575,9 @@ sg_device_destroy(struct kref *kref)
* any other cleanup.
*/
+ blk_trace_remove(q);
+ blk_put_queue(q);
+
write_lock_irqsave(&sg_index_lock, flags);
idr_remove(&sg_index_idr, sdp->index);
write_unlock_irqrestore(&sg_index_lock, flags);
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..e392eaf5b2bf 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.
*
@@ -982,12 +982,12 @@ struct report_phys_lun_16byte_wwid {
struct report_phys_lun_8byte_wwid_list {
struct report_lun_header header;
- struct report_phys_lun_8byte_wwid lun_entries[1];
+ struct report_phys_lun_8byte_wwid lun_entries[];
};
struct report_phys_lun_16byte_wwid_list {
struct report_lun_header header;
- struct report_phys_lun_16byte_wwid lun_entries[1];
+ struct report_phys_lun_16byte_wwid lun_entries[];
};
struct raid_map_disk_data {
@@ -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 03de97cd72c2..6aaaa7ebca37 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;
}
@@ -1176,7 +1203,6 @@ static inline int pqi_report_phys_luns(struct pqi_ctrl_info *ctrl_info, void **b
unsigned int i;
u8 rpl_response_format;
u32 num_physicals;
- size_t rpl_16byte_wwid_list_length;
void *rpl_list;
struct report_lun_header *rpl_header;
struct report_phys_lun_8byte_wwid_list *rpl_8byte_wwid_list;
@@ -1205,9 +1231,9 @@ static inline int pqi_report_phys_luns(struct pqi_ctrl_info *ctrl_info, void **b
rpl_8byte_wwid_list = rpl_list;
num_physicals = get_unaligned_be32(&rpl_8byte_wwid_list->header.list_length) / sizeof(rpl_8byte_wwid_list->lun_entries[0]);
- rpl_16byte_wwid_list_length = sizeof(struct report_lun_header) + (num_physicals * sizeof(struct report_phys_lun_16byte_wwid));
- rpl_16byte_wwid_list = kmalloc(rpl_16byte_wwid_list_length, GFP_KERNEL);
+ rpl_16byte_wwid_list = kmalloc(struct_size(rpl_16byte_wwid_list, lun_entries,
+ num_physicals), GFP_KERNEL);
if (!rpl_16byte_wwid_list)
return -ENOMEM;
@@ -1588,6 +1614,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 +1663,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 +1710,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 +1718,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 +2464,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 +2486,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) {
@@ -5015,7 +4980,7 @@ static int pqi_create_queues(struct pqi_ctrl_info *ctrl_info)
}
#define PQI_REPORT_EVENT_CONFIG_BUFFER_LENGTH \
- struct_size((struct pqi_event_config *)0, descriptors, PQI_MAX_EVENT_DESCRIPTORS)
+ struct_size_t(struct pqi_event_config, descriptors, PQI_MAX_EVENT_DESCRIPTORS)
static int pqi_configure_events(struct pqi_ctrl_info *ctrl_info,
bool enable_events)
@@ -5504,15 +5469,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 +5491,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 +5557,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 +5606,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 +5630,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 +5648,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 +5989,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 +6840,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 +7225,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 +7241,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 +7303,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 +7315,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 +7336,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 +7347,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 +7666,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 +8510,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 +8968,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 +9880,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 +9928,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 +9992,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 +10008,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..4db3ba62fcd3 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);
@@ -307,7 +307,7 @@ snic_tgt_create(struct snic *snic, struct snic_tgt_id *tgtid)
spin_lock_irqsave(snic->shost->host_lock, flags);
list_del(&tgt->list);
spin_unlock_irqrestore(snic->shost->host_lock, flags);
- kfree(tgt);
+ put_device(&tgt->dev);
tgt = NULL;
return tgt;
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 12869e6d4ebd..07ef3db3d1a1 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -484,9 +484,9 @@ static void sr_revalidate_disk(struct scsi_cd *cd)
get_sectorsize(cd);
}
-static int sr_block_open(struct block_device *bdev, fmode_t mode)
+static int sr_block_open(struct gendisk *disk, blk_mode_t mode)
{
- struct scsi_cd *cd = scsi_cd(bdev->bd_disk);
+ struct scsi_cd *cd = scsi_cd(disk);
struct scsi_device *sdev = cd->device;
int ret;
@@ -494,11 +494,11 @@ static int sr_block_open(struct block_device *bdev, fmode_t mode)
return -ENXIO;
scsi_autopm_get_device(sdev);
- if (bdev_check_media_change(bdev))
+ if (disk_check_media_change(disk))
sr_revalidate_disk(cd);
mutex_lock(&cd->lock);
- ret = cdrom_open(&cd->cdi, bdev, mode);
+ ret = cdrom_open(&cd->cdi, mode);
mutex_unlock(&cd->lock);
scsi_autopm_put_device(sdev);
@@ -507,19 +507,19 @@ static int sr_block_open(struct block_device *bdev, fmode_t mode)
return ret;
}
-static void sr_block_release(struct gendisk *disk, fmode_t mode)
+static void sr_block_release(struct gendisk *disk)
{
struct scsi_cd *cd = scsi_cd(disk);
mutex_lock(&cd->lock);
- cdrom_release(&cd->cdi, mode);
+ cdrom_release(&cd->cdi);
mutex_unlock(&cd->lock);
scsi_device_put(cd->device);
}
-static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
- unsigned long arg)
+static int sr_block_ioctl(struct block_device *bdev, blk_mode_t mode,
+ unsigned cmd, unsigned long arg)
{
struct scsi_cd *cd = scsi_cd(bdev->bd_disk);
struct scsi_device *sdev = cd->device;
@@ -532,18 +532,18 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
mutex_lock(&cd->lock);
ret = scsi_ioctl_block_when_processing_errors(sdev, cmd,
- (mode & FMODE_NDELAY) != 0);
+ (mode & BLK_OPEN_NDELAY));
if (ret)
goto out;
scsi_autopm_get_device(sdev);
if (cmd != CDROMCLOSETRAY && cmd != CDROMEJECT) {
- ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg);
+ ret = cdrom_ioctl(&cd->cdi, bdev, cmd, arg);
if (ret != -ENOSYS)
goto put;
}
- ret = scsi_ioctl(sdev, mode, cmd, argp);
+ ret = scsi_ioctl(sdev, mode & BLK_OPEN_WRITE, cmd, argp);
put:
scsi_autopm_put_device(sdev);
@@ -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/st.c b/drivers/scsi/st.c
index b90a440e135d..14d7981ddcdd 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3832,7 +3832,7 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
break;
}
- retval = scsi_ioctl(STp->device, file->f_mode, cmd_in, p);
+ retval = scsi_ioctl(STp->device, file->f_mode & FMODE_WRITE, cmd_in, p);
if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) {
/* unload */
STp->rew_at_close = 0;
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 659196a2f63a..047ffaf7d42a 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -318,6 +318,7 @@ enum storvsc_request_type {
#define SRB_STATUS_INVALID_REQUEST 0x06
#define SRB_STATUS_DATA_OVERRUN 0x12
#define SRB_STATUS_INVALID_LUN 0x20
+#define SRB_STATUS_INTERNAL_ERROR 0x30
#define SRB_STATUS(status) \
(status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN))
@@ -365,6 +366,7 @@ static void storvsc_on_channel_callback(void *context);
#define STORVSC_FC_MAX_LUNS_PER_TARGET 255
#define STORVSC_FC_MAX_TARGETS 128
#define STORVSC_FC_MAX_CHANNELS 8
+#define STORVSC_FC_MAX_XFER_SIZE ((u32)(512 * 1024))
#define STORVSC_IDE_MAX_LUNS_PER_TARGET 64
#define STORVSC_IDE_MAX_TARGETS 1
@@ -978,6 +980,7 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb,
case SRB_STATUS_ERROR:
case SRB_STATUS_ABORTED:
case SRB_STATUS_INVALID_REQUEST:
+ case SRB_STATUS_INTERNAL_ERROR:
if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID) {
/* Check for capacity change */
if ((asc == 0x2a) && (ascq == 0x9)) {
@@ -1671,10 +1674,6 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
*/
static enum scsi_timeout_action storvsc_eh_timed_out(struct scsi_cmnd *scmnd)
{
-#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
- if (scmnd->device->host->transportt == fc_transport_template)
- return fc_eh_timed_out(scmnd);
-#endif
return SCSI_EH_RESET_TIMER;
}
@@ -2004,6 +2003,9 @@ static int storvsc_probe(struct hv_device *device,
* protecting it from any weird value.
*/
max_xfer_bytes = round_down(stor_device->max_transfer_bytes, HV_HYP_PAGE_SIZE);
+ if (is_fc)
+ max_xfer_bytes = min(max_xfer_bytes, STORVSC_FC_MAX_XFER_SIZE);
+
/* max_hw_sectors_kb */
host->max_sectors = max_xfer_bytes >> 9;
/*
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/aspeed/aspeed-socinfo.c b/drivers/soc/aspeed/aspeed-socinfo.c
index 1ca140356a08..3f759121dc00 100644
--- a/drivers/soc/aspeed/aspeed-socinfo.c
+++ b/drivers/soc/aspeed/aspeed-socinfo.c
@@ -137,6 +137,7 @@ static int __init aspeed_socinfo_init(void)
soc_dev = soc_device_register(attrs);
if (IS_ERR(soc_dev)) {
+ kfree(attrs->machine);
kfree(attrs->soc_id);
kfree(attrs->serial_number);
kfree(attrs);
diff --git a/drivers/soc/aspeed/aspeed-uart-routing.c b/drivers/soc/aspeed/aspeed-uart-routing.c
index ef8b24fd1851..59123e1f27ac 100644
--- a/drivers/soc/aspeed/aspeed-uart-routing.c
+++ b/drivers/soc/aspeed/aspeed-uart-routing.c
@@ -524,7 +524,7 @@ static ssize_t aspeed_uart_routing_store(struct device *dev,
struct aspeed_uart_routing_selector *sel = to_routing_selector(attr);
int val;
- val = match_string(sel->options, -1, buf);
+ val = __sysfs_match_string(sel->options, -1, buf);
if (val < 0) {
dev_err(dev, "invalid value \"%s\"\n", buf);
return -EINVAL;
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/imx/imx8mp-blk-ctrl.c b/drivers/soc/imx/imx8mp-blk-ctrl.c
index 870aecc0202a..1c1fcab4979a 100644
--- a/drivers/soc/imx/imx8mp-blk-ctrl.c
+++ b/drivers/soc/imx/imx8mp-blk-ctrl.c
@@ -164,7 +164,7 @@ static int imx8mp_hsio_blk_ctrl_probe(struct imx8mp_blk_ctrl *bc)
clk_hsio_pll->hw.init = &init;
hw = &clk_hsio_pll->hw;
- ret = devm_clk_hw_register(bc->dev, hw);
+ ret = devm_clk_hw_register(bc->bus_power_dev, hw);
if (ret)
return ret;
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 795a2e1d59b3..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);
@@ -682,6 +662,30 @@ EXPORT_SYMBOL(geni_se_clk_freq_match);
#define GENI_SE_DMA_EOT_EN BIT(1)
#define GENI_SE_DMA_AHB_ERR_EN BIT(2)
#define GENI_SE_DMA_EOT_BUF BIT(0)
+
+/**
+ * geni_se_tx_init_dma() - Initiate TX DMA transfer on the serial engine
+ * @se: Pointer to the concerned serial engine.
+ * @iova: Mapped DMA address.
+ * @len: Length of the TX buffer.
+ *
+ * This function is used to initiate DMA TX transfer.
+ */
+void geni_se_tx_init_dma(struct geni_se *se, dma_addr_t iova, size_t len)
+{
+ u32 val;
+
+ val = GENI_SE_DMA_DONE_EN;
+ val |= GENI_SE_DMA_EOT_EN;
+ val |= GENI_SE_DMA_AHB_ERR_EN;
+ writel_relaxed(val, se->base + SE_DMA_TX_IRQ_EN_SET);
+ writel_relaxed(lower_32_bits(iova), se->base + SE_DMA_TX_PTR_L);
+ writel_relaxed(upper_32_bits(iova), se->base + SE_DMA_TX_PTR_H);
+ writel_relaxed(GENI_SE_DMA_EOT_BUF, se->base + SE_DMA_TX_ATTR);
+ writel(len, se->base + SE_DMA_TX_LEN);
+}
+EXPORT_SYMBOL(geni_se_tx_init_dma);
+
/**
* geni_se_tx_dma_prep() - Prepare the serial engine for TX DMA transfer
* @se: Pointer to the concerned serial engine.
@@ -697,7 +701,6 @@ int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len,
dma_addr_t *iova)
{
struct geni_wrapper *wrapper = se->wrapper;
- u32 val;
if (!wrapper)
return -EINVAL;
@@ -706,17 +709,34 @@ int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len,
if (dma_mapping_error(wrapper->dev, *iova))
return -EIO;
+ geni_se_tx_init_dma(se, *iova, len);
+ return 0;
+}
+EXPORT_SYMBOL(geni_se_tx_dma_prep);
+
+/**
+ * geni_se_rx_init_dma() - Initiate RX DMA transfer on the serial engine
+ * @se: Pointer to the concerned serial engine.
+ * @iova: Mapped DMA address.
+ * @len: Length of the RX buffer.
+ *
+ * This function is used to initiate DMA RX transfer.
+ */
+void geni_se_rx_init_dma(struct geni_se *se, dma_addr_t iova, size_t len)
+{
+ u32 val;
+
val = GENI_SE_DMA_DONE_EN;
val |= GENI_SE_DMA_EOT_EN;
val |= GENI_SE_DMA_AHB_ERR_EN;
- writel_relaxed(val, se->base + SE_DMA_TX_IRQ_EN_SET);
- writel_relaxed(lower_32_bits(*iova), se->base + SE_DMA_TX_PTR_L);
- writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_TX_PTR_H);
- writel_relaxed(GENI_SE_DMA_EOT_BUF, se->base + SE_DMA_TX_ATTR);
- writel(len, se->base + SE_DMA_TX_LEN);
- return 0;
+ writel_relaxed(val, se->base + SE_DMA_RX_IRQ_EN_SET);
+ writel_relaxed(lower_32_bits(iova), se->base + SE_DMA_RX_PTR_L);
+ writel_relaxed(upper_32_bits(iova), se->base + SE_DMA_RX_PTR_H);
+ /* RX does not have EOT buffer type bit. So just reset RX_ATTR */
+ writel_relaxed(0, se->base + SE_DMA_RX_ATTR);
+ writel(len, se->base + SE_DMA_RX_LEN);
}
-EXPORT_SYMBOL(geni_se_tx_dma_prep);
+EXPORT_SYMBOL(geni_se_rx_init_dma);
/**
* geni_se_rx_dma_prep() - Prepare the serial engine for RX DMA transfer
@@ -733,7 +753,6 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len,
dma_addr_t *iova)
{
struct geni_wrapper *wrapper = se->wrapper;
- u32 val;
if (!wrapper)
return -EINVAL;
@@ -742,15 +761,7 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len,
if (dma_mapping_error(wrapper->dev, *iova))
return -EIO;
- val = GENI_SE_DMA_DONE_EN;
- val |= GENI_SE_DMA_EOT_EN;
- val |= GENI_SE_DMA_AHB_ERR_EN;
- writel_relaxed(val, se->base + SE_DMA_RX_IRQ_EN_SET);
- writel_relaxed(lower_32_bits(*iova), se->base + SE_DMA_RX_PTR_L);
- writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_RX_PTR_H);
- /* RX does not have EOT buffer type bit. So just reset RX_ATTR */
- writel_relaxed(0, se->base + SE_DMA_RX_ATTR);
- writel(len, se->base + SE_DMA_RX_LEN);
+ geni_se_rx_init_dma(se, *iova, len);
return 0;
}
EXPORT_SYMBOL(geni_se_rx_dma_prep);
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..3a99f6dcdfaf 100644
--- a/drivers/soundwire/amd_manager.c
+++ b/drivers/soundwire/amd_manager.c
@@ -910,9 +910,9 @@ static int amd_sdw_manager_probe(struct platform_device *pdev)
return -ENOMEM;
amd_manager->acp_mmio = devm_ioremap(dev, res->start, resource_size(res));
- if (IS_ERR(amd_manager->mmio)) {
+ if (!amd_manager->acp_mmio) {
dev_err(dev, "mmio not found\n");
- return PTR_ERR(amd_manager->mmio);
+ return -ENOMEM;
}
amd_manager->instance = pdata->instance;
amd_manager->mmio = amd_manager->acp_mmio +
@@ -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..cf78839b3f74 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;
}
@@ -908,8 +922,8 @@ static void sdw_modify_slave_status(struct sdw_slave *slave,
"initializing enumeration and init completion for Slave %d\n",
slave->dev_num);
- init_completion(&slave->enumeration_complete);
- init_completion(&slave->initialization_complete);
+ reinit_completion(&slave->enumeration_complete);
+ reinit_completion(&slave->initialization_complete);
} else if ((status == SDW_SLAVE_ATTACHED) &&
(slave->status == SDW_SLAVE_UNATTACHED)) {
@@ -917,7 +931,7 @@ static void sdw_modify_slave_status(struct sdw_slave *slave,
"signaling enumeration completion for Slave %d\n",
slave->dev_num);
- complete(&slave->enumeration_complete);
+ complete_all(&slave->enumeration_complete);
}
slave->status = status;
mutex_unlock(&bus->bus_lock);
@@ -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;
/*
@@ -1941,7 +1951,7 @@ int sdw_handle_slave_status(struct sdw_bus *bus,
"signaling initialization completion for Slave %d\n",
slave->dev_num);
- complete(&slave->initialization_complete);
+ complete_all(&slave->initialization_complete);
/*
* If the manager became pm_runtime active, the peripherals will be
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..c029e4d53573 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;
}
@@ -436,7 +540,7 @@ static int qcom_swrm_get_alert_slave_dev_num(struct qcom_swrm_ctrl *ctrl)
status = (val >> (dev_num * SWRM_MCP_SLV_STATUS_SZ));
if ((status & SWRM_MCP_SLV_STATUS_MASK) == SDW_SLAVE_ALERT) {
- ctrl->status[dev_num] = status;
+ ctrl->status[dev_num] = status & SWRM_MCP_SLV_STATUS_MASK;
return dev_num;
}
}
@@ -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/spi/Kconfig b/drivers/spi/Kconfig
index 3de2ebe8294a..8962b2557615 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -825,6 +825,12 @@ config SPI_RSPI
help
SPI driver for Renesas RSPI and QSPI blocks.
+config SPI_RZV2M_CSI
+ tristate "Renesas RZ/V2M CSI controller"
+ depends on ARCH_RENESAS || COMPILE_TEST
+ help
+ SPI driver for Renesas RZ/V2M Clocked Serial Interface (CSI)
+
config SPI_QCOM_QSPI
tristate "QTI QSPI controller"
depends on ARCH_QCOM || COMPILE_TEST
@@ -936,6 +942,7 @@ config SPI_SPRD_ADI
config SPI_STM32
tristate "STMicroelectronics STM32 SPI controller"
depends on ARCH_STM32 || COMPILE_TEST
+ select SPI_SLAVE
help
SPI driver for STMicroelectronics STM32 SoCs.
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 28c4817a8a74..080c2c1b3ec1 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -113,6 +113,7 @@ obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o
obj-$(CONFIG_MACH_REALTEK_RTL) += spi-realtek-rtl.o
obj-$(CONFIG_SPI_RPCIF) += spi-rpc-if.o
obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
+obj-$(CONFIG_SPI_RZV2M_CSI) += spi-rzv2m-csi.o
obj-$(CONFIG_SPI_S3C64XX) += spi-s3c64xx.o
obj-$(CONFIG_SPI_SC18IS602) += spi-sc18is602.o
obj-$(CONFIG_SPI_SH) += spi-sh.o
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 7f06305e16cb..152cd6773403 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -233,7 +233,8 @@
*/
#define DMA_MIN_BYTES 16
-#define SPI_DMA_TIMEOUT (msecs_to_jiffies(1000))
+#define SPI_DMA_MIN_TIMEOUT (msecs_to_jiffies(1000))
+#define SPI_DMA_TIMEOUT_PER_10K (msecs_to_jiffies(4))
#define AUTOSUSPEND_TIMEOUT 2000
@@ -1279,7 +1280,8 @@ static int atmel_spi_one_transfer(struct spi_controller *host,
struct atmel_spi_device *asd;
int timeout;
int ret;
- unsigned long dma_timeout;
+ unsigned int dma_timeout;
+ long ret_timeout;
as = spi_controller_get_devdata(host);
@@ -1333,11 +1335,13 @@ static int atmel_spi_one_transfer(struct spi_controller *host,
atmel_spi_unlock(as);
}
- dma_timeout = wait_for_completion_timeout(&as->xfer_completion,
- SPI_DMA_TIMEOUT);
- if (WARN_ON(dma_timeout == 0)) {
- dev_err(&spi->dev, "spi transfer timeout\n");
- as->done_status = -EIO;
+ dma_timeout = msecs_to_jiffies(spi_controller_xfer_timeout(host, xfer));
+ ret_timeout = wait_for_completion_interruptible_timeout(&as->xfer_completion,
+ dma_timeout);
+ if (ret_timeout <= 0) {
+ dev_err(&spi->dev, "spi transfer %s\n",
+ !ret_timeout ? "timeout" : "canceled");
+ as->done_status = ret_timeout < 0 ? ret_timeout : -EIO;
}
if (as->done_status)
diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c
index 6b46a3b67c41..d91dfbe47aa5 100644
--- a/drivers/spi/spi-bcm-qspi.c
+++ b/drivers/spi/spi-bcm-qspi.c
@@ -1543,13 +1543,9 @@ int bcm_qspi_probe(struct platform_device *pdev,
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"mspi");
- if (res) {
- qspi->base[MSPI] = devm_ioremap_resource(dev, res);
- if (IS_ERR(qspi->base[MSPI]))
- return PTR_ERR(qspi->base[MSPI]);
- } else {
- return 0;
- }
+ qspi->base[MSPI] = devm_ioremap_resource(dev, res);
+ if (IS_ERR(qspi->base[MSPI]))
+ return PTR_ERR(qspi->base[MSPI]);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi");
if (res) {
diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c
index ee2528dad02d..9e218e143263 100644
--- a/drivers/spi/spi-bcm63xx-hsspi.c
+++ b/drivers/spi/spi-bcm63xx-hsspi.c
@@ -2,7 +2,7 @@
* Broadcom BCM63XX High Speed SPI Controller driver
*
* Copyright 2000-2010 Broadcom Corporation
- * Copyright 2012-2013 Jonas Gorski <jogo@openwrt.org>
+ * Copyright 2012-2013 Jonas Gorski <jonas.gorski@gmail.com>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c
index 9aecb77c3d89..07b5b71b2352 100644
--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -126,7 +126,7 @@ enum bcm63xx_regs_spi {
SPI_MSG_DATA_SIZE,
};
-#define BCM63XX_SPI_MAX_PREPEND 15
+#define BCM63XX_SPI_MAX_PREPEND 7
#define BCM63XX_SPI_MAX_CS 8
#define BCM63XX_SPI_BUS_NUM 0
diff --git a/drivers/spi/spi-bcmbca-hsspi.c b/drivers/spi/spi-bcmbca-hsspi.c
index 8cbd01619789..ca1b4741e9f4 100644
--- a/drivers/spi/spi-bcmbca-hsspi.c
+++ b/drivers/spi/spi-bcmbca-hsspi.c
@@ -3,7 +3,7 @@
* Broadcom BCMBCA High Speed SPI Controller driver
*
* Copyright 2000-2010 Broadcom Corporation
- * Copyright 2012-2013 Jonas Gorski <jogo@openwrt.org>
+ * Copyright 2012-2013 Jonas Gorski <jonas.gorski@gmail.com>
* Copyright 2019-2022 Broadcom Ltd
*/
diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
index 32449bef4415..abf10f92415d 100644
--- a/drivers/spi/spi-cadence-quadspi.c
+++ b/drivers/spi/spi-cadence-quadspi.c
@@ -40,6 +40,7 @@
#define CQSPI_SUPPORT_EXTERNAL_DMA BIT(2)
#define CQSPI_NO_SUPPORT_WR_COMPLETION BIT(3)
#define CQSPI_SLOW_SRAM BIT(4)
+#define CQSPI_NEEDS_APB_AHB_HAZARD_WAR BIT(5)
/* Capabilities */
#define CQSPI_SUPPORTS_OCTAL BIT(0)
@@ -90,6 +91,7 @@ struct cqspi_st {
u32 pd_dev_id;
bool wr_completion;
bool slow_sram;
+ bool apb_ahb_hazard;
};
struct cqspi_driver_platdata {
@@ -1027,6 +1029,13 @@ static int cqspi_indirect_write_execute(struct cqspi_flash_pdata *f_pdata,
if (cqspi->wr_delay)
ndelay(cqspi->wr_delay);
+ /*
+ * If a hazard exists between the APB and AHB interfaces, perform a
+ * dummy readback from the controller to ensure synchronization.
+ */
+ if (cqspi->apb_ahb_hazard)
+ readl(reg_base + CQSPI_REG_INDIRECTWR);
+
while (remaining > 0) {
size_t write_words, mod_bytes;
@@ -1754,6 +1763,8 @@ static int cqspi_probe(struct platform_device *pdev)
cqspi->wr_completion = false;
if (ddata->quirks & CQSPI_SLOW_SRAM)
cqspi->slow_sram = true;
+ if (ddata->quirks & CQSPI_NEEDS_APB_AHB_HAZARD_WAR)
+ cqspi->apb_ahb_hazard = true;
if (of_device_is_compatible(pdev->dev.of_node,
"xlnx,versal-ospi-1.0")) {
@@ -1888,6 +1899,10 @@ static const struct cqspi_driver_platdata jh7110_qspi = {
.quirks = CQSPI_DISABLE_DAC_MODE,
};
+static const struct cqspi_driver_platdata pensando_cdns_qspi = {
+ .quirks = CQSPI_NEEDS_APB_AHB_HAZARD_WAR | CQSPI_DISABLE_DAC_MODE,
+};
+
static const struct of_device_id cqspi_dt_ids[] = {
{
.compatible = "cdns,qspi-nor",
@@ -1917,6 +1932,10 @@ static const struct of_device_id cqspi_dt_ids[] = {
.compatible = "starfive,jh7110-qspi",
.data = &jh7110_qspi,
},
+ {
+ .compatible = "amd,pensando-elba-qspi",
+ .data = &pensando_cdns_qspi,
+ },
{ /* end of table */ }
};
diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c
index 26e663369319..9b021390263e 100644
--- a/drivers/spi/spi-cadence.c
+++ b/drivers/spi/spi-cadence.c
@@ -102,6 +102,7 @@
* @regs: Virtual address of the SPI controller registers
* @ref_clk: Pointer to the peripheral clock
* @pclk: Pointer to the APB clock
+ * @clk_rate: Reference clock frequency, taken from @ref_clk
* @speed_hz: Current SPI bus clock speed in Hz
* @txbuf: Pointer to the TX buffer
* @rxbuf: Pointer to the RX buffer
@@ -316,12 +317,6 @@ static void cdns_spi_process_fifo(struct cdns_spi *xspi, int ntx, int nrx)
xspi->rx_bytes -= nrx;
while (ntx || nrx) {
- /* When xspi in busy condition, bytes may send failed,
- * then spi control did't work thoroughly, add one byte delay
- */
- if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL)
- udelay(10);
-
if (ntx) {
if (xspi->txbuf)
cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++);
@@ -391,6 +386,11 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id)
if (xspi->tx_bytes) {
cdns_spi_process_fifo(xspi, trans_cnt, trans_cnt);
} else {
+ /* Fixed delay due to controller limitation with
+ * RX_NEMPTY incorrect status
+ * Xilinx AR:65885 contains more details
+ */
+ udelay(10);
cdns_spi_process_fifo(xspi, 0, trans_cnt);
cdns_spi_write(xspi, CDNS_SPI_IDR,
CDNS_SPI_IXR_DEFAULT);
@@ -438,12 +438,18 @@ static int cdns_transfer_one(struct spi_controller *ctlr,
cdns_spi_setup_transfer(spi, transfer);
} else {
/* Set TX empty threshold to half of FIFO depth
- * only if TX bytes are more than half FIFO depth.
+ * only if TX bytes are more than FIFO depth.
*/
if (xspi->tx_bytes > xspi->tx_fifo_depth)
cdns_spi_write(xspi, CDNS_SPI_THLD, xspi->tx_fifo_depth >> 1);
}
+ /* When xspi in busy condition, bytes may send failed,
+ * then spi control didn't work thoroughly, add one byte delay
+ */
+ if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL)
+ udelay(10);
+
cdns_spi_process_fifo(xspi, xspi->tx_fifo_depth, 0);
spi_transfer_delay_exec(transfer);
diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index ae3108c70f50..a8ba41ad4541 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -57,21 +57,17 @@ static const struct debugfs_reg32 dw_spi_dbgfs_regs[] = {
DW_SPI_DBGFS_REG("RX_SAMPLE_DLY", DW_SPI_RX_SAMPLE_DLY),
};
-static int dw_spi_debugfs_init(struct dw_spi *dws)
+static void dw_spi_debugfs_init(struct dw_spi *dws)
{
char name[32];
snprintf(name, 32, "dw_spi%d", dws->master->bus_num);
dws->debugfs = debugfs_create_dir(name, NULL);
- if (!dws->debugfs)
- return -ENOMEM;
dws->regset.regs = dw_spi_dbgfs_regs;
dws->regset.nregs = ARRAY_SIZE(dw_spi_dbgfs_regs);
dws->regset.base = dws->regs;
debugfs_create_regset32("registers", 0400, dws->debugfs, &dws->regset);
-
- return 0;
}
static void dw_spi_debugfs_remove(struct dw_spi *dws)
@@ -80,9 +76,8 @@ static void dw_spi_debugfs_remove(struct dw_spi *dws)
}
#else
-static inline int dw_spi_debugfs_init(struct dw_spi *dws)
+static inline void dw_spi_debugfs_init(struct dw_spi *dws)
{
- return 0;
}
static inline void dw_spi_debugfs_remove(struct dw_spi *dws)
@@ -426,7 +421,10 @@ static int dw_spi_transfer_one(struct spi_controller *master,
int ret;
dws->dma_mapped = 0;
- dws->n_bytes = DIV_ROUND_UP(transfer->bits_per_word, BITS_PER_BYTE);
+ dws->n_bytes =
+ roundup_pow_of_two(DIV_ROUND_UP(transfer->bits_per_word,
+ BITS_PER_BYTE));
+
dws->tx = (void *)transfer->tx_buf;
dws->tx_len = transfer->len / dws->n_bytes;
dws->rx = transfer->rx_buf;
diff --git a/drivers/spi/spi-dw-dma.c b/drivers/spi/spi-dw-dma.c
index ababb910b391..df819652901a 100644
--- a/drivers/spi/spi-dw-dma.c
+++ b/drivers/spi/spi-dw-dma.c
@@ -72,12 +72,22 @@ static void dw_spi_dma_maxburst_init(struct dw_spi *dws)
dw_writel(dws, DW_SPI_DMATDLR, dws->txburst);
}
-static void dw_spi_dma_sg_burst_init(struct dw_spi *dws)
+static int dw_spi_dma_caps_init(struct dw_spi *dws)
{
- struct dma_slave_caps tx = {0}, rx = {0};
+ struct dma_slave_caps tx, rx;
+ int ret;
+
+ ret = dma_get_slave_caps(dws->txchan, &tx);
+ if (ret)
+ return ret;
- dma_get_slave_caps(dws->txchan, &tx);
- dma_get_slave_caps(dws->rxchan, &rx);
+ ret = dma_get_slave_caps(dws->rxchan, &rx);
+ if (ret)
+ return ret;
+
+ if (!(tx.directions & BIT(DMA_MEM_TO_DEV) &&
+ rx.directions & BIT(DMA_DEV_TO_MEM)))
+ return -ENXIO;
if (tx.max_sg_burst > 0 && rx.max_sg_burst > 0)
dws->dma_sg_burst = min(tx.max_sg_burst, rx.max_sg_burst);
@@ -87,6 +97,15 @@ static void dw_spi_dma_sg_burst_init(struct dw_spi *dws)
dws->dma_sg_burst = rx.max_sg_burst;
else
dws->dma_sg_burst = 0;
+
+ /*
+ * Assuming both channels belong to the same DMA controller hence the
+ * peripheral side address width capabilities most likely would be
+ * the same.
+ */
+ dws->dma_addr_widths = tx.dst_addr_widths & rx.src_addr_widths;
+
+ return 0;
}
static int dw_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws)
@@ -95,6 +114,7 @@ static int dw_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws)
struct dw_dma_slave dma_rx = { .src_id = 0 }, *rx = &dma_rx;
struct pci_dev *dma_dev;
dma_cap_mask_t mask;
+ int ret = -EBUSY;
/*
* Get pci device for DMA controller, currently it could only
@@ -124,20 +144,25 @@ static int dw_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws)
init_completion(&dws->dma_completion);
- dw_spi_dma_maxburst_init(dws);
+ ret = dw_spi_dma_caps_init(dws);
+ if (ret)
+ goto free_txchan;
- dw_spi_dma_sg_burst_init(dws);
+ dw_spi_dma_maxburst_init(dws);
pci_dev_put(dma_dev);
return 0;
+free_txchan:
+ dma_release_channel(dws->txchan);
+ dws->txchan = NULL;
free_rxchan:
dma_release_channel(dws->rxchan);
dws->rxchan = NULL;
err_exit:
pci_dev_put(dma_dev);
- return -EBUSY;
+ return ret;
}
static int dw_spi_dma_init_generic(struct device *dev, struct dw_spi *dws)
@@ -163,12 +188,17 @@ static int dw_spi_dma_init_generic(struct device *dev, struct dw_spi *dws)
init_completion(&dws->dma_completion);
- dw_spi_dma_maxburst_init(dws);
+ ret = dw_spi_dma_caps_init(dws);
+ if (ret)
+ goto free_txchan;
- dw_spi_dma_sg_burst_init(dws);
+ dw_spi_dma_maxburst_init(dws);
return 0;
+free_txchan:
+ dma_release_channel(dws->txchan);
+ dws->txchan = NULL;
free_rxchan:
dma_release_channel(dws->rxchan);
dws->rxchan = NULL;
@@ -198,22 +228,32 @@ static irqreturn_t dw_spi_dma_transfer_handler(struct dw_spi *dws)
return IRQ_HANDLED;
}
+static enum dma_slave_buswidth dw_spi_dma_convert_width(u8 n_bytes)
+{
+ switch (n_bytes) {
+ case 1:
+ return DMA_SLAVE_BUSWIDTH_1_BYTE;
+ case 2:
+ return DMA_SLAVE_BUSWIDTH_2_BYTES;
+ case 4:
+ return DMA_SLAVE_BUSWIDTH_4_BYTES;
+ default:
+ return DMA_SLAVE_BUSWIDTH_UNDEFINED;
+ }
+}
+
static bool dw_spi_can_dma(struct spi_controller *master,
struct spi_device *spi, struct spi_transfer *xfer)
{
struct dw_spi *dws = spi_controller_get_devdata(master);
+ enum dma_slave_buswidth dma_bus_width;
- return xfer->len > dws->fifo_len;
-}
+ if (xfer->len <= dws->fifo_len)
+ return false;
-static enum dma_slave_buswidth dw_spi_dma_convert_width(u8 n_bytes)
-{
- if (n_bytes == 1)
- return DMA_SLAVE_BUSWIDTH_1_BYTE;
- else if (n_bytes == 2)
- return DMA_SLAVE_BUSWIDTH_2_BYTES;
+ dma_bus_width = dw_spi_dma_convert_width(dws->n_bytes);
- return DMA_SLAVE_BUSWIDTH_UNDEFINED;
+ return dws->dma_addr_widths & BIT(dma_bus_width);
}
static int dw_spi_dma_wait(struct dw_spi *dws, unsigned int len, u32 speed)
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index 15f5e9cb54ad..a963bc96c223 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -236,6 +236,24 @@ static int dw_spi_intel_init(struct platform_device *pdev,
return 0;
}
+/*
+ * DMA-based mem ops are not configured for this device and are not tested.
+ */
+static int dw_spi_mountevans_imc_init(struct platform_device *pdev,
+ struct dw_spi_mmio *dwsmmio)
+{
+ /*
+ * The Intel Mount Evans SoC's Integrated Management Complex DW
+ * apb_ssi_v4.02a controller has an errata where a full TX FIFO can
+ * result in data corruption. The suggested workaround is to never
+ * completely fill the FIFO. The TX FIFO has a size of 32 so the
+ * fifo_len is set to 31.
+ */
+ dwsmmio->dws.fifo_len = 31;
+
+ return 0;
+}
+
static int dw_spi_canaan_k210_init(struct platform_device *pdev,
struct dw_spi_mmio *dwsmmio)
{
@@ -405,6 +423,10 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_hssi_init},
{ .compatible = "intel,keembay-ssi", .data = dw_spi_intel_init},
{ .compatible = "intel,thunderbay-ssi", .data = dw_spi_intel_init},
+ {
+ .compatible = "intel,mountevans-imc-ssi",
+ .data = dw_spi_mountevans_imc_init,
+ },
{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
{ .compatible = "canaan,k210-spi", dw_spi_canaan_k210_init},
{ .compatible = "amd,pensando-elba-spi", .data = dw_spi_elba_init},
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index 9e8eb2b52d5c..3962e6dcf880 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -190,6 +190,7 @@ struct dw_spi {
struct dma_chan *rxchan;
u32 rxburst;
u32 dma_sg_burst;
+ u32 dma_addr_widths;
unsigned long dma_chan_busy;
dma_addr_t dma_addr; /* phy address of the Data register */
const struct dw_spi_dma_ops *dma_ops;
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index 4b70038ceb6b..fb68c72df171 100644
--- a/drivers/spi/spi-fsl-lpspi.c
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -303,6 +303,12 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi)
perclk_rate = clk_get_rate(fsl_lpspi->clk_per);
+ if (!config.speed_hz) {
+ dev_err(fsl_lpspi->dev,
+ "error: the transmission speed provided is 0!\n");
+ return -EINVAL;
+ }
+
if (config.speed_hz > perclk_rate / 2) {
dev_err(fsl_lpspi->dev,
"per-clk should be at least two times of transfer speed");
@@ -911,7 +917,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
if (ret == -EPROBE_DEFER)
goto out_pm_get;
if (ret < 0)
- dev_err(&pdev->dev, "dma setup error %d, use pio\n", ret);
+ dev_warn(&pdev->dev, "dma setup error %d, use pio\n", ret);
else
/*
* disable LPSPI module IRQ when enable DMA mode successfully,
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index b293428760bc..1df9d4844a68 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -35,7 +35,7 @@
#define CS_DEMUX_OUTPUT_SEL GENMASK(3, 0)
#define SE_SPI_TRANS_CFG 0x25c
-#define CS_TOGGLE BIT(0)
+#define CS_TOGGLE BIT(1)
#define SE_SPI_WORD_LEN 0x268
#define WORD_LEN_MSK GENMASK(9, 0)
@@ -97,8 +97,6 @@ struct spi_geni_master {
struct dma_chan *tx;
struct dma_chan *rx;
int cur_xfer_mode;
- dma_addr_t tx_se_dma;
- dma_addr_t rx_se_dma;
};
static int get_spi_clk_cfg(unsigned int speed_hz,
@@ -174,7 +172,7 @@ static void handle_se_timeout(struct spi_master *spi,
unmap_if_dma:
if (mas->cur_xfer_mode == GENI_SE_DMA) {
if (xfer) {
- if (xfer->tx_buf && mas->tx_se_dma) {
+ if (xfer->tx_buf) {
spin_lock_irq(&mas->lock);
reinit_completion(&mas->tx_reset_done);
writel(1, se->base + SE_DMA_TX_FSM_RST);
@@ -182,9 +180,8 @@ unmap_if_dma:
time_left = wait_for_completion_timeout(&mas->tx_reset_done, HZ);
if (!time_left)
dev_err(mas->dev, "DMA TX RESET failed\n");
- geni_se_tx_dma_unprep(se, mas->tx_se_dma, xfer->len);
}
- if (xfer->rx_buf && mas->rx_se_dma) {
+ if (xfer->rx_buf) {
spin_lock_irq(&mas->lock);
reinit_completion(&mas->rx_reset_done);
writel(1, se->base + SE_DMA_RX_FSM_RST);
@@ -192,7 +189,6 @@ unmap_if_dma:
time_left = wait_for_completion_timeout(&mas->rx_reset_done, HZ);
if (!time_left)
dev_err(mas->dev, "DMA RX RESET failed\n");
- geni_se_rx_dma_unprep(se, mas->rx_se_dma, xfer->len);
}
} else {
/*
@@ -523,17 +519,36 @@ static int setup_gsi_xfer(struct spi_transfer *xfer, struct spi_geni_master *mas
return 1;
}
+static u32 get_xfer_len_in_words(struct spi_transfer *xfer,
+ struct spi_geni_master *mas)
+{
+ u32 len;
+
+ if (!(mas->cur_bits_per_word % MIN_WORD_LEN))
+ len = xfer->len * BITS_PER_BYTE / mas->cur_bits_per_word;
+ else
+ len = xfer->len / (mas->cur_bits_per_word / BITS_PER_BYTE + 1);
+ len &= TRANS_LEN_MSK;
+
+ return len;
+}
+
static bool geni_can_dma(struct spi_controller *ctlr,
struct spi_device *slv, struct spi_transfer *xfer)
{
struct spi_geni_master *mas = spi_master_get_devdata(slv->master);
+ u32 len, fifo_size;
- /*
- * Return true if transfer needs to be mapped prior to
- * calling transfer_one which is the case only for GPI_DMA.
- * For SE_DMA mode, map/unmap is done in geni_se_*x_dma_prep.
- */
- return mas->cur_xfer_mode == GENI_GPI_DMA;
+ if (mas->cur_xfer_mode == GENI_GPI_DMA)
+ return true;
+
+ len = get_xfer_len_in_words(xfer, mas);
+ fifo_size = mas->tx_fifo_depth * mas->fifo_width_bits / mas->cur_bits_per_word;
+
+ if (len > fifo_size)
+ return true;
+ else
+ return false;
}
static int spi_geni_prepare_message(struct spi_master *spi,
@@ -774,7 +789,7 @@ static int setup_se_xfer(struct spi_transfer *xfer,
u16 mode, struct spi_master *spi)
{
u32 m_cmd = 0;
- u32 len, fifo_size;
+ u32 len;
struct geni_se *se = &mas->se;
int ret;
@@ -806,11 +821,7 @@ static int setup_se_xfer(struct spi_transfer *xfer,
mas->tx_rem_bytes = 0;
mas->rx_rem_bytes = 0;
- if (!(mas->cur_bits_per_word % MIN_WORD_LEN))
- len = xfer->len * BITS_PER_BYTE / mas->cur_bits_per_word;
- else
- len = xfer->len / (mas->cur_bits_per_word / BITS_PER_BYTE + 1);
- len &= TRANS_LEN_MSK;
+ len = get_xfer_len_in_words(xfer, mas);
mas->cur_xfer = xfer;
if (xfer->tx_buf) {
@@ -825,9 +836,20 @@ static int setup_se_xfer(struct spi_transfer *xfer,
mas->rx_rem_bytes = xfer->len;
}
- /* Select transfer mode based on transfer length */
- fifo_size = mas->tx_fifo_depth * mas->fifo_width_bits / mas->cur_bits_per_word;
- mas->cur_xfer_mode = (len <= fifo_size) ? GENI_SE_FIFO : GENI_SE_DMA;
+ /*
+ * Select DMA mode if sgt are present; and with only 1 entry
+ * This is not a serious limitation because the xfer buffers are
+ * expected to fit into in 1 entry almost always, and if any
+ * doesn't for any reason we fall back to FIFO mode anyway
+ */
+ if (!xfer->tx_sg.nents && !xfer->rx_sg.nents)
+ mas->cur_xfer_mode = GENI_SE_FIFO;
+ else if (xfer->tx_sg.nents > 1 || xfer->rx_sg.nents > 1) {
+ dev_warn_once(mas->dev, "Doing FIFO, cannot handle tx_nents-%d, rx_nents-%d\n",
+ xfer->tx_sg.nents, xfer->rx_sg.nents);
+ mas->cur_xfer_mode = GENI_SE_FIFO;
+ } else
+ mas->cur_xfer_mode = GENI_SE_DMA;
geni_se_select_mode(se, mas->cur_xfer_mode);
/*
@@ -838,35 +860,17 @@ static int setup_se_xfer(struct spi_transfer *xfer,
geni_se_setup_m_cmd(se, m_cmd, FRAGMENTATION);
if (mas->cur_xfer_mode == GENI_SE_DMA) {
- if (m_cmd & SPI_RX_ONLY) {
- ret = geni_se_rx_dma_prep(se, xfer->rx_buf,
- xfer->len, &mas->rx_se_dma);
- if (ret) {
- dev_err(mas->dev, "Failed to setup Rx dma %d\n", ret);
- mas->rx_se_dma = 0;
- goto unlock_and_return;
- }
- }
- if (m_cmd & SPI_TX_ONLY) {
- ret = geni_se_tx_dma_prep(se, (void *)xfer->tx_buf,
- xfer->len, &mas->tx_se_dma);
- if (ret) {
- dev_err(mas->dev, "Failed to setup Tx dma %d\n", ret);
- mas->tx_se_dma = 0;
- if (m_cmd & SPI_RX_ONLY) {
- /* Unmap rx buffer if duplex transfer */
- geni_se_rx_dma_unprep(se, mas->rx_se_dma, xfer->len);
- mas->rx_se_dma = 0;
- }
- goto unlock_and_return;
- }
- }
+ if (m_cmd & SPI_RX_ONLY)
+ geni_se_rx_init_dma(se, sg_dma_address(xfer->rx_sg.sgl),
+ sg_dma_len(xfer->rx_sg.sgl));
+ if (m_cmd & SPI_TX_ONLY)
+ geni_se_tx_init_dma(se, sg_dma_address(xfer->tx_sg.sgl),
+ sg_dma_len(xfer->tx_sg.sgl));
} else if (m_cmd & SPI_TX_ONLY) {
if (geni_spi_handle_tx(mas))
writel(mas->tx_wm, se->base + SE_GENI_TX_WATERMARK_REG);
}
-unlock_and_return:
spin_unlock_irq(&mas->lock);
return ret;
}
@@ -967,14 +971,6 @@ static irqreturn_t geni_spi_isr(int irq, void *data)
if (dma_rx_status & RX_RESET_DONE)
complete(&mas->rx_reset_done);
if (!mas->tx_rem_bytes && !mas->rx_rem_bytes && xfer) {
- if (xfer->tx_buf && mas->tx_se_dma) {
- geni_se_tx_dma_unprep(se, mas->tx_se_dma, xfer->len);
- mas->tx_se_dma = 0;
- }
- if (xfer->rx_buf && mas->rx_se_dma) {
- geni_se_rx_dma_unprep(se, mas->rx_se_dma, xfer->len);
- mas->rx_se_dma = 0;
- }
spi_finalize_current_transfer(spi);
mas->cur_xfer = NULL;
}
@@ -1059,6 +1055,7 @@ static int spi_geni_probe(struct platform_device *pdev)
spi->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
spi->num_chipselect = 4;
spi->max_speed_hz = 50000000;
+ spi->max_dma_len = 0xffff0; /* 24 bits for tx/rx dma length */
spi->prepare_message = spi_geni_prepare_message;
spi->transfer_one = spi_geni_transfer_one;
spi->can_dma = geni_can_dma;
@@ -1100,6 +1097,12 @@ static int spi_geni_probe(struct platform_device *pdev)
if (mas->cur_xfer_mode == GENI_SE_FIFO)
spi->set_cs = spi_geni_set_cs;
+ /*
+ * TX is required per GSI spec, see setup_gsi_xfer().
+ */
+ if (mas->cur_xfer_mode == GENI_GPI_DMA)
+ spi->flags = SPI_CONTROLLER_MUST_TX;
+
ret = request_irq(mas->irq, geni_spi_isr, 0, dev_name(dev), spi);
if (ret)
goto spi_geni_release_dma;
diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c
index 524eadbef87b..2b4b3d2a22b8 100644
--- a/drivers/spi/spi-hisi-kunpeng.c
+++ b/drivers/spi/spi-hisi-kunpeng.c
@@ -169,7 +169,7 @@ static int hisi_spi_debugfs_init(struct hisi_spi *hs)
master = container_of(hs->dev, struct spi_controller, dev);
snprintf(name, 32, "hisi_spi%d", master->bus_num);
hs->debugfs = debugfs_create_dir(name, NULL);
- if (!hs->debugfs)
+ if (IS_ERR(hs->debugfs))
return -ENOMEM;
hs->regset.regs = hisi_spi_regs;
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 34e5f81ec431..528ae46c087f 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -281,6 +281,7 @@ static bool spi_imx_can_dma(struct spi_controller *controller, struct spi_device
#define MX51_ECSPI_CONFIG_SCLKPOL(cs) (1 << ((cs & 3) + 4))
#define MX51_ECSPI_CONFIG_SBBCTRL(cs) (1 << ((cs & 3) + 8))
#define MX51_ECSPI_CONFIG_SSBPOL(cs) (1 << ((cs & 3) + 12))
+#define MX51_ECSPI_CONFIG_DATACTL(cs) (1 << ((cs & 3) + 16))
#define MX51_ECSPI_CONFIG_SCLKCTL(cs) (1 << ((cs & 3) + 20))
#define MX51_ECSPI_INT 0x10
@@ -516,6 +517,13 @@ static void mx51_ecspi_disable(struct spi_imx_data *spi_imx)
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
}
+static int mx51_ecspi_channel(const struct spi_device *spi)
+{
+ if (!spi_get_csgpiod(spi, 0))
+ return spi_get_chipselect(spi, 0);
+ return spi->controller->unused_native_cs;
+}
+
static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
struct spi_message *msg)
{
@@ -526,6 +534,7 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
u32 testreg, delay;
u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
u32 current_cfg = cfg;
+ int channel = mx51_ecspi_channel(spi);
/* set Master or Slave mode */
if (spi_imx->slave_mode)
@@ -540,7 +549,7 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
ctrl |= MX51_ECSPI_CTRL_DRCTL(spi_imx->spi_drctl);
/* set chip select to use */
- ctrl |= MX51_ECSPI_CTRL_CS(spi_get_chipselect(spi, 0));
+ ctrl |= MX51_ECSPI_CTRL_CS(channel);
/*
* The ctrl register must be written first, with the EN bit set other
@@ -561,22 +570,27 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
* BURST_LENGTH + 1 bits are received
*/
if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx))
- cfg &= ~MX51_ECSPI_CONFIG_SBBCTRL(spi_get_chipselect(spi, 0));
+ cfg &= ~MX51_ECSPI_CONFIG_SBBCTRL(channel);
else
- cfg |= MX51_ECSPI_CONFIG_SBBCTRL(spi_get_chipselect(spi, 0));
+ cfg |= MX51_ECSPI_CONFIG_SBBCTRL(channel);
if (spi->mode & SPI_CPOL) {
- cfg |= MX51_ECSPI_CONFIG_SCLKPOL(spi_get_chipselect(spi, 0));
- cfg |= MX51_ECSPI_CONFIG_SCLKCTL(spi_get_chipselect(spi, 0));
+ cfg |= MX51_ECSPI_CONFIG_SCLKPOL(channel);
+ cfg |= MX51_ECSPI_CONFIG_SCLKCTL(channel);
} else {
- cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(spi_get_chipselect(spi, 0));
- cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(spi_get_chipselect(spi, 0));
+ cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(channel);
+ cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(channel);
}
+ if (spi->mode & SPI_MOSI_IDLE_LOW)
+ cfg |= MX51_ECSPI_CONFIG_DATACTL(channel);
+ else
+ cfg &= ~MX51_ECSPI_CONFIG_DATACTL(channel);
+
if (spi->mode & SPI_CS_HIGH)
- cfg |= MX51_ECSPI_CONFIG_SSBPOL(spi_get_chipselect(spi, 0));
+ cfg |= MX51_ECSPI_CONFIG_SSBPOL(channel);
else
- cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi_get_chipselect(spi, 0));
+ cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(channel);
if (cfg == current_cfg)
return 0;
@@ -621,14 +635,15 @@ static void mx51_configure_cpha(struct spi_imx_data *spi_imx,
bool cpha = (spi->mode & SPI_CPHA);
bool flip_cpha = (spi->mode & SPI_RX_CPHA_FLIP) && spi_imx->rx_only;
u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
+ int channel = mx51_ecspi_channel(spi);
/* Flip cpha logical value iff flip_cpha */
cpha ^= flip_cpha;
if (cpha)
- cfg |= MX51_ECSPI_CONFIG_SCLKPHA(spi_get_chipselect(spi, 0));
+ cfg |= MX51_ECSPI_CONFIG_SCLKPHA(channel);
else
- cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(spi_get_chipselect(spi, 0));
+ cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(channel);
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
}
@@ -1737,20 +1752,21 @@ static int spi_imx_probe(struct platform_device *pdev)
else
controller->num_chipselect = 3;
- spi_imx->controller->transfer_one = spi_imx_transfer_one;
- spi_imx->controller->setup = spi_imx_setup;
- spi_imx->controller->cleanup = spi_imx_cleanup;
- spi_imx->controller->prepare_message = spi_imx_prepare_message;
- spi_imx->controller->unprepare_message = spi_imx_unprepare_message;
- spi_imx->controller->slave_abort = spi_imx_slave_abort;
- spi_imx->controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
+ controller->transfer_one = spi_imx_transfer_one;
+ controller->setup = spi_imx_setup;
+ controller->cleanup = spi_imx_cleanup;
+ controller->prepare_message = spi_imx_prepare_message;
+ controller->unprepare_message = spi_imx_unprepare_message;
+ controller->slave_abort = spi_imx_slave_abort;
+ controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS |
+ SPI_MOSI_IDLE_LOW;
if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx) ||
is_imx53_ecspi(spi_imx))
- spi_imx->controller->mode_bits |= SPI_LOOP | SPI_READY;
+ controller->mode_bits |= SPI_LOOP | SPI_READY;
if (is_imx51_ecspi(spi_imx) || is_imx53_ecspi(spi_imx))
- spi_imx->controller->mode_bits |= SPI_RX_CPHA_FLIP;
+ controller->mode_bits |= SPI_RX_CPHA_FLIP;
if (is_imx51_ecspi(spi_imx) &&
device_property_read_u32(&pdev->dev, "cs-gpios", NULL))
@@ -1759,7 +1775,12 @@ static int spi_imx_probe(struct platform_device *pdev)
* setting the burst length to the word size. This is
* considerably faster than manually controlling the CS.
*/
- spi_imx->controller->mode_bits |= SPI_CS_WORD;
+ controller->mode_bits |= SPI_CS_WORD;
+
+ if (is_imx51_ecspi(spi_imx) || is_imx53_ecspi(spi_imx)) {
+ controller->max_native_cs = 4;
+ controller->flags |= SPI_MASTER_GPIO_SS;
+ }
spi_imx->spi_drctl = spi_drctl;
diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
index d7432e2219d8..39272ad6641b 100644
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -1144,7 +1144,8 @@ static int mtk_spi_probe(struct platform_device *pdev)
if (mdata->dev_comp->must_tx)
master->flags = SPI_MASTER_MUST_TX;
if (mdata->dev_comp->ipm_design)
- master->mode_bits |= SPI_LOOP;
+ master->mode_bits |= SPI_LOOP | SPI_RX_DUAL | SPI_TX_DUAL |
+ SPI_RX_QUAD | SPI_TX_QUAD;
if (mdata->dev_comp->ipm_design) {
mdata->dev = dev;
@@ -1269,7 +1270,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
return 0;
}
-static int mtk_spi_remove(struct platform_device *pdev)
+static void mtk_spi_remove(struct platform_device *pdev)
{
struct spi_master *master = platform_get_drvdata(pdev);
struct mtk_spi *mdata = spi_master_get_devdata(master);
@@ -1278,21 +1279,25 @@ static int mtk_spi_remove(struct platform_device *pdev)
if (mdata->use_spimem && !completion_done(&mdata->spimem_done))
complete(&mdata->spimem_done);
- ret = pm_runtime_resume_and_get(&pdev->dev);
- if (ret < 0)
- return ret;
-
- mtk_spi_reset(mdata);
+ ret = pm_runtime_get_sync(&pdev->dev);
+ if (ret < 0) {
+ dev_warn(&pdev->dev, "Failed to resume hardware (%pe)\n", ERR_PTR(ret));
+ } else {
+ /*
+ * If pm runtime resume failed, clks are disabled and
+ * unprepared. So don't access the hardware and skip clk
+ * unpreparing.
+ */
+ mtk_spi_reset(mdata);
- if (mdata->dev_comp->no_need_unprepare) {
- clk_unprepare(mdata->spi_clk);
- clk_unprepare(mdata->spi_hclk);
+ if (mdata->dev_comp->no_need_unprepare) {
+ clk_unprepare(mdata->spi_clk);
+ clk_unprepare(mdata->spi_hclk);
+ }
}
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -1311,7 +1316,7 @@ static int mtk_spi_suspend(struct device *dev)
clk_disable_unprepare(mdata->spi_hclk);
}
- return ret;
+ return 0;
}
static int mtk_spi_resume(struct device *dev)
@@ -1412,7 +1417,7 @@ static struct platform_driver mtk_spi_driver = {
.of_match_table = mtk_spi_of_match,
},
.probe = mtk_spi_probe,
- .remove = mtk_spi_remove,
+ .remove_new = mtk_spi_remove,
};
module_platform_driver(mtk_spi_driver);
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 982407bc5d9f..1af75eff26b6 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -2217,8 +2217,8 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
amba_set_drvdata(adev, pl022);
status = devm_spi_register_master(&adev->dev, master);
if (status != 0) {
- dev_err(&adev->dev,
- "probe - problem registering spi master\n");
+ dev_err_probe(&adev->dev, status,
+ "problem registering spi master\n");
goto err_spi_register;
}
dev_dbg(dev, "probe succeeded\n");
diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c
index fab155389999..1954c39b3d08 100644
--- a/drivers/spi/spi-qcom-qspi.c
+++ b/drivers/spi/spi-qcom-qspi.c
@@ -2,6 +2,8 @@
// Copyright (c) 2017-2018, The Linux foundation. All rights reserved.
#include <linux/clk.h>
+#include <linux/dmapool.h>
+#include <linux/dma-mapping.h>
#include <linux/interconnect.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -62,11 +64,12 @@
#define WR_FIFO_FULL BIT(10)
#define WR_FIFO_OVERRUN BIT(11)
#define TRANSACTION_DONE BIT(16)
+#define DMA_CHAIN_DONE BIT(31)
#define QSPI_ERR_IRQS (RESP_FIFO_UNDERRUN | HRESP_FROM_NOC_ERR | \
WR_FIFO_OVERRUN)
#define QSPI_ALL_IRQS (QSPI_ERR_IRQS | RESP_FIFO_RDY | \
WR_FIFO_EMPTY | WR_FIFO_FULL | \
- TRANSACTION_DONE)
+ TRANSACTION_DONE | DMA_CHAIN_DONE)
#define PIO_XFER_CTRL 0x0014
#define REQUEST_COUNT_MSK 0xffff
@@ -108,18 +111,34 @@
#define RD_FIFO_RESET 0x0030
#define RESET_FIFO BIT(0)
+#define NEXT_DMA_DESC_ADDR 0x0040
+#define CURRENT_DMA_DESC_ADDR 0x0044
+#define CURRENT_MEM_ADDR 0x0048
+
#define CUR_MEM_ADDR 0x0048
#define HW_VERSION 0x004c
#define RD_FIFO 0x0050
#define SAMPLING_CLK_CFG 0x0090
#define SAMPLING_CLK_STATUS 0x0094
+#define QSPI_ALIGN_REQ 32
enum qspi_dir {
QSPI_READ,
QSPI_WRITE,
};
+struct qspi_cmd_desc {
+ u32 data_address;
+ u32 next_descriptor;
+ u32 direction:1;
+ u32 multi_io_mode:3;
+ u32 reserved1:4;
+ u32 fragment:1;
+ u32 reserved2:7;
+ u32 length:16;
+};
+
struct qspi_xfer {
union {
const void *tx_buf;
@@ -137,11 +156,23 @@ enum qspi_clocks {
QSPI_NUM_CLKS
};
+/*
+ * Number of entries in sgt returned from spi framework that-
+ * will be supported. Can be modified as required.
+ * In practice, given max_dma_len is 64KB, the number of
+ * entries is not expected to exceed 1.
+ */
+#define QSPI_MAX_SG 5
+
struct qcom_qspi {
void __iomem *base;
struct device *dev;
struct clk_bulk_data *clks;
struct qspi_xfer xfer;
+ struct dma_pool *dma_cmd_pool;
+ dma_addr_t dma_cmd_desc[QSPI_MAX_SG];
+ void *virt_cmd_desc[QSPI_MAX_SG];
+ unsigned int n_cmd_desc;
struct icc_path *icc_path_cpu_to_qspi;
unsigned long last_speed;
/* Lock to protect data accessed by IRQs */
@@ -153,21 +184,22 @@ static u32 qspi_buswidth_to_iomode(struct qcom_qspi *ctrl,
{
switch (buswidth) {
case 1:
- return SDR_1BIT << MULTI_IO_MODE_SHFT;
+ return SDR_1BIT;
case 2:
- return SDR_2BIT << MULTI_IO_MODE_SHFT;
+ return SDR_2BIT;
case 4:
- return SDR_4BIT << MULTI_IO_MODE_SHFT;
+ return SDR_4BIT;
default:
dev_warn_once(ctrl->dev,
"Unexpected bus width: %u\n", buswidth);
- return SDR_1BIT << MULTI_IO_MODE_SHFT;
+ return SDR_1BIT;
}
}
static void qcom_qspi_pio_xfer_cfg(struct qcom_qspi *ctrl)
{
u32 pio_xfer_cfg;
+ u32 iomode;
const struct qspi_xfer *xfer;
xfer = &ctrl->xfer;
@@ -179,7 +211,8 @@ static void qcom_qspi_pio_xfer_cfg(struct qcom_qspi *ctrl)
else
pio_xfer_cfg |= TRANSFER_FRAGMENT;
pio_xfer_cfg &= ~MULTI_IO_MODE_MSK;
- pio_xfer_cfg |= qspi_buswidth_to_iomode(ctrl, xfer->buswidth);
+ iomode = qspi_buswidth_to_iomode(ctrl, xfer->buswidth);
+ pio_xfer_cfg |= iomode << MULTI_IO_MODE_SHFT;
writel(pio_xfer_cfg, ctrl->base + PIO_XFER_CFG);
}
@@ -217,12 +250,22 @@ static void qcom_qspi_pio_xfer(struct qcom_qspi *ctrl)
static void qcom_qspi_handle_err(struct spi_master *master,
struct spi_message *msg)
{
+ u32 int_status;
struct qcom_qspi *ctrl = spi_master_get_devdata(master);
unsigned long flags;
+ int i;
spin_lock_irqsave(&ctrl->lock, flags);
writel(0, ctrl->base + MSTR_INT_EN);
+ int_status = readl(ctrl->base + MSTR_INT_STATUS);
+ writel(int_status, ctrl->base + MSTR_INT_STATUS);
ctrl->xfer.rem_bytes = 0;
+
+ /* free cmd descriptors if they are around (DMA mode) */
+ for (i = 0; i < ctrl->n_cmd_desc; i++)
+ dma_pool_free(ctrl->dma_cmd_pool, ctrl->virt_cmd_desc[i],
+ ctrl->dma_cmd_desc[i]);
+ ctrl->n_cmd_desc = 0;
spin_unlock_irqrestore(&ctrl->lock, flags);
}
@@ -242,7 +285,7 @@ static int qcom_qspi_set_speed(struct qcom_qspi *ctrl, unsigned long speed_hz)
}
/*
- * Set BW quota for CPU as driver supports FIFO mode only.
+ * Set BW quota for CPU.
* We don't have explicit peak requirement so keep it equal to avg_bw.
*/
avg_bw_cpu = Bps_to_icc(speed_hz);
@@ -258,6 +301,116 @@ static int qcom_qspi_set_speed(struct qcom_qspi *ctrl, unsigned long speed_hz)
return 0;
}
+static int qcom_qspi_alloc_desc(struct qcom_qspi *ctrl, dma_addr_t dma_ptr,
+ uint32_t n_bytes)
+{
+ struct qspi_cmd_desc *virt_cmd_desc, *prev;
+ dma_addr_t dma_cmd_desc;
+
+ /* allocate for dma cmd descriptor */
+ virt_cmd_desc = dma_pool_alloc(ctrl->dma_cmd_pool, GFP_ATOMIC | __GFP_ZERO, &dma_cmd_desc);
+ if (!virt_cmd_desc) {
+ dev_warn_once(ctrl->dev, "Couldn't find memory for descriptor\n");
+ return -EAGAIN;
+ }
+
+ ctrl->virt_cmd_desc[ctrl->n_cmd_desc] = virt_cmd_desc;
+ ctrl->dma_cmd_desc[ctrl->n_cmd_desc] = dma_cmd_desc;
+ ctrl->n_cmd_desc++;
+
+ /* setup cmd descriptor */
+ virt_cmd_desc->data_address = dma_ptr;
+ virt_cmd_desc->direction = ctrl->xfer.dir;
+ virt_cmd_desc->multi_io_mode = qspi_buswidth_to_iomode(ctrl, ctrl->xfer.buswidth);
+ virt_cmd_desc->fragment = !ctrl->xfer.is_last;
+ virt_cmd_desc->length = n_bytes;
+
+ /* update previous descriptor */
+ if (ctrl->n_cmd_desc >= 2) {
+ prev = (ctrl->virt_cmd_desc)[ctrl->n_cmd_desc - 2];
+ prev->next_descriptor = dma_cmd_desc;
+ prev->fragment = 1;
+ }
+
+ return 0;
+}
+
+static int qcom_qspi_setup_dma_desc(struct qcom_qspi *ctrl,
+ struct spi_transfer *xfer)
+{
+ int ret;
+ struct sg_table *sgt;
+ dma_addr_t dma_ptr_sg;
+ unsigned int dma_len_sg;
+ int i;
+
+ if (ctrl->n_cmd_desc) {
+ dev_err(ctrl->dev, "Remnant dma buffers n_cmd_desc-%d\n", ctrl->n_cmd_desc);
+ return -EIO;
+ }
+
+ sgt = (ctrl->xfer.dir == QSPI_READ) ? &xfer->rx_sg : &xfer->tx_sg;
+ if (!sgt->nents || sgt->nents > QSPI_MAX_SG) {
+ dev_warn_once(ctrl->dev, "Cannot handle %d entries in scatter list\n", sgt->nents);
+ return -EAGAIN;
+ }
+
+ for (i = 0; i < sgt->nents; i++) {
+ dma_ptr_sg = sg_dma_address(sgt->sgl + i);
+ dma_len_sg = sg_dma_len(sgt->sgl + i);
+ if (!IS_ALIGNED(dma_ptr_sg, QSPI_ALIGN_REQ)) {
+ dev_warn_once(ctrl->dev, "dma_address not aligned to %d\n", QSPI_ALIGN_REQ);
+ return -EAGAIN;
+ }
+ /*
+ * When reading with DMA the controller writes to memory 1 word
+ * at a time. If the length isn't a multiple of 4 bytes then
+ * the controller can clobber the things later in memory.
+ * Fallback to PIO to be safe.
+ */
+ if (ctrl->xfer.dir == QSPI_READ && (dma_len_sg & 0x03)) {
+ dev_warn_once(ctrl->dev, "fallback to PIO for read of size %#010x\n",
+ dma_len_sg);
+ return -EAGAIN;
+ }
+ }
+
+ for (i = 0; i < sgt->nents; i++) {
+ dma_ptr_sg = sg_dma_address(sgt->sgl + i);
+ dma_len_sg = sg_dma_len(sgt->sgl + i);
+
+ ret = qcom_qspi_alloc_desc(ctrl, dma_ptr_sg, dma_len_sg);
+ if (ret)
+ goto cleanup;
+ }
+ return 0;
+
+cleanup:
+ for (i = 0; i < ctrl->n_cmd_desc; i++)
+ dma_pool_free(ctrl->dma_cmd_pool, ctrl->virt_cmd_desc[i],
+ ctrl->dma_cmd_desc[i]);
+ ctrl->n_cmd_desc = 0;
+ return ret;
+}
+
+static void qcom_qspi_dma_xfer(struct qcom_qspi *ctrl)
+{
+ /* Setup new interrupts */
+ writel(DMA_CHAIN_DONE, ctrl->base + MSTR_INT_EN);
+
+ /* kick off transfer */
+ writel((u32)((ctrl->dma_cmd_desc)[0]), ctrl->base + NEXT_DMA_DESC_ADDR);
+}
+
+/* Switch to DMA if transfer length exceeds this */
+#define QSPI_MAX_BYTES_FIFO 64
+
+static bool qcom_qspi_can_dma(struct spi_controller *ctlr,
+ struct spi_device *slv, struct spi_transfer *xfer)
+{
+ return xfer->len > QSPI_MAX_BYTES_FIFO;
+}
+
static int qcom_qspi_transfer_one(struct spi_master *master,
struct spi_device *slv,
struct spi_transfer *xfer)
@@ -266,6 +419,7 @@ static int qcom_qspi_transfer_one(struct spi_master *master,
int ret;
unsigned long speed_hz;
unsigned long flags;
+ u32 mstr_cfg;
speed_hz = slv->max_speed_hz;
if (xfer->speed_hz)
@@ -276,6 +430,7 @@ static int qcom_qspi_transfer_one(struct spi_master *master,
return ret;
spin_lock_irqsave(&ctrl->lock, flags);
+ mstr_cfg = readl(ctrl->base + MSTR_CONFIG);
/* We are half duplex, so either rx or tx will be set */
if (xfer->rx_buf) {
@@ -290,10 +445,38 @@ static int qcom_qspi_transfer_one(struct spi_master *master,
ctrl->xfer.is_last = list_is_last(&xfer->transfer_list,
&master->cur_msg->transfers);
ctrl->xfer.rem_bytes = xfer->len;
+
+ if (xfer->rx_sg.nents || xfer->tx_sg.nents) {
+ /* do DMA transfer */
+ if (!(mstr_cfg & DMA_ENABLE)) {
+ mstr_cfg |= DMA_ENABLE;
+ writel(mstr_cfg, ctrl->base + MSTR_CONFIG);
+ }
+
+ ret = qcom_qspi_setup_dma_desc(ctrl, xfer);
+ if (ret != -EAGAIN) {
+ if (!ret) {
+ dma_wmb();
+ qcom_qspi_dma_xfer(ctrl);
+ }
+ goto exit;
+ }
+ dev_warn_once(ctrl->dev, "DMA failure, falling back to PIO\n");
+ ret = 0; /* We'll retry w/ PIO */
+ }
+
+ if (mstr_cfg & DMA_ENABLE) {
+ mstr_cfg &= ~DMA_ENABLE;
+ writel(mstr_cfg, ctrl->base + MSTR_CONFIG);
+ }
qcom_qspi_pio_xfer(ctrl);
+exit:
spin_unlock_irqrestore(&ctrl->lock, flags);
+ if (ret)
+ return ret;
+
/* We'll call spi_finalize_current_transfer() when done */
return 1;
}
@@ -328,6 +511,16 @@ static int qcom_qspi_prepare_message(struct spi_master *master,
return 0;
}
+static int qcom_qspi_alloc_dma(struct qcom_qspi *ctrl)
+{
+ ctrl->dma_cmd_pool = dmam_pool_create("qspi cmd desc pool",
+ ctrl->dev, sizeof(struct qspi_cmd_desc), 0, 0);
+ if (!ctrl->dma_cmd_pool)
+ return -ENOMEM;
+
+ return 0;
+}
+
static irqreturn_t pio_read(struct qcom_qspi *ctrl)
{
u32 rd_fifo_status;
@@ -426,6 +619,10 @@ static irqreturn_t qcom_qspi_irq(int irq, void *dev_id)
int_status = readl(ctrl->base + MSTR_INT_STATUS);
writel(int_status, ctrl->base + MSTR_INT_STATUS);
+ /* Ignore disabled interrupts */
+ int_status &= readl(ctrl->base + MSTR_INT_EN);
+
+ /* PIO mode handling */
if (ctrl->xfer.dir == QSPI_WRITE) {
if (int_status & WR_FIFO_EMPTY)
ret = pio_write(ctrl);
@@ -449,10 +646,50 @@ static irqreturn_t qcom_qspi_irq(int irq, void *dev_id)
spi_finalize_current_transfer(dev_get_drvdata(ctrl->dev));
}
+ /* DMA mode handling */
+ if (int_status & DMA_CHAIN_DONE) {
+ int i;
+
+ writel(0, ctrl->base + MSTR_INT_EN);
+ ctrl->xfer.rem_bytes = 0;
+
+ for (i = 0; i < ctrl->n_cmd_desc; i++)
+ dma_pool_free(ctrl->dma_cmd_pool, ctrl->virt_cmd_desc[i],
+ ctrl->dma_cmd_desc[i]);
+ ctrl->n_cmd_desc = 0;
+
+ ret = IRQ_HANDLED;
+ spi_finalize_current_transfer(dev_get_drvdata(ctrl->dev));
+ }
+
spin_unlock(&ctrl->lock);
return ret;
}
+static int qcom_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
+{
+ /*
+ * If qcom_qspi_can_dma() is going to return false we don't need to
+ * adjust anything.
+ */
+ if (op->data.nbytes <= QSPI_MAX_BYTES_FIFO)
+ return 0;
+
+ /*
+ * When reading, the transfer needs to be a multiple of 4 bytes so
+ * shrink the transfer if that's not true. The caller will then do a
+ * second transfer to finish things up.
+ */
+ if (op->data.dir == SPI_MEM_DATA_IN && (op->data.nbytes & 0x3))
+ op->data.nbytes &= ~0x3;
+
+ return 0;
+}
+
+static const struct spi_controller_mem_ops qcom_qspi_mem_ops = {
+ .adjust_op_size = qcom_qspi_adjust_op_size,
+};
+
static int qcom_qspi_probe(struct platform_device *pdev)
{
int ret;
@@ -517,7 +754,13 @@ static int qcom_qspi_probe(struct platform_device *pdev)
return ret;
}
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ if (ret)
+ return dev_err_probe(dev, ret, "could not set DMA mask\n");
+
master->max_speed_hz = 300000000;
+ master->max_dma_len = 65536; /* as per HPG */
+ master->dma_alignment = QSPI_ALIGN_REQ;
master->num_chipselect = QSPI_NUM_CS;
master->bus_num = -1;
master->dev.of_node = pdev->dev.of_node;
@@ -528,7 +771,10 @@ static int qcom_qspi_probe(struct platform_device *pdev)
master->prepare_message = qcom_qspi_prepare_message;
master->transfer_one = qcom_qspi_transfer_one;
master->handle_err = qcom_qspi_handle_err;
+ if (of_property_read_bool(pdev->dev.of_node, "iommus"))
+ master->can_dma = qcom_qspi_can_dma;
master->auto_runtime_pm = true;
+ master->mem_ops = &qcom_qspi_mem_ops;
ret = devm_pm_opp_set_clkname(&pdev->dev, "core");
if (ret)
@@ -540,6 +786,10 @@ static int qcom_qspi_probe(struct platform_device *pdev)
return ret;
}
+ ret = qcom_qspi_alloc_dma(ctrl);
+ if (ret)
+ return ret;
+
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, 250);
pm_runtime_enable(dev);
diff --git a/drivers/spi/spi-rzv2m-csi.c b/drivers/spi/spi-rzv2m-csi.c
new file mode 100644
index 000000000000..14ad65da930d
--- /dev/null
+++ b/drivers/spi/spi-rzv2m-csi.c
@@ -0,0 +1,667 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Renesas RZ/V2M Clocked Serial Interface (CSI) driver
+ *
+ * Copyright (C) 2023 Renesas Electronics Corporation
+ */
+
+#include <linux/clk.h>
+#include <linux/count_zeros.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/spi/spi.h>
+
+/* Registers */
+#define CSI_MODE 0x00 /* CSI mode control */
+#define CSI_CLKSEL 0x04 /* CSI clock select */
+#define CSI_CNT 0x08 /* CSI control */
+#define CSI_INT 0x0C /* CSI interrupt status */
+#define CSI_IFIFOL 0x10 /* CSI receive FIFO level display */
+#define CSI_OFIFOL 0x14 /* CSI transmit FIFO level display */
+#define CSI_IFIFO 0x18 /* CSI receive window */
+#define CSI_OFIFO 0x1C /* CSI transmit window */
+#define CSI_FIFOTRG 0x20 /* CSI FIFO trigger level */
+
+/* CSI_MODE */
+#define CSI_MODE_CSIE BIT(7)
+#define CSI_MODE_TRMD BIT(6)
+#define CSI_MODE_CCL BIT(5)
+#define CSI_MODE_DIR BIT(4)
+#define CSI_MODE_CSOT BIT(0)
+
+#define CSI_MODE_SETUP 0x00000040
+
+/* CSI_CLKSEL */
+#define CSI_CLKSEL_CKP BIT(17)
+#define CSI_CLKSEL_DAP BIT(16)
+#define CSI_CLKSEL_SLAVE BIT(15)
+#define CSI_CLKSEL_CKS GENMASK(14, 1)
+
+/* CSI_CNT */
+#define CSI_CNT_CSIRST BIT(28)
+#define CSI_CNT_R_TRGEN BIT(19)
+#define CSI_CNT_UNDER_E BIT(13)
+#define CSI_CNT_OVERF_E BIT(12)
+#define CSI_CNT_TREND_E BIT(9)
+#define CSI_CNT_CSIEND_E BIT(8)
+#define CSI_CNT_T_TRGR_E BIT(4)
+#define CSI_CNT_R_TRGR_E BIT(0)
+
+/* CSI_INT */
+#define CSI_INT_UNDER BIT(13)
+#define CSI_INT_OVERF BIT(12)
+#define CSI_INT_TREND BIT(9)
+#define CSI_INT_CSIEND BIT(8)
+#define CSI_INT_T_TRGR BIT(4)
+#define CSI_INT_R_TRGR BIT(0)
+
+/* CSI_FIFOTRG */
+#define CSI_FIFOTRG_R_TRG GENMASK(2, 0)
+
+#define CSI_FIFO_SIZE_BYTES 32
+#define CSI_FIFO_HALF_SIZE 16
+#define CSI_EN_DIS_TIMEOUT_US 100
+#define CSI_CKS_MAX 0x3FFF
+
+#define UNDERRUN_ERROR BIT(0)
+#define OVERFLOW_ERROR BIT(1)
+#define TX_TIMEOUT_ERROR BIT(2)
+#define RX_TIMEOUT_ERROR BIT(3)
+
+#define CSI_MAX_SPI_SCKO 8000000
+
+struct rzv2m_csi_priv {
+ void __iomem *base;
+ struct clk *csiclk;
+ struct clk *pclk;
+ struct device *dev;
+ struct spi_controller *controller;
+ const u8 *txbuf;
+ u8 *rxbuf;
+ int buffer_len;
+ int bytes_sent;
+ int bytes_received;
+ int bytes_to_transfer;
+ int words_to_transfer;
+ unsigned char bytes_per_word;
+ wait_queue_head_t wait;
+ u8 errors;
+ u32 status;
+};
+
+static const unsigned char x_trg[] = {
+ 0, 1, 1, 2, 2, 2, 2, 3,
+ 3, 3, 3, 3, 3, 3, 3, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 5
+};
+
+static const unsigned char x_trg_words[] = {
+ 1, 2, 2, 4, 4, 4, 4, 8,
+ 8, 8, 8, 8, 8, 8, 8, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 32
+};
+
+static void rzv2m_csi_reg_write_bit(const struct rzv2m_csi_priv *csi,
+ int reg_offs, int bit_mask, u32 value)
+{
+ int nr_zeros;
+ u32 tmp;
+
+ nr_zeros = count_trailing_zeros(bit_mask);
+ value <<= nr_zeros;
+
+ tmp = (readl(csi->base + reg_offs) & ~bit_mask) | value;
+ writel(tmp, csi->base + reg_offs);
+}
+
+static int rzv2m_csi_sw_reset(struct rzv2m_csi_priv *csi, int assert)
+{
+ u32 reg;
+
+ rzv2m_csi_reg_write_bit(csi, CSI_CNT, CSI_CNT_CSIRST, assert);
+
+ if (assert) {
+ return readl_poll_timeout(csi->base + CSI_MODE, reg,
+ !(reg & CSI_MODE_CSOT), 0,
+ CSI_EN_DIS_TIMEOUT_US);
+ }
+
+ return 0;
+}
+
+static int rzv2m_csi_start_stop_operation(const struct rzv2m_csi_priv *csi,
+ int enable, bool wait)
+{
+ u32 reg;
+
+ rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_CSIE, enable);
+
+ if (!enable && wait)
+ return readl_poll_timeout(csi->base + CSI_MODE, reg,
+ !(reg & CSI_MODE_CSOT), 0,
+ CSI_EN_DIS_TIMEOUT_US);
+
+ return 0;
+}
+
+static int rzv2m_csi_fill_txfifo(struct rzv2m_csi_priv *csi)
+{
+ int i;
+
+ if (readl(csi->base + CSI_OFIFOL))
+ return -EIO;
+
+ if (csi->bytes_per_word == 2) {
+ u16 *buf = (u16 *)csi->txbuf;
+
+ for (i = 0; i < csi->words_to_transfer; i++)
+ writel(buf[i], csi->base + CSI_OFIFO);
+ } else {
+ u8 *buf = (u8 *)csi->txbuf;
+
+ for (i = 0; i < csi->words_to_transfer; i++)
+ writel(buf[i], csi->base + CSI_OFIFO);
+ }
+
+ csi->txbuf += csi->bytes_to_transfer;
+ csi->bytes_sent += csi->bytes_to_transfer;
+
+ return 0;
+}
+
+static int rzv2m_csi_read_rxfifo(struct rzv2m_csi_priv *csi)
+{
+ int i;
+
+ if (readl(csi->base + CSI_IFIFOL) != csi->bytes_to_transfer)
+ return -EIO;
+
+ if (csi->bytes_per_word == 2) {
+ u16 *buf = (u16 *)csi->rxbuf;
+
+ for (i = 0; i < csi->words_to_transfer; i++)
+ buf[i] = (u16)readl(csi->base + CSI_IFIFO);
+ } else {
+ u8 *buf = (u8 *)csi->rxbuf;
+
+ for (i = 0; i < csi->words_to_transfer; i++)
+ buf[i] = (u8)readl(csi->base + CSI_IFIFO);
+ }
+
+ csi->rxbuf += csi->bytes_to_transfer;
+ csi->bytes_received += csi->bytes_to_transfer;
+
+ return 0;
+}
+
+static inline void rzv2m_csi_calc_current_transfer(struct rzv2m_csi_priv *csi)
+{
+ int bytes_transferred = max_t(int, csi->bytes_received, csi->bytes_sent);
+ int bytes_remaining = csi->buffer_len - bytes_transferred;
+ int to_transfer;
+
+ if (csi->txbuf)
+ /*
+ * Leaving a little bit of headroom in the FIFOs makes it very
+ * hard to raise an overflow error (which is only possible
+ * when IP transmits and receives at the same time).
+ */
+ to_transfer = min_t(int, CSI_FIFO_HALF_SIZE, bytes_remaining);
+ else
+ to_transfer = min_t(int, CSI_FIFO_SIZE_BYTES, bytes_remaining);
+
+ if (csi->bytes_per_word == 2)
+ to_transfer >>= 1;
+
+ /*
+ * We can only choose a trigger level from a predefined set of values.
+ * This will pick a value that is the greatest possible integer that's
+ * less than or equal to the number of bytes we need to transfer.
+ * This may result in multiple smaller transfers.
+ */
+ csi->words_to_transfer = x_trg_words[to_transfer - 1];
+
+ if (csi->bytes_per_word == 2)
+ csi->bytes_to_transfer = csi->words_to_transfer << 1;
+ else
+ csi->bytes_to_transfer = csi->words_to_transfer;
+}
+
+static inline void rzv2m_csi_set_rx_fifo_trigger_level(struct rzv2m_csi_priv *csi)
+{
+ rzv2m_csi_reg_write_bit(csi, CSI_FIFOTRG, CSI_FIFOTRG_R_TRG,
+ x_trg[csi->words_to_transfer - 1]);
+}
+
+static inline void rzv2m_csi_enable_rx_trigger(struct rzv2m_csi_priv *csi,
+ bool enable)
+{
+ rzv2m_csi_reg_write_bit(csi, CSI_CNT, CSI_CNT_R_TRGEN, enable);
+}
+
+static void rzv2m_csi_disable_irqs(const struct rzv2m_csi_priv *csi,
+ u32 enable_bits)
+{
+ u32 cnt = readl(csi->base + CSI_CNT);
+
+ writel(cnt & ~enable_bits, csi->base + CSI_CNT);
+}
+
+static void rzv2m_csi_disable_all_irqs(struct rzv2m_csi_priv *csi)
+{
+ rzv2m_csi_disable_irqs(csi, CSI_CNT_R_TRGR_E | CSI_CNT_T_TRGR_E |
+ CSI_CNT_CSIEND_E | CSI_CNT_TREND_E |
+ CSI_CNT_OVERF_E | CSI_CNT_UNDER_E);
+}
+
+static inline void rzv2m_csi_clear_irqs(struct rzv2m_csi_priv *csi, u32 irqs)
+{
+ writel(irqs, csi->base + CSI_INT);
+}
+
+static void rzv2m_csi_clear_all_irqs(struct rzv2m_csi_priv *csi)
+{
+ rzv2m_csi_clear_irqs(csi, CSI_INT_UNDER | CSI_INT_OVERF |
+ CSI_INT_TREND | CSI_INT_CSIEND | CSI_INT_T_TRGR |
+ CSI_INT_R_TRGR);
+}
+
+static void rzv2m_csi_enable_irqs(struct rzv2m_csi_priv *csi, u32 enable_bits)
+{
+ u32 cnt = readl(csi->base + CSI_CNT);
+
+ writel(cnt | enable_bits, csi->base + CSI_CNT);
+}
+
+static int rzv2m_csi_wait_for_interrupt(struct rzv2m_csi_priv *csi,
+ u32 wait_mask, u32 enable_bits)
+{
+ int ret;
+
+ rzv2m_csi_enable_irqs(csi, enable_bits);
+
+ ret = wait_event_timeout(csi->wait,
+ ((csi->status & wait_mask) == wait_mask) ||
+ csi->errors, HZ);
+
+ rzv2m_csi_disable_irqs(csi, enable_bits);
+
+ if (csi->errors)
+ return -EIO;
+
+ if (!ret)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int rzv2m_csi_wait_for_tx_empty(struct rzv2m_csi_priv *csi)
+{
+ int ret;
+
+ if (readl(csi->base + CSI_OFIFOL) == 0)
+ return 0;
+
+ ret = rzv2m_csi_wait_for_interrupt(csi, CSI_INT_TREND, CSI_CNT_TREND_E);
+
+ if (ret == -ETIMEDOUT)
+ csi->errors |= TX_TIMEOUT_ERROR;
+
+ return ret;
+}
+
+static inline int rzv2m_csi_wait_for_rx_ready(struct rzv2m_csi_priv *csi)
+{
+ int ret;
+
+ if (readl(csi->base + CSI_IFIFOL) == csi->bytes_to_transfer)
+ return 0;
+
+ ret = rzv2m_csi_wait_for_interrupt(csi, CSI_INT_R_TRGR,
+ CSI_CNT_R_TRGR_E);
+
+ if (ret == -ETIMEDOUT)
+ csi->errors |= RX_TIMEOUT_ERROR;
+
+ return ret;
+}
+
+static irqreturn_t rzv2m_csi_irq_handler(int irq, void *data)
+{
+ struct rzv2m_csi_priv *csi = (struct rzv2m_csi_priv *)data;
+
+ csi->status = readl(csi->base + CSI_INT);
+ rzv2m_csi_disable_irqs(csi, csi->status);
+
+ if (csi->status & CSI_INT_OVERF)
+ csi->errors |= OVERFLOW_ERROR;
+ if (csi->status & CSI_INT_UNDER)
+ csi->errors |= UNDERRUN_ERROR;
+
+ wake_up(&csi->wait);
+
+ return IRQ_HANDLED;
+}
+
+static void rzv2m_csi_setup_clock(struct rzv2m_csi_priv *csi, u32 spi_hz)
+{
+ unsigned long csiclk_rate = clk_get_rate(csi->csiclk);
+ unsigned long pclk_rate = clk_get_rate(csi->pclk);
+ unsigned long csiclk_rate_limit = pclk_rate >> 1;
+ u32 cks;
+
+ /*
+ * There is a restriction on the frequency of CSICLK, it has to be <=
+ * PCLK / 2.
+ */
+ if (csiclk_rate > csiclk_rate_limit) {
+ clk_set_rate(csi->csiclk, csiclk_rate >> 1);
+ csiclk_rate = clk_get_rate(csi->csiclk);
+ } else if ((csiclk_rate << 1) <= csiclk_rate_limit) {
+ clk_set_rate(csi->csiclk, csiclk_rate << 1);
+ csiclk_rate = clk_get_rate(csi->csiclk);
+ }
+
+ spi_hz = spi_hz > CSI_MAX_SPI_SCKO ? CSI_MAX_SPI_SCKO : spi_hz;
+
+ cks = DIV_ROUND_UP(csiclk_rate, spi_hz << 1);
+ if (cks > CSI_CKS_MAX)
+ cks = CSI_CKS_MAX;
+
+ dev_dbg(csi->dev, "SPI clk rate is %ldHz\n", csiclk_rate / (cks << 1));
+
+ rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_CKS, cks);
+}
+
+static void rzv2m_csi_setup_operating_mode(struct rzv2m_csi_priv *csi,
+ struct spi_transfer *t)
+{
+ if (t->rx_buf && !t->tx_buf)
+ /* Reception-only mode */
+ rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_TRMD, 0);
+ else
+ /* Send and receive mode */
+ rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_TRMD, 1);
+
+ csi->bytes_per_word = t->bits_per_word / 8;
+ rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_CCL,
+ csi->bytes_per_word == 2);
+}
+
+static int rzv2m_csi_setup(struct spi_device *spi)
+{
+ struct rzv2m_csi_priv *csi = spi_controller_get_devdata(spi->controller);
+ int ret;
+
+ rzv2m_csi_sw_reset(csi, 0);
+
+ writel(CSI_MODE_SETUP, csi->base + CSI_MODE);
+
+ /* Setup clock polarity and phase timing */
+ rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_CKP,
+ !(spi->mode & SPI_CPOL));
+ rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_DAP,
+ !(spi->mode & SPI_CPHA));
+
+ /* Setup serial data order */
+ rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_DIR,
+ !!(spi->mode & SPI_LSB_FIRST));
+
+ /* Set the operation mode as master */
+ rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_SLAVE, 0);
+
+ /* Give the IP a SW reset */
+ ret = rzv2m_csi_sw_reset(csi, 1);
+ if (ret)
+ return ret;
+ rzv2m_csi_sw_reset(csi, 0);
+
+ /*
+ * We need to enable the communication so that the clock will settle
+ * for the right polarity before enabling the CS.
+ */
+ rzv2m_csi_start_stop_operation(csi, 1, false);
+ udelay(10);
+ rzv2m_csi_start_stop_operation(csi, 0, false);
+
+ return 0;
+}
+
+static int rzv2m_csi_pio_transfer(struct rzv2m_csi_priv *csi)
+{
+ bool tx_completed = csi->txbuf ? false : true;
+ bool rx_completed = csi->rxbuf ? false : true;
+ int ret = 0;
+
+ /* Make sure the TX FIFO is empty */
+ writel(0, csi->base + CSI_OFIFOL);
+
+ csi->bytes_sent = 0;
+ csi->bytes_received = 0;
+ csi->errors = 0;
+
+ rzv2m_csi_disable_all_irqs(csi);
+ rzv2m_csi_clear_all_irqs(csi);
+ rzv2m_csi_enable_rx_trigger(csi, true);
+
+ while (!tx_completed || !rx_completed) {
+ /*
+ * Decide how many words we are going to transfer during
+ * this cycle (for both TX and RX), then set the RX FIFO trigger
+ * level accordingly. No need to set a trigger level for the
+ * TX FIFO, as this IP comes with an interrupt that fires when
+ * the TX FIFO is empty.
+ */
+ rzv2m_csi_calc_current_transfer(csi);
+ rzv2m_csi_set_rx_fifo_trigger_level(csi);
+
+ rzv2m_csi_enable_irqs(csi, CSI_INT_OVERF | CSI_INT_UNDER);
+
+ /* Make sure the RX FIFO is empty */
+ writel(0, csi->base + CSI_IFIFOL);
+
+ writel(readl(csi->base + CSI_INT), csi->base + CSI_INT);
+ csi->status = 0;
+
+ rzv2m_csi_start_stop_operation(csi, 1, false);
+
+ /* TX */
+ if (csi->txbuf) {
+ ret = rzv2m_csi_fill_txfifo(csi);
+ if (ret)
+ break;
+
+ ret = rzv2m_csi_wait_for_tx_empty(csi);
+ if (ret)
+ break;
+
+ if (csi->bytes_sent == csi->buffer_len)
+ tx_completed = true;
+ }
+
+ /*
+ * Make sure the RX FIFO contains the desired number of words.
+ * We then either flush its content, or we copy it onto
+ * csi->rxbuf.
+ */
+ ret = rzv2m_csi_wait_for_rx_ready(csi);
+ if (ret)
+ break;
+
+ /* RX */
+ if (csi->rxbuf) {
+ rzv2m_csi_start_stop_operation(csi, 0, false);
+
+ ret = rzv2m_csi_read_rxfifo(csi);
+ if (ret)
+ break;
+
+ if (csi->bytes_received == csi->buffer_len)
+ rx_completed = true;
+ }
+
+ ret = rzv2m_csi_start_stop_operation(csi, 0, true);
+ if (ret)
+ goto pio_quit;
+
+ if (csi->errors) {
+ ret = -EIO;
+ goto pio_quit;
+ }
+ }
+
+ rzv2m_csi_start_stop_operation(csi, 0, true);
+
+pio_quit:
+ rzv2m_csi_disable_all_irqs(csi);
+ rzv2m_csi_enable_rx_trigger(csi, false);
+ rzv2m_csi_clear_all_irqs(csi);
+
+ return ret;
+}
+
+static int rzv2m_csi_transfer_one(struct spi_controller *controller,
+ struct spi_device *spi,
+ struct spi_transfer *transfer)
+{
+ struct rzv2m_csi_priv *csi = spi_controller_get_devdata(controller);
+ struct device *dev = csi->dev;
+ int ret;
+
+ csi->txbuf = transfer->tx_buf;
+ csi->rxbuf = transfer->rx_buf;
+ csi->buffer_len = transfer->len;
+
+ rzv2m_csi_setup_operating_mode(csi, transfer);
+
+ rzv2m_csi_setup_clock(csi, transfer->speed_hz);
+
+ ret = rzv2m_csi_pio_transfer(csi);
+ if (ret) {
+ if (csi->errors & UNDERRUN_ERROR)
+ dev_err(dev, "Underrun error\n");
+ if (csi->errors & OVERFLOW_ERROR)
+ dev_err(dev, "Overflow error\n");
+ if (csi->errors & TX_TIMEOUT_ERROR)
+ dev_err(dev, "TX timeout error\n");
+ if (csi->errors & RX_TIMEOUT_ERROR)
+ dev_err(dev, "RX timeout error\n");
+ }
+
+ return ret;
+}
+
+static int rzv2m_csi_probe(struct platform_device *pdev)
+{
+ struct spi_controller *controller;
+ struct device *dev = &pdev->dev;
+ struct rzv2m_csi_priv *csi;
+ struct reset_control *rstc;
+ int irq;
+ int ret;
+
+ controller = devm_spi_alloc_master(dev, sizeof(*csi));
+ if (!controller)
+ return -ENOMEM;
+
+ csi = spi_controller_get_devdata(controller);
+ platform_set_drvdata(pdev, csi);
+
+ csi->dev = dev;
+ csi->controller = controller;
+
+ csi->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(csi->base))
+ return PTR_ERR(csi->base);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ csi->csiclk = devm_clk_get(dev, "csiclk");
+ if (IS_ERR(csi->csiclk))
+ return dev_err_probe(dev, PTR_ERR(csi->csiclk),
+ "could not get csiclk\n");
+
+ csi->pclk = devm_clk_get(dev, "pclk");
+ if (IS_ERR(csi->pclk))
+ return dev_err_probe(dev, PTR_ERR(csi->pclk),
+ "could not get pclk\n");
+
+ rstc = devm_reset_control_get_shared(dev, NULL);
+ if (IS_ERR(rstc))
+ return dev_err_probe(dev, PTR_ERR(rstc), "Missing reset ctrl\n");
+
+ init_waitqueue_head(&csi->wait);
+
+ controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
+ controller->dev.of_node = pdev->dev.of_node;
+ controller->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8);
+ controller->setup = rzv2m_csi_setup;
+ controller->transfer_one = rzv2m_csi_transfer_one;
+ controller->use_gpio_descriptors = true;
+
+ ret = devm_request_irq(dev, irq, rzv2m_csi_irq_handler, 0,
+ dev_name(dev), csi);
+ if (ret)
+ return dev_err_probe(dev, ret, "cannot request IRQ\n");
+
+ /*
+ * The reset also affects other HW that is not under the control
+ * of Linux. Therefore, all we can do is make sure the reset is
+ * deasserted.
+ */
+ reset_control_deassert(rstc);
+
+ /* Make sure the IP is in SW reset state */
+ ret = rzv2m_csi_sw_reset(csi, 1);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(csi->csiclk);
+ if (ret)
+ return dev_err_probe(dev, ret, "could not enable csiclk\n");
+
+ ret = spi_register_controller(controller);
+ if (ret) {
+ clk_disable_unprepare(csi->csiclk);
+ return dev_err_probe(dev, ret, "register controller failed\n");
+ }
+
+ return 0;
+}
+
+static int rzv2m_csi_remove(struct platform_device *pdev)
+{
+ struct rzv2m_csi_priv *csi = platform_get_drvdata(pdev);
+
+ spi_unregister_controller(csi->controller);
+ rzv2m_csi_sw_reset(csi, 1);
+ clk_disable_unprepare(csi->csiclk);
+
+ return 0;
+}
+
+static const struct of_device_id rzv2m_csi_match[] = {
+ { .compatible = "renesas,rzv2m-csi" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rzv2m_csi_match);
+
+static struct platform_driver rzv2m_csi_drv = {
+ .probe = rzv2m_csi_probe,
+ .remove = rzv2m_csi_remove,
+ .driver = {
+ .name = "rzv2m_csi",
+ .of_match_table = rzv2m_csi_match,
+ },
+};
+module_platform_driver(rzv2m_csi_drv);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Fabrizio Castro <castro.fabrizio.jz@renesas.com>");
+MODULE_DESCRIPTION("Clocked Serial Interface Driver");
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index 7ac17f0d18a9..b6c2659a66ca 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -19,7 +19,6 @@
#include <linux/platform_data/spi-s3c64xx.h>
#define MAX_SPI_PORTS 12
-#define S3C64XX_SPI_QUIRK_POLL (1 << 0)
#define S3C64XX_SPI_QUIRK_CS_AUTO (1 << 1)
#define AUTOSUSPEND_TIMEOUT 2000
@@ -59,6 +58,8 @@
#define S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD (1<<17)
#define S3C64XX_SPI_MODE_BUS_TSZ_WORD (2<<17)
#define S3C64XX_SPI_MODE_BUS_TSZ_MASK (3<<17)
+#define S3C64XX_SPI_MODE_RX_RDY_LVL GENMASK(16, 11)
+#define S3C64XX_SPI_MODE_RX_RDY_LVL_SHIFT 11
#define S3C64XX_SPI_MODE_SELF_LOOPBACK (1<<3)
#define S3C64XX_SPI_MODE_RXDMA_ON (1<<2)
#define S3C64XX_SPI_MODE_TXDMA_ON (1<<1)
@@ -115,8 +116,10 @@
#define S3C64XX_SPI_TRAILCNT S3C64XX_SPI_MAX_TRAILCNT
+#define S3C64XX_SPI_POLLING_SIZE 32
+
#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
-#define is_polling(x) (x->port_conf->quirks & S3C64XX_SPI_QUIRK_POLL)
+#define is_polling(x) (x->cntrlr_info->polling)
#define RXBUSY (1<<2)
#define TXBUSY (1<<3)
@@ -553,7 +556,7 @@ static int s3c64xx_wait_for_dma(struct s3c64xx_spi_driver_data *sdd,
}
static int s3c64xx_wait_for_pio(struct s3c64xx_spi_driver_data *sdd,
- struct spi_transfer *xfer)
+ struct spi_transfer *xfer, bool use_irq)
{
void __iomem *regs = sdd->regs;
unsigned long val;
@@ -562,11 +565,24 @@ static int s3c64xx_wait_for_pio(struct s3c64xx_spi_driver_data *sdd,
u32 cpy_len;
u8 *buf;
int ms;
+ unsigned long time_us;
- /* millisecs to xfer 'len' bytes @ 'cur_speed' */
- ms = xfer->len * 8 * 1000 / sdd->cur_speed;
+ /* microsecs to xfer 'len' bytes @ 'cur_speed' */
+ time_us = (xfer->len * 8 * 1000 * 1000) / sdd->cur_speed;
+ ms = (time_us / 1000);
ms += 10; /* some tolerance */
+ /* sleep during signal transfer time */
+ status = readl(regs + S3C64XX_SPI_STATUS);
+ if (RX_FIFO_LVL(status, sdd) < xfer->len)
+ usleep_range(time_us / 2, time_us);
+
+ if (use_irq) {
+ val = msecs_to_jiffies(ms);
+ if (!wait_for_completion_timeout(&sdd->xfer_completion, val))
+ return -EIO;
+ }
+
val = msecs_to_loops(ms);
do {
status = readl(regs + S3C64XX_SPI_STATUS);
@@ -668,6 +684,8 @@ static int s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
if ((sdd->cur_mode & SPI_LOOP) && sdd->port_conf->has_loopback)
val |= S3C64XX_SPI_MODE_SELF_LOOPBACK;
+ else
+ val &= ~S3C64XX_SPI_MODE_SELF_LOOPBACK;
writel(val, regs + S3C64XX_SPI_MODE_CFG);
@@ -729,10 +747,13 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
void *rx_buf = NULL;
int target_len = 0, origin_len = 0;
int use_dma = 0;
+ bool use_irq = false;
int status;
u32 speed;
u8 bpw;
unsigned long flags;
+ u32 rdy_lv;
+ u32 val;
reinit_completion(&sdd->xfer_completion);
@@ -753,17 +774,46 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
sdd->rx_dma.ch && sdd->tx_dma.ch) {
use_dma = 1;
- } else if (xfer->len > fifo_len) {
+ } else if (xfer->len >= fifo_len) {
tx_buf = xfer->tx_buf;
rx_buf = xfer->rx_buf;
origin_len = xfer->len;
-
target_len = xfer->len;
- if (xfer->len > fifo_len)
- xfer->len = fifo_len;
+ xfer->len = fifo_len - 1;
}
do {
+ /* transfer size is greater than 32, change to IRQ mode */
+ if (!use_dma && xfer->len > S3C64XX_SPI_POLLING_SIZE)
+ use_irq = true;
+
+ if (use_irq) {
+ reinit_completion(&sdd->xfer_completion);
+
+ rdy_lv = xfer->len;
+ /* Setup RDY_FIFO trigger Level
+ * RDY_LVL =
+ * fifo_lvl up to 64 byte -> N bytes
+ * 128 byte -> RDY_LVL * 2 bytes
+ * 256 byte -> RDY_LVL * 4 bytes
+ */
+ if (fifo_len == 128)
+ rdy_lv /= 2;
+ else if (fifo_len == 256)
+ rdy_lv /= 4;
+
+ val = readl(sdd->regs + S3C64XX_SPI_MODE_CFG);
+ val &= ~S3C64XX_SPI_MODE_RX_RDY_LVL;
+ val |= (rdy_lv << S3C64XX_SPI_MODE_RX_RDY_LVL_SHIFT);
+ writel(val, sdd->regs + S3C64XX_SPI_MODE_CFG);
+
+ /* Enable FIFO_RDY_EN IRQ */
+ val = readl(sdd->regs + S3C64XX_SPI_INT_EN);
+ writel((val | S3C64XX_SPI_INT_RX_FIFORDY_EN),
+ sdd->regs + S3C64XX_SPI_INT_EN);
+
+ }
+
spin_lock_irqsave(&sdd->lock, flags);
/* Pending only which is to be done */
@@ -785,7 +835,7 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
if (use_dma)
status = s3c64xx_wait_for_dma(sdd, xfer);
else
- status = s3c64xx_wait_for_pio(sdd, xfer);
+ status = s3c64xx_wait_for_pio(sdd, xfer, use_irq);
if (status) {
dev_err(&spi->dev,
@@ -824,8 +874,8 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
if (xfer->rx_buf)
xfer->rx_buf += xfer->len;
- if (target_len > fifo_len)
- xfer->len = fifo_len;
+ if (target_len >= fifo_len)
+ xfer->len = fifo_len - 1;
else
xfer->len = target_len;
}
@@ -995,6 +1045,14 @@ static irqreturn_t s3c64xx_spi_irq(int irq, void *data)
dev_err(&spi->dev, "TX underrun\n");
}
+ if (val & S3C64XX_SPI_ST_RX_FIFORDY) {
+ complete(&sdd->xfer_completion);
+ /* No pending clear irq, turn-off INT_EN_RX_FIFO_RDY */
+ val = readl(sdd->regs + S3C64XX_SPI_INT_EN);
+ writel((val & ~S3C64XX_SPI_INT_RX_FIFORDY_EN),
+ sdd->regs + S3C64XX_SPI_INT_EN);
+ }
+
/* Clear the pending irq by setting and then clearing it */
writel(clr, sdd->regs + S3C64XX_SPI_PENDING_CLR);
writel(0, sdd->regs + S3C64XX_SPI_PENDING_CLR);
@@ -1068,6 +1126,7 @@ static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev)
}
sci->no_cs = of_property_read_bool(dev->of_node, "no-cs-readback");
+ sci->polling = !of_property_present(dev->of_node, "dmas");
return sci;
}
@@ -1103,29 +1162,23 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
return PTR_ERR(sci);
}
- if (!sci) {
- dev_err(&pdev->dev, "platform_data missing!\n");
- return -ENODEV;
- }
+ if (!sci)
+ return dev_err_probe(&pdev->dev, -ENODEV,
+ "Platform_data missing!\n");
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (mem_res == NULL) {
- dev_err(&pdev->dev, "Unable to get SPI MEM resource\n");
- return -ENXIO;
- }
+ if (!mem_res)
+ return dev_err_probe(&pdev->dev, -ENXIO,
+ "Unable to get SPI MEM resource\n");
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_warn(&pdev->dev, "Failed to get IRQ: %d\n", irq);
- return irq;
- }
+ if (irq < 0)
+ return dev_err_probe(&pdev->dev, irq, "Failed to get IRQ\n");
- master = spi_alloc_master(&pdev->dev,
- sizeof(struct s3c64xx_spi_driver_data));
- if (master == NULL) {
- dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
- return -ENOMEM;
- }
+ master = devm_spi_alloc_master(&pdev->dev, sizeof(*sdd));
+ if (!master)
+ return dev_err_probe(&pdev->dev, -ENOMEM,
+ "Unable to allocate SPI Master\n");
platform_set_drvdata(pdev, master);
@@ -1137,11 +1190,9 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
sdd->sfr_start = mem_res->start;
if (pdev->dev.of_node) {
ret = of_alias_get_id(pdev->dev.of_node, "spi");
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to get alias id, errno %d\n",
- ret);
- goto err_deref_master;
- }
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to get alias id\n");
sdd->port_id = ret;
} else {
sdd->port_id = pdev->id;
@@ -1175,59 +1226,31 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
master->can_dma = s3c64xx_spi_can_dma;
sdd->regs = devm_ioremap_resource(&pdev->dev, mem_res);
- if (IS_ERR(sdd->regs)) {
- ret = PTR_ERR(sdd->regs);
- goto err_deref_master;
- }
+ if (IS_ERR(sdd->regs))
+ return PTR_ERR(sdd->regs);
- if (sci->cfg_gpio && sci->cfg_gpio()) {
- dev_err(&pdev->dev, "Unable to config gpio\n");
- ret = -EBUSY;
- goto err_deref_master;
- }
+ if (sci->cfg_gpio && sci->cfg_gpio())
+ return dev_err_probe(&pdev->dev, -EBUSY,
+ "Unable to config gpio\n");
/* Setup clocks */
- sdd->clk = devm_clk_get(&pdev->dev, "spi");
- if (IS_ERR(sdd->clk)) {
- dev_err(&pdev->dev, "Unable to acquire clock 'spi'\n");
- ret = PTR_ERR(sdd->clk);
- goto err_deref_master;
- }
-
- ret = clk_prepare_enable(sdd->clk);
- if (ret) {
- dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n");
- goto err_deref_master;
- }
+ sdd->clk = devm_clk_get_enabled(&pdev->dev, "spi");
+ if (IS_ERR(sdd->clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(sdd->clk),
+ "Unable to acquire clock 'spi'\n");
sprintf(clk_name, "spi_busclk%d", sci->src_clk_nr);
- sdd->src_clk = devm_clk_get(&pdev->dev, clk_name);
- if (IS_ERR(sdd->src_clk)) {
- dev_err(&pdev->dev,
- "Unable to acquire clock '%s'\n", clk_name);
- ret = PTR_ERR(sdd->src_clk);
- goto err_disable_clk;
- }
-
- ret = clk_prepare_enable(sdd->src_clk);
- if (ret) {
- dev_err(&pdev->dev, "Couldn't enable clock '%s'\n", clk_name);
- goto err_disable_clk;
- }
+ sdd->src_clk = devm_clk_get_enabled(&pdev->dev, clk_name);
+ if (IS_ERR(sdd->src_clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(sdd->src_clk),
+ "Unable to acquire clock '%s'\n",
+ clk_name);
if (sdd->port_conf->clk_ioclk) {
- sdd->ioclk = devm_clk_get(&pdev->dev, "spi_ioclk");
- if (IS_ERR(sdd->ioclk)) {
- dev_err(&pdev->dev, "Unable to acquire 'ioclk'\n");
- ret = PTR_ERR(sdd->ioclk);
- goto err_disable_src_clk;
- }
-
- ret = clk_prepare_enable(sdd->ioclk);
- if (ret) {
- dev_err(&pdev->dev, "Couldn't enable clock 'ioclk'\n");
- goto err_disable_src_clk;
- }
+ sdd->ioclk = devm_clk_get_enabled(&pdev->dev, "spi_ioclk");
+ if (IS_ERR(sdd->ioclk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(sdd->ioclk),
+ "Unable to acquire 'ioclk'\n");
}
pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT);
@@ -1275,14 +1298,6 @@ err_pm_put:
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
- clk_disable_unprepare(sdd->ioclk);
-err_disable_src_clk:
- clk_disable_unprepare(sdd->src_clk);
-err_disable_clk:
- clk_disable_unprepare(sdd->clk);
-err_deref_master:
- spi_master_put(master);
-
return ret;
}
@@ -1300,12 +1315,6 @@ static void s3c64xx_spi_remove(struct platform_device *pdev)
dma_release_channel(sdd->tx_dma.ch);
}
- clk_disable_unprepare(sdd->ioclk);
-
- clk_disable_unprepare(sdd->src_clk);
-
- clk_disable_unprepare(sdd->clk);
-
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
diff --git a/drivers/spi/spi-sc18is602.c b/drivers/spi/spi-sc18is602.c
index 70012333020b..d52ed67243f7 100644
--- a/drivers/spi/spi-sc18is602.c
+++ b/drivers/spi/spi-sc18is602.c
@@ -337,7 +337,7 @@ static struct i2c_driver sc18is602_driver = {
.name = "sc18is602",
.of_match_table = of_match_ptr(sc18is602_of_match),
},
- .probe_new = sc18is602_probe,
+ .probe = sc18is602_probe,
.id_table = sc18is602_id,
};
diff --git a/drivers/spi/spi-sn-f-ospi.c b/drivers/spi/spi-sn-f-ospi.c
index a2bd9dcde075..d64d3f75c726 100644
--- a/drivers/spi/spi-sn-f-ospi.c
+++ b/drivers/spi/spi-sn-f-ospi.c
@@ -526,7 +526,7 @@ static int f_ospi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
static bool f_ospi_supports_op_width(struct spi_mem *mem,
const struct spi_mem_op *op)
{
- u8 width_available[] = { 0, 1, 2, 4, 8 };
+ static const u8 width_available[] = { 0, 1, 2, 4, 8 };
u8 width_op[] = { op->cmd.buswidth, op->addr.buswidth,
op->dummy.buswidth, op->data.buswidth };
bool is_match_found;
@@ -566,7 +566,7 @@ static bool f_ospi_supports_op(struct spi_mem *mem,
static int f_ospi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
{
- op->data.nbytes = min((int)op->data.nbytes, (int)(OSPI_DAT_SIZE_MAX));
+ op->data.nbytes = min_t(int, op->data.nbytes, OSPI_DAT_SIZE_MAX);
return 0;
}
@@ -634,18 +634,12 @@ static int f_ospi_probe(struct platform_device *pdev)
goto err_put_ctlr;
}
- ospi->clk = devm_clk_get(dev, NULL);
+ ospi->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(ospi->clk)) {
ret = PTR_ERR(ospi->clk);
goto err_put_ctlr;
}
- ret = clk_prepare_enable(ospi->clk);
- if (ret) {
- dev_err(dev, "Failed to enable the clock\n");
- goto err_disable_clk;
- }
-
mutex_init(&ospi->mlock);
ret = f_ospi_init(ospi);
@@ -661,9 +655,6 @@ static int f_ospi_probe(struct platform_device *pdev)
err_destroy_mutex:
mutex_destroy(&ospi->mlock);
-err_disable_clk:
- clk_disable_unprepare(ospi->clk);
-
err_put_ctlr:
spi_controller_put(ctlr);
@@ -674,8 +665,6 @@ static void f_ospi_remove(struct platform_device *pdev)
{
struct f_ospi *ospi = platform_get_drvdata(pdev);
- clk_disable_unprepare(ospi->clk);
-
mutex_destroy(&ospi->mlock);
}
diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c
index d6598e4116bd..7ddf9db776b0 100644
--- a/drivers/spi/spi-stm32.c
+++ b/drivers/spi/spi-stm32.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
//
-// STMicroelectronics STM32 SPI Controller driver (master mode only)
+// STMicroelectronics STM32 SPI Controller driver
//
// Copyright (C) 2017, STMicroelectronics - All Rights Reserved
// Author(s): Amelie Delaunay <amelie.delaunay@st.com> for STMicroelectronics.
@@ -117,6 +117,7 @@
#define STM32H7_SPI_CFG2_CPHA BIT(24)
#define STM32H7_SPI_CFG2_CPOL BIT(25)
#define STM32H7_SPI_CFG2_SSM BIT(26)
+#define STM32H7_SPI_CFG2_SSIOP BIT(28)
#define STM32H7_SPI_CFG2_AFCNTR BIT(31)
/* STM32H7_SPI_IER bit fields */
@@ -170,6 +171,10 @@
*/
#define SPI_DMA_MIN_BYTES 16
+/* STM32 SPI driver helpers */
+#define STM32_SPI_MASTER_MODE(stm32_spi) (!(stm32_spi)->device_mode)
+#define STM32_SPI_DEVICE_MODE(stm32_spi) ((stm32_spi)->device_mode)
+
/**
* struct stm32_spi_reg - stm32 SPI register & bitfield desc
* @reg: register offset
@@ -190,6 +195,7 @@ struct stm32_spi_reg {
* @cpol: clock polarity register and polarity bit
* @cpha: clock phase register and phase bit
* @lsb_first: LSB transmitted first register and bit
+ * @cs_high: chips select active value
* @br: baud rate register and bitfields
* @rx: SPI RX data register
* @tx: SPI TX data register
@@ -201,6 +207,7 @@ struct stm32_spi_regspec {
const struct stm32_spi_reg cpol;
const struct stm32_spi_reg cpha;
const struct stm32_spi_reg lsb_first;
+ const struct stm32_spi_reg cs_high;
const struct stm32_spi_reg br;
const struct stm32_spi_reg rx;
const struct stm32_spi_reg tx;
@@ -258,7 +265,7 @@ struct stm32_spi_cfg {
/**
* struct stm32_spi - private data of the SPI controller
* @dev: driver model representation of the controller
- * @master: controller master interface
+ * @ctrl: controller interface
* @cfg: compatible configuration data
* @base: virtual memory area
* @clk: hw kernel clock feeding the SPI clock generator
@@ -280,10 +287,11 @@ struct stm32_spi_cfg {
* @dma_tx: dma channel for TX transfer
* @dma_rx: dma channel for RX transfer
* @phys_addr: SPI registers physical base address
+ * @device_mode: the controller is configured as SPI device
*/
struct stm32_spi {
struct device *dev;
- struct spi_master *master;
+ struct spi_controller *ctrl;
const struct stm32_spi_cfg *cfg;
void __iomem *base;
struct clk *clk;
@@ -307,6 +315,8 @@ struct stm32_spi {
struct dma_chan *dma_tx;
struct dma_chan *dma_rx;
dma_addr_t phys_addr;
+
+ bool device_mode;
};
static const struct stm32_spi_regspec stm32f4_spi_regspec = {
@@ -318,6 +328,7 @@ static const struct stm32_spi_regspec stm32f4_spi_regspec = {
.cpol = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_CPOL },
.cpha = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_CPHA },
.lsb_first = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_LSBFRST },
+ .cs_high = {},
.br = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_BR, STM32F4_SPI_CR1_BR_SHIFT },
.rx = { STM32F4_SPI_DR },
@@ -336,6 +347,7 @@ static const struct stm32_spi_regspec stm32h7_spi_regspec = {
.cpol = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPOL },
.cpha = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPHA },
.lsb_first = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_LSBFRST },
+ .cs_high = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_SSIOP },
.br = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_MBR,
STM32H7_SPI_CFG1_MBR_SHIFT },
@@ -437,9 +449,9 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz,
div = DIV_ROUND_CLOSEST(spi->clk_rate & ~0x1, speed_hz);
/*
- * SPI framework set xfer->speed_hz to master->max_speed_hz if
- * xfer->speed_hz is greater than master->max_speed_hz, and it returns
- * an error when xfer->speed_hz is lower than master->min_speed_hz, so
+ * SPI framework set xfer->speed_hz to ctrl->max_speed_hz if
+ * xfer->speed_hz is greater than ctrl->max_speed_hz, and it returns
+ * an error when xfer->speed_hz is lower than ctrl->min_speed_hz, so
* no need to check it there.
* However, we need to ensure the following calculations.
*/
@@ -657,9 +669,9 @@ static void stm32f4_spi_disable(struct stm32_spi *spi)
}
if (spi->cur_usedma && spi->dma_tx)
- dmaengine_terminate_all(spi->dma_tx);
+ dmaengine_terminate_async(spi->dma_tx);
if (spi->cur_usedma && spi->dma_rx)
- dmaengine_terminate_all(spi->dma_rx);
+ dmaengine_terminate_async(spi->dma_rx);
stm32_spi_clr_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_SPE);
@@ -696,9 +708,9 @@ static void stm32h7_spi_disable(struct stm32_spi *spi)
}
if (spi->cur_usedma && spi->dma_tx)
- dmaengine_terminate_all(spi->dma_tx);
+ dmaengine_terminate_async(spi->dma_tx);
if (spi->cur_usedma && spi->dma_rx)
- dmaengine_terminate_all(spi->dma_rx);
+ dmaengine_terminate_async(spi->dma_rx);
stm32_spi_clr_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE);
@@ -714,19 +726,19 @@ static void stm32h7_spi_disable(struct stm32_spi *spi)
/**
* stm32_spi_can_dma - Determine if the transfer is eligible for DMA use
- * @master: controller master interface
+ * @ctrl: controller interface
* @spi_dev: pointer to the spi device
* @transfer: pointer to spi transfer
*
* If driver has fifo and the current transfer size is greater than fifo size,
* use DMA. Otherwise use DMA for transfer longer than defined DMA min bytes.
*/
-static bool stm32_spi_can_dma(struct spi_master *master,
+static bool stm32_spi_can_dma(struct spi_controller *ctrl,
struct spi_device *spi_dev,
struct spi_transfer *transfer)
{
unsigned int dma_size;
- struct stm32_spi *spi = spi_master_get_devdata(master);
+ struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
if (spi->cfg->has_fifo)
dma_size = spi->fifo_size;
@@ -742,12 +754,12 @@ static bool stm32_spi_can_dma(struct spi_master *master,
/**
* stm32f4_spi_irq_event - Interrupt handler for SPI controller events
* @irq: interrupt line
- * @dev_id: SPI controller master interface
+ * @dev_id: SPI controller ctrl interface
*/
static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id)
{
- struct spi_master *master = dev_id;
- struct stm32_spi *spi = spi_master_get_devdata(master);
+ struct spi_controller *ctrl = dev_id;
+ struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
u32 sr, mask = 0;
bool end = false;
@@ -830,14 +842,14 @@ end_irq:
/**
* stm32f4_spi_irq_thread - Thread of interrupt handler for SPI controller
* @irq: interrupt line
- * @dev_id: SPI controller master interface
+ * @dev_id: SPI controller interface
*/
static irqreturn_t stm32f4_spi_irq_thread(int irq, void *dev_id)
{
- struct spi_master *master = dev_id;
- struct stm32_spi *spi = spi_master_get_devdata(master);
+ struct spi_controller *ctrl = dev_id;
+ struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
- spi_finalize_current_transfer(master);
+ spi_finalize_current_transfer(ctrl);
stm32f4_spi_disable(spi);
return IRQ_HANDLED;
@@ -846,12 +858,12 @@ static irqreturn_t stm32f4_spi_irq_thread(int irq, void *dev_id)
/**
* stm32h7_spi_irq_thread - Thread of interrupt handler for SPI controller
* @irq: interrupt line
- * @dev_id: SPI controller master interface
+ * @dev_id: SPI controller interface
*/
static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id)
{
- struct spi_master *master = dev_id;
- struct stm32_spi *spi = spi_master_get_devdata(master);
+ struct spi_controller *ctrl = dev_id;
+ struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
u32 sr, ier, mask;
unsigned long flags;
bool end = false;
@@ -931,7 +943,7 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id)
if (end) {
stm32h7_spi_disable(spi);
- spi_finalize_current_transfer(master);
+ spi_finalize_current_transfer(ctrl);
}
return IRQ_HANDLED;
@@ -939,13 +951,13 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id)
/**
* stm32_spi_prepare_msg - set up the controller to transfer a single message
- * @master: controller master interface
+ * @ctrl: controller interface
* @msg: pointer to spi message
*/
-static int stm32_spi_prepare_msg(struct spi_master *master,
+static int stm32_spi_prepare_msg(struct spi_controller *ctrl,
struct spi_message *msg)
{
- struct stm32_spi *spi = spi_master_get_devdata(master);
+ struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
struct spi_device *spi_dev = msg->spi;
struct device_node *np = spi_dev->dev.of_node;
unsigned long flags;
@@ -971,6 +983,11 @@ static int stm32_spi_prepare_msg(struct spi_master *master,
else
clrb |= spi->cfg->regs->lsb_first.mask;
+ if (STM32_SPI_DEVICE_MODE(spi) && spi_dev->mode & SPI_CS_HIGH)
+ setb |= spi->cfg->regs->cs_high.mask;
+ else
+ clrb |= spi->cfg->regs->cs_high.mask;
+
dev_dbg(spi->dev, "cpol=%d cpha=%d lsb_first=%d cs_high=%d\n",
!!(spi_dev->mode & SPI_CPOL),
!!(spi_dev->mode & SPI_CPHA),
@@ -984,7 +1001,7 @@ static int stm32_spi_prepare_msg(struct spi_master *master,
if (spi->cfg->set_number_of_data) {
int ret;
- ret = spi_split_transfers_maxwords(master, msg,
+ ret = spi_split_transfers_maxwords(ctrl, msg,
STM32H7_SPI_TSIZE_MAX,
GFP_KERNEL | GFP_DMA);
if (ret)
@@ -1016,7 +1033,7 @@ static void stm32f4_spi_dma_tx_cb(void *data)
struct stm32_spi *spi = data;
if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) {
- spi_finalize_current_transfer(spi->master);
+ spi_finalize_current_transfer(spi->ctrl);
stm32f4_spi_disable(spi);
}
}
@@ -1031,7 +1048,7 @@ static void stm32_spi_dma_rx_cb(void *data)
{
struct stm32_spi *spi = data;
- spi_finalize_current_transfer(spi->master);
+ spi_finalize_current_transfer(spi->ctrl);
spi->cfg->disable(spi);
}
@@ -1161,7 +1178,8 @@ static int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi)
if (spi->tx_buf)
stm32h7_spi_write_txfifo(spi);
- stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART);
+ if (STM32_SPI_MASTER_MODE(spi))
+ stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART);
writel_relaxed(ier, spi->base + STM32H7_SPI_IER);
@@ -1208,7 +1226,8 @@ static void stm32h7_spi_transfer_one_dma_start(struct stm32_spi *spi)
stm32_spi_enable(spi);
- stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART);
+ if (STM32_SPI_MASTER_MODE(spi))
+ stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART);
}
/**
@@ -1302,7 +1321,7 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi,
dma_submit_error:
if (spi->dma_rx)
- dmaengine_terminate_all(spi->dma_rx);
+ dmaengine_terminate_sync(spi->dma_rx);
dma_desc_error:
stm32_spi_clr_bits(spi, spi->cfg->regs->dma_rx_en.reg,
@@ -1536,16 +1555,18 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi,
spi->cfg->set_bpw(spi);
/* Update spi->cur_speed with real clock speed */
- mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz,
- spi->cfg->baud_rate_div_min,
- spi->cfg->baud_rate_div_max);
- if (mbr < 0) {
- ret = mbr;
- goto out;
- }
+ if (STM32_SPI_MASTER_MODE(spi)) {
+ mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz,
+ spi->cfg->baud_rate_div_min,
+ spi->cfg->baud_rate_div_max);
+ if (mbr < 0) {
+ ret = mbr;
+ goto out;
+ }
- transfer->speed_hz = spi->cur_speed;
- stm32_spi_set_mbr(spi, mbr);
+ transfer->speed_hz = spi->cur_speed;
+ stm32_spi_set_mbr(spi, mbr);
+ }
comm_type = stm32_spi_communication_type(spi_dev, transfer);
ret = spi->cfg->set_mode(spi, comm_type);
@@ -1554,7 +1575,7 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi,
spi->cur_comm = comm_type;
- if (spi->cfg->set_data_idleness)
+ if (STM32_SPI_MASTER_MODE(spi) && spi->cfg->set_data_idleness)
spi->cfg->set_data_idleness(spi, transfer->len);
if (spi->cur_bpw <= 8)
@@ -1575,7 +1596,8 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi,
dev_dbg(spi->dev,
"data frame of %d-bit, data packet of %d data frames\n",
spi->cur_bpw, spi->cur_fthlv);
- dev_dbg(spi->dev, "speed set to %dHz\n", spi->cur_speed);
+ if (STM32_SPI_MASTER_MODE(spi))
+ dev_dbg(spi->dev, "speed set to %dHz\n", spi->cur_speed);
dev_dbg(spi->dev, "transfer of %d bytes (%d data frames)\n",
spi->cur_xferlen, nb_words);
dev_dbg(spi->dev, "dma %s\n",
@@ -1589,18 +1611,18 @@ out:
/**
* stm32_spi_transfer_one - transfer a single spi_transfer
- * @master: controller master interface
+ * @ctrl: controller interface
* @spi_dev: pointer to the spi device
* @transfer: pointer to spi transfer
*
* It must return 0 if the transfer is finished or 1 if the transfer is still
* in progress.
*/
-static int stm32_spi_transfer_one(struct spi_master *master,
+static int stm32_spi_transfer_one(struct spi_controller *ctrl,
struct spi_device *spi_dev,
struct spi_transfer *transfer)
{
- struct stm32_spi *spi = spi_master_get_devdata(master);
+ struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
int ret;
spi->tx_buf = transfer->tx_buf;
@@ -1608,8 +1630,8 @@ static int stm32_spi_transfer_one(struct spi_master *master,
spi->tx_len = spi->tx_buf ? transfer->len : 0;
spi->rx_len = spi->rx_buf ? transfer->len : 0;
- spi->cur_usedma = (master->can_dma &&
- master->can_dma(master, spi_dev, transfer));
+ spi->cur_usedma = (ctrl->can_dma &&
+ ctrl->can_dma(ctrl, spi_dev, transfer));
ret = stm32_spi_transfer_one_setup(spi, spi_dev, transfer);
if (ret) {
@@ -1625,13 +1647,13 @@ static int stm32_spi_transfer_one(struct spi_master *master,
/**
* stm32_spi_unprepare_msg - relax the hardware
- * @master: controller master interface
+ * @ctrl: controller interface
* @msg: pointer to the spi message
*/
-static int stm32_spi_unprepare_msg(struct spi_master *master,
+static int stm32_spi_unprepare_msg(struct spi_controller *ctrl,
struct spi_message *msg)
{
- struct stm32_spi *spi = spi_master_get_devdata(master);
+ struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
spi->cfg->disable(spi);
@@ -1670,12 +1692,13 @@ static int stm32f4_spi_config(struct stm32_spi *spi)
}
/**
- * stm32h7_spi_config - Configure SPI controller as SPI master
+ * stm32h7_spi_config - Configure SPI controller
* @spi: pointer to the spi controller data structure
*/
static int stm32h7_spi_config(struct stm32_spi *spi)
{
unsigned long flags;
+ u32 cr1 = 0, cfg2 = 0;
spin_lock_irqsave(&spi->lock, flags);
@@ -1683,24 +1706,28 @@ static int stm32h7_spi_config(struct stm32_spi *spi)
stm32_spi_clr_bits(spi, STM32H7_SPI_I2SCFGR,
STM32H7_SPI_I2SCFGR_I2SMOD);
- /*
- * - SS input value high
- * - transmitter half duplex direction
- * - automatic communication suspend when RX-Fifo is full
- */
- stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SSI |
- STM32H7_SPI_CR1_HDDIR |
- STM32H7_SPI_CR1_MASRX);
+ if (STM32_SPI_DEVICE_MODE(spi)) {
+ /* Use native device select */
+ cfg2 &= ~STM32H7_SPI_CFG2_SSM;
+ } else {
+ /*
+ * - Transmitter half duplex direction
+ * - Automatic communication suspend when RX-Fifo is full
+ * - SS input value high
+ */
+ cr1 |= STM32H7_SPI_CR1_HDDIR | STM32H7_SPI_CR1_MASRX | STM32H7_SPI_CR1_SSI;
- /*
- * - Set the master mode (default Motorola mode)
- * - Consider 1 master/n slaves configuration and
- * SS input value is determined by the SSI bit
- * - keep control of all associated GPIOs
- */
- stm32_spi_set_bits(spi, STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_MASTER |
- STM32H7_SPI_CFG2_SSM |
- STM32H7_SPI_CFG2_AFCNTR);
+ /*
+ * - Set the master mode (default Motorola mode)
+ * - Consider 1 master/n devices configuration and
+ * SS input value is determined by the SSI bit
+ * - keep control of all associated GPIOs
+ */
+ cfg2 |= STM32H7_SPI_CFG2_MASTER | STM32H7_SPI_CFG2_SSM | STM32H7_SPI_CFG2_AFCNTR;
+ }
+
+ stm32_spi_set_bits(spi, STM32H7_SPI_CR1, cr1);
+ stm32_spi_set_bits(spi, STM32H7_SPI_CFG2, cfg2);
spin_unlock_irqrestore(&spi->lock, flags);
@@ -1756,24 +1783,38 @@ static const struct of_device_id stm32_spi_of_match[] = {
};
MODULE_DEVICE_TABLE(of, stm32_spi_of_match);
+static int stm32h7_spi_device_abort(struct spi_controller *ctrl)
+{
+ spi_finalize_current_transfer(ctrl);
+ return 0;
+}
+
static int stm32_spi_probe(struct platform_device *pdev)
{
- struct spi_master *master;
+ struct spi_controller *ctrl;
struct stm32_spi *spi;
struct resource *res;
struct reset_control *rst;
+ struct device_node *np = pdev->dev.of_node;
+ bool device_mode;
int ret;
- master = devm_spi_alloc_master(&pdev->dev, sizeof(struct stm32_spi));
- if (!master) {
- dev_err(&pdev->dev, "spi master allocation failed\n");
+ device_mode = of_property_read_bool(np, "spi-slave");
+
+ if (device_mode)
+ ctrl = devm_spi_alloc_slave(&pdev->dev, sizeof(struct stm32_spi));
+ else
+ ctrl = devm_spi_alloc_master(&pdev->dev, sizeof(struct stm32_spi));
+ if (!ctrl) {
+ dev_err(&pdev->dev, "spi controller allocation failed\n");
return -ENOMEM;
}
- platform_set_drvdata(pdev, master);
+ platform_set_drvdata(pdev, ctrl);
- spi = spi_master_get_devdata(master);
+ spi = spi_controller_get_devdata(ctrl);
spi->dev = &pdev->dev;
- spi->master = master;
+ spi->ctrl = ctrl;
+ spi->device_mode = device_mode;
spin_lock_init(&spi->lock);
spi->cfg = (const struct stm32_spi_cfg *)
@@ -1794,7 +1835,7 @@ static int stm32_spi_probe(struct platform_device *pdev)
ret = devm_request_threaded_irq(&pdev->dev, spi->irq,
spi->cfg->irq_handler_event,
spi->cfg->irq_handler_thread,
- IRQF_ONESHOT, pdev->name, master);
+ IRQF_ONESHOT, pdev->name, ctrl);
if (ret) {
dev_err(&pdev->dev, "irq%d request failed: %d\n", spi->irq,
ret);
@@ -1843,19 +1884,21 @@ static int stm32_spi_probe(struct platform_device *pdev)
goto err_clk_disable;
}
- master->dev.of_node = pdev->dev.of_node;
- master->auto_runtime_pm = true;
- master->bus_num = pdev->id;
- master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST |
- SPI_3WIRE;
- master->bits_per_word_mask = spi->cfg->get_bpw_mask(spi);
- master->max_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_min;
- master->min_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_max;
- master->use_gpio_descriptors = true;
- master->prepare_message = stm32_spi_prepare_msg;
- master->transfer_one = stm32_spi_transfer_one;
- master->unprepare_message = stm32_spi_unprepare_msg;
- master->flags = spi->cfg->flags;
+ ctrl->dev.of_node = pdev->dev.of_node;
+ ctrl->auto_runtime_pm = true;
+ ctrl->bus_num = pdev->id;
+ ctrl->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST |
+ SPI_3WIRE;
+ ctrl->bits_per_word_mask = spi->cfg->get_bpw_mask(spi);
+ ctrl->max_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_min;
+ ctrl->min_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_max;
+ ctrl->use_gpio_descriptors = true;
+ ctrl->prepare_message = stm32_spi_prepare_msg;
+ ctrl->transfer_one = stm32_spi_transfer_one;
+ ctrl->unprepare_message = stm32_spi_unprepare_msg;
+ ctrl->flags = spi->cfg->flags;
+ if (STM32_SPI_DEVICE_MODE(spi))
+ ctrl->slave_abort = stm32h7_spi_device_abort;
spi->dma_tx = dma_request_chan(spi->dev, "tx");
if (IS_ERR(spi->dma_tx)) {
@@ -1866,7 +1909,7 @@ static int stm32_spi_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "failed to request tx dma channel\n");
} else {
- master->dma_tx = spi->dma_tx;
+ ctrl->dma_tx = spi->dma_tx;
}
spi->dma_rx = dma_request_chan(spi->dev, "rx");
@@ -1878,11 +1921,11 @@ static int stm32_spi_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "failed to request rx dma channel\n");
} else {
- master->dma_rx = spi->dma_rx;
+ ctrl->dma_rx = spi->dma_rx;
}
if (spi->dma_tx || spi->dma_rx)
- master->can_dma = stm32_spi_can_dma;
+ ctrl->can_dma = stm32_spi_can_dma;
pm_runtime_set_autosuspend_delay(&pdev->dev,
STM32_SPI_AUTOSUSPEND_DELAY);
@@ -1891,9 +1934,9 @@ static int stm32_spi_probe(struct platform_device *pdev)
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_enable(&pdev->dev);
- ret = spi_register_master(master);
+ ret = spi_register_controller(ctrl);
if (ret) {
- dev_err(&pdev->dev, "spi master registration failed: %d\n",
+ dev_err(&pdev->dev, "spi controller registration failed: %d\n",
ret);
goto err_pm_disable;
}
@@ -1901,7 +1944,8 @@ static int stm32_spi_probe(struct platform_device *pdev)
pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
- dev_info(&pdev->dev, "driver initialized\n");
+ dev_info(&pdev->dev, "driver initialized (%s mode)\n",
+ STM32_SPI_MASTER_MODE(spi) ? "master" : "device");
return 0;
@@ -1923,12 +1967,12 @@ err_clk_disable:
static void stm32_spi_remove(struct platform_device *pdev)
{
- struct spi_master *master = platform_get_drvdata(pdev);
- struct stm32_spi *spi = spi_master_get_devdata(master);
+ struct spi_controller *ctrl = platform_get_drvdata(pdev);
+ struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
pm_runtime_get_sync(&pdev->dev);
- spi_unregister_master(master);
+ spi_unregister_controller(ctrl);
spi->cfg->disable(spi);
pm_runtime_disable(&pdev->dev);
@@ -1936,10 +1980,10 @@ static void stm32_spi_remove(struct platform_device *pdev)
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
- if (master->dma_tx)
- dma_release_channel(master->dma_tx);
- if (master->dma_rx)
- dma_release_channel(master->dma_rx);
+ if (ctrl->dma_tx)
+ dma_release_channel(ctrl->dma_tx);
+ if (ctrl->dma_rx)
+ dma_release_channel(ctrl->dma_rx);
clk_disable_unprepare(spi->clk);
@@ -1949,8 +1993,8 @@ static void stm32_spi_remove(struct platform_device *pdev)
static int __maybe_unused stm32_spi_runtime_suspend(struct device *dev)
{
- struct spi_master *master = dev_get_drvdata(dev);
- struct stm32_spi *spi = spi_master_get_devdata(master);
+ struct spi_controller *ctrl = dev_get_drvdata(dev);
+ struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
clk_disable_unprepare(spi->clk);
@@ -1959,8 +2003,8 @@ static int __maybe_unused stm32_spi_runtime_suspend(struct device *dev)
static int __maybe_unused stm32_spi_runtime_resume(struct device *dev)
{
- struct spi_master *master = dev_get_drvdata(dev);
- struct stm32_spi *spi = spi_master_get_devdata(master);
+ struct spi_controller *ctrl = dev_get_drvdata(dev);
+ struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
int ret;
ret = pinctrl_pm_select_default_state(dev);
@@ -1972,10 +2016,10 @@ static int __maybe_unused stm32_spi_runtime_resume(struct device *dev)
static int __maybe_unused stm32_spi_suspend(struct device *dev)
{
- struct spi_master *master = dev_get_drvdata(dev);
+ struct spi_controller *ctrl = dev_get_drvdata(dev);
int ret;
- ret = spi_master_suspend(master);
+ ret = spi_controller_suspend(ctrl);
if (ret)
return ret;
@@ -1984,15 +2028,15 @@ static int __maybe_unused stm32_spi_suspend(struct device *dev)
static int __maybe_unused stm32_spi_resume(struct device *dev)
{
- struct spi_master *master = dev_get_drvdata(dev);
- struct stm32_spi *spi = spi_master_get_devdata(master);
+ struct spi_controller *ctrl = dev_get_drvdata(dev);
+ struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
int ret;
ret = pm_runtime_force_resume(dev);
if (ret)
return ret;
- ret = spi_master_resume(master);
+ ret = spi_controller_resume(ctrl);
if (ret) {
clk_disable_unprepare(spi->clk);
return ret;
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 7532c85a352c..30d541612253 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -42,7 +42,9 @@
#define SUN6I_TFR_CTL_CS_MANUAL BIT(6)
#define SUN6I_TFR_CTL_CS_LEVEL BIT(7)
#define SUN6I_TFR_CTL_DHB BIT(8)
+#define SUN6I_TFR_CTL_SDC BIT(11)
#define SUN6I_TFR_CTL_FBS BIT(12)
+#define SUN6I_TFR_CTL_SDM BIT(13)
#define SUN6I_TFR_CTL_XCH BIT(31)
#define SUN6I_INT_CTL_REG 0x10
@@ -85,6 +87,11 @@
#define SUN6I_TXDATA_REG 0x200
#define SUN6I_RXDATA_REG 0x300
+struct sun6i_spi_cfg {
+ unsigned long fifo_depth;
+ bool has_clk_ctl;
+};
+
struct sun6i_spi {
struct spi_master *master;
void __iomem *base_addr;
@@ -99,7 +106,7 @@ struct sun6i_spi {
const u8 *tx_buf;
u8 *rx_buf;
int len;
- unsigned long fifo_depth;
+ const struct sun6i_spi_cfg *cfg;
};
static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg)
@@ -156,7 +163,7 @@ static inline void sun6i_spi_fill_fifo(struct sun6i_spi *sspi)
u8 byte;
/* See how much data we can fit */
- cnt = sspi->fifo_depth - sun6i_spi_get_tx_fifo_count(sspi);
+ cnt = sspi->cfg->fifo_depth - sun6i_spi_get_tx_fifo_count(sspi);
len = min((int)cnt, sspi->len);
@@ -256,7 +263,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
struct spi_transfer *tfr)
{
struct sun6i_spi *sspi = spi_master_get_devdata(master);
- unsigned int mclk_rate, div, div_cdr1, div_cdr2, timeout;
+ unsigned int div, div_cdr1, div_cdr2, timeout;
unsigned int start, end, tx_time;
unsigned int trig_level;
unsigned int tx_len = 0, rx_len = 0;
@@ -289,14 +296,14 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
* the hardcoded value used in old generation of Allwinner
* SPI controller. (See spi-sun4i.c)
*/
- trig_level = sspi->fifo_depth / 4 * 3;
+ trig_level = sspi->cfg->fifo_depth / 4 * 3;
} else {
/*
* Setup FIFO DMA request trigger level
* We choose 1/2 of the full fifo depth, that value will
* be used as DMA burst length.
*/
- trig_level = sspi->fifo_depth / 2;
+ trig_level = sspi->cfg->fifo_depth / 2;
if (tfr->tx_buf)
reg |= SUN6I_FIFO_CTL_TF_DRQ_EN;
@@ -346,39 +353,65 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
- /* Ensure that we have a parent clock fast enough */
- mclk_rate = clk_get_rate(sspi->mclk);
- if (mclk_rate < (2 * tfr->speed_hz)) {
- clk_set_rate(sspi->mclk, 2 * tfr->speed_hz);
- mclk_rate = clk_get_rate(sspi->mclk);
- }
+ if (sspi->cfg->has_clk_ctl) {
+ unsigned int mclk_rate = clk_get_rate(sspi->mclk);
- /*
- * Setup clock divider.
- *
- * We have two choices there. Either we can use the clock
- * divide rate 1, which is calculated thanks to this formula:
- * SPI_CLK = MOD_CLK / (2 ^ cdr)
- * Or we can use CDR2, which is calculated with the formula:
- * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
- * Wether we use the former or the latter is set through the
- * DRS bit.
- *
- * First try CDR2, and if we can't reach the expected
- * frequency, fall back to CDR1.
- */
- div_cdr1 = DIV_ROUND_UP(mclk_rate, tfr->speed_hz);
- div_cdr2 = DIV_ROUND_UP(div_cdr1, 2);
- if (div_cdr2 <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) {
- reg = SUN6I_CLK_CTL_CDR2(div_cdr2 - 1) | SUN6I_CLK_CTL_DRS;
- tfr->effective_speed_hz = mclk_rate / (2 * div_cdr2);
+ /* Ensure that we have a parent clock fast enough */
+ if (mclk_rate < (2 * tfr->speed_hz)) {
+ clk_set_rate(sspi->mclk, 2 * tfr->speed_hz);
+ mclk_rate = clk_get_rate(sspi->mclk);
+ }
+
+ /*
+ * Setup clock divider.
+ *
+ * We have two choices there. Either we can use the clock
+ * divide rate 1, which is calculated thanks to this formula:
+ * SPI_CLK = MOD_CLK / (2 ^ cdr)
+ * Or we can use CDR2, which is calculated with the formula:
+ * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
+ * Wether we use the former or the latter is set through the
+ * DRS bit.
+ *
+ * First try CDR2, and if we can't reach the expected
+ * frequency, fall back to CDR1.
+ */
+ div_cdr1 = DIV_ROUND_UP(mclk_rate, tfr->speed_hz);
+ div_cdr2 = DIV_ROUND_UP(div_cdr1, 2);
+ if (div_cdr2 <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) {
+ reg = SUN6I_CLK_CTL_CDR2(div_cdr2 - 1) | SUN6I_CLK_CTL_DRS;
+ tfr->effective_speed_hz = mclk_rate / (2 * div_cdr2);
+ } else {
+ div = min(SUN6I_CLK_CTL_CDR1_MASK, order_base_2(div_cdr1));
+ reg = SUN6I_CLK_CTL_CDR1(div);
+ tfr->effective_speed_hz = mclk_rate / (1 << div);
+ }
+
+ sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg);
} else {
- div = min(SUN6I_CLK_CTL_CDR1_MASK, order_base_2(div_cdr1));
- reg = SUN6I_CLK_CTL_CDR1(div);
- tfr->effective_speed_hz = mclk_rate / (1 << div);
+ clk_set_rate(sspi->mclk, tfr->speed_hz);
+ tfr->effective_speed_hz = clk_get_rate(sspi->mclk);
+
+ /*
+ * Configure work mode.
+ *
+ * There are three work modes depending on the controller clock
+ * frequency:
+ * - normal sample mode : CLK <= 24MHz SDM=1 SDC=0
+ * - delay half-cycle sample mode : CLK <= 40MHz SDM=0 SDC=0
+ * - delay one-cycle sample mode : CLK >= 80MHz SDM=0 SDC=1
+ */
+ reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
+ reg &= ~(SUN6I_TFR_CTL_SDM | SUN6I_TFR_CTL_SDC);
+
+ if (tfr->effective_speed_hz <= 24000000)
+ reg |= SUN6I_TFR_CTL_SDM;
+ else if (tfr->effective_speed_hz >= 80000000)
+ reg |= SUN6I_TFR_CTL_SDC;
+
+ sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
}
- sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg);
/* Finally enable the bus - doing so before might raise SCK to HIGH */
reg = sun6i_spi_read(sspi, SUN6I_GBL_CTL_REG);
reg |= SUN6I_GBL_CTL_BUS_ENABLE;
@@ -410,9 +443,9 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
reg = SUN6I_INT_CTL_TC;
if (!use_dma) {
- if (rx_len > sspi->fifo_depth)
+ if (rx_len > sspi->cfg->fifo_depth)
reg |= SUN6I_INT_CTL_RF_RDY;
- if (tx_len > sspi->fifo_depth)
+ if (tx_len > sspi->cfg->fifo_depth)
reg |= SUN6I_INT_CTL_TF_ERQ;
}
@@ -422,7 +455,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
- tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
+ tx_time = spi_controller_xfer_timeout(master, tfr);
start = jiffies;
timeout = wait_for_completion_timeout(&sspi->done,
msecs_to_jiffies(tx_time));
@@ -543,7 +576,7 @@ static bool sun6i_spi_can_dma(struct spi_master *master,
* the fifo length we can just fill the fifo and wait for a single
* irq, so don't bother setting up dma
*/
- return xfer->len > sspi->fifo_depth;
+ return xfer->len > sspi->cfg->fifo_depth;
}
static int sun6i_spi_probe(struct platform_device *pdev)
@@ -582,7 +615,7 @@ static int sun6i_spi_probe(struct platform_device *pdev)
}
sspi->master = master;
- sspi->fifo_depth = (unsigned long)of_device_get_match_data(&pdev->dev);
+ sspi->cfg = of_device_get_match_data(&pdev->dev);
master->max_speed_hz = 100 * 1000 * 1000;
master->min_speed_hz = 3 * 1000;
@@ -695,9 +728,27 @@ static void sun6i_spi_remove(struct platform_device *pdev)
dma_release_channel(master->dma_rx);
}
+static const struct sun6i_spi_cfg sun6i_a31_spi_cfg = {
+ .fifo_depth = SUN6I_FIFO_DEPTH,
+ .has_clk_ctl = true,
+};
+
+static const struct sun6i_spi_cfg sun8i_h3_spi_cfg = {
+ .fifo_depth = SUN8I_FIFO_DEPTH,
+ .has_clk_ctl = true,
+};
+
+static const struct sun6i_spi_cfg sun50i_r329_spi_cfg = {
+ .fifo_depth = SUN8I_FIFO_DEPTH,
+};
+
static const struct of_device_id sun6i_spi_match[] = {
- { .compatible = "allwinner,sun6i-a31-spi", .data = (void *)SUN6I_FIFO_DEPTH },
- { .compatible = "allwinner,sun8i-h3-spi", .data = (void *)SUN8I_FIFO_DEPTH },
+ { .compatible = "allwinner,sun6i-a31-spi", .data = &sun6i_a31_spi_cfg },
+ { .compatible = "allwinner,sun8i-h3-spi", .data = &sun8i_h3_spi_cfg },
+ {
+ .compatible = "allwinner,sun50i-r329-spi",
+ .data = &sun50i_r329_spi_cfg
+ },
{}
};
MODULE_DEVICE_TABLE(of, sun6i_spi_match);
diff --git a/drivers/spi/spi-xcomm.c b/drivers/spi/spi-xcomm.c
index 5d23411f2a3e..ae6218bcd02a 100644
--- a/drivers/spi/spi-xcomm.c
+++ b/drivers/spi/spi-xcomm.c
@@ -241,7 +241,7 @@ static struct i2c_driver spi_xcomm_driver = {
.name = "spi-xcomm",
},
.id_table = spi_xcomm_ids,
- .probe_new = spi_xcomm_probe,
+ .probe = spi_xcomm_probe,
};
module_i2c_driver(spi_xcomm_driver);
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 39d94c850839..d13dc15cc191 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -64,7 +64,8 @@ static_assert(N_SPI_MINORS > 0 && N_SPI_MINORS <= 256);
| SPI_NO_CS | SPI_READY | SPI_TX_DUAL \
| SPI_TX_QUAD | SPI_TX_OCTAL | SPI_RX_DUAL \
| SPI_RX_QUAD | SPI_RX_OCTAL \
- | SPI_RX_CPHA_FLIP)
+ | SPI_RX_CPHA_FLIP | SPI_3WIRE_HIZ \
+ | SPI_MOSI_IDLE_LOW)
struct spidev_data {
dev_t devt;
@@ -237,7 +238,7 @@ static int spidev_message(struct spidev_data *spidev,
/* Ensure that also following allocations from rx_buf/tx_buf will meet
* DMA alignment requirements.
*/
- unsigned int len_aligned = ALIGN(u_tmp->len, ARCH_KMALLOC_MINALIGN);
+ unsigned int len_aligned = ALIGN(u_tmp->len, ARCH_DMA_MINALIGN);
k_tmp->len = u_tmp->len;
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/fbtft/fb_ili9341.c b/drivers/staging/fbtft/fb_ili9341.c
index 9ccd0823c3ab..47e72b87d76d 100644
--- a/drivers/staging/fbtft/fb_ili9341.c
+++ b/drivers/staging/fbtft/fb_ili9341.c
@@ -145,7 +145,7 @@ static struct fbtft_display display = {
},
};
-FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9341", &display);
+FBTFT_REGISTER_SPI_DRIVER(DRVNAME, "ilitek", "ili9341", &display);
MODULE_ALIAS("spi:" DRVNAME);
MODULE_ALIAS("platform:" DRVNAME);
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/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c
index e03c87f0bfe7..0fb97a79ad0b 100644
--- a/drivers/staging/ks7010/ks_wlan_net.c
+++ b/drivers/staging/ks7010/ks_wlan_net.c
@@ -1583,8 +1583,10 @@ static int ks_wlan_set_encode_ext(struct net_device *dev,
commit |= SME_WEP_FLAG;
}
if (enc->key_len) {
- memcpy(&key->key_val[0], &enc->key[0], enc->key_len);
- key->key_len = enc->key_len;
+ int key_len = clamp_val(enc->key_len, 0, IW_ENCODING_TOKEN_MAX);
+
+ memcpy(&key->key_val[0], &enc->key[0], key_len);
+ key->key_len = key_len;
commit |= (SME_WEP_VAL1 << index);
}
break;
diff --git a/drivers/staging/media/atomisp/Kconfig b/drivers/staging/media/atomisp/Kconfig
index c9bff98e5309..e9b168ba97bf 100644
--- a/drivers/staging/media/atomisp/Kconfig
+++ b/drivers/staging/media/atomisp/Kconfig
@@ -13,6 +13,7 @@ config VIDEO_ATOMISP
tristate "Intel Atom Image Signal Processor Driver"
depends on VIDEO_DEV && INTEL_ATOMISP
depends on PMIC_OPREGION
+ select V4L2_FWNODE
select IOSF_MBI
select VIDEOBUF2_VMALLOC
select VIDEO_V4L2_SUBDEV_API
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/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c
index 090345bad223..6353dbe554d3 100644
--- a/drivers/staging/rtl8712/rtl871x_xmit.c
+++ b/drivers/staging/rtl8712/rtl871x_xmit.c
@@ -21,6 +21,7 @@
#include "osdep_intf.h"
#include "usb_ops.h"
+#include <linux/usb.h>
#include <linux/ieee80211.h>
static const u8 P802_1H_OUI[P80211_OUI_LEN] = {0x00, 0x00, 0xf8};
@@ -55,6 +56,7 @@ int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
sint i;
struct xmit_buf *pxmitbuf;
struct xmit_frame *pxframe;
+ int j;
memset((unsigned char *)pxmitpriv, 0, sizeof(struct xmit_priv));
spin_lock_init(&pxmitpriv->lock);
@@ -117,11 +119,8 @@ int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
_init_queue(&pxmitpriv->pending_xmitbuf_queue);
pxmitpriv->pallocated_xmitbuf =
kmalloc(NR_XMITBUFF * sizeof(struct xmit_buf) + 4, GFP_ATOMIC);
- if (!pxmitpriv->pallocated_xmitbuf) {
- kfree(pxmitpriv->pallocated_frame_buf);
- pxmitpriv->pallocated_frame_buf = NULL;
- return -ENOMEM;
- }
+ if (!pxmitpriv->pallocated_xmitbuf)
+ goto clean_up_frame_buf;
pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 -
((addr_t)(pxmitpriv->pallocated_xmitbuf) & 3);
pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
@@ -129,13 +128,17 @@ int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
INIT_LIST_HEAD(&pxmitbuf->list);
pxmitbuf->pallocated_buf =
kmalloc(MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ, GFP_ATOMIC);
- if (!pxmitbuf->pallocated_buf)
- return -ENOMEM;
+ if (!pxmitbuf->pallocated_buf) {
+ j = 0;
+ goto clean_up_alloc_buf;
+ }
pxmitbuf->pbuf = pxmitbuf->pallocated_buf + XMITBUF_ALIGN_SZ -
((addr_t) (pxmitbuf->pallocated_buf) &
(XMITBUF_ALIGN_SZ - 1));
- if (r8712_xmit_resource_alloc(padapter, pxmitbuf))
- return -ENOMEM;
+ if (r8712_xmit_resource_alloc(padapter, pxmitbuf)) {
+ j = 1;
+ goto clean_up_alloc_buf;
+ }
list_add_tail(&pxmitbuf->list,
&(pxmitpriv->free_xmitbuf_queue.queue));
pxmitbuf++;
@@ -146,6 +149,28 @@ int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
tasklet_setup(&pxmitpriv->xmit_tasklet, r8712_xmit_bh);
return 0;
+
+clean_up_alloc_buf:
+ if (j) {
+ /* failure happened in r8712_xmit_resource_alloc()
+ * delete extra pxmitbuf->pallocated_buf
+ */
+ kfree(pxmitbuf->pallocated_buf);
+ }
+ for (j = 0; j < i; j++) {
+ int k;
+
+ pxmitbuf--; /* reset pointer */
+ kfree(pxmitbuf->pallocated_buf);
+ for (k = 0; k < 8; k++) /* delete xmit urb's */
+ usb_free_urb(pxmitbuf->pxmit_urb[k]);
+ }
+ kfree(pxmitpriv->pallocated_xmitbuf);
+ pxmitpriv->pallocated_xmitbuf = NULL;
+clean_up_frame_buf:
+ kfree(pxmitpriv->pallocated_frame_buf);
+ pxmitpriv->pallocated_frame_buf = NULL;
+ return -ENOMEM;
}
void _free_xmit_priv(struct xmit_priv *pxmitpriv)
diff --git a/drivers/staging/rtl8712/xmit_linux.c b/drivers/staging/rtl8712/xmit_linux.c
index 132afbf49dde..ceb6b590b310 100644
--- a/drivers/staging/rtl8712/xmit_linux.c
+++ b/drivers/staging/rtl8712/xmit_linux.c
@@ -112,6 +112,12 @@ int r8712_xmit_resource_alloc(struct _adapter *padapter,
for (i = 0; i < 8; i++) {
pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
if (!pxmitbuf->pxmit_urb[i]) {
+ int k;
+
+ for (k = i - 1; k >= 0; k--) {
+ /* handle allocation errors part way through loop */
+ usb_free_urb(pxmitbuf->pxmit_urb[k]);
+ }
netdev_err(padapter->pnetdev, "pxmitbuf->pxmit_urb[i] == NULL\n");
return -ENOMEM;
}
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 b14835fcb033..91a75a4a7cc1 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -1129,6 +1129,8 @@ int iscsit_fe_sendpage_sg(
struct iscsit_conn *conn)
{
struct scatterlist *sg = cmd->first_data_sg;
+ struct bio_vec bvec;
+ struct msghdr msghdr = { .msg_flags = MSG_SPLICE_PAGES, };
struct kvec iov;
u32 tx_hdr_size, data_len;
u32 offset = cmd->first_data_sg_off;
@@ -1172,17 +1174,18 @@ send_hdr:
u32 space = (sg->length - offset);
u32 sub_len = min_t(u32, data_len, space);
send_pg:
- tx_sent = conn->sock->ops->sendpage(conn->sock,
- sg_page(sg), sg->offset + offset, sub_len, 0);
+ bvec_set_page(&bvec, sg_page(sg), sub_len, sg->offset + offset);
+ iov_iter_bvec(&msghdr.msg_iter, ITER_SOURCE, &bvec, 1, sub_len);
+
+ tx_sent = conn->sock->ops->sendmsg(conn->sock, &msghdr,
+ sub_len);
if (tx_sent != sub_len) {
if (tx_sent == -EAGAIN) {
- pr_err("tcp_sendpage() returned"
- " -EAGAIN\n");
+ pr_err("sendmsg/splice returned -EAGAIN\n");
goto send_pg;
}
- pr_err("tcp_sendpage() failure: %d\n",
- tx_sent);
+ pr_err("sendmsg/splice failure: %d\n", tx_sent);
return -1;
}
@@ -1372,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));
@@ -1411,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 cc838ffd1294..3d1b511ea284 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
@@ -90,7 +93,7 @@ static int iblock_configure_device(struct se_device *dev)
struct request_queue *q;
struct block_device *bd = NULL;
struct blk_integrity *bi;
- fmode_t mode;
+ blk_mode_t mode = BLK_OPEN_READ;
unsigned int max_write_zeroes_sectors;
int ret;
@@ -108,13 +111,12 @@ static int iblock_configure_device(struct se_device *dev)
pr_debug( "IBLOCK: Claiming struct block_device: %s\n",
ib_dev->ibd_udev_path);
- mode = FMODE_READ|FMODE_EXCL;
if (!ib_dev->ibd_readonly)
- mode |= FMODE_WRITE;
+ mode |= BLK_OPEN_WRITE;
else
dev->dev_flags |= DF_READ_ONLY;
- bd = blkdev_get_by_path(ib_dev->ibd_udev_path, mode, ib_dev);
+ bd = blkdev_get_by_path(ib_dev->ibd_udev_path, mode, ib_dev, NULL);
if (IS_ERR(bd)) {
ret = PTR_ERR(bd);
goto out_free_bioset;
@@ -175,7 +177,7 @@ static int iblock_configure_device(struct se_device *dev)
return 0;
out_blkdev_put:
- blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL);
+ blkdev_put(ib_dev->ibd_bd, ib_dev);
out_free_bioset:
bioset_exit(&ib_dev->ibd_bio_set);
out:
@@ -201,7 +203,7 @@ static void iblock_destroy_device(struct se_device *dev)
struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
if (ib_dev->ibd_bd != NULL)
- blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL);
+ blkdev_put(ib_dev->ibd_bd, ib_dev);
bioset_exit(&ib_dev->ibd_bio_set);
}
@@ -310,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;
@@ -318,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;
@@ -331,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);
@@ -343,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,
@@ -759,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;
}
@@ -817,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:
@@ -829,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_AND_ABORT);
+ 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);
@@ -869,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)
@@ -890,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_pscsi.c b/drivers/target/target_core_pscsi.c
index e7425549e39c..0d4f09693ef4 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -366,8 +366,8 @@ static int pscsi_create_type_disk(struct se_device *dev, struct scsi_device *sd)
* Claim exclusive struct block_device access to struct scsi_device
* for TYPE_DISK and TYPE_ZBC using supplied udev_path
*/
- bd = blkdev_get_by_path(dev->udev_path,
- FMODE_WRITE|FMODE_READ|FMODE_EXCL, pdv);
+ bd = blkdev_get_by_path(dev->udev_path, BLK_OPEN_WRITE | BLK_OPEN_READ,
+ pdv, NULL);
if (IS_ERR(bd)) {
pr_err("pSCSI: blkdev_get_by_path() failed\n");
scsi_device_put(sd);
@@ -377,7 +377,7 @@ static int pscsi_create_type_disk(struct se_device *dev, struct scsi_device *sd)
ret = pscsi_add_device_to_list(dev, sd);
if (ret) {
- blkdev_put(pdv->pdv_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL);
+ blkdev_put(pdv->pdv_bd, pdv);
scsi_device_put(sd);
return ret;
}
@@ -565,8 +565,7 @@ static void pscsi_destroy_device(struct se_device *dev)
*/
if ((sd->type == TYPE_DISK || sd->type == TYPE_ZBC) &&
pdv->pdv_bd) {
- blkdev_put(pdv->pdv_bd,
- FMODE_WRITE|FMODE_READ|FMODE_EXCL);
+ blkdev_put(pdv->pdv_bd, pdv);
pdv->pdv_bd = NULL;
}
/*
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/target/target_core_user.c b/drivers/target/target_core_user.c
index 15ffc8d2ac7b..22cc6cac0ba2 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -2820,14 +2820,14 @@ static ssize_t tcmu_dev_config_store(struct config_item *item, const char *page,
pr_err("Unable to reconfigure device\n");
return ret;
}
- strlcpy(udev->dev_config, page, TCMU_CONFIG_LEN);
+ strscpy(udev->dev_config, page, TCMU_CONFIG_LEN);
ret = tcmu_update_uio_info(udev);
if (ret)
return ret;
return count;
}
- strlcpy(udev->dev_config, page, TCMU_CONFIG_LEN);
+ strscpy(udev->dev_config, page, TCMU_CONFIG_LEN);
return count;
}
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/thermal/Kconfig b/drivers/thermal/Kconfig
index 4cd7ab707315..19a4b33cb564 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -130,6 +130,14 @@ config THERMAL_DEFAULT_GOV_POWER_ALLOCATOR
system and device power allocation. This governor can only
operate on cooling devices that implement the power API.
+config THERMAL_DEFAULT_GOV_BANG_BANG
+ bool "bang_bang"
+ depends on THERMAL_GOV_BANG_BANG
+ help
+ Use the bang_bang governor as default. This throttles the
+ devices one step at the time, taking into account the trip
+ point hysteresis.
+
endchoice
config THERMAL_GOV_FAIR_SHARE
diff --git a/drivers/thermal/amlogic_thermal.c b/drivers/thermal/amlogic_thermal.c
index 3abc2dcef408..756b218880a7 100644
--- a/drivers/thermal/amlogic_thermal.c
+++ b/drivers/thermal/amlogic_thermal.c
@@ -282,8 +282,7 @@ static int amlogic_thermal_probe(struct platform_device *pdev)
return ret;
}
- if (devm_thermal_add_hwmon_sysfs(&pdev->dev, pdata->tzd))
- dev_warn(&pdev->dev, "Failed to add hwmon sysfs attributes\n");
+ devm_thermal_add_hwmon_sysfs(&pdev->dev, pdata->tzd);
ret = amlogic_thermal_initialize(pdata);
if (ret)
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index 0e8dfa6a7757..9f6dc4fc9112 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -231,7 +231,7 @@ static void armada380_init(struct platform_device *pdev,
regmap_write(priv->syscon, data->syscon_control0_off, reg);
}
-static void armada_ap806_init(struct platform_device *pdev,
+static void armada_ap80x_init(struct platform_device *pdev,
struct armada_thermal_priv *priv)
{
struct armada_thermal_data *data = priv->data;
@@ -614,7 +614,7 @@ static const struct armada_thermal_data armada380_data = {
};
static const struct armada_thermal_data armada_ap806_data = {
- .init = armada_ap806_init,
+ .init = armada_ap80x_init,
.is_valid_bit = BIT(16),
.temp_shift = 0,
.temp_mask = 0x3ff,
@@ -637,6 +637,30 @@ static const struct armada_thermal_data armada_ap806_data = {
.cpu_nr = 4,
};
+static const struct armada_thermal_data armada_ap807_data = {
+ .init = armada_ap80x_init,
+ .is_valid_bit = BIT(16),
+ .temp_shift = 0,
+ .temp_mask = 0x3ff,
+ .thresh_shift = 3,
+ .hyst_shift = 19,
+ .hyst_mask = 0x3,
+ .coef_b = -128900LL,
+ .coef_m = 394ULL,
+ .coef_div = 1,
+ .inverted = true,
+ .signed_sample = true,
+ .syscon_control0_off = 0x84,
+ .syscon_control1_off = 0x88,
+ .syscon_status_off = 0x8C,
+ .dfx_irq_cause_off = 0x108,
+ .dfx_irq_mask_off = 0x10C,
+ .dfx_overheat_irq = BIT(22),
+ .dfx_server_irq_mask_off = 0x104,
+ .dfx_server_irq_en = BIT(1),
+ .cpu_nr = 4,
+};
+
static const struct armada_thermal_data armada_cp110_data = {
.init = armada_cp110_init,
.is_valid_bit = BIT(10),
@@ -681,6 +705,10 @@ static const struct of_device_id armada_thermal_id_table[] = {
.data = &armada_ap806_data,
},
{
+ .compatible = "marvell,armada-ap807-thermal",
+ .data = &armada_ap807_data,
+ },
+ {
.compatible = "marvell,armada-cp110-thermal",
.data = &armada_cp110_data,
},
diff --git a/drivers/thermal/imx8mm_thermal.c b/drivers/thermal/imx8mm_thermal.c
index d8005e9ec992..d4b40869c7d7 100644
--- a/drivers/thermal/imx8mm_thermal.c
+++ b/drivers/thermal/imx8mm_thermal.c
@@ -343,8 +343,7 @@ static int imx8mm_tmu_probe(struct platform_device *pdev)
}
tmu->sensors[i].hw_id = i;
- if (devm_thermal_add_hwmon_sysfs(&pdev->dev, tmu->sensors[i].tzd))
- dev_warn(&pdev->dev, "failed to add hwmon sysfs attributes\n");
+ devm_thermal_add_hwmon_sysfs(&pdev->dev, tmu->sensors[i].tzd);
}
platform_set_drvdata(pdev, tmu);
diff --git a/drivers/thermal/imx_sc_thermal.c b/drivers/thermal/imx_sc_thermal.c
index 839bb9958f60..8d6b4ef23746 100644
--- a/drivers/thermal/imx_sc_thermal.c
+++ b/drivers/thermal/imx_sc_thermal.c
@@ -116,8 +116,7 @@ static int imx_sc_thermal_probe(struct platform_device *pdev)
return ret;
}
- if (devm_thermal_add_hwmon_sysfs(&pdev->dev, sensor->tzd))
- dev_warn(&pdev->dev, "failed to add hwmon sysfs attributes\n");
+ devm_thermal_add_hwmon_sysfs(&pdev->dev, sensor->tzd);
}
return 0;
diff --git a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c
index 01b80331eab6..dc519a665c18 100644
--- a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c
+++ b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c
@@ -203,6 +203,151 @@ end:
}
EXPORT_SYMBOL(acpi_parse_art);
+/*
+ * acpi_parse_psvt - Passive Table (PSVT) for passive cooling
+ *
+ * @handle: ACPI handle of the device which contains PSVT
+ * @psvt_count: the number of valid entries resulted from parsing PSVT
+ * @psvtp: pointer to array of psvt entries
+ *
+ */
+static int acpi_parse_psvt(acpi_handle handle, int *psvt_count, struct psvt **psvtp)
+{
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ int nr_bad_entries = 0, revision = 0;
+ union acpi_object *p;
+ acpi_status status;
+ int i, result = 0;
+ struct psvt *psvts;
+
+ if (!acpi_has_method(handle, "PSVT"))
+ return -ENODEV;
+
+ status = acpi_evaluate_object(handle, "PSVT", NULL, &buffer);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ p = buffer.pointer;
+ if (!p || (p->type != ACPI_TYPE_PACKAGE)) {
+ result = -EFAULT;
+ goto end;
+ }
+
+ /* first package is the revision number */
+ if (p->package.count > 0) {
+ union acpi_object *prev = &(p->package.elements[0]);
+
+ if (prev->type == ACPI_TYPE_INTEGER)
+ revision = (int)prev->integer.value;
+ } else {
+ result = -EFAULT;
+ goto end;
+ }
+
+ /* Support only version 2 */
+ if (revision != 2) {
+ result = -EFAULT;
+ goto end;
+ }
+
+ *psvt_count = p->package.count - 1;
+ if (!*psvt_count) {
+ result = -EFAULT;
+ goto end;
+ }
+
+ psvts = kcalloc(*psvt_count, sizeof(*psvts), GFP_KERNEL);
+ if (!psvts) {
+ result = -ENOMEM;
+ goto end;
+ }
+
+ /* Start index is 1 because the first package is the revision number */
+ for (i = 1; i < p->package.count; i++) {
+ struct acpi_buffer psvt_int_format = { sizeof("RRNNNNNNNNNN"), "RRNNNNNNNNNN" };
+ struct acpi_buffer psvt_str_format = { sizeof("RRNNNNNSNNNN"), "RRNNNNNSNNNN" };
+ union acpi_object *package = &(p->package.elements[i]);
+ struct psvt *psvt = &psvts[i - 1 - nr_bad_entries];
+ struct acpi_buffer *psvt_format = &psvt_int_format;
+ struct acpi_buffer element = { 0, NULL };
+ union acpi_object *knob;
+ struct acpi_device *res;
+ struct psvt *psvt_ptr;
+
+ element.length = ACPI_ALLOCATE_BUFFER;
+ element.pointer = NULL;
+
+ if (package->package.count >= ACPI_NR_PSVT_ELEMENTS) {
+ knob = &(package->package.elements[ACPI_PSVT_CONTROL_KNOB]);
+ } else {
+ nr_bad_entries++;
+ pr_info("PSVT package %d is invalid, ignored\n", i);
+ continue;
+ }
+
+ if (knob->type == ACPI_TYPE_STRING) {
+ psvt_format = &psvt_str_format;
+ if (knob->string.length > ACPI_LIMIT_STR_MAX_LEN - 1) {
+ pr_info("PSVT package %d limit string len exceeds max\n", i);
+ knob->string.length = ACPI_LIMIT_STR_MAX_LEN - 1;
+ }
+ }
+
+ status = acpi_extract_package(&(p->package.elements[i]), psvt_format, &element);
+ if (ACPI_FAILURE(status)) {
+ nr_bad_entries++;
+ pr_info("PSVT package %d is invalid, ignored\n", i);
+ continue;
+ }
+
+ psvt_ptr = (struct psvt *)element.pointer;
+
+ memcpy(psvt, psvt_ptr, sizeof(*psvt));
+
+ /* The limit element can be string or U64 */
+ psvt->control_knob_type = (u64)knob->type;
+
+ if (knob->type == ACPI_TYPE_STRING) {
+ memset(&psvt->limit, 0, sizeof(u64));
+ strncpy(psvt->limit.string, psvt_ptr->limit.str_ptr, knob->string.length);
+ } else {
+ psvt->limit.integer = psvt_ptr->limit.integer;
+ }
+
+ kfree(element.pointer);
+
+ res = acpi_fetch_acpi_dev(psvt->source);
+ if (!res) {
+ nr_bad_entries++;
+ pr_info("Failed to get source ACPI device\n");
+ continue;
+ }
+
+ res = acpi_fetch_acpi_dev(psvt->target);
+ if (!res) {
+ nr_bad_entries++;
+ pr_info("Failed to get target ACPI device\n");
+ continue;
+ }
+ }
+
+ /* don't count bad entries */
+ *psvt_count -= nr_bad_entries;
+
+ if (!*psvt_count) {
+ result = -EFAULT;
+ kfree(psvts);
+ goto end;
+ }
+
+ *psvtp = psvts;
+
+ return 0;
+
+end:
+ kfree(buffer.pointer);
+ return result;
+}
/* get device name from acpi handle */
static void get_single_name(acpi_handle handle, char *name)
@@ -289,6 +434,57 @@ free_trt:
return ret;
}
+static int fill_psvt(char __user *ubuf)
+{
+ int i, ret, count, psvt_len;
+ union psvt_object *psvt_user;
+ struct psvt *psvts;
+
+ ret = acpi_parse_psvt(acpi_thermal_rel_handle, &count, &psvts);
+ if (ret)
+ return ret;
+
+ psvt_len = count * sizeof(*psvt_user);
+
+ psvt_user = kzalloc(psvt_len, GFP_KERNEL);
+ if (!psvt_user) {
+ ret = -ENOMEM;
+ goto free_psvt;
+ }
+
+ /* now fill in user psvt data */
+ for (i = 0; i < count; i++) {
+ /* userspace psvt needs device name instead of acpi reference */
+ get_single_name(psvts[i].source, psvt_user[i].source_device);
+ get_single_name(psvts[i].target, psvt_user[i].target_device);
+
+ psvt_user[i].priority = psvts[i].priority;
+ psvt_user[i].sample_period = psvts[i].sample_period;
+ psvt_user[i].passive_temp = psvts[i].passive_temp;
+ psvt_user[i].source_domain = psvts[i].source_domain;
+ psvt_user[i].control_knob = psvts[i].control_knob;
+ psvt_user[i].step_size = psvts[i].step_size;
+ psvt_user[i].limit_coeff = psvts[i].limit_coeff;
+ psvt_user[i].unlimit_coeff = psvts[i].unlimit_coeff;
+ psvt_user[i].control_knob_type = psvts[i].control_knob_type;
+ if (psvt_user[i].control_knob_type == ACPI_TYPE_STRING)
+ strncpy(psvt_user[i].limit.string, psvts[i].limit.string,
+ ACPI_LIMIT_STR_MAX_LEN);
+ else
+ psvt_user[i].limit.integer = psvts[i].limit.integer;
+
+ }
+
+ if (copy_to_user(ubuf, psvt_user, psvt_len))
+ ret = -EFAULT;
+
+ kfree(psvt_user);
+
+free_psvt:
+ kfree(psvts);
+ return ret;
+}
+
static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd,
unsigned long __arg)
{
@@ -298,6 +494,7 @@ static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd,
char __user *arg = (void __user *)__arg;
struct trt *trts = NULL;
struct art *arts = NULL;
+ struct psvt *psvts;
switch (cmd) {
case ACPI_THERMAL_GET_TRT_COUNT:
@@ -336,6 +533,27 @@ static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd,
case ACPI_THERMAL_GET_ART:
return fill_art(arg);
+ case ACPI_THERMAL_GET_PSVT_COUNT:
+ ret = acpi_parse_psvt(acpi_thermal_rel_handle, &count, &psvts);
+ if (!ret) {
+ kfree(psvts);
+ return put_user(count, (unsigned long __user *)__arg);
+ }
+ return ret;
+
+ case ACPI_THERMAL_GET_PSVT_LEN:
+ /* total length of the data retrieved (count * PSVT entry size) */
+ ret = acpi_parse_psvt(acpi_thermal_rel_handle, &count, &psvts);
+ length = count * sizeof(union psvt_object);
+ if (!ret) {
+ kfree(psvts);
+ return put_user(length, (unsigned long __user *)__arg);
+ }
+ return ret;
+
+ case ACPI_THERMAL_GET_PSVT:
+ return fill_psvt(arg);
+
default:
return -ENOTTY;
}
diff --git a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h
index 78d942477035..ac376d8f9ee4 100644
--- a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h
+++ b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h
@@ -14,6 +14,16 @@
#define ACPI_THERMAL_GET_TRT _IOR(ACPI_THERMAL_MAGIC, 5, unsigned long)
#define ACPI_THERMAL_GET_ART _IOR(ACPI_THERMAL_MAGIC, 6, unsigned long)
+/*
+ * ACPI_THERMAL_GET_PSVT_COUNT = Number of PSVT entries
+ * ACPI_THERMAL_GET_PSVT_LEN = Total return data size (PSVT count x each
+ * PSVT entry size)
+ * ACPI_THERMAL_GET_PSVT = Get the data as an array of psvt_objects
+ */
+#define ACPI_THERMAL_GET_PSVT_LEN _IOR(ACPI_THERMAL_MAGIC, 7, unsigned long)
+#define ACPI_THERMAL_GET_PSVT_COUNT _IOR(ACPI_THERMAL_MAGIC, 8, unsigned long)
+#define ACPI_THERMAL_GET_PSVT _IOR(ACPI_THERMAL_MAGIC, 9, unsigned long)
+
struct art {
acpi_handle source;
acpi_handle target;
@@ -43,6 +53,32 @@ struct trt {
u64 reserved4;
} __packed;
+#define ACPI_NR_PSVT_ELEMENTS 12
+#define ACPI_PSVT_CONTROL_KNOB 7
+#define ACPI_LIMIT_STR_MAX_LEN 8
+
+struct psvt {
+ acpi_handle source;
+ acpi_handle target;
+ u64 priority;
+ u64 sample_period;
+ u64 passive_temp;
+ u64 source_domain;
+ u64 control_knob;
+ union {
+ /* For limit_type = ACPI_TYPE_INTEGER */
+ u64 integer;
+ /* For limit_type = ACPI_TYPE_STRING */
+ char string[ACPI_LIMIT_STR_MAX_LEN];
+ char *str_ptr;
+ } limit;
+ u64 step_size;
+ u64 limit_coeff;
+ u64 unlimit_coeff;
+ /* Spec calls this field reserved, so we borrow it for type info */
+ u64 control_knob_type; /* ACPI_TYPE_STRING or ACPI_TYPE_INTEGER */
+} __packed;
+
#define ACPI_NR_ART_ELEMENTS 13
/* for usrspace */
union art_object {
@@ -77,6 +113,27 @@ union trt_object {
u64 __data[8];
};
+union psvt_object {
+ struct {
+ char source_device[8];
+ char target_device[8];
+ u64 priority;
+ u64 sample_period;
+ u64 passive_temp;
+ u64 source_domain;
+ u64 control_knob;
+ union {
+ u64 integer;
+ char string[ACPI_LIMIT_STR_MAX_LEN];
+ } limit;
+ u64 step_size;
+ u64 limit_coeff;
+ u64 unlimit_coeff;
+ u64 control_knob_type;
+ };
+ u64 __data[ACPI_NR_PSVT_ELEMENTS];
+};
+
#ifdef __KERNEL__
int acpi_thermal_rel_misc_device_add(acpi_handle handle);
int acpi_thermal_rel_misc_device_remove(acpi_handle handle);
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c
index a205221ec8df..2f00fc3bf274 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c
@@ -15,8 +15,8 @@ static const struct rapl_mmio_regs rapl_mmio_default = {
.reg_unit = 0x5938,
.regs[RAPL_DOMAIN_PACKAGE] = { 0x59a0, 0x593c, 0x58f0, 0, 0x5930},
.regs[RAPL_DOMAIN_DRAM] = { 0x58e0, 0x58e8, 0x58ec, 0, 0},
- .limits[RAPL_DOMAIN_PACKAGE] = 2,
- .limits[RAPL_DOMAIN_DRAM] = 2,
+ .limits[RAPL_DOMAIN_PACKAGE] = BIT(POWER_LIMIT2),
+ .limits[RAPL_DOMAIN_DRAM] = BIT(POWER_LIMIT2),
};
static int rapl_mmio_cpu_online(unsigned int cpu)
@@ -27,9 +27,9 @@ static int rapl_mmio_cpu_online(unsigned int cpu)
if (topology_physical_package_id(cpu))
return 0;
- rp = rapl_find_package_domain(cpu, &rapl_mmio_priv);
+ rp = rapl_find_package_domain(cpu, &rapl_mmio_priv, true);
if (!rp) {
- rp = rapl_add_package(cpu, &rapl_mmio_priv);
+ rp = rapl_add_package(cpu, &rapl_mmio_priv, true);
if (IS_ERR(rp))
return PTR_ERR(rp);
}
@@ -42,7 +42,7 @@ static int rapl_mmio_cpu_down_prep(unsigned int cpu)
struct rapl_package *rp;
int lead_cpu;
- rp = rapl_find_package_domain(cpu, &rapl_mmio_priv);
+ rp = rapl_find_package_domain(cpu, &rapl_mmio_priv, true);
if (!rp)
return 0;
@@ -57,10 +57,10 @@ static int rapl_mmio_cpu_down_prep(unsigned int cpu)
static int rapl_mmio_read_raw(int cpu, struct reg_action *ra)
{
- if (!ra->reg)
+ if (!ra->reg.mmio)
return -EINVAL;
- ra->value = readq((void __iomem *)ra->reg);
+ ra->value = readq(ra->reg.mmio);
ra->value &= ra->mask;
return 0;
}
@@ -69,13 +69,13 @@ static int rapl_mmio_write_raw(int cpu, struct reg_action *ra)
{
u64 val;
- if (!ra->reg)
+ if (!ra->reg.mmio)
return -EINVAL;
- val = readq((void __iomem *)ra->reg);
+ val = readq(ra->reg.mmio);
val &= ~ra->mask;
val |= ra->value;
- writeq(val, (void __iomem *)ra->reg);
+ writeq(val, ra->reg.mmio);
return 0;
}
@@ -92,12 +92,13 @@ int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc
for (domain = RAPL_DOMAIN_PACKAGE; domain < RAPL_DOMAIN_MAX; domain++) {
for (reg = RAPL_DOMAIN_REG_LIMIT; reg < RAPL_DOMAIN_REG_MAX; reg++)
if (rapl_regs->regs[domain][reg])
- rapl_mmio_priv.regs[domain][reg] =
- (u64)proc_priv->mmio_base +
+ rapl_mmio_priv.regs[domain][reg].mmio =
+ proc_priv->mmio_base +
rapl_regs->regs[domain][reg];
rapl_mmio_priv.limits[domain] = rapl_regs->limits[domain];
}
- rapl_mmio_priv.reg_unit = (u64)proc_priv->mmio_base + rapl_regs->reg_unit;
+ rapl_mmio_priv.type = RAPL_IF_MMIO;
+ rapl_mmio_priv.reg_unit.mmio = proc_priv->mmio_base + rapl_regs->reg_unit;
rapl_mmio_priv.read_raw = rapl_mmio_read_raw;
rapl_mmio_priv.write_raw = rapl_mmio_write_raw;
diff --git a/drivers/thermal/k3_bandgap.c b/drivers/thermal/k3_bandgap.c
index 791210458606..1c3e590157ec 100644
--- a/drivers/thermal/k3_bandgap.c
+++ b/drivers/thermal/k3_bandgap.c
@@ -222,8 +222,7 @@ static int k3_bandgap_probe(struct platform_device *pdev)
goto err_alloc;
}
- if (devm_thermal_add_hwmon_sysfs(dev, data[id].tzd))
- dev_warn(dev, "Failed to add hwmon sysfs attributes\n");
+ devm_thermal_add_hwmon_sysfs(dev, data[id].tzd);
}
platform_set_drvdata(pdev, bgp);
diff --git a/drivers/thermal/mediatek/auxadc_thermal.c b/drivers/thermal/mediatek/auxadc_thermal.c
index 0b5528804bbd..f59d36de20a0 100644
--- a/drivers/thermal/mediatek/auxadc_thermal.c
+++ b/drivers/thermal/mediatek/auxadc_thermal.c
@@ -1222,12 +1222,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
return -ENODEV;
}
- auxadc_base = devm_of_iomap(&pdev->dev, auxadc, 0, NULL);
- if (IS_ERR(auxadc_base)) {
- of_node_put(auxadc);
- return PTR_ERR(auxadc_base);
- }
-
+ auxadc_base = of_iomap(auxadc, 0);
auxadc_phys_base = of_get_phys_base(auxadc);
of_node_put(auxadc);
@@ -1243,12 +1238,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
return -ENODEV;
}
- apmixed_base = devm_of_iomap(&pdev->dev, apmixedsys, 0, NULL);
- if (IS_ERR(apmixed_base)) {
- of_node_put(apmixedsys);
- return PTR_ERR(apmixed_base);
- }
-
+ apmixed_base = of_iomap(apmixedsys, 0);
apmixed_phys_base = of_get_phys_base(apmixedsys);
of_node_put(apmixedsys);
diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c
index d0a3f95b7884..b693fac2d677 100644
--- a/drivers/thermal/mediatek/lvts_thermal.c
+++ b/drivers/thermal/mediatek/lvts_thermal.c
@@ -19,6 +19,8 @@
#include <linux/thermal.h>
#include <dt-bindings/thermal/mediatek,lvts-thermal.h>
+#include "../thermal_hwmon.h"
+
#define LVTS_MONCTL0(__base) (__base + 0x0000)
#define LVTS_MONCTL1(__base) (__base + 0x0004)
#define LVTS_MONCTL2(__base) (__base + 0x0008)
@@ -996,6 +998,8 @@ static int lvts_ctrl_start(struct device *dev, struct lvts_ctrl *lvts_ctrl)
return PTR_ERR(tz);
}
+ devm_thermal_add_hwmon_sysfs(dev, tz);
+
/*
* The thermal zone pointer will be needed in the
* interrupt handler, we store it in the sensor
diff --git a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c
index 5749149ae2e4..5ddc39b2be32 100644
--- a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c
+++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c
@@ -689,9 +689,7 @@ static int adc_tm5_register_tzd(struct adc_tm5_chip *adc_tm)
return PTR_ERR(tzd);
}
adc_tm->channels[i].tzd = tzd;
- if (devm_thermal_add_hwmon_sysfs(adc_tm->dev, tzd))
- dev_warn(adc_tm->dev,
- "Failed to add hwmon sysfs attributes\n");
+ devm_thermal_add_hwmon_sysfs(adc_tm->dev, tzd);
}
return 0;
diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
index 0f88e98428ac..0e8ebfcd84c5 100644
--- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
+++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
@@ -411,22 +411,19 @@ static int qpnp_tm_probe(struct platform_device *pdev)
chip->base = res;
ret = qpnp_tm_read(chip, QPNP_TM_REG_TYPE, &type);
- if (ret < 0) {
- dev_err(&pdev->dev, "could not read type\n");
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "could not read type\n");
ret = qpnp_tm_read(chip, QPNP_TM_REG_SUBTYPE, &subtype);
- if (ret < 0) {
- dev_err(&pdev->dev, "could not read subtype\n");
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "could not read subtype\n");
ret = qpnp_tm_read(chip, QPNP_TM_REG_DIG_MAJOR, &dig_major);
- if (ret < 0) {
- dev_err(&pdev->dev, "could not read dig_major\n");
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "could not read dig_major\n");
if (type != QPNP_TM_TYPE || (subtype != QPNP_TM_SUBTYPE_GEN1
&& subtype != QPNP_TM_SUBTYPE_GEN2)) {
@@ -448,20 +445,15 @@ static int qpnp_tm_probe(struct platform_device *pdev)
*/
chip->tz_dev = devm_thermal_of_zone_register(
&pdev->dev, 0, chip, &qpnp_tm_sensor_ops);
- if (IS_ERR(chip->tz_dev)) {
- dev_err(&pdev->dev, "failed to register sensor\n");
- return PTR_ERR(chip->tz_dev);
- }
+ if (IS_ERR(chip->tz_dev))
+ return dev_err_probe(&pdev->dev, PTR_ERR(chip->tz_dev),
+ "failed to register sensor\n");
ret = qpnp_tm_init(chip);
- if (ret < 0) {
- dev_err(&pdev->dev, "init failed\n");
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret, "init failed\n");
- if (devm_thermal_add_hwmon_sysfs(&pdev->dev, chip->tz_dev))
- dev_warn(&pdev->dev,
- "Failed to add hwmon sysfs attributes\n");
+ devm_thermal_add_hwmon_sysfs(&pdev->dev, chip->tz_dev);
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, qpnp_tm_isr,
IRQF_ONESHOT, node->name, chip);
diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c
index e89c6f39a3ae..a941b4241b0a 100644
--- a/drivers/thermal/qcom/tsens-v0_1.c
+++ b/drivers/thermal/qcom/tsens-v0_1.c
@@ -39,26 +39,6 @@ struct tsens_legacy_calibration_format tsens_8916_nvmem = {
},
};
-struct tsens_legacy_calibration_format tsens_8939_nvmem = {
- .base_len = 8,
- .base_shift = 2,
- .sp_len = 6,
- .mode = { 12, 0 },
- .invalid = { 12, 2 },
- .base = { { 0, 0 }, { 1, 24 } },
- .sp = {
- { { 12, 3 }, { 12, 9 } },
- { { 12, 15 }, { 12, 21 } },
- { { 12, 27 }, { 13, 1 } },
- { { 13, 7 }, { 13, 13 } },
- { { 13, 19 }, { 13, 25 } },
- { { 0, 8 }, { 0, 14 } },
- { { 0, 20 }, { 0, 26 } },
- { { 1, 0 }, { 1, 6 } },
- { { 1, 12 }, { 1, 18 } },
- },
-};
-
struct tsens_legacy_calibration_format tsens_8974_nvmem = {
.base_len = 8,
.base_shift = 2,
@@ -103,22 +83,6 @@ struct tsens_legacy_calibration_format tsens_8974_backup_nvmem = {
},
};
-struct tsens_legacy_calibration_format tsens_9607_nvmem = {
- .base_len = 8,
- .base_shift = 2,
- .sp_len = 6,
- .mode = { 2, 20 },
- .invalid = { 2, 22 },
- .base = { { 0, 0 }, { 2, 12 } },
- .sp = {
- { { 0, 8 }, { 0, 14 } },
- { { 0, 20 }, { 0, 26 } },
- { { 1, 0 }, { 1, 6 } },
- { { 1, 12 }, { 1, 18 } },
- { { 2, 0 }, { 2, 6 } },
- },
-};
-
static int calibrate_8916(struct tsens_priv *priv)
{
u32 p1[5], p2[5];
@@ -243,6 +207,39 @@ static int calibrate_8974(struct tsens_priv *priv)
return 0;
}
+static int __init init_8226(struct tsens_priv *priv)
+{
+ priv->sensor[0].slope = 2901;
+ priv->sensor[1].slope = 2846;
+ priv->sensor[2].slope = 3038;
+ priv->sensor[3].slope = 2955;
+ priv->sensor[4].slope = 2901;
+ priv->sensor[5].slope = 2846;
+
+ return init_common(priv);
+}
+
+static int __init init_8909(struct tsens_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->num_sensors; ++i)
+ priv->sensor[i].slope = 3000;
+
+ priv->sensor[0].p1_calib_offset = 0;
+ priv->sensor[0].p2_calib_offset = 0;
+ priv->sensor[1].p1_calib_offset = -10;
+ priv->sensor[1].p2_calib_offset = -6;
+ priv->sensor[2].p1_calib_offset = 0;
+ priv->sensor[2].p2_calib_offset = 0;
+ priv->sensor[3].p1_calib_offset = -9;
+ priv->sensor[3].p2_calib_offset = -9;
+ priv->sensor[4].p1_calib_offset = -8;
+ priv->sensor[4].p2_calib_offset = -10;
+
+ return init_common(priv);
+}
+
static int __init init_8939(struct tsens_priv *priv) {
priv->sensor[0].slope = 2911;
priv->sensor[1].slope = 2789;
@@ -258,7 +255,28 @@ static int __init init_8939(struct tsens_priv *priv) {
return init_common(priv);
}
-/* v0.1: 8916, 8939, 8974, 9607 */
+static int __init init_9607(struct tsens_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->num_sensors; ++i)
+ priv->sensor[i].slope = 3000;
+
+ priv->sensor[0].p1_calib_offset = 1;
+ priv->sensor[0].p2_calib_offset = 1;
+ priv->sensor[1].p1_calib_offset = -4;
+ priv->sensor[1].p2_calib_offset = -2;
+ priv->sensor[2].p1_calib_offset = 4;
+ priv->sensor[2].p2_calib_offset = 8;
+ priv->sensor[3].p1_calib_offset = -3;
+ priv->sensor[3].p2_calib_offset = -5;
+ priv->sensor[4].p1_calib_offset = -4;
+ priv->sensor[4].p2_calib_offset = -4;
+
+ return init_common(priv);
+}
+
+/* v0.1: 8226, 8909, 8916, 8939, 8974, 9607 */
static struct tsens_features tsens_v0_1_feat = {
.ver_major = VER_0_1,
@@ -313,6 +331,32 @@ static const struct tsens_ops ops_v0_1 = {
.get_temp = get_temp_common,
};
+static const struct tsens_ops ops_8226 = {
+ .init = init_8226,
+ .calibrate = tsens_calibrate_common,
+ .get_temp = get_temp_common,
+};
+
+struct tsens_plat_data data_8226 = {
+ .num_sensors = 6,
+ .ops = &ops_8226,
+ .feat = &tsens_v0_1_feat,
+ .fields = tsens_v0_1_regfields,
+};
+
+static const struct tsens_ops ops_8909 = {
+ .init = init_8909,
+ .calibrate = tsens_calibrate_common,
+ .get_temp = get_temp_common,
+};
+
+struct tsens_plat_data data_8909 = {
+ .num_sensors = 5,
+ .ops = &ops_8909,
+ .feat = &tsens_v0_1_feat,
+ .fields = tsens_v0_1_regfields,
+};
+
static const struct tsens_ops ops_8916 = {
.init = init_common,
.calibrate = calibrate_8916,
@@ -356,9 +400,15 @@ struct tsens_plat_data data_8974 = {
.fields = tsens_v0_1_regfields,
};
+static const struct tsens_ops ops_9607 = {
+ .init = init_9607,
+ .calibrate = tsens_calibrate_common,
+ .get_temp = get_temp_common,
+};
+
struct tsens_plat_data data_9607 = {
.num_sensors = 5,
- .ops = &ops_v0_1,
+ .ops = &ops_9607,
.feat = &tsens_v0_1_feat,
.fields = tsens_v0_1_regfields,
};
diff --git a/drivers/thermal/qcom/tsens-v1.c b/drivers/thermal/qcom/tsens-v1.c
index b822a426066d..51322430f1fe 100644
--- a/drivers/thermal/qcom/tsens-v1.c
+++ b/drivers/thermal/qcom/tsens-v1.c
@@ -42,28 +42,6 @@ struct tsens_legacy_calibration_format tsens_qcs404_nvmem = {
},
};
-struct tsens_legacy_calibration_format tsens_8976_nvmem = {
- .base_len = 8,
- .base_shift = 2,
- .sp_len = 6,
- .mode = { 4, 0 },
- .invalid = { 4, 2 },
- .base = { { 0, 0 }, { 2, 8 } },
- .sp = {
- { { 0, 8 }, { 0, 14 } },
- { { 0, 20 }, { 0, 26 } },
- { { 1, 0 }, { 1, 6 } },
- { { 1, 12 }, { 1, 18 } },
- { { 2, 8 }, { 2, 14 } },
- { { 2, 20 }, { 2, 26 } },
- { { 3, 0 }, { 3, 6 } },
- { { 3, 12 }, { 3, 18 } },
- { { 4, 2 }, { 4, 9 } },
- { { 4, 14 }, { 4, 21 } },
- { { 4, 26 }, { 5, 1 } },
- },
-};
-
static int calibrate_v1(struct tsens_priv *priv)
{
u32 p1[10], p2[10];
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index d3218127e617..98c356acfe98 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -134,10 +134,12 @@ int tsens_read_calibration(struct tsens_priv *priv, int shift, u32 *p1, u32 *p2,
p1[i] = p1[i] + (base1 << shift);
break;
case TWO_PT_CALIB:
+ case TWO_PT_CALIB_NO_OFFSET:
for (i = 0; i < priv->num_sensors; i++)
p2[i] = (p2[i] + base2) << shift;
fallthrough;
case ONE_PT_CALIB2:
+ case ONE_PT_CALIB2_NO_OFFSET:
for (i = 0; i < priv->num_sensors; i++)
p1[i] = (p1[i] + base1) << shift;
break;
@@ -149,6 +151,18 @@ int tsens_read_calibration(struct tsens_priv *priv, int shift, u32 *p1, u32 *p2,
}
}
+ /* Apply calibration offset workaround except for _NO_OFFSET modes */
+ switch (mode) {
+ case TWO_PT_CALIB:
+ for (i = 0; i < priv->num_sensors; i++)
+ p2[i] += priv->sensor[i].p2_calib_offset;
+ fallthrough;
+ case ONE_PT_CALIB2:
+ for (i = 0; i < priv->num_sensors; i++)
+ p1[i] += priv->sensor[i].p1_calib_offset;
+ break;
+ }
+
return mode;
}
@@ -254,7 +268,7 @@ void compute_intercept_slope(struct tsens_priv *priv, u32 *p1,
if (!priv->sensor[i].slope)
priv->sensor[i].slope = SLOPE_DEFAULT;
- if (mode == TWO_PT_CALIB) {
+ if (mode == TWO_PT_CALIB || mode == TWO_PT_CALIB_NO_OFFSET) {
/*
* slope (m) = adc_code2 - adc_code1 (y2 - y1)/
* temp_120_degc - temp_30_degc (x2 - x1)
@@ -1096,6 +1110,12 @@ static const struct of_device_id tsens_table[] = {
.compatible = "qcom,mdm9607-tsens",
.data = &data_9607,
}, {
+ .compatible = "qcom,msm8226-tsens",
+ .data = &data_8226,
+ }, {
+ .compatible = "qcom,msm8909-tsens",
+ .data = &data_8909,
+ }, {
.compatible = "qcom,msm8916-tsens",
.data = &data_8916,
}, {
@@ -1189,9 +1209,7 @@ static int tsens_register(struct tsens_priv *priv)
if (priv->ops->enable)
priv->ops->enable(priv, i);
- if (devm_thermal_add_hwmon_sysfs(priv->dev, tzd))
- dev_warn(priv->dev,
- "Failed to add hwmon sysfs attributes\n");
+ devm_thermal_add_hwmon_sysfs(priv->dev, tzd);
}
/* VER_0 require to set MIN and MAX THRESH
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index dba9cd38f637..2805de1c6827 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -10,6 +10,8 @@
#define ONE_PT_CALIB 0x1
#define ONE_PT_CALIB2 0x2
#define TWO_PT_CALIB 0x3
+#define ONE_PT_CALIB2_NO_OFFSET 0x6
+#define TWO_PT_CALIB_NO_OFFSET 0x7
#define CAL_DEGC_PT1 30
#define CAL_DEGC_PT2 120
#define SLOPE_FACTOR 1000
@@ -57,6 +59,8 @@ struct tsens_sensor {
unsigned int hw_id;
int slope;
u32 status;
+ int p1_calib_offset;
+ int p2_calib_offset;
};
/**
@@ -635,7 +639,7 @@ int get_temp_common(const struct tsens_sensor *s, int *temp);
extern struct tsens_plat_data data_8960;
/* TSENS v0.1 targets */
-extern struct tsens_plat_data data_8916, data_8939, data_8974, data_9607;
+extern struct tsens_plat_data data_8226, data_8909, data_8916, data_8939, data_8974, data_9607;
/* TSENS v1 targets */
extern struct tsens_plat_data data_tsens_v1, data_8976, data_8956;
diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
index e58756323457..ccc2eea7f9f5 100644
--- a/drivers/thermal/qoriq_thermal.c
+++ b/drivers/thermal/qoriq_thermal.c
@@ -31,7 +31,6 @@
#define TMR_DISABLE 0x0
#define TMR_ME 0x80000000
#define TMR_ALPF 0x0c000000
-#define TMR_MSITE_ALL GENMASK(15, 0)
#define REGS_TMTMIR 0x008 /* Temperature measurement interval Register */
#define TMTMIR_DEFAULT 0x0000000f
@@ -51,6 +50,7 @@
* Site Register
*/
#define TRITSR_V BIT(31)
+#define TRITSR_TP5 BIT(9)
#define REGS_V2_TMSAR(n) (0x304 + 16 * (n)) /* TMU monitoring
* site adjustment register
*/
@@ -105,6 +105,11 @@ static int tmu_get_temp(struct thermal_zone_device *tz, int *temp)
* within sensor range. TEMP is an 9 bit value representing
* temperature in KelVin.
*/
+
+ regmap_read(qdata->regmap, REGS_TMR, &val);
+ if (!(val & TMR_ME))
+ return -EAGAIN;
+
if (regmap_read_poll_timeout(qdata->regmap,
REGS_TRITSR(qsensor->id),
val,
@@ -113,10 +118,15 @@ static int tmu_get_temp(struct thermal_zone_device *tz, int *temp)
10 * USEC_PER_MSEC))
return -ENODATA;
- if (qdata->ver == TMU_VER1)
+ if (qdata->ver == TMU_VER1) {
*temp = (val & GENMASK(7, 0)) * MILLIDEGREE_PER_DEGREE;
- else
- *temp = kelvin_to_millicelsius(val & GENMASK(8, 0));
+ } else {
+ if (val & TRITSR_TP5)
+ *temp = milli_kelvin_to_millicelsius((val & GENMASK(8, 0)) *
+ MILLIDEGREE_PER_DEGREE + 500);
+ else
+ *temp = kelvin_to_millicelsius(val & GENMASK(8, 0));
+ }
return 0;
}
@@ -128,15 +138,7 @@ static const struct thermal_zone_device_ops tmu_tz_ops = {
static int qoriq_tmu_register_tmu_zone(struct device *dev,
struct qoriq_tmu_data *qdata)
{
- int id;
-
- if (qdata->ver == TMU_VER1) {
- regmap_write(qdata->regmap, REGS_TMR,
- TMR_MSITE_ALL | TMR_ME | TMR_ALPF);
- } else {
- regmap_write(qdata->regmap, REGS_V2_TMSR, TMR_MSITE_ALL);
- regmap_write(qdata->regmap, REGS_TMR, TMR_ME | TMR_ALPF_V2);
- }
+ int id, sites = 0;
for (id = 0; id < SITES_MAX; id++) {
struct thermal_zone_device *tzd;
@@ -153,14 +155,24 @@ static int qoriq_tmu_register_tmu_zone(struct device *dev,
if (ret == -ENODEV)
continue;
- regmap_write(qdata->regmap, REGS_TMR, TMR_DISABLE);
return ret;
}
- if (devm_thermal_add_hwmon_sysfs(dev, tzd))
- dev_warn(dev,
- "Failed to add hwmon sysfs attributes\n");
+ if (qdata->ver == TMU_VER1)
+ sites |= 0x1 << (15 - id);
+ else
+ sites |= 0x1 << id;
+
+ devm_thermal_add_hwmon_sysfs(dev, tzd);
+ }
+ if (sites) {
+ if (qdata->ver == TMU_VER1) {
+ regmap_write(qdata->regmap, REGS_TMR, TMR_ME | TMR_ALPF | sites);
+ } else {
+ regmap_write(qdata->regmap, REGS_V2_TMSR, sites);
+ regmap_write(qdata->regmap, REGS_TMR, TMR_ME | TMR_ALPF_V2);
+ }
}
return 0;
@@ -208,8 +220,6 @@ static int qoriq_tmu_calibration(struct device *dev,
static void qoriq_tmu_init_device(struct qoriq_tmu_data *data)
{
- int i;
-
/* Disable interrupt, using polling instead */
regmap_write(data->regmap, REGS_TIER, TIER_DISABLE);
@@ -220,8 +230,6 @@ static void qoriq_tmu_init_device(struct qoriq_tmu_data *data)
} else {
regmap_write(data->regmap, REGS_V2_TMTMIR, TMTMIR_DEFAULT);
regmap_write(data->regmap, REGS_V2_TEUMR(0), TEUMR0_V2);
- for (i = 0; i < SITES_MAX; i++)
- regmap_write(data->regmap, REGS_V2_TMSAR(i), TMSARA_V2);
}
/* Disable monitoring */
@@ -230,7 +238,7 @@ static void qoriq_tmu_init_device(struct qoriq_tmu_data *data)
static const struct regmap_range qoriq_yes_ranges[] = {
regmap_reg_range(REGS_TMR, REGS_TSCFGR),
- regmap_reg_range(REGS_TTRnCR(0), REGS_TTRnCR(3)),
+ regmap_reg_range(REGS_TTRnCR(0), REGS_TTRnCR(15)),
regmap_reg_range(REGS_V2_TEUMR(0), REGS_V2_TEUMR(2)),
regmap_reg_range(REGS_V2_TMSAR(0), REGS_V2_TMSAR(15)),
regmap_reg_range(REGS_IPBRR(0), REGS_IPBRR(1)),
diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c
index 42a4724d3920..9029d01e029b 100644
--- a/drivers/thermal/rcar_gen3_thermal.c
+++ b/drivers/thermal/rcar_gen3_thermal.c
@@ -35,6 +35,12 @@
#define REG_GEN3_PTAT2 0x60
#define REG_GEN3_PTAT3 0x64
#define REG_GEN3_THSCP 0x68
+#define REG_GEN4_THSFMON00 0x180
+#define REG_GEN4_THSFMON01 0x184
+#define REG_GEN4_THSFMON02 0x188
+#define REG_GEN4_THSFMON15 0x1BC
+#define REG_GEN4_THSFMON16 0x1C0
+#define REG_GEN4_THSFMON17 0x1C4
/* IRQ{STR,MSK,EN} bits */
#define IRQ_TEMP1 BIT(0)
@@ -55,6 +61,7 @@
#define MCELSIUS(temp) ((temp) * 1000)
#define GEN3_FUSE_MASK 0xFFF
+#define GEN4_FUSE_MASK 0xFFF
#define TSC_MAX_NUM 5
@@ -66,6 +73,13 @@ struct equation_coefs {
int b2;
};
+struct rcar_gen3_thermal_priv;
+
+struct rcar_thermal_info {
+ int ths_tj_1;
+ void (*read_fuses)(struct rcar_gen3_thermal_priv *priv);
+};
+
struct rcar_gen3_thermal_tsc {
void __iomem *base;
struct thermal_zone_device *zone;
@@ -79,6 +93,7 @@ struct rcar_gen3_thermal_priv {
struct thermal_zone_device_ops ops;
unsigned int num_tscs;
int ptat[3];
+ const struct rcar_thermal_info *info;
};
static inline u32 rcar_gen3_thermal_read(struct rcar_gen3_thermal_tsc *tsc,
@@ -236,6 +251,62 @@ static irqreturn_t rcar_gen3_thermal_irq(int irq, void *data)
return IRQ_HANDLED;
}
+static void rcar_gen3_thermal_read_fuses_gen3(struct rcar_gen3_thermal_priv *priv)
+{
+ unsigned int i;
+
+ /*
+ * Set the pseudo calibration points with fused values.
+ * PTAT is shared between all TSCs but only fused for the first
+ * TSC while THCODEs are fused for each TSC.
+ */
+ priv->ptat[0] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT1) &
+ GEN3_FUSE_MASK;
+ priv->ptat[1] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT2) &
+ GEN3_FUSE_MASK;
+ priv->ptat[2] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT3) &
+ GEN3_FUSE_MASK;
+
+ for (i = 0; i < priv->num_tscs; i++) {
+ struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
+
+ tsc->thcode[0] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE1) &
+ GEN3_FUSE_MASK;
+ tsc->thcode[1] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE2) &
+ GEN3_FUSE_MASK;
+ tsc->thcode[2] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE3) &
+ GEN3_FUSE_MASK;
+ }
+}
+
+static void rcar_gen3_thermal_read_fuses_gen4(struct rcar_gen3_thermal_priv *priv)
+{
+ unsigned int i;
+
+ /*
+ * Set the pseudo calibration points with fused values.
+ * PTAT is shared between all TSCs but only fused for the first
+ * TSC while THCODEs are fused for each TSC.
+ */
+ priv->ptat[0] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN4_THSFMON16) &
+ GEN4_FUSE_MASK;
+ priv->ptat[1] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN4_THSFMON17) &
+ GEN4_FUSE_MASK;
+ priv->ptat[2] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN4_THSFMON15) &
+ GEN4_FUSE_MASK;
+
+ for (i = 0; i < priv->num_tscs; i++) {
+ struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
+
+ tsc->thcode[0] = rcar_gen3_thermal_read(tsc, REG_GEN4_THSFMON01) &
+ GEN4_FUSE_MASK;
+ tsc->thcode[1] = rcar_gen3_thermal_read(tsc, REG_GEN4_THSFMON02) &
+ GEN4_FUSE_MASK;
+ tsc->thcode[2] = rcar_gen3_thermal_read(tsc, REG_GEN4_THSFMON00) &
+ GEN4_FUSE_MASK;
+ }
+}
+
static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv)
{
unsigned int i;
@@ -243,7 +314,8 @@ static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv)
/* If fuses are not set, fallback to pseudo values. */
thscp = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_THSCP);
- if ((thscp & THSCP_COR_PARA_VLD) != THSCP_COR_PARA_VLD) {
+ if (!priv->info->read_fuses ||
+ (thscp & THSCP_COR_PARA_VLD) != THSCP_COR_PARA_VLD) {
/* Default THCODE values in case FUSEs are not set. */
static const int thcodes[TSC_MAX_NUM][3] = {
{ 3397, 2800, 2221 },
@@ -268,29 +340,7 @@ static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv)
return false;
}
- /*
- * Set the pseudo calibration points with fused values.
- * PTAT is shared between all TSCs but only fused for the first
- * TSC while THCODEs are fused for each TSC.
- */
- priv->ptat[0] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT1) &
- GEN3_FUSE_MASK;
- priv->ptat[1] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT2) &
- GEN3_FUSE_MASK;
- priv->ptat[2] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT3) &
- GEN3_FUSE_MASK;
-
- for (i = 0; i < priv->num_tscs; i++) {
- struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
-
- tsc->thcode[0] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE1) &
- GEN3_FUSE_MASK;
- tsc->thcode[1] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE2) &
- GEN3_FUSE_MASK;
- tsc->thcode[2] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE3) &
- GEN3_FUSE_MASK;
- }
-
+ priv->info->read_fuses(priv);
return true;
}
@@ -318,52 +368,65 @@ static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_priv *priv,
usleep_range(1000, 2000);
}
-static const int rcar_gen3_ths_tj_1 = 126;
-static const int rcar_gen3_ths_tj_1_m3_w = 116;
+static const struct rcar_thermal_info rcar_m3w_thermal_info = {
+ .ths_tj_1 = 116,
+ .read_fuses = rcar_gen3_thermal_read_fuses_gen3,
+};
+
+static const struct rcar_thermal_info rcar_gen3_thermal_info = {
+ .ths_tj_1 = 126,
+ .read_fuses = rcar_gen3_thermal_read_fuses_gen3,
+};
+
+static const struct rcar_thermal_info rcar_gen4_thermal_info = {
+ .ths_tj_1 = 126,
+ .read_fuses = rcar_gen3_thermal_read_fuses_gen4,
+};
+
static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
{
.compatible = "renesas,r8a774a1-thermal",
- .data = &rcar_gen3_ths_tj_1_m3_w,
+ .data = &rcar_m3w_thermal_info,
},
{
.compatible = "renesas,r8a774b1-thermal",
- .data = &rcar_gen3_ths_tj_1,
+ .data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a774e1-thermal",
- .data = &rcar_gen3_ths_tj_1,
+ .data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a7795-thermal",
- .data = &rcar_gen3_ths_tj_1,
+ .data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a7796-thermal",
- .data = &rcar_gen3_ths_tj_1_m3_w,
+ .data = &rcar_m3w_thermal_info,
},
{
.compatible = "renesas,r8a77961-thermal",
- .data = &rcar_gen3_ths_tj_1_m3_w,
+ .data = &rcar_m3w_thermal_info,
},
{
.compatible = "renesas,r8a77965-thermal",
- .data = &rcar_gen3_ths_tj_1,
+ .data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a77980-thermal",
- .data = &rcar_gen3_ths_tj_1,
+ .data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a779a0-thermal",
- .data = &rcar_gen3_ths_tj_1,
+ .data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a779f0-thermal",
- .data = &rcar_gen3_ths_tj_1,
+ .data = &rcar_gen4_thermal_info,
},
{
.compatible = "renesas,r8a779g0-thermal",
- .data = &rcar_gen3_ths_tj_1,
+ .data = &rcar_gen4_thermal_info,
},
{},
};
@@ -418,7 +481,6 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
{
struct rcar_gen3_thermal_priv *priv;
struct device *dev = &pdev->dev;
- const int *ths_tj_1 = of_device_get_match_data(dev);
struct resource *res;
struct thermal_zone_device *zone;
unsigned int i;
@@ -430,6 +492,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
priv->ops = rcar_gen3_tz_of_ops;
+ priv->info = of_device_get_match_data(dev);
platform_set_drvdata(pdev, priv);
if (rcar_gen3_thermal_request_irqs(priv, pdev))
@@ -469,7 +532,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
rcar_gen3_thermal_init(priv, tsc);
- rcar_gen3_thermal_calc_coefs(priv, tsc, *ths_tj_1);
+ rcar_gen3_thermal_calc_coefs(priv, tsc, priv->info->ths_tj_1);
zone = devm_thermal_of_zone_register(dev, i, tsc, &priv->ops);
if (IS_ERR(zone)) {
diff --git a/drivers/thermal/st/st_thermal.c b/drivers/thermal/st/st_thermal.c
index 2d3042098445..0d6249b36609 100644
--- a/drivers/thermal/st/st_thermal.c
+++ b/drivers/thermal/st/st_thermal.c
@@ -227,14 +227,12 @@ sensor_off:
}
EXPORT_SYMBOL_GPL(st_thermal_register);
-int st_thermal_unregister(struct platform_device *pdev)
+void st_thermal_unregister(struct platform_device *pdev)
{
struct st_thermal_sensor *sensor = platform_get_drvdata(pdev);
st_thermal_sensor_off(sensor);
thermal_zone_device_unregister(sensor->thermal_dev);
-
- return 0;
}
EXPORT_SYMBOL_GPL(st_thermal_unregister);
diff --git a/drivers/thermal/st/st_thermal.h b/drivers/thermal/st/st_thermal.h
index d661b2f2ef29..75a84e6ec6a7 100644
--- a/drivers/thermal/st/st_thermal.h
+++ b/drivers/thermal/st/st_thermal.h
@@ -94,7 +94,7 @@ struct st_thermal_sensor {
extern int st_thermal_register(struct platform_device *pdev,
const struct of_device_id *st_thermal_of_match);
-extern int st_thermal_unregister(struct platform_device *pdev);
+extern void st_thermal_unregister(struct platform_device *pdev);
extern const struct dev_pm_ops st_thermal_pm_ops;
#endif /* __STI_RESET_SYSCFG_H */
diff --git a/drivers/thermal/st/st_thermal_memmap.c b/drivers/thermal/st/st_thermal_memmap.c
index d68596c40be9..e8cfa83b724a 100644
--- a/drivers/thermal/st/st_thermal_memmap.c
+++ b/drivers/thermal/st/st_thermal_memmap.c
@@ -172,9 +172,9 @@ static int st_mmap_probe(struct platform_device *pdev)
return st_thermal_register(pdev, st_mmap_thermal_of_match);
}
-static int st_mmap_remove(struct platform_device *pdev)
+static void st_mmap_remove(struct platform_device *pdev)
{
- return st_thermal_unregister(pdev);
+ st_thermal_unregister(pdev);
}
static struct platform_driver st_mmap_thermal_driver = {
@@ -184,7 +184,7 @@ static struct platform_driver st_mmap_thermal_driver = {
.of_match_table = st_mmap_thermal_of_match,
},
.probe = st_mmap_probe,
- .remove = st_mmap_remove,
+ .remove_new = st_mmap_remove,
};
module_platform_driver(st_mmap_thermal_driver);
diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 793ddce72132..195f3c5d0b38 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -319,6 +319,11 @@ out:
return ret;
}
+static void sun8i_ths_reset_control_assert(void *data)
+{
+ reset_control_assert(data);
+}
+
static int sun8i_ths_resource_init(struct ths_device *tmdev)
{
struct device *dev = tmdev->dev;
@@ -339,47 +344,35 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
if (IS_ERR(tmdev->reset))
return PTR_ERR(tmdev->reset);
- tmdev->bus_clk = devm_clk_get(&pdev->dev, "bus");
+ ret = reset_control_deassert(tmdev->reset);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, sun8i_ths_reset_control_assert,
+ tmdev->reset);
+ if (ret)
+ return ret;
+
+ tmdev->bus_clk = devm_clk_get_enabled(&pdev->dev, "bus");
if (IS_ERR(tmdev->bus_clk))
return PTR_ERR(tmdev->bus_clk);
}
if (tmdev->chip->has_mod_clk) {
- tmdev->mod_clk = devm_clk_get(&pdev->dev, "mod");
+ tmdev->mod_clk = devm_clk_get_enabled(&pdev->dev, "mod");
if (IS_ERR(tmdev->mod_clk))
return PTR_ERR(tmdev->mod_clk);
}
- ret = reset_control_deassert(tmdev->reset);
- if (ret)
- return ret;
-
- ret = clk_prepare_enable(tmdev->bus_clk);
- if (ret)
- goto assert_reset;
-
ret = clk_set_rate(tmdev->mod_clk, 24000000);
if (ret)
- goto bus_disable;
-
- ret = clk_prepare_enable(tmdev->mod_clk);
- if (ret)
- goto bus_disable;
+ return ret;
ret = sun8i_ths_calibrate(tmdev);
if (ret)
- goto mod_disable;
+ return ret;
return 0;
-
-mod_disable:
- clk_disable_unprepare(tmdev->mod_clk);
-bus_disable:
- clk_disable_unprepare(tmdev->bus_clk);
-assert_reset:
- reset_control_assert(tmdev->reset);
-
- return ret;
}
static int sun8i_h3_thermal_init(struct ths_device *tmdev)
@@ -475,9 +468,7 @@ static int sun8i_ths_register(struct ths_device *tmdev)
if (IS_ERR(tmdev->sensor[i].tzd))
return PTR_ERR(tmdev->sensor[i].tzd);
- if (devm_thermal_add_hwmon_sysfs(tmdev->dev, tmdev->sensor[i].tzd))
- dev_warn(tmdev->dev,
- "Failed to add hwmon sysfs attributes\n");
+ devm_thermal_add_hwmon_sysfs(tmdev->dev, tmdev->sensor[i].tzd);
}
return 0;
@@ -530,17 +521,6 @@ static int sun8i_ths_probe(struct platform_device *pdev)
return 0;
}
-static int sun8i_ths_remove(struct platform_device *pdev)
-{
- struct ths_device *tmdev = platform_get_drvdata(pdev);
-
- clk_disable_unprepare(tmdev->mod_clk);
- clk_disable_unprepare(tmdev->bus_clk);
- reset_control_assert(tmdev->reset);
-
- return 0;
-}
-
static const struct ths_thermal_chip sun8i_a83t_ths = {
.sensor_num = 3,
.scale = 705,
@@ -642,7 +622,6 @@ MODULE_DEVICE_TABLE(of, of_ths_match);
static struct platform_driver ths_driver = {
.probe = sun8i_ths_probe,
- .remove = sun8i_ths_remove,
.driver = {
.name = "sun8i-thermal",
.of_match_table = of_ths_match,
diff --git a/drivers/thermal/tegra/tegra30-tsensor.c b/drivers/thermal/tegra/tegra30-tsensor.c
index cb584a5735ed..c243e9d76d3c 100644
--- a/drivers/thermal/tegra/tegra30-tsensor.c
+++ b/drivers/thermal/tegra/tegra30-tsensor.c
@@ -523,8 +523,7 @@ static int tegra_tsensor_register_channel(struct tegra_tsensor *ts,
return 0;
}
- if (devm_thermal_add_hwmon_sysfs(ts->dev, tsc->tzd))
- dev_warn(ts->dev, "failed to add hwmon sysfs attributes\n");
+ devm_thermal_add_hwmon_sysfs(ts->dev, tsc->tzd);
return 0;
}
diff --git a/drivers/thermal/thermal-generic-adc.c b/drivers/thermal/thermal-generic-adc.c
index 017b0ce52122..f4f1a04f8c0f 100644
--- a/drivers/thermal/thermal-generic-adc.c
+++ b/drivers/thermal/thermal-generic-adc.c
@@ -13,6 +13,8 @@
#include <linux/slab.h>
#include <linux/thermal.h>
+#include "thermal_hwmon.h"
+
struct gadc_thermal_info {
struct device *dev;
struct thermal_zone_device *tz_dev;
@@ -153,6 +155,8 @@ static int gadc_thermal_probe(struct platform_device *pdev)
return ret;
}
+ devm_thermal_add_hwmon_sysfs(&pdev->dev, gti->tz_dev);
+
return 0;
}
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 842f678c1c3e..cc2b5e81c620 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1203,7 +1203,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_crit_temp);
struct thermal_zone_device *
thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *trips, int num_trips, int mask,
void *devdata, struct thermal_zone_device_ops *ops,
- struct thermal_zone_params *tzp, int passive_delay,
+ const struct thermal_zone_params *tzp, int passive_delay,
int polling_delay)
{
struct thermal_zone_device *tz;
@@ -1371,7 +1371,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_device_register_with_trips);
struct thermal_zone_device *thermal_zone_device_register(const char *type, int ntrips, int mask,
void *devdata, struct thermal_zone_device_ops *ops,
- struct thermal_zone_params *tzp, int passive_delay,
+ const struct thermal_zone_params *tzp, int passive_delay,
int polling_delay)
{
return thermal_zone_device_register_with_trips(type, NULL, ntrips, mask,
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index 3d4a787c6b28..17c1bbed734d 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -23,6 +23,8 @@
#define DEFAULT_THERMAL_GOVERNOR "user_space"
#elif defined(CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR)
#define DEFAULT_THERMAL_GOVERNOR "power_allocator"
+#elif defined(CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG)
+#define DEFAULT_THERMAL_GOVERNOR "bang_bang"
#endif
/* Initial state of a cooling device during binding */
diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c
index fbe55509e307..c3ae44659b81 100644
--- a/drivers/thermal/thermal_hwmon.c
+++ b/drivers/thermal/thermal_hwmon.c
@@ -271,11 +271,14 @@ int devm_thermal_add_hwmon_sysfs(struct device *dev, struct thermal_zone_device
ptr = devres_alloc(devm_thermal_hwmon_release, sizeof(*ptr),
GFP_KERNEL);
- if (!ptr)
+ if (!ptr) {
+ dev_warn(dev, "Failed to allocate device resource data\n");
return -ENOMEM;
+ }
ret = thermal_add_hwmon_sysfs(tz);
if (ret) {
+ dev_warn(dev, "Failed to add hwmon sysfs attributes\n");
devres_free(ptr);
return ret;
}
diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c
index 6fb14e521197..bc07ae1c284c 100644
--- a/drivers/thermal/thermal_of.c
+++ b/drivers/thermal/thermal_of.c
@@ -238,17 +238,13 @@ static int thermal_of_monitor_init(struct device_node *np, int *delay, int *pdel
return 0;
}
-static struct thermal_zone_params *thermal_of_parameters_init(struct device_node *np)
+static void thermal_of_parameters_init(struct device_node *np,
+ struct thermal_zone_params *tzp)
{
- struct thermal_zone_params *tzp;
int coef[2];
int ncoef = ARRAY_SIZE(coef);
int prop, ret;
- tzp = kzalloc(sizeof(*tzp), GFP_KERNEL);
- if (!tzp)
- return ERR_PTR(-ENOMEM);
-
tzp->no_hwmon = true;
if (!of_property_read_u32(np, "sustainable-power", &prop))
@@ -267,8 +263,6 @@ static struct thermal_zone_params *thermal_of_parameters_init(struct device_node
tzp->slope = coef[0];
tzp->offset = coef[1];
-
- return tzp;
}
static struct device_node *thermal_of_zone_get_by_name(struct thermal_zone_device *tz)
@@ -442,13 +436,11 @@ static int thermal_of_unbind(struct thermal_zone_device *tz,
static void thermal_of_zone_unregister(struct thermal_zone_device *tz)
{
struct thermal_trip *trips = tz->trips;
- struct thermal_zone_params *tzp = tz->tzp;
struct thermal_zone_device_ops *ops = tz->ops;
thermal_zone_device_disable(tz);
thermal_zone_device_unregister(tz);
kfree(trips);
- kfree(tzp);
kfree(ops);
}
@@ -477,7 +469,7 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node *
{
struct thermal_zone_device *tz;
struct thermal_trip *trips;
- struct thermal_zone_params *tzp;
+ struct thermal_zone_params tzp = {};
struct thermal_zone_device_ops *of_ops;
struct device_node *np;
int delay, pdelay;
@@ -509,12 +501,7 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node *
goto out_kfree_trips;
}
- tzp = thermal_of_parameters_init(np);
- if (IS_ERR(tzp)) {
- ret = PTR_ERR(tzp);
- pr_err("Failed to initialize parameter from %pOFn: %d\n", np, ret);
- goto out_kfree_trips;
- }
+ thermal_of_parameters_init(np, &tzp);
of_ops->bind = thermal_of_bind;
of_ops->unbind = thermal_of_unbind;
@@ -522,12 +509,12 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node *
mask = GENMASK_ULL((ntrips) - 1, 0);
tz = thermal_zone_device_register_with_trips(np->name, trips, ntrips,
- mask, data, of_ops, tzp,
+ mask, data, of_ops, &tzp,
pdelay, delay);
if (IS_ERR(tz)) {
ret = PTR_ERR(tz);
pr_err("Failed to register thermal zone %pOFn: %d\n", np, ret);
- goto out_kfree_tzp;
+ goto out_kfree_trips;
}
ret = thermal_zone_device_enable(tz);
@@ -540,8 +527,6 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node *
return tz;
-out_kfree_tzp:
- kfree(tzp);
out_kfree_trips:
kfree(trips);
out_kfree_of_ops:
diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
index 6a5335931f4d..d414a4b7a94a 100644
--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
@@ -182,8 +182,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
ti_bandgap_write_update_interval(bgp, data->sensor_id,
TI_BANDGAP_UPDATE_INTERVAL_MS);
- if (devm_thermal_add_hwmon_sysfs(bgp->dev, data->ti_thermal))
- dev_warn(bgp->dev, "failed to add hwmon sysfs attributes\n");
+ devm_thermal_add_hwmon_sysfs(bgp->dev, data->ti_thermal);
return 0;
}
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..3fb4553a6442 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");
@@ -1810,6 +1964,8 @@ unlock:
pm_runtime_mark_last_busy(&tb->dev);
pm_runtime_put_autosuspend(&tb->dev);
+
+ kfree(ev);
}
static void tb_queue_dp_bandwidth_request(struct tb *tb, u64 route, u8 port)
@@ -1830,17 +1986,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 +2120,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 +2161,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..0dfd1e083994 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,51 @@ 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);
+ ret = tb_switch_tmu_rate_write(sw, tmu_rates[TB_SWITCH_TMU_MODE_OFF]);
+ if (ret)
+ return ret;
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 +634,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 +675,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 +690,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 +708,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 +758,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 +824,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;
- tb_switch_set_tmu_mode_params(sw, sw->tmu.rate);
- tb_port_tmu_set_unidirectional(up, sw->tmu.unidirectional);
+ case TB_SWITCH_TMU_MODE_HIFI_BI:
+ tb_port_tmu_set_unidirectional(up, false);
+ break;
+
+ 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 +927,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 +935,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 +964,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 +995,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/Kconfig b/drivers/tty/Kconfig
index 341abaed4ce2..069de553127c 100644
--- a/drivers/tty/Kconfig
+++ b/drivers/tty/Kconfig
@@ -164,6 +164,9 @@ config LEGACY_TIOCSTI
userspace depends on this functionality to continue operating
normally.
+ Processes which run with CAP_SYS_ADMIN, such as BRLTTY, can
+ use TIOCSTI even when this is set to N.
+
This functionality can be changed at runtime with the
dev.tty.legacy_tiocsti sysctl. This configuration option sets
the default value of the sysctl.
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index b411a26cc092..739f522cb893 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -3042,12 +3042,13 @@ static void gsm_error(struct gsm_mux *gsm)
static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
{
int i;
- struct gsm_dlci *dlci = gsm->dlci[0];
+ struct gsm_dlci *dlci;
struct gsm_msg *txq, *ntxq;
gsm->dead = true;
mutex_lock(&gsm->mutex);
+ dlci = gsm->dlci[0];
if (dlci) {
if (disc && dlci->state != DLCI_CLOSED) {
gsm_dlci_begin_close(dlci);
@@ -3070,8 +3071,10 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
gsm->has_devices = false;
}
for (i = NUM_DLCI - 1; i >= 0; i--)
- if (gsm->dlci[i])
+ if (gsm->dlci[i]) {
gsm_dlci_release(gsm->dlci[i]);
+ gsm->dlci[i] = NULL;
+ }
mutex_unlock(&gsm->mutex);
/* Now wipe the queues */
tty_ldisc_flush(gsm->tty);
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..3449f8790e46 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -488,6 +488,35 @@ 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;
+ up->port.port_id = 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 +530,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 +602,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 +851,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 +1023,25 @@ 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.port_id = up->port.port_id;
uart->port.iobase = up->port.iobase;
uart->port.membase = up->port.membase;
uart->port.irq = up->port.irq;
@@ -1120,6 +1166,7 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)
}
}
+unlock:
mutex_unlock(&serial_mutex);
return ret;
@@ -1157,6 +1204,7 @@ void serial8250_unregister_port(int line)
uart->port.flags &= ~UPF_BOOT_AUTOCONF;
uart->port.type = PORT_UNKNOWN;
uart->port.dev = &serial8250_isa_devs->dev;
+ uart->port.port_id = line;
uart->capabilities = 0;
serial8250_init_port(uart);
serial8250_apply_quirks(uart);
diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c
index 75f32f054ebb..84843e204a5e 100644
--- a/drivers/tty/serial/8250/8250_dwlib.c
+++ b/drivers/tty/serial/8250/8250_dwlib.c
@@ -244,7 +244,7 @@ void dw8250_setup_port(struct uart_port *p)
struct dw8250_port_data *pd = p->private_data;
struct dw8250_data *data = to_dw8250_data(pd);
struct uart_8250_port *up = up_to_u8250p(p);
- u32 reg;
+ u32 reg, old_dlf;
pd->hw_rs485_support = dw8250_detect_rs485_hw(p);
if (pd->hw_rs485_support) {
@@ -270,9 +270,11 @@ void dw8250_setup_port(struct uart_port *p)
dev_dbg(p->dev, "Designware UART version %c.%c%c\n",
(reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff);
+ /* Preserve value written by firmware or bootloader */
+ old_dlf = dw8250_readl_ext(p, DW_UART_DLF);
dw8250_writel_ext(p, DW_UART_DLF, ~0U);
reg = dw8250_readl_ext(p, DW_UART_DLF);
- dw8250_writel_ext(p, DW_UART_DLF, 0);
+ dw8250_writel_ext(p, DW_UART_DLF, old_dlf);
if (reg) {
pd->dlf_size = fls(reg);
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..483bb552cdc4 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);
@@ -848,7 +785,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 +975,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 +1161,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 +1335,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 +1350,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 +1363,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 +1381,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 +1403,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 +1455,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 +1637,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 +1667,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 +1684,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 +2143,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 +2196,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 +2211,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 +2334,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 +2486,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 +2629,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 +2784,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 +2793,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 +2960,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 +3124,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 +3208,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 +3274,8 @@ 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->pm = NULL;
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 3e3fb377d90d..bdc568a4ab66 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -450,8 +450,8 @@ config SERIAL_SA1100
help
If you have a machine based on a SA1100/SA1110 StrongARM(R) CPU you
can enable its onboard serial port by enabling this option.
- Please read <file:Documentation/arm/sa1100/serial_uart.rst> for further
- info.
+ Please read <file:Documentation/arch/arm/sa1100/serial_uart.rst> for
+ further info.
config SERIAL_SA1100_CONSOLE
bool "Console on SA1100 serial port"
@@ -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..c569a08b5b19 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,
@@ -1137,8 +1139,8 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)
unsigned long sr = lpuart32_read(&sport->port, UARTSTAT);
if (sr & (UARTSTAT_PE | UARTSTAT_FE)) {
- /* Read DR to clear the error flags */
- lpuart32_read(&sport->port, UARTDATA);
+ /* Clear the error flags */
+ lpuart32_write(&sport->port, sr, UARTSTAT);
if (sr & UARTSTAT_PE)
sport->port.icount.parity++;
@@ -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..daaf2a64e7f1 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);
@@ -1676,13 +1681,6 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
if (ret)
return ret;
- /*
- * Set pm_runtime status as ACTIVE so that wakeup_irq gets
- * enabled/disabled from dev_pm_arm_wake_irq during system
- * suspend/resume respectively.
- */
- pm_runtime_set_active(&pdev->dev);
-
if (port->wakeup_irq > 0) {
device_init_wakeup(&pdev->dev, true);
ret = dev_pm_set_dedicated_wake_irq(&pdev->dev,
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..c74c548f0db6
--- /dev/null
+++ b/drivers/tty/serial/serial_base.h
@@ -0,0 +1,47 @@
+/* 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 ida port_ida;
+};
+
+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..3dfcf20c4eb6
--- /dev/null
+++ b/drivers/tty/serial/serial_base_bus.c
@@ -0,0 +1,247 @@
+// 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/idr.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 const struct device_type serial_ctrl_type = {
+ .name = "ctrl",
+};
+
+static const struct device_type serial_port_type = {
+ .name = "port",
+};
+
+static int serial_base_match(struct device *dev, struct device_driver *drv)
+{
+ if (dev->type == &serial_ctrl_type &&
+ str_has_prefix(drv->name, serial_ctrl_type.name))
+ return 1;
+
+ if (dev->type == &serial_port_type &&
+ str_has_prefix(drv->name, serial_port_type.name))
+ return 1;
+
+ return 0;
+}
+
+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),
+ unsigned int ctrl_id,
+ unsigned int port_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;
+ }
+
+ if (type == &serial_ctrl_type)
+ return dev_set_name(dev, "%s:%d", dev_name(port->dev), ctrl_id);
+
+ if (type == &serial_port_type)
+ return dev_set_name(dev, "%s:%d.%d", dev_name(port->dev),
+ ctrl_id, port_id);
+
+ return -EINVAL;
+}
+
+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);
+ put_device(&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);
+
+ ida_init(&ctrl_dev->port_ida);
+
+ err = serial_base_device_init(port, &ctrl_dev->dev,
+ parent, &serial_ctrl_type,
+ serial_base_ctrl_release,
+ port->ctrl_id, 0);
+ 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 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 min = 0, max = -1; /* Use -1 for max to apply IDA defaults */
+ int err;
+
+ port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL);
+ if (!port_dev)
+ return ERR_PTR(-ENOMEM);
+
+ /* Device driver specified port_id vs automatic assignment? */
+ if (port->port_id) {
+ min = port->port_id;
+ max = port->port_id;
+ }
+
+ err = ida_alloc_range(&ctrl_dev->port_ida, min, max, GFP_KERNEL);
+ if (err < 0) {
+ kfree(port_dev);
+ return ERR_PTR(err);
+ }
+
+ port->port_id = err;
+
+ err = serial_base_device_init(port, &port_dev->dev,
+ &ctrl_dev->dev, &serial_port_type,
+ serial_base_port_release,
+ port->ctrl_id, port->port_id);
+ 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);
+ ida_free(&ctrl_dev->port_ida, port->port_id);
+
+ return ERR_PTR(err);
+}
+
+void serial_base_port_device_remove(struct serial_port_device *port_dev)
+{
+ struct serial_ctrl_device *ctrl_dev;
+ struct device *parent;
+
+ if (!port_dev)
+ return;
+
+ parent = port_dev->dev.parent;
+ ctrl_dev = to_serial_base_ctrl_device(parent);
+
+ device_del(&port_dev->dev);
+ ida_free(&ctrl_dev->port_ida, port_dev->port->port_id);
+ put_device(&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/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 7c9457962a3d..8b7a42e05d6d 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -590,7 +590,7 @@ static void sci_start_tx(struct uart_port *port)
dma_submit_error(s->cookie_tx)) {
if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE)
/* Switch irq from SCIF to DMA */
- disable_irq(s->irqs[SCIx_TXI_IRQ]);
+ disable_irq_nosync(s->irqs[SCIx_TXI_IRQ]);
s->cookie_tx = 0;
schedule_work(&s->work_tx);
diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c
index 1f565a216e74..a19db49327e2 100644
--- a/drivers/tty/serial/sifive.c
+++ b/drivers/tty/serial/sifive.c
@@ -811,7 +811,7 @@ static void sifive_serial_console_write(struct console *co, const char *s,
local_irq_restore(flags);
}
-static int __init sifive_serial_console_setup(struct console *co, char *options)
+static int sifive_serial_console_setup(struct console *co, char *options)
{
struct sifive_serial_port *ssp;
int baud = SIFIVE_DEFAULT_BAUD_RATE;
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/ucc_uart.c b/drivers/tty/serial/ucc_uart.c
index 404230c1ebb2..0a370b9ea70b 100644
--- a/drivers/tty/serial/ucc_uart.c
+++ b/drivers/tty/serial/ucc_uart.c
@@ -59,7 +59,7 @@ static int firmware_loaded;
/* #define LOOPBACK */
/* The major and minor device numbers are defined in
- * http://www.lanana.org/docs/device-list/devices-2.6+.txt. For the QE
+ * Documentation/admin-guide/devices.txt. For the QE
* UART, we have major number 204 and minor numbers 46 - 49, which are the
* same as for the CPM2. This decision was made because no Freescale part
* has both a CPM and a QE.
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 c84be40fb8df..63db04b9113a 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>
@@ -466,7 +467,7 @@ static const struct file_operations tty_fops = {
.llseek = no_llseek,
.read_iter = tty_read,
.write_iter = tty_write,
- .splice_read = generic_file_splice_read,
+ .splice_read = copy_splice_read,
.splice_write = iter_file_splice_write,
.poll = tty_poll,
.unlocked_ioctl = tty_ioctl,
@@ -481,7 +482,7 @@ static const struct file_operations console_fops = {
.llseek = no_llseek,
.read_iter = tty_read,
.write_iter = redirected_tty_write,
- .splice_read = generic_file_splice_read,
+ .splice_read = copy_splice_read,
.splice_write = iter_file_splice_write,
.poll = tty_poll,
.unlocked_ioctl = tty_ioctl,
@@ -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:
@@ -2276,7 +2285,7 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
char ch, mbz = 0;
struct tty_ldisc *ld;
- if (!tty_legacy_tiocsti)
+ if (!tty_legacy_tiocsti && !capable(CAP_SYS_ADMIN))
return -EIO;
if ((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN))
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..386674ead7f0 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,245 @@ 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;
+ __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++;
+ if (sq_head_slot == hwq->max_entries)
+ sq_head_slot = 0;
+ }
+
+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..0f3bd943b58b 100644
--- a/drivers/ufs/core/ufshcd-priv.h
+++ b/drivers/ufs/core/ufshcd-priv.h
@@ -68,25 +68,26 @@ int ufshcd_mcq_decide_queue_depth(struct ufs_hba *hba);
int ufshcd_mcq_memory_alloc(struct ufs_hba *hba);
void ufshcd_mcq_make_queues_operational(struct ufs_hba *hba);
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 +367,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 +406,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..129446775796 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 */
@@ -8410,6 +8520,41 @@ out:
return ret;
}
+static void ufshcd_set_timestamp_attr(struct ufs_hba *hba)
+{
+ int err;
+ struct ufs_query_req *request = NULL;
+ struct ufs_query_res *response = NULL;
+ struct ufs_dev_info *dev_info = &hba->dev_info;
+ struct utp_upiu_query_v4_0 *upiu_data;
+
+ if (dev_info->wspecversion < 0x400)
+ return;
+
+ ufshcd_hold(hba);
+
+ mutex_lock(&hba->dev_cmd.lock);
+
+ ufshcd_init_query(hba, &request, &response,
+ UPIU_QUERY_OPCODE_WRITE_ATTR,
+ QUERY_ATTR_IDN_TIMESTAMP, 0, 0);
+
+ request->query_func = UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST;
+
+ upiu_data = (struct utp_upiu_query_v4_0 *)&request->upiu_req;
+
+ put_unaligned_be64(ktime_get_real_ns(), &upiu_data->osf3);
+
+ err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
+
+ if (err)
+ dev_err(hba->dev, "%s: failed to set timestamp %d\n",
+ __func__, err);
+
+ mutex_unlock(&hba->dev_cmd.lock);
+ ufshcd_release(hba);
+}
+
/**
* ufshcd_add_lus - probe and add UFS logical units
* @hba: per-adapter instance
@@ -8502,11 +8647,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);
@@ -8594,6 +8743,8 @@ static int ufshcd_device_init(struct ufs_hba *hba, bool init_dev_params)
ufshcd_set_ufs_dev_active(hba);
ufshcd_force_reset_auto_bkops(hba);
+ ufshcd_set_timestamp_attr(hba);
+
/* Gear up to HS gear if supported */
if (hba->max_pwr_info.is_valid) {
/*
@@ -8774,7 +8925,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 +9335,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 +9582,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))
@@ -9634,6 +9786,7 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
ret = ufshcd_set_dev_pwr_mode(hba, UFS_ACTIVE_PWR_MODE);
if (ret)
goto set_old_link_state;
+ ufshcd_set_timestamp_attr(hba);
}
if (ufshcd_keep_autobkops_enabled_except_suspend(hba))
@@ -9775,28 +9928,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 +10112,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 +10366,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..580c8d0bd8bb 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
@@ -72,6 +72,7 @@ config SCSI_UFS_QCOM
config SCSI_UFS_MEDIATEK
tristate "Mediatek specific hooks to UFS controller platform driver"
depends on SCSI_UFSHCD_PLATFORM && ARCH_MEDIATEK
+ depends on RESET_CONTROLLER
select PHY_MTK_UFS
select RESET_TI_SYSCON
help
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..c1557d21b027 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)
{
@@ -225,7 +321,7 @@ static void ufs_qcom_select_unipro_mode(struct ufs_qcom_host *host)
ufs_qcom_cap_qunipro(host) ? QUNIPRO_SEL : 0,
REG_UFS_CFG1);
- if (host->hw_ver.major == 0x05)
+ if (host->hw_ver.major >= 0x05)
ufshcd_rmwl(host->hba, QUNIPRO_G4_SEL, 0, REG_UFS_CFG0);
/* make sure above configuration is applied before we return */
@@ -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-renesas.c b/drivers/ufs/host/ufs-renesas.c
index f8a5e79ed3b4..ab0652d8705a 100644
--- a/drivers/ufs/host/ufs-renesas.c
+++ b/drivers/ufs/host/ufs-renesas.c
@@ -359,7 +359,7 @@ static int ufs_renesas_init(struct ufs_hba *hba)
{
struct ufs_renesas_priv *priv;
- priv = devm_kmalloc(hba->dev, sizeof(*priv), GFP_KERNEL);
+ priv = devm_kzalloc(hba->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
ufshcd_set_variant(hba, priv);
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..aa0111b365bb 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);
@@ -3012,12 +3015,14 @@ static int cdns3_gadget_udc_stop(struct usb_gadget *gadget)
static int cdns3_gadget_check_config(struct usb_gadget *gadget)
{
struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
+ struct cdns3_endpoint *priv_ep;
struct usb_ep *ep;
int n_in = 0;
int total;
list_for_each_entry(ep, &gadget->ep_list, ep_list) {
- if (ep->claimed && (ep->address & USB_DIR_IN))
+ priv_ep = ep_to_cdns3_ep(ep);
+ if ((priv_ep->flags & EP_CLAIMED) && (ep->address & USB_DIR_IN))
n_in++;
}
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..501e8bc9738e 100644
--- a/drivers/usb/common/usb-conn-gpio.c
+++ b/drivers/usb/common/usb-conn-gpio.c
@@ -42,6 +42,7 @@ struct usb_conn_info {
struct power_supply_desc desc;
struct power_supply *charger;
+ bool initial_detection;
};
/*
@@ -86,11 +87,13 @@ static void usb_conn_detect_cable(struct work_struct *work)
dev_dbg(info->dev, "role %s -> %s, gpios: id %d, vbus %d\n",
usb_role_string(info->last_role), usb_role_string(role), id, vbus);
- if (info->last_role == role) {
+ if (!info->initial_detection && info->last_role == role) {
dev_warn(info->dev, "repeated role: %s\n", usb_role_string(role));
return;
}
+ info->initial_detection = false;
+
if (info->last_role == USB_ROLE_HOST && info->vbus)
regulator_disable(info->vbus);
@@ -258,6 +261,7 @@ static int usb_conn_probe(struct platform_device *pdev)
device_set_wakeup_capable(&pdev->dev, true);
/* Perform initial detection */
+ info->initial_detection = true;
usb_conn_queue_dwork(info, 0);
return 0;
@@ -267,7 +271,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 +281,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 +340,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/buffer.c b/drivers/usb/core/buffer.c
index 268ccbec88f9..87230869e1fa 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -34,13 +34,13 @@ void __init usb_init_pool_max(void)
{
/*
* The pool_max values must never be smaller than
- * ARCH_KMALLOC_MINALIGN.
+ * ARCH_DMA_MINALIGN.
*/
- if (ARCH_KMALLOC_MINALIGN <= 32)
+ if (ARCH_DMA_MINALIGN <= 32)
; /* Original value is okay */
- else if (ARCH_KMALLOC_MINALIGN <= 64)
+ else if (ARCH_DMA_MINALIGN <= 64)
pool_max[0] = 64;
- else if (ARCH_KMALLOC_MINALIGN <= 128)
+ else if (ARCH_DMA_MINALIGN <= 128)
pool_max[0] = 0; /* Don't use this pool */
else
BUILD_BUG(); /* We don't allow this */
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/core/quirks.c b/drivers/usb/core/quirks.c
index 934b3d997702..15e9bd180a1d 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -436,6 +436,10 @@ static const struct usb_device_id usb_quirk_list[] = {
/* novation SoundControl XL */
{ USB_DEVICE(0x1235, 0x0061), .driver_info = USB_QUIRK_RESET_RESUME },
+ /* Focusrite Scarlett Solo USB */
+ { USB_DEVICE(0x1235, 0x8211), .driver_info =
+ USB_QUIRK_DISCONNECT_SUSPEND },
+
/* Huawei 4G LTE module */
{ USB_DEVICE(0x12d1, 0x15bb), .driver_info =
USB_QUIRK_DISCONNECT_SUSPEND },
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..9c6bf054f15d 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -277,9 +277,9 @@ int dwc3_core_soft_reset(struct dwc3 *dwc)
/*
* We're resetting only the device side because, if we're in host mode,
* XHCI driver will reset the host block. If dwc3 was configured for
- * host-only mode, then we can return early.
+ * host-only mode or current role is host, then we can return early.
*/
- if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST)
+ if (dwc->dr_mode == USB_DR_MODE_HOST || dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST)
return 0;
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
@@ -1209,22 +1209,6 @@ static int dwc3_core_init(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
}
- if (dwc->dr_mode == USB_DR_MODE_HOST ||
- dwc->dr_mode == USB_DR_MODE_OTG) {
- reg = dwc3_readl(dwc->regs, DWC3_GUCTL);
-
- /*
- * Enable Auto retry Feature to make the controller operating in
- * Host mode on seeing transaction errors(CRC errors or internal
- * overrun scenerios) on IN transfers to reply to the device
- * with a non-terminating retry ACK (i.e, an ACK transcation
- * packet with Retry=1 & Nump != 0)
- */
- reg |= DWC3_GUCTL_HSTINAUTORETRY;
-
- dwc3_writel(dwc->regs, DWC3_GUCTL, reg);
- }
-
/*
* Must config both number of packets and max burst settings to enable
* RX and/or TX threshold.
@@ -1800,6 +1784,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 +1908,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 +1935,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 +2245,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..a69ac67d89fe 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
@@ -254,9 +256,6 @@
#define DWC3_GCTL_GBLHIBERNATIONEN BIT(1)
#define DWC3_GCTL_DSBLCLKGTNG BIT(0)
-/* Global User Control Register */
-#define DWC3_GUCTL_HSTINAUTORETRY BIT(14)
-
/* Global User Control 1 Register */
#define DWC3_GUCTL1_DEV_DECOUPLE_L1L2_EVT BIT(31)
#define DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS BIT(28)
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-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index 44a04c9b2073..6604845c397c 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -233,10 +233,12 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc,
/*
* A lot of BYT devices lack ACPI resource entries for
- * the GPIOs, add a fallback mapping to the reference
+ * the GPIOs. If the ACPI entry for the GPIO controller
+ * is present add a fallback mapping to the reference
* design GPIOs which all boards seem to use.
*/
- gpiod_add_lookup_table(&platform_bytcr_gpios);
+ if (acpi_dev_present("INT33FC", NULL, -1))
+ gpiod_add_lookup_table(&platform_bytcr_gpios);
/*
* These GPIOs will turn on the USB2 PHY. Note that we have to
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..858fe4c299b7 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;
}
}
@@ -4446,9 +4455,14 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
u32 count;
if (pm_runtime_suspended(dwc->dev)) {
+ dwc->pending_events = true;
+ /*
+ * Trigger runtime resume. The get() function will be balanced
+ * after processing the pending events in dwc3_process_pending
+ * events().
+ */
pm_runtime_get(dwc->dev);
disable_irq_nosync(dwc->irq_gadget);
- dwc->pending_events = true;
return IRQ_HANDLED;
}
@@ -4709,6 +4723,8 @@ void dwc3_gadget_process_pending_events(struct dwc3 *dwc)
{
if (dwc->pending_events) {
dwc3_interrupt(dwc->irq_gadget, dwc->ev_buf);
+ dwc3_thread_interrupt(dwc->irq_gadget, dwc->ev_buf);
+ pm_runtime_put(dwc->dev);
dwc->pending_events = false;
enable_irq(dwc->irq_gadget);
}
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/composite.c b/drivers/usb/gadget/composite.c
index 1b3489149e5e..dd9b90481b4c 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1125,6 +1125,10 @@ int usb_add_config(struct usb_composite_dev *cdev,
goto done;
status = bind(config);
+
+ if (status == 0)
+ status = usb_gadget_check_config(cdev->gadget);
+
if (status < 0) {
while (!list_empty(&config->functions)) {
struct usb_function *f;
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/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c
index 2acece16b890..e549022642e5 100644
--- a/drivers/usb/gadget/legacy/raw_gadget.c
+++ b/drivers/usb/gadget/legacy/raw_gadget.c
@@ -310,13 +310,15 @@ static int gadget_bind(struct usb_gadget *gadget,
dev->eps_num = i;
spin_unlock_irqrestore(&dev->lock, flags);
- /* Matches kref_put() in gadget_unbind(). */
- kref_get(&dev->count);
-
ret = raw_queue_event(dev, USB_RAW_EVENT_CONNECT, 0, NULL);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&gadget->dev, "failed to queue event\n");
+ set_gadget_data(gadget, NULL);
+ return ret;
+ }
+ /* Matches kref_put() in gadget_unbind(). */
+ kref_get(&dev->count);
return ret;
}
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..7d49d8a0b00c 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 */
@@ -822,6 +822,9 @@ EXPORT_SYMBOL_GPL(usb_gadget_disconnect);
* usb_gadget_activate() is called. For example, user mode components may
* need to be activated before the system can talk to hosts.
*
+ * This routine may sleep; it must not be called in interrupt context
+ * (such as from within a gadget driver's disconnect() callback).
+ *
* Returns zero on success, else negative errno.
*/
int usb_gadget_deactivate(struct usb_gadget *gadget)
@@ -860,6 +863,8 @@ EXPORT_SYMBOL_GPL(usb_gadget_deactivate);
* This routine activates gadget which was previously deactivated with
* usb_gadget_deactivate() call. It calls usb_gadget_connect() if needed.
*
+ * This routine may sleep; it must not be called in interrupt context.
+ *
* Returns zero on success, else negative errno.
*/
int usb_gadget_activate(struct usb_gadget *gadget)
@@ -878,7 +883,6 @@ int usb_gadget_activate(struct usb_gadget *gadget)
*/
if (gadget->connected)
ret = usb_gadget_connect_locked(gadget);
- mutex_unlock(&gadget->udc->connect_lock);
unlock:
mutex_unlock(&gadget->udc->connect_lock);
@@ -1378,7 +1382,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",
@@ -1639,7 +1643,11 @@ static void gadget_unbind_driver(struct device *dev)
usb_gadget_disable_async_callbacks(udc);
if (gadget->irq)
synchronize_irq(gadget->irq);
+ mutex_unlock(&udc->connect_lock);
+
udc->driver->unbind(gadget);
+
+ mutex_lock(&udc->connect_lock);
usb_gadget_udc_stop_locked(udc);
mutex_unlock(&udc->connect_lock);
@@ -1856,6 +1864,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 +1880,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 +1894,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..df6028f7b273 100644
--- a/drivers/usb/gadget/udc/tegra-xudc.c
+++ b/drivers/usb/gadget/udc/tegra-xudc.c
@@ -3718,15 +3718,15 @@ static int tegra_xudc_powerdomain_init(struct tegra_xudc *xudc)
int err;
xudc->genpd_dev_device = dev_pm_domain_attach_by_name(dev, "dev");
- if (IS_ERR_OR_NULL(xudc->genpd_dev_device)) {
- err = PTR_ERR(xudc->genpd_dev_device) ? : -ENODATA;
+ if (IS_ERR(xudc->genpd_dev_device)) {
+ err = PTR_ERR(xudc->genpd_dev_device);
dev_err(dev, "failed to get device power domain: %d\n", err);
return err;
}
xudc->genpd_dev_ss = dev_pm_domain_attach_by_name(dev, "ss");
- if (IS_ERR_OR_NULL(xudc->genpd_dev_ss)) {
- err = PTR_ERR(xudc->genpd_dev_ss) ? : -ENODATA;
+ if (IS_ERR(xudc->genpd_dev_ss)) {
+ err = PTR_ERR(xudc->genpd_dev_ss);
dev_err(dev, "failed to get SuperSpeed power domain: %d\n", err);
return err;
}
@@ -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..b805c4b52ac3 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
@@ -673,7 +672,13 @@ ohci_hcd_at91_drv_resume(struct device *dev)
else
at91_start_clock(ohci_at91);
- ohci_resume(hcd, false);
+ /*
+ * According to the comment in ohci_hcd_at91_drv_suspend()
+ * we need to do a reset if the 48Mhz clock was stopped,
+ * that is, if ohci_at91->wakeup is clear. Tell ohci_resume()
+ * to reset in this case by setting its "hibernated" flag.
+ */
+ ohci_resume(hcd, !ohci_at91->wakeup);
return 0;
}
@@ -683,7 +688,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..bbdf1b0b7be1 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
@@ -592,6 +586,7 @@ static int xhci_mtk_probe(struct platform_device *pdev)
}
device_init_wakeup(dev, true);
+ dma_set_max_seg_size(dev, UINT_MAX);
xhci = hcd_to_xhci(hcd);
xhci->main_hcd = hcd;
@@ -673,7 +668,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 +698,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 +817,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..b9ae5c2a2527 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
@@ -486,10 +479,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == 0x3432)
xhci->quirks |= XHCI_BROKEN_STREAMS;
- if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483) {
+ if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483)
xhci->quirks |= XHCI_LPM_SUPPORT;
- xhci->quirks |= XHCI_EP_CTX_BROKEN_DCS;
- }
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI) {
@@ -528,6 +519,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 +836,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 +871,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..1dde53f6eb31 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;
- if (ring->num_trbs_free < num_trbs)
+ /* how many trbs will be queued past the enqueue segment? */
+ trbs_past_seg = enq_used + num_trbs - (TRBS_PER_SEGMENT - 1);
+
+ 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 */
@@ -592,11 +626,8 @@ static int xhci_move_dequeue_past_td(struct xhci_hcd *xhci,
struct xhci_ring *ep_ring;
struct xhci_command *cmd;
struct xhci_segment *new_seg;
- struct xhci_segment *halted_seg = NULL;
union xhci_trb *new_deq;
int new_cycle;
- union xhci_trb *halted_trb;
- int index = 0;
dma_addr_t addr;
u64 hw_dequeue;
bool cycle_found = false;
@@ -634,27 +665,7 @@ static int xhci_move_dequeue_past_td(struct xhci_hcd *xhci,
hw_dequeue = xhci_get_hw_deq(xhci, dev, ep_index, stream_id);
new_seg = ep_ring->deq_seg;
new_deq = ep_ring->dequeue;
-
- /*
- * Quirk: xHC write-back of the DCS field in the hardware dequeue
- * pointer is wrong - use the cycle state of the TRB pointed to by
- * the dequeue pointer.
- */
- if (xhci->quirks & XHCI_EP_CTX_BROKEN_DCS &&
- !(ep->ep_state & EP_HAS_STREAMS))
- halted_seg = trb_in_td(xhci, td->start_seg,
- td->first_trb, td->last_trb,
- hw_dequeue & ~0xf, false);
- if (halted_seg) {
- index = ((dma_addr_t)(hw_dequeue & ~0xf) - halted_seg->dma) /
- sizeof(*halted_trb);
- halted_trb = &halted_seg->trbs[index];
- new_cycle = halted_trb->generic.field[3] & 0x1;
- xhci_dbg(xhci, "Endpoint DCS = %d TRB index = %d cycle = %d\n",
- (u8)(hw_dequeue & 0x1), index, new_cycle);
- } else {
- new_cycle = hw_dequeue & 0x1;
- }
+ new_cycle = hw_dequeue & 0x1;
/*
* We want to find the pointer, segment and cycle state of the new trb
@@ -1268,10 +1279,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 +1295,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 +1304,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 +2162,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 +2231,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 +2454,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 +3158,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 +3195,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 +4175,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 +4256,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..4693d83351c6 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -1145,15 +1145,15 @@ static int tegra_xusb_powerdomain_init(struct device *dev,
int err;
tegra->genpd_dev_host = dev_pm_domain_attach_by_name(dev, "xusb_host");
- if (IS_ERR_OR_NULL(tegra->genpd_dev_host)) {
- err = PTR_ERR(tegra->genpd_dev_host) ? : -ENODATA;
+ if (IS_ERR(tegra->genpd_dev_host)) {
+ err = PTR_ERR(tegra->genpd_dev_host);
dev_err(dev, "failed to get host pm-domain: %d\n", err);
return err;
}
tegra->genpd_dev_ss = dev_pm_domain_attach_by_name(dev, "xusb_ss");
- if (IS_ERR_OR_NULL(tegra->genpd_dev_ss)) {
- err = PTR_ERR(tegra->genpd_dev_ss) ? : -ENODATA;
+ if (IS_ERR(tegra->genpd_dev_ss)) {
+ err = PTR_ERR(tegra->genpd_dev_ss);
dev_err(dev, "failed to get superspeed pm-domain: %d\n", err);
return err;
}
@@ -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/ehset.c b/drivers/usb/misc/ehset.c
index 986d6589f053..36b6e9fa7ffb 100644
--- a/drivers/usb/misc/ehset.c
+++ b/drivers/usb/misc/ehset.c
@@ -77,7 +77,7 @@ static int ehset_probe(struct usb_interface *intf,
switch (test_pid) {
case TEST_SE0_NAK_PID:
ret = ehset_prepare_port_for_testing(hub_udev, portnum);
- if (!ret)
+ if (ret < 0)
break;
ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
USB_RT_PORT, USB_PORT_FEAT_TEST,
@@ -86,7 +86,7 @@ static int ehset_probe(struct usb_interface *intf,
break;
case TEST_J_PID:
ret = ehset_prepare_port_for_testing(hub_udev, portnum);
- if (!ret)
+ if (ret < 0)
break;
ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
USB_RT_PORT, USB_PORT_FEAT_TEST,
@@ -95,7 +95,7 @@ static int ehset_probe(struct usb_interface *intf,
break;
case TEST_K_PID:
ret = ehset_prepare_port_for_testing(hub_udev, portnum);
- if (!ret)
+ if (ret < 0)
break;
ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
USB_RT_PORT, USB_PORT_FEAT_TEST,
@@ -104,7 +104,7 @@ static int ehset_probe(struct usb_interface *intf,
break;
case TEST_PACKET_PID:
ret = ehset_prepare_port_for_testing(hub_udev, portnum);
- if (!ret)
+ if (ret < 0)
break;
ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
USB_RT_PORT, USB_PORT_FEAT_TEST,
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..8ac98e60fff5 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -251,6 +251,7 @@ static void option_instat_callback(struct urb *urb);
#define QUECTEL_PRODUCT_EM061K_LTA 0x0123
#define QUECTEL_PRODUCT_EM061K_LMS 0x0124
#define QUECTEL_PRODUCT_EC25 0x0125
+#define QUECTEL_PRODUCT_EM060K_128 0x0128
#define QUECTEL_PRODUCT_EG91 0x0191
#define QUECTEL_PRODUCT_EG95 0x0195
#define QUECTEL_PRODUCT_BG96 0x0296
@@ -268,6 +269,7 @@ static void option_instat_callback(struct urb *urb);
#define QUECTEL_PRODUCT_RM520N 0x0801
#define QUECTEL_PRODUCT_EC200U 0x0901
#define QUECTEL_PRODUCT_EC200S_CN 0x6002
+#define QUECTEL_PRODUCT_EC200A 0x6005
#define QUECTEL_PRODUCT_EM061K_LWW 0x6008
#define QUECTEL_PRODUCT_EM061K_LCN 0x6009
#define QUECTEL_PRODUCT_EC200T 0x6026
@@ -1151,6 +1153,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) },
@@ -1193,6 +1199,9 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0x00, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x30) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0xff, 0x30) },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0x00, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0xff, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0xff, 0x30) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0x00, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0xff, 0x40) },
@@ -1221,6 +1230,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, 0x0900, 0xff, 0, 0), /* RM500U-CN */
.driver_info = ZLP },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200A, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200U, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) },
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-simple.c b/drivers/usb/serial/usb-serial-simple.c
index 4c6747889a19..24b8772a345e 100644
--- a/drivers/usb/serial/usb-serial-simple.c
+++ b/drivers/usb/serial/usb-serial-simple.c
@@ -38,16 +38,6 @@ static struct usb_serial_driver vendor##_device = { \
{ USB_DEVICE(0x0a21, 0x8001) } /* MMT-7305WW */
DEVICE(carelink, CARELINK_IDS);
-/* ZIO Motherboard USB driver */
-#define ZIO_IDS() \
- { USB_DEVICE(0x1CBE, 0x0103) }
-DEVICE(zio, ZIO_IDS);
-
-/* Funsoft Serial USB driver */
-#define FUNSOFT_IDS() \
- { USB_DEVICE(0x1404, 0xcddc) }
-DEVICE(funsoft, FUNSOFT_IDS);
-
/* Infineon Flashloader driver */
#define FLASHLOADER_IDS() \
{ USB_DEVICE_INTERFACE_CLASS(0x058b, 0x0041, USB_CLASS_CDC_DATA) }, \
@@ -55,6 +45,11 @@ DEVICE(funsoft, FUNSOFT_IDS);
{ USB_DEVICE(0x8087, 0x0801) }
DEVICE(flashloader, FLASHLOADER_IDS);
+/* Funsoft Serial USB driver */
+#define FUNSOFT_IDS() \
+ { USB_DEVICE(0x1404, 0xcddc) }
+DEVICE(funsoft, FUNSOFT_IDS);
+
/* Google Serial USB SubClass */
#define GOOGLE_IDS() \
{ USB_VENDOR_AND_INTERFACE_INFO(0x18d1, \
@@ -63,16 +58,21 @@ DEVICE(flashloader, FLASHLOADER_IDS);
0x01) }
DEVICE(google, GOOGLE_IDS);
+/* HP4x (48/49) Generic Serial driver */
+#define HP4X_IDS() \
+ { USB_DEVICE(0x03f0, 0x0121) }
+DEVICE(hp4x, HP4X_IDS);
+
+/* KAUFMANN RKS+CAN VCP */
+#define KAUFMANN_IDS() \
+ { USB_DEVICE(0x16d0, 0x0870) }
+DEVICE(kaufmann, KAUFMANN_IDS);
+
/* Libtransistor USB console */
#define LIBTRANSISTOR_IDS() \
{ USB_DEVICE(0x1209, 0x8b00) }
DEVICE(libtransistor, LIBTRANSISTOR_IDS);
-/* ViVOpay USB Serial Driver */
-#define VIVOPAY_IDS() \
- { USB_DEVICE(0x1d5f, 0x1004) } /* ViVOpay 8800 */
-DEVICE(vivopay, VIVOPAY_IDS);
-
/* Motorola USB Phone driver */
#define MOTO_IDS() \
{ USB_DEVICE(0x05c6, 0x3197) }, /* unknown Motorola phone */ \
@@ -101,10 +101,10 @@ DEVICE(nokia, NOKIA_IDS);
{ USB_DEVICE(0x09d7, 0x0100) } /* NovAtel FlexPack GPS */
DEVICE_N(novatel_gps, NOVATEL_IDS, 3);
-/* HP4x (48/49) Generic Serial driver */
-#define HP4X_IDS() \
- { USB_DEVICE(0x03f0, 0x0121) }
-DEVICE(hp4x, HP4X_IDS);
+/* Siemens USB/MPI adapter */
+#define SIEMENS_IDS() \
+ { USB_DEVICE(0x908, 0x0004) }
+DEVICE(siemens_mpi, SIEMENS_IDS);
/* Suunto ANT+ USB Driver */
#define SUUNTO_IDS() \
@@ -112,45 +112,52 @@ DEVICE(hp4x, HP4X_IDS);
{ USB_DEVICE(0x0fcf, 0x1009) } /* Dynastream ANT USB-m Stick */
DEVICE(suunto, SUUNTO_IDS);
-/* Siemens USB/MPI adapter */
-#define SIEMENS_IDS() \
- { USB_DEVICE(0x908, 0x0004) }
-DEVICE(siemens_mpi, SIEMENS_IDS);
+/* ViVOpay USB Serial Driver */
+#define VIVOPAY_IDS() \
+ { USB_DEVICE(0x1d5f, 0x1004) } /* ViVOpay 8800 */
+DEVICE(vivopay, VIVOPAY_IDS);
+
+/* ZIO Motherboard USB driver */
+#define ZIO_IDS() \
+ { USB_DEVICE(0x1CBE, 0x0103) }
+DEVICE(zio, ZIO_IDS);
/* All of the above structures mushed into two lists */
static struct usb_serial_driver * const serial_drivers[] = {
&carelink_device,
- &zio_device,
- &funsoft_device,
&flashloader_device,
+ &funsoft_device,
&google_device,
+ &hp4x_device,
+ &kaufmann_device,
&libtransistor_device,
- &vivopay_device,
&moto_modem_device,
&motorola_tetra_device,
&nokia_device,
&novatel_gps_device,
- &hp4x_device,
- &suunto_device,
&siemens_mpi_device,
+ &suunto_device,
+ &vivopay_device,
+ &zio_device,
NULL
};
static const struct usb_device_id id_table[] = {
CARELINK_IDS(),
- ZIO_IDS(),
- FUNSOFT_IDS(),
FLASHLOADER_IDS(),
+ FUNSOFT_IDS(),
GOOGLE_IDS(),
+ HP4X_IDS(),
+ KAUFMANN_IDS(),
LIBTRANSISTOR_IDS(),
- VIVOPAY_IDS(),
MOTO_IDS(),
MOTOROLA_TETRA_IDS(),
NOKIA_IDS(),
NOVATEL_IDS(),
- HP4X_IDS(),
- SUUNTO_IDS(),
SIEMENS_IDS(),
+ SUUNTO_IDS(),
+ VIVOPAY_IDS(),
+ ZIO_IDS(),
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
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/storage/alauda.c b/drivers/usb/storage/alauda.c
index 5e912dd29b4c..115f05a6201a 100644
--- a/drivers/usb/storage/alauda.c
+++ b/drivers/usb/storage/alauda.c
@@ -318,7 +318,8 @@ static int alauda_get_media_status(struct us_data *us, unsigned char *data)
rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
command, 0xc0, 0, 1, data, 2);
- usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]);
+ if (rc == USB_STOR_XFER_GOOD)
+ usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]);
return rc;
}
@@ -454,9 +455,14 @@ static int alauda_init_media(struct us_data *us)
static int alauda_check_media(struct us_data *us)
{
struct alauda_info *info = (struct alauda_info *) us->extra;
- unsigned char status[2];
+ unsigned char *status = us->iobuf;
+ int rc;
- alauda_get_media_status(us, status);
+ rc = alauda_get_media_status(us, status);
+ if (rc != USB_STOR_XFER_GOOD) {
+ status[0] = 0xF0; /* Pretend there's no media */
+ status[1] = 0;
+ }
/* Check for no media or door open */
if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10)
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/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
index 66de880b28d0..cdf8261e22db 100644
--- a/drivers/usb/typec/altmodes/displayport.c
+++ b/drivers/usb/typec/altmodes/displayport.c
@@ -60,6 +60,7 @@ struct dp_altmode {
enum dp_state state;
bool hpd;
+ bool pending_hpd;
struct mutex lock; /* device lock */
struct work_struct work;
@@ -144,8 +145,13 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
dp->state = DP_STATE_EXIT;
} else if (!(con & DP_CONF_CURRENTLY(dp->data.conf))) {
ret = dp_altmode_configure(dp, con);
- if (!ret)
+ if (!ret) {
dp->state = DP_STATE_CONFIGURE;
+ if (dp->hpd != hpd) {
+ dp->hpd = hpd;
+ dp->pending_hpd = true;
+ }
+ }
} else {
if (dp->hpd != hpd) {
drm_connector_oob_hotplug_event(dp->connector_fwnode);
@@ -161,6 +167,16 @@ static int dp_altmode_configured(struct dp_altmode *dp)
{
sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration");
sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment");
+ /*
+ * If the DFP_D/UFP_D sends a change in HPD when first notifying the
+ * DisplayPort driver that it is connected, then we wait until
+ * configuration is complete to signal HPD.
+ */
+ if (dp->pending_hpd) {
+ drm_connector_oob_hotplug_event(dp->connector_fwnode);
+ sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd");
+ dp->pending_hpd = false;
+ }
return dp_altmode_notify(dp);
}
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..9c1dbf3c00e0 100644
--- a/drivers/usb/typec/class.c
+++ b/drivers/usb/typec/class.c
@@ -1277,8 +1277,7 @@ static ssize_t select_usb_power_delivery_show(struct device *dev,
{
struct typec_port *port = to_typec_port(dev);
struct usb_power_delivery **pds;
- struct usb_power_delivery *pd;
- int ret = 0;
+ int i, ret = 0;
if (!port->ops || !port->ops->pd_get)
return -EOPNOTSUPP;
@@ -1287,11 +1286,11 @@ static ssize_t select_usb_power_delivery_show(struct device *dev,
if (!pds)
return 0;
- for (pd = pds[0]; pd; pd++) {
- if (pd == port->pd)
- ret += sysfs_emit(buf + ret, "[%s] ", dev_name(&pd->dev));
+ for (i = 0; pds[i]; i++) {
+ if (pds[i] == port->pd)
+ ret += sysfs_emit_at(buf, ret, "[%s] ", dev_name(&pds[i]->dev));
else
- ret += sysfs_emit(buf + ret, "%s ", dev_name(&pd->dev));
+ ret += sysfs_emit_at(buf, ret, "%s ", dev_name(&pds[i]->dev));
}
buf[ret - 1] = '\n';
@@ -2110,7 +2109,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 +2273,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);
@@ -2288,6 +2287,8 @@ struct typec_port *typec_register_port(struct device *parent,
return ERR_PTR(ret);
}
+ port->pd = cap->pd;
+
ret = device_add(&port->dev);
if (ret) {
dev_err(parent, "failed to register port (%d)\n", ret);
@@ -2295,7 +2296,7 @@ struct typec_port *typec_register_port(struct device *parent,
return ERR_PTR(ret);
}
- ret = typec_port_set_usb_power_delivery(port, cap->pd);
+ ret = usb_power_delivery_link_device(port->pd, &port->dev);
if (ret) {
dev_err(&port->dev, "failed to link pd\n");
device_unregister(&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..65da61150ba7 100644
--- a/drivers/usb/typec/mux/Kconfig
+++ b/drivers/usb/typec/mux/Kconfig
@@ -29,10 +29,21 @@ config TYPEC_MUX_INTEL_PMC
tristate "Intel PMC mux control"
depends on ACPI
depends on INTEL_SCU_IPC
+ select USB_COMMON
select USB_ROLE_SWITCH
help
Driver for USB muxes controlled by Intel PMC FW. Intel PMC FW can
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..4d1122d95013
--- /dev/null
+++ b/drivers/usb/typec/mux/nb7vpq904m.c
@@ -0,0 +1,540 @@
+// 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)
+ goto err_disable_gpio;
+
+ 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)) {
+ ret = dev_err_probe(dev, PTR_ERR(nb7->sw),
+ "Error registering typec switch\n");
+ goto err_disable_gpio;
+ }
+
+ 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)) {
+ ret = dev_err_probe(dev, PTR_ERR(nb7->retimer),
+ "Error registering typec retimer\n");
+ goto err_switch_unregister;
+ }
+
+ return 0;
+
+err_switch_unregister:
+ typec_switch_unregister(nb7->sw);
+
+err_disable_gpio:
+ gpiod_set_value(nb7->enable_gpio, 0);
+ regulator_disable(nb7->vcc_supply);
+
+ return ret;
+}
+
+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..9b467a346114
--- /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 (!tcpm->tcpc.fwnode)
+ return -EINVAL;
+
+ 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..cc1d83926497 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;
@@ -5348,6 +5349,10 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
/* Do nothing, vbus drop expected */
break;
+ case SNK_HARD_RESET_WAIT_VBUS:
+ /* Do nothing, its OK to receive vbus off events */
+ break;
+
default:
if (port->pwr_role == TYPEC_SINK && port->attached)
tcpm_set_state(port, SNK_UNATTACHED, tcpm_wait_for_discharge(port));
@@ -5394,6 +5399,9 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port)
case SNK_DEBOUNCED:
/*Do nothing, still waiting for VSAFE5V for connect */
break;
+ case SNK_HARD_RESET_WAIT_VBUS:
+ /* Do nothing, its OK to receive vbus off events */
+ break;
default:
if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled)
tcpm_set_state(port, SNK_UNATTACHED, 0);
@@ -6339,6 +6347,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 +6397,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..f6901319639d 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -785,6 +785,8 @@ static void ucsi_unregister_partner(struct ucsi_connector *con)
if (!con->partner)
return;
+ typec_set_mode(con->port, TYPEC_STATE_SAFE);
+
ucsi_unregister_partner_pdos(con);
ucsi_unregister_altmodes(con, UCSI_RECIPIENT_SOP);
typec_unregister_partner(con->partner);
@@ -812,6 +814,21 @@ 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);
+ }
+ }
+
/* 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/core/mlx5_vdpa.h b/drivers/vdpa/mlx5/core/mlx5_vdpa.h
index 25fc4120b618..b53420e874ac 100644
--- a/drivers/vdpa/mlx5/core/mlx5_vdpa.h
+++ b/drivers/vdpa/mlx5/core/mlx5_vdpa.h
@@ -31,6 +31,7 @@ struct mlx5_vdpa_mr {
struct list_head head;
unsigned long num_directs;
unsigned long num_klms;
+ /* state of dvq mr */
bool initialized;
/* serialize mkey creation and destruction */
@@ -121,6 +122,7 @@ int mlx5_vdpa_handle_set_map(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *io
int mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb,
unsigned int asid);
void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev);
+void mlx5_vdpa_destroy_mr_asid(struct mlx5_vdpa_dev *mvdev, unsigned int asid);
#define mlx5_vdpa_warn(__dev, format, ...) \
dev_warn((__dev)->mdev->device, "%s:%d:(pid %d) warning: " format, __func__, __LINE__, \
diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c
index 03e543229791..5a1971fcd87b 100644
--- a/drivers/vdpa/mlx5/core/mr.c
+++ b/drivers/vdpa/mlx5/core/mr.c
@@ -489,60 +489,103 @@ static void destroy_user_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr
}
}
-void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev)
+static void _mlx5_vdpa_destroy_cvq_mr(struct mlx5_vdpa_dev *mvdev, unsigned int asid)
+{
+ if (mvdev->group2asid[MLX5_VDPA_CVQ_GROUP] != asid)
+ return;
+
+ prune_iotlb(mvdev);
+}
+
+static void _mlx5_vdpa_destroy_dvq_mr(struct mlx5_vdpa_dev *mvdev, unsigned int asid)
{
struct mlx5_vdpa_mr *mr = &mvdev->mr;
- mutex_lock(&mr->mkey_mtx);
+ if (mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP] != asid)
+ return;
+
if (!mr->initialized)
- goto out;
+ return;
- prune_iotlb(mvdev);
if (mr->user_mr)
destroy_user_mr(mvdev, mr);
else
destroy_dma_mr(mvdev, mr);
mr->initialized = false;
-out:
+}
+
+void mlx5_vdpa_destroy_mr_asid(struct mlx5_vdpa_dev *mvdev, unsigned int asid)
+{
+ struct mlx5_vdpa_mr *mr = &mvdev->mr;
+
+ mutex_lock(&mr->mkey_mtx);
+
+ _mlx5_vdpa_destroy_dvq_mr(mvdev, asid);
+ _mlx5_vdpa_destroy_cvq_mr(mvdev, asid);
+
mutex_unlock(&mr->mkey_mtx);
}
-static int _mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev,
- struct vhost_iotlb *iotlb, unsigned int asid)
+void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev)
+{
+ mlx5_vdpa_destroy_mr_asid(mvdev, mvdev->group2asid[MLX5_VDPA_CVQ_GROUP]);
+ mlx5_vdpa_destroy_mr_asid(mvdev, mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP]);
+}
+
+static int _mlx5_vdpa_create_cvq_mr(struct mlx5_vdpa_dev *mvdev,
+ struct vhost_iotlb *iotlb,
+ unsigned int asid)
+{
+ if (mvdev->group2asid[MLX5_VDPA_CVQ_GROUP] != asid)
+ return 0;
+
+ return dup_iotlb(mvdev, iotlb);
+}
+
+static int _mlx5_vdpa_create_dvq_mr(struct mlx5_vdpa_dev *mvdev,
+ struct vhost_iotlb *iotlb,
+ unsigned int asid)
{
struct mlx5_vdpa_mr *mr = &mvdev->mr;
int err;
- if (mr->initialized)
+ if (mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP] != asid)
return 0;
- if (mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP] == asid) {
- if (iotlb)
- err = create_user_mr(mvdev, iotlb);
- else
- err = create_dma_mr(mvdev, mr);
+ if (mr->initialized)
+ return 0;
- if (err)
- return err;
- }
+ if (iotlb)
+ err = create_user_mr(mvdev, iotlb);
+ else
+ err = create_dma_mr(mvdev, mr);
- if (mvdev->group2asid[MLX5_VDPA_CVQ_GROUP] == asid) {
- err = dup_iotlb(mvdev, iotlb);
- if (err)
- goto out_err;
- }
+ if (err)
+ return err;
mr->initialized = true;
+
+ return 0;
+}
+
+static int _mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev,
+ struct vhost_iotlb *iotlb, unsigned int asid)
+{
+ int err;
+
+ err = _mlx5_vdpa_create_dvq_mr(mvdev, iotlb, asid);
+ if (err)
+ return err;
+
+ err = _mlx5_vdpa_create_cvq_mr(mvdev, iotlb, asid);
+ if (err)
+ goto out_err;
+
return 0;
out_err:
- if (mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP] == asid) {
- if (iotlb)
- destroy_user_mr(mvdev, mr);
- else
- destroy_dma_mr(mvdev, mr);
- }
+ _mlx5_vdpa_destroy_dvq_mr(mvdev, asid);
return err;
}
diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c
index 279ac6a558d2..37be945a0230 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);
@@ -2447,7 +2517,15 @@ static int mlx5_vdpa_set_driver_features(struct vdpa_device *vdev, u64 features)
else
ndev->rqt_size = 1;
- ndev->cur_num_vqs = 2 * ndev->rqt_size;
+ /* Device must start with 1 queue pair, as per VIRTIO v1.2 spec, section
+ * 5.1.6.5.5 "Device operation in multiqueue mode":
+ *
+ * Multiqueue is disabled by default.
+ * The driver enables multiqueue by sending a command using class
+ * VIRTIO_NET_CTRL_MQ. The command selects the mode of multiqueue
+ * operation, as follows: ...
+ */
+ ndev->cur_num_vqs = 2;
update_cvq_info(mvdev);
return err;
@@ -2505,6 +2583,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 +2628,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;
}
}
@@ -2564,7 +2644,7 @@ static int mlx5_vdpa_change_map(struct mlx5_vdpa_dev *mvdev,
goto err_mr;
teardown_driver(ndev);
- mlx5_vdpa_destroy_mr(mvdev);
+ mlx5_vdpa_destroy_mr_asid(mvdev, asid);
err = mlx5_vdpa_create_mr(mvdev, iotlb, asid);
if (err)
goto err_mr;
@@ -2580,7 +2660,7 @@ static int mlx5_vdpa_change_map(struct mlx5_vdpa_dev *mvdev,
return 0;
err_setup:
- mlx5_vdpa_destroy_mr(mvdev);
+ mlx5_vdpa_destroy_mr_asid(mvdev, asid);
err_mr:
return err;
}
@@ -2833,6 +2913,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 +2947,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 +2976,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 +3269,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 +3375,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;
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..c2d314d4614d
--- /dev/null
+++ b/drivers/vdpa/pds/Makefile
@@ -0,0 +1,9 @@
+# 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 \
+ debugfs.o \
+ vdpa_dev.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..9b04aad6ec35
--- /dev/null
+++ b/drivers/vdpa/pds/debugfs.c
@@ -0,0 +1,286 @@
+// 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;
+ u64 hw_features;
+
+ 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);
+ hw_features = le64_to_cpu(vdpa_aux->ident.hw_features);
+ seq_printf(seq, "hw_features: %#llx\n", hw_features);
+ print_feature_bits_all(seq, hw_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;
+ 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, "negotiated_features: %#llx\n", pdsv->negotiated_features);
+ print_feature_bits_all(seq, pdsv->negotiated_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..52b2449182ad
--- /dev/null
+++ b/drivers/vdpa/pds/vdpa_dev.c
@@ -0,0 +1,843 @@
+// 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 device *dev = &pdsv->vdpa_dev.dev;
+ u64 driver_features;
+ u16 invert_idx = 0;
+ 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) {
+ /* 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));
+ 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));
+ }
+
+ 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 hw_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;
+ }
+
+ /* Check for valid feature bits */
+ nego_features = features & pdsv->supported_features;
+ missing = features & ~nego_features;
+ if (missing) {
+ dev_err(dev, "Can't support all requested features in %#llx, missing %#llx features\n",
+ features, missing);
+ return -EOPNOTSUPP;
+ }
+
+ pdsv->negotiated_features = nego_features;
+
+ driver_features = pds_vdpa_get_driver_features(vdpa_dev);
+ dev_dbg(dev, "%s: %#llx => %#llx\n",
+ __func__, driver_features, nego_features);
+
+ /* if we're faking the F_MAC, strip it before writing to device */
+ hw_features = le64_to_cpu(pdsv->vdpa_aux->ident.hw_features);
+ if (!(hw_features & BIT_ULL(VIRTIO_NET_F_MAC)))
+ nego_features &= ~BIT_ULL(VIRTIO_NET_F_MAC);
+
+ 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 pdsv->negotiated_features;
+}
+
+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 int pds_vdpa_request_irqs(struct pds_vdpa_device *pdsv)
+{
+ struct pci_dev *pdev = pdsv->vdpa_aux->padev->vf_pdev;
+ struct pds_vdpa_aux *vdpa_aux = pdsv->vdpa_aux;
+ struct device *dev = &pdsv->vdpa_dev.dev;
+ int max_vq, nintrs, qid, err;
+
+ max_vq = vdpa_aux->vdpa_mdev.max_supported_vqs;
+
+ nintrs = pci_alloc_irq_vectors(pdev, max_vq, max_vq, PCI_IRQ_MSIX);
+ if (nintrs < 0) {
+ dev_err(dev, "Couldn't get %d msix vectors: %pe\n",
+ max_vq, ERR_PTR(nintrs));
+ return nintrs;
+ }
+
+ for (qid = 0; qid < pdsv->num_vqs; ++qid) {
+ int 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));
+ goto err_release;
+ }
+
+ pdsv->vqs[qid].irq = irq;
+ }
+
+ vdpa_aux->nintrs = nintrs;
+
+ return 0;
+
+err_release:
+ while (qid--)
+ pds_vdpa_release_irq(pdsv, qid);
+
+ pci_free_irq_vectors(pdev);
+
+ vdpa_aux->nintrs = 0;
+
+ return err;
+}
+
+static void pds_vdpa_release_irqs(struct pds_vdpa_device *pdsv)
+{
+ struct pci_dev *pdev = pdsv->vdpa_aux->padev->vf_pdev;
+ struct pds_vdpa_aux *vdpa_aux = pdsv->vdpa_aux;
+ int qid;
+
+ if (!vdpa_aux->nintrs)
+ return;
+
+ for (qid = 0; qid < pdsv->num_vqs; qid++)
+ pds_vdpa_release_irq(pdsv, qid);
+
+ pci_free_irq_vectors(pdev);
+
+ vdpa_aux->nintrs = 0;
+}
+
+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);
+
+ if (status & ~old_status & VIRTIO_CONFIG_S_DRIVER_OK) {
+ if (pds_vdpa_request_irqs(pdsv))
+ status = old_status | VIRTIO_CONFIG_S_FAILED;
+ }
+
+ 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;
+ }
+
+ pds_vdpa_cmd_set_mac(pdsv, pdsv->mac);
+ }
+
+ 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);
+ }
+ }
+
+ if (old_status & ~status & VIRTIO_CONFIG_S_DRIVER_OK)
+ pds_vdpa_release_irqs(pdsv);
+}
+
+static void pds_vdpa_init_vqs_entry(struct pds_vdpa_device *pdsv, int qid,
+ void __iomem *notify)
+{
+ memset(&pdsv->vqs[qid], 0, sizeof(pdsv->vqs[0]));
+ pdsv->vqs[qid].qid = qid;
+ pdsv->vqs[qid].pdsv = pdsv;
+ pdsv->vqs[qid].ready = false;
+ pdsv->vqs[qid].irq = VIRTIO_MSI_NO_VECTOR;
+ pdsv->vqs[qid].notify = notify;
+}
+
+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_set_status(vdpa_dev, 0);
+
+ if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
+ /* Reset the vq info */
+ for (i = 0; i < pdsv->num_vqs && !err; i++)
+ pds_vdpa_init_vqs_entry(pdsv, i, pdsv->vqs[i].notify);
+ }
+
+ 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;
+ 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 & ~pdsv->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 use the device's mac if not 00:..:00
+ * or set a random mac
+ */
+ if (add_config->mask & BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR)) {
+ ether_addr_copy(pdsv->mac, add_config->net.mac);
+ } else {
+ struct virtio_net_config __iomem *vc;
+
+ vc = pdsv->vdpa_aux->vd_mdev.device;
+ memcpy_fromio(pdsv->mac, vc->mac, sizeof(pdsv->mac));
+ if (is_zero_ether_addr(pdsv->mac) &&
+ (pdsv->supported_features & BIT_ULL(VIRTIO_NET_F_MAC))) {
+ eth_random_addr(pdsv->mac);
+ dev_info(dev, "setting random mac %pM\n", pdsv->mac);
+ }
+ }
+ pds_vdpa_cmd_set_mac(pdsv, pdsv->mac);
+
+ for (i = 0; i < pdsv->num_vqs; i++) {
+ void __iomem *notify;
+
+ notify = vp_modern_map_vq_notify(&pdsv->vdpa_aux->vd_mdev,
+ i, &pdsv->vqs[i].notify_pa);
+ pds_vdpa_init_vqs_entry(pdsv, i, notify);
+ }
+
+ 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 = 0;
+
+ 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);
+
+ /* advertise F_MAC even if the device doesn't */
+ mgmt->supported_features |= BIT_ULL(VIRTIO_NET_F_MAC);
+
+ 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);
+
+ return 0;
+}
diff --git a/drivers/vdpa/pds/vdpa_dev.h b/drivers/vdpa/pds/vdpa_dev.h
new file mode 100644
index 000000000000..d984ba24a7da
--- /dev/null
+++ b/drivers/vdpa/pds/vdpa_dev.h
@@ -0,0 +1,50 @@
+/* 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; /* supported device features */
+ u64 negotiated_features; /* negotiated features */
+ u8 vdpa_index; /* rsvd for future subdevice use */
+ u8 num_vqs; /* num vqs in use */
+ u8 mac[ETH_ALEN]; /* mac selected when the device was added */
+ 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.c b/drivers/vdpa/vdpa.c
index 965e32529eb8..a7612e0783b3 100644
--- a/drivers/vdpa/vdpa.c
+++ b/drivers/vdpa/vdpa.c
@@ -1247,44 +1247,41 @@ static const struct nla_policy vdpa_nl_policy[VDPA_ATTR_MAX + 1] = {
[VDPA_ATTR_MGMTDEV_DEV_NAME] = { .type = NLA_STRING },
[VDPA_ATTR_DEV_NAME] = { .type = NLA_STRING },
[VDPA_ATTR_DEV_NET_CFG_MACADDR] = NLA_POLICY_ETH_ADDR,
+ [VDPA_ATTR_DEV_NET_CFG_MAX_VQP] = { .type = NLA_U16 },
/* virtio spec 1.1 section 5.1.4.1 for valid MTU range */
[VDPA_ATTR_DEV_NET_CFG_MTU] = NLA_POLICY_MIN(NLA_U16, 68),
+ [VDPA_ATTR_DEV_QUEUE_INDEX] = { .type = NLA_U32 },
+ [VDPA_ATTR_DEV_FEATURES] = { .type = NLA_U64 },
};
static const struct genl_ops vdpa_nl_ops[] = {
{
.cmd = VDPA_CMD_MGMTDEV_GET,
- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = vdpa_nl_cmd_mgmtdev_get_doit,
.dumpit = vdpa_nl_cmd_mgmtdev_get_dumpit,
},
{
.cmd = VDPA_CMD_DEV_NEW,
- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = vdpa_nl_cmd_dev_add_set_doit,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = VDPA_CMD_DEV_DEL,
- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = vdpa_nl_cmd_dev_del_set_doit,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = VDPA_CMD_DEV_GET,
- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = vdpa_nl_cmd_dev_get_doit,
.dumpit = vdpa_nl_cmd_dev_get_dumpit,
},
{
.cmd = VDPA_CMD_DEV_CONFIG_GET,
- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = vdpa_nl_cmd_dev_config_get_doit,
.dumpit = vdpa_nl_cmd_dev_config_get_dumpit,
},
{
.cmd = VDPA_CMD_DEV_VSTATS_GET,
- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = vdpa_nl_cmd_dev_stats_get_doit,
.flags = GENL_ADMIN_PERM,
},
diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c
index 5f5c21674fdc..df7869537ef1 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;
}
@@ -931,10 +935,10 @@ static void vduse_dev_irq_inject(struct work_struct *work)
{
struct vduse_dev *dev = container_of(work, struct vduse_dev, inject);
- spin_lock_irq(&dev->irq_lock);
+ spin_lock_bh(&dev->irq_lock);
if (dev->config_cb.callback)
dev->config_cb.callback(dev->config_cb.private);
- spin_unlock_irq(&dev->irq_lock);
+ spin_unlock_bh(&dev->irq_lock);
}
static void vduse_vq_irq_inject(struct work_struct *work)
@@ -942,10 +946,10 @@ static void vduse_vq_irq_inject(struct work_struct *work)
struct vduse_virtqueue *vq = container_of(work,
struct vduse_virtqueue, inject);
- spin_lock_irq(&vq->irq_lock);
+ spin_lock_bh(&vq->irq_lock);
if (vq->ready && vq->cb.callback)
vq->cb.callback(vq->cb.private);
- spin_unlock_irq(&vq->irq_lock);
+ spin_unlock_bh(&vq->irq_lock);
}
static bool vduse_vq_signal_irqfd(struct vduse_virtqueue *vq)
@@ -1052,7 +1056,7 @@ static int vduse_dev_reg_umem(struct vduse_dev *dev,
goto out;
pinned = pin_user_pages(uaddr, npages, FOLL_LONGTERM | FOLL_WRITE,
- page_list, NULL);
+ page_list);
if (pinned != npages) {
ret = pinned < 0 ? pinned : -ENOMEM;
goto out;
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/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 0d2f805468e1..ebe0ad31d0b0 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -514,6 +514,7 @@ static int follow_fault_pfn(struct vm_area_struct *vma, struct mm_struct *mm,
bool write_fault)
{
pte_t *ptep;
+ pte_t pte;
spinlock_t *ptl;
int ret;
@@ -536,10 +537,12 @@ static int follow_fault_pfn(struct vm_area_struct *vma, struct mm_struct *mm,
return ret;
}
- if (write_fault && !pte_write(*ptep))
+ pte = ptep_get(ptep);
+
+ if (write_fault && !pte_write(pte))
ret = -EFAULT;
else
- *pfn = pte_pfn(*ptep);
+ *pfn = pte_pfn(pte);
pte_unmap_unlock(ptep, ptl);
return ret;
@@ -562,7 +565,7 @@ static int vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr,
mmap_read_lock(mm);
ret = pin_user_pages_remote(mm, vaddr, npages, flags | FOLL_LONGTERM,
- pages, NULL, NULL);
+ pages, NULL);
if (ret > 0) {
int i;
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..abef0619c790 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -25,6 +25,8 @@
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <linux/miscdevice.h>
+#include <linux/blk_types.h>
+#include <linux/bio.h>
#include <asm/unaligned.h>
#include <scsi/scsi_common.h>
#include <scsi/scsi_proto.h>
@@ -75,6 +77,9 @@ struct vhost_scsi_cmd {
u32 tvc_prot_sgl_count;
/* Saved unpacked SCSI LUN for vhost_scsi_target_queue_cmd() */
u32 tvc_lun;
+ u32 copied_iov:1;
+ const void *saved_iter_addr;
+ struct iov_iter saved_iter;
/* Pointer to the SGL formatted memory from virtio-scsi */
struct scatterlist *tvc_sgl;
struct scatterlist *tvc_prot_sgl;
@@ -167,6 +172,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 +187,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 +199,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 */
@@ -328,8 +333,13 @@ static void vhost_scsi_release_cmd_res(struct se_cmd *se_cmd)
int i;
if (tv_cmd->tvc_sgl_count) {
- for (i = 0; i < tv_cmd->tvc_sgl_count; i++)
- put_page(sg_page(&tv_cmd->tvc_sgl[i]));
+ for (i = 0; i < tv_cmd->tvc_sgl_count; i++) {
+ if (tv_cmd->copied_iov)
+ __free_page(sg_page(&tv_cmd->tvc_sgl[i]));
+ else
+ put_page(sg_page(&tv_cmd->tvc_sgl[i]));
+ }
+ kfree(tv_cmd->saved_iter_addr);
}
if (tv_cmd->tvc_prot_sgl_count) {
for (i = 0; i < tv_cmd->tvc_prot_sgl_count; i++)
@@ -353,15 +363,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);
}
}
@@ -502,6 +514,28 @@ static void vhost_scsi_evt_work(struct vhost_work *work)
mutex_unlock(&vq->mutex);
}
+static int vhost_scsi_copy_sgl_to_iov(struct vhost_scsi_cmd *cmd)
+{
+ struct iov_iter *iter = &cmd->saved_iter;
+ struct scatterlist *sg = cmd->tvc_sgl;
+ struct page *page;
+ size_t len;
+ int i;
+
+ for (i = 0; i < cmd->tvc_sgl_count; i++) {
+ page = sg_page(&sg[i]);
+ len = sg[i].length;
+
+ if (copy_page_to_iter(page, 0, len, iter) != len) {
+ pr_err("Could not copy data while handling misaligned cmd. Error %zu\n",
+ len);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
/* Fill in status and signal that we are done processing this command
*
* This is scheduled in the vhost work queue so we are called with the owner
@@ -509,51 +543,52 @@ 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;
pr_debug("%s tv_cmd %p resid %u status %#02x\n", __func__,
cmd, se_cmd->residual_count, se_cmd->scsi_status);
-
memset(&v_rsp, 0, sizeof(v_rsp));
- v_rsp.resid = cpu_to_vhost32(cmd->tvc_vq, se_cmd->residual_count);
- /* TODO is status_qualifier field needed? */
- v_rsp.status = se_cmd->scsi_status;
- v_rsp.sense_len = cpu_to_vhost32(cmd->tvc_vq,
- se_cmd->scsi_sense_length);
- memcpy(v_rsp.sense, cmd->tvc_sense_buf,
- se_cmd->scsi_sense_length);
+
+ if (cmd->saved_iter_addr && vhost_scsi_copy_sgl_to_iov(cmd)) {
+ v_rsp.response = VIRTIO_SCSI_S_BAD_TARGET;
+ } else {
+ v_rsp.resid = cpu_to_vhost32(cmd->tvc_vq,
+ se_cmd->residual_count);
+ /* TODO is status_qualifier field needed? */
+ v_rsp.status = se_cmd->scsi_status;
+ v_rsp.sense_len = cpu_to_vhost32(cmd->tvc_vq,
+ se_cmd->scsi_sense_length);
+ memcpy(v_rsp.sense, cmd->tvc_sense_buf,
+ se_cmd->scsi_sense_length);
+ }
iov_iter_init(&iov_iter, ITER_DEST, cmd->tvc_resp_iov,
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 *
@@ -615,12 +650,12 @@ static int
vhost_scsi_map_to_sgl(struct vhost_scsi_cmd *cmd,
struct iov_iter *iter,
struct scatterlist *sgl,
- bool write)
+ bool is_prot)
{
struct page **pages = cmd->tvc_upages;
struct scatterlist *sg = sgl;
- ssize_t bytes;
- size_t offset;
+ ssize_t bytes, mapped_bytes;
+ size_t offset, mapped_offset;
unsigned int npages = 0;
bytes = iov_iter_get_pages2(iter, pages, LONG_MAX,
@@ -629,13 +664,53 @@ vhost_scsi_map_to_sgl(struct vhost_scsi_cmd *cmd,
if (bytes <= 0)
return bytes < 0 ? bytes : -EFAULT;
+ mapped_bytes = bytes;
+ mapped_offset = offset;
+
while (bytes) {
unsigned n = min_t(unsigned, PAGE_SIZE - offset, bytes);
+ /*
+ * The block layer requires bios/requests to be a multiple of
+ * 512 bytes, but Windows can send us vecs that are misaligned.
+ * This can result in bios and later requests with misaligned
+ * sizes if we have to break up a cmd/scatterlist into multiple
+ * bios.
+ *
+ * We currently only break up a command into multiple bios if
+ * we hit the vec/seg limit, so check if our sgl_count is
+ * greater than the max and if a vec in the cmd has a
+ * misaligned offset/size.
+ */
+ if (!is_prot &&
+ (offset & (SECTOR_SIZE - 1) || n & (SECTOR_SIZE - 1)) &&
+ cmd->tvc_sgl_count > BIO_MAX_VECS) {
+ WARN_ONCE(true,
+ "vhost-scsi detected misaligned IO. Performance may be degraded.");
+ goto revert_iter_get_pages;
+ }
+
sg_set_page(sg++, pages[npages++], n, offset);
bytes -= n;
offset = 0;
}
+
return npages;
+
+revert_iter_get_pages:
+ iov_iter_revert(iter, mapped_bytes);
+
+ npages = 0;
+ while (mapped_bytes) {
+ unsigned int n = min_t(unsigned int, PAGE_SIZE - mapped_offset,
+ mapped_bytes);
+
+ put_page(pages[npages++]);
+
+ mapped_bytes -= n;
+ mapped_offset = 0;
+ }
+
+ return -EINVAL;
}
static int
@@ -659,25 +734,80 @@ vhost_scsi_calc_sgls(struct iov_iter *iter, size_t bytes, int max_sgls)
}
static int
-vhost_scsi_iov_to_sgl(struct vhost_scsi_cmd *cmd, bool write,
- struct iov_iter *iter,
- struct scatterlist *sg, int sg_count)
+vhost_scsi_copy_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter,
+ struct scatterlist *sg, int sg_count)
+{
+ size_t len = iov_iter_count(iter);
+ unsigned int nbytes = 0;
+ struct page *page;
+ int i;
+
+ if (cmd->tvc_data_direction == DMA_FROM_DEVICE) {
+ cmd->saved_iter_addr = dup_iter(&cmd->saved_iter, iter,
+ GFP_KERNEL);
+ if (!cmd->saved_iter_addr)
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < sg_count; i++) {
+ page = alloc_page(GFP_KERNEL);
+ if (!page) {
+ i--;
+ goto err;
+ }
+
+ nbytes = min_t(unsigned int, PAGE_SIZE, len);
+ sg_set_page(&sg[i], page, nbytes, 0);
+
+ if (cmd->tvc_data_direction == DMA_TO_DEVICE &&
+ copy_page_from_iter(page, 0, nbytes, iter) != nbytes)
+ goto err;
+
+ len -= nbytes;
+ }
+
+ cmd->copied_iov = 1;
+ return 0;
+
+err:
+ pr_err("Could not read %u bytes while handling misaligned cmd\n",
+ nbytes);
+
+ for (; i >= 0; i--)
+ __free_page(sg_page(&sg[i]));
+ kfree(cmd->saved_iter_addr);
+ return -ENOMEM;
+}
+
+static int
+vhost_scsi_map_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter,
+ struct scatterlist *sg, int sg_count, bool is_prot)
{
struct scatterlist *p = sg;
+ size_t revert_bytes;
int ret;
while (iov_iter_count(iter)) {
- ret = vhost_scsi_map_to_sgl(cmd, iter, sg, write);
+ ret = vhost_scsi_map_to_sgl(cmd, iter, sg, is_prot);
if (ret < 0) {
+ revert_bytes = 0;
+
while (p < sg) {
- struct page *page = sg_page(p++);
- if (page)
+ struct page *page = sg_page(p);
+
+ if (page) {
put_page(page);
+ revert_bytes += p->length;
+ }
+ p++;
}
+
+ iov_iter_revert(iter, revert_bytes);
return ret;
}
sg += ret;
}
+
return 0;
}
@@ -687,7 +817,6 @@ vhost_scsi_mapal(struct vhost_scsi_cmd *cmd,
size_t data_bytes, struct iov_iter *data_iter)
{
int sgl_count, ret;
- bool write = (cmd->tvc_data_direction == DMA_FROM_DEVICE);
if (prot_bytes) {
sgl_count = vhost_scsi_calc_sgls(prot_iter, prot_bytes,
@@ -700,9 +829,9 @@ vhost_scsi_mapal(struct vhost_scsi_cmd *cmd,
pr_debug("%s prot_sg %p prot_sgl_count %u\n", __func__,
cmd->tvc_prot_sgl, cmd->tvc_prot_sgl_count);
- ret = vhost_scsi_iov_to_sgl(cmd, write, prot_iter,
- cmd->tvc_prot_sgl,
- cmd->tvc_prot_sgl_count);
+ ret = vhost_scsi_map_iov_to_sgl(cmd, prot_iter,
+ cmd->tvc_prot_sgl,
+ cmd->tvc_prot_sgl_count, true);
if (ret < 0) {
cmd->tvc_prot_sgl_count = 0;
return ret;
@@ -718,8 +847,14 @@ vhost_scsi_mapal(struct vhost_scsi_cmd *cmd,
pr_debug("%s data_sg %p data_sgl_count %u\n", __func__,
cmd->tvc_sgl, cmd->tvc_sgl_count);
- ret = vhost_scsi_iov_to_sgl(cmd, write, data_iter,
- cmd->tvc_sgl, cmd->tvc_sgl_count);
+ ret = vhost_scsi_map_iov_to_sgl(cmd, data_iter, cmd->tvc_sgl,
+ cmd->tvc_sgl_count, false);
+ if (ret == -EINVAL) {
+ sg_init_table(cmd->tvc_sgl, cmd->tvc_sgl_count);
+ ret = vhost_scsi_copy_iov_to_sgl(cmd, data_iter, cmd->tvc_sgl,
+ cmd->tvc_sgl_count);
+ }
+
if (ret < 0) {
cmd->tvc_sgl_count = 0;
return ret;
@@ -1135,12 +1270,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 +1485,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 +1509,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 +1523,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 +1919,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 +1938,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 +1952,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 +1962,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 +1984,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 +2003,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 +2064,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 +2151,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/vdpa.c b/drivers/vhost/vdpa.c
index bf77924d5b60..b43e8680eee8 100644
--- a/drivers/vhost/vdpa.c
+++ b/drivers/vhost/vdpa.c
@@ -1009,7 +1009,7 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
while (npages) {
sz2pin = min_t(unsigned long, npages, list_size);
pinned = pin_user_pages(cur_base, sz2pin,
- gup_flags, page_list, NULL);
+ gup_flags, page_list);
if (sz2pin != pinned) {
if (pinned < 0) {
ret = pinned;
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..992a4fa431aa 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
@@ -156,7 +156,7 @@ static bool sticon_scroll(struct vc_data *conp, unsigned int t,
return false;
}
-static int sticon_set_def_font(int unit, struct console_font *op)
+static void sticon_set_def_font(int unit)
{
if (font_data[unit] != STI_DEF_FONT) {
if (--FNTREFCOUNT(font_data[unit]) == 0) {
@@ -165,8 +165,6 @@ static int sticon_set_def_font(int unit, struct console_font *op)
}
font_data[unit] = STI_DEF_FONT;
}
-
- return 0;
}
static int sticon_set_font(struct vc_data *vc, struct console_font *op,
@@ -246,7 +244,7 @@ static int sticon_set_font(struct vc_data *vc, struct console_font *op,
vc->vc_video_erase_char, font_data[vc->vc_num]);
/* delete old font in case it is a user font */
- sticon_set_def_font(unit, NULL);
+ sticon_set_def_font(unit);
FNTREFCOUNT(cooked_font)++;
font_data[unit] = cooked_font;
@@ -264,7 +262,9 @@ static int sticon_set_font(struct vc_data *vc, struct console_font *op,
static int sticon_font_default(struct vc_data *vc, struct console_font *op, char *name)
{
- return sticon_set_def_font(vc->vc_num, op);
+ sticon_set_def_font(vc->vc_num);
+
+ return 0;
}
static int sticon_font_set(struct vc_data *vc, struct console_font *font,
@@ -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;
@@ -297,7 +297,7 @@ static void sticon_deinit(struct vc_data *c)
/* free memory used by user font */
for (i = 0; i < MAX_NR_CONSOLES; i++)
- sticon_set_def_font(i, NULL);
+ sticon_set_def_font(i);
}
static void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
@@ -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/console/vgacon.c b/drivers/video/console/vgacon.c
index e25ba523892e..7ad047bcae17 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -65,16 +65,8 @@ static struct vgastate vgastate;
* Interface used by the world
*/
-static const char *vgacon_startup(void);
-static void vgacon_init(struct vc_data *c, int init);
-static void vgacon_deinit(struct vc_data *c);
-static void vgacon_cursor(struct vc_data *c, int mode);
-static int vgacon_switch(struct vc_data *c);
-static int vgacon_blank(struct vc_data *c, int blank, int mode_switch);
-static void vgacon_scrolldelta(struct vc_data *c, int lines);
static int vgacon_set_origin(struct vc_data *c);
-static void vgacon_save_screen(struct vc_data *c);
-static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
+
static struct uni_pagedict *vgacon_uni_pagedir;
static int vgacon_refcount;
@@ -142,12 +134,6 @@ static inline void vga_set_mem_top(struct vc_data *c)
write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
}
-static void vgacon_restore_screen(struct vc_data *c)
-{
- if (c->vc_origin != c->vc_visible_origin)
- vgacon_scrolldelta(c, 0);
-}
-
static void vgacon_scrolldelta(struct vc_data *c, int lines)
{
vc_scrolldelta_helper(c, lines, vga_rolled_over, (void *)vga_vram_base,
@@ -155,6 +141,12 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
vga_set_mem_top(c);
}
+static void vgacon_restore_screen(struct vc_data *c)
+{
+ if (c->vc_origin != c->vc_visible_origin)
+ vgacon_scrolldelta(c, 0);
+}
+
static const char *vgacon_startup(void)
{
const char *display_desc = NULL;
@@ -445,7 +437,7 @@ static void vgacon_invert_region(struct vc_data *c, u16 * p, int count)
}
}
-static void vgacon_set_cursor_size(int xpos, int from, int to)
+static void vgacon_set_cursor_size(int from, int to)
{
unsigned long flags;
int curs, cure;
@@ -478,18 +470,22 @@ static void vgacon_set_cursor_size(int xpos, int from, int to)
static void vgacon_cursor(struct vc_data *c, int mode)
{
+ unsigned int c_height;
+
if (c->vc_mode != KD_TEXT)
return;
vgacon_restore_screen(c);
+ c_height = c->vc_cell_height;
+
switch (mode) {
case CM_ERASE:
write_vga(14, (c->vc_pos - vga_vram_base) / 2);
if (vga_video_type >= VIDEO_TYPE_VGAC)
- vgacon_set_cursor_size(c->state.x, 31, 30);
+ vgacon_set_cursor_size(31, 30);
else
- vgacon_set_cursor_size(c->state.x, 31, 31);
+ vgacon_set_cursor_size(31, 31);
break;
case CM_MOVE:
@@ -497,51 +493,38 @@ static void vgacon_cursor(struct vc_data *c, int mode)
write_vga(14, (c->vc_pos - vga_vram_base) / 2);
switch (CUR_SIZE(c->vc_cursor_type)) {
case CUR_UNDERLINE:
- vgacon_set_cursor_size(c->state.x,
- c->vc_cell_height -
- (c->vc_cell_height <
- 10 ? 2 : 3),
- c->vc_cell_height -
- (c->vc_cell_height <
- 10 ? 1 : 2));
+ vgacon_set_cursor_size(c_height -
+ (c_height < 10 ? 2 : 3),
+ c_height -
+ (c_height < 10 ? 1 : 2));
break;
case CUR_TWO_THIRDS:
- vgacon_set_cursor_size(c->state.x,
- c->vc_cell_height / 3,
- c->vc_cell_height -
- (c->vc_cell_height <
- 10 ? 1 : 2));
+ vgacon_set_cursor_size(c_height / 3, c_height -
+ (c_height < 10 ? 1 : 2));
break;
case CUR_LOWER_THIRD:
- vgacon_set_cursor_size(c->state.x,
- (c->vc_cell_height * 2) / 3,
- c->vc_cell_height -
- (c->vc_cell_height <
- 10 ? 1 : 2));
+ vgacon_set_cursor_size(c_height * 2 / 3, c_height -
+ (c_height < 10 ? 1 : 2));
break;
case CUR_LOWER_HALF:
- vgacon_set_cursor_size(c->state.x,
- c->vc_cell_height / 2,
- c->vc_cell_height -
- (c->vc_cell_height <
- 10 ? 1 : 2));
+ vgacon_set_cursor_size(c_height / 2, c_height -
+ (c_height < 10 ? 1 : 2));
break;
case CUR_NONE:
if (vga_video_type >= VIDEO_TYPE_VGAC)
- vgacon_set_cursor_size(c->state.x, 31, 30);
+ vgacon_set_cursor_size(31, 30);
else
- vgacon_set_cursor_size(c->state.x, 31, 31);
+ vgacon_set_cursor_size(31, 31);
break;
default:
- vgacon_set_cursor_size(c->state.x, 1,
- c->vc_cell_height);
+ vgacon_set_cursor_size(1, c_height);
break;
}
break;
}
}
-static int vgacon_doresize(struct vc_data *c,
+static void vgacon_doresize(struct vc_data *c,
unsigned int width, unsigned int height)
{
unsigned long flags;
@@ -600,7 +583,6 @@ static int vgacon_doresize(struct vc_data *c,
}
raw_spin_unlock_irqrestore(&vga_lock, flags);
- return 0;
}
static int vgacon_switch(struct vc_data *c)
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/amifb.c b/drivers/video/fbdev/amifb.c
index d88265dbebf4..f216b2c702a1 100644
--- a/drivers/video/fbdev/amifb.c
+++ b/drivers/video/fbdev/amifb.c
@@ -687,7 +687,7 @@ struct fb_var_cursorinfo {
__u16 height;
__u16 xspot;
__u16 yspot;
- __u8 data[1]; /* field with [height][width] */
+ DECLARE_FLEX_ARRAY(__u8, data); /* field with [height][width] */
};
struct fb_cursorstate {
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/atmel_lcdfb.c b/drivers/video/fbdev/atmel_lcdfb.c
index 987c5f5f0241..f245da138e68 100644
--- a/drivers/video/fbdev/atmel_lcdfb.c
+++ b/drivers/video/fbdev/atmel_lcdfb.c
@@ -1308,7 +1308,7 @@ static struct platform_driver atmel_lcdfb_driver = {
.resume = atmel_lcdfb_resume,
.driver = {
.name = "atmel_lcdfb",
- .of_match_table = of_match_ptr(atmel_lcdfb_dt_ids),
+ .of_match_table = atmel_lcdfb_dt_ids,
},
};
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..c137d6afe484 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);
@@ -1732,6 +1732,9 @@ static int au1200fb_drv_probe(struct platform_device *dev)
/* Now hook interrupt too */
irq = platform_get_irq(dev, 0);
+ if (irq < 0)
+ return irq;
+
ret = request_irq(irq, au1200fb_handle_irq,
IRQF_SHARED, "lcd", (void *)dev);
if (ret) {
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/bw2.c b/drivers/video/fbdev/bw2.c
index 025d663dc6fd..39f438de0d6b 100644
--- a/drivers/video/fbdev/bw2.c
+++ b/drivers/video/fbdev/bw2.c
@@ -17,7 +17,8 @@
#include <linux/init.h>
#include <linux/fb.h>
#include <linux/mm.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/fbio.h>
diff --git a/drivers/video/fbdev/cg14.c b/drivers/video/fbdev/cg14.c
index 832a82f45c80..90fdc9d9bf5a 100644
--- a/drivers/video/fbdev/cg14.c
+++ b/drivers/video/fbdev/cg14.c
@@ -17,7 +17,8 @@
#include <linux/fb.h>
#include <linux/mm.h>
#include <linux/uaccess.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/fbio.h>
diff --git a/drivers/video/fbdev/cg3.c b/drivers/video/fbdev/cg3.c
index 6335cd364c74..98c60f72046a 100644
--- a/drivers/video/fbdev/cg3.c
+++ b/drivers/video/fbdev/cg3.c
@@ -17,7 +17,8 @@
#include <linux/init.h>
#include <linux/fb.h>
#include <linux/mm.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/fbio.h>
diff --git a/drivers/video/fbdev/cg6.c b/drivers/video/fbdev/cg6.c
index 6884572efea1..6427b85f1a94 100644
--- a/drivers/video/fbdev/cg6.c
+++ b/drivers/video/fbdev/cg6.c
@@ -17,7 +17,8 @@
#include <linux/init.h>
#include <linux/fb.h>
#include <linux/mm.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/fbio.h>
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..887fad44e7ec 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"
@@ -1613,8 +1612,7 @@ static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info,
}
}
-static void fbcon_redraw(struct vc_data *vc, struct fbcon_display *p,
- int line, int count, int offset)
+static void fbcon_redraw(struct vc_data *vc, int line, int count, int offset)
{
unsigned short *d = (unsigned short *)
(vc->vc_origin + vc->vc_size_row * line);
@@ -1828,7 +1826,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
case SCROLL_REDRAW:
redraw_up:
- fbcon_redraw(vc, p, t, b - t - count,
+ fbcon_redraw(vc, t, b - t - count,
count * vc->vc_cols);
fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
scr_memsetw((unsigned short *) (vc->vc_origin +
@@ -1914,7 +1912,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
case SCROLL_REDRAW:
redraw_down:
- fbcon_redraw(vc, p, b - 1, b - t - count,
+ fbcon_redraw(vc, b - 1, b - t - count,
-count * vc->vc_cols);
fbcon_clear(vc, t, 0, count, vc->vc_cols);
scr_memsetw((unsigned short *) (vc->vc_origin +
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/ep93xx-fb.c b/drivers/video/fbdev/ep93xx-fb.c
index 94fe52928be2..22158d9ca8dd 100644
--- a/drivers/video/fbdev/ep93xx-fb.c
+++ b/drivers/video/fbdev/ep93xx-fb.c
@@ -548,7 +548,9 @@ static int ep93xxfb_probe(struct platform_device *pdev)
}
ep93xxfb_set_par(info);
- clk_prepare_enable(fbi->clk);
+ err = clk_prepare_enable(fbi->clk);
+ if (err)
+ goto failed_check;
err = register_framebuffer(info);
if (err)
diff --git a/drivers/video/fbdev/ffb.c b/drivers/video/fbdev/ffb.c
index c6d3111dcbb0..c473841eb6ff 100644
--- a/drivers/video/fbdev/ffb.c
+++ b/drivers/video/fbdev/ffb.c
@@ -16,7 +16,8 @@
#include <linux/fb.h>
#include <linux/mm.h>
#include <linux/timer.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/upa.h>
diff --git a/drivers/video/fbdev/goldfishfb.c b/drivers/video/fbdev/goldfishfb.c
index 6fa2108fd912..e41c9fef4a3b 100644
--- a/drivers/video/fbdev/goldfishfb.c
+++ b/drivers/video/fbdev/goldfishfb.c
@@ -203,8 +203,8 @@ static int goldfish_fb_probe(struct platform_device *pdev)
}
fb->irq = platform_get_irq(pdev, 0);
- if (fb->irq <= 0) {
- ret = -ENODEV;
+ if (fb->irq < 0) {
+ ret = fb->irq;
goto err_no_irq;
}
diff --git a/drivers/video/fbdev/grvga.c b/drivers/video/fbdev/grvga.c
index 9aa15be29ea9..d4a9a58b3691 100644
--- a/drivers/video/fbdev/grvga.c
+++ b/drivers/video/fbdev/grvga.c
@@ -12,8 +12,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
-#include <linux/of_platform.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
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/imxfb.c b/drivers/video/fbdev/imxfb.c
index adf36690c342..77dedd2c05fd 100644
--- a/drivers/video/fbdev/imxfb.c
+++ b/drivers/video/fbdev/imxfb.c
@@ -613,10 +613,10 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
if (var->hsync_len < 1 || var->hsync_len > 64)
printk(KERN_ERR "%s: invalid hsync_len %d\n",
info->fix.id, var->hsync_len);
- if (var->left_margin > 255)
+ if (var->left_margin < 3 || var->left_margin > 255)
printk(KERN_ERR "%s: invalid left_margin %d\n",
info->fix.id, var->left_margin);
- if (var->right_margin > 255)
+ if (var->right_margin < 1 || var->right_margin > 255)
printk(KERN_ERR "%s: invalid right_margin %d\n",
info->fix.id, var->right_margin);
if (var->yres < 1 || var->yres > ymax_mask)
@@ -673,7 +673,8 @@ static int imxfb_init_fbinfo(struct platform_device *pdev)
pr_debug("%s\n",__func__);
- info->pseudo_palette = kmalloc_array(16, sizeof(u32), GFP_KERNEL);
+ info->pseudo_palette = devm_kmalloc_array(&pdev->dev, 16,
+ sizeof(u32), GFP_KERNEL);
if (!info->pseudo_palette)
return -ENOMEM;
@@ -868,7 +869,6 @@ static int imxfb_probe(struct platform_device *pdev)
struct imxfb_info *fbi;
struct lcd_device *lcd;
struct fb_info *info;
- struct resource *res;
struct imx_fb_videomode *m;
const struct of_device_id *of_id;
struct device_node *display_np;
@@ -885,10 +885,6 @@ static int imxfb_probe(struct platform_device *pdev)
if (of_id)
pdev->id_entry = of_id->data;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
info = framebuffer_alloc(sizeof(struct imxfb_info), &pdev->dev);
if (!info)
return -ENOMEM;
@@ -907,7 +903,7 @@ static int imxfb_probe(struct platform_device *pdev)
if (!display_np) {
dev_err(&pdev->dev, "No display defined in devicetree\n");
ret = -EINVAL;
- goto failed_of_parse;
+ goto failed_init;
}
/*
@@ -921,13 +917,13 @@ static int imxfb_probe(struct platform_device *pdev)
if (!fbi->mode) {
ret = -ENOMEM;
of_node_put(display_np);
- goto failed_of_parse;
+ goto failed_init;
}
ret = imxfb_of_read_mode(&pdev->dev, display_np, fbi->mode);
of_node_put(display_np);
if (ret)
- goto failed_of_parse;
+ goto failed_init;
/* Calculate maximum bytes used per pixel. In most cases this should
* be the same as m->bpp/8 */
@@ -940,7 +936,7 @@ static int imxfb_probe(struct platform_device *pdev)
fbi->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(fbi->clk_ipg)) {
ret = PTR_ERR(fbi->clk_ipg);
- goto failed_getclock;
+ goto failed_init;
}
/*
@@ -955,25 +951,25 @@ static int imxfb_probe(struct platform_device *pdev)
*/
ret = clk_prepare_enable(fbi->clk_ipg);
if (ret)
- goto failed_getclock;
+ goto failed_init;
clk_disable_unprepare(fbi->clk_ipg);
fbi->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
if (IS_ERR(fbi->clk_ahb)) {
ret = PTR_ERR(fbi->clk_ahb);
- goto failed_getclock;
+ goto failed_init;
}
fbi->clk_per = devm_clk_get(&pdev->dev, "per");
if (IS_ERR(fbi->clk_per)) {
ret = PTR_ERR(fbi->clk_per);
- goto failed_getclock;
+ goto failed_init;
}
- fbi->regs = devm_ioremap_resource(&pdev->dev, res);
+ fbi->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(fbi->regs)) {
ret = PTR_ERR(fbi->regs);
- goto failed_ioremap;
+ goto failed_init;
}
fbi->map_size = PAGE_ALIGN(info->fix.smem_len);
@@ -982,7 +978,7 @@ static int imxfb_probe(struct platform_device *pdev)
if (!info->screen_buffer) {
dev_err(&pdev->dev, "Failed to allocate video RAM\n");
ret = -ENOMEM;
- goto failed_map;
+ goto failed_init;
}
info->fix.smem_start = fbi->map_dma;
@@ -1034,18 +1030,11 @@ static int imxfb_probe(struct platform_device *pdev)
failed_lcd:
unregister_framebuffer(info);
-
failed_register:
fb_dealloc_cmap(&info->cmap);
failed_cmap:
dma_free_wc(&pdev->dev, fbi->map_size, info->screen_buffer,
fbi->map_dma);
-failed_map:
-failed_ioremap:
-failed_getclock:
- release_mem_region(res->start, resource_size(res));
-failed_of_parse:
- kfree(info->pseudo_palette);
failed_init:
framebuffer_release(info);
return ret;
@@ -1062,11 +1051,10 @@ static void imxfb_remove(struct platform_device *pdev)
fb_dealloc_cmap(&info->cmap);
dma_free_wc(&pdev->dev, fbi->map_size, info->screen_buffer,
fbi->map_dma);
- kfree(info->pseudo_palette);
framebuffer_release(info);
}
-static int __maybe_unused imxfb_suspend(struct device *dev)
+static int imxfb_suspend(struct device *dev)
{
struct fb_info *info = dev_get_drvdata(dev);
struct imxfb_info *fbi = info->par;
@@ -1076,7 +1064,7 @@ static int __maybe_unused imxfb_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused imxfb_resume(struct device *dev)
+static int imxfb_resume(struct device *dev)
{
struct fb_info *info = dev_get_drvdata(dev);
struct imxfb_info *fbi = info->par;
@@ -1086,13 +1074,13 @@ static int __maybe_unused imxfb_resume(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(imxfb_pm_ops, imxfb_suspend, imxfb_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(imxfb_pm_ops, imxfb_suspend, imxfb_resume);
static struct platform_driver imxfb_driver = {
.driver = {
.name = DRIVER_NAME,
.of_match_table = imxfb_of_dev_id,
- .pm = &imxfb_pm_ops,
+ .pm = pm_sleep_ptr(&imxfb_pm_ops),
},
.probe = imxfb_probe,
.remove_new = imxfb_remove,
diff --git a/drivers/video/fbdev/kyro/STG4000InitDevice.c b/drivers/video/fbdev/kyro/STG4000InitDevice.c
index edfa0a04854d..79886a246638 100644
--- a/drivers/video/fbdev/kyro/STG4000InitDevice.c
+++ b/drivers/video/fbdev/kyro/STG4000InitDevice.c
@@ -83,11 +83,11 @@ volatile u32 i,count=0; \
static u32 InitSDRAMRegisters(volatile STG4000REG __iomem *pSTGReg,
u32 dwSubSysID, u32 dwRevID)
{
- u32 adwSDRAMArgCfg0[] = { 0xa0, 0x80, 0xa0, 0xa0, 0xa0 };
- u32 adwSDRAMCfg1[] = { 0x8732, 0x8732, 0xa732, 0xa732, 0x8732 };
- u32 adwSDRAMCfg2[] = { 0x87d2, 0x87d2, 0xa7d2, 0x87d2, 0xa7d2 };
- u32 adwSDRAMRsh[] = { 36, 39, 40 };
- u32 adwChipSpeed[] = { 110, 120, 125 };
+ static const u8 adwSDRAMArgCfg0[] = { 0xa0, 0x80, 0xa0, 0xa0, 0xa0 };
+ static const u16 adwSDRAMCfg1[] = { 0x8732, 0x8732, 0xa732, 0xa732, 0x8732 };
+ static const u16 adwSDRAMCfg2[] = { 0x87d2, 0x87d2, 0xa7d2, 0x87d2, 0xa7d2 };
+ static const u8 adwSDRAMRsh[] = { 36, 39, 40 };
+ static const u8 adwChipSpeed[] = { 110, 120, 125 };
u32 dwMemTypeIdx;
u32 dwChipSpeedIdx;
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/leo.c b/drivers/video/fbdev/leo.c
index 3ffc0a725f89..89ca48235dbe 100644
--- a/drivers/video/fbdev/leo.c
+++ b/drivers/video/fbdev/leo.c
@@ -16,8 +16,9 @@
#include <linux/init.h>
#include <linux/fb.h>
#include <linux/mm.h>
-#include <linux/of_device.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
#include <asm/fbio.h>
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/mb862xx/mb862xxfb_accel.c b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c
index 61aed7fc0b8d..c35a7479fbf2 100644
--- a/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c
+++ b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c
@@ -15,9 +15,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#if defined(CONFIG_OF)
-#include <linux/of_platform.h>
-#endif
+
#include "mb862xxfb.h"
#include "mb862xx_reg.h"
#include "mb862xxfb_accel.h"
diff --git a/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c b/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c
index b5c8fcab9940..9dc347d163cf 100644
--- a/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c
+++ b/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c
@@ -18,11 +18,11 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#if defined(CONFIG_OF)
+#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#endif
+#include <linux/platform_device.h>
+
#include "mb862xxfb.h"
#include "mb862xx_reg.h"
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/mmp/hw/mmp_ctrl.c b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c
index 51fbf02a0343..76b50b6c98ad 100644
--- a/drivers/video/fbdev/mmp/hw/mmp_ctrl.c
+++ b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c
@@ -519,7 +519,9 @@ static int mmphw_probe(struct platform_device *pdev)
"unable to get clk %s\n", mi->clk_name);
goto failed;
}
- clk_prepare_enable(ctrl->clk);
+ ret = clk_prepare_enable(ctrl->clk);
+ if (ret)
+ goto failed;
/* init global regs */
ctrl_set_default(ctrl);
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/omap2/omapfb/displays/panel-dsi-cm.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
index ba94a0a7bd4f..77fce1223a64 100644
--- a/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
+++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
@@ -15,12 +15,12 @@
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/sched/signal.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
-#include <linux/of_device.h>
#include <video/omapfb_dss.h>
#include <video/mipi_display.h>
diff --git a/drivers/video/fbdev/p9100.c b/drivers/video/fbdev/p9100.c
index 0876962c52eb..e2e747cae9b1 100644
--- a/drivers/video/fbdev/p9100.c
+++ b/drivers/video/fbdev/p9100.c
@@ -15,7 +15,8 @@
#include <linux/init.h>
#include <linux/fb.h>
#include <linux/mm.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/fbio.h>
diff --git a/drivers/video/fbdev/platinumfb.c b/drivers/video/fbdev/platinumfb.c
index f8283fcd5edb..b27f43b3616e 100644
--- a/drivers/video/fbdev/platinumfb.c
+++ b/drivers/video/fbdev/platinumfb.c
@@ -30,9 +30,9 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/nvram.h>
+#include <linux/of.h>
#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
+#include <linux/platform_device.h>
#include "macmodes.h"
#include "platinumfb.h"
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/sbuslib.c b/drivers/video/fbdev/sbuslib.c
index 7f79db827b07..21e9fd8e69e2 100644
--- a/drivers/video/fbdev/sbuslib.c
+++ b/drivers/video/fbdev/sbuslib.c
@@ -11,7 +11,7 @@
#include <linux/fb.h>
#include <linux/mm.h>
#include <linux/uaccess.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <asm/fbio.h>
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..46881a691549 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)
@@ -396,8 +399,8 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
/* Enable the PWM */
pwm_enable(par->pwm);
- dev_dbg(&par->client->dev, "Using PWM%d with a %lluns period.\n",
- par->pwm->pwm, pwm_get_period(par->pwm));
+ dev_dbg(&par->client->dev, "Using PWM %s with a %lluns period.\n",
+ par->pwm->label, pwm_get_period(par->pwm));
}
/* Set initial contrast */
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/sunxvr1000.c b/drivers/video/fbdev/sunxvr1000.c
index 490bd9a14763..17d61e1d11a6 100644
--- a/drivers/video/fbdev/sunxvr1000.c
+++ b/drivers/video/fbdev/sunxvr1000.c
@@ -8,7 +8,8 @@
#include <linux/kernel.h>
#include <linux/fb.h>
#include <linux/init.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
struct gfb_info {
struct fb_info *info;
diff --git a/drivers/video/fbdev/sunxvr2500.c b/drivers/video/fbdev/sunxvr2500.c
index 2cab4b9be68a..e64ec7d0caf9 100644
--- a/drivers/video/fbdev/sunxvr2500.c
+++ b/drivers/video/fbdev/sunxvr2500.c
@@ -10,7 +10,7 @@
#include <linux/fb.h>
#include <linux/pci.h>
#include <linux/init.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <asm/io.h>
diff --git a/drivers/video/fbdev/sunxvr500.c b/drivers/video/fbdev/sunxvr500.c
index 6ec358af1256..c4e01e871483 100644
--- a/drivers/video/fbdev/sunxvr500.c
+++ b/drivers/video/fbdev/sunxvr500.c
@@ -10,7 +10,7 @@
#include <linux/fb.h>
#include <linux/pci.h>
#include <linux/init.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <asm/io.h>
diff --git a/drivers/video/fbdev/tcx.c b/drivers/video/fbdev/tcx.c
index fc3ac2301b45..255eb57aefa2 100644
--- a/drivers/video/fbdev/tcx.c
+++ b/drivers/video/fbdev/tcx.c
@@ -17,7 +17,8 @@
#include <linux/init.h>
#include <linux/fb.h>
#include <linux/mm.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/fbio.h>
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/fbdev/xilinxfb.c b/drivers/video/fbdev/xilinxfb.c
index 2aa3a528277f..542baddd54ad 100644
--- a/drivers/video/fbdev/xilinxfb.c
+++ b/drivers/video/fbdev/xilinxfb.c
@@ -24,14 +24,13 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
+#include <linux/platform_device.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-#include <linux/of_address.h>
+#include <linux/of.h>
#include <linux/io.h>
#include <linux/slab.h>
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/virt/acrn/ioreq.c b/drivers/virt/acrn/ioreq.c
index d75ab3f66da4..cecdc1c13af7 100644
--- a/drivers/virt/acrn/ioreq.c
+++ b/drivers/virt/acrn/ioreq.c
@@ -576,8 +576,8 @@ static void ioreq_resume(void)
int acrn_ioreq_intr_setup(void)
{
acrn_setup_intr_handler(ioreq_intr_handler);
- ioreq_wq = alloc_workqueue("ioreq_wq",
- WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+ ioreq_wq = alloc_ordered_workqueue("ioreq_wq",
+ WQ_HIGHPRI | WQ_MEM_RECLAIM);
if (!ioreq_wq) {
dev_err(acrn_dev.this_device, "Failed to alloc workqueue!\n");
acrn_remove_intr_handler();
diff --git a/drivers/virt/coco/sev-guest/Kconfig b/drivers/virt/coco/sev-guest/Kconfig
index f9db0799ae67..da2d7ca531f0 100644
--- a/drivers/virt/coco/sev-guest/Kconfig
+++ b/drivers/virt/coco/sev-guest/Kconfig
@@ -2,6 +2,7 @@ config SEV_GUEST
tristate "AMD SEV Guest driver"
default m
depends on AMD_MEM_ENCRYPT
+ select CRYPTO
select CRYPTO_AEAD2
select CRYPTO_GCM
help
diff --git a/drivers/virtio/virtio_mem.c b/drivers/virtio/virtio_mem.c
index 835f6cc2fb66..fa5226c198cc 100644
--- a/drivers/virtio/virtio_mem.c
+++ b/drivers/virtio/virtio_mem.c
@@ -38,11 +38,6 @@ module_param(bbm_block_size, ulong, 0444);
MODULE_PARM_DESC(bbm_block_size,
"Big Block size in bytes. Default is 0 (auto-detection).");
-static bool bbm_safe_unplug = true;
-module_param(bbm_safe_unplug, bool, 0444);
-MODULE_PARM_DESC(bbm_safe_unplug,
- "Use a safe unplug mechanism in BBM, avoiding long/endless loops");
-
/*
* virtio-mem currently supports the following modes of operation:
*
@@ -173,6 +168,13 @@ struct virtio_mem {
/* The number of subblocks per Linux memory block. */
uint32_t sbs_per_mb;
+ /*
+ * Some of the Linux memory blocks tracked as "partially
+ * plugged" are completely unplugged and can be offlined
+ * and removed -- which previously failed.
+ */
+ bool have_unplugged_mb;
+
/* Summary of all memory block states. */
unsigned long mb_count[VIRTIO_MEM_SBM_MB_COUNT];
@@ -746,11 +748,15 @@ static int virtio_mem_offline_and_remove_memory(struct virtio_mem *vm,
* immediately instead of waiting.
*/
virtio_mem_retry(vm);
- } else {
- dev_dbg(&vm->vdev->dev,
- "offlining and removing memory failed: %d\n", rc);
+ return 0;
}
- return rc;
+ dev_dbg(&vm->vdev->dev, "offlining and removing memory failed: %d\n", rc);
+ /*
+ * We don't really expect this to fail, because we fake-offlined all
+ * memory already. But it could fail in corner cases.
+ */
+ WARN_ON_ONCE(rc != -ENOMEM && rc != -EBUSY);
+ return rc == -ENOMEM ? -ENOMEM : -EBUSY;
}
/*
@@ -767,6 +773,34 @@ static int virtio_mem_sbm_offline_and_remove_mb(struct virtio_mem *vm,
}
/*
+ * Try (offlining and) removing memory from Linux in case all subblocks are
+ * unplugged. Can be called on online and offline memory blocks.
+ *
+ * May modify the state of memory blocks in virtio-mem.
+ */
+static int virtio_mem_sbm_try_remove_unplugged_mb(struct virtio_mem *vm,
+ unsigned long mb_id)
+{
+ int rc;
+
+ /*
+ * Once all subblocks of a memory block were unplugged, offline and
+ * remove it.
+ */
+ if (!virtio_mem_sbm_test_sb_unplugged(vm, mb_id, 0, vm->sbm.sbs_per_mb))
+ return 0;
+
+ /* offline_and_remove_memory() works for online and offline memory. */
+ mutex_unlock(&vm->hotplug_mutex);
+ rc = virtio_mem_sbm_offline_and_remove_mb(vm, mb_id);
+ mutex_lock(&vm->hotplug_mutex);
+ if (!rc)
+ virtio_mem_sbm_set_mb_state(vm, mb_id,
+ VIRTIO_MEM_SBM_MB_UNUSED);
+ return rc;
+}
+
+/*
* See virtio_mem_offline_and_remove_memory(): Try to offline and remove a
* all Linux memory blocks covered by the big block.
*/
@@ -1155,7 +1189,8 @@ static void virtio_mem_fake_online(unsigned long pfn, unsigned long nr_pages)
* Try to allocate a range, marking pages fake-offline, effectively
* fake-offlining them.
*/
-static int virtio_mem_fake_offline(unsigned long pfn, unsigned long nr_pages)
+static int virtio_mem_fake_offline(struct virtio_mem *vm, unsigned long pfn,
+ unsigned long nr_pages)
{
const bool is_movable = is_zone_movable_page(pfn_to_page(pfn));
int rc, retry_count;
@@ -1168,6 +1203,14 @@ static int virtio_mem_fake_offline(unsigned long pfn, unsigned long nr_pages)
* some guarantees.
*/
for (retry_count = 0; retry_count < 5; retry_count++) {
+ /*
+ * If the config changed, stop immediately and go back to the
+ * main loop: avoid trying to keep unplugging if the device
+ * might have decided to not remove any more memory.
+ */
+ if (atomic_read(&vm->config_changed))
+ return -EAGAIN;
+
rc = alloc_contig_range(pfn, pfn + nr_pages, MIGRATE_MOVABLE,
GFP_KERNEL);
if (rc == -ENOMEM)
@@ -1917,7 +1960,7 @@ static int virtio_mem_sbm_unplug_sb_online(struct virtio_mem *vm,
start_pfn = PFN_DOWN(virtio_mem_mb_id_to_phys(mb_id) +
sb_id * vm->sbm.sb_size);
- rc = virtio_mem_fake_offline(start_pfn, nr_pages);
+ rc = virtio_mem_fake_offline(vm, start_pfn, nr_pages);
if (rc)
return rc;
@@ -1989,20 +2032,10 @@ static int virtio_mem_sbm_unplug_any_sb_online(struct virtio_mem *vm,
}
unplugged:
- /*
- * Once all subblocks of a memory block were unplugged, offline and
- * remove it. This will usually not fail, as no memory is in use
- * anymore - however some other notifiers might NACK the request.
- */
- if (virtio_mem_sbm_test_sb_unplugged(vm, mb_id, 0, vm->sbm.sbs_per_mb)) {
- mutex_unlock(&vm->hotplug_mutex);
- rc = virtio_mem_sbm_offline_and_remove_mb(vm, mb_id);
- mutex_lock(&vm->hotplug_mutex);
- if (!rc)
- virtio_mem_sbm_set_mb_state(vm, mb_id,
- VIRTIO_MEM_SBM_MB_UNUSED);
- }
-
+ rc = virtio_mem_sbm_try_remove_unplugged_mb(vm, mb_id);
+ if (rc)
+ vm->sbm.have_unplugged_mb = 1;
+ /* Ignore errors, this is not critical. We'll retry later. */
return 0;
}
@@ -2111,38 +2144,32 @@ static int virtio_mem_bbm_offline_remove_and_unplug_bb(struct virtio_mem *vm,
VIRTIO_MEM_BBM_BB_ADDED))
return -EINVAL;
- if (bbm_safe_unplug) {
- /*
- * Start by fake-offlining all memory. Once we marked the device
- * block as fake-offline, all newly onlined memory will
- * automatically be kept fake-offline. Protect from concurrent
- * onlining/offlining until we have a consistent state.
- */
- mutex_lock(&vm->hotplug_mutex);
- virtio_mem_bbm_set_bb_state(vm, bb_id,
- VIRTIO_MEM_BBM_BB_FAKE_OFFLINE);
+ /*
+ * Start by fake-offlining all memory. Once we marked the device
+ * block as fake-offline, all newly onlined memory will
+ * automatically be kept fake-offline. Protect from concurrent
+ * onlining/offlining until we have a consistent state.
+ */
+ mutex_lock(&vm->hotplug_mutex);
+ virtio_mem_bbm_set_bb_state(vm, bb_id, VIRTIO_MEM_BBM_BB_FAKE_OFFLINE);
- for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
- page = pfn_to_online_page(pfn);
- if (!page)
- continue;
+ for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+ page = pfn_to_online_page(pfn);
+ if (!page)
+ continue;
- rc = virtio_mem_fake_offline(pfn, PAGES_PER_SECTION);
- if (rc) {
- end_pfn = pfn;
- goto rollback_safe_unplug;
- }
+ rc = virtio_mem_fake_offline(vm, pfn, PAGES_PER_SECTION);
+ if (rc) {
+ end_pfn = pfn;
+ goto rollback;
}
- mutex_unlock(&vm->hotplug_mutex);
}
+ mutex_unlock(&vm->hotplug_mutex);
rc = virtio_mem_bbm_offline_and_remove_bb(vm, bb_id);
if (rc) {
- if (bbm_safe_unplug) {
- mutex_lock(&vm->hotplug_mutex);
- goto rollback_safe_unplug;
- }
- return rc;
+ mutex_lock(&vm->hotplug_mutex);
+ goto rollback;
}
rc = virtio_mem_bbm_unplug_bb(vm, bb_id);
@@ -2154,7 +2181,7 @@ static int virtio_mem_bbm_offline_remove_and_unplug_bb(struct virtio_mem *vm,
VIRTIO_MEM_BBM_BB_UNUSED);
return rc;
-rollback_safe_unplug:
+rollback:
for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
page = pfn_to_online_page(pfn);
if (!page)
@@ -2260,12 +2287,13 @@ static int virtio_mem_unplug_request(struct virtio_mem *vm, uint64_t diff)
/*
* Try to unplug all blocks that couldn't be unplugged before, for example,
- * because the hypervisor was busy.
+ * because the hypervisor was busy. Further, offline and remove any memory
+ * blocks where we previously failed.
*/
-static int virtio_mem_unplug_pending_mb(struct virtio_mem *vm)
+static int virtio_mem_cleanup_pending_mb(struct virtio_mem *vm)
{
unsigned long id;
- int rc;
+ int rc = 0;
if (!vm->in_sbm) {
virtio_mem_bbm_for_each_bb(vm, id,
@@ -2287,6 +2315,27 @@ static int virtio_mem_unplug_pending_mb(struct virtio_mem *vm)
VIRTIO_MEM_SBM_MB_UNUSED);
}
+ if (!vm->sbm.have_unplugged_mb)
+ return 0;
+
+ /*
+ * Let's retry (offlining and) removing completely unplugged Linux
+ * memory blocks.
+ */
+ vm->sbm.have_unplugged_mb = false;
+
+ mutex_lock(&vm->hotplug_mutex);
+ virtio_mem_sbm_for_each_mb(vm, id, VIRTIO_MEM_SBM_MB_MOVABLE_PARTIAL)
+ rc |= virtio_mem_sbm_try_remove_unplugged_mb(vm, id);
+ virtio_mem_sbm_for_each_mb(vm, id, VIRTIO_MEM_SBM_MB_KERNEL_PARTIAL)
+ rc |= virtio_mem_sbm_try_remove_unplugged_mb(vm, id);
+ virtio_mem_sbm_for_each_mb(vm, id, VIRTIO_MEM_SBM_MB_OFFLINE_PARTIAL)
+ rc |= virtio_mem_sbm_try_remove_unplugged_mb(vm, id);
+ mutex_unlock(&vm->hotplug_mutex);
+
+ if (rc)
+ vm->sbm.have_unplugged_mb = true;
+ /* Ignore errors, this is not critical. We'll retry later. */
return 0;
}
@@ -2368,9 +2417,9 @@ retry:
virtio_mem_refresh_config(vm);
}
- /* Unplug any leftovers from previous runs */
+ /* Cleanup any leftovers from previous runs */
if (!rc)
- rc = virtio_mem_unplug_pending_mb(vm);
+ rc = virtio_mem_cleanup_pending_mb(vm);
if (!rc && vm->requested_size != vm->plugged_size) {
if (vm->requested_size > vm->plugged_size) {
@@ -2382,6 +2431,13 @@ retry:
}
}
+ /*
+ * Keep retrying to offline and remove completely unplugged Linux
+ * memory blocks.
+ */
+ if (!rc && vm->in_sbm && vm->sbm.have_unplugged_mb)
+ rc = -EBUSY;
+
switch (rc) {
case 0:
vm->retry_timer_ms = VIRTIO_MEM_RETRY_TIMER_MIN_MS;
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index a46a4a29e929..97760f611295 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -607,9 +607,8 @@ static void virtio_mmio_release_dev(struct device *_d)
struct virtio_device *vdev =
container_of(_d, struct virtio_device, dev);
struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
- struct platform_device *pdev = vm_dev->pdev;
- devm_kfree(&pdev->dev, vm_dev);
+ kfree(vm_dev);
}
/* Platform device */
@@ -620,7 +619,7 @@ static int virtio_mmio_probe(struct platform_device *pdev)
unsigned long magic;
int rc;
- vm_dev = devm_kzalloc(&pdev->dev, sizeof(*vm_dev), GFP_KERNEL);
+ vm_dev = kzalloc(sizeof(*vm_dev), GFP_KERNEL);
if (!vm_dev)
return -ENOMEM;
diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index a6c86f916dbd..c2524a7207cf 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -557,8 +557,6 @@ static int virtio_pci_probe(struct pci_dev *pci_dev,
pci_set_master(pci_dev);
- vp_dev->is_legacy = vp_dev->ldev.ioaddr ? true : false;
-
rc = register_virtio_device(&vp_dev->vdev);
reg_dev = vp_dev;
if (rc)
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_legacy.c b/drivers/virtio/virtio_pci_legacy.c
index 2257f1b3d8ae..d9cbb02b35a1 100644
--- a/drivers/virtio/virtio_pci_legacy.c
+++ b/drivers/virtio/virtio_pci_legacy.c
@@ -223,6 +223,7 @@ int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev)
vp_dev->config_vector = vp_config_vector;
vp_dev->setup_vq = setup_vq;
vp_dev->del_vq = del_vq;
+ vp_dev->is_legacy = true;
return 0;
}
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..961161da5900 100644
--- a/drivers/virtio/virtio_vdpa.c
+++ b/drivers/virtio/virtio_vdpa.c
@@ -385,17 +385,21 @@ 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;
cb.private = vd_dev;
ops->set_config_cb(vdpa, &cb);
+ kfree(masks);
return 0;
err_setup_vq:
virtio_vdpa_del_vqs(vdev);
+ kfree(masks);
return err;
}
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();
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index f22138709bf5..ee97d89dfc11 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -304,6 +304,24 @@ config XILINX_WATCHDOG
To compile this driver as a module, choose M here: the
module will be called of_xilinx_wdt.
+config XILINX_WINDOW_WATCHDOG
+ tristate "Xilinx window watchdog timer"
+ depends on HAS_IOMEM
+ depends on ARM64
+ select WATCHDOG_CORE
+ help
+ Window watchdog driver for the versal_wwdt IP core.
+ Window watchdog timer(WWDT) contains closed(first) and
+ open(second) window with 32 bit width. Write to the watchdog
+ timer within predefined window periods of time. This means
+ a period that is not too soon and a period that is not too
+ late. The WWDT has to be restarted within the open window time.
+ If software tries to restart WWDT outside of the open window
+ time period, it generates a reset.
+
+ To compile this driver as a module, choose M here: the
+ module will be called xilinx_wwdt.
+
config ZIIRAVE_WATCHDOG
tristate "Zodiac RAVE Watchdog Timer"
depends on I2C
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index b4c4ccf2d703..3633f5b98236 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -157,6 +157,7 @@ obj-$(CONFIG_M54xx_WATCHDOG) += m54xx_wdt.o
# MicroBlaze Architecture
obj-$(CONFIG_XILINX_WATCHDOG) += of_xilinx_wdt.o
+obj-$(CONFIG_XILINX_WINDOW_WATCHDOG) += xilinx_wwdt.o
# MIPS Architecture
obj-$(CONFIG_ATH79_WDT) += ath79_wdt.o
diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c
index 38e26f160b9a..59dfd7f6bf0b 100644
--- a/drivers/watchdog/ep93xx_wdt.c
+++ b/drivers/watchdog/ep93xx_wdt.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Watchdog driver for Cirrus Logic EP93xx family of devices.
*
@@ -11,10 +12,6 @@
* Copyright (c) 2012 H Hartley Sweeten <hsweeten@visionengravers.com>
* Convert to a platform device and use the watchdog framework API
*
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- *
* This watchdog fires after 250msec, which is a too short interval
* for us to rely on the user space daemon alone. So we ping the
* wdt each ~200msec and eventually stop doing it if the user space
diff --git a/drivers/watchdog/ibmasr.c b/drivers/watchdog/ibmasr.c
index 4a22fe152086..6955c693b5fd 100644
--- a/drivers/watchdog/ibmasr.c
+++ b/drivers/watchdog/ibmasr.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-1.0+
/*
* IBM Automatic Server Restart driver.
*
@@ -6,8 +7,6 @@
* Based on driver written by Pete Reynolds.
* Copyright (c) IBM Corporation, 1998-2004.
*
- * This software may be used and distributed according to the terms
- * of the GNU Public License, incorporated herein by reference.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/watchdog/loongson1_wdt.c b/drivers/watchdog/loongson1_wdt.c
index 3c651c50a98c..4ac7810a314d 100644
--- a/drivers/watchdog/loongson1_wdt.c
+++ b/drivers/watchdog/loongson1_wdt.c
@@ -5,6 +5,7 @@
#include <linux/clk.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/watchdog.h>
@@ -112,7 +113,7 @@ static int ls1x_wdt_probe(struct platform_device *pdev)
if (IS_ERR(drvdata->base))
return PTR_ERR(drvdata->base);
- drvdata->clk = devm_clk_get_enabled(dev, pdev->name);
+ drvdata->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(drvdata->clk))
return PTR_ERR(drvdata->clk);
@@ -144,10 +145,20 @@ static int ls1x_wdt_probe(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id ls1x_wdt_dt_ids[] = {
+ { .compatible = "loongson,ls1b-wdt", },
+ { .compatible = "loongson,ls1c-wdt", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ls1x_wdt_dt_ids);
+#endif
+
static struct platform_driver ls1x_wdt_driver = {
.probe = ls1x_wdt_probe,
.driver = {
.name = "ls1x-wdt",
+ .of_match_table = of_match_ptr(ls1x_wdt_dt_ids),
},
};
diff --git a/drivers/watchdog/m54xx_wdt.c b/drivers/watchdog/m54xx_wdt.c
index f388a769dbd3..062ea3e6497e 100644
--- a/drivers/watchdog/m54xx_wdt.c
+++ b/drivers/watchdog/m54xx_wdt.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* drivers/watchdog/m54xx_wdt.c
*
@@ -11,9 +12,6 @@
* Copyright 2004 (c) MontaVista, Software, Inc.
* Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
*
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c
index 9e1541cfae0d..21935f9620e4 100644
--- a/drivers/watchdog/max63xx_wdt.c
+++ b/drivers/watchdog/max63xx_wdt.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* drivers/char/watchdog/max63xx_wdt.c
*
@@ -5,10 +6,6 @@
*
* Copyright (C) 2009 Marc Zyngier <maz@misterjones.org>
*
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- *
* This driver assumes the watchdog pins are memory mapped (as it is
* the case for the Arcom Zeus). Should it be connected over GPIOs or
* another interface, some abstraction will have to be introduced.
diff --git a/drivers/watchdog/moxart_wdt.c b/drivers/watchdog/moxart_wdt.c
index 6340a1f5f471..b7b1da3c932d 100644
--- a/drivers/watchdog/moxart_wdt.c
+++ b/drivers/watchdog/moxart_wdt.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* MOXA ART SoCs watchdog driver.
*
@@ -5,9 +6,6 @@
*
* Jonas Jensen <jonas.jensen@gmail.com>
*
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
*/
#include <linux/clk.h>
diff --git a/drivers/watchdog/octeon-wdt-nmi.S b/drivers/watchdog/octeon-wdt-nmi.S
index 97f6eb7b5a8e..e308cc743920 100644
--- a/drivers/watchdog/octeon-wdt-nmi.S
+++ b/drivers/watchdog/octeon-wdt-nmi.S
@@ -1,8 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
* Copyright (C) 2007-2017 Cavium, Inc.
*/
#include <asm/asm.h>
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index 5ec2dd8fd5fa..1fe583e8a95b 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* drivers/watchdog/orion_wdt.c
*
@@ -5,9 +6,6 @@
*
* Author: Sylver Bruneau <sylver.bruneau@googlemail.com>
*
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/watchdog/rtd119x_wdt.c b/drivers/watchdog/rtd119x_wdt.c
index 95c8d7abce42..984905695dde 100644
--- a/drivers/watchdog/rtd119x_wdt.c
+++ b/drivers/watchdog/rtd119x_wdt.c
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Realtek RTD129x watchdog
*
* Copyright (c) 2017 Andreas Färber
*
- * SPDX-License-Identifier: GPL-2.0+
*/
#include <linux/bitops.h>
diff --git a/drivers/watchdog/sbc_fitpc2_wdt.c b/drivers/watchdog/sbc_fitpc2_wdt.c
index 13db71e16583..b8eb8d5ca1af 100644
--- a/drivers/watchdog/sbc_fitpc2_wdt.c
+++ b/drivers/watchdog/sbc_fitpc2_wdt.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Watchdog driver for SBC-FITPC2 board
*
@@ -5,9 +6,6 @@
*
* Adapted from the IXP2000 watchdog driver by Deepak Saxena.
*
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
*/
#define pr_fmt(fmt) KBUILD_MODNAME " WATCHDOG: " fmt
diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c
index 14f8d8d90920..2bd3dc25cb03 100644
--- a/drivers/watchdog/sp5100_tco.c
+++ b/drivers/watchdog/sp5100_tco.c
@@ -96,7 +96,7 @@ static enum tco_reg_layout tco_reg_layout(struct pci_dev *dev)
sp5100_tco_pci->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS &&
sp5100_tco_pci->revision >= AMD_ZEN_SMBUS_PCI_REV) {
return efch_mmio;
- } else if (dev->vendor == PCI_VENDOR_ID_AMD &&
+ } else if ((dev->vendor == PCI_VENDOR_ID_AMD || dev->vendor == PCI_VENDOR_ID_HYGON) &&
((dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS &&
dev->revision >= 0x41) ||
(dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS &&
@@ -579,6 +579,8 @@ static const struct pci_device_id sp5100_tco_pci_tbl[] = {
PCI_ANY_ID, },
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_KERNCZ_SMBUS, PCI_ANY_ID,
PCI_ANY_ID, },
+ { PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_KERNCZ_SMBUS, PCI_ANY_ID,
+ PCI_ANY_ID, },
{ 0, }, /* End of list */
};
MODULE_DEVICE_TABLE(pci, sp5100_tco_pci_tbl);
diff --git a/drivers/watchdog/ts4800_wdt.c b/drivers/watchdog/ts4800_wdt.c
index 0ea554c7cda5..0099403f4992 100644
--- a/drivers/watchdog/ts4800_wdt.c
+++ b/drivers/watchdog/ts4800_wdt.c
@@ -1,11 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Watchdog driver for TS-4800 based boards
*
* Copyright (c) 2015 - Savoir-faire Linux
*
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
*/
#include <linux/kernel.h>
diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c
index bf918f5fa131..3d57670befe1 100644
--- a/drivers/watchdog/ts72xx_wdt.c
+++ b/drivers/watchdog/ts72xx_wdt.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Watchdog driver for Technologic Systems TS-72xx based SBCs
* (TS-7200, TS-7250 and TS-7260). These boards have external
@@ -8,9 +9,6 @@
*
* This driver is based on ep93xx_wdt and wm831x_wdt drivers.
*
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
*/
#include <linux/platform_device.h>
diff --git a/drivers/watchdog/xilinx_wwdt.c b/drivers/watchdog/xilinx_wwdt.c
new file mode 100644
index 000000000000..2585038d5575
--- /dev/null
+++ b/drivers/watchdog/xilinx_wwdt.c
@@ -0,0 +1,201 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Window watchdog device driver for Xilinx Versal WWDT
+ *
+ * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/watchdog.h>
+
+/* Max timeout is calculated at 100MHz source clock */
+#define XWWDT_DEFAULT_TIMEOUT 42
+#define XWWDT_MIN_TIMEOUT 1
+
+/* Register offsets for the WWDT device */
+#define XWWDT_MWR_OFFSET 0x00
+#define XWWDT_ESR_OFFSET 0x04
+#define XWWDT_FCR_OFFSET 0x08
+#define XWWDT_FWR_OFFSET 0x0c
+#define XWWDT_SWR_OFFSET 0x10
+
+/* Master Write Control Register Masks */
+#define XWWDT_MWR_MASK BIT(0)
+
+/* Enable and Status Register Masks */
+#define XWWDT_ESR_WINT_MASK BIT(16)
+#define XWWDT_ESR_WSW_MASK BIT(8)
+#define XWWDT_ESR_WEN_MASK BIT(0)
+
+#define XWWDT_CLOSE_WINDOW_PERCENT 50
+
+static int wwdt_timeout;
+static int closed_window_percent;
+
+module_param(wwdt_timeout, int, 0);
+MODULE_PARM_DESC(wwdt_timeout,
+ "Watchdog time in seconds. (default="
+ __MODULE_STRING(XWWDT_DEFAULT_TIMEOUT) ")");
+module_param(closed_window_percent, int, 0);
+MODULE_PARM_DESC(closed_window_percent,
+ "Watchdog closed window percentage. (default="
+ __MODULE_STRING(XWWDT_CLOSE_WINDOW_PERCENT) ")");
+/**
+ * struct xwwdt_device - Watchdog device structure
+ * @base: base io address of WDT device
+ * @spinlock: spinlock for IO register access
+ * @xilinx_wwdt_wdd: watchdog device structure
+ * @freq: source clock frequency of WWDT
+ * @close_percent: Closed window percent
+ */
+struct xwwdt_device {
+ void __iomem *base;
+ spinlock_t spinlock; /* spinlock for register handling */
+ struct watchdog_device xilinx_wwdt_wdd;
+ unsigned long freq;
+ u32 close_percent;
+};
+
+static int xilinx_wwdt_start(struct watchdog_device *wdd)
+{
+ struct xwwdt_device *xdev = watchdog_get_drvdata(wdd);
+ struct watchdog_device *xilinx_wwdt_wdd = &xdev->xilinx_wwdt_wdd;
+ u64 time_out, closed_timeout, open_timeout;
+ u32 control_status_reg;
+
+ /* Calculate timeout count */
+ time_out = xdev->freq * wdd->timeout;
+ closed_timeout = (time_out * xdev->close_percent) / 100;
+ open_timeout = time_out - closed_timeout;
+ wdd->min_hw_heartbeat_ms = xdev->close_percent * 10 * wdd->timeout;
+
+ spin_lock(&xdev->spinlock);
+
+ iowrite32(XWWDT_MWR_MASK, xdev->base + XWWDT_MWR_OFFSET);
+ iowrite32(~(u32)XWWDT_ESR_WEN_MASK, xdev->base + XWWDT_ESR_OFFSET);
+ iowrite32((u32)closed_timeout, xdev->base + XWWDT_FWR_OFFSET);
+ iowrite32((u32)open_timeout, xdev->base + XWWDT_SWR_OFFSET);
+
+ /* Enable the window watchdog timer */
+ control_status_reg = ioread32(xdev->base + XWWDT_ESR_OFFSET);
+ control_status_reg |= XWWDT_ESR_WEN_MASK;
+ iowrite32(control_status_reg, xdev->base + XWWDT_ESR_OFFSET);
+
+ spin_unlock(&xdev->spinlock);
+
+ dev_dbg(xilinx_wwdt_wdd->parent, "Watchdog Started!\n");
+
+ return 0;
+}
+
+static int xilinx_wwdt_keepalive(struct watchdog_device *wdd)
+{
+ struct xwwdt_device *xdev = watchdog_get_drvdata(wdd);
+ u32 control_status_reg;
+
+ spin_lock(&xdev->spinlock);
+
+ /* Enable write access control bit for the window watchdog */
+ iowrite32(XWWDT_MWR_MASK, xdev->base + XWWDT_MWR_OFFSET);
+
+ /* Trigger restart kick to watchdog */
+ control_status_reg = ioread32(xdev->base + XWWDT_ESR_OFFSET);
+ control_status_reg |= XWWDT_ESR_WSW_MASK;
+ iowrite32(control_status_reg, xdev->base + XWWDT_ESR_OFFSET);
+
+ spin_unlock(&xdev->spinlock);
+
+ return 0;
+}
+
+static const struct watchdog_info xilinx_wwdt_ident = {
+ .options = WDIOF_KEEPALIVEPING |
+ WDIOF_SETTIMEOUT,
+ .firmware_version = 1,
+ .identity = "xlnx_window watchdog",
+};
+
+static const struct watchdog_ops xilinx_wwdt_ops = {
+ .owner = THIS_MODULE,
+ .start = xilinx_wwdt_start,
+ .ping = xilinx_wwdt_keepalive,
+};
+
+static int xwwdt_probe(struct platform_device *pdev)
+{
+ struct watchdog_device *xilinx_wwdt_wdd;
+ struct device *dev = &pdev->dev;
+ struct xwwdt_device *xdev;
+ struct clk *clk;
+ int ret;
+
+ xdev = devm_kzalloc(dev, sizeof(*xdev), GFP_KERNEL);
+ if (!xdev)
+ return -ENOMEM;
+
+ xilinx_wwdt_wdd = &xdev->xilinx_wwdt_wdd;
+ xilinx_wwdt_wdd->info = &xilinx_wwdt_ident;
+ xilinx_wwdt_wdd->ops = &xilinx_wwdt_ops;
+ xilinx_wwdt_wdd->parent = dev;
+
+ xdev->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(xdev->base))
+ return PTR_ERR(xdev->base);
+
+ clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ xdev->freq = clk_get_rate(clk);
+ if (!xdev->freq)
+ return -EINVAL;
+
+ xilinx_wwdt_wdd->min_timeout = XWWDT_MIN_TIMEOUT;
+ xilinx_wwdt_wdd->timeout = XWWDT_DEFAULT_TIMEOUT;
+ xilinx_wwdt_wdd->max_hw_heartbeat_ms = 1000 * xilinx_wwdt_wdd->timeout;
+
+ if (closed_window_percent == 0 || closed_window_percent >= 100)
+ xdev->close_percent = XWWDT_CLOSE_WINDOW_PERCENT;
+ else
+ xdev->close_percent = closed_window_percent;
+
+ watchdog_init_timeout(xilinx_wwdt_wdd, wwdt_timeout, &pdev->dev);
+ spin_lock_init(&xdev->spinlock);
+ watchdog_set_drvdata(xilinx_wwdt_wdd, xdev);
+ watchdog_set_nowayout(xilinx_wwdt_wdd, 1);
+
+ ret = devm_watchdog_register_device(dev, xilinx_wwdt_wdd);
+ if (ret)
+ return ret;
+
+ dev_info(dev, "Xilinx window watchdog Timer with timeout %ds\n",
+ xilinx_wwdt_wdd->timeout);
+
+ return 0;
+}
+
+static const struct of_device_id xwwdt_of_match[] = {
+ { .compatible = "xlnx,versal-wwdt", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, xwwdt_of_match);
+
+static struct platform_driver xwwdt_driver = {
+ .probe = xwwdt_probe,
+ .driver = {
+ .name = "Xilinx window watchdog",
+ .of_match_table = xwwdt_of_match,
+ },
+};
+
+module_platform_driver(xwwdt_driver);
+
+MODULE_AUTHOR("Neeli Srinivas <srinivas.neeli@amd.com>");
+MODULE_DESCRIPTION("Xilinx window watchdog driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/ziirave_wdt.c b/drivers/watchdog/ziirave_wdt.c
index 21ca08a694ee..5ed33df68e9a 100644
--- a/drivers/watchdog/ziirave_wdt.c
+++ b/drivers/watchdog/ziirave_wdt.c
@@ -731,7 +731,7 @@ static struct i2c_driver ziirave_wdt_driver = {
.name = "ziirave_wdt",
.of_match_table = zrv_wdt_of_match,
},
- .probe_new = ziirave_wdt_probe,
+ .probe = ziirave_wdt_probe,
.remove = ziirave_wdt_remove,
.id_table = ziirave_wdt_id,
};
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index c7715f8bd452..3bdd5b59661d 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -112,6 +112,7 @@ struct irq_info {
unsigned int irq_epoch; /* If eoi_cpu valid: irq_epoch of event */
u64 eoi_time; /* Time in jiffies when to EOI. */
raw_spinlock_t lock;
+ bool is_static; /* Is event channel static */
union {
unsigned short virq;
@@ -815,15 +816,6 @@ static void xen_free_irq(unsigned irq)
irq_free_desc(irq);
}
-static void xen_evtchn_close(evtchn_port_t port)
-{
- struct evtchn_close close;
-
- close.port = port;
- if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
- BUG();
-}
-
/* Not called for lateeoi events. */
static void event_handler_exit(struct irq_info *info)
{
@@ -982,7 +974,8 @@ static void __unbind_from_irq(unsigned int irq)
unsigned int cpu = cpu_from_irq(irq);
struct xenbus_device *dev;
- xen_evtchn_close(evtchn);
+ if (!info->is_static)
+ xen_evtchn_close(evtchn);
switch (type_from_irq(irq)) {
case IRQT_VIRQ:
@@ -1574,7 +1567,7 @@ int xen_set_irq_priority(unsigned irq, unsigned priority)
}
EXPORT_SYMBOL_GPL(xen_set_irq_priority);
-int evtchn_make_refcounted(evtchn_port_t evtchn)
+int evtchn_make_refcounted(evtchn_port_t evtchn, bool is_static)
{
int irq = get_evtchn_to_irq(evtchn);
struct irq_info *info;
@@ -1590,6 +1583,7 @@ int evtchn_make_refcounted(evtchn_port_t evtchn)
WARN_ON(info->refcnt != -1);
info->refcnt = 1;
+ info->is_static = is_static;
return 0;
}
diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c
index c99415a70051..9139a7364df5 100644
--- a/drivers/xen/evtchn.c
+++ b/drivers/xen/evtchn.c
@@ -366,10 +366,10 @@ static int evtchn_resize_ring(struct per_user_data *u)
return 0;
}
-static int evtchn_bind_to_user(struct per_user_data *u, evtchn_port_t port)
+static int evtchn_bind_to_user(struct per_user_data *u, evtchn_port_t port,
+ bool is_static)
{
struct user_evtchn *evtchn;
- struct evtchn_close close;
int rc = 0;
/*
@@ -402,14 +402,14 @@ static int evtchn_bind_to_user(struct per_user_data *u, evtchn_port_t port)
if (rc < 0)
goto err;
- rc = evtchn_make_refcounted(port);
+ rc = evtchn_make_refcounted(port, is_static);
return rc;
err:
/* bind failed, should close the port now */
- close.port = port;
- if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
- BUG();
+ if (!is_static)
+ xen_evtchn_close(port);
+
del_evtchn(u, evtchn);
return rc;
}
@@ -456,7 +456,7 @@ static long evtchn_ioctl(struct file *file,
if (rc != 0)
break;
- rc = evtchn_bind_to_user(u, bind_virq.port);
+ rc = evtchn_bind_to_user(u, bind_virq.port, false);
if (rc == 0)
rc = bind_virq.port;
break;
@@ -482,7 +482,7 @@ static long evtchn_ioctl(struct file *file,
if (rc != 0)
break;
- rc = evtchn_bind_to_user(u, bind_interdomain.local_port);
+ rc = evtchn_bind_to_user(u, bind_interdomain.local_port, false);
if (rc == 0)
rc = bind_interdomain.local_port;
break;
@@ -507,7 +507,7 @@ static long evtchn_ioctl(struct file *file,
if (rc != 0)
break;
- rc = evtchn_bind_to_user(u, alloc_unbound.port);
+ rc = evtchn_bind_to_user(u, alloc_unbound.port, false);
if (rc == 0)
rc = alloc_unbound.port;
break;
@@ -536,6 +536,23 @@ static long evtchn_ioctl(struct file *file,
break;
}
+ case IOCTL_EVTCHN_BIND_STATIC: {
+ struct ioctl_evtchn_bind bind;
+ struct user_evtchn *evtchn;
+
+ rc = -EFAULT;
+ if (copy_from_user(&bind, uarg, sizeof(bind)))
+ break;
+
+ rc = -EISCONN;
+ evtchn = find_evtchn(u, bind.port);
+ if (evtchn)
+ break;
+
+ rc = evtchn_bind_to_user(u, bind.port, true);
+ break;
+ }
+
case IOCTL_EVTCHN_NOTIFY: {
struct ioctl_evtchn_notify notify;
struct user_evtchn *evtchn;
diff --git a/drivers/xen/grant-dma-ops.c b/drivers/xen/grant-dma-ops.c
index 9784a77fa3c9..76f6f26265a3 100644
--- a/drivers/xen/grant-dma-ops.c
+++ b/drivers/xen/grant-dma-ops.c
@@ -303,6 +303,8 @@ static struct device_node *xen_dt_get_node(struct device *dev)
while (!pci_is_root_bus(bus))
bus = bus->parent;
+ if (!bus->bridge->parent)
+ return NULL;
return of_node_get(bus->bridge->parent->of_node);
}
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index e1ec725c2819..f13c3b76ad1e 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -498,14 +498,21 @@ static LIST_HEAD(deferred_list);
static void gnttab_handle_deferred(struct timer_list *);
static DEFINE_TIMER(deferred_timer, gnttab_handle_deferred);
+static atomic64_t deferred_count;
+static atomic64_t leaked_count;
+static unsigned int free_per_iteration = 10;
+module_param(free_per_iteration, uint, 0600);
+
static void gnttab_handle_deferred(struct timer_list *unused)
{
- unsigned int nr = 10;
+ unsigned int nr = READ_ONCE(free_per_iteration);
+ const bool ignore_limit = nr == 0;
struct deferred_entry *first = NULL;
unsigned long flags;
+ size_t freed = 0;
spin_lock_irqsave(&gnttab_list_lock, flags);
- while (nr--) {
+ while ((ignore_limit || nr--) && !list_empty(&deferred_list)) {
struct deferred_entry *entry
= list_first_entry(&deferred_list,
struct deferred_entry, list);
@@ -515,10 +522,14 @@ static void gnttab_handle_deferred(struct timer_list *unused)
list_del(&entry->list);
spin_unlock_irqrestore(&gnttab_list_lock, flags);
if (_gnttab_end_foreign_access_ref(entry->ref)) {
+ uint64_t ret = atomic64_dec_return(&deferred_count);
+
put_free_entry(entry->ref);
- pr_debug("freeing g.e. %#x (pfn %#lx)\n",
- entry->ref, page_to_pfn(entry->page));
+ pr_debug("freeing g.e. %#x (pfn %#lx), %llu remaining\n",
+ entry->ref, page_to_pfn(entry->page),
+ (unsigned long long)ret);
put_page(entry->page);
+ freed++;
kfree(entry);
entry = NULL;
} else {
@@ -530,21 +541,22 @@ static void gnttab_handle_deferred(struct timer_list *unused)
spin_lock_irqsave(&gnttab_list_lock, flags);
if (entry)
list_add_tail(&entry->list, &deferred_list);
- else if (list_empty(&deferred_list))
- break;
}
- if (!list_empty(&deferred_list) && !timer_pending(&deferred_timer)) {
+ if (list_empty(&deferred_list))
+ WARN_ON(atomic64_read(&deferred_count));
+ else if (!timer_pending(&deferred_timer)) {
deferred_timer.expires = jiffies + HZ;
add_timer(&deferred_timer);
}
spin_unlock_irqrestore(&gnttab_list_lock, flags);
+ pr_debug("Freed %zu references", freed);
}
static void gnttab_add_deferred(grant_ref_t ref, struct page *page)
{
struct deferred_entry *entry;
gfp_t gfp = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
- const char *what = KERN_WARNING "leaking";
+ uint64_t leaked, deferred;
entry = kmalloc(sizeof(*entry), gfp);
if (!page) {
@@ -567,10 +579,16 @@ static void gnttab_add_deferred(grant_ref_t ref, struct page *page)
add_timer(&deferred_timer);
}
spin_unlock_irqrestore(&gnttab_list_lock, flags);
- what = KERN_DEBUG "deferring";
+ deferred = atomic64_inc_return(&deferred_count);
+ leaked = atomic64_read(&leaked_count);
+ pr_debug("deferring g.e. %#x (pfn %#lx) (total deferred %llu, total leaked %llu)\n",
+ ref, page ? page_to_pfn(page) : -1, deferred, leaked);
+ } else {
+ deferred = atomic64_read(&deferred_count);
+ leaked = atomic64_inc_return(&leaked_count);
+ pr_warn("leaking g.e. %#x (pfn %#lx) (total deferred %llu, total leaked %llu)\n",
+ ref, page ? page_to_pfn(page) : -1, deferred, leaked);
}
- printk("%s g.e. %#x (pfn %#lx)\n",
- what, ref, page ? page_to_pfn(page) : -1);
}
int gnttab_try_end_foreign_access(grant_ref_t ref)
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index e2f580e30a86..f447cd37cc4c 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -949,7 +949,7 @@ static int privcmd_mmap(struct file *file, struct vm_area_struct *vma)
*/
static int is_mapped_fn(pte_t *pte, unsigned long addr, void *data)
{
- return pte_none(*pte) ? 0 : -EBUSY;
+ return pte_none(ptep_get(pte)) ? 0 : -EBUSY;
}
static int privcmd_vma_range_is_mapped(
diff --git a/drivers/xen/pvcalls-back.c b/drivers/xen/pvcalls-back.c
index 7beaf2c41fbb..d52593466a79 100644
--- a/drivers/xen/pvcalls-back.c
+++ b/drivers/xen/pvcalls-back.c
@@ -363,7 +363,7 @@ static struct sock_mapping *pvcalls_new_active_socket(
map->data.in = map->bytes;
map->data.out = map->bytes + XEN_FLEX_RING_SIZE(map->ring_order);
- map->ioworker.wq = alloc_workqueue("pvcalls_io", WQ_UNBOUND, 1);
+ map->ioworker.wq = alloc_ordered_workqueue("pvcalls_io", 0);
if (!map->ioworker.wq)
goto out;
atomic_set(&map->io, 1);
@@ -636,7 +636,7 @@ static int pvcalls_back_bind(struct xenbus_device *dev,
INIT_WORK(&map->register_work, __pvcalls_back_accept);
spin_lock_init(&map->copy_lock);
- map->wq = alloc_workqueue("pvcalls_wq", WQ_UNBOUND, 1);
+ map->wq = alloc_ordered_workqueue("pvcalls_wq", 0);
if (!map->wq) {
ret = -ENOMEM;
goto out;
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index 58b732dcbfb8..639bf628389b 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -811,6 +811,9 @@ static int xenbus_probe_thread(void *unused)
static int __init xenbus_probe_initcall(void)
{
+ if (!xen_domain())
+ return -ENODEV;
+
/*
* Probe XenBus here in the XS_PV case, and also XS_HVM unless we
* need to wait for the platform PCI device to come up or